35 #include <gnutls/abstract.h> 36 #include <gnutls/gnutls.h> 37 #include <gnutls/x509.h> 39 #ifdef USE_GNUTLS_NETTLE 40 #include <gnutls/crypto.h> 41 #include <nettle/md5.h> 42 #include <nettle/sha2.h> 63 #ifndef GNUTLS_POINTER_TO_SOCKET_CAST 64 #define GNUTLS_POINTER_TO_SOCKET_CAST(p) \ 65 ((curl_socket_t) ((char *)(p) - (char *)NULL)) 67 #ifndef GNUTLS_SOCKET_TO_POINTER_CAST 68 #define GNUTLS_SOCKET_TO_POINTER_CAST(s) \ 69 ((void *) ((char *)NULL + (s))) 76 static void tls_log_func(
int level,
const char *
str)
78 fprintf(stderr,
"|<%d>| %s", level, str);
81 static bool gtls_inited =
FALSE;
83 #if defined(GNUTLS_VERSION_NUMBER) 84 # if (GNUTLS_VERSION_NUMBER >= 0x020c00) 85 # undef gnutls_transport_set_lowat 86 # define gnutls_transport_set_lowat(A,B) Curl_nop_stmt 87 # define USE_GNUTLS_PRIORITY_SET_DIRECT 1 89 # if (GNUTLS_VERSION_NUMBER >= 0x020c03) 90 # define GNUTLS_MAPS_WINSOCK_ERRORS 1 93 # if HAVE_GNUTLS_ALPN_SET_PROTOCOLS 97 # if HAVE_GNUTLS_OCSP_REQ_INIT 101 # if (GNUTLS_VERSION_NUMBER >= 0x030306) 107 # include <gnutls/ocsp.h> 110 struct ssl_backend_data {
111 gnutls_session_t session;
112 gnutls_certificate_credentials_t cred;
114 gnutls_srp_client_credentials_t srp_client_cred;
118 #define BACKEND connssl->backend 144 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) 145 # define gtls_EINTR 4 147 # define gtls_EAGAIN 11 148 static int gtls_mapped_sockerrno(
void)
162 static ssize_t Curl_gtls_push(
void *s,
const void *
buf,
size_t len)
164 ssize_t ret = swrite(GNUTLS_POINTER_TO_SOCKET_CAST(s), buf, len);
165 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) 167 gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
172 static ssize_t Curl_gtls_pull(
void *s,
void *buf,
size_t len)
174 ssize_t ret = sread(GNUTLS_POINTER_TO_SOCKET_CAST(s), buf, len);
175 #if defined(USE_WINSOCK) && !defined(GNUTLS_MAPS_WINSOCK_ERRORS) 177 gnutls_transport_set_global_errno(gtls_mapped_sockerrno());
182 static ssize_t Curl_gtls_push_ssl(
void *s,
const void *buf,
size_t len)
184 return gnutls_record_send((gnutls_session_t) s, buf, len);
187 static ssize_t Curl_gtls_pull_ssl(
void *s,
void *buf,
size_t len)
189 return gnutls_record_recv((gnutls_session_t) s, buf, len);
199 static int Curl_gtls_init(
void)
203 ret = gnutls_global_init()?0:1;
205 gnutls_global_set_log_function(tls_log_func);
206 gnutls_global_set_log_level(2);
213 static void Curl_gtls_cleanup(
void)
216 gnutls_global_deinit();
221 #ifndef CURL_DISABLE_VERBOSE_STRINGS 227 const struct tm *tm = &
buffer;
235 "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
244 infof(data,
"%s\n", str);
248 static gnutls_datum_t load_file(
const char *file)
251 gnutls_datum_t loaded_file = { NULL, 0 };
255 f = fopen(file,
"rb");
258 if(fseek(f, 0, SEEK_END) != 0
259 || (filelen = ftell(f)) < 0
260 || fseek(f, 0, SEEK_SET) != 0
261 || !(ptr =
malloc((
size_t)filelen)))
263 if(
fread(ptr, 1, (
size_t)filelen, f) < (
size_t)filelen) {
268 loaded_file.data =
ptr;
269 loaded_file.size = (
unsigned int)filelen;
275 static void unload_file(gnutls_datum_t data)
289 gnutls_session_t session = BACKEND->session;
301 failf(data,
"SSL connection timeout");
316 timeout_ms?timeout_ms:1000);
325 else if(timeout_ms) {
327 failf(data,
"SSL connection timeout at %ld", (
long)timeout_ms);
334 rc = gnutls_handshake(session);
336 if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
338 gnutls_record_get_direction(session)?
342 else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
343 const char *strerr = NULL;
345 if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
346 int alert = gnutls_alert_get(session);
347 strerr = gnutls_alert_get_name(alert);
351 strerr = gnutls_strerror(rc);
353 infof(data,
"gnutls_handshake() warning: %s\n", strerr);
357 const char *strerr = NULL;
359 if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
360 int alert = gnutls_alert_get(session);
361 strerr = gnutls_alert_get_name(alert);
365 strerr = gnutls_strerror(rc);
367 failf(data,
"gnutls_handshake() failed: %s", strerr);
377 static gnutls_x509_crt_fmt_t do_file_type(
const char *type)
379 if(!type || !type[0])
380 return GNUTLS_X509_FMT_PEM;
382 return GNUTLS_X509_FMT_PEM;
384 return GNUTLS_X509_FMT_DER;
388 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT 390 set_ssl_version_min_max(
int *list,
size_t list_size,
struct connectdata *conn)
395 long i = ssl_version;
396 long protocol_priority_idx = 0;
398 switch(ssl_version_max) {
400 ssl_version_max = ssl_version << 16;
407 for(; i <= (ssl_version_max >> 16) &&
408 protocol_priority_idx < list_size; ++
i) {
411 protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_0;
414 protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_1;
417 protocol_priority[protocol_priority_idx++] = GNUTLS_TLS1_2;
420 failf(data,
"GnuTLS: TLS 1.3 is not yet supported");
427 #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509" 431 #define GNUTLS_SRP "+SRP" 434 set_ssl_version_min_max(
const char **prioritylist,
struct connectdata *conn)
441 failf(data,
"GnuTLS: TLS 1.3 is not yet supported");
445 ssl_version_max = ssl_version << 16;
447 switch(ssl_version | ssl_version_max) {
449 *prioritylist = GNUTLS_CIPHERS
":-VERS-SSL3.0:-VERS-TLS-ALL:" 450 "+VERS-TLS1.0:" GNUTLS_SRP;
453 *prioritylist = GNUTLS_CIPHERS
":-VERS-SSL3.0:-VERS-TLS-ALL:" 454 "+VERS-TLS1.0:+VERS-TLS1.1:" GNUTLS_SRP;
458 *prioritylist = GNUTLS_CIPHERS
":-VERS-SSL3.0:-VERS-TLS-ALL:" 459 "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
462 *prioritylist = GNUTLS_CIPHERS
":-VERS-SSL3.0:-VERS-TLS-ALL:" 463 "+VERS-TLS1.1:" GNUTLS_SRP;
467 *prioritylist = GNUTLS_CIPHERS
":-VERS-SSL3.0:-VERS-TLS-ALL:" 468 "+VERS-TLS1.1:+VERS-TLS1.2:" GNUTLS_SRP;
472 *prioritylist = GNUTLS_CIPHERS
":-VERS-SSL3.0:-VERS-TLS-ALL:" 473 "+VERS-TLS1.2:" GNUTLS_SRP;
477 failf(data,
"GnuTLS: cannot set ssl protocol");
489 gnutls_session_t session;
492 void *transport_ptr = NULL;
493 gnutls_push_func gnutls_transport_push = NULL;
494 gnutls_pull_func gnutls_transport_pull = NULL;
496 struct in6_addr addr;
500 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT 501 static const int cipher_priority[] = {
507 GNUTLS_CIPHER_AES_128_CBC,
508 GNUTLS_CIPHER_AES_256_CBC,
509 GNUTLS_CIPHER_CAMELLIA_128_CBC,
510 GNUTLS_CIPHER_CAMELLIA_256_CBC,
511 GNUTLS_CIPHER_3DES_CBC,
513 static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
514 int protocol_priority[] = { 0, 0, 0, 0 };
516 const char *prioritylist;
517 const char *err = NULL;
532 failf(data,
"GnuTLS does not support SSLv2");
539 rc = gnutls_certificate_allocate_credentials(&BACKEND->cred);
540 if(rc != GNUTLS_E_SUCCESS) {
541 failf(data,
"gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
549 rc = gnutls_srp_allocate_client_credentials(
550 &BACKEND->srp_client_cred);
551 if(rc != GNUTLS_E_SUCCESS) {
552 failf(data,
"gnutls_srp_allocate_client_cred() failed: %s",
553 gnutls_strerror(rc));
557 rc = gnutls_srp_set_client_credentials(BACKEND->srp_client_cred,
560 if(rc != GNUTLS_E_SUCCESS) {
561 failf(data,
"gnutls_srp_set_client_cred() failed: %s",
562 gnutls_strerror(rc));
570 gnutls_certificate_set_verify_flags(BACKEND->cred,
571 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
573 rc = gnutls_certificate_set_x509_trust_file(BACKEND->cred,
575 GNUTLS_X509_FMT_PEM);
577 infof(data,
"error reading ca cert file %s (%s)\n",
583 infof(data,
"found %d certificates in %s\n", rc,
590 rc = gnutls_certificate_set_x509_trust_dir(BACKEND->cred,
592 GNUTLS_X509_FMT_PEM);
594 infof(data,
"error reading ca cert file %s (%s)\n",
600 infof(data,
"found %d certificates in %s\n",
605 #ifdef CURL_CA_FALLBACK 609 gnutls_certificate_set_x509_system_trust(BACKEND->cred);
615 rc = gnutls_certificate_set_x509_crl_file(BACKEND->cred,
617 GNUTLS_X509_FMT_PEM);
619 failf(data,
"error reading crl file %s (%s)",
624 infof(data,
"found %d CRL in %s\n",
629 init_flags = GNUTLS_CLIENT;
631 #if defined(GNUTLS_NO_TICKETS) 633 init_flags |= GNUTLS_NO_TICKETS;
636 rc = gnutls_init(&BACKEND->session, init_flags);
637 if(rc != GNUTLS_E_SUCCESS) {
638 failf(data,
"gnutls_init() failed: %d", rc);
643 session = BACKEND->session;
650 (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
651 strlen(hostname)) < 0))
652 infof(data,
"WARNING: failed to configure server name indication (SNI) " 656 rc = gnutls_set_default_priority(session);
657 if(rc != GNUTLS_E_SUCCESS)
660 #ifndef USE_GNUTLS_PRIORITY_SET_DIRECT 661 rc = gnutls_cipher_set_priority(session, cipher_priority);
662 if(rc != GNUTLS_E_SUCCESS)
668 rc = gnutls_certificate_type_set_priority(session, cert_type_priority);
669 if(rc != GNUTLS_E_SUCCESS)
673 failf(data,
"can't pass a custom cipher list to older GnuTLS" 680 protocol_priority[0] = GNUTLS_SSL3;
684 protocol_priority[0] = GNUTLS_TLS1_0;
685 protocol_priority[1] = GNUTLS_TLS1_1;
686 protocol_priority[2] = GNUTLS_TLS1_2;
693 CURLcode result = set_ssl_version_min_max(protocol_priority,
694 sizeof(protocol_priority)/
sizeof(protocol_priority[0]), conn);
700 failf(data,
"GnuTLS does not support SSLv2");
703 failf(data,
"Unrecognized parameter passed via CURLOPT_SSLVERSION");
706 rc = gnutls_protocol_set_priority(session, protocol_priority);
707 if(rc != GNUTLS_E_SUCCESS) {
708 failf(data,
"Did you pass a valid GnuTLS cipher list?");
718 prioritylist = GNUTLS_CIPHERS
":-VERS-TLS-ALL:+VERS-SSL3.0";
723 prioritylist = GNUTLS_CIPHERS
":-VERS-SSL3.0:" GNUTLS_SRP;
730 CURLcode result = set_ssl_version_min_max(&prioritylist, conn);
736 failf(data,
"GnuTLS does not support SSLv2");
739 failf(data,
"Unrecognized parameter passed via CURLOPT_SSLVERSION");
742 rc = gnutls_priority_set_direct(session, prioritylist, &err);
743 if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
744 if(!strcmp(err, GNUTLS_SRP)) {
747 int validprioritylen =
curlx_uztosi(err - prioritylist);
748 char *prioritycopy =
strdup(prioritylist);
752 infof(data,
"This GnuTLS does not support SRP\n");
755 prioritycopy[validprioritylen - 1] = 0;
756 rc = gnutls_priority_set_direct(session, prioritycopy, &err);
760 if(rc != GNUTLS_E_SUCCESS) {
761 failf(data,
"Error %d setting GnuTLS cipher list starting with %s",
775 protocols[cur].data = (
unsigned char *)NGHTTP2_PROTO_VERSION_ID;
776 protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
778 infof(data,
"ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
787 gnutls_alpn_set_protocols(session, protocols, cur, 0);
793 #if HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 794 const unsigned int supported_key_encryption_algorithms =
795 GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
796 GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
797 GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
798 GNUTLS_PKCS_USE_PBES2_AES_256;
799 rc = gnutls_certificate_set_x509_key_file2(
806 supported_key_encryption_algorithms);
807 if(rc != GNUTLS_E_SUCCESS) {
809 "error reading X.509 potentially-encrypted key file: %s",
810 gnutls_strerror(rc));
814 failf(data,
"gnutls lacks support for encrypted key files");
819 if(gnutls_certificate_set_x509_key_file(
826 failf(data,
"error reading X.509 key or certificate file");
835 rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
836 BACKEND->srp_client_cred);
837 if(rc != GNUTLS_E_SUCCESS) {
838 failf(data,
"gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
845 rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
847 if(rc != GNUTLS_E_SUCCESS) {
848 failf(data,
"gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
854 transport_ptr = conn->
proxy_ssl[sockindex].backend->session;
855 gnutls_transport_push = Curl_gtls_push_ssl;
856 gnutls_transport_pull = Curl_gtls_pull_ssl;
860 transport_ptr = GNUTLS_SOCKET_TO_POINTER_CAST(conn->
sock[sockindex]);
861 gnutls_transport_push = Curl_gtls_push;
862 gnutls_transport_pull = Curl_gtls_pull;
866 gnutls_transport_set_ptr(session, transport_ptr);
869 gnutls_transport_set_push_function(session, gnutls_transport_push);
870 gnutls_transport_set_pull_function(session, gnutls_transport_pull);
873 gnutls_transport_set_lowat(session, 0);
877 rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
878 if(rc != GNUTLS_E_SUCCESS) {
879 failf(data,
"gnutls_ocsp_status_request_enable_client() failed: %d", rc);
891 Curl_ssl_sessionid_lock(conn);
892 if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
894 gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
897 infof(data,
"SSL re-using session ID\n");
899 Curl_ssl_sessionid_unlock(conn);
906 gnutls_x509_crt_t cert,
907 const char *pinnedpubkey)
910 size_t len1 = 0, len2 = 0;
911 unsigned char *buff1 = NULL;
913 gnutls_pubkey_t
key = NULL;
920 if(NULL == pinnedpubkey)
928 gnutls_pubkey_init(&key);
930 ret = gnutls_pubkey_import_x509(key, cert, 0);
934 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
935 if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
944 ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
945 if(ret < 0 || len1 != len2)
951 result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
955 gnutls_pubkey_deinit(key);
969 unsigned int cert_list_size;
970 const gnutls_datum_t *chainp;
971 unsigned int verify_status = 0;
972 gnutls_x509_crt_t x509_cert, x509_issuer;
973 gnutls_datum_t issuerp;
974 char certbuf[256] =
"";
980 gnutls_session_t session = BACKEND->session;
983 gnutls_datum_t proto;
986 #ifndef CURL_DISABLE_VERBOSE_STRINGS 989 gnutls_protocol_t version = gnutls_protocol_get_version(session);
995 ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
996 gnutls_cipher_get(session),
997 gnutls_mac_get(session));
999 infof(data,
"SSL connection using %s / %s\n",
1000 gnutls_protocol_get_name(version), ptr);
1008 chainp = gnutls_certificate_get_peers(session, &cert_list_size);
1017 && gnutls_cipher_get(session)) {
1023 failf(data,
"failed to get server cert");
1029 infof(data,
"\t common name: WARNING couldn't obtain\n");
1035 result = Curl_ssl_init_certinfo(data, cert_list_size);
1039 for(i = 0; i < cert_list_size; i++) {
1040 const char *beg = (
const char *) chainp[i].data;
1041 const char *end = beg + chainp[
i].size;
1043 result = Curl_extract_certinfo(conn, i, beg, end);
1057 rc = gnutls_certificate_verify_peers2(session, &verify_status);
1059 failf(data,
"server cert verify failed: %d", rc);
1064 if(verify_status & GNUTLS_CERT_INVALID) {
1066 failf(data,
"server certificate verification failed. CAfile: %s " 1073 infof(data,
"\t server certificate verification FAILED\n");
1076 infof(data,
"\t server certificate verification OK\n");
1079 infof(data,
"\t server certificate verification SKIPPED\n");
1083 if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
1084 gnutls_datum_t status_request;
1085 gnutls_ocsp_resp_t ocsp_resp;
1087 gnutls_ocsp_cert_status_t status;
1088 gnutls_x509_crl_reason_t reason;
1090 rc = gnutls_ocsp_status_request_get(session, &status_request);
1092 infof(data,
"\t server certificate status verification FAILED\n");
1094 if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1095 failf(data,
"No OCSP response received");
1100 failf(data,
"Invalid OCSP response received");
1104 gnutls_ocsp_resp_init(&ocsp_resp);
1106 rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
1108 failf(data,
"Invalid OCSP response received");
1112 rc = gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
1113 &status, NULL, NULL, NULL, &reason);
1116 case GNUTLS_OCSP_CERT_GOOD:
1119 case GNUTLS_OCSP_CERT_REVOKED: {
1120 const char *crl_reason;
1124 case GNUTLS_X509_CRLREASON_UNSPECIFIED:
1125 crl_reason =
"unspecified reason";
1128 case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
1129 crl_reason =
"private key compromised";
1132 case GNUTLS_X509_CRLREASON_CACOMPROMISE:
1133 crl_reason =
"CA compromised";
1136 case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
1137 crl_reason =
"affiliation has changed";
1140 case GNUTLS_X509_CRLREASON_SUPERSEDED:
1141 crl_reason =
"certificate superseded";
1144 case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
1145 crl_reason =
"operation has ceased";
1148 case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
1149 crl_reason =
"certificate is on hold";
1152 case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
1153 crl_reason =
"will be removed from delta CRL";
1156 case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
1157 crl_reason =
"privilege withdrawn";
1160 case GNUTLS_X509_CRLREASON_AACOMPROMISE:
1161 crl_reason =
"AA compromised";
1165 failf(data,
"Server certificate was revoked: %s", crl_reason);
1170 case GNUTLS_OCSP_CERT_UNKNOWN:
1171 failf(data,
"Server certificate status is unknown");
1175 gnutls_ocsp_resp_deinit(ocsp_resp);
1180 infof(data,
"\t server certificate status verification OK\n");
1183 infof(data,
"\t server certificate status verification SKIPPED\n");
1187 gnutls_x509_crt_init(&x509_cert);
1192 gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1195 gnutls_x509_crt_init(&x509_issuer);
1197 gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1198 rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1199 gnutls_x509_crt_deinit(x509_issuer);
1200 unload_file(issuerp);
1202 failf(data,
"server certificate issuer check failed (IssuerCert: %s)",
1204 gnutls_x509_crt_deinit(x509_cert);
1207 infof(data,
"\t server certificate issuer check OK (Issuer Cert: %s)\n",
1211 size =
sizeof(certbuf);
1212 rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1218 infof(data,
"error fetching CN from cert:%s\n",
1219 gnutls_strerror(rc));
1227 rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
1228 #if GNUTLS_VERSION_NUMBER < 0x030306 1233 #define use_addr in6_addr 1235 #define use_addr in_addr 1237 unsigned char addrbuf[
sizeof(
struct use_addr)];
1238 unsigned char certaddr[
sizeof(
struct use_addr)];
1239 size_t addrlen = 0, certaddrlen;
1252 certaddrlen =
sizeof(certaddr);
1253 ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1254 &certaddrlen, NULL);
1256 if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1260 if(ret != GNUTLS_SAN_IPADDRESS)
1262 if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1275 failf(data,
"SSL: certificate subject name (%s) does not match " 1276 "target host name '%s'", certbuf, dispname);
1277 gnutls_x509_crt_deinit(x509_cert);
1281 infof(data,
"\t common name: %s (does not match '%s')\n",
1285 infof(data,
"\t common name: %s (matched)\n", certbuf);
1288 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1290 if(certclock == (time_t)-1) {
1292 failf(data,
"server cert expiration date verify failed");
1293 gnutls_x509_crt_deinit(x509_cert);
1297 infof(data,
"\t server certificate expiration date verify FAILED\n");
1300 if(certclock < time(NULL)) {
1302 failf(data,
"server certificate expiration date has passed.");
1303 gnutls_x509_crt_deinit(x509_cert);
1307 infof(data,
"\t server certificate expiration date FAILED\n");
1310 infof(data,
"\t server certificate expiration date OK\n");
1313 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1315 if(certclock == (time_t)-1) {
1317 failf(data,
"server cert activation date verify failed");
1318 gnutls_x509_crt_deinit(x509_cert);
1322 infof(data,
"\t server certificate activation date verify FAILED\n");
1325 if(certclock > time(NULL)) {
1327 failf(data,
"server certificate not activated yet.");
1328 gnutls_x509_crt_deinit(x509_cert);
1332 infof(data,
"\t server certificate activation date FAILED\n");
1335 infof(data,
"\t server certificate activation date OK\n");
1341 result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
1343 failf(data,
"SSL: public key does not match pinned public key!");
1344 gnutls_x509_crt_deinit(x509_cert);
1359 #ifndef CURL_DISABLE_VERBOSE_STRINGS 1361 algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1362 infof(data,
"\t certificate public key: %s\n",
1363 gnutls_pk_algorithm_get_name(algo));
1366 infof(data,
"\t certificate version: #%d\n",
1367 gnutls_x509_crt_get_version(x509_cert));
1370 size =
sizeof(certbuf);
1371 gnutls_x509_crt_get_dn(x509_cert, certbuf, &size);
1372 infof(data,
"\t subject: %s\n", certbuf);
1374 certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1375 showtime(data,
"start date", certclock);
1377 certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1378 showtime(data,
"expire date", certclock);
1380 size =
sizeof(certbuf);
1381 gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
1382 infof(data,
"\t issuer: %s\n", certbuf);
1385 ptr = gnutls_compression_get_name(gnutls_compression_get(session));
1387 infof(data,
"\t compression: %s\n", ptr);
1390 gnutls_x509_crt_deinit(x509_cert);
1394 rc = gnutls_alpn_get_selected_protocol(session, &proto);
1396 infof(data,
"ALPN, server accepted to use %.*s\n", proto.size,
1400 if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
1401 !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
1402 NGHTTP2_PROTO_VERSION_ID_LEN)) {
1413 infof(data,
"ALPN, server did not agree to a protocol\n");
1418 conn->
recv[sockindex] = gtls_recv;
1419 conn->
send[sockindex] = gtls_send;
1427 void *ssl_sessionid;
1428 void *connect_sessionid;
1429 size_t connect_idsize = 0;
1432 gnutls_session_get_data(session, NULL, &connect_idsize);
1433 connect_sessionid =
malloc(connect_idsize);
1435 if(connect_sessionid) {
1437 gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
1439 Curl_ssl_sessionid_lock(conn);
1440 incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
1445 Curl_ssl_delsessionid(conn, ssl_sessionid);
1449 result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
1451 Curl_ssl_sessionid_unlock(conn);
1453 free(connect_sessionid);
1485 rc = gtls_connect_step1(conn, sockindex);
1490 rc = handshake(conn, sockindex,
TRUE, nonblocking);
1497 rc = gtls_connect_step3(conn, sockindex);
1508 int sockindex,
bool *done)
1510 return gtls_connect_common(conn, sockindex,
TRUE, done);
1518 result = gtls_connect_common(conn, sockindex,
FALSE, &done);
1527 static bool Curl_gtls_data_pending(
const struct connectdata *conn,
1532 if(BACKEND->session &&
1533 0 != gnutls_record_check_pending(BACKEND->session))
1537 if(BACKEND->session &&
1538 0 != gnutls_record_check_pending(BACKEND->session))
1551 ssize_t rc = gnutls_record_send(BACKEND->session, mem, len);
1554 *curlcode = (rc == GNUTLS_E_AGAIN)
1566 if(BACKEND->session) {
1567 gnutls_bye(BACKEND->session, GNUTLS_SHUT_RDWR);
1568 gnutls_deinit(BACKEND->session);
1569 BACKEND->session = NULL;
1572 gnutls_certificate_free_credentials(BACKEND->cred);
1573 BACKEND->cred = NULL;
1576 if(BACKEND->srp_client_cred) {
1577 gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
1578 BACKEND->srp_client_cred = NULL;
1583 static void Curl_gtls_close(
struct connectdata *conn,
int sockindex)
1585 close_one(&conn->
ssl[sockindex]);
1593 static int Curl_gtls_shutdown(
struct connectdata *conn,
int sockindex)
1608 gnutls_bye(BACKEND->session, GNUTLS_SHUT_WR);
1610 if(BACKEND->session) {
1613 SSL_SHUTDOWN_TIMEOUT);
1617 result = gnutls_record_recv(BACKEND->session,
1625 case GNUTLS_E_AGAIN:
1626 case GNUTLS_E_INTERRUPTED:
1627 infof(data,
"GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
1635 else if(0 == what) {
1637 failf(data,
"SSL shutdown timeout");
1648 gnutls_deinit(BACKEND->session);
1650 gnutls_certificate_free_credentials(BACKEND->cred);
1655 gnutls_srp_free_client_credentials(BACKEND->srp_client_cred);
1658 BACKEND->cred = NULL;
1659 BACKEND->session = NULL;
1673 ret = gnutls_record_recv(BACKEND->session, buf, buffersize);
1674 if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1679 if(ret == GNUTLS_E_REHANDSHAKE) {
1692 failf(conn->
data,
"GnuTLS recv error (%d): %s",
1694 (
int)ret, gnutls_strerror((
int)ret));
1702 static void Curl_gtls_session_free(
void *ptr)
1707 static size_t Curl_gtls_version(
char *
buffer,
size_t size)
1709 return snprintf(buffer, size,
"GnuTLS/%s", gnutls_check_version(NULL));
1712 #ifndef USE_GNUTLS_NETTLE 1713 static int Curl_gtls_seed(
struct Curl_easy *data)
1717 static bool ssl_seeded =
FALSE;
1720 gcry_fast_random_poll();
1738 unsigned char *entropy,
size_t length)
1740 #if defined(USE_GNUTLS_NETTLE) 1743 rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1745 #elif defined(USE_GNUTLS) 1747 Curl_gtls_seed(data);
1748 gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
1753 static CURLcode Curl_gtls_md5sum(
unsigned char *tmp,
1755 unsigned char *md5sum,
1758 #if defined(USE_GNUTLS_NETTLE) 1759 struct md5_ctx MD5pw;
1761 md5_update(&MD5pw, (
unsigned int)tmplen, tmp);
1762 md5_digest(&MD5pw, (
unsigned int)md5len, md5sum);
1763 #elif defined(USE_GNUTLS) 1765 gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
1766 gcry_md_write(MD5pw, tmp, tmplen);
1767 memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
1768 gcry_md_close(MD5pw);
1773 static void Curl_gtls_sha256sum(
const unsigned char *tmp,
1775 unsigned char *sha256sum,
1778 #if defined(USE_GNUTLS_NETTLE) 1779 struct sha256_ctx SHA256pw;
1780 sha256_init(&SHA256pw);
1781 sha256_update(&SHA256pw, (
unsigned int)tmplen, tmp);
1782 sha256_digest(&SHA256pw, (
unsigned int)sha256len, sha256sum);
1783 #elif defined(USE_GNUTLS) 1784 gcry_md_hd_t SHA256pw;
1785 gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
1786 gcry_md_write(SHA256pw, tmp, tmplen);
1787 memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
1788 gcry_md_close(SHA256pw);
1792 static bool Curl_gtls_cert_status_request(
void)
1805 return BACKEND->session;
1808 const struct Curl_ssl Curl_ssl_gnutls = {
1817 sizeof(
struct ssl_backend_data),
1824 Curl_gtls_data_pending,
1826 Curl_gtls_cert_status_request,
1828 Curl_gtls_connect_nonblocking,
1829 Curl_gtls_get_internals,
1832 Curl_gtls_session_free,
struct ssl_connect_data ssl[2]
ssize_t( Curl_recv)(struct connectdata *conn, int sockindex, char *buf, size_t len, CURLcode *err)
const char *const Curl_wkday[]
#define SSL_CONN_CONFIG(var)
#define SSL_SET_OPTION(var)
ssl_connect_state connecting_state
const char *const Curl_month[]
UNITTEST_START char * ptr
static const struct Curl_handler *const protocols[]
#define strcasecompare(a, b)
int curlx_uztosi(size_t uznum)
UNITTEST_START int result
struct ssl_config_data ssl
struct proxy_info http_proxy
ssl_connection_state state
memcpy(filename, filename1, strlen(filename1))
int Curl_none_check_cxn(struct connectdata *conn)
#define ALPN_HTTP_1_1_LENGTH
time_t Curl_timeleft(struct Curl_easy *data, struct curltime *nowp, bool duringconnect)
bool Curl_none_false_start(void)
#define SOCKET_READABLE(x, z)
ssize_t( Curl_send)(struct connectdata *conn, int sockindex, const void *buf, size_t len, CURLcode *err)
int Curl_inet_pton(int af, const char *src, void *dst)
#define Curl_safefree(ptr)
int Curl_socket_check(curl_socket_t readfd0, curl_socket_t readfd1, curl_socket_t writefd, time_t timeout_ms)
CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine)
CURLcode Curl_gmtime(time_t intime, struct tm *store)
struct curl_slist * Curl_none_engines_list(struct Curl_easy *data)
struct ssl_connect_data proxy_ssl[2]
#define CURL_HTTP_VERSION_2
CURLcode Curl_none_set_engine_default(struct Curl_easy *data)
void Curl_none_close_all(struct Curl_easy *data)