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