gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls_3_0_18-104-g7338cd1


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_3_0_18-104-g7338cd1
Date: Sun, 03 Jun 2012 10:16:16 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=7338cd1084f805513d3fbb0ffb1517f3aea847a7

The branch, master has been updated
       via  7338cd1084f805513d3fbb0ffb1517f3aea847a7 (commit)
       via  e78a1008a5768630bc3c2c128f22184af2ec00a1 (commit)
       via  9a43e8fafbf93ae6b7811f90822d3c270ddb3222 (commit)
       via  d3b3e2fe76cfeda1c72a72ce716e6472b9e9f845 (commit)
      from  9833f4a19133b495f96d0da3adf57f1c7212dece (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 7338cd1084f805513d3fbb0ffb1517f3aea847a7
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Jun 3 12:15:15 2012 +0200

    gnutls_certificate_set_x509_simple_pkcs12_file() now imports certificate 
chain if it is present.
    gnutls_pkcs12_parse() was renamed to gnutls_pkcs12_simple_parse()

commit e78a1008a5768630bc3c2c128f22184af2ec00a1
Author: David Woodhouse <address@hidden>
Date:   Fri Jun 1 11:58:42 2012 +0100

    Export parse_pkcs12() as gnutls_pkcs12_parse()
    
    Signed-off-by: Nikos Mavrogiannopoulos <address@hidden>

commit 9a43e8fafbf93ae6b7811f90822d3c270ddb3222
Author: David Woodhouse <address@hidden>
Date:   Fri Jun 1 11:32:55 2012 +0100

    Make parse_pkcs12() return extra certificates too
    
    Optionally create a separate list, and return them for the caller to use
    as appropriate.
    
    This also cleans up the error handling a little. There seemed to be a
    potential memory leak (of *key, for example) when returning errors after
    some information had already been extracted.
    
    Signed-off-by: Nikos Mavrogiannopoulos <address@hidden>

commit d3b3e2fe76cfeda1c72a72ce716e6472b9e9f845
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sat Jun 2 10:31:02 2012 +0200

    minor documentation updates

-----------------------------------------------------------------------

Summary of changes:
 lib/gnutls_str.h             |    5 +
 lib/gnutls_x509.c            |  348 +++++--------------------------------
 lib/includes/gnutls/pkcs12.h |    8 +
 lib/libgnutls.map            |    1 +
 lib/nettle/pk.c              |    8 +-
 lib/x509/pkcs12.c            |  388 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 452 insertions(+), 306 deletions(-)

diff --git a/lib/gnutls_str.h b/lib/gnutls_str.h
index 965d2fc..a0fb44e 100644
--- a/lib/gnutls_str.h
+++ b/lib/gnutls_str.h
@@ -39,8 +39,13 @@ typedef struct
   size_t length;                /* API: current length */
 } gnutls_buffer_st;
 
+/* Initialize a buffer */
 void _gnutls_buffer_init (gnutls_buffer_st *);
+
+/* Free the data in a buffer */
 void _gnutls_buffer_clear (gnutls_buffer_st *);
