diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2014-10-01 20:27:51 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2014-10-01 20:41:41 +0200 |
commit | 0aa92d8a73f7f59f46f9feb42a754e651235b386 (patch) | |
tree | ee8e1befbcec1d6b34ff0f5bc032d6432ef4c385 | |
parent | 690ce2d1daffc43ab24bdec7a8aa3c750fd565b1 (diff) | |
download | gnutls-0aa92d8a73f7f59f46f9feb42a754e651235b386.tar.gz |
Added GNUTLS_TL_GET_COPY flag and documented the limitations of gnutls_x509_trust_list_get_issuer()
-rw-r--r-- | lib/gnutls_cert.c | 5 | ||||
-rw-r--r-- | lib/gnutls_x509.c | 13 | ||||
-rw-r--r-- | lib/includes/gnutls/x509.h | 1 | ||||
-rw-r--r-- | lib/x509/ocsp.c | 6 | ||||
-rw-r--r-- | lib/x509/verify-high.c | 33 |
5 files changed, 47 insertions, 11 deletions
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index 3e5432167f..0b9672736f 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -99,9 +99,12 @@ void gnutls_certificate_free_cas(gnutls_certificate_credentials_t sc) * @sc: is a #gnutls_certificate_credentials_t structure. * @cert: is the certificate to find issuer for * @issuer: Will hold the issuer if any. Should be treated as constant. - * @flags: Use zero. + * @flags: Use zero or %GNUTLS_TL_GET_COPY * * This function will return the issuer of a given certificate. + * As with gnutls_x509_trust_list_get_issuer() this function requires + * the %GNUTLS_TL_GET_COPY flag in order to operate with PKCS #11 trust + * lists. In that case the issuer must be freed using gnutls_x509_crt_deinit(). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index a4921f9311..0d6ebb72d5 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -191,9 +191,10 @@ _gnutls_x509_cert_verify_peers(gnutls_session_t session, gnutls_x509_crt_t *peer_certificate_list; gnutls_datum_t resp; int peer_certificate_list_size, i, x, ret; - gnutls_x509_crt_t issuer; + gnutls_x509_crt_t issuer = NULL; unsigned int ocsp_status = 0; unsigned int verify_flags; + unsigned issuer_deinit = 0; /* No OCSP check so far */ session->internals.ocsp_check_ok = 0; @@ -264,21 +265,25 @@ _gnutls_x509_cert_verify_peers(gnutls_session_t session, if (ret < 0) goto skip_ocsp; - if (peer_certificate_list_size > 1) + if (peer_certificate_list_size > 1) { issuer = peer_certificate_list[1]; - else { + } else { ret = gnutls_x509_trust_list_get_issuer(cred->tlist, peer_certificate_list - [0], &issuer, 0); + [0], &issuer, GNUTLS_TL_GET_COPY); if (ret < 0) { goto skip_ocsp; } + issuer_deinit = 1; } ret = check_ocsp_response(session, peer_certificate_list[0], issuer, &resp, &ocsp_status); + if (issuer_deinit != 0) + gnutls_x509_crt_deinit(issuer); + if (ret < 0) { CLEAR_CERTS; return gnutls_assert_val(ret); diff --git a/lib/includes/gnutls/x509.h b/lib/includes/gnutls/x509.h index 0f08cff67e..740a274ca5 100644 --- a/lib/includes/gnutls/x509.h +++ b/lib/includes/gnutls/x509.h @@ -1233,6 +1233,7 @@ int gnutls_x509_trust_list_get_issuer(gnutls_x509_trust_list_t #define GNUTLS_TL_USE_IN_TLS (1<<1) #define GNUTLS_TL_NO_DUPLICATES (1<<2) #define GNUTLS_TL_NO_DUPLICATE_KEY (1<<3) +#define GNUTLS_TL_GET_COPY (1<<4) int gnutls_x509_trust_list_add_cas(gnutls_x509_trust_list_t list, const gnutls_x509_crt_t * clist, diff --git a/lib/x509/ocsp.c b/lib/x509/ocsp.c index f82fb684a3..5c3cae82f2 100644 --- a/lib/x509/ocsp.c +++ b/lib/x509/ocsp.c @@ -2082,6 +2082,7 @@ gnutls_ocsp_resp_verify(gnutls_ocsp_resp_t resp, unsigned int *verify, unsigned int flags) { gnutls_x509_crt_t signercert = NULL; + gnutls_x509_crt_t issuer = NULL; int rc; /* Algorithm: @@ -2109,14 +2110,13 @@ gnutls_ocsp_resp_verify(gnutls_ocsp_resp_t resp, rc = _gnutls_trustlist_inlist(trustlist, signercert); if (rc == 0) { /* not in trustlist, need to verify signature and bits */ - gnutls_x509_crt_t issuer; unsigned vtmp; gnutls_assert(); rc = gnutls_x509_trust_list_get_issuer(trustlist, signercert, &issuer, - 0); + GNUTLS_TL_GET_COPY); if (rc != GNUTLS_E_SUCCESS) { gnutls_assert(); *verify = GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER; @@ -2151,6 +2151,8 @@ gnutls_ocsp_resp_verify(gnutls_ocsp_resp_t resp, done: gnutls_x509_crt_deinit(signercert); + if (issuer != NULL) + gnutls_x509_crt_deinit(issuer); return rc; } diff --git a/lib/x509/verify-high.c b/lib/x509/verify-high.c index 2c067e6c0a..0edfaa45dd 100644 --- a/lib/x509/verify-high.c +++ b/lib/x509/verify-high.c @@ -669,10 +669,13 @@ int trust_list_get_issuer(gnutls_x509_trust_list_t list, * @list: The structure of the list * @cert: is the certificate to find issuer for * @issuer: Will hold the issuer if any. Should be treated as constant. - * @flags: Use zero. + * @flags: Use zero or %GNUTLS_TL_GET_COPY * - * This function will attempt to find the issuer of the - * given certificate. + * This function will find the issuer of the given certificate. + * If the flag %GNUTLS_TL_GET_COPY is specified a copy of the issuer + * will be returned which must be freed using gnutls_x509_crt_deinit(). + * Note that the flag %GNUTLS_TL_GET_COPY is required for this function + * to work with PKCS #11 trust lists in a thread-safe way. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. @@ -695,6 +698,24 @@ int gnutls_x509_trust_list_get_issuer(gnutls_x509_trust_list_t list, if (ret < 0) return gnutls_assert_val(ret); + if (flags & GNUTLS_TL_GET_COPY) { + gnutls_x509_crt_t crt; + ret = gnutls_x509_crt_init(&crt); + if (ret < 0) { + gnutls_free(der.data); + return gnutls_assert_val(ret); + } + + ret = gnutls_x509_crt_import(crt, &der, GNUTLS_X509_FMT_DER); + if (ret < 0) { + gnutls_free(der.data); + gnutls_x509_crt_deinit(crt); + return gnutls_assert_val(ret); + } + *issuer = crt; + return 0; + } + /* we add this CA to the trusted list in order to make it * persistent. It will be deallocated when the trust list is. */ @@ -707,7 +728,11 @@ int gnutls_x509_trust_list_get_issuer(gnutls_x509_trust_list_t list, } #endif - return trust_list_get_issuer(list, cert, issuer, flags); + ret = trust_list_get_issuer(list, cert, issuer, flags); + if (flags & GNUTLS_TL_GET_COPY) { + *issuer = crt_cpy(*issuer); + } + return ret; } static |