Revert "Update to 7.44.0"
[platform/upstream/curl.git] / lib / vtls / gtls.c
index c54dfc1..550a0ed 100644 (file)
@@ -39,7 +39,6 @@
 #ifdef USE_GNUTLS_NETTLE
 #include <gnutls/crypto.h>
 #include <nettle/md5.h>
-#include <nettle/sha2.h>
 #else
 #include <gcrypt.h>
 #endif
@@ -54,8 +53,9 @@
 #include "select.h"
 #include "rawstr.h"
 #include "warnless.h"
-#include "x509asn1.h"
-#include "curl_printf.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
 #include "curl_memory.h"
 /* The last #include file should be: */
 #include "memdebug.h"
@@ -92,17 +92,16 @@ static bool gtls_inited = FALSE;
 #    define GNUTLS_MAPS_WINSOCK_ERRORS 1
 #  endif
 
-#  if (GNUTLS_VERSION_NUMBER >= 0x030200)
-#    define HAS_ALPN
+#  ifdef USE_NGHTTP2
+#    undef HAS_ALPN
+#    if (GNUTLS_VERSION_NUMBER >= 0x030200)
+#      define HAS_ALPN
+#    endif
 #  endif
 
 #  if (GNUTLS_VERSION_NUMBER >= 0x03020d)
 #    define HAS_OCSP
 #  endif
-
-#  if (GNUTLS_VERSION_NUMBER >= 0x030306)
-#    define HAS_CAPATH
-#  endif
 #endif
 
 #ifdef HAS_OCSP
