summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2014-10-01 20:27:51 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2014-10-01 20:41:41 +0200
commit0aa92d8a73f7f59f46f9feb42a754e651235b386 (patch)
treeee8e1befbcec1d6b34ff0f5bc032d6432ef4c385
parent690ce2d1daffc43ab24bdec7a8aa3c750fd565b1 (diff)
downloadgnutls-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.c5
-rw-r--r--lib/gnutls_x509.c13
-rw-r--r--lib/includes/gnutls/x509.h1
-rw-r--r--lib/x509/ocsp.c6
-rw-r--r--lib/x509/verify-high.c33
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