diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2014-04-19 01:09:21 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2014-04-19 01:10:49 +0200 |
commit | 34384369873dc8267419b4d9c2f99f6e7e703efc (patch) | |
tree | 88251bee93893e9f9bf53fde55024aeb65a2db0b /lib | |
parent | db327838d7861ac485caf8b71f6f591e9cbbc184 (diff) | |
download | gnutls-34384369873dc8267419b4d9c2f99f6e7e703efc.tar.gz |
Corrected decoding of XMPP SAN othername.
This also corrects the semantics of the get_*_othername_oid() functions,
such as gnutls_x509_crt_get_subject_alt_othername_oid().
Diffstat (limited to 'lib')
-rw-r--r-- | lib/x509/common.c | 14 | ||||
-rw-r--r-- | lib/x509/common.h | 4 | ||||
-rw-r--r-- | lib/x509/output.c | 5 | ||||
-rw-r--r-- | lib/x509/x509.c | 40 |
4 files changed, 44 insertions, 19 deletions
diff --git a/lib/x509/common.c b/lib/x509/common.c index 77a90a7336..3376fe3cc9 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -131,6 +131,17 @@ static const struct oid_to_string _oid2str[] = { {NULL, 0, NULL, 0, NULL, 0} }; +int _san_othername_to_virtual(const char *oid, size_t size) +{ + if (oid) { + if ((unsigned) size == (sizeof(XMPP_OID)-1) + && memcmp(oid, XMPP_OID, sizeof(XMPP_OID)-1) == 0) + return GNUTLS_SAN_OTHERNAME_XMPP; + } + + return GNUTLS_SAN_OTHERNAME; +} + static const struct oid_to_string *get_oid_entry(const char *oid) { unsigned int i = 0; @@ -1048,8 +1059,9 @@ _gnutls_x509_read_value(ASN1_TYPE c, const char *root, if (etype == ASN1_ETYPE_BIT_STRING) { ret->size = (len+7) / 8; - } else + } else { ret->size = (unsigned) len; + } tmp[ret->size] = 0; ret->data = tmp; diff --git a/lib/x509/common.h b/lib/x509/common.h index 76c5e80704..022010df0c 100644 --- a/lib/x509/common.h +++ b/lib/x509/common.h @@ -69,6 +69,8 @@ #define SIG_GOST_R3410_2001_OID "1.2.643.2.2.3" #define ISO_SIG_RSA_SHA1_OID "1.3.14.3.2.29" +#define XMPP_OID "1.3.6.1.5.5.7.8.5" + #define ASN1_NULL "\x05\x00" #define ASN1_NULL_SIZE 2 @@ -198,4 +200,6 @@ bool _gnutls_is_same_dn(gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2); int _gnutls_copy_string(gnutls_datum_t* str, uint8_t *out, size_t *out_size); int _gnutls_copy_data(gnutls_datum_t* str, uint8_t *out, size_t *out_size); +int _san_othername_to_virtual(const char *oid, size_t oid_size); + #endif diff --git a/lib/x509/output.c b/lib/x509/output.c index 3ba6c04850..33a1b28729 100644 --- a/lib/x509/output.c +++ b/lib/x509/output.c @@ -802,7 +802,6 @@ print_altname(gnutls_buffer_st * str, const char *prefix, return; } - if (err == GNUTLS_SAN_OTHERNAME) { char *oid = NULL; size_t oidsize; @@ -824,8 +823,8 @@ print_altname(gnutls_buffer_st * str, const char *prefix, if (err != GNUTLS_E_SHORT_MEMORY_BUFFER) { gnutls_free(buffer); addf(str, - "error: get_subject/issuer_alt_othername_oid: %s\n", - gnutls_strerror(err)); + "error: get_subject/issuer_alt_othername_oid: %s (%d)\n", + gnutls_strerror(err), err); return; } diff --git a/lib/x509/x509.c b/lib/x509/x509.c index 2b1933a1fe..d13c231a99 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -847,7 +847,7 @@ gnutls_x509_crt_get_subject_key_id(gnutls_x509_crt_t cert, void *ret, inline static int is_type_printable(int type) { if (type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_RFC822NAME || - type == GNUTLS_SAN_URI) + type == GNUTLS_SAN_URI || type == GNUTLS_SAN_OTHERNAME_XMPP) return 1; else return 0; @@ -1081,8 +1081,6 @@ gnutls_x509_crt_get_pk_algorithm(gnutls_x509_crt_t cert, } -#define XMPP_OID "1.3.6.1.5.5.7.8.5" - /* returns the type and the name on success. * Type is also returned as a parameter in case of an error. * @@ -1090,7 +1088,7 @@ gnutls_x509_crt_get_pk_algorithm(gnutls_x509_crt_t cert, * in case of GeneralName, it must be -1 * @dname: the name returned * @ret_type: The type of the name - * @othername_oid: if the name is AnotherName return the OID + * @othername_oid: if the name is otherName return the OID * */ int @@ -1153,11 +1151,10 @@ _gnutls_parse_general_name2(ASN1_TYPE src, const char *src_name, } if (othername_oid) { - if ((unsigned) tmp.size == (sizeof(XMPP_OID)-1) - && memcmp(tmp.data, XMPP_OID, sizeof(XMPP_OID)-1) == 0) - type = GNUTLS_SAN_OTHERNAME_XMPP; + dname->size = tmp.size; + dname->data = tmp.data; } else { - char oid[42]; + char oid[MAX_OID_SIZE]; if (src_name[0] != 0) snprintf(nptr, sizeof(nptr), @@ -1168,15 +1165,16 @@ _gnutls_parse_general_name2(ASN1_TYPE src, const char *src_name, "?%u.otherName.type-id", seq); len = sizeof(oid); + result = asn1_read_value(src, nptr, oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } + if (len > 0) len--; - if ((unsigned) len == (sizeof(XMPP_OID)-1) - && memcmp(oid, XMPP_OID, sizeof(XMPP_OID)-1) == 0) { + if (_san_othername_to_virtual(oid, len) == GNUTLS_SAN_OTHERNAME_XMPP) { gnutls_datum_t out; ret = @@ -1194,12 +1192,15 @@ _gnutls_parse_general_name2(ASN1_TYPE src, const char *src_name, /* out is already null terminated */ ret = type; goto cleanup; + } else { + dname->size = tmp.size; + dname->data = tmp.data; } } } else if (type == GNUTLS_SAN_DN) { _gnutls_str_cat(nptr, sizeof(nptr), ".directoryName"); ret = _gnutls_x509_get_dn(src, nptr, dname); - if (result < 0) { + if (ret < 0) { gnutls_assert(); goto cleanup; } @@ -1272,6 +1273,7 @@ get_alt_name(gnutls_x509_crt_t cert, const char *extension_id, { int ret; gnutls_datum_t dnsname = {NULL, 0}; + gnutls_datum_t ooid = {NULL, 0}; gnutls_datum_t res; gnutls_subject_alt_names_t sans = NULL; unsigned int type; @@ -1307,19 +1309,27 @@ get_alt_name(gnutls_x509_crt_t cert, const char *extension_id, goto cleanup; } - ret = gnutls_subject_alt_names_get(sans, seq, &type, &res, NULL); + ret = gnutls_subject_alt_names_get(sans, seq, &type, &res, &ooid); if (ret < 0) { gnutls_assert(); goto cleanup; } + if (othername_oid && type == GNUTLS_SAN_OTHERNAME) { + type = _san_othername_to_virtual((char*)ooid.data, ooid.size); + } + if (alt_type) *alt_type = type; - if (is_type_printable(type)) { - ret = _gnutls_copy_string(&res, alt, alt_size); + if (othername_oid) { + ret = _gnutls_copy_string(&ooid, alt, alt_size); } else { - ret = _gnutls_copy_data(&res, alt, alt_size); + if (is_type_printable(type)) { + ret = _gnutls_copy_string(&res, alt, alt_size); + } else { + ret = _gnutls_copy_data(&res, alt, alt_size); + } } if (ret < 0) { |