diff --git a/lib/asn1/asn1-common.h b/lib/asn1/asn1-common.h index 8ab97761d..34bb73b10 100644 --- a/lib/asn1/asn1-common.h +++ b/lib/asn1/asn1-common.h @@ -20,8 +20,8 @@ typedef struct heim_octet_string { typedef char *heim_general_string; typedef char *heim_utf8_string; -typedef char *heim_printable_string; -typedef char *heim_ia5_string; +typedef struct heim_octet_string heim_printable_string; +typedef struct heim_octet_string heim_ia5_string; typedef struct heim_bmp_string { size_t length; diff --git a/lib/asn1/asn1_print.c b/lib/asn1/asn1_print.c index a95485bfe..279e969b0 100644 --- a/lib/asn1/asn1_print.c +++ b/lib/asn1/asn1_print.c @@ -181,11 +181,33 @@ loop (unsigned char *buf, size_t len, int indent) free (str.data); break; } + case UT_IA5String : + case UT_PrintableString : { + heim_printable_string str; + unsigned char *s; + size_t n; + + memset(&str, 0, sizeof(str)); + + ret = der_get_printable_string (buf, length, &str, NULL); + if (ret) + errx (1, "der_get_general_string: %s", + error_message (ret)); + s = str.data; + printf("\""); + for (n = 0; n < str.length; n++) { + if (isprint((int)s[n])) + printf ("%c", s[n]); + else + printf ("#%02x", s[n]); + } + printf("\"\n"); + der_free_printable_string(&str); + break; + } case UT_GeneralizedTime : case UT_GeneralString : - case UT_PrintableString : case UT_VisibleString : - case UT_IA5String : case UT_UTF8String : { heim_general_string str; diff --git a/lib/asn1/check-gen.c b/lib/asn1/check-gen.c index 067485926..cce8705ba 100644 --- a/lib/asn1/check-gen.c +++ b/lib/asn1/check-gen.c @@ -352,12 +352,14 @@ test_Name (void) atv1[0].type.length = sizeof(cmp_CN)/sizeof(cmp_CN[0]); atv1[0].type.components = cmp_CN; atv1[0].value.element = choice_DirectoryString_printableString; - atv1[0].value.u.printableString = "Love"; + atv1[0].value.u.printableString.data = "Love"; + atv1[0].value.u.printableString.length = 4; atv1[1].type.length = sizeof(cmp_L)/sizeof(cmp_L[0]); atv1[1].type.components = cmp_L; atv1[1].value.element = choice_DirectoryString_printableString; - atv1[1].value.u.printableString = "STOCKHOLM"; + atv1[1].value.u.printableString.data = "STOCKHOLM"; + atv1[1].value.u.printableString.length = 9; /* n2 */ n2.element = choice_Name_rdnSequence; @@ -369,12 +371,14 @@ test_Name (void) atv2[0].type.length = sizeof(cmp_L)/sizeof(cmp_L[0]); atv2[0].type.components = cmp_L; atv2[0].value.element = choice_DirectoryString_printableString; - atv2[0].value.u.printableString = "STOCKHOLM"; + atv2[0].value.u.printableString.data = "STOCKHOLM"; + atv2[0].value.u.printableString.length = 9; atv2[1].type.length = sizeof(cmp_CN)/sizeof(cmp_CN[0]); atv2[1].type.components = cmp_CN; atv2[1].value.element = choice_DirectoryString_printableString; - atv2[1].value.u.printableString = "Love"; + atv2[1].value.u.printableString.data = "Love"; + atv2[1].value.u.printableString.length = 4; /* */ tests[0].val = &n1; diff --git a/lib/asn1/der_cmp.c b/lib/asn1/der_cmp.c index 7329c5867..c9e560ebb 100644 --- a/lib/asn1/der_cmp.c +++ b/lib/asn1/der_cmp.c @@ -52,6 +52,20 @@ der_heim_octet_string_cmp(const heim_octet_string *p, return memcmp(p->data, q->data, p->length); } +int +der_printable_string_cmp(const heim_printable_string *p, + const heim_printable_string *q) +{ + return der_heim_octet_string_cmp(q, q); +} + +int +der_ia5_string_cmp(const heim_ia5_string *p, + const heim_ia5_string *q) +{ + return der_heim_octet_string_cmp(q, q); +} + int der_heim_bit_string_cmp(const heim_bit_string *p, const heim_bit_string *q) diff --git a/lib/asn1/der_copy.c b/lib/asn1/der_copy.c index a80c851f9..3a0a8c5ff 100644 --- a/lib/asn1/der_copy.c +++ b/lib/asn1/der_copy.c @@ -85,14 +85,20 @@ int der_copy_printable_string (const heim_printable_string *from, heim_printable_string *to) { - return der_copy_general_string(from, to); + to->length = from->length; + to->data = malloc(to->length + 1); + if(to->data == NULL) + return ENOMEM; + memcpy(to->data, from->data, to->length); + ((char *)to->data)[to->length] = '\0'; + return 0; } int -der_copy_ia5_string (const heim_printable_string *from, - heim_printable_string *to) +der_copy_ia5_string (const heim_ia5_string *from, + heim_ia5_string *to) { - return der_copy_general_string(from, to); + return der_copy_printable_string(from, to); } int diff --git a/lib/asn1/der_free.c b/lib/asn1/der_free.c index a16ddaed1..4bae5fc23 100644 --- a/lib/asn1/der_free.c +++ b/lib/asn1/der_free.c @@ -79,15 +79,13 @@ der_free_utf8string (heim_utf8_string *str) void der_free_printable_string (heim_printable_string *str) { - free(*str); - *str = NULL; + der_free_octet_string(str); } void der_free_ia5_string (heim_ia5_string *str) { - free(*str); - *str = NULL; + der_free_octet_string(str); } void diff --git a/lib/asn1/der_get.c b/lib/asn1/der_get.c index aee565040..3ea0d5ea1 100644 --- a/lib/asn1/der_get.c +++ b/lib/asn1/der_get.c @@ -167,17 +167,24 @@ der_get_utf8string (const unsigned char *p, size_t len, } int -der_get_printable_string (const unsigned char *p, size_t len, - heim_printable_string *str, size_t *size) +der_get_printable_string(const unsigned char *p, size_t len, + heim_printable_string *str, size_t *size) { - return der_get_general_string(p, len, str, size); + str->length = len; + str->data = malloc(len + 1); + if (str->data == NULL) + return ENOMEM; + memcpy(str->data, p, len); + ((char *)str->data)[len] = '\0'; + if(size) *size = len; + return 0; } int -der_get_ia5_string (const unsigned char *p, size_t len, - heim_ia5_string *str, size_t *size) +der_get_ia5_string(const unsigned char *p, size_t len, + heim_ia5_string *str, size_t *size) { - return der_get_general_string(p, len, str, size); + return der_get_printable_string(p, len, str, size); } int diff --git a/lib/asn1/der_length.c b/lib/asn1/der_length.c index 688e6ba81..7a41de9d2 100644 --- a/lib/asn1/der_length.c +++ b/lib/asn1/der_length.c @@ -161,13 +161,13 @@ der_length_utf8string (const heim_utf8_string *data) size_t der_length_printable_string (const heim_printable_string *data) { - return strlen(*data); + return data->length; } size_t der_length_ia5_string (const heim_ia5_string *data) { - return strlen(*data); + return data->length; } size_t diff --git a/lib/asn1/der_put.c b/lib/asn1/der_put.c index 10fc00233..c8192f25f 100644 --- a/lib/asn1/der_put.c +++ b/lib/asn1/der_put.c @@ -181,14 +181,14 @@ int der_put_printable_string (unsigned char *p, size_t len, const heim_printable_string *str, size_t *size) { - return der_put_general_string(p, len, str, size); + return der_put_octet_string(p, len, str, size); } int der_put_ia5_string (unsigned char *p, size_t len, const heim_ia5_string *str, size_t *size) { - return der_put_general_string(p, len, str, size); + return der_put_octet_string(p, len, str, size); } int diff --git a/lib/asn1/gen.c b/lib/asn1/gen.c index 610669698..9eec3f601 100644 --- a/lib/asn1/gen.c +++ b/lib/asn1/gen.c @@ -181,10 +181,10 @@ init_generate (const char *filename, const char *base) "typedef char *heim_utf8_string;\n\n" ); fprintf (headerfile, - "typedef char *heim_printable_string;\n\n" + "typedef struct heim_octet_string heim_printable_string;\n\n" ); fprintf (headerfile, - "typedef char *heim_ia5_string;\n\n" + "typedef struct heim_octet_string heim_ia5_string;\n\n" ); fprintf (headerfile, "typedef struct heim_bmp_string {\n" diff --git a/lib/hx509/ca.c b/lib/hx509/ca.c index 8ec6eae22..ebb056bd4 100644 --- a/lib/hx509/ca.c +++ b/lib/hx509/ca.c @@ -485,7 +485,8 @@ hx509_ca_tbs_add_crl_dp_uri(hx509_context context, name.u.fullName.val = &gn; gn.element = choice_GeneralName_uniformResourceIdentifier; - gn.u.uniformResourceIdentifier = rk_UNCONST(uri); + gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri); + gn.u.uniformResourceIdentifier.length = strlen(uri); ASN1_MALLOC_ENCODE(DistributionPointName, dp.distributionPoint->data, @@ -785,7 +786,8 @@ hx509_ca_tbs_add_san_hostname(hx509_context context, memset(&gn, 0, sizeof(gn)); gn.element = choice_GeneralName_dNSName; - gn.u.dNSName = rk_UNCONST(dnsname); + gn.u.dNSName.data = rk_UNCONST(dnsname); + gn.u.dNSName.length = strlen(dnsname); return add_GeneralNames(&tbs->san, &gn); } @@ -812,7 +814,8 @@ hx509_ca_tbs_add_san_rfc822name(hx509_context context, memset(&gn, 0, sizeof(gn)); gn.element = choice_GeneralName_rfc822Name; - gn.u.rfc822Name = rk_UNCONST(rfc822Name); + gn.u.rfc822Name.data = rk_UNCONST(rfc822Name); + gn.u.rfc822Name.length = strlen(rfc822Name); return add_GeneralNames(&tbs->san, &gn); } diff --git a/lib/hx509/cert.c b/lib/hx509/cert.c index 4783edd68..25c62cf7c 100644 --- a/lib/hx509/cert.c +++ b/lib/hx509/cert.c @@ -1696,19 +1696,20 @@ match_general_name(const GeneralName *c, const GeneralName *n, int *match) case choice_GeneralName_rfc822Name: { const char *s; size_t len1, len2; - s = strchr(c->u.rfc822Name, '@'); + s = memchr(c->u.rfc822Name.data, '@', c->u.rfc822Name.length); if (s) { - if (strcasecmp(c->u.rfc822Name, n->u.rfc822Name) != 0) + if (der_printable_string_cmp(&c->u.rfc822Name, &n->u.rfc822Name) != 0) return HX509_NAME_CONSTRAINT_ERROR; } else { - s = strchr(n->u.rfc822Name, '@'); + s = memchr(n->u.rfc822Name.data, '@', n->u.rfc822Name.length); if (s == NULL) return HX509_NAME_CONSTRAINT_ERROR; - len1 = strlen(c->u.rfc822Name); - len2 = strlen(s + 1); + len1 = c->u.rfc822Name.length; + len2 = n->u.rfc822Name.length - + (s - ((char *)n->u.rfc822Name.data)); if (len1 > len2) return HX509_NAME_CONSTRAINT_ERROR; - if (strcasecmp(s + 1 + len2 - len1, c->u.rfc822Name) != 0) + if (memcmp(s + 1 + len2 - len1, c->u.rfc822Name.data, len1) != 0) return HX509_NAME_CONSTRAINT_ERROR; if (len1 < len2 && s[len2 - len1 + 1] != '.') return HX509_NAME_CONSTRAINT_ERROR; @@ -1718,14 +1719,16 @@ match_general_name(const GeneralName *c, const GeneralName *n, int *match) } case choice_GeneralName_dNSName: { size_t lenc, lenn; + char *ptr; - lenc = strlen(c->u.dNSName); - lenn = strlen(n->u.dNSName); + lenc = c->u.dNSName.length; + lenn = n->u.dNSName.length; if (lenc > lenn) return HX509_NAME_CONSTRAINT_ERROR; - if (strcasecmp(&n->u.dNSName[lenn - lenc], c->u.dNSName) != 0) + ptr = n->u.dNSName.data; + if (memcmp(&ptr[lenn - lenc], c->u.dNSName.data, c->u.dNSName.length) != 0) return HX509_NAME_CONSTRAINT_ERROR; - if (lenc != lenn && n->u.dNSName[lenn - lenc - 1] != '.') + if (lenc != lenn && ptr[lenn - lenc - 1] != '.') return HX509_NAME_CONSTRAINT_ERROR; *match = 1; return 0; @@ -2405,12 +2408,17 @@ hx509_verify_hostname(hx509_context context, for (j = 0; j < san.len; j++) { switch (san.val[j].element) { - case choice_GeneralName_dNSName: - if (strcasecmp(san.val[j].u.dNSName, hostname) == 0) { + case choice_GeneralName_dNSName: { + heim_printable_string hn; + hn.data = rk_UNCONST(hostname); + hn.length = strlen(hostname); + + if (der_printable_string_cmp(&san.val[j].u.dNSName, &hn) == 0) { free_GeneralNames(&san); return 0; } break; + } default: break; } @@ -2428,14 +2436,24 @@ hx509_verify_hostname(hx509_context context, if (der_heim_oid_cmp(&n->type, &asn1_oid_id_at_commonName) == 0) { DirectoryString *ds = &n->value; switch (ds->element) { - case choice_DirectoryString_printableString: - if (strcasecmp(ds->u.printableString, hostname) == 0) + case choice_DirectoryString_printableString: { + heim_printable_string hn; + hn.data = rk_UNCONST(hostname); + hn.length = strlen(hostname); + + if (der_printable_string_cmp(&ds->u.printableString, &hn) == 0) return 0; break; - case choice_DirectoryString_ia5String: - if (strcasecmp(ds->u.ia5String, hostname) == 0) - return 0; + } + case choice_DirectoryString_ia5String: { + heim_ia5_string hn; + hn.data = rk_UNCONST(hostname); + hn.length = strlen(hostname); + + if (der_ia5_string_cmp(&ds->u.ia5String, &hn) == 0) + return 0; break; + } case choice_DirectoryString_utf8String: if (strcasecmp(ds->u.utf8String, hostname) == 0) return 0; diff --git a/lib/hx509/char_map.h b/lib/hx509/char_map.h new file mode 100644 index 000000000..d2b39d041 --- /dev/null +++ b/lib/hx509/char_map.h @@ -0,0 +1,45 @@ +#define Q_CONTROL_CHAR 1 +#define Q_PRINTABLE 2 +#define Q_RFC2253_QUOTE_FIRST 4 +#define Q_RFC2253_QUOTE_LAST 8 +#define Q_RFC2253_QUOTE 16 +#define Q_RFC2253_HEX 32 + +#define Q_RFC2253 (Q_RFC2253_QUOTE_FIRST|Q_RFC2253_QUOTE_LAST|Q_RFC2253_QUOTE|Q_RFC2253_HEX) + + + +unsigned char char_map[] = { + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x06 , 0x00 , 0x00 , 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , + 0x00 , 0x00 , 0x00 , 0x12 , 0x12 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x10 , 0x10 , 0x12 , 0x10 , 0x02 , + 0x00 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , + 0x00 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , 0x02 , + 0x02 , 0x02 , 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , + 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 , 0x21 +}; diff --git a/lib/hx509/data/win-u16-in-printablestring.der b/lib/hx509/data/win-u16-in-printablestring.der new file mode 100644 index 000000000..5f6178f9a Binary files /dev/null and b/lib/hx509/data/win-u16-in-printablestring.der differ diff --git a/lib/hx509/name.c b/lib/hx509/name.c index c7a7ddd3d..94fecc990 100644 --- a/lib/hx509/name.c +++ b/lib/hx509/name.c @@ -33,6 +33,7 @@ #include "hx_locl.h" #include +#include "char_map.h" /** * @page page_name PKIX/X.509 Names @@ -79,11 +80,11 @@ static const struct { }; static char * -quote_string(const char *f, size_t len, size_t *rlen) +quote_string(const char *f, size_t len, int flags, size_t *rlen) { size_t i, j, tolen; - const char *from = f; - char *to; + const unsigned char *from = (const unsigned char *)f; + unsigned char *to; tolen = len * 3 + 1; to = malloc(tolen); @@ -91,26 +92,29 @@ quote_string(const char *f, size_t len, size_t *rlen) 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] == ' ') - { + unsigned char map = char_map[from[i]] & flags; + if (i == 0 && (map & Q_RFC2253_QUOTE_FIRST)) { to[j++] = '\\'; to[j++] = from[i]; - } else if (((unsigned char)from[i]) >= 32 && ((unsigned char)from[i]) <= 127) { + } else if ((i + 1) == len && (map & Q_RFC2253_QUOTE_LAST)) { + + to[j++] = '\\'; to[j++] = from[i]; - } else { - int l = snprintf(&to[j], tolen - j - 1, + } else if (map & Q_RFC2253_QUOTE) { + to[j++] = '\\'; + to[j++] = from[i]; + } else if (map & Q_RFC2253_HEX) { + int l = snprintf((char *)&to[j], tolen - j - 1, "#%02x", (unsigned char)from[i]); j += l; + } else { + to[j++] = from[i]; } } to[j] = '\0'; assert(j < tolen); *rlen = j; - return to; + return (char *)to; } @@ -121,7 +125,7 @@ append_string(char **str, size_t *total_len, const char *ss, char *s, *qs; if (quote) - qs = quote_string(ss, len, &len); + qs = quote_string(ss, len, Q_RFC2253, &len); else qs = rk_UNCONST(ss); @@ -203,7 +207,7 @@ _hx509_Name_to_string(const Name *n, char **str) return ENOMEM; for (i = n->u.rdnSequence.len - 1 ; i >= 0 ; i--) { - int len; + size_t len; for (j = 0; j < n->u.rdnSequence.val[i].len; j++) { DirectoryString *ds = &n->u.rdnSequence.val[i].val[j].value; @@ -214,13 +218,16 @@ _hx509_Name_to_string(const Name *n, char **str) switch(ds->element) { case choice_DirectoryString_ia5String: - ss = ds->u.ia5String; + ss = ds->u.ia5String.data; + len = ds->u.ia5String.length; break; case choice_DirectoryString_printableString: - ss = ds->u.printableString; + ss = ds->u.printableString.data; + len = ds->u.printableString.length; break; case choice_DirectoryString_utf8String: ss = ds->u.utf8String; + len = strlen(ss); break; case choice_DirectoryString_bmpString: { const uint16_t *bmp = ds->u.bmpString.data; @@ -240,10 +247,12 @@ _hx509_Name_to_string(const Name *n, char **str) return ret; } ss[k] = '\0'; + len = k; break; } case choice_DirectoryString_teletexString: ss = ds->u.teletexString; + len = strlen(ss); break; case choice_DirectoryString_universalString: { const uint32_t *uni = ds->u.universalString.data; @@ -263,6 +272,7 @@ _hx509_Name_to_string(const Name *n, char **str) return ret; } ss[k] = '\0'; + len = k; break; } default: @@ -272,10 +282,9 @@ _hx509_Name_to_string(const Name *n, char **str) 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) + if (ds->element == choice_DirectoryString_bmpString || + ds->element == choice_DirectoryString_universalString) { free(ss); } @@ -330,12 +339,12 @@ dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen) switch(ds->element) { case choice_DirectoryString_ia5String: flags = WIND_PROFILE_LDAP; - COPYCHARARRAY(ds, ia5String, len, name); + COPYVOIDARRAY(ds, ia5String, len, name); break; case choice_DirectoryString_printableString: flags = WIND_PROFILE_LDAP; flags |= WIND_PROFILE_LDAP_CASE_EXACT_ATTRIBUTE; - COPYCHARARRAY(ds, printableString, len, name); + COPYVOIDARRAY(ds, printableString, len, name); break; case choice_DirectoryString_teletexString: flags = WIND_PROFILE_LDAP_CASE; @@ -939,12 +948,14 @@ hx509_general_name_unparse(GeneralName *name, char **str) break; } case choice_GeneralName_rfc822Name: - strpool = rk_strpoolprintf(strpool, "rfc822Name: %s\n", - name->u.rfc822Name); + strpool = rk_strpoolprintf(strpool, "rfc822Name: %.*s\n", + (int)name->u.rfc822Name.length, + (char *)name->u.rfc822Name.data); break; case choice_GeneralName_dNSName: - strpool = rk_strpoolprintf(strpool, "dNSName: %s\n", - name->u.dNSName); + strpool = rk_strpoolprintf(strpool, "dNSName: %.*s\n", + (int)name->u.dNSName.length, + (char *)name->u.dNSName.data); break; case choice_GeneralName_directoryName: { Name dir; @@ -961,8 +972,9 @@ hx509_general_name_unparse(GeneralName *name, char **str) break; } case choice_GeneralName_uniformResourceIdentifier: - strpool = rk_strpoolprintf(strpool, "URI: %s", - name->u.uniformResourceIdentifier); + strpool = rk_strpoolprintf(strpool, "URI: %.*s", + (int)name->u.uniformResourceIdentifier.length, + (char *)name->u.uniformResourceIdentifier.data); break; case choice_GeneralName_iPAddress: { unsigned char *a = name->u.iPAddress.data; diff --git a/lib/hx509/quote.py b/lib/hx509/quote.py new file mode 100644 index 000000000..41887e5d4 --- /dev/null +++ b/lib/hx509/quote.py @@ -0,0 +1,101 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# Copyright (c) 2010 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. +# + +CONTROL_CHAR = 1 +PRINTABLE = 2 +RFC2253_QUOTE_FIRST = 4 +RFC2253_QUOTE_LAST = 8 +RFC2253_QUOTE = 16 +RFC2253_HEX = 32 + +chars = [] + +for i in range(0, 256): + chars.append(0); + +for i in range(0, 256): + if (i < 32 or i > 126): + chars[i] |= CONTROL_CHAR | RFC2253_HEX; + +for i in range(ord("A"), ord("Z") + 1): + chars[i] |= PRINTABLE +for i in range(ord("a"), ord("z") + 1): + chars[i] |= PRINTABLE +for i in range(ord("0"), ord("9") + 1): + chars[i] |= PRINTABLE + +chars[ord(' ')] |= PRINTABLE +chars[ord('+')] |= PRINTABLE +chars[ord(',')] |= PRINTABLE +chars[ord('-')] |= PRINTABLE +chars[ord('.')] |= PRINTABLE +chars[ord('/')] |= PRINTABLE +chars[ord(':')] |= PRINTABLE +chars[ord('=')] |= PRINTABLE +chars[ord('?')] |= PRINTABLE + +chars[ord(' ')] |= RFC2253_QUOTE_FIRST | RFC2253_QUOTE_FIRST + +chars[ord(',')] |= RFC2253_QUOTE +chars[ord('=')] |= RFC2253_QUOTE +chars[ord('+')] |= RFC2253_QUOTE +chars[ord('<')] |= RFC2253_QUOTE +chars[ord('>')] |= RFC2253_QUOTE +chars[ord('#')] |= RFC2253_QUOTE +chars[ord(';')] |= RFC2253_QUOTE + +print "#define Q_CONTROL_CHAR 1" +print "#define Q_PRINTABLE 2" +print "#define Q_RFC2253_QUOTE_FIRST 4" +print "#define Q_RFC2253_QUOTE_LAST 8" +print "#define Q_RFC2253_QUOTE 16" +print "#define Q_RFC2253_HEX 32" +print "" +print "#define Q_RFC2253 (Q_RFC2253_QUOTE_FIRST|Q_RFC2253_QUOTE_LAST|Q_RFC2253_QUOTE|Q_RFC2253_HEX)" +print "\n" * 2 + + + + +print "unsigned char char_map[] = {\n\t", +for x in range(0, 256): + if (x % 8) == 0 and x != 0: + print "\n\t", + print "0x%(char)02x" % { 'char' : chars[x] }, + if x < 255: + print ", ", + else: + print "" +print "};" diff --git a/lib/hx509/req.c b/lib/hx509/req.c index 0d174e0ce..917f08891 100644 --- a/lib/hx509/req.c +++ b/lib/hx509/req.c @@ -143,7 +143,8 @@ _hx509_request_add_dns_name(hx509_context context, memset(&name, 0, sizeof(name)); name.element = choice_GeneralName_dNSName; - name.u.dNSName = rk_UNCONST(hostname); + name.u.dNSName.data = rk_UNCONST(hostname); + name.u.dNSName.length = strlen(hostname); return add_GeneralNames(&req->san, &name); } @@ -157,7 +158,8 @@ _hx509_request_add_email(hx509_context context, memset(&name, 0, sizeof(name)); name.element = choice_GeneralName_rfc822Name; - name.u.dNSName = rk_UNCONST(email); + name.u.dNSName.data = rk_UNCONST(email); + name.u.dNSName.length = strlen(email); return add_GeneralNames(&req->san, &name); } diff --git a/lib/hx509/test_cert.in b/lib/hx509/test_cert.in index 9ce67d640..6cbf21bf0 100644 --- a/lib/hx509/test_cert.in +++ b/lib/hx509/test_cert.in @@ -76,4 +76,9 @@ ${hxtool} verify --missing-revoke \ cert:FILE:$srcdir/data/n0ll.pem \ anchor:FILE:$srcdir/data/n0ll.pem && exit 1 +echo "check that windows cert with utf16 in printable string works" +${hxtool} verify --missing-revoke \ + cert:FILE:$srcdir/data/win-u16-in-printablestring.der \ + anchor:FILE:$srcdir/data/win-u16-in-printablestring.der || exit 1 + exit 0