]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added gnutls_certificate_set_retrieve_function2() to replace
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Wed, 20 Apr 2011 22:21:56 +0000 (00:21 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Wed, 20 Apr 2011 22:21:56 +0000 (00:21 +0200)
gnutls_certificate_set_retrieve_function(). The new one is a
efficient for busy servers because it eliminates the need
for the server to encode the certificate to DER format.

doc/examples/ex-cert-select.c
lib/auth/cert.c
lib/auth/cert.h
lib/gnutls_cert.c
lib/includes/gnutls/abstract.h
lib/includes/gnutls/gnutls.h.in
lib/libgnutls.map
src/certtool.c
src/cli.c
tests/x509dn.c

index 09b9a5e57c3a8c6e59e78279f079d028250fb76e..461820cb4e66e53de4269329ae4fafee1e2984e2 100644 (file)
@@ -13,6 +13,7 @@
 #include <unistd.h>
 #include <gnutls/gnutls.h>
 #include <gnutls/x509.h>
+#include <gnutls/abstract.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 extern int tcp_connect (void);
 extern void tcp_close (int sd);
 
-static int cert_callback (gnutls_session_t session,
-                          const gnutls_datum_t * req_ca_rdn, int nreqs,
-                          const gnutls_pk_algorithm_t * sign_algos,
-                          int sign_algos_length, gnutls_retr2_st * st);
+static int
+cert_callback (gnutls_session_t session,
+               const gnutls_datum_t * req_ca_rdn, int nreqs,
+               const gnutls_pk_algorithm_t * sign_algos,
+               int sign_algos_length, gnutls_pcert_st** pcert,
+               unsigned int *pcert_length, gnutls_privkey_t* pkey);
 
-gnutls_x509_crt_t crt;
-gnutls_x509_privkey_t key;
+gnutls_pcert_st crt;
+gnutls_privkey_t key;
 
 /* Helper functions to load a certificate and key
  * files into memory.
@@ -77,19 +80,19 @@ load_keys (void)
 {
   int ret;
   gnutls_datum_t data;
+  gnutls_x509_privkey_t x509_key;
 
   data = load_file (CERT_FILE);
   if (data.data == NULL)
     {
-      fprintf (stderr, "*** Error loading cert file.\n");
+      fprintf (stderr, "*** Error loading certificate file.\n");
       exit (1);
     }
-  gnutls_x509_crt_init (&crt);
-
-  ret = gnutls_x509_crt_import (crt, &data, GNUTLS_X509_FMT_PEM);
+  
+  ret = gnutls_pcert_import_x509_raw(&crt, &data, GNUTLS_X509_FMT_PEM, 0);
   if (ret < 0)
     {
-      fprintf (stderr, "*** Error loading key file: %s\n",
+      fprintf (stderr, "*** Error loading certificate file: %s\n",
                gnutls_strerror (ret));
       exit (1);
     }
@@ -103,9 +106,9 @@ load_keys (void)
       exit (1);
     }
 
-  gnutls_x509_privkey_init (&key);
+  gnutls_x509_privkey_init (&x509_key);
 
-  ret = gnutls_x509_privkey_import (key, &data, GNUTLS_X509_FMT_PEM);
+  ret = gnutls_x509_privkey_import (x509_key, &data, GNUTLS_X509_FMT_PEM);
   if (ret < 0)
     {
       fprintf (stderr, "*** Error loading key file: %s\n",
@@ -113,8 +116,17 @@ load_keys (void)
       exit (1);
     }
 
-  unload_file (data);
+  gnutls_privkey_init (&key);
 
+  ret = gnutls_privkey_import_x509(key, x509_key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
+  if (ret < 0)
+    {
+      fprintf (stderr, "*** Error importing key: %s\n", 
+               gnutls_strerror (ret));
+      exit (1);
+    }
+
+  unload_file (data);
 }
 
 int
@@ -143,7 +155,7 @@ main (void)
    */
   gnutls_certificate_set_x509_trust_file (xcred, CAFILE, GNUTLS_X509_FMT_PEM);
 
-  gnutls_certificate_set_retrieve_function (xcred, cert_callback);
+  gnutls_certificate_set_retrieve_function2 (xcred, cert_callback);
 
   /* Initialize TLS session 
    */
@@ -225,7 +237,8 @@ static int
 cert_callback (gnutls_session_t session,
                const gnutls_datum_t * req_ca_rdn, int nreqs,
                const gnutls_pk_algorithm_t * sign_algos,
-               int sign_algos_length, gnutls_retr2_st * st)
+               int sign_algos_length, gnutls_pcert_st** pcert,
+               unsigned int *pcert_length, gnutls_privkey_t* pkey)
 {
   char issuer_dn[256];
   int i, ret;
@@ -255,59 +268,12 @@ cert_callback (gnutls_session_t session,
    * The certificate must be of any of the "sign algorithms"
    * supported by the server.
    */
-
   type = gnutls_certificate_type_get (session);
   if (type == GNUTLS_CRT_X509)
     {
-      /* check if the certificate we are sending is signed
-       * with an algorithm that the server accepts */
-      gnutls_sign_algorithm_t cert_algo, req_algo;
-      int i, match = 0;
-
-      ret = gnutls_x509_crt_get_signature_algorithm (crt);
-      if (ret < 0)
-        {
-          /* error reading signature algorithm 
-           */
-          return -1;
-        }
-      cert_algo = ret;
-
-      i = 0;
-      do
-        {
-          ret = gnutls_sign_algorithm_get_requested (session, i, &req_algo);
-          if (ret >= 0 && cert_algo == req_algo)
-            {
-              match = 1;
-              break;
-            }
-
-          /* server has not requested anything specific */
-          if (i == 0 && ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
-            {
-              match = 1;
-              break;
-            }
-          i++;
-        }
-      while (ret >= 0);
-
-      if (match == 0)
-        {
-          printf
-            ("- Could not find a suitable certificate to send to server\n");
-          return -1;
-        }
-
-      st->cert_type = type;
-      st->ncerts = 1;
-
-      st->cert.x509 = &crt;
-      st->key.x509 = key;
-      st->key_type = GNUTLS_PRIVKEY_X509;
-
-      st->deinit_all = 0;
+      *pcert_length = 1;
+      *pcert = &crt;
+      *pkey = key;
     }
   else
     {
index 39cf8edbd033734a4592860cdcd6760fe72fffd4..ac87412c489ea2b01083fe92ab0441497738819d 100644 (file)
@@ -459,6 +459,8 @@ call_get_cert_callback (gnutls_session_t session,
   gnutls_certificate_type_t type = gnutls_certificate_type_get (session);
   gnutls_certificate_credentials_t cred;
   gnutls_retr2_st st2;
+  gnutls_pcert_st *pcert = NULL;
+  unsigned int pcert_length = 0;
 
   cred = (gnutls_certificate_credentials_t)
     _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
@@ -470,7 +472,31 @@ call_get_cert_callback (gnutls_session_t session,
 
   memset (&st2, 0, sizeof (st2));
 
-  if (cred->get_cert_callback)
+  if (cred->get_cert_callback2)
+    {
+      /* we avoid all allocations and transformations */
+      ret = cred->get_cert_callback2 (session, issuers_dn, issuers_dn_length,
+                                     pk_algos, pk_algos_length, 
+                                     &pcert, &pcert_length, &local_key);
+      if (ret < 0)
+        return gnutls_assert_val(GNUTLS_E_USER_ERROR);
+
+      if (pcert_length > 0 && type != pcert[0].type)
+        return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+      if (pcert_length == 0)
+        {
+          pcert = NULL;
+          local_key = NULL;
+        }
+      _gnutls_selected_certs_set (session, pcert,
+                              pcert_length,
+                              local_key, 0);
+      
+      return 0;
+
+    }
+  else if (cred->get_cert_callback)
     {
       ret = cred->get_cert_callback (session, issuers_dn, issuers_dn_length,
                                      pk_algos, pk_algos_length, &st2);
@@ -511,7 +537,7 @@ call_get_cert_callback (gnutls_session_t session,
   if (ret < 0)
     {
       gnutls_assert ();
-      return GNUTLS_E_INTERNAL_ERROR;
+      return GNUTLS_E_USER_ERROR;
     }
 
   if (st2.ncerts == 0)
@@ -663,7 +689,7 @@ _select_client_cert (gnutls_session_t session,
     }
 
   if (cred->client_get_cert_callback != NULL
-      || cred->get_cert_callback != NULL)
+      || cred->get_cert_callback != NULL || cred->get_cert_callback2 != NULL)
     {
 
       /* use a callback to get certificate 
@@ -2046,7 +2072,8 @@ _gnutls_server_select_cert (gnutls_session_t session,
   /* If the callback which retrieves certificate has been set,
    * use it and leave.
    */
-  if (cred->server_get_cert_callback != NULL)
+  if (cred->server_get_cert_callback != NULL || cred->server_get_cert_callback ||
+      cred->get_cert_callback2)
     {
       ret = call_get_cert_callback (session, NULL, 0, NULL, 0);
       if (ret < 0)
@@ -2074,11 +2101,10 @@ _gnutls_server_select_cert (gnutls_session_t session,
       if (requested_algo == GNUTLS_PK_ANY ||
           requested_algo == pk)
         {
-          /* if cert type and signature algorithm matches
+          /* if cert type matches
            */
          /* *INDENT-OFF* */
-         if (session->security_parameters.cert_type == cred->cert_list[i][0].type
-             && (cred->cert_list[i][0].type == GNUTLS_CRT_OPENPGP))
+         if (session->security_parameters.cert_type == cred->cert_list[i][0].type)
            {
              idx = i;
              break;
index d26935bdc1d78c4747b4bf69cea2803838a81f5d..d8e29ddb79e311add9f14374e3e32970b1be6e6e 100644 (file)
@@ -84,11 +84,15 @@ typedef struct gnutls_certificate_credentials_st
    */
   gnutls_datum_t x509_rdn_sequence;
 
+  /* It's a mess here. However we need to keep the old 3 functions
+   * for compatibility */
+  gnutls_certificate_retrieve_function *get_cert_callback; /* deprecated */
   gnutls_certificate_client_retrieve_function *client_get_cert_callback;        /* deprecated */
   gnutls_certificate_server_retrieve_function *server_get_cert_callback;        /* deprecated */
+  gnutls_certificate_retrieve_function2 *get_cert_callback2;
+
   gnutls_certificate_verify_function *verify_callback;
 
-  gnutls_certificate_retrieve_function *get_cert_callback;
 } certificate_credentials_st;
 
 typedef struct rsa_info_st
index f587f16b39649efeaaeb59dd640e2e7fd338b528..91ad7caccfd1bef3c9a1c2c715baba797e7a4ff5 100644 (file)
@@ -305,6 +305,8 @@ gnutls_certificate_server_set_request (gnutls_session_t session,
  *
  * This function sets a callback to be called in order to retrieve the
  * certificate to be used in the handshake.
+ * You are advised to use gnutls_certificate_set_retrieve_function2() because it
+ * is much more efficient in the processing it requires from gnutls.
  *
  * The callback's function prototype is:
  * int (*callback)(gnutls_session_t, const gnutls_datum_t* req_ca_dn, int nreqs,
@@ -343,6 +345,8 @@ void gnutls_certificate_client_set_retrieve_function
  *
  * This function sets a callback to be called in order to retrieve the
  * certificate to be used in the handshake.
+ * You are advised to use gnutls_certificate_set_retrieve_function2() because it
+ * is much more efficient in the processing it requires from gnutls.
  *
  * The callback's function prototype is:
  * int (*callback)(gnutls_session_t, gnutls_retr_st* st);
@@ -369,7 +373,9 @@ void gnutls_certificate_server_set_retrieve_function
  * @func: is the callback function
  *
  * This function sets a callback to be called in order to retrieve the
- * certificate to be used in the handshake.
+ * certificate to be used in the handshake. You are advised
+ * to use gnutls_certificate_set_retrieve_function2() because it
+ * is much more efficient in the processing it requires from gnutls.
  *
  * The callback's function prototype is:
  * int (*callback)(gnutls_session_t, const gnutls_datum_t* req_ca_dn, int nreqs,
@@ -403,6 +409,46 @@ void gnutls_certificate_set_retrieve_function
   cred->get_cert_callback = func;
 }
 
+/**
+ * gnutls_certificate_set_retrieve_function2:
+ * @cred: is a #gnutls_certificate_credentials_t structure.
+ * @func: is the callback function
+ *
+ * This function sets a callback to be called in order to retrieve the
+ * certificate to be used in the handshake.
+ *
+ * The callback's function prototype is:
+ * int (*callback)(gnutls_session_t, const gnutls_datum_t* req_ca_dn, int nreqs,
+ * const gnutls_pk_algorithm_t* pk_algos, int pk_algos_length, gnutls_pcert_st* st);
+ *
+ * @req_ca_cert is only used in X.509 certificates.
+ * Contains a list with the CA names that the server considers trusted.
+ * Normally we should send a certificate that is signed
+ * by one of these CAs. These names are DER encoded. To get a more
+ * meaningful value use the function gnutls_x509_rdn_get().
+ *
+ * @pk_algos contains a list with server's acceptable signature algorithms.
+ * The certificate returned should support the server's given algorithms.
+ *
+ * @st should contain the certificates and private keys.
+ *
+ * If the callback function is provided then gnutls will call it, in the
+ * handshake, after the certificate request message has been received.
+ *
+ * In server side pk_algos and req_ca_dn are NULL.
+ *
+ * The callback function should set the certificate list to be sent,
+ * and return 0 on success. If no certificate was selected then the
+ * number of certificates should be set to zero. The value (-1)
+ * indicates error and the handshake will be terminated.
+ **/
+void gnutls_certificate_set_retrieve_function2
+  (gnutls_certificate_credentials_t cred,
+   gnutls_certificate_retrieve_function2 * func)
+{
+  cred->get_cert_callback2 = func;
+}
+
 /**
  * gnutls_certificate_set_verify_function:
  * @cred: is a #gnutls_certificate_credentials_t structure.
index 85a427ff414c8cd62161f894cf03cb8206d57ce1..3c6274fc213a9937ffe381ddeb698028b6eef147 100644 (file)
@@ -181,5 +181,27 @@ int gnutls_pcert_import_openpgp (gnutls_pcert_st* pcert,
 
 void gnutls_pcert_deinit (gnutls_pcert_st* pcert);
 
+/* For certificate credentials */
+  /* This is the same as gnutls_certificate_retrieve_function()
+   * but retrieves a gnutls_pcert_st which requires much less processing
+   * within the library.
+   */
+  typedef int gnutls_certificate_retrieve_function2 (gnutls_session_t,
+                                                    const gnutls_datum_t *
+                                                    req_ca_rdn,
+                                                    int nreqs,
+                                                    const
+                                                    gnutls_pk_algorithm_t
+                                                    * pk_algos,
+                                                    int pk_algos_length,
+                                                    gnutls_pcert_st **,
+                                                    unsigned int *pcert_length,
+                                                    gnutls_privkey_t *privkey);
+
+
+  void gnutls_certificate_set_retrieve_function2
+    (gnutls_certificate_credentials_t cred,
+     gnutls_certificate_retrieve_function2 * func);
+
 
 #endif
index 06f6f40505d62b13dacc6047d1731926743ba157..0cdbffd27a30d402bfff8949587e0ce8682ddfcc 100644 (file)
@@ -1479,25 +1479,10 @@ extern "C"
 
   /* These are set on the credentials structure.
    */
-  
-  /* This is the same as gnutls_certificate_retrieve_function()
-   * but retrieves a gnutls_pcert_st which requires much less processing
-   * within the library.
-   */
-  typedef int gnutls_certificate_retrieve_function2 (gnutls_session_t,
-                                                    const gnutls_datum_t *
-                                                    req_ca_rdn,
-                                                    int nreqs,
-                                                    const
-                                                    gnutls_pk_algorithm_t
-                                                    * pk_algos,
-                                                    int pk_algos_length,
-                                                    gnutls_pcert_st *);
-
 
-  void gnutls_certificate_set_retrieve_function2
-    (gnutls_certificate_credentials_t cred,
-     gnutls_certificate_retrieve_function2 * func);
+  /* use gnutls_certificate_set_retrieve_function2() in abstract.h
+   * instead. It's much more efficient.
+   */
 
   typedef int gnutls_certificate_retrieve_function (gnutls_session_t,
                                                     const
index 0b93d685494a369fbe6efc9591cc637ddc182164..87d70cc37b10b6bb7afdbd6bfe45663d9cd29379 100644 (file)
@@ -708,6 +708,7 @@ GNUTLS_3_0_0 {
        gnutls_pcert_import_openpgp;
        gnutls_pcert_import_openpgp_raw;
        gnutls_pubkey_get_openpgp_key_id;
+       gnutls_certificate_set_retrieve_function2;
 } GNUTLS_2_12;
 
 GNUTLS_PRIVATE {
index 9800bfb2595458f06f1588779a1aa4f62074bb58..18096606184ee9903b3267e802bedb22533128b1 100644 (file)
@@ -1317,7 +1317,7 @@ void
 pgp_privkey_info (void)
 {
   gnutls_openpgp_privkey_t key;
-  gnutls_openpgp_keyid_t keyid;
+  unsigned char keyid[GNUTLS_OPENPGP_KEYID_SIZE];
   size_t size;
   int ret, i, subkeys;
   gnutls_datum_t pem;
index 31eb80e0f5bd5190d415d08177710798e74f4b10..88aa645999ca43f9c031f57838cc22f60b9dd637 100644 (file)
--- a/src/cli.c
+++ b/src/cli.c
@@ -34,8 +34,8 @@
 #include <error.h>
 
 #include <gnutls/gnutls.h>
+#include <gnutls/abstract.h>
 #include <gnutls/dtls.h>
-#include <gnutls/extra.h>
 #include <gnutls/x509.h>
 #include <gnutls/openpgp.h>
 #include <gnutls/pkcs11.h>
@@ -135,13 +135,11 @@ unload_file (gnutls_datum_t data)
 
 #define MAX_CRT 6
 static unsigned int x509_crt_size;
-static gnutls_x509_crt_t x509_crt[MAX_CRT];
-static gnutls_x509_privkey_t x509_key = NULL;
+static gnutls_pcert_st x509_crt[MAX_CRT];
+static gnutls_privkey_t x509_key = NULL;
 
-static gnutls_pkcs11_privkey_t pkcs11_key = NULL;
-
-static gnutls_openpgp_crt_t pgp_crt = NULL;
-static gnutls_openpgp_privkey_t pgp_key = NULL;
+static gnutls_pcert_st pgp_crt;
+static gnutls_privkey_t pgp_key = NULL;
 
 static void
 get_keyid (gnutls_openpgp_keyid_t keyid, const char *str)
@@ -170,22 +168,26 @@ static void
 load_keys (void)
 {
   unsigned int crt_num;
-  int ret;
+  int ret, i;
   gnutls_datum_t data;
+  gnutls_x509_crt_t crt_list[MAX_CRT];
+  gnutls_pkcs11_privkey_t pkcs11_key;
+  gnutls_x509_privkey_t tmp_key;
+  uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE];
 
   if (x509_certfile != NULL && x509_keyfile != NULL)
     {
       if (strncmp (x509_certfile, "pkcs11:", 7) == 0)
         {
           crt_num = 1;
-          gnutls_x509_crt_init (&x509_crt[0]);
+          gnutls_x509_crt_init (&crt_list[0]);
 
           ret =
-            gnutls_x509_crt_import_pkcs11_url (x509_crt[0], x509_certfile, 0);
+            gnutls_x509_crt_import_pkcs11_url (crt_list[0], x509_certfile, 0);
 
           if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
             ret =
-              gnutls_x509_crt_import_pkcs11_url (x509_crt[0], x509_certfile,
+              gnutls_x509_crt_import_pkcs11_url (crt_list[0], x509_certfile,
                                                  GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
 
           if (ret < 0)
@@ -207,7 +209,7 @@ load_keys (void)
 
           crt_num = MAX_CRT;
           ret =
-            gnutls_x509_crt_list_import (x509_crt, &crt_num, &data,
+            gnutls_x509_crt_list_import (crt_list, &crt_num, &data,
                                          GNUTLS_X509_FMT_PEM,
                                          GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
           if (ret < 0)
@@ -229,10 +231,29 @@ load_keys (void)
             }
           x509_crt_size = ret;
         }
-      fprintf (stdout, "Processed %d client certificates...\n", ret);
+      
+      for (i=0;i<x509_crt_size;i++)
+        {
+          ret = gnutls_pcert_import_x509(&x509_crt[i], crt_list[i], 0);
+          if (ret < 0)
+            {
+              fprintf(stderr, "*** Error importing crt to pcert: %s\n",
+                gnutls_strerror(ret));
+              exit(1);
+            }
+          gnutls_x509_crt_deinit(crt_list[i]);
+        }
 
       unload_file (data);
 
+      ret = gnutls_privkey_init(&x509_key);
+      if (ret < 0)
+         {
+           fprintf (stderr, "*** Error initializing key: %s\n",
+                    gnutls_strerror (ret));
+           exit (1);
+         }
+
       if (strncmp (x509_keyfile, "pkcs11:", 7) == 0)
         {
           gnutls_pkcs11_privkey_init (&pkcs11_key);
@@ -245,6 +266,14 @@ load_keys (void)
                        gnutls_strerror (ret));
               exit (1);
             }
+
+          ret = gnutls_privkey_import_pkcs11( x509_key, pkcs11_key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
+          if (ret < 0)
+            {
+              fprintf (stderr, "*** Error loading url: %s\n",
+                       gnutls_strerror (ret));
+              exit (1);
+            }
         }
       else
         {
@@ -255,10 +284,10 @@ load_keys (void)
               exit (1);
             }
 
-          gnutls_x509_privkey_init (&x509_key);
+          gnutls_x509_privkey_init (&tmp_key);
 
           ret =
-            gnutls_x509_privkey_import (x509_key, &data, GNUTLS_X509_FMT_PEM);
+            gnutls_x509_privkey_import (tmp_key, &data, GNUTLS_X509_FMT_PEM);
           if (ret < 0)
             {
               fprintf (stderr, "*** Error loading key file: %s\n",
@@ -266,25 +295,43 @@ load_keys (void)
               exit (1);
             }
 
+          ret = gnutls_privkey_import_x509( x509_key, tmp_key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
+          if (ret < 0)
+            {
+              fprintf (stderr, "*** Error loading url: %s\n",
+                       gnutls_strerror (ret));
+              exit (1);
+            }
+
           unload_file (data);
         }
 
       fprintf (stdout, "Processed %d client X.509 certificates...\n",
                x509_crt_size);
     }
+
+
 #ifdef ENABLE_OPENPGP
+  if (info.pgp_subkey != NULL)
+    {
+      get_keyid (keyid, info.pgp_subkey);
+    }
+
   if (pgp_certfile != NULL && pgp_keyfile != NULL)
     {
+      gnutls_openpgp_crt_t tmp_pgp_crt;
+
       data = load_file (pgp_certfile);
       if (data.data == NULL)
         {
           fprintf (stderr, "*** Error loading PGP cert file.\n");
           exit (1);
         }
-      gnutls_openpgp_crt_init (&pgp_crt);
+
+      gnutls_openpgp_crt_init (&tmp_pgp_crt);
 
       ret =
-        gnutls_openpgp_crt_import (pgp_crt, &data, GNUTLS_OPENPGP_FMT_BASE64);
+        gnutls_pcert_import_openpgp_raw (&pgp_crt, &data, GNUTLS_OPENPGP_FMT_BASE64, info.pgp_subkey!=NULL?keyid:NULL, 0);
       if (ret < 0)
         {
           fprintf (stderr,
@@ -292,10 +339,17 @@ load_keys (void)
                    gnutls_strerror (ret));
           exit (1);
         }
-
-
       unload_file (data);
 
+      ret = gnutls_privkey_init(&pgp_key);
+      if (ret < 0)
+         {
+           fprintf (stderr, "*** Error initializing key: %s\n",
+                    gnutls_strerror (ret));
+           exit (1);
+         }
+
       if (strncmp (pgp_keyfile, "pkcs11:", 7) == 0)
         {
           gnutls_pkcs11_privkey_init (&pkcs11_key);
@@ -307,9 +361,18 @@ load_keys (void)
                        gnutls_strerror (ret));
               exit (1);
             }
+
+          ret = gnutls_privkey_import_pkcs11( pgp_key, pkcs11_key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
+          if (ret < 0)
+            {
+              fprintf (stderr, "*** Error loading url: %s\n",
+                       gnutls_strerror (ret));
+              exit (1);
+            }
         }
       else
         {
+          gnutls_openpgp_privkey_t tmp_pgp_key;
 
           data = load_file (pgp_keyfile);
           if (data.data == NULL)
@@ -318,10 +381,10 @@ load_keys (void)
               exit (1);
             }
 
-          gnutls_openpgp_privkey_init (&pgp_key);
+          gnutls_openpgp_privkey_init (&tmp_pgp_key);
 
           ret =
-            gnutls_openpgp_privkey_import (pgp_key, &data,
+            gnutls_openpgp_privkey_import (tmp_pgp_key, &data,
                                            GNUTLS_OPENPGP_FMT_BASE64, NULL,
                                            0);
           if (ret < 0)
@@ -332,40 +395,31 @@ load_keys (void)
               exit (1);
             }
 
-          unload_file (data);
-        }
-
-      if (info.pgp_subkey != NULL)
-        {
-          gnutls_openpgp_keyid_t keyid;
-
-          if (strcasecmp (info.pgp_subkey, "auto") == 0)
+          if (info.pgp_subkey != NULL)
             {
-              ret = gnutls_openpgp_crt_get_auth_subkey (pgp_crt, keyid, 1);
+              ret =
+                gnutls_openpgp_privkey_set_preferred_key_id (tmp_pgp_key, keyid);
               if (ret < 0)
                 {
                   fprintf (stderr,
-                           "*** Error setting preferred sub key id (%s): %s\n",
-                           info.pgp_subkey, gnutls_strerror (ret));
+                      "*** Error setting preferred sub key id (%s): %s\n",
+                      info.pgp_subkey, gnutls_strerror (ret));
                   exit (1);
                 }
             }
-          else
-            get_keyid (keyid, info.pgp_subkey);
 
-          ret = gnutls_openpgp_crt_set_preferred_key_id (pgp_crt, keyid);
-          if (ret >= 0)
-            ret =
-              gnutls_openpgp_privkey_set_preferred_key_id (pgp_key, keyid);
+          ret = gnutls_privkey_import_openpgp( pgp_key, tmp_pgp_key, GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE);
           if (ret < 0)
             {
-              fprintf (stderr,
-                       "*** Error setting preferred sub key id (%s): %s\n",
-                       info.pgp_subkey, gnutls_strerror (ret));
+              fprintf (stderr, "*** Error loading url: %s\n",
+                       gnutls_strerror (ret));
               exit (1);
             }
+
+          unload_file (data);
         }
 
+
       fprintf (stdout, "Processed 1 client PGP certificate...\n");
     }
 #endif
@@ -401,10 +455,11 @@ static int
 cert_callback (gnutls_session_t session,
                const gnutls_datum_t * req_ca_rdn, int nreqs,
                const gnutls_pk_algorithm_t * sign_algos,
-               int sign_algos_length, gnutls_retr2_st * st)
+               int sign_algos_length, gnutls_pcert_st **pcert,
+               unsigned int *pcert_length, gnutls_privkey_t * pkey)
 {
   char issuer_dn[256];
-  int i, ret;
+  int i, ret, cert_type;
   size_t len;
 
   if (verbose)
@@ -434,62 +489,17 @@ cert_callback (gnutls_session_t session,
    * supported by the server.
    */
 
-  st->cert_type = gnutls_certificate_type_get (session);
+  cert_type = gnutls_certificate_type_get (session);
 
-  st->ncerts = 0;
+  *pcert_length = 0;
 
-  if (st->cert_type == GNUTLS_CRT_X509)
+  if (cert_type == GNUTLS_CRT_X509)
     {
-      gnutls_sign_algorithm_t cert_algo, req_algo;
-      int i, match = 0;
-
       if (x509_crt_size > 0)
         {
-          ret = gnutls_x509_crt_get_signature_algorithm (x509_crt[0]);
-          if (ret < 0)
-            {
-              /* error reading signature algorithm */
-              return -1;
-            }
-          cert_algo = ret;
-
-          i = 0;
-          do
-            {
-              ret =
-                gnutls_sign_algorithm_get_requested (session, i, &req_algo);
-              if (ret >= 0 && cert_algo == req_algo)
-                {
-                  match = 1;
-                  break;
-                }
-
-              /* server has not requested anything specific */
-              if (i == 0 && ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
-                {
-                  match = 1;
-                  break;
-                }
-              i++;
-            }
-          while (ret >= 0);
-
-          if (match == 0)
-            {
-              printf
-                ("- Could not find a suitable certificate to send to server\n");
-              return -1;
-            }
-
           if (x509_key != NULL)
             {
-              st->key.x509 = x509_key;
-              st->key_type = GNUTLS_PRIVKEY_X509;
-            }
-          else if (pkcs11_key != NULL)
-            {
-              st->key.pkcs11 = pkcs11_key;
-              st->key_type = GNUTLS_PRIVKEY_PKCS11;
+              *pkey = x509_key;
             }
           else
             {
@@ -497,48 +507,23 @@ cert_callback (gnutls_session_t session,
               return -1;
             }
 
-          st->ncerts = x509_crt_size;
-
-          st->cert.x509 = x509_crt;
-
-          st->deinit_all = 0;
-
-          return 0;
+          *pcert_length = x509_crt_size;
+          *pcert = x509_crt;
         }
 
     }
-  else if (st->cert_type == GNUTLS_CRT_OPENPGP)
+  else if (cert_type == GNUTLS_CRT_OPENPGP)
     {
-      if (pgp_crt != NULL)
+      if (pgp_key != NULL)
         {
+          *pkey = pgp_key;
 
-          if (pgp_key != NULL)
-            {
-              st->key.pgp = pgp_key;
-              st->key_type = GNUTLS_PRIVKEY_OPENPGP;
-            }
-          else if (pkcs11_key != NULL)
-            {
-              st->key.pkcs11 = pkcs11_key;
-              st->key_type = GNUTLS_PRIVKEY_PKCS11;
-            }
-          else
-            {
-              printf ("- Could not find a suitable key to send to server\n");
-              return -1;
-            }
-
-          st->ncerts = 1;
-
-          st->cert.pgp = pgp_crt;
-
-          st->deinit_all = 0;
-
-          return 0;
+          *pcert_length = 1;
+          *pcert = &pgp_crt;
         }
     }
 
-  printf ("- Successfully sent %d certificate(s) to server.\n", st->ncerts);
+  printf ("- Successfully sent %u certificate(s) to server.\n", *pcert_length);
   return 0;
 
 }
@@ -586,7 +571,7 @@ init_tls_session (const char *hostname)
     gnutls_credentials_set (session, GNUTLS_CRD_PSK, psk_cred);
   gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred);
 
-  gnutls_certificate_set_retrieve_function (xcred, cert_callback);
+  gnutls_certificate_set_retrieve_function2 (xcred, cert_callback);
   gnutls_certificate_set_verify_function (xcred, cert_verify_callback);
   gnutls_certificate_set_verify_flags (xcred, 0);
 
@@ -741,12 +726,6 @@ main (int argc, char **argv)
       exit (1);
     }
 
-  if ((ret = gnutls_global_init_extra ()) < 0)
-    {
-      fprintf (stderr, "global_init_extra: %s\n", gnutls_strerror (ret));
-      exit (1);
-    }
-
   pkcs11_common ();
   gaa_parser (argc, argv);
   if (hostname == NULL)
@@ -1490,3 +1469,4 @@ socket_open (socket_st * hd, const char *hostname, const char *service)
 
   return;
 }
+
index cf6cc2ba9539ae48d0a4c8a18ca0bc25676f2d01..4ee44c14e77df629f3cb0e6bbeb49fb9383ed956 100644 (file)
@@ -115,7 +115,8 @@ static int
 cert_callback (gnutls_session_t session,
                const gnutls_datum_t * req_ca_rdn, int nreqs,
                const gnutls_pk_algorithm_t * sign_algos,
-               int sign_algos_length, gnutls_retr2_st * st)
+               int sign_algos_length, gnutls_pcert_st ** pcert,
+               unsigned int* pcert_length, gnutls_privkey_t *pkey)
 {
   int result;
   gnutls_x509_dn_t dn;
@@ -199,7 +200,7 @@ client (void)
    */
   gnutls_certificate_set_x509_trust_mem (xcred, &ca, GNUTLS_X509_FMT_PEM);
 
-  gnutls_certificate_set_retrieve_function (xcred, cert_callback);
+  gnutls_certificate_set_retrieve_function2 (xcred, cert_callback);
 
   /* Initialize TLS session
    */