x509name.c revision 280304
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 67int 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) 73 return (-1); 74 return (X509_NAME_get_text_by_OBJ(name, obj, buf, len)); 75} 76 77int X509_NAME_get_text_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, char *buf, 78 int len) 79{ 80 int i; 81 ASN1_STRING *data; 82 83 i = X509_NAME_get_index_by_OBJ(name, obj, -1); 84 if (i < 0) 85 return (-1); 86 data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); 87 i = (data->length > (len - 1)) ? (len - 1) : data->length; 88 if (buf == NULL) 89 return (data->length); 90 memcpy(buf, data->data, i); 91 buf[i] = '\0'; 92 return (i); 93} 94 95int X509_NAME_entry_count(X509_NAME *name) 96{ 97 if (name == NULL) 98 return (0); 99 return (sk_X509_NAME_ENTRY_num(name->entries)); 100} 101 102int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos) 103{ 104 ASN1_OBJECT *obj; 105 106 obj = OBJ_nid2obj(nid); 107 if (obj == NULL) 108 return (-2); 109 return (X509_NAME_get_index_by_OBJ(name, obj, lastpos)); 110} 111 112/* NOTE: you should be passsing -1, not 0 as lastpos */ 113int X509_NAME_get_index_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int lastpos) 114{ 115 int n; 116 X509_NAME_ENTRY *ne; 117 STACK_OF(X509_NAME_ENTRY) *sk; 118 119 if (name == NULL) 120 return (-1); 121 if (lastpos < 0) 122 lastpos = -1; 123 sk = name->entries; 124 n = sk_X509_NAME_ENTRY_num(sk); 125 for (lastpos++; lastpos < n; lastpos++) { 126 ne = sk_X509_NAME_ENTRY_value(sk, lastpos); 127 if (OBJ_cmp(ne->object, obj) == 0) 128 return (lastpos); 129 } 130 return (-1); 131} 132 133X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc) 134{ 135 if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc 136 || loc < 0) 137 return (NULL); 138 else 139 return (sk_X509_NAME_ENTRY_value(name->entries, loc)); 140} 141 142X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc) 143{ 144 X509_NAME_ENTRY *ret; 145 int i, n, set_prev, set_next; 146 STACK_OF(X509_NAME_ENTRY) *sk; 147 148 if (name == NULL || sk_X509_NAME_ENTRY_num(name->entries) <= loc 149 || loc < 0) 150 return (NULL); 151 sk = name->entries; 152 ret = sk_X509_NAME_ENTRY_delete(sk, loc); 153 n = sk_X509_NAME_ENTRY_num(sk); 154 name->modified = 1; 155 if (loc == n) 156 return (ret); 157 158 /* else we need to fixup the set field */ 159 if (loc != 0) 160 set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set; 161 else 162 set_prev = ret->set - 1; 163 set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set; 164 165 /*- 166 * set_prev is the previous set 167 * set is the current set 168 * set_next is the following 169 * prev 1 1 1 1 1 1 1 1 170 * set 1 1 2 2 171 * next 1 1 2 2 2 2 3 2 172 * so basically only if prev and next differ by 2, then 173 * re-number down by 1 174 */ 175 if (set_prev + 1 < set_next) 176 for (i = loc; i < n; i++) 177 sk_X509_NAME_ENTRY_value(sk, i)->set--; 178 return (ret); 179} 180 181int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type, 182 unsigned char *bytes, int len, int loc, 183 int set) 184{ 185 X509_NAME_ENTRY *ne; 186 int ret; 187 ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len); 188 if (!ne) 189 return 0; 190 ret = X509_NAME_add_entry(name, ne, loc, set); 191 X509_NAME_ENTRY_free(ne); 192 return ret; 193} 194 195int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type, 196 unsigned char *bytes, int len, int loc, 197 int set) 198{ 199 X509_NAME_ENTRY *ne; 200 int ret; 201 ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len); 202 if (!ne) 203 return 0; 204 ret = X509_NAME_add_entry(name, ne, loc, set); 205 X509_NAME_ENTRY_free(ne); 206 return ret; 207} 208 209int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type, 210 const unsigned char *bytes, int len, int loc, 211 int set) 212{ 213 X509_NAME_ENTRY *ne; 214 int ret; 215 ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len); 216 if (!ne) 217 return 0; 218 ret = X509_NAME_add_entry(name, ne, loc, set); 219 X509_NAME_ENTRY_free(ne); 220 return ret; 221} 222 223/* 224 * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the 225 * guy we are about to stomp on. 226 */ 227int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc, 228 int set) 229{ 230 X509_NAME_ENTRY *new_name = NULL; 231 int n, i, inc; 232 STACK_OF(X509_NAME_ENTRY) *sk; 233 234 if (name == NULL) 235 return (0); 236 sk = name->entries; 237 n = sk_X509_NAME_ENTRY_num(sk); 238 if (loc > n) 239 loc = n; 240 else if (loc < 0) 241 loc = n; 242 243 name->modified = 1; 244 245 if (set == -1) { 246 if (loc == 0) { 247 set = 0; 248 inc = 1; 249 } else { 250 set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set; 251 inc = 0; 252 } 253 } else { /* if (set >= 0) */ 254 255 if (loc >= n) { 256 if (loc != 0) 257 set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1; 258 else 259 set = 0; 260 } else 261 set = sk_X509_NAME_ENTRY_value(sk, loc)->set; 262 inc = (set == 0) ? 1 : 0; 263 } 264 265 if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL) 266 goto err; 267 new_name->set = set; 268 if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) { 269 X509err(X509_F_X509_NAME_ADD_ENTRY, ERR_R_MALLOC_FAILURE); 270 goto err; 271 } 272 if (inc) { 273 n = sk_X509_NAME_ENTRY_num(sk); 274 for (i = loc + 1; i < n; i++) 275 sk_X509_NAME_ENTRY_value(sk, i - 1)->set += 1; 276 } 277 return (1); 278 err: 279 if (new_name != NULL) 280 X509_NAME_ENTRY_free(new_name); 281 return (0); 282} 283 284X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne, 285 const char *field, int type, 286 const unsigned char *bytes, 287 int len) 288{ 289 ASN1_OBJECT *obj; 290 X509_NAME_ENTRY *nentry; 291 292 obj = OBJ_txt2obj(field, 0); 293 if (obj == NULL) { 294 X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_TXT, 295 X509_R_INVALID_FIELD_NAME); 296 ERR_add_error_data(2, "name=", field); 297 return (NULL); 298 } 299 nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); 300 ASN1_OBJECT_free(obj); 301 return nentry; 302} 303 304X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid, 305 int type, unsigned char *bytes, 306 int len) 307{ 308 ASN1_OBJECT *obj; 309 X509_NAME_ENTRY *nentry; 310 311 obj = OBJ_nid2obj(nid); 312 if (obj == NULL) { 313 X509err(X509_F_X509_NAME_ENTRY_CREATE_BY_NID, X509_R_UNKNOWN_NID); 314 return (NULL); 315 } 316 nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len); 317 ASN1_OBJECT_free(obj); 318 return nentry; 319} 320 321X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne, 322 ASN1_OBJECT *obj, int type, 323 const unsigned char *bytes, 324 int len) 325{ 326 X509_NAME_ENTRY *ret; 327 328 if ((ne == NULL) || (*ne == NULL)) { 329 if ((ret = X509_NAME_ENTRY_new()) == NULL) 330 return (NULL); 331 } else 332 ret = *ne; 333 334 if (!X509_NAME_ENTRY_set_object(ret, obj)) 335 goto err; 336 if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len)) 337 goto err; 338 339 if ((ne != NULL) && (*ne == NULL)) 340 *ne = ret; 341 return (ret); 342 err: 343 if ((ne == NULL) || (ret != *ne)) 344 X509_NAME_ENTRY_free(ret); 345 return (NULL); 346} 347 348int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, ASN1_OBJECT *obj) 349{ 350 if ((ne == NULL) || (obj == NULL)) { 351 X509err(X509_F_X509_NAME_ENTRY_SET_OBJECT, 352 ERR_R_PASSED_NULL_PARAMETER); 353 return (0); 354 } 355 ASN1_OBJECT_free(ne->object); 356 ne->object = OBJ_dup(obj); 357 return ((ne->object == NULL) ? 0 : 1); 358} 359 360int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type, 361 const unsigned char *bytes, int len) 362{ 363 int i; 364 365 if ((ne == NULL) || ((bytes == NULL) && (len != 0))) 366 return (0); 367 if ((type > 0) && (type & MBSTRING_FLAG)) 368 return ASN1_STRING_set_by_NID(&ne->value, bytes, 369 len, type, 370 OBJ_obj2nid(ne->object)) ? 1 : 0; 371 if (len < 0) 372 len = strlen((const char *)bytes); 373 i = ASN1_STRING_set(ne->value, bytes, len); 374 if (!i) 375 return (0); 376 if (type != V_ASN1_UNDEF) { 377 if (type == V_ASN1_APP_CHOOSE) 378 ne->value->type = ASN1_PRINTABLE_type(bytes, len); 379 else 380 ne->value->type = type; 381 } 382 return (1); 383} 384 385ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne) 386{ 387 if (ne == NULL) 388 return (NULL); 389 return (ne->object); 390} 391 392ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne) 393{ 394 if (ne == NULL) 395 return (NULL); 396 return (ne->value); 397} 398