summaryrefslogtreecommitdiff
path: root/source4/heimdal/lib/hx509/name.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/heimdal/lib/hx509/name.c')
-rw-r--r--source4/heimdal/lib/hx509/name.c240
1 files changed, 228 insertions, 12 deletions
diff --git a/source4/heimdal/lib/hx509/name.c b/source4/heimdal/lib/hx509/name.c
index 92e9e6f974..5198633b1e 100644
--- a/source4/heimdal/lib/hx509/name.c
+++ b/source4/heimdal/lib/hx509/name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 - 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -32,7 +32,7 @@
*/
#include "hx_locl.h"
-RCSID("$Id: name.c,v 1.33 2006/12/30 23:04:11 lha Exp $");
+RCSID("$Id: name.c 20891 2007-06-04 22:51:41Z lha $");
/*
* name parsing from rfc2253
@@ -41,7 +41,7 @@ RCSID("$Id: name.c,v 1.33 2006/12/30 23:04:11 lha Exp $");
*/
static const struct {
- char *n;
+ const char *n;
const heim_oid *(*o)(void);
} no[] = {
{ "C", oid_id_at_countryName },
@@ -51,6 +51,7 @@ static const struct {
{ "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 }
@@ -81,25 +82,27 @@ quote_string(const char *f, size_t len, size_t *rlen)
to[j++] = from[i];
} else {
int l = snprintf(&to[j], tolen - j - 1,
- "#%02x", (unsigned int)from[i]);
+ "#%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, char *ss, size_t len, int quote)
+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 = ss;
+ qs = rk_UNCONST(ss);
s = realloc(*str, len + *total_len + 1);
if (s == NULL)
@@ -181,10 +184,10 @@ _hx509_Name_to_string(const Name *n, char **str)
ss = ds->u.ia5String;
break;
case choice_DirectoryString_printableString:
- ss = ds->u.ia5String;
+ ss = ds->u.printableString;
break;
case choice_DirectoryString_utf8String:
- ss = ds->u.ia5String;
+ ss = ds->u.utf8String;
break;
case choice_DirectoryString_bmpString: {
uint16_t *bmp = ds->u.bmpString.data;
@@ -200,11 +203,25 @@ _hx509_Name_to_string(const Name *n, char **str)
break;
}
case choice_DirectoryString_teletexString:
- ss = "teletex-string"; /* XXX */
+ 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:
- ss = "universalString"; /* XXX */
+ 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);
@@ -214,8 +231,12 @@ _hx509_Name_to_string(const Name *n, char **str)
append_string(str, &total_len, "=", 1, 0);
len = strlen(ss);
append_string(str, &total_len, ss, len, 1);
- if (ds->element == choice_DirectoryString_bmpString)
+ 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);
}
@@ -299,6 +320,13 @@ _hx509_name_cmp(const Name *n1, const Name *n2)
}
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;
@@ -487,6 +515,106 @@ 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;
+}
+
+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++) {
+ /*
+ 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;
+}
+
void
hx509_name_free(hx509_name *name)
@@ -548,3 +676,91 @@ hx509_name_is_null_p(const hx509_name name)
{
return name->der_name.u.rdnSequence.len == 0;
}
+
+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;
+}