Home | History | Annotate | Line # | Download | only in hx509
      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