diff options
author | Pierre Ossman <ossman@cendio.se> | 2020-03-24 15:32:13 +0100 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2020-04-03 15:36:55 +0200 |
commit | 279b5f865c60ccaa97f4dd24575a37d261d97505 (patch) | |
tree | 201cfb9ba7deac68a27d9a0d9c4c7ffc5d874b59 /lib | |
parent | bbf7ed8b122b30c9951b11cb2e8c966769754147 (diff) | |
download | gnutls-279b5f865c60ccaa97f4dd24575a37d261d97505.tar.gz |
Compare DNs by comparing their string representations
A binary comparison will not work in case the contents is the same but
the ASN.1 type differ (e.g. PrintableString vs UTF8String). Such
variations are permitted so we need to handle them.
Signed-off-by: Pierre Ossman <ossman@cendio.se>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pkcs11.c | 3 | ||||
-rw-r--r-- | lib/x509/dn.c | 49 |
2 files changed, 49 insertions, 3 deletions
diff --git a/lib/pkcs11.c b/lib/pkcs11.c index 8b65212a50..d03bf6e444 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -4141,6 +4141,8 @@ find_cert_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo, a_vals++; } + /* This doesn't do a proper comparison, see + * _gnutls_x509_compare_raw_dn() */ if (priv->dn.size > 0) { a[a_vals].type = CKA_SUBJECT; a[a_vals].value = priv->dn.data; @@ -4155,6 +4157,7 @@ find_cert_cb(struct ck_function_list *module, struct pkcs11_session_info *sinfo, a_vals++; } + /* Same problem as for priv->dn */ if (priv->issuer_dn.size > 0) { a[a_vals].type = CKA_ISSUER; a[a_vals].value = priv->issuer_dn.data; diff --git a/lib/x509/dn.c b/lib/x509/dn.c index 8d428e9b3f..33739e2271 100644 --- a/lib/x509/dn.c +++ b/lib/x509/dn.c @@ -982,13 +982,56 @@ int _gnutls_x509_compare_raw_dn(const gnutls_datum_t * dn1, const gnutls_datum_t * dn2) { + int ret; + gnutls_datum_t str1, str2; + + /* Simple case of completely identical? */ + + if (dn1->size == dn2->size) { + if (memcmp(dn1->data, dn2->data, dn2->size) == 0) { + return 1; + } + } + + /* RFC5280 (https://tools.ietf.org/html/rfc5280#section-7.1) + * requires that the LDAP StringPrep profile and caseIgnoreMatch + * must be used for this comparison. We do not use that but + * instead we do a simpler comparison that ignores the tags used + * such as `UTF8String` and `PrintableString`. */ - if (dn1->size != dn2->size) { + if ((dn1->size == 0) || (dn2->size == 0)) { + gnutls_assert(); + return 0; + } + + ret = gnutls_x509_rdn_get2(dn1, &str1, 0); + if (ret < 0) { + gnutls_assert(); return 0; } - if (memcmp(dn1->data, dn2->data, dn2->size) != 0) { + + ret = gnutls_x509_rdn_get2(dn2, &str2, 0); + if (ret < 0) { gnutls_assert(); + _gnutls_free_datum(&str1); return 0; } - return 1; /* they match */ + + if (str1.size != str2.size) { + ret = 0; + goto cleanup; + } + if (memcmp(str1.data, str2.data, str2.size) != 0) { + gnutls_assert(); + ret = 0; + goto cleanup; + } + + ret = 1; /* they match */ + +cleanup: + _gnutls_free_datum(&str1); + _gnutls_free_datum(&str2); + + return ret; } |