]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added GNUTLS_TL_GET_COPY flag and documented the limitations of gnutls_x509_trust_lis...
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Wed, 1 Oct 2014 18:27:51 +0000 (20:27 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Wed, 1 Oct 2014 18:35:20 +0000 (20:35 +0200)
lib/gnutls_cert.c
lib/gnutls_x509.c
lib/includes/gnutls/x509.h
lib/x509/ocsp.c
lib/x509/verify-high.c

index cb4c58989f1817947670a165d73f31b7ad9a5072..5a8bce01985ffdf9245782aad3b7a160f5b2d880 100644 (file)
@@ -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.
index 1a60974cfd1b5170eecddccbba585cc8b5de31af..0abf3ed710826572f41a5d4d9764e6d846a1f574 100644 (file)
@@ -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);
index 7ad0618d1bda6bcb8605805b34e4a47eb1e9bb1b..0314bbe38abbcf06d1efe2482245db93bfb9a3d0 100644 (file)
@@ -1261,6 +1261,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,
index f82fb684a34b57a115762794b13d820b8841b927..5c3cae82f2bf87ac1b1d2e1100e43f37d123e2b0 100644 (file)
@@ -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;
 }
index c1cb98dfc948af4a20d5f8cb3a67ce0346080d06..b7d54acb4a92867de84427b891734000462c4530 100644 (file)
@@ -757,10 +757,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.
@@ -783,6 +786,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.
                 */
@@ -795,7 +816,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