Home | History | Annotate | Download | only in x509
      1 /* crypto/x509/x509name.c */
      2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
      3  * All rights reserved.
      4  *
      5  * This package is an SSL implementation written
      6  * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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((const 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 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 ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
    379 	{
    380 	if (ne == NULL) return(NULL);
    381 	return(ne->value);
    382 	}
    383 
    384