os/ossrv/ssl/libcrypto/src/crypto/x509/x509name.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* crypto/x509/x509name.c */
     2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
     3  * All rights reserved.
     4  *
     5  * This package is an SSL implementation written
     6  * by Eric Young (eay@cryptsoft.com).
     7  * The implementation was written so as to conform with Netscapes SSL.
     8  * 
     9  * This library is free for commercial and non-commercial use as long as
    10  * the following conditions are aheared to.  The following conditions
    11  * apply to all code found in this distribution, be it the RC4, RSA,
    12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
    13  * included with this distribution is covered by the same copyright terms
    14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
    15  * 
    16  * Copyright remains Eric Young's, and as such any Copyright notices in
    17  * the code are not to be removed.
    18  * If this package is used in a product, Eric Young should be given attribution
    19  * as the author of the parts of the library used.
    20  * This can be in the form of a textual message at program startup or
    21  * in documentation (online or textual) provided with the package.
    22  * 
    23  * Redistribution and use in source and binary forms, with or without
    24  * modification, are permitted provided that the following conditions
    25  * are met:
    26  * 1. Redistributions of source code must retain the copyright
    27  *    notice, this list of conditions and the following disclaimer.
    28  * 2. Redistributions in binary form must reproduce the above copyright
    29  *    notice, this list of conditions and the following disclaimer in the
    30  *    documentation and/or other materials provided with the distribution.
    31  * 3. All advertising materials mentioning features or use of this software
    32  *    must display the following acknowledgement:
    33  *    "This product includes cryptographic software written by
    34  *     Eric Young (eay@cryptsoft.com)"
    35  *    The word 'cryptographic' can be left out if the rouines from the library
    36  *    being used are not cryptographic related :-).
    37  * 4. If you include any Windows specific code (or a derivative thereof) from 
    38  *    the apps directory (application code) you must include an acknowledgement:
    39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
    40  * 
    41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
    42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    51  * SUCH DAMAGE.
    52  * 
    53  * The licence and distribution terms for any publically available version or
    54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
    55  * copied and put under another distribution licence
    56  * [including the GNU Public Licence.]
    57  */
    58 
    59 #include <stdio.h>
    60 #include <openssl/stack.h>
    61 #include "cryptlib.h"
    62 #include <openssl/asn1.h>
    63 #include <openssl/objects.h>
    64 #include <openssl/evp.h>
    65 #include <openssl/x509.h>
    66 
    67 EXPORT_C int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
    68 	{
    69 	ASN1_OBJECT *obj;
    70 
    71 	obj=OBJ_nid2obj(nid);
    72 	if (obj == NULL) return(-1);
    73 	return(X509_NAME_get_text_by_OBJ(name,obj,buf,len));
    74 	}
    75 
    76 EXPORT_C int X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, char *buf,
    77 	     int len)
    78 	{
    79 	int i;
    80 	ASN1_STRING *data;
    81 
    82 	i=X509_NAME_get_index_by_OBJ(name,obj,-1);
    83 	if (i < 0) return(-1);
    84 	data=X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
    85 	i=(data->length > (len-1))?(len-1):data->length;
    86 	if (buf == NULL) return(data->length);
    87 	memcpy(buf,data->data,i);
    88 	buf[i]='\0';
    89 	return(i);
    90 	}
    91 
    92 EXPORT_C int X509_NAME_entry_count(X509_NAME *name)
    93 	{
    94 	if (name == NULL) return(0);
    95 	return(sk_X509_NAME_ENTRY_num(name->entries));
    96 	}
    97 
    98 EXPORT_C int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
    99 	{
   100 	ASN1_OBJECT *obj;
   101 
   102 	obj=OBJ_nid2obj(nid);
   103 	if (obj == NULL) return(-2);
   104 	return(X509_NAME_get_index_by_OBJ(name,obj,lastpos));
   105 	}
   106 
   107 /* NOTE: you should be passsing -1, not 0 as lastpos */
   108 EXPORT_C int X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj,
   109 	     int lastpos)
   110 	{
   111 	int n;
   112 	X509_NAME_ENTRY *ne;
   113 	STACK_OF(X509_NAME_ENTRY) *sk;
   114 
   115 	if (name == NULL) return(-1);
   116 	if (lastpos < 0)
   117 		lastpos= -1;
   118 	sk=name->entries;
   119 	n=sk_X509_NAME_ENTRY_num(sk);
   120 	for (lastpos++; lastpos < n; lastpos++)
   121 		{
   122 		ne=sk_X509_NAME_ENTRY_value(sk,lastpos);
   123 		if (OBJ_cmp(ne->object,obj) == 0)
   124 			return(lastpos);
   125 		}
   126 	return(-1);
   127 	}
   128 
   129 EXPORT_C X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc)
   130 	{
   131 	if(name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
   132 	   || loc < 0)
   133 		return(NULL);
   134 	else
   135 		return(sk_X509_NAME_ENTRY_value(name->entries,loc));
   136 	}
   137 
   138 EXPORT_C X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
   139 	{
   140 	X509_NAME_ENTRY *ret;
   141 	int i,n,set_prev,set_next;
   142 	STACK_OF(X509_NAME_ENTRY) *sk;
   143 
   144 	if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc
   145 	    || loc < 0)
   146 		return(NULL);
   147 	sk=name->entries;
   148 	ret=sk_X509_NAME_ENTRY_delete(sk,loc);
   149 	n=sk_X509_NAME_ENTRY_num(sk);
   150 	name->modified=1;
   151 	if (loc == n) return(ret);
   152 
   153 	/* else we need to fixup the set field */
   154 	if (loc != 0)
   155 		set_prev=(sk_X509_NAME_ENTRY_value(sk,loc-1))->set;
   156 	else
   157 		set_prev=ret->set-1;
   158 	set_next=sk_X509_NAME_ENTRY_value(sk,loc)->set;
   159 
   160 	/* set_prev is the previous set
   161 	 * set is the current set
   162 	 * set_next is the following
   163 	 * prev  1 1	1 1	1 1	1 1
   164 	 * set   1	1	2	2
   165 	 * next  1 1	2 2	2 2	3 2
   166 	 * so basically only if prev and next differ by 2, then
   167 	 * re-number down by 1 */
   168 	if (set_prev+1 < set_next)
   169 		for (i=loc; i<n; i++)
   170 			sk_X509_NAME_ENTRY_value(sk,i)->set--;
   171 	return(ret);
   172 	}
   173 
   174 EXPORT_C int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
   175 			unsigned char *bytes, int len, int loc, int set)
   176 {
   177 	X509_NAME_ENTRY *ne;
   178 	int ret;
   179 	ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
   180 	if(!ne) return 0;
   181 	ret = X509_NAME_add_entry(name, ne, loc, set);
   182 	X509_NAME_ENTRY_free(ne);
   183 	return ret;
   184 }
   185 
   186 EXPORT_C int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
   187 			unsigned char *bytes, int len, int loc, int set)
   188 {
   189 	X509_NAME_ENTRY *ne;
   190 	int ret;
   191 	ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
   192 	if(!ne) return 0;
   193 	ret = X509_NAME_add_entry(name, ne, loc, set);
   194 	X509_NAME_ENTRY_free(ne);
   195 	return ret;
   196 }
   197 
   198 EXPORT_C int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
   199 			const unsigned char *bytes, int len, int loc, int set)
   200 {
   201 	X509_NAME_ENTRY *ne;
   202 	int ret;
   203 	ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
   204 	if(!ne) return 0;
   205 	ret = X509_NAME_add_entry(name, ne, loc, set);
   206 	X509_NAME_ENTRY_free(ne);
   207 	return ret;
   208 }
   209 
   210 /* if set is -1, append to previous set, 0 'a new one', and 1,
   211  * prepend to the guy we are about to stomp on. */
   212 EXPORT_C int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
   213 	     int set)
   214 	{
   215 	X509_NAME_ENTRY *new_name=NULL;
   216 	int n,i,inc;
   217 	STACK_OF(X509_NAME_ENTRY) *sk;
   218 
   219 	if (name == NULL) return(0);
   220 	sk=name->entries;
   221 	n=sk_X509_NAME_ENTRY_num(sk);
   222 	if (loc > n) loc=n;
   223 	else if (loc < 0) loc=n;
   224 
   225 	name->modified=1;
   226 
   227 	if (set == -1)
   228 		{
   229 		if (loc == 0)
   230 			{
   231 			set=0;
   232 			inc=1;
   233 			}
   234 		else
   235 			{
   236 			set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set;
   237 			inc=0;
   238 			}
   239 		}
   240 	else /* if (set >= 0) */
   241 		{
   242 		if (loc >= n)
   243 			{
   244 			if (loc != 0)
   245 				set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set+1;
   246 			else
   247 				set=0;
   248 			}
   249 		else
   250 			set=sk_X509_NAME_ENTRY_value(sk,loc)->set;
   251 		inc=(set == 0)?1:0;
   252 		}
   253 
   254 	if ((new_name=X509_NAME_ENTRY_dup(ne)) == NULL)
   255 		goto err;
   256 	new_name->set=set;
   257 	if (!sk_X509_NAME_ENTRY_insert(sk,new_name,loc))
   258 		{
   259 		X509err(X509_F_X509_NAME_ADD_ENTRY,ERR_R_MALLOC_FAILURE);
   260 		goto err;
   261 		}
   262 	if (inc)
   263 		{
   264 		n=sk_X509_NAME_ENTRY_num(sk);
   265 		for (i=loc+1; i<n; i++)
   266 			sk_X509_NAME_ENTRY_value(sk,i-1)->set+=1;
   267 		}	
   268 	return(1);
   269 err:
   270 	if (new_name != NULL)
   271 		X509_NAME_ENTRY_free(new_name);
   272 	return(0);
   273 	}
   274 
   275 EXPORT_C X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
   276 		const char *field, int type, const unsigned char *bytes, int len)
   277 	{
   278 	ASN1_OBJECT *obj;
   279 	X509_NAME_ENTRY *nentry;
   280 
   281 	obj=OBJ_txt2obj(field, 0);
   282 	if (obj == NULL)
   283 		{
   284 		X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT,
   285 						X509_R_INVALID_FIELD_NAME);
   286 		ERR_add_error_data(2, "name=", field);
   287 		return(NULL);
   288 		}
   289 	nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
   290 	ASN1_OBJECT_free(obj);
   291 	return nentry;
   292 	}
   293 
   294 EXPORT_C X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
   295 	     int type, unsigned char *bytes, int len)
   296 	{
   297 	ASN1_OBJECT *obj;
   298 	X509_NAME_ENTRY *nentry;
   299 
   300 	obj=OBJ_nid2obj(nid);
   301 	if (obj == NULL)
   302 		{
   303 		X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID,X509_R_UNKNOWN_NID);
   304 		return(NULL);
   305 		}
   306 	nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
   307 	ASN1_OBJECT_free(obj);
   308 	return nentry;
   309 	}
   310 
   311 EXPORT_C X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
   312 	     ASN1_OBJECT *obj, int type, const unsigned char *bytes, int len)
   313 	{
   314 	X509_NAME_ENTRY *ret;
   315 
   316 	if ((ne == NULL) || (*ne == NULL))
   317 		{
   318 		if ((ret=X509_NAME_ENTRY_new()) == NULL)
   319 			return(NULL);
   320 		}
   321 	else
   322 		ret= *ne;
   323 
   324 	if (!X509_NAME_ENTRY_set_object(ret,obj))
   325 		goto err;
   326 	if (!X509_NAME_ENTRY_set_data(ret,type,bytes,len))
   327 		goto err;
   328 
   329 	if ((ne != NULL) && (*ne == NULL)) *ne=ret;
   330 	return(ret);
   331 err:
   332 	if ((ne == NULL) || (ret != *ne))
   333 		X509_NAME_ENTRY_free(ret);
   334 	return(NULL);
   335 	}
   336 
   337 EXPORT_C int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj)
   338 	{
   339 	if ((ne == NULL) || (obj == NULL))
   340 		{
   341 		X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT,ERR_R_PASSED_NULL_PARAMETER);
   342 		return(0);
   343 		}
   344 	ASN1_OBJECT_free(ne->object);
   345 	ne->object=OBJ_dup(obj);
   346 	return((ne->object == NULL)?0:1);
   347 	}
   348 
   349 EXPORT_C int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
   350 	     const unsigned char *bytes, int len)
   351 	{
   352 	int i;
   353 
   354 	if ((ne == NULL) || ((bytes == NULL) && (len != 0))) return(0);
   355 	if((type > 0) && (type & MBSTRING_FLAG)) 
   356 		return ASN1_STRING_set_by_NID(&ne->value, bytes,
   357 						len, type,
   358 					OBJ_obj2nid(ne->object)) ? 1 : 0;
   359 	if (len < 0) len=strlen((char *)bytes);
   360 	i=ASN1_STRING_set(ne->value,bytes,len);
   361 	if (!i) return(0);
   362 	if (type != V_ASN1_UNDEF)
   363 		{
   364 		if (type == V_ASN1_APP_CHOOSE)
   365 			ne->value->type=ASN1_PRINTABLE_type(bytes,len);
   366 		else
   367 			ne->value->type=type;
   368 		}
   369 	return(1);
   370 	}
   371 
   372 EXPORT_C ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
   373 	{
   374 	if (ne == NULL) return(NULL);
   375 	return(ne->object);
   376 	}
   377 
   378 EXPORT_C ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
   379 	{
   380 	if (ne == NULL) return(NULL);
   381 	return(ne->value);
   382 	}
   383