@@ -213,7 +212,7 @@ static void showtime(struct SessionHandle *data,
 
   snprintf(data->state.buffer,
            BUFSIZE,
-           "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
+           "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT\n",
            text,
            Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
            tm->tm_mday,
@@ -232,7 +231,7 @@ static gnutls_datum_t load_file (const char *file)
   long filelen;
   void *ptr;
 
-  if(!(f = fopen(file, "rb")))
+  if(!(f = fopen(file, "r")))
     return loaded_file;
   if(fseek(f, 0, SEEK_END) != 0
      || (filelen = ftell(f)) < 0
@@ -328,8 +327,7 @@ static CURLcode handshake(struct connectdata *conn,
       if(strerr == NULL)
         strerr = gnutls_strerror(rc);
 
-      infof(data, "gnutls_handshake() warning: %s\n", strerr);
-      continue;
+      failf(data, "gnutls_handshake() warning: %s", strerr);
     }
     else if(rc < 0) {
       const char *strerr = NULL;
@@ -402,6 +400,10 @@ gtls_connect_step1(struct connectdata *conn,
   const char* prioritylist;
   const char *err = NULL;
 #endif
+#ifdef HAS_ALPN
+  int protocols_size = 2;
+  gnutls_datum_t protocols[2];
+#endif
 
   if(conn->ssl[sockindex].state == ssl_connection_complete)
     /* to make us tolerant against being called more than once for the
@@ -469,24 +471,6 @@ gtls_connect_step1(struct connectdata *conn,
             rc, data->set.ssl.CAfile);
   }
 
-#ifdef HAS_CAPATH
-  if(data->set.ssl.CApath) {
-    /* set the trusted CA cert directory */
-    rc = gnutls_certificate_set_x509_trust_dir(conn->ssl[sockindex].cred,
-                                                data->set.ssl.CApath,
-                                                GNUTLS_X509_FMT_PEM);
-    if(rc < 0) {
-      infof(data, "error reading ca cert file %s (%s)\n",
-            data->set.ssl.CAfile, gnutls_strerror(rc));
-      if(data->set.ssl.verifypeer)
-        return CURLE_SSL_CACERT_BADFILE;
-    }
-    else
-      infof(data, "found %d certificates in %s\n",
-            rc, data->set.ssl.CApath);
-  }
-#endif
-
   if(data->set.ssl.CRLfile) {
     /* set the CRL list file */
     rc = gnutls_certificate_set_x509_crl_file(conn->ssl[sockindex].cred,
@@ -633,25 +617,20 @@ gtls_connect_step1(struct connectdata *conn,
 #endif
 
 #ifdef HAS_ALPN
-  if(data->set.ssl_enable_alpn) {
-    int cur = 0;
-    gnutls_datum_t protocols[2];
-
-#ifdef USE_NGHTTP2
-    if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
-      protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
-      protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
-      cur++;
-      infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
+  if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
+    if(data->set.ssl_enable_alpn) {
+      protocols[0].data = NGHTTP2_PROTO_VERSION_ID;
+      protocols[0].size = NGHTTP2_PROTO_VERSION_ID_LEN;
+      protocols[1].data = ALPN_HTTP_1_1;
+      protocols[1].size = ALPN_HTTP_1_1_LENGTH;
+      gnutls_alpn_set_protocols(session, protocols, protocols_size, 0);
+      infof(data, "ALPN, offering %s, %s\n", NGHTTP2_PROTO_VERSION_ID,
+            ALPN_HTTP_1_1);
+      connssl->asked_for_h2 = TRUE;
+    }
+    else {
+      infof(data, "SSL, can't negotiate HTTP/2.0 without ALPN\n");
     }
-#endif
-
-    protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
-    protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
-    cur++;
-    infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
-
-    gnutls_alpn_set_protocols(session, protocols, cur, 0);
   }
 #endif
 
@@ -673,21 +652,13 @@ gtls_connect_step1(struct connectdata *conn,
   if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) {
     rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
                                 conn->ssl[sockindex].srp_client_cred);
-    if(rc != GNUTLS_E_SUCCESS) {
+    if(rc != GNUTLS_E_SUCCESS)
       failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
-      return CURLE_SSL_CONNECT_ERROR;
-    }
   }
   else
 #endif
-  {
     rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
                                 conn->ssl[sockindex].cred);
-    if(rc != GNUTLS_E_SUCCESS) {
-      failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
-      return CURLE_SSL_CONNECT_ERROR;
-    }
-  }
 
   /* set the connection handle (file descriptor for the socket) */
   gnutls_transport_set_ptr(session,
@@ -789,8 +760,8 @@ gtls_connect_step3(struct connectdata *conn,
 {
   unsigned int cert_list_size;
   const gnutls_datum_t *chainp;
-  unsigned int verify_status = 0;
-  gnutls_x509_crt_t x509_cert, x509_issuer;
+  unsigned int verify_status;
+  gnutls_x509_crt_t x509_cert,x509_issuer;
   gnutls_datum_t issuerp;
   char certbuf[256] = ""; /* big enough? */
   size_t size;
@@ -808,16 +779,6 @@ gtls_connect_step3(struct connectdata *conn,
 #endif
   CURLcode result = CURLE_OK;
 
-  gnutls_protocol_t version = gnutls_protocol_get_version(session);
-
-  /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
-  ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
-                                     gnutls_cipher_get(session),
-                                     gnutls_mac_get(session));
-
-  infof(data, "SSL connection using %s / %s\n",
-        gnutls_protocol_get_name(version), ptr);
-
   /* This function will return the peer's raw certificate (chain) as sent by
      the peer. These certificates are in raw format (DER encoded for
      X.509). In case of a X.509 then a certificate list may be present. The
@@ -848,23 +809,6 @@ gtls_connect_step3(struct connectdata *conn,
     infof(data, "\t common name: WARNING couldn't obtain\n");
   }
 
-  if(data->set.ssl.certinfo && chainp) {
-    unsigned int i;
-
-    result = Curl_ssl_init_certinfo(data, cert_list_size);
-    if(result)
-      return result;
-
-    for(i = 0; i < cert_list_size; i++) {
-      const char *beg = (const char *) chainp[i].data;
-      const char *end = beg + chainp[i].size;
-
-      result = Curl_extract_certinfo(conn, i, beg, end);
-      if(result)
-        return result;
-    }
-  }
-
   if(data->set.ssl.verifypeer) {
     /* This function will try to verify the peer's certificate and return its
        status (trusted, invalid etc.). The value of status should be one or
@@ -899,106 +843,18 @@ gtls_connect_step3(struct connectdata *conn,
 #ifdef HAS_OCSP
   if(data->set.ssl.verifystatus) {
     if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
-      gnutls_datum_t status_request;
-      gnutls_ocsp_resp_t ocsp_resp;
-
-      gnutls_ocsp_cert_status_t status;
-      gnutls_x509_crl_reason_t reason;
-
-      rc = gnutls_ocsp_status_request_get(session, &status_request);
-
-      infof(data, "\t server certificate status verification FAILED\n");
-
-      if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
-        failf(data, "No OCSP response received");
-        return CURLE_SSL_INVALIDCERTSTATUS;
-      }
-
-      if(rc < 0) {
-        failf(data, "Invalid OCSP response received");
-        return CURLE_SSL_INVALIDCERTSTATUS;
-      }
-
-      gnutls_ocsp_resp_init(&ocsp_resp);
-
-      rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
-      if(rc < 0) {
-        failf(data, "Invalid OCSP response received");
-        return CURLE_SSL_INVALIDCERTSTATUS;
-      }
-
-      rc = gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
-                                       &status, NULL, NULL, NULL, &reason);
-
-      switch(status) {
-      case GNUTLS_OCSP_CERT_GOOD:
-        break;
-
-      case GNUTLS_OCSP_CERT_REVOKED: {
-        const char *crl_reason;
-
-        switch(reason) {
-          default:
-          case GNUTLS_X509_CRLREASON_UNSPECIFIED:
-            crl_reason = "unspecified reason";
-            break;
-
-          case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
-            crl_reason = "private key compromised";
-            break;
-
-          case GNUTLS_X509_CRLREASON_CACOMPROMISE:
-            crl_reason = "CA compromised";
-            break;
-
-          case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
-            crl_reason = "affiliation has changed";
-            break;
-
-          case GNUTLS_X509_CRLREASON_SUPERSEDED:
-            crl_reason = "certificate superseded";
-            break;
-
-          case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
-            crl_reason = "operation has ceased";
-            break;
-
-          case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
-            crl_reason = "certificate is on hold";
-            break;
-
-          case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
-            crl_reason = "will be removed from delta CRL";
-            break;
-
-          case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
-            crl_reason = "privilege withdrawn";
-            break;
-
-          case GNUTLS_X509_CRLREASON_AACOMPROMISE:
-            crl_reason = "AA compromised";
-            break;
-        }
-
-        failf(data, "Server certificate was revoked: %s", crl_reason);
-        break;
-      }
-
-      default:
-      case GNUTLS_OCSP_CERT_UNKNOWN:
-        failf(data, "Server certificate status is unknown");
-        break;
-      }
-
-      gnutls_ocsp_resp_deinit(ocsp_resp);
+      if(verify_status & GNUTLS_CERT_REVOKED)
+        failf(data, "SSL server certificate was REVOKED\n");
+      else
+        failf(data, "SSL server certificate status verification FAILED");
 
       return CURLE_SSL_INVALIDCERTSTATUS;
     }
     else
-      infof(data, "\t server certificate status verification OK\n");
+      infof(data, "SSL server certificate status verification OK\n");
   }
   else
-    infof(data, "\t server certificate status verification SKIPPED\n");
+    infof(data, "SSL server certificate status verification SKIPPED\n");
 #endif
 
   /* initialize an X.509 certificate structure. */
@@ -1013,7 +869,7 @@ gtls_connect_step3(struct connectdata *conn,
     gnutls_x509_crt_init(&x509_issuer);
     issuerp = load_file(data->set.ssl.issuercert);
     gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
-    rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
+    rc = gnutls_x509_crt_check_issuer(x509_cert,x509_issuer);
     gnutls_x509_crt_deinit(x509_issuer);
     unload_file(issuerp);
     if(rc <= 0) {
@@ -1022,7 +878,7 @@ gtls_connect_step3(struct connectdata *conn,
       gnutls_x509_crt_deinit(x509_cert);
       return CURLE_SSL_ISSUER_ERROR;
     }
-    infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
+    infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n",
           data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
   }
 
@@ -1162,6 +1018,7 @@ gtls_connect_step3(struct connectdata *conn,
 
   /* Show:
 
+  - ciphers used
   - subject
   - start date
   - expire date
@@ -1201,6 +1058,14 @@ gtls_connect_step3(struct connectdata *conn,
   /* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
   infof(data, "\t compression: %s\n", ptr);
 
+  /* the name of the cipher used. ie 3DES. */
+  ptr = gnutls_cipher_get_name(gnutls_cipher_get(session));
+  infof(data, "\t cipher: %s\n", ptr);
+
+  /* the MAC algorithms name. ie SHA1 */
+  ptr = gnutls_mac_get_name(gnutls_mac_get(session));
+  infof(data, "\t MAC: %s\n", ptr);
+
 #ifdef HAS_ALPN
   if(data->set.ssl_enable_alpn) {
     rc = gnutls_alpn_get_selected_protocol(session, &proto);
@@ -1208,21 +1073,19 @@ gtls_connect_step3(struct connectdata *conn,
       infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
           proto.data);
 
-#ifdef USE_NGHTTP2
       if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
-         !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
-                 NGHTTP2_PROTO_VERSION_ID_LEN)) {
-        conn->negnpn = CURL_HTTP_VERSION_2_0;
+        memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
+        NGHTTP2_PROTO_VERSION_ID_LEN) == 0) {
+        conn->negnpn = NPN_HTTP2;
       }
-      else
-#endif
-      if(proto.size == ALPN_HTTP_1_1_LENGTH &&
-         !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
-        conn->negnpn = CURL_HTTP_VERSION_1_1;
+      else if(proto.size == ALPN_HTTP_1_1_LENGTH && memcmp(ALPN_HTTP_1_1,
+          proto.data, ALPN_HTTP_1_1_LENGTH) == 0) {
+        conn->negnpn = NPN_HTTP1_1;
       }
     }
-    else
+    else if(connssl->asked_for_h2) {
       infof(data, "ALPN, server did not agree to a protocol\n");
+    }
   }
 #endif
 
@@ -1354,6 +1217,12 @@ static ssize_t gtls_send(struct connectdata *conn,
   return rc;
 }
 
+void Curl_gtls_close_all(struct SessionHandle *data)
+{
+  /* FIX: make the OpenSSL code more generic and use parts of it here */
+  (void)data;
+}
+
 static void close_one(struct connectdata *conn,
                       int idx)
 {
@@ -1558,25 +1427,6 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */
 #endif
 }
 
-void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
-                      size_t tmplen,
-                      unsigned char *sha256sum, /* output */
-                      size_t sha256len)
-{
-#if defined(USE_GNUTLS_NETTLE)
-  struct sha256_ctx SHA256pw;
-  sha256_init(&SHA256pw);
-  sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
-  sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
-#elif defined(USE_GNUTLS)
-  gcry_md_hd_t SHA256pw;
-  gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
-  gcry_md_write(SHA256pw, tmp, tmplen);
-  memcpy(sha256sum, gcry_md_read (SHA256pw, 0), sha256len);
-  gcry_md_close(SHA256pw);
-#endif
-}
-
 bool Curl_gtls_cert_status_request(void)
 {
 #ifdef HAS_OCSP