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