Fixed fetch_remote_credentials(), got working tool/testcli --> tool/testsrv
authorRick van Rein <rick@openfortress.nl>
Fri, 17 Jun 2016 10:00:16 +0000 (11:00 +0100)
committerRick van Rein <rick@openfortress.nl>
Fri, 17 Jun 2016 10:00:16 +0000 (11:00 +0100)
src/donai.h
src/starttls.c

index 2cc7b4f..845e1c7 100644 (file)
@@ -73,6 +73,12 @@ typedef struct userdomain selector_t;  /* userlen<0 should be read as userlen==0
 
 
 
+/* Setup a clean DBT data handle, so it can withstand dbt_free().
+ */
+static inline void dbt_init_empty (DBT *dbt) {
+       memset (dbt, 0, sizeof (DBT));
+}
+
 /* Setup a DBT data handle to point to a pre-allocated, fixed-size
  * data buffer that will be used throughout the use of the handle.
  * Cleanup is not necessary, but the buffer must not be cleared
@@ -102,7 +108,9 @@ static inline void dbt_init_malloc (DBT *dbt) {
  */
 static inline void dbt_free (DBT *dbt) {
        /* assert (dbt->flags & DB_DBT_MALLOC); */
-       free (dbt->data);
+       if (dbt->data) {
+               free (dbt->data);
+       }
        dbt->data = NULL;
 }
 
index 5249292..15acce7 100644 (file)
@@ -1928,10 +1928,10 @@ static gtls_error fetch_remote_credentials (struct command *cmd) {
 
        // Did we run this before?  Then cleanup.
        cleanup_any_remote_credentials (cmd);
-       // Prepare default return values
-       memset (cmd->remote_cert, 0, sizeof (cmd->remote_cert));
+       //INVOLVES// memset (cmd->remote_cert, 0, sizeof (cmd->remote_cert));
+       //INVOLVES// cmd->remote_cert_count = 0;
+       // Prepare as-yet-unset default return values
        cmd->remote_auth_type = -1;
-       cmd->remote_cert_count = 0;
        cmd->remote_cert_raw = NULL;
        //
        // Obtain the authentication type for the peer
@@ -2007,26 +2007,36 @@ static gtls_error fetch_remote_credentials (struct command *cmd) {
        if (cmd->remote_cert_type == GNUTLS_CRT_X509) {
                // Retrieve the AuthorityKeyIdentifier from last (or semi-last)
                uint8_t id [100];
-               size_t idsz = sizeof (id);
+               size_t idsz;
                DBT rootca;
                DBT anchor;
                DBC *crs_trust = NULL;
                int db_errno;
                gnutls_datum_t anchor_gnutls;
                gnutls_x509_crt_t dbroot;
+               dbt_init_empty (&rootca);
+               dbt_init_empty (&anchor);
+               idsz = sizeof (id);
                gtls_errno = gnutls_x509_crt_get_authority_key_id (
                        cmd->remote_cert [cmd->remote_cert_count-1],
                        id, &idsz,
                        NULL);
-               if ((gtls_errno == GNUTLS_E_X509_UNSUPPORTED_EXTENSION) && (cmd->remote_cert_count > 1)) {
-                       // Assume the last is a root cert, as it lacks authid
-                       idsz = sizeof (id);
-                       gnutls_x509_crt_deinit (
-                               cmd->remote_cert [--cmd->remote_cert_count]);
-                       gtls_errno = gnutls_x509_crt_get_authority_key_id (
-                               cmd->remote_cert [cmd->remote_cert_count-1],
-                               id, &idsz,
-                               NULL);
+               if (gtls_errno == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+                       // Only retry if the last is a signer, possibly CA
+                       if (cmd->remote_cert_count == 1) {
+                               // Permit self-signed certificate evaluation
+                               gtls_errno = GNUTLS_E_SUCCESS;
+                       } else if (cmd->remote_cert_count > 1) {
+                               // Assume the last is a root cert, as it lacks authid
+                               gnutls_x509_crt_deinit (
+                                       cmd->remote_cert [--cmd->remote_cert_count]);
+                               cmd->remote_cert [cmd->remote_cert_count] = NULL;
+                               idsz = sizeof (id);
+                               gtls_errno = gnutls_x509_crt_get_authority_key_id (
+                                       cmd->remote_cert [cmd->remote_cert_count-1],
+                                       id, &idsz,
+                                       NULL);
+                       }
                }
                if (gtls_errno != GNUTLS_E_SUCCESS) {
                        goto cleanup;
@@ -2094,7 +2104,7 @@ static gtls_error fetch_remote_credentials (struct command *cmd) {
                        crs_trust = NULL;
                }
                dbt_free (&anchor);
-               dbt_free (&rootca);
+               // No dbt_free (&rootca) because it is set to a fixed buffer
                if (db_errno != DB_NOTFOUND) {
                        goto cleanup;
                }