* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
#ifdef USE_GNUTLS
-#include <gnutls/abstract.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
# define HAS_ALPN
# endif
# endif
-
-# if (GNUTLS_VERSION_NUMBER >= 0x03020d)
-# define HAS_OCSP
-# endif
-#endif
-
-#ifdef HAS_OCSP
-# include <gnutls/ocsp.h>
#endif
/*
gnutls_record_get_direction(session)?
ssl_connect_2_writing:ssl_connect_2_reading;
continue;
+ if(nonblocking)
+ return CURLE_OK;
}
else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
const char *strerr = NULL;
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");
/* lowat must be set to zero when using custom push and pull functions. */
gnutls_transport_set_lowat(session, 0);
-#ifdef HAS_OCSP
- if(data->set.ssl.verifystatus) {
- rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
- if(rc != GNUTLS_E_SUCCESS) {
- failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
- return CURLE_SSL_CONNECT_ERROR;
- }
- }
-#endif
-
/* This might be a reconnect, so we check for a session ID in the cache
to speed up things */
return CURLE_OK;
}
-static CURLcode pkp_pin_peer_pubkey(gnutls_x509_crt_t cert,
- const char *pinnedpubkey)
-{
- /* Scratch */
- size_t len1 = 0, len2 = 0;
- unsigned char *buff1 = NULL;
-
- gnutls_pubkey_t key = NULL;
-
- /* Result is returned to caller */
- int ret = 0;
- CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
-
- /* if a path wasn't specified, don't pin */
- if(NULL == pinnedpubkey)
- return CURLE_OK;
-
- if(NULL == cert)
- return result;
-
- do {
- /* Begin Gyrations to get the public key */
- gnutls_pubkey_init(&key);
-
- ret = gnutls_pubkey_import_x509(key, cert, 0);
- if(ret < 0)
- break; /* failed */
-
- ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
- if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
- break; /* failed */
-
- buff1 = malloc(len1);
- if(NULL == buff1)
- break; /* failed */
-
- len2 = len1;
-
- ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
- if(ret < 0 || len1 != len2)
- break; /* failed */
-
- /* End Gyrations */
-
- /* The one good exit point */
- result = Curl_pin_peer_pubkey(pinnedpubkey, buff1, len1);
- } while(0);
-
- if(NULL != key)
- gnutls_pubkey_deinit(key);
-
- Curl_safefree(buff1);
-
- return result;
-}
-
static Curl_recv gtls_recv;
static Curl_send gtls_send;
struct SessionHandle *data = conn->data;
gnutls_session_t session = conn->ssl[sockindex].session;
int rc;
- bool incache;
+ int incache;
void *ssl_sessionid;
#ifdef HAS_ALPN
gnutls_datum_t proto;
else
infof(data, "\t server certificate verification SKIPPED\n");
-#ifdef HAS_OCSP
- if(data->set.ssl.verifystatus) {
- if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
- 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, "SSL server certificate status verification OK\n");
- }
- else
- infof(data, "SSL server certificate status verification SKIPPED\n");
-#endif
-
/* initialize an X.509 certificate structure. */
gnutls_x509_crt_init(&x509_cert);
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);
- gnutls_x509_crt_deinit(x509_issuer);
unload_file(issuerp);
if(rc <= 0) {
failf(data, "server certificate issuer check failed (IssuerCert: %s)",
data->set.ssl.issuercert?data->set.ssl.issuercert:"none");
- gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_ISSUER_ERROR;
}
infof(data,"\t server certificate issuer check OK (Issuer Cert: %s)\n",
if(certclock == (time_t)-1) {
if(data->set.ssl.verifypeer) {
failf(data, "server cert expiration date verify failed");
- gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_CONNECT_ERROR;
}
else
if(certclock < time(NULL)) {
if(data->set.ssl.verifypeer) {
failf(data, "server certificate expiration date has passed.");
- gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
}
else
if(certclock == (time_t)-1) {
if(data->set.ssl.verifypeer) {
failf(data, "server cert activation date verify failed");
- gnutls_x509_crt_deinit(x509_cert);
return CURLE_SSL_CONNECT_ERROR;
}
else
if(certclock > time(NULL)) {
if(data->set.ssl.verifypeer) {
failf(data, "server certificate not activated yet.");
- gnutls_x509_crt_deinit(x509_cert);
return CURLE_PEER_FAILED_VERIFICATION;
}
else
infof(data, "\t server certificate activation date OK\n");
}
- ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
- if(ptr) {
- result = pkp_pin_peer_pubkey(x509_cert, ptr);
- if(result != CURLE_OK) {
- failf(data, "SSL: public key does not match pinned public key!");
- gnutls_x509_crt_deinit(x509_cert);
- return result;
- }
- }
-
/* Show:
- ciphers used
conn->negnpn = NPN_HTTP1_1;
}
}
- else if(connssl->asked_for_h2) {
+ else {
infof(data, "ALPN, server did not agree to a protocol\n");
}
}
int sockindex)
{
- CURLcode result;
+ CURLcode retcode;
bool done = FALSE;
- result = gtls_connect_common(conn, sockindex, FALSE, &done);
- if(result)
- return result;
+ retcode = gtls_connect_common(conn, sockindex, FALSE, &done);
+ if(retcode)
+ return retcode;
DEBUGASSERT(done);
if(ret == GNUTLS_E_REHANDSHAKE) {
/* BLOCKING call, this is bad but a work-around for now. Fixing this "the
proper way" takes a whole lot of work. */
- CURLcode result = handshake(conn, num, FALSE, FALSE);
- if(result)
+ CURLcode rc = handshake(conn, num, FALSE, FALSE);
+ if(rc)
/* handshake() writes error message on its own */
- *curlcode = result;
+ *curlcode = rc;
else
*curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
return -1;
return snprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
}
-#ifndef USE_GNUTLS_NETTLE
-static int Curl_gtls_seed(struct SessionHandle *data)
+int Curl_gtls_seed(struct SessionHandle *data)
{
/* we have the "SSL is seeded" boolean static to prevent multiple
time-consuming seedings in vain */
static bool ssl_seeded = FALSE;
/* Quickly add a bit of entropy */
+#ifndef USE_GNUTLS_NETTLE
gcry_fast_random_poll();
+#endif
if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
data->set.str[STRING_SSL_EGDSOCKET]) {
}
return 0;
}
-#endif
-/* data might be NULL! */
-int Curl_gtls_random(struct SessionHandle *data,
- unsigned char *entropy,
- size_t length)
+void Curl_gtls_random(struct SessionHandle *data,
+ unsigned char *entropy,
+ size_t length)
{
#if defined(USE_GNUTLS_NETTLE)
(void)data;
gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
#elif defined(USE_GNUTLS)
- if(data)
- Curl_gtls_seed(data); /* Initiate the seed if not already done */
+ Curl_gtls_seed(data); /* Initiate the seed if not already done */
gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
#endif
- return 0;
}
void Curl_gtls_md5sum(unsigned char *tmp, /* input */
#endif
}
-bool Curl_gtls_cert_status_request(void)
-{
-#ifdef HAS_OCSP
- return TRUE;
-#else
- return FALSE;
-#endif
-}
-
#endif /* USE_GNUTLS */