Annotation of embedaddon/curl/lib/vtls/gtls.c, revision 1.1.1.1
1.1 misho 1: /***************************************************************************
2: * _ _ ____ _
3: * Project ___| | | | _ \| |
4: * / __| | | | |_) | |
5: * | (__| |_| | _ <| |___
6: * \___|\___/|_| \_\_____|
7: *
8: * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
9: *
10: * This software is licensed as described in the file COPYING, which
11: * you should have received as part of this distribution. The terms
12: * are also available at https://curl.haxx.se/docs/copyright.html.
13: *
14: * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15: * copies of the Software, and permit persons to whom the Software is
16: * furnished to do so, under the terms of the COPYING file.
17: *
18: * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19: * KIND, either express or implied.
20: *
21: ***************************************************************************/
22:
23: /*
24: * Source file for all GnuTLS-specific code for the TLS/SSL layer. No code
25: * but vtls.c should ever call or use these functions.
26: *
27: * Note: don't use the GnuTLS' *_t variable type names in this source code,
28: * since they were not present in 1.0.X.
29: */
30:
31: #include "curl_setup.h"
32:
33: #ifdef USE_GNUTLS
34:
35: #include <gnutls/abstract.h>
36: #include <gnutls/gnutls.h>
37: #include <gnutls/x509.h>
38:
39: #ifdef USE_GNUTLS_NETTLE
40: #include <gnutls/crypto.h>
41: #include <nettle/md5.h>
42: #include <nettle/sha2.h>
43: #else
44: #include <gcrypt.h>
45: #endif
46:
47: #include "urldata.h"
48: #include "sendf.h"
49: #include "inet_pton.h"
50: #include "gtls.h"
51: #include "vtls.h"
52: #include "parsedate.h"
53: #include "connect.h" /* for the connect timeout */
54: #include "select.h"
55: #include "strcase.h"
56: #include "warnless.h"
57: #include "x509asn1.h"
58: #include "multiif.h"
59: #include "curl_printf.h"
60: #include "curl_memory.h"
61: /* The last #include file should be: */
62: #include "memdebug.h"
63:
64: /* Enable GnuTLS debugging by defining GTLSDEBUG */
65: /*#define GTLSDEBUG */
66:
67: #ifdef GTLSDEBUG
68: static void tls_log_func(int level, const char *str)
69: {
70: fprintf(stderr, "|<%d>| %s", level, str);
71: }
72: #endif
73: static bool gtls_inited = FALSE;
74:
75: #if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x03010a)
76: #error "too old GnuTLS version"
77: #endif
78:
79: # include <gnutls/ocsp.h>
80:
81: struct ssl_backend_data {
82: gnutls_session_t session;
83: gnutls_certificate_credentials_t cred;
84: #ifdef USE_TLS_SRP
85: gnutls_srp_client_credentials_t srp_client_cred;
86: #endif
87: };
88:
89: static ssize_t Curl_gtls_push(void *s, const void *buf, size_t len)
90: {
91: curl_socket_t sock = *(curl_socket_t *)s;
92: ssize_t ret = swrite(sock, buf, len);
93: return ret;
94: }
95:
96: static ssize_t Curl_gtls_pull(void *s, void *buf, size_t len)
97: {
98: curl_socket_t sock = *(curl_socket_t *)s;
99: ssize_t ret = sread(sock, buf, len);
100: return ret;
101: }
102:
103: static ssize_t Curl_gtls_push_ssl(void *s, const void *buf, size_t len)
104: {
105: return gnutls_record_send((gnutls_session_t) s, buf, len);
106: }
107:
108: static ssize_t Curl_gtls_pull_ssl(void *s, void *buf, size_t len)
109: {
110: return gnutls_record_recv((gnutls_session_t) s, buf, len);
111: }
112:
113: /* Curl_gtls_init()
114: *
115: * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that
116: * are not thread-safe and thus this function itself is not thread-safe and
117: * must only be called from within curl_global_init() to keep the thread
118: * situation under control!
119: */
120: static int Curl_gtls_init(void)
121: {
122: int ret = 1;
123: if(!gtls_inited) {
124: ret = gnutls_global_init()?0:1;
125: #ifdef GTLSDEBUG
126: gnutls_global_set_log_function(tls_log_func);
127: gnutls_global_set_log_level(2);
128: #endif
129: gtls_inited = TRUE;
130: }
131: return ret;
132: }
133:
134: static void Curl_gtls_cleanup(void)
135: {
136: if(gtls_inited) {
137: gnutls_global_deinit();
138: gtls_inited = FALSE;
139: }
140: }
141:
142: #ifndef CURL_DISABLE_VERBOSE_STRINGS
143: static void showtime(struct Curl_easy *data,
144: const char *text,
145: time_t stamp)
146: {
147: struct tm buffer;
148: const struct tm *tm = &buffer;
149: char str[96];
150: CURLcode result = Curl_gmtime(stamp, &buffer);
151: if(result)
152: return;
153:
154: msnprintf(str,
155: sizeof(str),
156: "\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
157: text,
158: Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
159: tm->tm_mday,
160: Curl_month[tm->tm_mon],
161: tm->tm_year + 1900,
162: tm->tm_hour,
163: tm->tm_min,
164: tm->tm_sec);
165: infof(data, "%s\n", str);
166: }
167: #endif
168:
169: static gnutls_datum_t load_file(const char *file)
170: {
171: FILE *f;
172: gnutls_datum_t loaded_file = { NULL, 0 };
173: long filelen;
174: void *ptr;
175:
176: f = fopen(file, "rb");
177: if(!f)
178: return loaded_file;
179: if(fseek(f, 0, SEEK_END) != 0
180: || (filelen = ftell(f)) < 0
181: || fseek(f, 0, SEEK_SET) != 0
182: || !(ptr = malloc((size_t)filelen)))
183: goto out;
184: if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) {
185: free(ptr);
186: goto out;
187: }
188:
189: loaded_file.data = ptr;
190: loaded_file.size = (unsigned int)filelen;
191: out:
192: fclose(f);
193: return loaded_file;
194: }
195:
196: static void unload_file(gnutls_datum_t data)
197: {
198: free(data.data);
199: }
200:
201:
202: /* this function does a SSL/TLS (re-)handshake */
203: static CURLcode handshake(struct connectdata *conn,
204: int sockindex,
205: bool duringconnect,
206: bool nonblocking)
207: {
208: struct Curl_easy *data = conn->data;
209: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
210: struct ssl_backend_data *backend = connssl->backend;
211: gnutls_session_t session = backend->session;
212: curl_socket_t sockfd = conn->sock[sockindex];
213:
214: for(;;) {
215: timediff_t timeout_ms;
216: int rc;
217:
218: /* check allowed time left */
219: timeout_ms = Curl_timeleft(data, NULL, duringconnect);
220:
221: if(timeout_ms < 0) {
222: /* no need to continue if time already is up */
223: failf(data, "SSL connection timeout");
224: return CURLE_OPERATION_TIMEDOUT;
225: }
226:
227: /* if ssl is expecting something, check if it's available. */
228: if(connssl->connecting_state == ssl_connect_2_reading
229: || connssl->connecting_state == ssl_connect_2_writing) {
230: int what;
231: curl_socket_t writefd = ssl_connect_2_writing ==
232: connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
233: curl_socket_t readfd = ssl_connect_2_reading ==
234: connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
235:
236: what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
237: nonblocking?0:
238: timeout_ms?(time_t)timeout_ms:1000);
239: if(what < 0) {
240: /* fatal error */
241: failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
242: return CURLE_SSL_CONNECT_ERROR;
243: }
244: else if(0 == what) {
245: if(nonblocking)
246: return CURLE_OK;
247: else if(timeout_ms) {
248: /* timeout */
249: failf(data, "SSL connection timeout at %ld", (long)timeout_ms);
250: return CURLE_OPERATION_TIMEDOUT;
251: }
252: }
253: /* socket is readable or writable */
254: }
255:
256: rc = gnutls_handshake(session);
257:
258: if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
259: connssl->connecting_state =
260: gnutls_record_get_direction(session)?
261: ssl_connect_2_writing:ssl_connect_2_reading;
262: continue;
263: }
264: else if((rc < 0) && !gnutls_error_is_fatal(rc)) {
265: const char *strerr = NULL;
266:
267: if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
268: int alert = gnutls_alert_get(session);
269: strerr = gnutls_alert_get_name(alert);
270: }
271:
272: if(strerr == NULL)
273: strerr = gnutls_strerror(rc);
274:
275: infof(data, "gnutls_handshake() warning: %s\n", strerr);
276: continue;
277: }
278: else if(rc < 0) {
279: const char *strerr = NULL;
280:
281: if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
282: int alert = gnutls_alert_get(session);
283: strerr = gnutls_alert_get_name(alert);
284: }
285:
286: if(strerr == NULL)
287: strerr = gnutls_strerror(rc);
288:
289: failf(data, "gnutls_handshake() failed: %s", strerr);
290: return CURLE_SSL_CONNECT_ERROR;
291: }
292:
293: /* Reset our connect state machine */
294: connssl->connecting_state = ssl_connect_1;
295: return CURLE_OK;
296: }
297: }
298:
299: static gnutls_x509_crt_fmt_t do_file_type(const char *type)
300: {
301: if(!type || !type[0])
302: return GNUTLS_X509_FMT_PEM;
303: if(strcasecompare(type, "PEM"))
304: return GNUTLS_X509_FMT_PEM;
305: if(strcasecompare(type, "DER"))
306: return GNUTLS_X509_FMT_DER;
307: return -1;
308: }
309:
310: #define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509"
311: /* If GnuTLS was compiled without support for SRP it will error out if SRP is
312: requested in the priority string, so treat it specially
313: */
314: #define GNUTLS_SRP "+SRP"
315:
316: static CURLcode
317: set_ssl_version_min_max(const char **prioritylist, struct connectdata *conn)
318: {
319: struct Curl_easy *data = conn->data;
320: long ssl_version = SSL_CONN_CONFIG(version);
321: long ssl_version_max = SSL_CONN_CONFIG(version_max);
322:
323: if(ssl_version_max == CURL_SSLVERSION_MAX_NONE) {
324: ssl_version_max = CURL_SSLVERSION_MAX_DEFAULT;
325: }
326: switch(ssl_version | ssl_version_max) {
327: case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_0:
328: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
329: "+VERS-TLS1.0";
330: return CURLE_OK;
331: case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_1:
332: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
333: "+VERS-TLS1.0:+VERS-TLS1.1";
334: return CURLE_OK;
335: case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_TLSv1_2:
336: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
337: "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2";
338: return CURLE_OK;
339: case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_1:
340: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
341: "+VERS-TLS1.1";
342: return CURLE_OK;
343: case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_TLSv1_2:
344: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
345: "+VERS-TLS1.1:+VERS-TLS1.2";
346: return CURLE_OK;
347: case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_TLSv1_2:
348: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
349: "+VERS-TLS1.2";
350: return CURLE_OK;
351: case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_TLSv1_3:
352: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
353: "+VERS-TLS1.3";
354: return CURLE_OK;
355: case CURL_SSLVERSION_TLSv1_0 | CURL_SSLVERSION_MAX_DEFAULT:
356: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
357: "+VERS-TLS1.0:+VERS-TLS1.1:+VERS-TLS1.2"
358: ":+VERS-TLS1.3";
359: return CURLE_OK;
360: case CURL_SSLVERSION_TLSv1_1 | CURL_SSLVERSION_MAX_DEFAULT:
361: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
362: "+VERS-TLS1.1:+VERS-TLS1.2"
363: ":+VERS-TLS1.3";
364: return CURLE_OK;
365: case CURL_SSLVERSION_TLSv1_2 | CURL_SSLVERSION_MAX_DEFAULT:
366: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
367: "+VERS-TLS1.2"
368: ":+VERS-TLS1.3";
369: return CURLE_OK;
370: case CURL_SSLVERSION_TLSv1_3 | CURL_SSLVERSION_MAX_DEFAULT:
371: *prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0:-VERS-TLS-ALL:"
372: "+VERS-TLS1.2"
373: ":+VERS-TLS1.3";
374: return CURLE_OK;
375: }
376:
377: failf(data, "GnuTLS: cannot set ssl protocol");
378: return CURLE_SSL_CONNECT_ERROR;
379: }
380:
381: static CURLcode
382: gtls_connect_step1(struct connectdata *conn,
383: int sockindex)
384: {
385: struct Curl_easy *data = conn->data;
386: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
387: struct ssl_backend_data *backend = connssl->backend;
388: unsigned int init_flags;
389: gnutls_session_t session;
390: int rc;
391: bool sni = TRUE; /* default is SNI enabled */
392: void *transport_ptr = NULL;
393: gnutls_push_func gnutls_transport_push = NULL;
394: gnutls_pull_func gnutls_transport_pull = NULL;
395: #ifdef ENABLE_IPV6
396: struct in6_addr addr;
397: #else
398: struct in_addr addr;
399: #endif
400: const char *prioritylist;
401: const char *err = NULL;
402: const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
403: conn->host.name;
404:
405: if(connssl->state == ssl_connection_complete)
406: /* to make us tolerant against being called more than once for the
407: same connection */
408: return CURLE_OK;
409:
410: if(!gtls_inited)
411: Curl_gtls_init();
412:
413: if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
414: failf(data, "GnuTLS does not support SSLv2");
415: return CURLE_SSL_CONNECT_ERROR;
416: }
417: else if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv3)
418: sni = FALSE; /* SSLv3 has no SNI */
419:
420: /* allocate a cred struct */
421: rc = gnutls_certificate_allocate_credentials(&backend->cred);
422: if(rc != GNUTLS_E_SUCCESS) {
423: failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc));
424: return CURLE_SSL_CONNECT_ERROR;
425: }
426:
427: #ifdef USE_TLS_SRP
428: if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
429: infof(data, "Using TLS-SRP username: %s\n", SSL_SET_OPTION(username));
430:
431: rc = gnutls_srp_allocate_client_credentials(
432: &backend->srp_client_cred);
433: if(rc != GNUTLS_E_SUCCESS) {
434: failf(data, "gnutls_srp_allocate_client_cred() failed: %s",
435: gnutls_strerror(rc));
436: return CURLE_OUT_OF_MEMORY;
437: }
438:
439: rc = gnutls_srp_set_client_credentials(backend->srp_client_cred,
440: SSL_SET_OPTION(username),
441: SSL_SET_OPTION(password));
442: if(rc != GNUTLS_E_SUCCESS) {
443: failf(data, "gnutls_srp_set_client_cred() failed: %s",
444: gnutls_strerror(rc));
445: return CURLE_BAD_FUNCTION_ARGUMENT;
446: }
447: }
448: #endif
449:
450: if(SSL_CONN_CONFIG(CAfile)) {
451: /* set the trusted CA cert bundle file */
452: gnutls_certificate_set_verify_flags(backend->cred,
453: GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
454:
455: rc = gnutls_certificate_set_x509_trust_file(backend->cred,
456: SSL_CONN_CONFIG(CAfile),
457: GNUTLS_X509_FMT_PEM);
458: if(rc < 0) {
459: infof(data, "error reading ca cert file %s (%s)\n",
460: SSL_CONN_CONFIG(CAfile), gnutls_strerror(rc));
461: if(SSL_CONN_CONFIG(verifypeer))
462: return CURLE_SSL_CACERT_BADFILE;
463: }
464: else
465: infof(data, "found %d certificates in %s\n", rc,
466: SSL_CONN_CONFIG(CAfile));
467: }
468:
469: if(SSL_CONN_CONFIG(CApath)) {
470: /* set the trusted CA cert directory */
471: rc = gnutls_certificate_set_x509_trust_dir(backend->cred,
472: SSL_CONN_CONFIG(CApath),
473: GNUTLS_X509_FMT_PEM);
474: if(rc < 0) {
475: infof(data, "error reading ca cert file %s (%s)\n",
476: SSL_CONN_CONFIG(CApath), gnutls_strerror(rc));
477: if(SSL_CONN_CONFIG(verifypeer))
478: return CURLE_SSL_CACERT_BADFILE;
479: }
480: else
481: infof(data, "found %d certificates in %s\n",
482: rc, SSL_CONN_CONFIG(CApath));
483: }
484:
485: #ifdef CURL_CA_FALLBACK
486: /* use system ca certificate store as fallback */
487: if(SSL_CONN_CONFIG(verifypeer) &&
488: !(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(CApath))) {
489: gnutls_certificate_set_x509_system_trust(backend->cred);
490: }
491: #endif
492:
493: if(SSL_SET_OPTION(CRLfile)) {
494: /* set the CRL list file */
495: rc = gnutls_certificate_set_x509_crl_file(backend->cred,
496: SSL_SET_OPTION(CRLfile),
497: GNUTLS_X509_FMT_PEM);
498: if(rc < 0) {
499: failf(data, "error reading crl file %s (%s)",
500: SSL_SET_OPTION(CRLfile), gnutls_strerror(rc));
501: return CURLE_SSL_CRL_BADFILE;
502: }
503: else
504: infof(data, "found %d CRL in %s\n",
505: rc, SSL_SET_OPTION(CRLfile));
506: }
507:
508: /* Initialize TLS session as a client */
509: init_flags = GNUTLS_CLIENT;
510:
511: #if defined(GNUTLS_FORCE_CLIENT_CERT)
512: init_flags |= GNUTLS_FORCE_CLIENT_CERT;
513: #endif
514:
515: #if defined(GNUTLS_NO_TICKETS)
516: /* Disable TLS session tickets */
517: init_flags |= GNUTLS_NO_TICKETS;
518: #endif
519:
520: rc = gnutls_init(&backend->session, init_flags);
521: if(rc != GNUTLS_E_SUCCESS) {
522: failf(data, "gnutls_init() failed: %d", rc);
523: return CURLE_SSL_CONNECT_ERROR;
524: }
525:
526: /* convenient assign */
527: session = backend->session;
528:
529: if((0 == Curl_inet_pton(AF_INET, hostname, &addr)) &&
530: #ifdef ENABLE_IPV6
531: (0 == Curl_inet_pton(AF_INET6, hostname, &addr)) &&
532: #endif
533: sni &&
534: (gnutls_server_name_set(session, GNUTLS_NAME_DNS, hostname,
535: strlen(hostname)) < 0))
536: infof(data, "WARNING: failed to configure server name indication (SNI) "
537: "TLS extension\n");
538:
539: /* Use default priorities */
540: rc = gnutls_set_default_priority(session);
541: if(rc != GNUTLS_E_SUCCESS)
542: return CURLE_SSL_CONNECT_ERROR;
543:
544: /* Ensure +SRP comes at the *end* of all relevant strings so that it can be
545: * removed if a run-time error indicates that SRP is not supported by this
546: * GnuTLS version */
547: switch(SSL_CONN_CONFIG(version)) {
548: case CURL_SSLVERSION_SSLv3:
549: prioritylist = GNUTLS_CIPHERS ":-VERS-TLS-ALL:+VERS-SSL3.0";
550: break;
551: case CURL_SSLVERSION_DEFAULT:
552: case CURL_SSLVERSION_TLSv1:
553: prioritylist = GNUTLS_CIPHERS ":-VERS-SSL3.0"
554: #ifdef HAS_TLS13
555: ":+VERS-TLS1.3"
556: #endif
557: ;
558: break;
559: case CURL_SSLVERSION_TLSv1_0:
560: case CURL_SSLVERSION_TLSv1_1:
561: case CURL_SSLVERSION_TLSv1_2:
562: case CURL_SSLVERSION_TLSv1_3:
563: {
564: CURLcode result = set_ssl_version_min_max(&prioritylist, conn);
565: if(result != CURLE_OK)
566: return result;
567: break;
568: }
569: case CURL_SSLVERSION_SSLv2:
570: failf(data, "GnuTLS does not support SSLv2");
571: return CURLE_SSL_CONNECT_ERROR;
572: default:
573: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
574: return CURLE_SSL_CONNECT_ERROR;
575: }
576:
577: #ifdef USE_TLS_SRP
578: /* Only add SRP to the cipher list if SRP is requested. Otherwise
579: * GnuTLS will disable TLS 1.3 support. */
580: if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
581: size_t len = strlen(prioritylist);
582:
583: char *prioritysrp = malloc(len + sizeof(GNUTLS_SRP) + 1);
584: if(!prioritysrp)
585: return CURLE_OUT_OF_MEMORY;
586: strcpy(prioritysrp, prioritylist);
587: strcpy(prioritysrp + len, ":" GNUTLS_SRP);
588:
589: rc = gnutls_priority_set_direct(session, prioritysrp, &err);
590: free(prioritysrp);
591:
592: if((rc == GNUTLS_E_INVALID_REQUEST) && err) {
593: infof(data, "This GnuTLS does not support SRP\n");
594: }
595: }
596: else {
597: #endif
598: rc = gnutls_priority_set_direct(session, prioritylist, &err);
599: #ifdef USE_TLS_SRP
600: }
601: #endif
602:
603: if(rc != GNUTLS_E_SUCCESS) {
604: failf(data, "Error %d setting GnuTLS cipher list starting with %s",
605: rc, err);
606: return CURLE_SSL_CONNECT_ERROR;
607: }
608:
609: if(conn->bits.tls_enable_alpn) {
610: int cur = 0;
611: gnutls_datum_t protocols[2];
612:
613: #ifdef USE_NGHTTP2
614: if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
615: (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
616: protocols[cur].data = (unsigned char *)NGHTTP2_PROTO_VERSION_ID;
617: protocols[cur].size = NGHTTP2_PROTO_VERSION_ID_LEN;
618: cur++;
619: infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
620: }
621: #endif
622:
623: protocols[cur].data = (unsigned char *)ALPN_HTTP_1_1;
624: protocols[cur].size = ALPN_HTTP_1_1_LENGTH;
625: cur++;
626: infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
627:
628: gnutls_alpn_set_protocols(session, protocols, cur, 0);
629: }
630:
631: if(SSL_SET_OPTION(cert)) {
632: if(SSL_SET_OPTION(key_passwd)) {
633: const unsigned int supported_key_encryption_algorithms =
634: GNUTLS_PKCS_USE_PKCS12_3DES | GNUTLS_PKCS_USE_PKCS12_ARCFOUR |
635: GNUTLS_PKCS_USE_PKCS12_RC2_40 | GNUTLS_PKCS_USE_PBES2_3DES |
636: GNUTLS_PKCS_USE_PBES2_AES_128 | GNUTLS_PKCS_USE_PBES2_AES_192 |
637: GNUTLS_PKCS_USE_PBES2_AES_256;
638: rc = gnutls_certificate_set_x509_key_file2(
639: backend->cred,
640: SSL_SET_OPTION(cert),
641: SSL_SET_OPTION(key) ?
642: SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
643: do_file_type(SSL_SET_OPTION(cert_type)),
644: SSL_SET_OPTION(key_passwd),
645: supported_key_encryption_algorithms);
646: if(rc != GNUTLS_E_SUCCESS) {
647: failf(data,
648: "error reading X.509 potentially-encrypted key file: %s",
649: gnutls_strerror(rc));
650: return CURLE_SSL_CONNECT_ERROR;
651: }
652: }
653: else {
654: if(gnutls_certificate_set_x509_key_file(
655: backend->cred,
656: SSL_SET_OPTION(cert),
657: SSL_SET_OPTION(key) ?
658: SSL_SET_OPTION(key) : SSL_SET_OPTION(cert),
659: do_file_type(SSL_SET_OPTION(cert_type)) ) !=
660: GNUTLS_E_SUCCESS) {
661: failf(data, "error reading X.509 key or certificate file");
662: return CURLE_SSL_CONNECT_ERROR;
663: }
664: }
665: }
666:
667: #ifdef USE_TLS_SRP
668: /* put the credentials to the current session */
669: if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP) {
670: rc = gnutls_credentials_set(session, GNUTLS_CRD_SRP,
671: backend->srp_client_cred);
672: if(rc != GNUTLS_E_SUCCESS) {
673: failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
674: return CURLE_SSL_CONNECT_ERROR;
675: }
676: }
677: else
678: #endif
679: {
680: rc = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
681: backend->cred);
682: if(rc != GNUTLS_E_SUCCESS) {
683: failf(data, "gnutls_credentials_set() failed: %s", gnutls_strerror(rc));
684: return CURLE_SSL_CONNECT_ERROR;
685: }
686: }
687:
688: if(conn->proxy_ssl[sockindex].use) {
689: transport_ptr = conn->proxy_ssl[sockindex].backend->session;
690: gnutls_transport_push = Curl_gtls_push_ssl;
691: gnutls_transport_pull = Curl_gtls_pull_ssl;
692: }
693: else {
694: /* file descriptor for the socket */
695: transport_ptr = &conn->sock[sockindex];
696: gnutls_transport_push = Curl_gtls_push;
697: gnutls_transport_pull = Curl_gtls_pull;
698: }
699:
700: /* set the connection handle */
701: gnutls_transport_set_ptr(session, transport_ptr);
702:
703: /* register callback functions to send and receive data. */
704: gnutls_transport_set_push_function(session, gnutls_transport_push);
705: gnutls_transport_set_pull_function(session, gnutls_transport_pull);
706:
707: if(SSL_CONN_CONFIG(verifystatus)) {
708: rc = gnutls_ocsp_status_request_enable_client(session, NULL, 0, NULL);
709: if(rc != GNUTLS_E_SUCCESS) {
710: failf(data, "gnutls_ocsp_status_request_enable_client() failed: %d", rc);
711: return CURLE_SSL_CONNECT_ERROR;
712: }
713: }
714:
715: /* This might be a reconnect, so we check for a session ID in the cache
716: to speed up things */
717: if(SSL_SET_OPTION(primary.sessionid)) {
718: void *ssl_sessionid;
719: size_t ssl_idsize;
720:
721: Curl_ssl_sessionid_lock(conn);
722: if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, &ssl_idsize, sockindex)) {
723: /* we got a session id, use it! */
724: gnutls_session_set_data(session, ssl_sessionid, ssl_idsize);
725:
726: /* Informational message */
727: infof(data, "SSL re-using session ID\n");
728: }
729: Curl_ssl_sessionid_unlock(conn);
730: }
731:
732: return CURLE_OK;
733: }
734:
735: static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
736: gnutls_x509_crt_t cert,
737: const char *pinnedpubkey)
738: {
739: /* Scratch */
740: size_t len1 = 0, len2 = 0;
741: unsigned char *buff1 = NULL;
742:
743: gnutls_pubkey_t key = NULL;
744:
745: /* Result is returned to caller */
746: CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
747:
748: /* if a path wasn't specified, don't pin */
749: if(NULL == pinnedpubkey)
750: return CURLE_OK;
751:
752: if(NULL == cert)
753: return result;
754:
755: do {
756: int ret;
757:
758: /* Begin Gyrations to get the public key */
759: gnutls_pubkey_init(&key);
760:
761: ret = gnutls_pubkey_import_x509(key, cert, 0);
762: if(ret < 0)
763: break; /* failed */
764:
765: ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, NULL, &len1);
766: if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0)
767: break; /* failed */
768:
769: buff1 = malloc(len1);
770: if(NULL == buff1)
771: break; /* failed */
772:
773: len2 = len1;
774:
775: ret = gnutls_pubkey_export(key, GNUTLS_X509_FMT_DER, buff1, &len2);
776: if(ret < 0 || len1 != len2)
777: break; /* failed */
778:
779: /* End Gyrations */
780:
781: /* The one good exit point */
782: result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1);
783: } while(0);
784:
785: if(NULL != key)
786: gnutls_pubkey_deinit(key);
787:
788: Curl_safefree(buff1);
789:
790: return result;
791: }
792:
793: static Curl_recv gtls_recv;
794: static Curl_send gtls_send;
795:
796: static CURLcode
797: gtls_connect_step3(struct connectdata *conn,
798: int sockindex)
799: {
800: unsigned int cert_list_size;
801: const gnutls_datum_t *chainp;
802: unsigned int verify_status = 0;
803: gnutls_x509_crt_t x509_cert, x509_issuer;
804: gnutls_datum_t issuerp;
805: gnutls_datum_t certfields;
806: char certname[65] = ""; /* limited to 64 chars by ASN.1 */
807: size_t size;
808: time_t certclock;
809: const char *ptr;
810: struct Curl_easy *data = conn->data;
811: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
812: struct ssl_backend_data *backend = connssl->backend;
813: gnutls_session_t session = backend->session;
814: int rc;
815: gnutls_datum_t proto;
816: CURLcode result = CURLE_OK;
817: #ifndef CURL_DISABLE_VERBOSE_STRINGS
818: unsigned int algo;
819: unsigned int bits;
820: gnutls_protocol_t version = gnutls_protocol_get_version(session);
821: #endif
822: const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
823: conn->host.name;
824:
825: /* the name of the cipher suite used, e.g. ECDHE_RSA_AES_256_GCM_SHA384. */
826: ptr = gnutls_cipher_suite_get_name(gnutls_kx_get(session),
827: gnutls_cipher_get(session),
828: gnutls_mac_get(session));
829:
830: infof(data, "SSL connection using %s / %s\n",
831: gnutls_protocol_get_name(version), ptr);
832:
833: /* This function will return the peer's raw certificate (chain) as sent by
834: the peer. These certificates are in raw format (DER encoded for
835: X.509). In case of a X.509 then a certificate list may be present. The
836: first certificate in the list is the peer's certificate, following the
837: issuer's certificate, then the issuer's issuer etc. */
838:
839: chainp = gnutls_certificate_get_peers(session, &cert_list_size);
840: if(!chainp) {
841: if(SSL_CONN_CONFIG(verifypeer) ||
842: SSL_CONN_CONFIG(verifyhost) ||
843: SSL_SET_OPTION(issuercert)) {
844: #ifdef USE_TLS_SRP
845: if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
846: && SSL_SET_OPTION(username) != NULL
847: && !SSL_CONN_CONFIG(verifypeer)
848: && gnutls_cipher_get(session)) {
849: /* no peer cert, but auth is ok if we have SRP user and cipher and no
850: peer verify */
851: }
852: else {
853: #endif
854: failf(data, "failed to get server cert");
855: return CURLE_PEER_FAILED_VERIFICATION;
856: #ifdef USE_TLS_SRP
857: }
858: #endif
859: }
860: infof(data, "\t common name: WARNING couldn't obtain\n");
861: }
862:
863: if(data->set.ssl.certinfo && chainp) {
864: unsigned int i;
865:
866: result = Curl_ssl_init_certinfo(data, cert_list_size);
867: if(result)
868: return result;
869:
870: for(i = 0; i < cert_list_size; i++) {
871: const char *beg = (const char *) chainp[i].data;
872: const char *end = beg + chainp[i].size;
873:
874: result = Curl_extract_certinfo(conn, i, beg, end);
875: if(result)
876: return result;
877: }
878: }
879:
880: if(SSL_CONN_CONFIG(verifypeer)) {
881: /* This function will try to verify the peer's certificate and return its
882: status (trusted, invalid etc.). The value of status should be one or
883: more of the gnutls_certificate_status_t enumerated elements bitwise
884: or'd. To avoid denial of service attacks some default upper limits
885: regarding the certificate key size and chain size are set. To override
886: them use gnutls_certificate_set_verify_limits(). */
887:
888: rc = gnutls_certificate_verify_peers2(session, &verify_status);
889: if(rc < 0) {
890: failf(data, "server cert verify failed: %d", rc);
891: return CURLE_SSL_CONNECT_ERROR;
892: }
893:
894: /* verify_status is a bitmask of gnutls_certificate_status bits */
895: if(verify_status & GNUTLS_CERT_INVALID) {
896: if(SSL_CONN_CONFIG(verifypeer)) {
897: failf(data, "server certificate verification failed. CAfile: %s "
898: "CRLfile: %s", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
899: "none",
900: SSL_SET_OPTION(CRLfile)?SSL_SET_OPTION(CRLfile):"none");
901: return CURLE_PEER_FAILED_VERIFICATION;
902: }
903: else
904: infof(data, "\t server certificate verification FAILED\n");
905: }
906: else
907: infof(data, "\t server certificate verification OK\n");
908: }
909: else
910: infof(data, "\t server certificate verification SKIPPED\n");
911:
912: if(SSL_CONN_CONFIG(verifystatus)) {
913: if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) {
914: gnutls_datum_t status_request;
915: gnutls_ocsp_resp_t ocsp_resp;
916:
917: gnutls_ocsp_cert_status_t status;
918: gnutls_x509_crl_reason_t reason;
919:
920: rc = gnutls_ocsp_status_request_get(session, &status_request);
921:
922: infof(data, "\t server certificate status verification FAILED\n");
923:
924: if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
925: failf(data, "No OCSP response received");
926: return CURLE_SSL_INVALIDCERTSTATUS;
927: }
928:
929: if(rc < 0) {
930: failf(data, "Invalid OCSP response received");
931: return CURLE_SSL_INVALIDCERTSTATUS;
932: }
933:
934: gnutls_ocsp_resp_init(&ocsp_resp);
935:
936: rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
937: if(rc < 0) {
938: failf(data, "Invalid OCSP response received");
939: return CURLE_SSL_INVALIDCERTSTATUS;
940: }
941:
942: (void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
943: &status, NULL, NULL, NULL, &reason);
944:
945: switch(status) {
946: case GNUTLS_OCSP_CERT_GOOD:
947: break;
948:
949: case GNUTLS_OCSP_CERT_REVOKED: {
950: const char *crl_reason;
951:
952: switch(reason) {
953: default:
954: case GNUTLS_X509_CRLREASON_UNSPECIFIED:
955: crl_reason = "unspecified reason";
956: break;
957:
958: case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
959: crl_reason = "private key compromised";
960: break;
961:
962: case GNUTLS_X509_CRLREASON_CACOMPROMISE:
963: crl_reason = "CA compromised";
964: break;
965:
966: case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
967: crl_reason = "affiliation has changed";
968: break;
969:
970: case GNUTLS_X509_CRLREASON_SUPERSEDED:
971: crl_reason = "certificate superseded";
972: break;
973:
974: case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
975: crl_reason = "operation has ceased";
976: break;
977:
978: case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
979: crl_reason = "certificate is on hold";
980: break;
981:
982: case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
983: crl_reason = "will be removed from delta CRL";
984: break;
985:
986: case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
987: crl_reason = "privilege withdrawn";
988: break;
989:
990: case GNUTLS_X509_CRLREASON_AACOMPROMISE:
991: crl_reason = "AA compromised";
992: break;
993: }
994:
995: failf(data, "Server certificate was revoked: %s", crl_reason);
996: break;
997: }
998:
999: default:
1000: case GNUTLS_OCSP_CERT_UNKNOWN:
1001: failf(data, "Server certificate status is unknown");
1002: break;
1003: }
1004:
1005: gnutls_ocsp_resp_deinit(ocsp_resp);
1006:
1007: return CURLE_SSL_INVALIDCERTSTATUS;
1008: }
1009: else
1010: infof(data, "\t server certificate status verification OK\n");
1011: }
1012: else
1013: infof(data, "\t server certificate status verification SKIPPED\n");
1014:
1015: /* initialize an X.509 certificate structure. */
1016: gnutls_x509_crt_init(&x509_cert);
1017:
1018: if(chainp)
1019: /* convert the given DER or PEM encoded Certificate to the native
1020: gnutls_x509_crt_t format */
1021: gnutls_x509_crt_import(x509_cert, chainp, GNUTLS_X509_FMT_DER);
1022:
1023: if(SSL_SET_OPTION(issuercert)) {
1024: gnutls_x509_crt_init(&x509_issuer);
1025: issuerp = load_file(SSL_SET_OPTION(issuercert));
1026: gnutls_x509_crt_import(x509_issuer, &issuerp, GNUTLS_X509_FMT_PEM);
1027: rc = gnutls_x509_crt_check_issuer(x509_cert, x509_issuer);
1028: gnutls_x509_crt_deinit(x509_issuer);
1029: unload_file(issuerp);
1030: if(rc <= 0) {
1031: failf(data, "server certificate issuer check failed (IssuerCert: %s)",
1032: SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
1033: gnutls_x509_crt_deinit(x509_cert);
1034: return CURLE_SSL_ISSUER_ERROR;
1035: }
1036: infof(data, "\t server certificate issuer check OK (Issuer Cert: %s)\n",
1037: SSL_SET_OPTION(issuercert)?SSL_SET_OPTION(issuercert):"none");
1038: }
1039:
1040: size = sizeof(certname);
1041: rc = gnutls_x509_crt_get_dn_by_oid(x509_cert, GNUTLS_OID_X520_COMMON_NAME,
1042: 0, /* the first and only one */
1043: FALSE,
1044: certname,
1045: &size);
1046: if(rc) {
1047: infof(data, "error fetching CN from cert:%s\n",
1048: gnutls_strerror(rc));
1049: }
1050:
1051: /* This function will check if the given certificate's subject matches the
1052: given hostname. This is a basic implementation of the matching described
1053: in RFC2818 (HTTPS), which takes into account wildcards, and the subject
1054: alternative name PKIX extension. Returns non zero on success, and zero on
1055: failure. */
1056: rc = gnutls_x509_crt_check_hostname(x509_cert, hostname);
1057: #if GNUTLS_VERSION_NUMBER < 0x030306
1058: /* Before 3.3.6, gnutls_x509_crt_check_hostname() didn't check IP
1059: addresses. */
1060: if(!rc) {
1061: #ifdef ENABLE_IPV6
1062: #define use_addr in6_addr
1063: #else
1064: #define use_addr in_addr
1065: #endif
1066: unsigned char addrbuf[sizeof(struct use_addr)];
1067: size_t addrlen = 0;
1068:
1069: if(Curl_inet_pton(AF_INET, hostname, addrbuf) > 0)
1070: addrlen = 4;
1071: #ifdef ENABLE_IPV6
1072: else if(Curl_inet_pton(AF_INET6, hostname, addrbuf) > 0)
1073: addrlen = 16;
1074: #endif
1075:
1076: if(addrlen) {
1077: unsigned char certaddr[sizeof(struct use_addr)];
1078: int i;
1079:
1080: for(i = 0; ; i++) {
1081: size_t certaddrlen = sizeof(certaddr);
1082: int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr,
1083: &certaddrlen, NULL);
1084: /* If this happens, it wasn't an IP address. */
1085: if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
1086: continue;
1087: if(ret < 0)
1088: break;
1089: if(ret != GNUTLS_SAN_IPADDRESS)
1090: continue;
1091: if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) {
1092: rc = 1;
1093: break;
1094: }
1095: }
1096: }
1097: }
1098: #endif
1099: if(!rc) {
1100: const char * const dispname = SSL_IS_PROXY() ?
1101: conn->http_proxy.host.dispname : conn->host.dispname;
1102:
1103: if(SSL_CONN_CONFIG(verifyhost)) {
1104: failf(data, "SSL: certificate subject name (%s) does not match "
1105: "target host name '%s'", certname, dispname);
1106: gnutls_x509_crt_deinit(x509_cert);
1107: return CURLE_PEER_FAILED_VERIFICATION;
1108: }
1109: else
1110: infof(data, "\t common name: %s (does not match '%s')\n",
1111: certname, dispname);
1112: }
1113: else
1114: infof(data, "\t common name: %s (matched)\n", certname);
1115:
1116: /* Check for time-based validity */
1117: certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1118:
1119: if(certclock == (time_t)-1) {
1120: if(SSL_CONN_CONFIG(verifypeer)) {
1121: failf(data, "server cert expiration date verify failed");
1122: gnutls_x509_crt_deinit(x509_cert);
1123: return CURLE_SSL_CONNECT_ERROR;
1124: }
1125: else
1126: infof(data, "\t server certificate expiration date verify FAILED\n");
1127: }
1128: else {
1129: if(certclock < time(NULL)) {
1130: if(SSL_CONN_CONFIG(verifypeer)) {
1131: failf(data, "server certificate expiration date has passed.");
1132: gnutls_x509_crt_deinit(x509_cert);
1133: return CURLE_PEER_FAILED_VERIFICATION;
1134: }
1135: else
1136: infof(data, "\t server certificate expiration date FAILED\n");
1137: }
1138: else
1139: infof(data, "\t server certificate expiration date OK\n");
1140: }
1141:
1142: certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1143:
1144: if(certclock == (time_t)-1) {
1145: if(SSL_CONN_CONFIG(verifypeer)) {
1146: failf(data, "server cert activation date verify failed");
1147: gnutls_x509_crt_deinit(x509_cert);
1148: return CURLE_SSL_CONNECT_ERROR;
1149: }
1150: else
1151: infof(data, "\t server certificate activation date verify FAILED\n");
1152: }
1153: else {
1154: if(certclock > time(NULL)) {
1155: if(SSL_CONN_CONFIG(verifypeer)) {
1156: failf(data, "server certificate not activated yet.");
1157: gnutls_x509_crt_deinit(x509_cert);
1158: return CURLE_PEER_FAILED_VERIFICATION;
1159: }
1160: else
1161: infof(data, "\t server certificate activation date FAILED\n");
1162: }
1163: else
1164: infof(data, "\t server certificate activation date OK\n");
1165: }
1166:
1167: ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1168: data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
1169: if(ptr) {
1170: result = pkp_pin_peer_pubkey(data, x509_cert, ptr);
1171: if(result != CURLE_OK) {
1172: failf(data, "SSL: public key does not match pinned public key!");
1173: gnutls_x509_crt_deinit(x509_cert);
1174: return result;
1175: }
1176: }
1177:
1178: /* Show:
1179:
1180: - subject
1181: - start date
1182: - expire date
1183: - common name
1184: - issuer
1185:
1186: */
1187:
1188: #ifndef CURL_DISABLE_VERBOSE_STRINGS
1189: /* public key algorithm's parameters */
1190: algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
1191: infof(data, "\t certificate public key: %s\n",
1192: gnutls_pk_algorithm_get_name(algo));
1193:
1194: /* version of the X.509 certificate. */
1195: infof(data, "\t certificate version: #%d\n",
1196: gnutls_x509_crt_get_version(x509_cert));
1197:
1198:
1199: rc = gnutls_x509_crt_get_dn2(x509_cert, &certfields);
1200: if(rc != 0)
1201: return CURLE_OUT_OF_MEMORY;
1202: infof(data, "\t subject: %s\n", certfields.data);
1203:
1204: certclock = gnutls_x509_crt_get_activation_time(x509_cert);
1205: showtime(data, "start date", certclock);
1206:
1207: certclock = gnutls_x509_crt_get_expiration_time(x509_cert);
1208: showtime(data, "expire date", certclock);
1209:
1210: rc = gnutls_x509_crt_get_issuer_dn2(x509_cert, &certfields);
1211: if(rc != 0)
1212: return CURLE_OUT_OF_MEMORY;
1213: infof(data, "\t issuer: %s\n", certfields.data);
1214: #endif
1215:
1216: gnutls_x509_crt_deinit(x509_cert);
1217:
1218: if(conn->bits.tls_enable_alpn) {
1219: rc = gnutls_alpn_get_selected_protocol(session, &proto);
1220: if(rc == 0) {
1221: infof(data, "ALPN, server accepted to use %.*s\n", proto.size,
1222: proto.data);
1223:
1224: #ifdef USE_NGHTTP2
1225: if(proto.size == NGHTTP2_PROTO_VERSION_ID_LEN &&
1226: !memcmp(NGHTTP2_PROTO_VERSION_ID, proto.data,
1227: NGHTTP2_PROTO_VERSION_ID_LEN)) {
1228: conn->negnpn = CURL_HTTP_VERSION_2;
1229: }
1230: else
1231: #endif
1232: if(proto.size == ALPN_HTTP_1_1_LENGTH &&
1233: !memcmp(ALPN_HTTP_1_1, proto.data, ALPN_HTTP_1_1_LENGTH)) {
1234: conn->negnpn = CURL_HTTP_VERSION_1_1;
1235: }
1236: }
1237: else
1238: infof(data, "ALPN, server did not agree to a protocol\n");
1239:
1240: Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
1241: BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
1242: }
1243:
1244: conn->ssl[sockindex].state = ssl_connection_complete;
1245: conn->recv[sockindex] = gtls_recv;
1246: conn->send[sockindex] = gtls_send;
1247:
1248: if(SSL_SET_OPTION(primary.sessionid)) {
1249: /* we always unconditionally get the session id here, as even if we
1250: already got it from the cache and asked to use it in the connection, it
1251: might've been rejected and then a new one is in use now and we need to
1252: detect that. */
1253: void *connect_sessionid;
1254: size_t connect_idsize = 0;
1255:
1256: /* get the session ID data size */
1257: gnutls_session_get_data(session, NULL, &connect_idsize);
1258: connect_sessionid = malloc(connect_idsize); /* get a buffer for it */
1259:
1260: if(connect_sessionid) {
1261: bool incache;
1262: void *ssl_sessionid;
1263:
1264: /* extract session ID to the allocated buffer */
1265: gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
1266:
1267: Curl_ssl_sessionid_lock(conn);
1268: incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL,
1269: sockindex));
1270: if(incache) {
1271: /* there was one before in the cache, so instead of risking that the
1272: previous one was rejected, we just kill that and store the new */
1273: Curl_ssl_delsessionid(conn, ssl_sessionid);
1274: }
1275:
1276: /* store this session id */
1277: result = Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize,
1278: sockindex);
1279: Curl_ssl_sessionid_unlock(conn);
1280: if(result) {
1281: free(connect_sessionid);
1282: result = CURLE_OUT_OF_MEMORY;
1283: }
1284: }
1285: else
1286: result = CURLE_OUT_OF_MEMORY;
1287: }
1288:
1289: return result;
1290: }
1291:
1292:
1293: /*
1294: * This function is called after the TCP connect has completed. Setup the TLS
1295: * layer and do all necessary magic.
1296: */
1297: /* We use connssl->connecting_state to keep track of the connection status;
1298: there are three states: 'ssl_connect_1' (not started yet or complete),
1299: 'ssl_connect_2_reading' (waiting for data from server), and
1300: 'ssl_connect_2_writing' (waiting to be able to write).
1301: */
1302: static CURLcode
1303: gtls_connect_common(struct connectdata *conn,
1304: int sockindex,
1305: bool nonblocking,
1306: bool *done)
1307: {
1308: int rc;
1309: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1310:
1311: /* Initiate the connection, if not already done */
1312: if(ssl_connect_1 == connssl->connecting_state) {
1313: rc = gtls_connect_step1(conn, sockindex);
1314: if(rc)
1315: return rc;
1316: }
1317:
1318: rc = handshake(conn, sockindex, TRUE, nonblocking);
1319: if(rc)
1320: /* handshake() sets its own error message with failf() */
1321: return rc;
1322:
1323: /* Finish connecting once the handshake is done */
1324: if(ssl_connect_1 == connssl->connecting_state) {
1325: rc = gtls_connect_step3(conn, sockindex);
1326: if(rc)
1327: return rc;
1328: }
1329:
1330: *done = ssl_connect_1 == connssl->connecting_state;
1331:
1332: return CURLE_OK;
1333: }
1334:
1335: static CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
1336: int sockindex, bool *done)
1337: {
1338: return gtls_connect_common(conn, sockindex, TRUE, done);
1339: }
1340:
1341: static CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex)
1342: {
1343: CURLcode result;
1344: bool done = FALSE;
1345:
1346: result = gtls_connect_common(conn, sockindex, FALSE, &done);
1347: if(result)
1348: return result;
1349:
1350: DEBUGASSERT(done);
1351:
1352: return CURLE_OK;
1353: }
1354:
1355: static bool Curl_gtls_data_pending(const struct connectdata *conn,
1356: int connindex)
1357: {
1358: const struct ssl_connect_data *connssl = &conn->ssl[connindex];
1359: bool res = FALSE;
1360: struct ssl_backend_data *backend = connssl->backend;
1361: if(backend->session &&
1362: 0 != gnutls_record_check_pending(backend->session))
1363: res = TRUE;
1364:
1365: connssl = &conn->proxy_ssl[connindex];
1366: if(backend->session &&
1367: 0 != gnutls_record_check_pending(backend->session))
1368: res = TRUE;
1369:
1370: return res;
1371: }
1372:
1373: static ssize_t gtls_send(struct connectdata *conn,
1374: int sockindex,
1375: const void *mem,
1376: size_t len,
1377: CURLcode *curlcode)
1378: {
1379: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1380: struct ssl_backend_data *backend = connssl->backend;
1381: ssize_t rc = gnutls_record_send(backend->session, mem, len);
1382:
1383: if(rc < 0) {
1384: *curlcode = (rc == GNUTLS_E_AGAIN)
1385: ? CURLE_AGAIN
1386: : CURLE_SEND_ERROR;
1387:
1388: rc = -1;
1389: }
1390:
1391: return rc;
1392: }
1393:
1394: static void close_one(struct ssl_connect_data *connssl)
1395: {
1396: struct ssl_backend_data *backend = connssl->backend;
1397: if(backend->session) {
1398: gnutls_bye(backend->session, GNUTLS_SHUT_WR);
1399: gnutls_deinit(backend->session);
1400: backend->session = NULL;
1401: }
1402: if(backend->cred) {
1403: gnutls_certificate_free_credentials(backend->cred);
1404: backend->cred = NULL;
1405: }
1406: #ifdef USE_TLS_SRP
1407: if(backend->srp_client_cred) {
1408: gnutls_srp_free_client_credentials(backend->srp_client_cred);
1409: backend->srp_client_cred = NULL;
1410: }
1411: #endif
1412: }
1413:
1414: static void Curl_gtls_close(struct connectdata *conn, int sockindex)
1415: {
1416: close_one(&conn->ssl[sockindex]);
1417: close_one(&conn->proxy_ssl[sockindex]);
1418: }
1419:
1420: /*
1421: * This function is called to shut down the SSL layer but keep the
1422: * socket open (CCC - Clear Command Channel)
1423: */
1424: static int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
1425: {
1426: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1427: struct ssl_backend_data *backend = connssl->backend;
1428: int retval = 0;
1429: struct Curl_easy *data = conn->data;
1430:
1431: #ifndef CURL_DISABLE_FTP
1432: /* This has only been tested on the proftpd server, and the mod_tls code
1433: sends a close notify alert without waiting for a close notify alert in
1434: response. Thus we wait for a close notify alert from the server, but
1435: we do not send one. Let's hope other servers do the same... */
1436:
1437: if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
1438: gnutls_bye(backend->session, GNUTLS_SHUT_WR);
1439: #endif
1440:
1441: if(backend->session) {
1442: ssize_t result;
1443: bool done = FALSE;
1444: char buf[120];
1445:
1446: while(!done) {
1447: int what = SOCKET_READABLE(conn->sock[sockindex],
1448: SSL_SHUTDOWN_TIMEOUT);
1449: if(what > 0) {
1450: /* Something to read, let's do it and hope that it is the close
1451: notify alert from the server */
1452: result = gnutls_record_recv(backend->session,
1453: buf, sizeof(buf));
1454: switch(result) {
1455: case 0:
1456: /* This is the expected response. There was no data but only
1457: the close notify alert */
1458: done = TRUE;
1459: break;
1460: case GNUTLS_E_AGAIN:
1461: case GNUTLS_E_INTERRUPTED:
1462: infof(data, "GNUTLS_E_AGAIN || GNUTLS_E_INTERRUPTED\n");
1463: break;
1464: default:
1465: retval = -1;
1466: done = TRUE;
1467: break;
1468: }
1469: }
1470: else if(0 == what) {
1471: /* timeout */
1472: failf(data, "SSL shutdown timeout");
1473: done = TRUE;
1474: }
1475: else {
1476: /* anything that gets here is fatally bad */
1477: failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1478: retval = -1;
1479: done = TRUE;
1480: }
1481: }
1482: gnutls_deinit(backend->session);
1483: }
1484: gnutls_certificate_free_credentials(backend->cred);
1485:
1486: #ifdef USE_TLS_SRP
1487: if(SSL_SET_OPTION(authtype) == CURL_TLSAUTH_SRP
1488: && SSL_SET_OPTION(username) != NULL)
1489: gnutls_srp_free_client_credentials(backend->srp_client_cred);
1490: #endif
1491:
1492: backend->cred = NULL;
1493: backend->session = NULL;
1494:
1495: return retval;
1496: }
1497:
1498: static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
1499: int num, /* socketindex */
1500: char *buf, /* store read data here */
1501: size_t buffersize, /* max amount to read */
1502: CURLcode *curlcode)
1503: {
1504: struct ssl_connect_data *connssl = &conn->ssl[num];
1505: struct ssl_backend_data *backend = connssl->backend;
1506: ssize_t ret;
1507:
1508: ret = gnutls_record_recv(backend->session, buf, buffersize);
1509: if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
1510: *curlcode = CURLE_AGAIN;
1511: return -1;
1512: }
1513:
1514: if(ret == GNUTLS_E_REHANDSHAKE) {
1515: /* BLOCKING call, this is bad but a work-around for now. Fixing this "the
1516: proper way" takes a whole lot of work. */
1517: CURLcode result = handshake(conn, num, FALSE, FALSE);
1518: if(result)
1519: /* handshake() writes error message on its own */
1520: *curlcode = result;
1521: else
1522: *curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
1523: return -1;
1524: }
1525:
1526: if(ret < 0) {
1527: failf(conn->data, "GnuTLS recv error (%d): %s",
1528:
1529: (int)ret, gnutls_strerror((int)ret));
1530: *curlcode = CURLE_RECV_ERROR;
1531: return -1;
1532: }
1533:
1534: return ret;
1535: }
1536:
1537: static void Curl_gtls_session_free(void *ptr)
1538: {
1539: free(ptr);
1540: }
1541:
1542: static size_t Curl_gtls_version(char *buffer, size_t size)
1543: {
1544: return msnprintf(buffer, size, "GnuTLS/%s", gnutls_check_version(NULL));
1545: }
1546:
1547: #ifndef USE_GNUTLS_NETTLE
1548: static int Curl_gtls_seed(struct Curl_easy *data)
1549: {
1550: /* we have the "SSL is seeded" boolean static to prevent multiple
1551: time-consuming seedings in vain */
1552: static bool ssl_seeded = FALSE;
1553:
1554: /* Quickly add a bit of entropy */
1555: gcry_fast_random_poll();
1556:
1557: if(!ssl_seeded || data->set.str[STRING_SSL_RANDOM_FILE] ||
1558: data->set.str[STRING_SSL_EGDSOCKET]) {
1559: ssl_seeded = TRUE;
1560: }
1561: return 0;
1562: }
1563: #endif
1564:
1565: /* data might be NULL! */
1566: static CURLcode Curl_gtls_random(struct Curl_easy *data,
1567: unsigned char *entropy, size_t length)
1568: {
1569: #if defined(USE_GNUTLS_NETTLE)
1570: int rc;
1571: (void)data;
1572: rc = gnutls_rnd(GNUTLS_RND_RANDOM, entropy, length);
1573: return rc?CURLE_FAILED_INIT:CURLE_OK;
1574: #elif defined(USE_GNUTLS)
1575: if(data)
1576: Curl_gtls_seed(data); /* Initiate the seed if not already done */
1577: gcry_randomize(entropy, length, GCRY_STRONG_RANDOM);
1578: #endif
1579: return CURLE_OK;
1580: }
1581:
1582: static CURLcode Curl_gtls_md5sum(unsigned char *tmp, /* input */
1583: size_t tmplen,
1584: unsigned char *md5sum, /* output */
1585: size_t md5len)
1586: {
1587: #if defined(USE_GNUTLS_NETTLE)
1588: struct md5_ctx MD5pw;
1589: md5_init(&MD5pw);
1590: md5_update(&MD5pw, (unsigned int)tmplen, tmp);
1591: md5_digest(&MD5pw, (unsigned int)md5len, md5sum);
1592: #elif defined(USE_GNUTLS)
1593: gcry_md_hd_t MD5pw;
1594: gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
1595: gcry_md_write(MD5pw, tmp, tmplen);
1596: memcpy(md5sum, gcry_md_read(MD5pw, 0), md5len);
1597: gcry_md_close(MD5pw);
1598: #endif
1599: return CURLE_OK;
1600: }
1601:
1602: static CURLcode Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
1603: size_t tmplen,
1604: unsigned char *sha256sum, /* output */
1605: size_t sha256len)
1606: {
1607: #if defined(USE_GNUTLS_NETTLE)
1608: struct sha256_ctx SHA256pw;
1609: sha256_init(&SHA256pw);
1610: sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
1611: sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
1612: #elif defined(USE_GNUTLS)
1613: gcry_md_hd_t SHA256pw;
1614: gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
1615: gcry_md_write(SHA256pw, tmp, tmplen);
1616: memcpy(sha256sum, gcry_md_read(SHA256pw, 0), sha256len);
1617: gcry_md_close(SHA256pw);
1618: #endif
1619: return CURLE_OK;
1620: }
1621:
1622: static bool Curl_gtls_cert_status_request(void)
1623: {
1624: return TRUE;
1625: }
1626:
1627: static void *Curl_gtls_get_internals(struct ssl_connect_data *connssl,
1628: CURLINFO info UNUSED_PARAM)
1629: {
1630: struct ssl_backend_data *backend = connssl->backend;
1631: (void)info;
1632: return backend->session;
1633: }
1634:
1635: const struct Curl_ssl Curl_ssl_gnutls = {
1636: { CURLSSLBACKEND_GNUTLS, "gnutls" }, /* info */
1637:
1638: SSLSUPP_CA_PATH |
1639: SSLSUPP_CERTINFO |
1640: SSLSUPP_PINNEDPUBKEY |
1641: SSLSUPP_HTTPS_PROXY,
1642:
1643: sizeof(struct ssl_backend_data),
1644:
1645: Curl_gtls_init, /* init */
1646: Curl_gtls_cleanup, /* cleanup */
1647: Curl_gtls_version, /* version */
1648: Curl_none_check_cxn, /* check_cxn */
1649: Curl_gtls_shutdown, /* shutdown */
1650: Curl_gtls_data_pending, /* data_pending */
1651: Curl_gtls_random, /* random */
1652: Curl_gtls_cert_status_request, /* cert_status_request */
1653: Curl_gtls_connect, /* connect */
1654: Curl_gtls_connect_nonblocking, /* connect_nonblocking */
1655: Curl_gtls_get_internals, /* get_internals */
1656: Curl_gtls_close, /* close_one */
1657: Curl_none_close_all, /* close_all */
1658: Curl_gtls_session_free, /* session_free */
1659: Curl_none_set_engine, /* set_engine */
1660: Curl_none_set_engine_default, /* set_engine_default */
1661: Curl_none_engines_list, /* engines_list */
1662: Curl_none_false_start, /* false_start */
1663: Curl_gtls_md5sum, /* md5sum */
1664: Curl_gtls_sha256sum /* sha256sum */
1665: };
1666:
1667: #endif /* USE_GNUTLS */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>