+
+/* Set the buffer data to be of zero length */
 inline static void _gnutls_buffer_reset (gnutls_buffer_st * buf)
 {
   buf->data = buf->allocd;
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index 12af295..b308d6b 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -1832,306 +1832,6 @@ gnutls_certificate_set_x509_crl_file 
(gnutls_certificate_credentials_t res,
 
 #include <gnutls/pkcs12.h>
 
-static int
-parse_pkcs12 (gnutls_certificate_credentials_t res,
-              gnutls_pkcs12_t p12,
-              const char *password,
-              gnutls_x509_privkey_t * key,
-              gnutls_x509_crt_t * cert, gnutls_x509_crl_t * crl)
-{
-  gnutls_pkcs12_bag_t bag = NULL;
-  int idx = 0;
-  int ret;
-  size_t cert_id_size = 0;
-  size_t key_id_size = 0;
-  uint8_t cert_id[20];
-  uint8_t key_id[20];
-  int privkey_ok = 0;
-
-  *cert = NULL;
-  *key = NULL;
-  *crl = NULL;
-
-  /* find the first private key */
-  for (;;)
-    {
-      int elements_in_bag;
-      int i;
-
-      ret = gnutls_pkcs12_bag_init (&bag);
-      if (ret < 0)
-        {
-          bag = NULL;
-          gnutls_assert ();
-          goto done;
-        }
-
-      ret = gnutls_pkcs12_get_bag (p12, idx, bag);
-      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
-        break;
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          goto done;
-        }
-
-      ret = gnutls_pkcs12_bag_get_type (bag, 0);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          goto done;
-        }
-
-      if (ret == GNUTLS_BAG_ENCRYPTED)
-        {
-          ret = gnutls_pkcs12_bag_decrypt (bag, password);
-          if (ret < 0)
-            {
-              gnutls_assert ();
-              goto done;
-            }
-        }
-
-      elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
-      if (elements_in_bag < 0)
-        {
-          gnutls_assert ();
-          goto done;
-        }
-
-      for (i = 0; i < elements_in_bag; i++)
-        {
-          int type;
-          gnutls_datum_t data;
-
-          type = gnutls_pkcs12_bag_get_type (bag, i);
-          if (type < 0)
-            {
-              gnutls_assert ();
-              goto done;
-            }
-
-          ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
-          if (ret < 0)
-            {
-              gnutls_assert ();
-              goto done;
-            }
-
-          switch (type)
-            {
-            case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
-            case GNUTLS_BAG_PKCS8_KEY:
-              if (*key != NULL) /* too simple to continue */
-                {
-                  gnutls_assert ();
-                  break;
-                }
-
-              ret = gnutls_x509_privkey_init (key);
-              if (ret < 0)
-                {
-                  gnutls_assert ();
-                  goto done;
-                }
-
-              ret = gnutls_x509_privkey_import_pkcs8
-                (*key, &data, GNUTLS_X509_FMT_DER, password,
-                 type == GNUTLS_BAG_PKCS8_KEY ? GNUTLS_PKCS_PLAIN : 0);
-              if (ret < 0)
-                {
-                  gnutls_assert ();
-                  gnutls_x509_privkey_deinit (*key);
-                  goto done;
-                }
-
-              key_id_size = sizeof (key_id);
-              ret =
-                gnutls_x509_privkey_get_key_id (*key, 0, key_id,
-                                                &key_id_size);
-              if (ret < 0)
-                {
-                  gnutls_assert ();
-                  gnutls_x509_privkey_deinit (*key);
-                  goto done;
-                }
-
-              privkey_ok = 1;   /* break */
-              break;
-            default:
-              break;
-            }
-        }
-
-      idx++;
-      gnutls_pkcs12_bag_deinit (bag);
-
-      if (privkey_ok != 0)      /* private key was found */
-        break;
-    }
-
-  if (privkey_ok == 0)          /* no private key */
-    {
-      gnutls_assert ();
-      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
-    }
-
-  /* now find the corresponding certificate 
-   */
-  idx = 0;
-  bag = NULL;
-  for (;;)
-    {
-      int elements_in_bag;
-      int i;
-
-      ret = gnutls_pkcs12_bag_init (&bag);
-      if (ret < 0)
-        {
-          bag = NULL;
-          gnutls_assert ();
-          goto done;
-        }
-
-      ret = gnutls_pkcs12_get_bag (p12, idx, bag);
-      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
-        break;
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          goto done;
-        }
-
-      ret = gnutls_pkcs12_bag_get_type (bag, 0);
-      if (ret < 0)
-        {
-          gnutls_assert ();
-          goto done;
-        }
-
-      if (ret == GNUTLS_BAG_ENCRYPTED)
-        {
-          ret = gnutls_pkcs12_bag_decrypt (bag, password);
-          if (ret < 0)
-            {
-              gnutls_assert ();
-              goto done;
-            }
-        }
-
-      elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
-      if (elements_in_bag < 0)
-        {
-          gnutls_assert ();
-          goto done;
-        }
-
-      for (i = 0; i < elements_in_bag; i++)
-        {
-          int type;
-          gnutls_datum_t data;
-
-          type = gnutls_pkcs12_bag_get_type (bag, i);
-          if (type < 0)
-            {
-              gnutls_assert ();
-              goto done;
-            }
-
-          ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
-          if (ret < 0)
-            {
-              gnutls_assert ();
-              goto done;
-            }
-
-          switch (type)
-            {
-            case GNUTLS_BAG_CERTIFICATE:
-              if (*cert != NULL)        /* no need to set it again */
-                {
-                  gnutls_assert ();
-                  break;
-                }
-
-              ret = gnutls_x509_crt_init (cert);
-              if (ret < 0)
-                {
-                  gnutls_assert ();
-                  goto done;
-                }
-
-              ret =
-                gnutls_x509_crt_import (*cert, &data, GNUTLS_X509_FMT_DER);
-              if (ret < 0)
-                {
-                  gnutls_assert ();
-                  gnutls_x509_crt_deinit (*cert);
-                  goto done;
-                }
-
-              /* check if the key id match */
-              cert_id_size = sizeof (cert_id);
-              ret =
-                gnutls_x509_crt_get_key_id (*cert, 0, cert_id, &cert_id_size);
-              if (ret < 0)
-                {
-                  gnutls_assert ();
-                  gnutls_x509_crt_deinit (*cert);
-                  goto done;
-                }
-
-              if (memcmp (cert_id, key_id, cert_id_size) != 0)
-                {               /* they don't match - skip the certificate */
-                  gnutls_x509_crt_deinit (*cert);
-                  *cert = NULL;
-                }
-              break;
-
-            case GNUTLS_BAG_CRL:
-              if (*crl != NULL)
-                {
-                  gnutls_assert ();
-                  break;
-                }
-
-              ret = gnutls_x509_crl_init (crl);
-              if (ret < 0)
-                {
-                  gnutls_assert ();
-                  goto done;
-                }
-
-              ret = gnutls_x509_crl_import (*crl, &data, GNUTLS_X509_FMT_DER);
-              if (ret < 0)
-                {
-                  gnutls_assert ();
-                  gnutls_x509_crl_deinit (*crl);
-                  goto done;
-                }
-              break;
-
-            case GNUTLS_BAG_ENCRYPTED:
-              /* XXX Bother to recurse one level down?  Unlikely to
-                 use the same password anyway. */
-            case GNUTLS_BAG_EMPTY:
-            default:
-              break;
-            }
-        }
-
-      idx++;
-      gnutls_pkcs12_bag_deinit (bag);
-    }
-
-  ret = 0;
-
-done:
-  if (bag)
-    gnutls_pkcs12_bag_deinit (bag);
-
-  return ret;
-}
 
 /**
  * gnutls_certificate_set_x509_simple_pkcs12_file:
@@ -2187,6 +1887,8 @@ int
   return ret;
 }
 
+#define MAX_CERT_LIST 16
+
 /**
  * gnutls_certificate_set_x509_simple_pkcs12_mem:
  * @res: is a #gnutls_certificate_credentials_t structure.
@@ -2226,7 +1928,9 @@ int
   gnutls_pkcs12_t p12;
   gnutls_x509_privkey_t key = NULL;
   gnutls_x509_crt_t cert = NULL;
+  gnutls_x509_crt_t *extra_certs = NULL;
   gnutls_x509_crl_t crl = NULL;
+  unsigned int extra_certs_size = 0, i;
   int ret;
 
   ret = gnutls_pkcs12_init (&p12);
@@ -2255,7 +1959,8 @@ int
         }
     }
 
-  ret = parse_pkcs12 (res, p12, password, &key, &cert, &crl);
+  ret = gnutls_pkcs12_simple_parse (p12, password, &key, &cert, 
+                             &extra_certs, &extra_certs_size, &crl);
   gnutls_pkcs12_deinit (p12);
   if (ret < 0)
     {
@@ -2265,7 +1970,40 @@ int
 
   if (key && cert)
     {
-      ret = gnutls_certificate_set_x509_key (res, &cert, 1, key);
+      gnutls_x509_crt_t chain[MAX_CERT_LIST];
+      unsigned int chain_size = 1, j;
+      unsigned int done = 0;
+      
+      j = 0;
+      chain[j] = cert;
+
+      if (extra_certs_size > 0 && extra_certs_size < MAX_CERT_LIST-1)
+        {
+          do 
+            {
+              for (i=0;i<extra_certs_size;i++)
+                {
+                  if (gnutls_x509_crt_check_issuer(chain[j], extra_certs[i]) 
!= 0 &&
+                      gnutls_x509_crt_check_issuer(extra_certs[i], chain[j]) 
== 0)
+                    {
+                      if (gnutls_x509_crt_check_issuer(extra_certs[i], 
extra_certs[i]) != 0)
+                        { /* we found a self-signed one. We are done. */
+                          done = 1;
+                          break;
+                        }
+                      chain[++j] = extra_certs[i];
+                      chain_size++;
+                      break;
+                    }
+
+                  if (i==extra_certs_size - 1) 
+                    done = 1;
+                }
+            }
+          while(done == 0);
+        }
+
+      ret = gnutls_certificate_set_x509_key (res, chain, chain_size, key);
       if (ret < 0)
         {
           gnutls_assert ();
@@ -2286,6 +2024,12 @@ int
   ret = 0;
 
 done:
+  if (extra_certs)
+    {
+      for (i=0;i<extra_certs_size;i++)
+        gnutls_x509_crt_deinit (extra_certs[i]);
+      gnutls_free(extra_certs);
+    }
   if (cert)
     gnutls_x509_crt_deinit (cert);
   if (key)
diff --git a/lib/includes/gnutls/pkcs12.h b/lib/includes/gnutls/pkcs12.h
index 91a1c69..dde5b84 100644
--- a/lib/includes/gnutls/pkcs12.h
+++ b/lib/includes/gnutls/pkcs12.h
@@ -57,6 +57,14 @@ extern "C"
   int gnutls_pkcs12_bag_decrypt (gnutls_pkcs12_bag_t bag, const char *pass);
   int gnutls_pkcs12_bag_encrypt (gnutls_pkcs12_bag_t bag, const char *pass,
                                  unsigned int flags);
+  int gnutls_pkcs12_simple_parse (
+                           gnutls_pkcs12_t p12,
+                           const char *password,
+                           gnutls_x509_privkey_t * key,
+                           gnutls_x509_crt_t * cert,
+                           gnutls_x509_crt_t ** extra_certs_ret,
+                           unsigned int * extra_certs_ret_len,
+                           gnutls_x509_crl_t * crl);
 
 /**
  * gnutls_pkcs12_bag_type_t:
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 7ac20a4..8a9b390 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -797,6 +797,7 @@ GNUTLS_3_1_0 {
        gnutls_x509_trust_list_add_system_trust;
        gnutls_x509_trust_list_add_trust_file;
        gnutls_x509_trust_list_add_trust_mem;
+       gnutls_pkcs12_parse;
 } GNUTLS_3_0_0;
 
 GNUTLS_PRIVATE {
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index ea46f4c..41a0fb1 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -264,7 +264,6 @@ _wrap_nettle_pk_decrypt (gnutls_pk_algorithm_t algo,
         unsigned length;
         bigint_t c;
 
-        memset(&priv, 0, sizeof(priv));
         _rsa_params_to_privkey (pk_params, &priv);
         _rsa_params_to_pubkey (pk_params, &pub);
 
@@ -409,15 +408,16 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
     case GNUTLS_PK_RSA:
       {
         struct rsa_private_key priv;
+        struct rsa_public_key pub;
         mpz_t s;
 
-        memset(&priv, 0, sizeof(priv));
         _rsa_params_to_privkey (pk_params, &priv);
+        _rsa_params_to_pubkey (pk_params, &pub);
         
         mpz_init(s);
 
-/* XXX update when _tr is available */
-        ret = rsa_pkcs1_sign(&priv, vdata->size, vdata->data, s);
+        ret = rsa_pkcs1_sign_tr(&pub, &priv, NULL, rnd_func,
+                                vdata->size, vdata->data, s);
         if (ret == 0)
           {
             gnutls_assert();
diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c
index f26fd4f..40b3a8a 100644
--- a/lib/x509/pkcs12.c
+++ b/lib/x509/pkcs12.c
@@ -1328,3 +1328,391 @@ cleanup:
 
 }
 
+/**
+ * gnutls_pkcs12_simple_parse:
+ * @p12: the PKCS#12 blob.
+ * @password: optional password used to decrypt PKCS#12 blob, bags and keys.
+ * @key: a structure to store the parsed private key.
+ * @cert: a structure to store the parsed certificate.
+ * @extra_certs_ret: optional pointer to receive an array of additional
+ *                   certificates found in the PKCS#12 blob.
+ * @extra_certs_ret_len: will be updated with the number of additional
+ *                       certs.
+ * @crl: a structure to store the parsed CRL.
+ *
+ * This function parses a PKCS#12 blob in @p12blob and extracts the
+ * private key, the corresponding certificate, and any additional
+ * certificates and a CRL.
+ *
+ * The @extra_certs_ret and @extra_certs_ret_len parameters are optional
+ * and both may be set to %NULL. If either is non-%NULL, then both must
+ * be.
+ * 
+ * MAC:ed PKCS#12 files are supported.  Encrypted PKCS#12 bags are
+ * supported.  Encrypted PKCS#8 private keys are supported.  However,
+ * only password based security, and the same password for all
+ * operations, are supported.
+ *
+ * The private keys may be RSA PKCS#1 or DSA private keys encoded in
+ * the OpenSSL way.
+ *
+ * PKCS#12 file may contain many keys and/or certificates, and there
+ * is no way to identify which key/certificate pair you want.  You
+ * should make sure the PKCS#12 file only contain one key/certificate
+ * pair and/or one CRL.
+ *
+ * It is believed that the limitations of this function is acceptable
+ * for most usage, and that any more flexibility would introduce
+ * complexity that would make it harder to use this functionality at
+ * all.
+ *
+ * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
+ *
+ * Since: 3.1
+ **/
+int
+gnutls_pkcs12_simple_parse (gnutls_pkcs12_t p12,
+                     const char *password,
+                     gnutls_x509_privkey_t * key,
+                     gnutls_x509_crt_t * cert,
+                     gnutls_x509_crt_t ** extra_certs_ret,
+                     unsigned int * extra_certs_ret_len,
+                     gnutls_x509_crl_t * crl)
+{
+  gnutls_pkcs12_bag_t bag = NULL;
+  gnutls_x509_crt_t *extra_certs = NULL;
+  unsigned int extra_certs_len = 0;
+  int idx = 0;
+  int ret;
+  size_t cert_id_size = 0;
+  size_t key_id_size = 0;
+  uint8_t cert_id[20];
+  uint8_t key_id[20];
+  int privkey_ok = 0;
+
+  *cert = NULL;
+  *key = NULL;
+  *crl = NULL;
+
+  /* find the first private key */
+  for (;;)
+    {
+      int elements_in_bag;
+      int i;
+
+      ret = gnutls_pkcs12_bag_init (&bag);
+      if (ret < 0)
+        {
+          bag = NULL;
+          gnutls_assert ();
+          goto done;
+        }
+
+      ret = gnutls_pkcs12_get_bag (p12, idx, bag);
+      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+        break;
+      if (ret < 0)
+        {
+          gnutls_assert ();
+          goto done;
+        }
+
+      ret = gnutls_pkcs12_bag_get_type (bag, 0);
+      if (ret < 0)
+        {
+          gnutls_assert ();
+          goto done;
+        }
+
+      if (ret == GNUTLS_BAG_ENCRYPTED)
+        {
+          ret = gnutls_pkcs12_bag_decrypt (bag, password);
+          if (ret < 0)
+            {
+              gnutls_assert ();
+              goto done;
+            }
+        }
+
+      elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
+      if (elements_in_bag < 0)
+        {
+          gnutls_assert ();
+          goto done;
+        }
+
+      for (i = 0; i < elements_in_bag; i++)
+        {
+          int type;
+          gnutls_datum_t data;
+
+          type = gnutls_pkcs12_bag_get_type (bag, i);
+          if (type < 0)
+            {
+              gnutls_assert ();
+              goto done;
+            }
+
+          ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
+          if (ret < 0)
+            {
+              gnutls_assert ();
+              goto done;
+            }
+
+          switch (type)
+            {
+            case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
+            case GNUTLS_BAG_PKCS8_KEY:
+              if (*key != NULL) /* too simple to continue */
+                {
+                  gnutls_assert ();
+                  break;
+                }
+
+              ret = gnutls_x509_privkey_init (key);
+              if (ret < 0)
+                {
+                  gnutls_assert ();
+                  goto done;
+                }
+
+              ret = gnutls_x509_privkey_import_pkcs8
+                (*key, &data, GNUTLS_X509_FMT_DER, password,
+                 type == GNUTLS_BAG_PKCS8_KEY ? GNUTLS_PKCS_PLAIN : 0);
+              if (ret < 0)
+                {
+                  gnutls_assert ();
+                  gnutls_x509_privkey_deinit (*key);
+                  goto done;
+                }
+
+              key_id_size = sizeof (key_id);
+              ret =
+                gnutls_x509_privkey_get_key_id (*key, 0, key_id,
+                                                &key_id_size);
+              if (ret < 0)
+                {
+                  gnutls_assert ();
+                  gnutls_x509_privkey_deinit (*key);
+                  goto done;
+                }
+
+              privkey_ok = 1;   /* break */
+              break;
+            default:
+              break;
+            }
+        }
+
+      idx++;
+      gnutls_pkcs12_bag_deinit (bag);
+
+      if (privkey_ok != 0)      /* private key was found */
+        break;
+    }
+
+  if (privkey_ok == 0)          /* no private key */
+    {
+      gnutls_assert ();
+      return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+    }
+
+  /* now find the corresponding certificate 
+   */
+  idx = 0;
+  bag = NULL;
+  for (;;)
+    {
+      int elements_in_bag;
+      int i;
+
+      ret = gnutls_pkcs12_bag_init (&bag);
+      if (ret < 0)
+        {
+          bag = NULL;
+          gnutls_assert ();
+          goto done;
+        }
+
+      ret = gnutls_pkcs12_get_bag (p12, idx, bag);
+      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
+        break;
+      if (ret < 0)
+        {
+          gnutls_assert ();
+          goto done;
+        }
+
+      ret = gnutls_pkcs12_bag_get_type (bag, 0);
+      if (ret < 0)
+        {
+          gnutls_assert ();
+          goto done;
+        }
+
+      if (ret == GNUTLS_BAG_ENCRYPTED)
+        {
+          ret = gnutls_pkcs12_bag_decrypt (bag, password);
+          if (ret < 0)
+            {
+              gnutls_assert ();
+              goto done;
+            }
+        }
+
+      elements_in_bag = gnutls_pkcs12_bag_get_count (bag);
+      if (elements_in_bag < 0)
+        {
+          gnutls_assert ();
+          goto done;
+        }
+
+      for (i = 0; i < elements_in_bag; i++)
+        {
+          int type;
+          gnutls_datum_t data;
+          gnutls_x509_crt_t this_cert;
+
+          type = gnutls_pkcs12_bag_get_type (bag, i);
+          if (type < 0)
+            {
+              gnutls_assert ();
+              goto done;
+            }
+
+          ret = gnutls_pkcs12_bag_get_data (bag, i, &data);
+          if (ret < 0)
+            {
+              gnutls_assert ();
+              goto done;
+            }
+
+          switch (type)
+            {
+            case GNUTLS_BAG_CERTIFICATE:
+              ret = gnutls_x509_crt_init (&this_cert);
+              if (ret < 0)
+                {
+                  gnutls_assert ();
+                  goto done;
+                }
+
+              ret =
+                gnutls_x509_crt_import (this_cert, &data, GNUTLS_X509_FMT_DER);
+              if (ret < 0)
+                {
+                  gnutls_assert ();
+                  gnutls_x509_crt_deinit (this_cert);
+                  goto done;
+                }
+
+              /* check if the key id match */
+              cert_id_size = sizeof (cert_id);
+              ret =
+                gnutls_x509_crt_get_key_id (this_cert, 0, cert_id, 
&cert_id_size);
+              if (ret < 0)
+                {
+                  gnutls_assert ();
+                  gnutls_x509_crt_deinit (this_cert);
+                  goto done;
+                }
+
+              if (memcmp (cert_id, key_id, cert_id_size) != 0)
+                {               /* they don't match - skip the certificate */
+                  if (extra_certs_ret)
+                    {
+                      extra_certs = gnutls_realloc (extra_certs,
+                                                    sizeof(extra_certs[0]) *
+                                                    ++extra_certs_len);
+                      if (!extra_certs)
+                        {
+                          gnutls_assert ();
+                          ret = GNUTLS_E_MEMORY_ERROR;
+                          goto done;
+                        }
+                      extra_certs[extra_certs_len - 1] = this_cert;
+                      this_cert = NULL;
+                    }
+                  else
+                    {
+                       gnutls_x509_crt_deinit (this_cert);
+                    }
+                  break;
+                }
+              else
+                {
+                   if (*cert != NULL)        /* no need to set it again */
+                     {
+                        gnutls_assert ();
+                        break;
+                     }
+                   *cert = this_cert;
+                   this_cert = NULL;
+                }
+              break;
+
+            case GNUTLS_BAG_CRL:
+              if (*crl != NULL)
+                {
+                  gnutls_assert ();
+                  break;
+                }
+
+              ret = gnutls_x509_crl_init (crl);
+              if (ret < 0)
+                {
+                  gnutls_assert ();
+                  goto done;
+                }
+
+              ret = gnutls_x509_crl_import (*crl, &data, GNUTLS_X509_FMT_DER);
+              if (ret < 0)
+                {
+                  gnutls_assert ();
+                  gnutls_x509_crl_deinit (*crl);
+                  goto done;
+                }
+              break;
+
+            case GNUTLS_BAG_ENCRYPTED:
+              /* XXX Bother to recurse one level down?  Unlikely to
+                 use the same password anyway. */
+            case GNUTLS_BAG_EMPTY:
+            default:
+              break;
+            }
+        }
+
+      idx++;
+      gnutls_pkcs12_bag_deinit (bag);
+    }
+
+  ret = 0;
+
+done:
+  if (bag)
+    gnutls_pkcs12_bag_deinit (bag);
+
+  if (ret)
+    {
+      if (*key)
+        gnutls_x509_privkey_deinit(*key);
+      if (*cert)
+        gnutls_x509_crt_deinit(*cert);
+      if (extra_certs_len)
+        {
+          unsigned int i;
+          for (i = 0; i < extra_certs_len; i++)
+            gnutls_x509_crt_deinit(extra_certs[i]);
+          gnutls_free(extra_certs);
+        }
+    }
+  else if (extra_certs_ret)
+    {
+      *extra_certs_ret = extra_certs;
+      *extra_certs_ret_len = extra_certs_len;
+    }
+
+  return ret;
+}


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]