diff options
Diffstat (limited to 'crypto/heimdal/lib/hx509/name.c')
-rw-r--r-- | crypto/heimdal/lib/hx509/name.c | 918 |
1 files changed, 0 insertions, 918 deletions
diff --git a/crypto/heimdal/lib/hx509/name.c b/crypto/heimdal/lib/hx509/name.c deleted file mode 100644 index 69fafe1..0000000 --- a/crypto/heimdal/lib/hx509/name.c +++ /dev/null @@ -1,918 +0,0 @@ -/* - * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "hx_locl.h" -RCSID("$Id: name.c 22432 2008-01-13 14:08:03Z lha $"); - -/** - * @page page_name PKIX/X.509 Names - * - * There are several names in PKIX/X.509, GeneralName and Name. - * - * A Name consists of an ordered list of Relative Distinguished Names - * (RDN). Each RDN consists of an unordered list of typed strings. The - * types are defined by OID and have long and short description. For - * example id-at-commonName (2.5.4.3) have the long name CommonName - * and short name CN. The string itself can be of serveral encoding, - * UTF8, UTF16, Teltex string, etc. The type limit what encoding - * should be used. - * - * GeneralName is a broader nametype that can contains al kind of - * stuff like Name, IP addresses, partial Name, etc. - * - * Name is mapped into a hx509_name object. - * - * Parse and string name into a hx509_name object with hx509_parse_name(), - * make it back into string representation with hx509_name_to_string(). - * - * Name string are defined rfc2253, rfc1779 and X.501. - * - * See the library functions here: @ref hx509_name - */ - -static const struct { - const char *n; - const heim_oid *(*o)(void); -} no[] = { - { "C", oid_id_at_countryName }, - { "CN", oid_id_at_commonName }, - { "DC", oid_id_domainComponent }, - { "L", oid_id_at_localityName }, - { "O", oid_id_at_organizationName }, - { "OU", oid_id_at_organizationalUnitName }, - { "S", oid_id_at_stateOrProvinceName }, - { "STREET", oid_id_at_streetAddress }, - { "UID", oid_id_Userid }, - { "emailAddress", oid_id_pkcs9_emailAddress }, - { "serialNumber", oid_id_at_serialNumber } -}; - -static char * -quote_string(const char *f, size_t len, size_t *rlen) -{ - size_t i, j, tolen; - const char *from = f; - char *to; - - tolen = len * 3 + 1; - to = malloc(tolen); - if (to == NULL) - return NULL; - - for (i = 0, j = 0; i < len; i++) { - if (from[i] == ' ' && i + 1 < len) - to[j++] = from[i]; - else if (from[i] == ',' || from[i] == '=' || from[i] == '+' || - from[i] == '<' || from[i] == '>' || from[i] == '#' || - from[i] == ';' || from[i] == ' ') - { - to[j++] = '\\'; - to[j++] = from[i]; - } else if (((unsigned char)from[i]) >= 32 && ((unsigned char)from[i]) <= 127) { - to[j++] = from[i]; - } else { - int l = snprintf(&to[j], tolen - j - 1, - "#%02x", (unsigned char)from[i]); - j += l; - } - } - to[j] = '\0'; - assert(j < tolen); - *rlen = j; - return to; -} - - -static int -append_string(char **str, size_t *total_len, const char *ss, - size_t len, int quote) -{ - char *s, *qs; - - if (quote) - qs = quote_string(ss, len, &len); - else - qs = rk_UNCONST(ss); - - s = realloc(*str, len + *total_len + 1); - if (s == NULL) - _hx509_abort("allocation failure"); /* XXX */ - memcpy(s + *total_len, qs, len); - if (qs != ss) - free(qs); - s[*total_len + len] = '\0'; - *str = s; - *total_len += len; - return 0; -} - -static char * -oidtostring(const heim_oid *type) -{ - char *s; - size_t i; - - for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) { - if (der_heim_oid_cmp((*no[i].o)(), type) == 0) - return strdup(no[i].n); - } - if (der_print_heim_oid(type, '.', &s) != 0) - return NULL; - return s; -} - -static int -stringtooid(const char *name, size_t len, heim_oid *oid) -{ - int i, ret; - char *s; - - memset(oid, 0, sizeof(*oid)); - - for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) { - if (strncasecmp(no[i].n, name, len) == 0) - return der_copy_oid((*no[i].o)(), oid); - } - s = malloc(len + 1); - if (s == NULL) - return ENOMEM; - memcpy(s, name, len); - s[len] = '\0'; - ret = der_parse_heim_oid(s, ".", oid); - free(s); - return ret; -} - -/** - * Convert the hx509 name object into a printable string. - * The resulting string should be freed with free(). - * - * @param name name to print - * @param str the string to return - * - * @return An hx509 error code, see hx509_get_error_string(). - * - * @ingroup hx509_name - */ - -int -hx509_name_to_string(const hx509_name name, char **str) -{ - return _hx509_Name_to_string(&name->der_name, str); -} - -int -_hx509_Name_to_string(const Name *n, char **str) -{ - size_t total_len = 0; - int i, j; - - *str = strdup(""); - if (*str == NULL) - return ENOMEM; - - for (i = n->u.rdnSequence.len - 1 ; i >= 0 ; i--) { - int len; - - for (j = 0; j < n->u.rdnSequence.val[i].len; j++) { - DirectoryString *ds = &n->u.rdnSequence.val[i].val[j].value; - char *oidname; - char *ss; - - oidname = oidtostring(&n->u.rdnSequence.val[i].val[j].type); - - switch(ds->element) { - case choice_DirectoryString_ia5String: - ss = ds->u.ia5String; - break; - case choice_DirectoryString_printableString: - ss = ds->u.printableString; - break; - case choice_DirectoryString_utf8String: - ss = ds->u.utf8String; - break; - case choice_DirectoryString_bmpString: { - uint16_t *bmp = ds->u.bmpString.data; - size_t bmplen = ds->u.bmpString.length; - size_t k; - - ss = malloc(bmplen + 1); - if (ss == NULL) - _hx509_abort("allocation failure"); /* XXX */ - for (k = 0; k < bmplen; k++) - ss[k] = bmp[k] & 0xff; /* XXX */ - ss[k] = '\0'; - break; - } - case choice_DirectoryString_teletexString: - ss = malloc(ds->u.teletexString.length + 1); - if (ss == NULL) - _hx509_abort("allocation failure"); /* XXX */ - memcpy(ss, ds->u.teletexString.data, ds->u.teletexString.length); - ss[ds->u.teletexString.length] = '\0'; - break; - case choice_DirectoryString_universalString: { - uint32_t *uni = ds->u.universalString.data; - size_t unilen = ds->u.universalString.length; - size_t k; - - ss = malloc(unilen + 1); - if (ss == NULL) - _hx509_abort("allocation failure"); /* XXX */ - for (k = 0; k < unilen; k++) - ss[k] = uni[k] & 0xff; /* XXX */ - ss[k] = '\0'; - break; - } - default: - _hx509_abort("unknown directory type: %d", ds->element); - exit(1); - } - append_string(str, &total_len, oidname, strlen(oidname), 0); - free(oidname); - append_string(str, &total_len, "=", 1, 0); - len = strlen(ss); - append_string(str, &total_len, ss, len, 1); - if (ds->element == choice_DirectoryString_universalString || - ds->element == choice_DirectoryString_bmpString || - ds->element == choice_DirectoryString_teletexString) - { - free(ss); - } - if (j + 1 < n->u.rdnSequence.val[i].len) - append_string(str, &total_len, "+", 1, 0); - } - - if (i > 0) - append_string(str, &total_len, ",", 1, 0); - } - return 0; -} - -/* - * XXX this function is broken, it needs to compare code points, not - * bytes. - */ - -static void -prune_space(const unsigned char **s) -{ - while (**s == ' ') - (*s)++; -} - -int -_hx509_name_ds_cmp(const DirectoryString *ds1, const DirectoryString *ds2) -{ - int c; - - c = ds1->element - ds2->element; - if (c) - return c; - - switch(ds1->element) { - case choice_DirectoryString_ia5String: - c = strcmp(ds1->u.ia5String, ds2->u.ia5String); - break; - case choice_DirectoryString_teletexString: - c = der_heim_octet_string_cmp(&ds1->u.teletexString, - &ds2->u.teletexString); - break; - case choice_DirectoryString_printableString: { - const unsigned char *s1 = (unsigned char*)ds1->u.printableString; - const unsigned char *s2 = (unsigned char*)ds2->u.printableString; - prune_space(&s1); prune_space(&s2); - while (*s1 && *s2) { - if (toupper(*s1) != toupper(*s2)) { - c = toupper(*s1) - toupper(*s2); - break; - } - if (*s1 == ' ') { prune_space(&s1); prune_space(&s2); } - else { s1++; s2++; } - } - prune_space(&s1); prune_space(&s2); - c = *s1 - *s2; - break; - } - case choice_DirectoryString_utf8String: - c = strcmp(ds1->u.utf8String, ds2->u.utf8String); - break; - case choice_DirectoryString_universalString: - c = der_heim_universal_string_cmp(&ds1->u.universalString, - &ds2->u.universalString); - break; - case choice_DirectoryString_bmpString: - c = der_heim_bmp_string_cmp(&ds1->u.bmpString, - &ds2->u.bmpString); - break; - default: - c = 1; - break; - } - return c; -} - -int -_hx509_name_cmp(const Name *n1, const Name *n2) -{ - int i, j, c; - - c = n1->u.rdnSequence.len - n2->u.rdnSequence.len; - if (c) - return c; - - for (i = 0 ; i < n1->u.rdnSequence.len; i++) { - c = n1->u.rdnSequence.val[i].len - n2->u.rdnSequence.val[i].len; - if (c) - return c; - - for (j = 0; j < n1->u.rdnSequence.val[i].len; j++) { - c = der_heim_oid_cmp(&n1->u.rdnSequence.val[i].val[j].type, - &n1->u.rdnSequence.val[i].val[j].type); - if (c) - return c; - - c = _hx509_name_ds_cmp(&n1->u.rdnSequence.val[i].val[j].value, - &n2->u.rdnSequence.val[i].val[j].value); - if (c) - return c; - } - } - return 0; -} - -/** - * Compare to hx509 name object, useful for sorting. - * - * @param n1 a hx509 name object. - * @param n2 a hx509 name object. - * - * @return 0 the objects are the same, returns > 0 is n2 is "larger" - * then n2, < 0 if n1 is "smaller" then n2. - * - * @ingroup hx509_name - */ - -int -hx509_name_cmp(hx509_name n1, hx509_name n2) -{ - return _hx509_name_cmp(&n1->der_name, &n2->der_name); -} - - -int -_hx509_name_from_Name(const Name *n, hx509_name *name) -{ - int ret; - *name = calloc(1, sizeof(**name)); - if (*name == NULL) - return ENOMEM; - ret = copy_Name(n, &(*name)->der_name); - if (ret) { - free(*name); - *name = NULL; - } - return ret; -} - -int -_hx509_name_modify(hx509_context context, - Name *name, - int append, - const heim_oid *oid, - const char *str) -{ - RelativeDistinguishedName *rdn; - int ret; - void *ptr; - - ptr = realloc(name->u.rdnSequence.val, - sizeof(name->u.rdnSequence.val[0]) * - (name->u.rdnSequence.len + 1)); - if (ptr == NULL) { - hx509_set_error_string(context, 0, ENOMEM, "Out of memory"); - return ENOMEM; - } - name->u.rdnSequence.val = ptr; - - if (append) { - rdn = &name->u.rdnSequence.val[name->u.rdnSequence.len]; - } else { - memmove(&name->u.rdnSequence.val[1], - &name->u.rdnSequence.val[0], - name->u.rdnSequence.len * - sizeof(name->u.rdnSequence.val[0])); - - rdn = &name->u.rdnSequence.val[0]; - } - rdn->val = malloc(sizeof(rdn->val[0])); - if (rdn->val == NULL) - return ENOMEM; - rdn->len = 1; - ret = der_copy_oid(oid, &rdn->val[0].type); - if (ret) - return ret; - rdn->val[0].value.element = choice_DirectoryString_utf8String; - rdn->val[0].value.u.utf8String = strdup(str); - if (rdn->val[0].value.u.utf8String == NULL) - return ENOMEM; - name->u.rdnSequence.len += 1; - - return 0; -} - -/** - * Parse a string into a hx509 name object. - * - * @param context A hx509 context. - * @param str a string to parse. - * @param name the resulting object, NULL in case of error. - * - * @return An hx509 error code, see hx509_get_error_string(). - * - * @ingroup hx509_name - */ - -int -hx509_parse_name(hx509_context context, const char *str, hx509_name *name) -{ - const char *p, *q; - size_t len; - hx509_name n; - int ret; - - *name = NULL; - - n = calloc(1, sizeof(*n)); - if (n == NULL) { - hx509_set_error_string(context, 0, ENOMEM, "out of memory"); - return ENOMEM; - } - - n->der_name.element = choice_Name_rdnSequence; - - p = str; - - while (p != NULL && *p != '\0') { - heim_oid oid; - int last; - - q = strchr(p, ','); - if (q) { - len = (q - p); - last = 1; - } else { - len = strlen(p); - last = 0; - } - - q = strchr(p, '='); - if (q == NULL) { - ret = HX509_PARSING_NAME_FAILED; - hx509_set_error_string(context, 0, ret, "missing = in %s", p); - goto out; - } - if (q == p) { - ret = HX509_PARSING_NAME_FAILED; - hx509_set_error_string(context, 0, ret, - "missing name before = in %s", p); - goto out; - } - - if ((q - p) > len) { - ret = HX509_PARSING_NAME_FAILED; - hx509_set_error_string(context, 0, ret, " = after , in %s", p); - goto out; - } - - ret = stringtooid(p, q - p, &oid); - if (ret) { - ret = HX509_PARSING_NAME_FAILED; - hx509_set_error_string(context, 0, ret, - "unknown type: %.*s", (int)(q - p), p); - goto out; - } - - { - size_t pstr_len = len - (q - p) - 1; - const char *pstr = p + (q - p) + 1; - char *r; - - r = malloc(pstr_len + 1); - if (r == NULL) { - der_free_oid(&oid); - ret = ENOMEM; - hx509_set_error_string(context, 0, ret, "out of memory"); - goto out; - } - memcpy(r, pstr, pstr_len); - r[pstr_len] = '\0'; - - ret = _hx509_name_modify(context, &n->der_name, 0, &oid, r); - free(r); - der_free_oid(&oid); - if(ret) - goto out; - } - p += len + last; - } - - *name = n; - - return 0; -out: - hx509_name_free(&n); - return HX509_NAME_MALFORMED; -} - -/** - * Copy a hx509 name object. - * - * @param context A hx509 cotext. - * @param from the name to copy from - * @param to the name to copy to - * - * @return An hx509 error code, see hx509_get_error_string(). - * - * @ingroup hx509_name - */ - -int -hx509_name_copy(hx509_context context, const hx509_name from, hx509_name *to) -{ - int ret; - - *to = calloc(1, sizeof(**to)); - if (*to == NULL) - return ENOMEM; - ret = copy_Name(&from->der_name, &(*to)->der_name); - if (ret) { - free(*to); - *to = NULL; - return ENOMEM; - } - return 0; -} - -/** - * Convert a hx509_name into a Name. - * - * @param from the name to copy from - * @param to the name to copy to - * - * @return An hx509 error code, see hx509_get_error_string(). - * - * @ingroup hx509_name - */ - -int -hx509_name_to_Name(const hx509_name from, Name *to) -{ - return copy_Name(&from->der_name, to); -} - -int -hx509_name_normalize(hx509_context context, hx509_name name) -{ - return 0; -} - -/** - * Expands variables in the name using env. Variables are on the form - * ${name}. Useful when dealing with certificate templates. - * - * @param context A hx509 cotext. - * @param name the name to expand. - * @param env environment variable to expand. - * - * @return An hx509 error code, see hx509_get_error_string(). - * - * @ingroup hx509_name - */ - -int -hx509_name_expand(hx509_context context, - hx509_name name, - hx509_env env) -{ - Name *n = &name->der_name; - int i, j; - - if (env == NULL) - return 0; - - if (n->element != choice_Name_rdnSequence) { - hx509_set_error_string(context, 0, EINVAL, "RDN not of supported type"); - return EINVAL; - } - - for (i = 0 ; i < n->u.rdnSequence.len; i++) { - for (j = 0; j < n->u.rdnSequence.val[i].len; j++) { - /** Only UTF8String rdnSequence names are allowed */ - /* - THIS SHOULD REALLY BE: - COMP = n->u.rdnSequence.val[i].val[j]; - normalize COMP to utf8 - check if there are variables - expand variables - convert back to orignal format, store in COMP - free normalized utf8 string - */ - DirectoryString *ds = &n->u.rdnSequence.val[i].val[j].value; - char *p, *p2; - struct rk_strpool *strpool = NULL; - - if (ds->element != choice_DirectoryString_utf8String) { - hx509_set_error_string(context, 0, EINVAL, "unsupported type"); - return EINVAL; - } - p = strstr(ds->u.utf8String, "${"); - if (p) { - strpool = rk_strpoolprintf(strpool, "%.*s", - (int)(p - ds->u.utf8String), - ds->u.utf8String); - if (strpool == NULL) { - hx509_set_error_string(context, 0, ENOMEM, "out of memory"); - return ENOMEM; - } - } - while (p != NULL) { - /* expand variables */ - const char *value; - p2 = strchr(p, '}'); - if (p2 == NULL) { - hx509_set_error_string(context, 0, EINVAL, "missing }"); - rk_strpoolfree(strpool); - return EINVAL; - } - p += 2; - value = hx509_env_lfind(context, env, p, p2 - p); - if (value == NULL) { - hx509_set_error_string(context, 0, EINVAL, - "variable %.*s missing", - (int)(p2 - p), p); - rk_strpoolfree(strpool); - return EINVAL; - } - strpool = rk_strpoolprintf(strpool, "%s", value); - if (strpool == NULL) { - hx509_set_error_string(context, 0, ENOMEM, "out of memory"); - return ENOMEM; - } - p2++; - - p = strstr(p2, "${"); - if (p) - strpool = rk_strpoolprintf(strpool, "%.*s", - (int)(p - p2), p2); - else - strpool = rk_strpoolprintf(strpool, "%s", p2); - if (strpool == NULL) { - hx509_set_error_string(context, 0, ENOMEM, "out of memory"); - return ENOMEM; - } - } - if (strpool) { - free(ds->u.utf8String); - ds->u.utf8String = rk_strpoolcollect(strpool); - if (ds->u.utf8String == NULL) { - hx509_set_error_string(context, 0, ENOMEM, "out of memory"); - return ENOMEM; - } - } - } - } - return 0; -} - -/** - * Free a hx509 name object, upond return *name will be NULL. - * - * @param name a hx509 name object to be freed. - * - * @ingroup hx509_name - */ - -void -hx509_name_free(hx509_name *name) -{ - free_Name(&(*name)->der_name); - memset(*name, 0, sizeof(**name)); - free(*name); - *name = NULL; -} - -/** - * Convert a DER encoded name info a string. - * - * @param data data to a DER/BER encoded name - * @param length length of data - * @param str the resulting string, is NULL on failure. - * - * @return An hx509 error code, see hx509_get_error_string(). - * - * @ingroup hx509_name - */ - -int -hx509_unparse_der_name(const void *data, size_t length, char **str) -{ - Name name; - int ret; - - *str = NULL; - - ret = decode_Name(data, length, &name, NULL); - if (ret) - return ret; - ret = _hx509_Name_to_string(&name, str); - free_Name(&name); - return ret; -} - -/** - * Convert a hx509_name object to DER encoded name. - * - * @param name name to concert - * @param os data to a DER encoded name, free the resulting octet - * string with hx509_xfree(os->data). - * - * @return An hx509 error code, see hx509_get_error_string(). - * - * @ingroup hx509_name - */ - -int -hx509_name_binary(const hx509_name name, heim_octet_string *os) -{ - size_t size; - int ret; - - ASN1_MALLOC_ENCODE(Name, os->data, os->length, &name->der_name, &size, ret); - if (ret) - return ret; - if (os->length != size) - _hx509_abort("internal ASN.1 encoder error"); - - return 0; -} - -int -_hx509_unparse_Name(const Name *aname, char **str) -{ - hx509_name name; - int ret; - - ret = _hx509_name_from_Name(aname, &name); - if (ret) - return ret; - - ret = hx509_name_to_string(name, str); - hx509_name_free(&name); - return ret; -} - -/** - * Unparse the hx509 name in name into a string. - * - * @param name the name to check if its empty/null. - * - * @return non zero if the name is empty/null. - * - * @ingroup hx509_name - */ - -int -hx509_name_is_null_p(const hx509_name name) -{ - return name->der_name.u.rdnSequence.len == 0; -} - -/** - * Unparse the hx509 name in name into a string. - * - * @param name the name to print - * @param str an allocated string returns the name in string form - * - * @return An hx509 error code, see krb5_get_error_string(). - * - * @ingroup hx509_name - */ - -int -hx509_general_name_unparse(GeneralName *name, char **str) -{ - struct rk_strpool *strpool = NULL; - - *str = NULL; - - switch (name->element) { - case choice_GeneralName_otherName: { - char *str; - hx509_oid_sprint(&name->u.otherName.type_id, &str); - if (str == NULL) - return ENOMEM; - strpool = rk_strpoolprintf(strpool, "otherName: %s", str); - free(str); - break; - } - case choice_GeneralName_rfc822Name: - strpool = rk_strpoolprintf(strpool, "rfc822Name: %s\n", - name->u.rfc822Name); - break; - case choice_GeneralName_dNSName: - strpool = rk_strpoolprintf(strpool, "dNSName: %s\n", - name->u.dNSName); - break; - case choice_GeneralName_directoryName: { - Name dir; - char *s; - int ret; - memset(&dir, 0, sizeof(dir)); - dir.element = name->u.directoryName.element; - dir.u.rdnSequence = name->u.directoryName.u.rdnSequence; - ret = _hx509_unparse_Name(&dir, &s); - if (ret) - return ret; - strpool = rk_strpoolprintf(strpool, "directoryName: %s", s); - free(s); - break; - } - case choice_GeneralName_uniformResourceIdentifier: - strpool = rk_strpoolprintf(strpool, "URI: %s", - name->u.uniformResourceIdentifier); - break; - case choice_GeneralName_iPAddress: { - unsigned char *a = name->u.iPAddress.data; - - strpool = rk_strpoolprintf(strpool, "IPAddress: "); - if (strpool == NULL) - break; - if (name->u.iPAddress.length == 4) - strpool = rk_strpoolprintf(strpool, "%d.%d.%d.%d", - a[0], a[1], a[2], a[3]); - else if (name->u.iPAddress.length == 16) - strpool = rk_strpoolprintf(strpool, - "%02X:%02X:%02X:%02X:" - "%02X:%02X:%02X:%02X:" - "%02X:%02X:%02X:%02X:" - "%02X:%02X:%02X:%02X", - a[0], a[1], a[2], a[3], - a[4], a[5], a[6], a[7], - a[8], a[9], a[10], a[11], - a[12], a[13], a[14], a[15]); - else - strpool = rk_strpoolprintf(strpool, - "unknown IP address of length %lu", - (unsigned long)name->u.iPAddress.length); - break; - } - case choice_GeneralName_registeredID: { - char *str; - hx509_oid_sprint(&name->u.registeredID, &str); - if (str == NULL) - return ENOMEM; - strpool = rk_strpoolprintf(strpool, "registeredID: %s", str); - free(str); - break; - } - default: - return EINVAL; - } - if (strpool == NULL) - return ENOMEM; - - *str = rk_strpoolcollect(strpool); - - return 0; -} |