1 1.1 elric /* $NetBSD: name.c,v 1.3 2023/06/19 21:41:44 christos Exp $ */ 2 1.1 elric 3 1.1 elric /* 4 1.1 elric * Copyright (c) 2004 - 2009 Kungliga Tekniska Hgskolan 5 1.1 elric * (Royal Institute of Technology, Stockholm, Sweden). 6 1.1 elric * All rights reserved. 7 1.1 elric * 8 1.1 elric * Redistribution and use in source and binary forms, with or without 9 1.1 elric * modification, are permitted provided that the following conditions 10 1.1 elric * are met: 11 1.1 elric * 12 1.1 elric * 1. Redistributions of source code must retain the above copyright 13 1.1 elric * notice, this list of conditions and the following disclaimer. 14 1.1 elric * 15 1.1 elric * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 elric * notice, this list of conditions and the following disclaimer in the 17 1.1 elric * documentation and/or other materials provided with the distribution. 18 1.1 elric * 19 1.1 elric * 3. Neither the name of the Institute nor the names of its contributors 20 1.1 elric * may be used to endorse or promote products derived from this software 21 1.1 elric * without specific prior written permission. 22 1.1 elric * 23 1.1 elric * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 1.1 elric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 1.1 elric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 1.1 elric * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 1.1 elric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 1.1 elric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 1.1 elric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 1.1 elric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 1.1 elric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 1.1 elric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 1.1 elric * SUCH DAMAGE. 34 1.1 elric */ 35 1.1 elric 36 1.1 elric #include "hx_locl.h" 37 1.1 elric #include <krb5/wind.h> 38 1.1 elric #include "char_map.h" 39 1.1 elric 40 1.1 elric /** 41 1.1 elric * @page page_name PKIX/X.509 Names 42 1.1 elric * 43 1.1 elric * There are several names in PKIX/X.509, GeneralName and Name. 44 1.1 elric * 45 1.1 elric * A Name consists of an ordered list of Relative Distinguished Names 46 1.1 elric * (RDN). Each RDN consists of an unordered list of typed strings. The 47 1.1 elric * types are defined by OID and have long and short description. For 48 1.1 elric * example id-at-commonName (2.5.4.3) have the long name CommonName 49 1.1 elric * and short name CN. The string itself can be of several encoding, 50 1.1 elric * UTF8, UTF16, Teltex string, etc. The type limit what encoding 51 1.1 elric * should be used. 52 1.1 elric * 53 1.1 elric * GeneralName is a broader nametype that can contains al kind of 54 1.1 elric * stuff like Name, IP addresses, partial Name, etc. 55 1.1 elric * 56 1.1 elric * Name is mapped into a hx509_name object. 57 1.1 elric * 58 1.1 elric * Parse and string name into a hx509_name object with hx509_parse_name(), 59 1.1 elric * make it back into string representation with hx509_name_to_string(). 60 1.1 elric * 61 1.1 elric * Name string are defined rfc2253, rfc1779 and X.501. 62 1.1 elric * 63 1.1 elric * See the library functions here: @ref hx509_name 64 1.1 elric */ 65 1.1 elric 66 1.1 elric static const struct { 67 1.1 elric const char *n; 68 1.1 elric const heim_oid *o; 69 1.1 elric wind_profile_flags flags; 70 1.1 elric } no[] = { 71 1.2 christos { "C", &asn1_oid_id_at_countryName, 0 }, 72 1.2 christos { "CN", &asn1_oid_id_at_commonName, 0 }, 73 1.2 christos { "DC", &asn1_oid_id_domainComponent, 0 }, 74 1.2 christos { "L", &asn1_oid_id_at_localityName, 0 }, 75 1.2 christos { "O", &asn1_oid_id_at_organizationName, 0 }, 76 1.2 christos { "OU", &asn1_oid_id_at_organizationalUnitName, 0 }, 77 1.2 christos { "S", &asn1_oid_id_at_stateOrProvinceName, 0 }, 78 1.2 christos { "STREET", &asn1_oid_id_at_streetAddress, 0 }, 79 1.2 christos { "UID", &asn1_oid_id_Userid, 0 }, 80 1.2 christos { "emailAddress", &asn1_oid_id_pkcs9_emailAddress, 0 }, 81 1.2 christos { "serialNumber", &asn1_oid_id_at_serialNumber, 0 } 82 1.1 elric }; 83 1.1 elric 84 1.1 elric static char * 85 1.1 elric quote_string(const char *f, size_t len, int flags, size_t *rlen) 86 1.1 elric { 87 1.1 elric size_t i, j, tolen; 88 1.1 elric const unsigned char *from = (const unsigned char *)f; 89 1.1 elric unsigned char *to; 90 1.1 elric 91 1.1 elric tolen = len * 3 + 1; 92 1.1 elric to = malloc(tolen); 93 1.1 elric if (to == NULL) 94 1.1 elric return NULL; 95 1.1 elric 96 1.1 elric for (i = 0, j = 0; i < len; i++) { 97 1.1 elric unsigned char map = char_map[from[i]] & flags; 98 1.1 elric if (i == 0 && (map & Q_RFC2253_QUOTE_FIRST)) { 99 1.1 elric to[j++] = '\\'; 100 1.1 elric to[j++] = from[i]; 101 1.1 elric } else if ((i + 1) == len && (map & Q_RFC2253_QUOTE_LAST)) { 102 1.1 elric 103 1.1 elric to[j++] = '\\'; 104 1.1 elric to[j++] = from[i]; 105 1.1 elric } else if (map & Q_RFC2253_QUOTE) { 106 1.1 elric to[j++] = '\\'; 107 1.1 elric to[j++] = from[i]; 108 1.1 elric } else if (map & Q_RFC2253_HEX) { 109 1.1 elric int l = snprintf((char *)&to[j], tolen - j - 1, 110 1.1 elric "#%02x", (unsigned char)from[i]); 111 1.1 elric j += l; 112 1.1 elric } else { 113 1.1 elric to[j++] = from[i]; 114 1.1 elric } 115 1.1 elric } 116 1.1 elric to[j] = '\0'; 117 1.1 elric assert(j < tolen); 118 1.1 elric *rlen = j; 119 1.1 elric return (char *)to; 120 1.1 elric } 121 1.1 elric 122 1.1 elric 123 1.1 elric static int 124 1.1 elric append_string(char **str, size_t *total_len, const char *ss, 125 1.1 elric size_t len, int quote) 126 1.1 elric { 127 1.1 elric char *s, *qs; 128 1.1 elric 129 1.1 elric if (quote) 130 1.1 elric qs = quote_string(ss, len, Q_RFC2253, &len); 131 1.1 elric else 132 1.1 elric qs = rk_UNCONST(ss); 133 1.1 elric 134 1.1 elric s = realloc(*str, len + *total_len + 1); 135 1.1 elric if (s == NULL) 136 1.1 elric _hx509_abort("allocation failure"); /* XXX */ 137 1.1 elric memcpy(s + *total_len, qs, len); 138 1.1 elric if (qs != ss) 139 1.1 elric free(qs); 140 1.1 elric s[*total_len + len] = '\0'; 141 1.1 elric *str = s; 142 1.1 elric *total_len += len; 143 1.1 elric return 0; 144 1.1 elric } 145 1.1 elric 146 1.1 elric static char * 147 1.1 elric oidtostring(const heim_oid *type) 148 1.1 elric { 149 1.1 elric char *s; 150 1.1 elric size_t i; 151 1.1 elric 152 1.1 elric for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) { 153 1.1 elric if (der_heim_oid_cmp(no[i].o, type) == 0) 154 1.1 elric return strdup(no[i].n); 155 1.1 elric } 156 1.1 elric if (der_print_heim_oid(type, '.', &s) != 0) 157 1.1 elric return NULL; 158 1.1 elric return s; 159 1.1 elric } 160 1.1 elric 161 1.1 elric static int 162 1.1 elric stringtooid(const char *name, size_t len, heim_oid *oid) 163 1.1 elric { 164 1.2 christos int ret; 165 1.2 christos size_t i; 166 1.1 elric char *s; 167 1.1 elric 168 1.1 elric memset(oid, 0, sizeof(*oid)); 169 1.1 elric 170 1.1 elric for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) { 171 1.1 elric if (strncasecmp(no[i].n, name, len) == 0) 172 1.1 elric return der_copy_oid(no[i].o, oid); 173 1.1 elric } 174 1.1 elric s = malloc(len + 1); 175 1.1 elric if (s == NULL) 176 1.1 elric return ENOMEM; 177 1.1 elric memcpy(s, name, len); 178 1.1 elric s[len] = '\0'; 179 1.1 elric ret = der_parse_heim_oid(s, ".", oid); 180 1.1 elric free(s); 181 1.1 elric return ret; 182 1.1 elric } 183 1.1 elric 184 1.1 elric /** 185 1.1 elric * Convert the hx509 name object into a printable string. 186 1.1 elric * The resulting string should be freed with free(). 187 1.1 elric * 188 1.1 elric * @param name name to print 189 1.1 elric * @param str the string to return 190 1.1 elric * 191 1.1 elric * @return An hx509 error code, see hx509_get_error_string(). 192 1.1 elric * 193 1.1 elric * @ingroup hx509_name 194 1.1 elric */ 195 1.1 elric 196 1.1 elric int 197 1.1 elric hx509_name_to_string(const hx509_name name, char **str) 198 1.1 elric { 199 1.1 elric return _hx509_Name_to_string(&name->der_name, str); 200 1.1 elric } 201 1.1 elric 202 1.1 elric int 203 1.1 elric _hx509_Name_to_string(const Name *n, char **str) 204 1.1 elric { 205 1.1 elric size_t total_len = 0; 206 1.2 christos size_t i, j, m; 207 1.2 christos int ret; 208 1.1 elric 209 1.1 elric *str = strdup(""); 210 1.1 elric if (*str == NULL) 211 1.1 elric return ENOMEM; 212 1.1 elric 213 1.2 christos for (m = n->u.rdnSequence.len; m > 0; m--) { 214 1.1 elric size_t len; 215 1.2 christos i = m - 1; 216 1.1 elric 217 1.1 elric for (j = 0; j < n->u.rdnSequence.val[i].len; j++) { 218 1.1 elric DirectoryString *ds = &n->u.rdnSequence.val[i].val[j].value; 219 1.1 elric char *oidname; 220 1.1 elric char *ss; 221 1.2 christos 222 1.1 elric oidname = oidtostring(&n->u.rdnSequence.val[i].val[j].type); 223 1.1 elric 224 1.1 elric switch(ds->element) { 225 1.1 elric case choice_DirectoryString_ia5String: 226 1.1 elric ss = ds->u.ia5String.data; 227 1.1 elric len = ds->u.ia5String.length; 228 1.1 elric break; 229 1.1 elric case choice_DirectoryString_printableString: 230 1.1 elric ss = ds->u.printableString.data; 231 1.1 elric len = ds->u.printableString.length; 232 1.1 elric break; 233 1.1 elric case choice_DirectoryString_utf8String: 234 1.1 elric ss = ds->u.utf8String; 235 1.1 elric len = strlen(ss); 236 1.1 elric break; 237 1.1 elric case choice_DirectoryString_bmpString: { 238 1.1 elric const uint16_t *bmp = ds->u.bmpString.data; 239 1.1 elric size_t bmplen = ds->u.bmpString.length; 240 1.1 elric size_t k; 241 1.1 elric 242 1.1 elric ret = wind_ucs2utf8_length(bmp, bmplen, &k); 243 1.2 christos if (ret) { 244 1.2 christos free(oidname); 245 1.2 christos free(*str); 246 1.2 christos *str = NULL; 247 1.1 elric return ret; 248 1.2 christos } 249 1.2 christos 250 1.1 elric ss = malloc(k + 1); 251 1.1 elric if (ss == NULL) 252 1.1 elric _hx509_abort("allocation failure"); /* XXX */ 253 1.1 elric ret = wind_ucs2utf8(bmp, bmplen, ss, NULL); 254 1.1 elric if (ret) { 255 1.2 christos free(oidname); 256 1.1 elric free(ss); 257 1.2 christos free(*str); 258 1.2 christos *str = NULL; 259 1.1 elric return ret; 260 1.1 elric } 261 1.1 elric ss[k] = '\0'; 262 1.1 elric len = k; 263 1.1 elric break; 264 1.1 elric } 265 1.1 elric case choice_DirectoryString_teletexString: 266 1.1 elric ss = ds->u.teletexString; 267 1.1 elric len = strlen(ss); 268 1.1 elric break; 269 1.1 elric case choice_DirectoryString_universalString: { 270 1.1 elric const uint32_t *uni = ds->u.universalString.data; 271 1.1 elric size_t unilen = ds->u.universalString.length; 272 1.1 elric size_t k; 273 1.1 elric 274 1.1 elric ret = wind_ucs4utf8_length(uni, unilen, &k); 275 1.2 christos if (ret) { 276 1.2 christos free(oidname); 277 1.2 christos free(*str); 278 1.2 christos *str = NULL; 279 1.1 elric return ret; 280 1.2 christos } 281 1.1 elric 282 1.1 elric ss = malloc(k + 1); 283 1.1 elric if (ss == NULL) 284 1.1 elric _hx509_abort("allocation failure"); /* XXX */ 285 1.1 elric ret = wind_ucs4utf8(uni, unilen, ss, NULL); 286 1.1 elric if (ret) { 287 1.1 elric free(ss); 288 1.2 christos free(oidname); 289 1.2 christos free(*str); 290 1.2 christos *str = NULL; 291 1.1 elric return ret; 292 1.1 elric } 293 1.1 elric ss[k] = '\0'; 294 1.1 elric len = k; 295 1.1 elric break; 296 1.1 elric } 297 1.1 elric default: 298 1.1 elric _hx509_abort("unknown directory type: %d", ds->element); 299 1.1 elric exit(1); 300 1.1 elric } 301 1.1 elric append_string(str, &total_len, oidname, strlen(oidname), 0); 302 1.1 elric free(oidname); 303 1.1 elric append_string(str, &total_len, "=", 1, 0); 304 1.1 elric append_string(str, &total_len, ss, len, 1); 305 1.1 elric if (ds->element == choice_DirectoryString_bmpString || 306 1.1 elric ds->element == choice_DirectoryString_universalString) 307 1.1 elric { 308 1.1 elric free(ss); 309 1.1 elric } 310 1.1 elric if (j + 1 < n->u.rdnSequence.val[i].len) 311 1.1 elric append_string(str, &total_len, "+", 1, 0); 312 1.1 elric } 313 1.1 elric 314 1.1 elric if (i > 0) 315 1.1 elric append_string(str, &total_len, ",", 1, 0); 316 1.1 elric } 317 1.1 elric return 0; 318 1.1 elric } 319 1.1 elric 320 1.1 elric #define COPYCHARARRAY(_ds,_el,_l,_n) \ 321 1.1 elric (_l) = strlen(_ds->u._el); \ 322 1.1 elric (_n) = malloc((_l) * sizeof((_n)[0])); \ 323 1.1 elric if ((_n) == NULL) \ 324 1.1 elric return ENOMEM; \ 325 1.1 elric for (i = 0; i < (_l); i++) \ 326 1.1 elric (_n)[i] = _ds->u._el[i] 327 1.1 elric 328 1.1 elric 329 1.1 elric #define COPYVALARRAY(_ds,_el,_l,_n) \ 330 1.1 elric (_l) = _ds->u._el.length; \ 331 1.1 elric (_n) = malloc((_l) * sizeof((_n)[0])); \ 332 1.1 elric if ((_n) == NULL) \ 333 1.1 elric return ENOMEM; \ 334 1.1 elric for (i = 0; i < (_l); i++) \ 335 1.1 elric (_n)[i] = _ds->u._el.data[i] 336 1.1 elric 337 1.1 elric #define COPYVOIDARRAY(_ds,_el,_l,_n) \ 338 1.1 elric (_l) = _ds->u._el.length; \ 339 1.1 elric (_n) = malloc((_l) * sizeof((_n)[0])); \ 340 1.1 elric if ((_n) == NULL) \ 341 1.1 elric return ENOMEM; \ 342 1.1 elric for (i = 0; i < (_l); i++) \ 343 1.1 elric (_n)[i] = ((unsigned char *)_ds->u._el.data)[i] 344 1.1 elric 345 1.1 elric 346 1.1 elric 347 1.1 elric static int 348 1.1 elric dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen) 349 1.1 elric { 350 1.1 elric wind_profile_flags flags; 351 1.1 elric size_t i, len; 352 1.1 elric int ret; 353 1.1 elric uint32_t *name; 354 1.1 elric 355 1.1 elric *rname = NULL; 356 1.1 elric *rlen = 0; 357 1.1 elric 358 1.1 elric switch(ds->element) { 359 1.1 elric case choice_DirectoryString_ia5String: 360 1.1 elric flags = WIND_PROFILE_LDAP; 361 1.1 elric COPYVOIDARRAY(ds, ia5String, len, name); 362 1.1 elric break; 363 1.1 elric case choice_DirectoryString_printableString: 364 1.1 elric flags = WIND_PROFILE_LDAP; 365 1.1 elric flags |= WIND_PROFILE_LDAP_CASE_EXACT_ATTRIBUTE; 366 1.1 elric COPYVOIDARRAY(ds, printableString, len, name); 367 1.1 elric break; 368 1.1 elric case choice_DirectoryString_teletexString: 369 1.1 elric flags = WIND_PROFILE_LDAP_CASE; 370 1.1 elric COPYCHARARRAY(ds, teletexString, len, name); 371 1.1 elric break; 372 1.1 elric case choice_DirectoryString_bmpString: 373 1.1 elric flags = WIND_PROFILE_LDAP; 374 1.1 elric COPYVALARRAY(ds, bmpString, len, name); 375 1.1 elric break; 376 1.1 elric case choice_DirectoryString_universalString: 377 1.1 elric flags = WIND_PROFILE_LDAP; 378 1.1 elric COPYVALARRAY(ds, universalString, len, name); 379 1.1 elric break; 380 1.1 elric case choice_DirectoryString_utf8String: 381 1.1 elric flags = WIND_PROFILE_LDAP; 382 1.1 elric ret = wind_utf8ucs4_length(ds->u.utf8String, &len); 383 1.1 elric if (ret) 384 1.1 elric return ret; 385 1.1 elric name = malloc(len * sizeof(name[0])); 386 1.1 elric if (name == NULL) 387 1.1 elric return ENOMEM; 388 1.1 elric ret = wind_utf8ucs4(ds->u.utf8String, name, &len); 389 1.1 elric if (ret) { 390 1.1 elric free(name); 391 1.1 elric return ret; 392 1.1 elric } 393 1.1 elric break; 394 1.1 elric default: 395 1.1 elric _hx509_abort("unknown directory type: %d", ds->element); 396 1.1 elric } 397 1.1 elric 398 1.1 elric *rlen = len; 399 1.1 elric /* try a couple of times to get the length right, XXX gross */ 400 1.1 elric for (i = 0; i < 4; i++) { 401 1.1 elric *rlen = *rlen * 2; 402 1.1 elric *rname = malloc(*rlen * sizeof((*rname)[0])); 403 1.1 elric 404 1.1 elric ret = wind_stringprep(name, len, *rname, rlen, flags); 405 1.1 elric if (ret == WIND_ERR_OVERRUN) { 406 1.1 elric free(*rname); 407 1.1 elric *rname = NULL; 408 1.1 elric continue; 409 1.1 elric } else 410 1.1 elric break; 411 1.1 elric } 412 1.1 elric free(name); 413 1.1 elric if (ret) { 414 1.1 elric if (*rname) 415 1.1 elric free(*rname); 416 1.1 elric *rname = NULL; 417 1.1 elric *rlen = 0; 418 1.1 elric return ret; 419 1.1 elric } 420 1.1 elric 421 1.1 elric return 0; 422 1.1 elric } 423 1.1 elric 424 1.1 elric int 425 1.1 elric _hx509_name_ds_cmp(const DirectoryString *ds1, 426 1.1 elric const DirectoryString *ds2, 427 1.1 elric int *diff) 428 1.1 elric { 429 1.1 elric uint32_t *ds1lp, *ds2lp; 430 1.1 elric size_t ds1len, ds2len, i; 431 1.1 elric int ret; 432 1.1 elric 433 1.1 elric ret = dsstringprep(ds1, &ds1lp, &ds1len); 434 1.1 elric if (ret) 435 1.1 elric return ret; 436 1.1 elric ret = dsstringprep(ds2, &ds2lp, &ds2len); 437 1.1 elric if (ret) { 438 1.1 elric free(ds1lp); 439 1.1 elric return ret; 440 1.1 elric } 441 1.1 elric 442 1.1 elric if (ds1len != ds2len) 443 1.1 elric *diff = ds1len - ds2len; 444 1.1 elric else { 445 1.1 elric for (i = 0; i < ds1len; i++) { 446 1.1 elric *diff = ds1lp[i] - ds2lp[i]; 447 1.1 elric if (*diff) 448 1.1 elric break; 449 1.1 elric } 450 1.1 elric } 451 1.1 elric free(ds1lp); 452 1.1 elric free(ds2lp); 453 1.1 elric 454 1.1 elric return 0; 455 1.1 elric } 456 1.1 elric 457 1.1 elric int 458 1.1 elric _hx509_name_cmp(const Name *n1, const Name *n2, int *c) 459 1.1 elric { 460 1.2 christos int ret; 461 1.2 christos size_t i, j; 462 1.1 elric 463 1.1 elric *c = n1->u.rdnSequence.len - n2->u.rdnSequence.len; 464 1.1 elric if (*c) 465 1.1 elric return 0; 466 1.1 elric 467 1.1 elric for (i = 0 ; i < n1->u.rdnSequence.len; i++) { 468 1.1 elric *c = n1->u.rdnSequence.val[i].len - n2->u.rdnSequence.val[i].len; 469 1.1 elric if (*c) 470 1.1 elric return 0; 471 1.1 elric 472 1.1 elric for (j = 0; j < n1->u.rdnSequence.val[i].len; j++) { 473 1.1 elric *c = der_heim_oid_cmp(&n1->u.rdnSequence.val[i].val[j].type, 474 1.1 elric &n1->u.rdnSequence.val[i].val[j].type); 475 1.1 elric if (*c) 476 1.1 elric return 0; 477 1.2 christos 478 1.1 elric ret = _hx509_name_ds_cmp(&n1->u.rdnSequence.val[i].val[j].value, 479 1.1 elric &n2->u.rdnSequence.val[i].val[j].value, 480 1.1 elric c); 481 1.1 elric if (ret) 482 1.1 elric return ret; 483 1.1 elric if (*c) 484 1.1 elric return 0; 485 1.1 elric } 486 1.1 elric } 487 1.1 elric *c = 0; 488 1.1 elric return 0; 489 1.1 elric } 490 1.1 elric 491 1.1 elric /** 492 1.1 elric * Compare to hx509 name object, useful for sorting. 493 1.1 elric * 494 1.1 elric * @param n1 a hx509 name object. 495 1.1 elric * @param n2 a hx509 name object. 496 1.1 elric * 497 1.1 elric * @return 0 the objects are the same, returns > 0 is n2 is "larger" 498 1.1 elric * then n2, < 0 if n1 is "smaller" then n2. 499 1.1 elric * 500 1.1 elric * @ingroup hx509_name 501 1.1 elric */ 502 1.1 elric 503 1.1 elric int 504 1.1 elric hx509_name_cmp(hx509_name n1, hx509_name n2) 505 1.1 elric { 506 1.1 elric int ret, diff; 507 1.1 elric ret = _hx509_name_cmp(&n1->der_name, &n2->der_name, &diff); 508 1.1 elric if (ret) 509 1.1 elric return ret; 510 1.1 elric return diff; 511 1.1 elric } 512 1.1 elric 513 1.1 elric 514 1.1 elric int 515 1.1 elric _hx509_name_from_Name(const Name *n, hx509_name *name) 516 1.1 elric { 517 1.1 elric int ret; 518 1.1 elric *name = calloc(1, sizeof(**name)); 519 1.1 elric if (*name == NULL) 520 1.1 elric return ENOMEM; 521 1.1 elric ret = copy_Name(n, &(*name)->der_name); 522 1.1 elric if (ret) { 523 1.1 elric free(*name); 524 1.1 elric *name = NULL; 525 1.1 elric } 526 1.1 elric return ret; 527 1.1 elric } 528 1.1 elric 529 1.1 elric int 530 1.1 elric _hx509_name_modify(hx509_context context, 531 1.1 elric Name *name, 532 1.1 elric int append, 533 1.1 elric const heim_oid *oid, 534 1.1 elric const char *str) 535 1.1 elric { 536 1.1 elric RelativeDistinguishedName *rdn; 537 1.1 elric int ret; 538 1.1 elric void *ptr; 539 1.1 elric 540 1.1 elric ptr = realloc(name->u.rdnSequence.val, 541 1.1 elric sizeof(name->u.rdnSequence.val[0]) * 542 1.1 elric (name->u.rdnSequence.len + 1)); 543 1.1 elric if (ptr == NULL) { 544 1.1 elric hx509_set_error_string(context, 0, ENOMEM, "Out of memory"); 545 1.1 elric return ENOMEM; 546 1.1 elric } 547 1.1 elric name->u.rdnSequence.val = ptr; 548 1.1 elric 549 1.1 elric if (append) { 550 1.1 elric rdn = &name->u.rdnSequence.val[name->u.rdnSequence.len]; 551 1.1 elric } else { 552 1.1 elric memmove(&name->u.rdnSequence.val[1], 553 1.1 elric &name->u.rdnSequence.val[0], 554 1.1 elric name->u.rdnSequence.len * 555 1.1 elric sizeof(name->u.rdnSequence.val[0])); 556 1.2 christos 557 1.1 elric rdn = &name->u.rdnSequence.val[0]; 558 1.1 elric } 559 1.1 elric rdn->val = malloc(sizeof(rdn->val[0])); 560 1.1 elric if (rdn->val == NULL) 561 1.1 elric return ENOMEM; 562 1.1 elric rdn->len = 1; 563 1.1 elric ret = der_copy_oid(oid, &rdn->val[0].type); 564 1.1 elric if (ret) 565 1.1 elric return ret; 566 1.1 elric rdn->val[0].value.element = choice_DirectoryString_utf8String; 567 1.1 elric rdn->val[0].value.u.utf8String = strdup(str); 568 1.1 elric if (rdn->val[0].value.u.utf8String == NULL) 569 1.1 elric return ENOMEM; 570 1.1 elric name->u.rdnSequence.len += 1; 571 1.1 elric 572 1.1 elric return 0; 573 1.1 elric } 574 1.1 elric 575 1.1 elric /** 576 1.1 elric * Parse a string into a hx509 name object. 577 1.1 elric * 578 1.1 elric * @param context A hx509 context. 579 1.1 elric * @param str a string to parse. 580 1.1 elric * @param name the resulting object, NULL in case of error. 581 1.1 elric * 582 1.1 elric * @return An hx509 error code, see hx509_get_error_string(). 583 1.1 elric * 584 1.1 elric * @ingroup hx509_name 585 1.1 elric */ 586 1.1 elric 587 1.1 elric int 588 1.1 elric hx509_parse_name(hx509_context context, const char *str, hx509_name *name) 589 1.1 elric { 590 1.1 elric const char *p, *q; 591 1.1 elric size_t len; 592 1.1 elric hx509_name n; 593 1.1 elric int ret; 594 1.1 elric 595 1.1 elric *name = NULL; 596 1.1 elric 597 1.1 elric n = calloc(1, sizeof(*n)); 598 1.1 elric if (n == NULL) { 599 1.1 elric hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 600 1.1 elric return ENOMEM; 601 1.1 elric } 602 1.1 elric 603 1.1 elric n->der_name.element = choice_Name_rdnSequence; 604 1.1 elric 605 1.1 elric p = str; 606 1.1 elric 607 1.1 elric while (p != NULL && *p != '\0') { 608 1.1 elric heim_oid oid; 609 1.1 elric int last; 610 1.1 elric 611 1.1 elric q = strchr(p, ','); 612 1.1 elric if (q) { 613 1.1 elric len = (q - p); 614 1.1 elric last = 1; 615 1.1 elric } else { 616 1.1 elric len = strlen(p); 617 1.1 elric last = 0; 618 1.1 elric } 619 1.1 elric 620 1.1 elric q = strchr(p, '='); 621 1.1 elric if (q == NULL) { 622 1.1 elric ret = HX509_PARSING_NAME_FAILED; 623 1.1 elric hx509_set_error_string(context, 0, ret, "missing = in %s", p); 624 1.1 elric goto out; 625 1.1 elric } 626 1.1 elric if (q == p) { 627 1.1 elric ret = HX509_PARSING_NAME_FAILED; 628 1.1 elric hx509_set_error_string(context, 0, ret, 629 1.1 elric "missing name before = in %s", p); 630 1.1 elric goto out; 631 1.1 elric } 632 1.2 christos 633 1.2 christos if ((size_t)(q - p) > len) { 634 1.1 elric ret = HX509_PARSING_NAME_FAILED; 635 1.1 elric hx509_set_error_string(context, 0, ret, " = after , in %s", p); 636 1.1 elric goto out; 637 1.1 elric } 638 1.1 elric 639 1.1 elric ret = stringtooid(p, q - p, &oid); 640 1.1 elric if (ret) { 641 1.1 elric ret = HX509_PARSING_NAME_FAILED; 642 1.1 elric hx509_set_error_string(context, 0, ret, 643 1.1 elric "unknown type: %.*s", (int)(q - p), p); 644 1.1 elric goto out; 645 1.1 elric } 646 1.2 christos 647 1.1 elric { 648 1.1 elric size_t pstr_len = len - (q - p) - 1; 649 1.1 elric const char *pstr = p + (q - p) + 1; 650 1.1 elric char *r; 651 1.2 christos 652 1.1 elric r = malloc(pstr_len + 1); 653 1.1 elric if (r == NULL) { 654 1.1 elric der_free_oid(&oid); 655 1.1 elric ret = ENOMEM; 656 1.1 elric hx509_set_error_string(context, 0, ret, "out of memory"); 657 1.1 elric goto out; 658 1.1 elric } 659 1.1 elric memcpy(r, pstr, pstr_len); 660 1.1 elric r[pstr_len] = '\0'; 661 1.1 elric 662 1.1 elric ret = _hx509_name_modify(context, &n->der_name, 0, &oid, r); 663 1.1 elric free(r); 664 1.1 elric der_free_oid(&oid); 665 1.1 elric if(ret) 666 1.1 elric goto out; 667 1.1 elric } 668 1.1 elric p += len + last; 669 1.1 elric } 670 1.1 elric 671 1.1 elric *name = n; 672 1.1 elric 673 1.1 elric return 0; 674 1.1 elric out: 675 1.1 elric hx509_name_free(&n); 676 1.1 elric return HX509_NAME_MALFORMED; 677 1.1 elric } 678 1.1 elric 679 1.1 elric /** 680 1.1 elric * Copy a hx509 name object. 681 1.1 elric * 682 1.1 elric * @param context A hx509 cotext. 683 1.1 elric * @param from the name to copy from 684 1.1 elric * @param to the name to copy to 685 1.1 elric * 686 1.1 elric * @return An hx509 error code, see hx509_get_error_string(). 687 1.1 elric * 688 1.1 elric * @ingroup hx509_name 689 1.1 elric */ 690 1.1 elric 691 1.1 elric int 692 1.1 elric hx509_name_copy(hx509_context context, const hx509_name from, hx509_name *to) 693 1.1 elric { 694 1.1 elric int ret; 695 1.1 elric 696 1.1 elric *to = calloc(1, sizeof(**to)); 697 1.1 elric if (*to == NULL) 698 1.1 elric return ENOMEM; 699 1.1 elric ret = copy_Name(&from->der_name, &(*to)->der_name); 700 1.1 elric if (ret) { 701 1.1 elric free(*to); 702 1.1 elric *to = NULL; 703 1.1 elric return ENOMEM; 704 1.1 elric } 705 1.1 elric return 0; 706 1.1 elric } 707 1.1 elric 708 1.1 elric /** 709 1.1 elric * Convert a hx509_name into a Name. 710 1.1 elric * 711 1.1 elric * @param from the name to copy from 712 1.1 elric * @param to the name to copy to 713 1.1 elric * 714 1.1 elric * @return An hx509 error code, see hx509_get_error_string(). 715 1.1 elric * 716 1.1 elric * @ingroup hx509_name 717 1.1 elric */ 718 1.1 elric 719 1.1 elric int 720 1.1 elric hx509_name_to_Name(const hx509_name from, Name *to) 721 1.1 elric { 722 1.1 elric return copy_Name(&from->der_name, to); 723 1.1 elric } 724 1.1 elric 725 1.1 elric int 726 1.1 elric hx509_name_normalize(hx509_context context, hx509_name name) 727 1.1 elric { 728 1.1 elric return 0; 729 1.1 elric } 730 1.1 elric 731 1.1 elric /** 732 1.1 elric * Expands variables in the name using env. Variables are on the form 733 1.1 elric * ${name}. Useful when dealing with certificate templates. 734 1.1 elric * 735 1.1 elric * @param context A hx509 cotext. 736 1.1 elric * @param name the name to expand. 737 1.1 elric * @param env environment variable to expand. 738 1.1 elric * 739 1.1 elric * @return An hx509 error code, see hx509_get_error_string(). 740 1.1 elric * 741 1.1 elric * @ingroup hx509_name 742 1.1 elric */ 743 1.1 elric 744 1.1 elric int 745 1.1 elric hx509_name_expand(hx509_context context, 746 1.1 elric hx509_name name, 747 1.1 elric hx509_env env) 748 1.1 elric { 749 1.1 elric Name *n = &name->der_name; 750 1.2 christos size_t i, j; 751 1.1 elric 752 1.1 elric if (env == NULL) 753 1.1 elric return 0; 754 1.1 elric 755 1.1 elric if (n->element != choice_Name_rdnSequence) { 756 1.1 elric hx509_set_error_string(context, 0, EINVAL, "RDN not of supported type"); 757 1.1 elric return EINVAL; 758 1.1 elric } 759 1.1 elric 760 1.1 elric for (i = 0 ; i < n->u.rdnSequence.len; i++) { 761 1.1 elric for (j = 0; j < n->u.rdnSequence.val[i].len; j++) { 762 1.1 elric /** Only UTF8String rdnSequence names are allowed */ 763 1.1 elric /* 764 1.1 elric THIS SHOULD REALLY BE: 765 1.1 elric COMP = n->u.rdnSequence.val[i].val[j]; 766 1.1 elric normalize COMP to utf8 767 1.1 elric check if there are variables 768 1.1 elric expand variables 769 1.1 elric convert back to orignal format, store in COMP 770 1.1 elric free normalized utf8 string 771 1.1 elric */ 772 1.1 elric DirectoryString *ds = &n->u.rdnSequence.val[i].val[j].value; 773 1.1 elric char *p, *p2; 774 1.1 elric struct rk_strpool *strpool = NULL; 775 1.1 elric 776 1.1 elric if (ds->element != choice_DirectoryString_utf8String) { 777 1.1 elric hx509_set_error_string(context, 0, EINVAL, "unsupported type"); 778 1.1 elric return EINVAL; 779 1.1 elric } 780 1.1 elric p = strstr(ds->u.utf8String, "${"); 781 1.1 elric if (p) { 782 1.1 elric strpool = rk_strpoolprintf(strpool, "%.*s", 783 1.1 elric (int)(p - ds->u.utf8String), 784 1.1 elric ds->u.utf8String); 785 1.1 elric if (strpool == NULL) { 786 1.1 elric hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 787 1.1 elric return ENOMEM; 788 1.1 elric } 789 1.1 elric } 790 1.1 elric while (p != NULL) { 791 1.1 elric /* expand variables */ 792 1.1 elric const char *value; 793 1.1 elric p2 = strchr(p, '}'); 794 1.1 elric if (p2 == NULL) { 795 1.1 elric hx509_set_error_string(context, 0, EINVAL, "missing }"); 796 1.1 elric rk_strpoolfree(strpool); 797 1.1 elric return EINVAL; 798 1.1 elric } 799 1.1 elric p += 2; 800 1.1 elric value = hx509_env_lfind(context, env, p, p2 - p); 801 1.1 elric if (value == NULL) { 802 1.1 elric hx509_set_error_string(context, 0, EINVAL, 803 1.1 elric "variable %.*s missing", 804 1.1 elric (int)(p2 - p), p); 805 1.1 elric rk_strpoolfree(strpool); 806 1.1 elric return EINVAL; 807 1.1 elric } 808 1.1 elric strpool = rk_strpoolprintf(strpool, "%s", value); 809 1.1 elric if (strpool == NULL) { 810 1.1 elric hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 811 1.1 elric return ENOMEM; 812 1.1 elric } 813 1.1 elric p2++; 814 1.1 elric 815 1.1 elric p = strstr(p2, "${"); 816 1.1 elric if (p) 817 1.1 elric strpool = rk_strpoolprintf(strpool, "%.*s", 818 1.1 elric (int)(p - p2), p2); 819 1.1 elric else 820 1.1 elric strpool = rk_strpoolprintf(strpool, "%s", p2); 821 1.1 elric if (strpool == NULL) { 822 1.1 elric hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 823 1.1 elric return ENOMEM; 824 1.1 elric } 825 1.1 elric } 826 1.1 elric if (strpool) { 827 1.1 elric free(ds->u.utf8String); 828 1.1 elric ds->u.utf8String = rk_strpoolcollect(strpool); 829 1.1 elric if (ds->u.utf8String == NULL) { 830 1.1 elric hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 831 1.1 elric return ENOMEM; 832 1.1 elric } 833 1.1 elric } 834 1.1 elric } 835 1.1 elric } 836 1.1 elric return 0; 837 1.1 elric } 838 1.1 elric 839 1.1 elric /** 840 1.1 elric * Free a hx509 name object, upond return *name will be NULL. 841 1.1 elric * 842 1.1 elric * @param name a hx509 name object to be freed. 843 1.1 elric * 844 1.1 elric * @ingroup hx509_name 845 1.1 elric */ 846 1.1 elric 847 1.1 elric void 848 1.1 elric hx509_name_free(hx509_name *name) 849 1.1 elric { 850 1.1 elric free_Name(&(*name)->der_name); 851 1.1 elric memset(*name, 0, sizeof(**name)); 852 1.1 elric free(*name); 853 1.1 elric *name = NULL; 854 1.1 elric } 855 1.1 elric 856 1.1 elric /** 857 1.1 elric * Convert a DER encoded name info a string. 858 1.1 elric * 859 1.1 elric * @param data data to a DER/BER encoded name 860 1.1 elric * @param length length of data 861 1.1 elric * @param str the resulting string, is NULL on failure. 862 1.1 elric * 863 1.1 elric * @return An hx509 error code, see hx509_get_error_string(). 864 1.1 elric * 865 1.1 elric * @ingroup hx509_name 866 1.1 elric */ 867 1.1 elric 868 1.1 elric int 869 1.1 elric hx509_unparse_der_name(const void *data, size_t length, char **str) 870 1.1 elric { 871 1.1 elric Name name; 872 1.1 elric int ret; 873 1.1 elric 874 1.1 elric *str = NULL; 875 1.1 elric 876 1.1 elric ret = decode_Name(data, length, &name, NULL); 877 1.1 elric if (ret) 878 1.1 elric return ret; 879 1.1 elric ret = _hx509_Name_to_string(&name, str); 880 1.1 elric free_Name(&name); 881 1.1 elric return ret; 882 1.1 elric } 883 1.1 elric 884 1.1 elric /** 885 1.1 elric * Convert a hx509_name object to DER encoded name. 886 1.1 elric * 887 1.1 elric * @param name name to concert 888 1.1 elric * @param os data to a DER encoded name, free the resulting octet 889 1.1 elric * string with hx509_xfree(os->data). 890 1.1 elric * 891 1.1 elric * @return An hx509 error code, see hx509_get_error_string(). 892 1.1 elric * 893 1.1 elric * @ingroup hx509_name 894 1.1 elric */ 895 1.1 elric 896 1.1 elric int 897 1.1 elric hx509_name_binary(const hx509_name name, heim_octet_string *os) 898 1.1 elric { 899 1.1 elric size_t size; 900 1.1 elric int ret; 901 1.1 elric 902 1.1 elric ASN1_MALLOC_ENCODE(Name, os->data, os->length, &name->der_name, &size, ret); 903 1.1 elric if (ret) 904 1.1 elric return ret; 905 1.1 elric if (os->length != size) 906 1.1 elric _hx509_abort("internal ASN.1 encoder error"); 907 1.1 elric 908 1.1 elric return 0; 909 1.1 elric } 910 1.1 elric 911 1.1 elric int 912 1.1 elric _hx509_unparse_Name(const Name *aname, char **str) 913 1.1 elric { 914 1.1 elric hx509_name name; 915 1.1 elric int ret; 916 1.1 elric 917 1.1 elric ret = _hx509_name_from_Name(aname, &name); 918 1.1 elric if (ret) 919 1.1 elric return ret; 920 1.1 elric 921 1.1 elric ret = hx509_name_to_string(name, str); 922 1.1 elric hx509_name_free(&name); 923 1.1 elric return ret; 924 1.1 elric } 925 1.1 elric 926 1.1 elric /** 927 1.1 elric * Unparse the hx509 name in name into a string. 928 1.1 elric * 929 1.1 elric * @param name the name to check if its empty/null. 930 1.1 elric * 931 1.1 elric * @return non zero if the name is empty/null. 932 1.1 elric * 933 1.1 elric * @ingroup hx509_name 934 1.1 elric */ 935 1.1 elric 936 1.1 elric int 937 1.1 elric hx509_name_is_null_p(const hx509_name name) 938 1.1 elric { 939 1.1 elric return name->der_name.u.rdnSequence.len == 0; 940 1.1 elric } 941 1.1 elric 942 1.1 elric /** 943 1.1 elric * Unparse the hx509 name in name into a string. 944 1.1 elric * 945 1.1 elric * @param name the name to print 946 1.1 elric * @param str an allocated string returns the name in string form 947 1.1 elric * 948 1.1 elric * @return An hx509 error code, see hx509_get_error_string(). 949 1.1 elric * 950 1.1 elric * @ingroup hx509_name 951 1.1 elric */ 952 1.1 elric 953 1.1 elric int 954 1.1 elric hx509_general_name_unparse(GeneralName *name, char **str) 955 1.1 elric { 956 1.1 elric struct rk_strpool *strpool = NULL; 957 1.3 christos int ret = 0; 958 1.1 elric 959 1.1 elric *str = NULL; 960 1.1 elric 961 1.1 elric switch (name->element) { 962 1.1 elric case choice_GeneralName_otherName: { 963 1.1 elric char *oid; 964 1.1 elric hx509_oid_sprint(&name->u.otherName.type_id, &oid); 965 1.1 elric if (oid == NULL) 966 1.1 elric return ENOMEM; 967 1.1 elric strpool = rk_strpoolprintf(strpool, "otherName: %s", oid); 968 1.1 elric free(oid); 969 1.1 elric break; 970 1.1 elric } 971 1.1 elric case choice_GeneralName_rfc822Name: 972 1.1 elric strpool = rk_strpoolprintf(strpool, "rfc822Name: %.*s\n", 973 1.1 elric (int)name->u.rfc822Name.length, 974 1.1 elric (char *)name->u.rfc822Name.data); 975 1.1 elric break; 976 1.1 elric case choice_GeneralName_dNSName: 977 1.1 elric strpool = rk_strpoolprintf(strpool, "dNSName: %.*s\n", 978 1.1 elric (int)name->u.dNSName.length, 979 1.1 elric (char *)name->u.dNSName.data); 980 1.1 elric break; 981 1.1 elric case choice_GeneralName_directoryName: { 982 1.1 elric Name dir; 983 1.1 elric char *s; 984 1.1 elric memset(&dir, 0, sizeof(dir)); 985 1.2 christos dir.element = (enum Name_enum)name->u.directoryName.element; 986 1.1 elric dir.u.rdnSequence = name->u.directoryName.u.rdnSequence; 987 1.1 elric ret = _hx509_unparse_Name(&dir, &s); 988 1.1 elric if (ret) 989 1.1 elric return ret; 990 1.1 elric strpool = rk_strpoolprintf(strpool, "directoryName: %s", s); 991 1.1 elric free(s); 992 1.1 elric break; 993 1.1 elric } 994 1.1 elric case choice_GeneralName_uniformResourceIdentifier: 995 1.1 elric strpool = rk_strpoolprintf(strpool, "URI: %.*s", 996 1.1 elric (int)name->u.uniformResourceIdentifier.length, 997 1.1 elric (char *)name->u.uniformResourceIdentifier.data); 998 1.1 elric break; 999 1.1 elric case choice_GeneralName_iPAddress: { 1000 1.1 elric unsigned char *a = name->u.iPAddress.data; 1001 1.1 elric 1002 1.1 elric strpool = rk_strpoolprintf(strpool, "IPAddress: "); 1003 1.1 elric if (strpool == NULL) 1004 1.1 elric break; 1005 1.1 elric if (name->u.iPAddress.length == 4) 1006 1.1 elric strpool = rk_strpoolprintf(strpool, "%d.%d.%d.%d", 1007 1.1 elric a[0], a[1], a[2], a[3]); 1008 1.1 elric else if (name->u.iPAddress.length == 16) 1009 1.1 elric strpool = rk_strpoolprintf(strpool, 1010 1.1 elric "%02X:%02X:%02X:%02X:" 1011 1.1 elric "%02X:%02X:%02X:%02X:" 1012 1.1 elric "%02X:%02X:%02X:%02X:" 1013 1.1 elric "%02X:%02X:%02X:%02X", 1014 1.1 elric a[0], a[1], a[2], a[3], 1015 1.1 elric a[4], a[5], a[6], a[7], 1016 1.1 elric a[8], a[9], a[10], a[11], 1017 1.1 elric a[12], a[13], a[14], a[15]); 1018 1.1 elric else 1019 1.1 elric strpool = rk_strpoolprintf(strpool, 1020 1.1 elric "unknown IP address of length %lu", 1021 1.1 elric (unsigned long)name->u.iPAddress.length); 1022 1.1 elric break; 1023 1.1 elric } 1024 1.1 elric case choice_GeneralName_registeredID: { 1025 1.1 elric char *oid; 1026 1.1 elric hx509_oid_sprint(&name->u.registeredID, &oid); 1027 1.1 elric if (oid == NULL) 1028 1.1 elric return ENOMEM; 1029 1.1 elric strpool = rk_strpoolprintf(strpool, "registeredID: %s", oid); 1030 1.1 elric free(oid); 1031 1.1 elric break; 1032 1.1 elric } 1033 1.1 elric default: 1034 1.1 elric return EINVAL; 1035 1.1 elric } 1036 1.3 christos if (ret) 1037 1.3 christos rk_strpoolfree(strpool); 1038 1.3 christos else if (strpool == NULL || (*str = rk_strpoolcollect(strpool)) == NULL) 1039 1.1 elric return ENOMEM; 1040 1.3 christos return ret; 1041 1.1 elric } 1042