1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 2010, DirecTV * contact: Eric Hu <ehu@directv.com>
9 * Copyright (C) 2010 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
11 * This software is licensed as described in the file COPYING, which
12 * you should have received as part of this distribution. The terms
13 * are also available at http://curl.haxx.se/docs/copyright.html.
15 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
16 * copies of the Software, and permit persons to whom the Software is
17 * furnished to do so, under the terms of the COPYING file.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ***************************************************************************/
25 * Source file for all axTLS-specific code for the TLS/SSL layer. No code
26 * but curl_sslgen.c should ever call or use these functions.
29 #include "curl_setup.h"
32 #include <axTLS/ssl.h>
33 #include "curl_axtls.h"
35 #include "curl_sendf.h"
36 #include "curl_inet_pton.h"
37 #include "curl_sslgen.h"
38 #include "curl_parsedate.h"
39 #include "curl_connect.h" /* for the connect timeout */
40 #include "curl_select.h"
41 #define _MPRINTF_REPLACE /* use our functions only */
42 #include <curl/mprintf.h>
43 #include "curl_memory.h"
44 /* The last #include file should be: */
45 #include "curl_memdebug.h"
46 #include "curl_hostcheck.h"
49 /* SSL_read is opied from axTLS compat layer */
50 static int SSL_read(SSL *ssl, void *buf, int num)
55 while((ret = ssl_read(ssl, &read_buf)) == SSL_OK);
58 memcpy(buf, read_buf, ret > num ? num : ret);
64 /* Global axTLS init, called from Curl_ssl_init() */
65 int Curl_axtls_init(void)
67 /* axTLS has no global init. Everything is done through SSL and SSL_CTX
68 * structs stored in connectdata structure. Perhaps can move to curl_axtls.h.
73 int Curl_axtls_cleanup(void)
75 /* axTLS has no global cleanup. Perhaps can move this to curl_axtls.h. */
79 static CURLcode map_error_to_curl(int axtls_err)
82 case SSL_ERROR_NOT_SUPPORTED:
83 case SSL_ERROR_INVALID_VERSION:
84 case -70: /* protocol version alert from server */
85 return CURLE_UNSUPPORTED_PROTOCOL;
87 case SSL_ERROR_NO_CIPHER:
88 return CURLE_SSL_CIPHER;
90 case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */
91 case SSL_ERROR_NO_CERT_DEFINED:
92 case -42: /* bad certificate alert from server */
93 case -43: /* unsupported cert alert from server */
94 case -44: /* cert revoked alert from server */
95 case -45: /* cert expired alert from server */
96 case -46: /* cert unknown alert from server */
97 return CURLE_SSL_CERTPROBLEM;
99 case SSL_X509_ERROR(X509_NOT_OK):
100 case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
101 case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
102 case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
103 case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
104 case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED):
105 case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN):
106 case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
107 case SSL_X509_ERROR(X509_INVALID_PRIV_KEY):
108 return CURLE_PEER_FAILED_VERIFICATION;
110 case -48: /* unknown ca alert from server */
111 return CURLE_SSL_CACERT;
113 case -49: /* access denied alert from server */
114 return CURLE_REMOTE_ACCESS_DENIED;
116 case SSL_ERROR_CONN_LOST:
117 case SSL_ERROR_SOCK_SETUP_FAILURE:
118 case SSL_ERROR_INVALID_HANDSHAKE:
119 case SSL_ERROR_INVALID_PROT_MSG:
120 case SSL_ERROR_INVALID_HMAC:
121 case SSL_ERROR_INVALID_SESSION:
122 case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */
123 case SSL_ERROR_FINISHED_INVALID:
124 case SSL_ERROR_NO_CLIENT_RENOG:
126 return CURLE_SSL_CONNECT_ERROR;
131 static Curl_recv axtls_recv;
132 static Curl_send axtls_send;
135 * This function is called after the TCP connect has completed. Setup the TLS
136 * layer and do all necessary magic.
139 Curl_axtls_connect(struct connectdata *conn,
143 struct SessionHandle *data = conn->data;
146 int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
147 int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
148 int i, ssl_fcn_return;
149 const uint8_t *ssl_sessionid;
152 uint32_t dns_altname_index;
153 const char *dns_altname;
154 int8_t found_subject_alt_names = 0;
155 int8_t found_subject_alt_name_matching_conn = 0;
157 /* Assuming users will not compile in custom key/cert to axTLS */
158 uint32_t client_option = SSL_NO_DEFAULT_KEY|SSL_SERVER_VERIFY_LATER;
160 if(conn->ssl[sockindex].state == ssl_connection_complete)
161 /* to make us tolerant against being called more than once for the
165 /* axTLS only supports TLSv1 */
166 /* check to see if we've been told to use an explicit SSL/TLS version */
167 switch(data->set.ssl.version) {
168 case CURL_SSLVERSION_DEFAULT:
169 case CURL_SSLVERSION_TLSv1:
172 failf(data, "axTLS only supports TLSv1");
173 return CURLE_SSL_CONNECT_ERROR;
177 client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
178 #endif /* AXTLSDEBUG */
180 /* Allocate an SSL_CTX struct */
181 ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
182 if(ssl_ctx == NULL) {
183 failf(data, "unable to create client SSL context");
184 return CURLE_SSL_CONNECT_ERROR;
187 /* Load the trusted CA cert bundle file */
188 if(data->set.ssl.CAfile) {
189 if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL)
191 infof(data, "error reading ca cert file %s \n",
192 data->set.ssl.CAfile);
193 if(data->set.ssl.verifypeer) {
194 Curl_axtls_close(conn, sockindex);
195 return CURLE_SSL_CACERT_BADFILE;
199 infof(data, "found certificates in %s\n", data->set.ssl.CAfile);
202 /* curl_gtls.c tasks we're skipping for now:
203 * 1) certificate revocation list checking
204 * 2) dns name assignment to host
205 * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore
206 * 4) set certificate priority. axTLS ignores type and sends certs in
207 * order added. can probably ignore this.
210 /* Load client certificate */
211 if(data->set.str[STRING_CERT]) {
213 /* Instead of trying to analyze cert type here, let axTLS try them all. */
214 while(cert_types[i] != 0) {
215 ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
216 data->set.str[STRING_CERT], NULL);
217 if(ssl_fcn_return == SSL_OK) {
218 infof(data, "successfully read cert file %s \n",
219 data->set.str[STRING_CERT]);
224 /* Tried all cert types, none worked. */
225 if(cert_types[i] == 0) {
226 failf(data, "%s is not x509 or pkcs12 format",
227 data->set.str[STRING_CERT]);
228 Curl_axtls_close(conn, sockindex);
229 return CURLE_SSL_CERTPROBLEM;
234 If a pkcs12 file successfully loaded a cert, then there's nothing to do
235 because the key has already been loaded. */
236 if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) {
238 /* Instead of trying to analyze key type here, let axTLS try them all. */
239 while(key_types[i] != 0) {
240 ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
241 data->set.str[STRING_KEY], NULL);
242 if(ssl_fcn_return == SSL_OK) {
243 infof(data, "successfully read key file %s \n",
244 data->set.str[STRING_KEY]);
249 /* Tried all key types, none worked. */
250 if(key_types[i] == 0) {
251 failf(data, "Failure: %s is not a supported key file",
252 data->set.str[STRING_KEY]);
253 Curl_axtls_close(conn, sockindex);
254 return CURLE_SSL_CONNECT_ERROR;
258 /* curl_gtls.c does more here that is being left out for now
259 * 1) set session credentials. can probably ignore since axtls puts this
260 * info in the ssl_ctx struct
261 * 2) setting up callbacks. these seem gnutls specific
264 /* In axTLS, handshaking happens inside ssl_client_new. */
265 if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) {
266 /* we got a session id, use it! */
267 infof (data, "SSL re-using session ID\n");
268 ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
269 ssl_sessionid, (uint8_t)ssl_idsize);
272 ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0);
274 /* Check to make sure handshake was ok. */
275 ssl_fcn_return = ssl_handshake_status(ssl);
276 if(ssl_fcn_return != SSL_OK) {
277 Curl_axtls_close(conn, sockindex);
278 ssl_display_error(ssl_fcn_return); /* goes to stdout. */
279 return map_error_to_curl(ssl_fcn_return);
281 infof (data, "handshake completed successfully\n");
283 /* Here, curl_gtls.c gets the peer certificates and fails out depending on
284 * settings in "data." axTLS api doesn't have get cert chain fcn, so omit?
287 /* Verify server's certificate */
288 if(data->set.ssl.verifypeer) {
289 if(ssl_verify_cert(ssl) != SSL_OK) {
290 Curl_axtls_close(conn, sockindex);
291 failf(data, "server cert verify failed");
292 return CURLE_SSL_CONNECT_ERROR;
296 infof(data, "\t server certificate verification SKIPPED\n");
298 /* Here, curl_gtls.c does issuer verification. axTLS has no straightforward
299 * equivalent, so omitting for now.*/
301 /* Here, curl_gtls.c does the following
302 * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but
303 * it seems useful. This is now implemented, by Oscar Koeroo
304 * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert
305 * 3) displays a bunch of cert information. axTLS doesn't support most of
306 * this, but a couple fields are available.
310 /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
311 risk of an inifite loop */
312 for(dns_altname_index = 0; ; dns_altname_index++) {
313 dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index);
314 if(dns_altname == NULL) {
317 found_subject_alt_names = 1;
319 infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
320 dns_altname, conn->host.name);
321 if(Curl_cert_hostcheck(dns_altname, conn->host.name)) {
322 found_subject_alt_name_matching_conn = 1;
328 if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
329 /* Break connection ! */
330 Curl_axtls_close(conn, sockindex);
331 failf(data, "\tsubjectAltName(s) do not match %s\n", conn->host.dispname);
332 return CURLE_PEER_FAILED_VERIFICATION;
334 else if(found_subject_alt_names == 0) {
335 /* Per RFC2818, when no Subject Alt Names were available, examine the peer
336 CN as a legacy fallback */
337 peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
338 if(peer_CN == NULL) {
339 /* Similar behaviour to the OpenSSL interface */
340 Curl_axtls_close(conn, sockindex);
341 failf(data, "unable to obtain common name from peer certificate");
342 return CURLE_PEER_FAILED_VERIFICATION;
345 if(!Curl_cert_hostcheck((const char *)peer_CN, conn->host.name)) {
346 if(data->set.ssl.verifyhost) {
347 /* Break connection ! */
348 Curl_axtls_close(conn, sockindex);
349 failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
350 peer_CN, conn->host.dispname);
351 return CURLE_PEER_FAILED_VERIFICATION;
354 infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
355 peer_CN, conn->host.dispname);
360 /* General housekeeping */
361 conn->ssl[sockindex].state = ssl_connection_complete;
362 conn->ssl[sockindex].ssl = ssl;
363 conn->ssl[sockindex].ssl_ctx = ssl_ctx;
364 conn->recv[sockindex] = axtls_recv;
365 conn->send[sockindex] = axtls_send;
367 /* Put our freshly minted SSL session in cache */
368 ssl_idsize = ssl_get_session_id_size(ssl);
369 ssl_sessionid = ssl_get_session_id(ssl);
370 if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize)
372 infof (data, "failed to add session to cache\n");
378 /* return number of sent (non-SSL) bytes */
379 static ssize_t axtls_send(struct connectdata *conn,
385 /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
386 int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len);
388 infof(conn->data, " axtls_send\n");
391 *err = map_error_to_curl(rc);
392 rc = -1; /* generic error code for send failure */
399 void Curl_axtls_close_all(struct SessionHandle *data)
402 infof(data, " Curl_axtls_close_all\n");
405 void Curl_axtls_close(struct connectdata *conn, int sockindex)
407 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
409 infof(conn->data, " Curl_axtls_close\n");
411 /* line from curl_ssluse.c: (void)SSL_shutdown(connssl->ssl);
412 axTLS compat layer does nothing for SSL_shutdown */
414 /* The following line is from curl_ssluse.c. There seems to be no axTLS
415 equivalent. ssl_free and ssl_ctx_free close things.
416 SSL_set_connect_state(connssl->handle); */
418 ssl_free (connssl->ssl);
421 if(connssl->ssl_ctx) {
422 ssl_ctx_free (connssl->ssl_ctx);
423 connssl->ssl_ctx = NULL;
428 * This function is called to shut down the SSL layer but keep the
429 * socket open (CCC - Clear Command Channel)
431 int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
433 /* Outline taken from curl_ssluse.c since functions are in axTLS compat
434 layer. axTLS's error set is much smaller, so a lot of error-handling
438 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
439 struct SessionHandle *data = conn->data;
440 char buf[120]; /* We will use this for the OpenSSL error buffer, so it has
441 to be at least 120 bytes long. */
444 infof(conn->data, " Curl_axtls_shutdown\n");
446 /* This has only been tested on the proftpd server, and the mod_tls code
447 sends a close notify alert without waiting for a close notify alert in
448 response. Thus we wait for a close notify alert from the server, but
449 we do not send one. Let's hope other servers do the same... */
451 /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
452 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
453 (void)SSL_shutdown(connssl->ssl);
457 int what = Curl_socket_ready(conn->sock[sockindex],
458 CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT);
460 /* Something to read, let's do it and hope that it is the close
461 notify alert from the server */
462 nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf,
466 failf(data, "close notify alert not received during shutdown");
472 failf(data, "SSL shutdown timeout");
475 /* anything that gets here is fatally bad */
476 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
480 ssl_free (connssl->ssl);
486 static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
487 int num, /* socketindex */
488 char *buf, /* store read data here */
489 size_t buffersize, /* max amount to read */
492 struct ssl_connect_data *connssl = &conn->ssl[num];
495 infof(conn->data, " axtls_recv\n");
498 ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize);
500 /* axTLS isn't terribly generous about error reporting */
501 /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS
502 team approves proposed fix. */
504 Curl_axtls_close(conn, num);
507 failf(conn->data, "axTLS recv error (%d)", (int)ret);
508 *err = map_error_to_curl(ret);
519 * 1 means the connection is still in place
520 * 0 means the connection has been closed
521 * -1 means the connection status is unknown
523 int Curl_axtls_check_cxn(struct connectdata *conn)
525 /* curl_ssluse.c line:
526 rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1);
527 axTLS compat layer always returns the last argument, so connection is
530 infof(conn->data, " Curl_axtls_check_cxn\n");
531 return 1; /* connection still in place */
534 void Curl_axtls_session_free(void *ptr)
538 /* both curl_ssluse.c and curl_gtls.c do something here, but axTLS's
539 OpenSSL compatibility layer does nothing, so we do nothing too. */
542 size_t Curl_axtls_version(char *buffer, size_t size)
544 return snprintf(buffer, size, "axTLS/%s", ssl_version());
547 #endif /* USE_AXTLS */