1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 2010, DirecTV 9 * contact: Eric Hu <ehu@directv.com> 10 * 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. 14 * 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. 18 * 19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20 * KIND, either express or implied. 21 * 22 ***************************************************************************/ 23 24/* 25 * Source file for all axTLS-specific code for the TLS/SSL layer. No code 26 * but sslgen.c should ever call or use these functions. 27 */ 28 29#include "setup.h" 30#ifdef USE_AXTLS 31#include <axTLS/ssl.h> 32#include "axtls.h" 33 34#include <string.h> 35#include <stdlib.h> 36#include <ctype.h> 37#ifdef HAVE_SYS_SOCKET_H 38#include <sys/socket.h> 39#endif 40 41#include "sendf.h" 42#include "inet_pton.h" 43#include "sslgen.h" 44#include "parsedate.h" 45#include "connect.h" /* for the connect timeout */ 46#include "select.h" 47#define _MPRINTF_REPLACE /* use our functions only */ 48#include <curl/mprintf.h> 49#include "curl_memory.h" 50/* The last #include file should be: */ 51#include "memdebug.h" 52 53/* SSL_read is opied from axTLS compat layer */ 54static int SSL_read(SSL *ssl, void *buf, int num) 55{ 56 uint8_t *read_buf; 57 int ret; 58 59 while((ret = ssl_read(ssl, &read_buf)) == SSL_OK); 60 61 if(ret > SSL_OK){ 62 memcpy(buf, read_buf, ret > num ? num : ret); 63 } 64 65 return ret; 66} 67 68/* Global axTLS init, called from Curl_ssl_init() */ 69int Curl_axtls_init(void) 70{ 71/* axTLS has no global init. Everything is done through SSL and SSL_CTX 72 * structs stored in connectdata structure. Perhaps can move to axtls.h. 73 */ 74 return 1; 75} 76 77int Curl_axtls_cleanup(void) 78{ 79 /* axTLS has no global cleanup. Perhaps can move this to axtls.h. */ 80 return 1; 81} 82 83static CURLcode map_error_to_curl(int axtls_err) 84{ 85 switch (axtls_err) { 86 case SSL_ERROR_NOT_SUPPORTED: 87 case SSL_ERROR_INVALID_VERSION: 88 case -70: /* protocol version alert from server */ 89 return CURLE_UNSUPPORTED_PROTOCOL; 90 break; 91 case SSL_ERROR_NO_CIPHER: 92 return CURLE_SSL_CIPHER; 93 break; 94 case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */ 95 case SSL_ERROR_NO_CERT_DEFINED: 96 case -42: /* bad certificate alert from server */ 97 case -43: /* unsupported cert alert from server */ 98 case -44: /* cert revoked alert from server */ 99 case -45: /* cert expired alert from server */ 100 case -46: /* cert unknown alert from server */ 101 return CURLE_SSL_CERTPROBLEM; 102 break; 103 case SSL_X509_ERROR(X509_NOT_OK): 104 case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT): 105 case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE): 106 case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID): 107 case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED): 108 case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED): 109 case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN): 110 case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST): 111 case SSL_X509_ERROR(X509_INVALID_PRIV_KEY): 112 return CURLE_PEER_FAILED_VERIFICATION; 113 break; 114 case -48: /* unknown ca alert from server */ 115 return CURLE_SSL_CACERT; 116 break; 117 case -49: /* access denied alert from server */ 118 return CURLE_REMOTE_ACCESS_DENIED; 119 break; 120 case SSL_ERROR_CONN_LOST: 121 case SSL_ERROR_SOCK_SETUP_FAILURE: 122 case SSL_ERROR_INVALID_HANDSHAKE: 123 case SSL_ERROR_INVALID_PROT_MSG: 124 case SSL_ERROR_INVALID_HMAC: 125 case SSL_ERROR_INVALID_SESSION: 126 case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */ 127 case SSL_ERROR_FINISHED_INVALID: 128 case SSL_ERROR_NO_CLIENT_RENOG: 129 default: 130 return CURLE_SSL_CONNECT_ERROR; 131 break; 132 } 133} 134 135static Curl_recv axtls_recv; 136static Curl_send axtls_send; 137 138/* 139 * This function is called after the TCP connect has completed. Setup the TLS 140 * layer and do all necessary magic. 141 */ 142CURLcode 143Curl_axtls_connect(struct connectdata *conn, 144 int sockindex) 145 146{ 147 struct SessionHandle *data = conn->data; 148 SSL_CTX *ssl_ctx; 149 SSL *ssl; 150 int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0}; 151 int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0}; 152 int i, ssl_fcn_return; 153 const uint8_t *ssl_sessionid; 154 size_t ssl_idsize; 155 const char *x509; 156 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; 159 160 if(conn->ssl[sockindex].state == ssl_connection_complete) 161 /* to make us tolerant against being called more than once for the 162 same connection */ 163 return CURLE_OK; 164 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: 170 break; 171 default: 172 failf(data, "axTLS only supports TLSv1"); 173 return CURLE_SSL_CONNECT_ERROR; 174 } 175 176#ifdef AXTLSDEBUG 177 client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS; 178#endif /* AXTLSDEBUG */ 179 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; 185 } 186 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) 190 != SSL_OK){ 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; 196 } 197 } 198 else 199 infof(data, "found certificates in %s\n", data->set.ssl.CAfile); 200 } 201 202 /* 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. 208 */ 209 210 /* Load client certificate */ 211 if(data->set.str[STRING_CERT]){ 212 i=0; 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]); 220 break; 221 } 222 i++; 223 } 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; 230 } 231 } 232 233 /* Load client key. 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){ 237 i=0; 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]); 245 break; 246 } 247 i++; 248 } 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; 255 } 256 } 257 258 /* 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 262 */ 263 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); 270 } 271 else 272 ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0); 273 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); 280 } 281 infof (data, "handshake completed successfully\n"); 282 283 /* Here, 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? 285 */ 286 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; 293 } 294 } 295 else 296 infof(data, "\t server certificate verification SKIPPED\n"); 297 298 /* Here, gtls.c does issuer verification. axTLS has no straightforward 299 * equivalent, so omitting for now.*/ 300 301 /* See if common name was set in server certificate */ 302 x509 = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); 303 if(x509 == NULL) 304 infof(data, "error fetching CN from cert\n"); 305 306 /* Here, gtls.c does the following 307 * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but 308 * it seems useful. Omitting for now. 309 * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert 310 * 3) displays a bunch of cert information. axTLS doesn't support most of 311 * this, but a couple fields are available. 312 */ 313 314 /* General housekeeping */ 315 conn->ssl[sockindex].state = ssl_connection_complete; 316 conn->ssl[sockindex].ssl = ssl; 317 conn->ssl[sockindex].ssl_ctx = ssl_ctx; 318 conn->recv[sockindex] = axtls_recv; 319 conn->send[sockindex] = axtls_send; 320 321 /* Put our freshly minted SSL session in cache */ 322 ssl_idsize = ssl_get_session_id_size(ssl); 323 ssl_sessionid = ssl_get_session_id(ssl); 324 if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize) 325 != CURLE_OK) 326 infof (data, "failed to add session to cache\n"); 327 328 return CURLE_OK; 329} 330 331 332/* return number of sent (non-SSL) bytes */ 333static ssize_t axtls_send(struct connectdata *conn, 334 int sockindex, 335 const void *mem, 336 size_t len, 337 CURLcode *err) 338{ 339 /* ssl_write() returns 'int' while write() and send() returns 'size_t' */ 340 int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len); 341 342 infof(conn->data, " axtls_send\n"); 343 344 if(rc < 0 ) { 345 *err = map_error_to_curl(rc); 346 rc = -1; /* generic error code for send failure */ 347 } 348 349 *err = CURLE_OK; 350 return rc; 351} 352 353void Curl_axtls_close_all(struct SessionHandle *data) 354{ 355 (void)data; 356 infof(data, " Curl_axtls_close_all\n"); 357} 358 359void Curl_axtls_close(struct connectdata *conn, int sockindex) 360{ 361 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 362 363 infof(conn->data, " Curl_axtls_close\n"); 364 if(connssl->ssl) { 365 /* line from ssluse.c: (void)SSL_shutdown(connssl->ssl); 366 axTLS compat layer does nothing for SSL_shutdown */ 367 368 /* The following line is from ssluse.c. There seems to be no axTLS 369 equivalent. ssl_free and ssl_ctx_free close things. 370 SSL_set_connect_state(connssl->handle); */ 371 372 ssl_free (connssl->ssl); 373 connssl->ssl = NULL; 374 } 375 if(connssl->ssl_ctx) { 376 ssl_ctx_free (connssl->ssl_ctx); 377 connssl->ssl_ctx = NULL; 378 } 379} 380 381/* 382 * This function is called to shut down the SSL layer but keep the 383 * socket open (CCC - Clear Command Channel) 384 */ 385int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) 386{ 387 /* Outline taken from ssluse.c since functions are in axTLS compat layer. 388 axTLS's error set is much smaller, so a lot of error-handling was removed. 389 */ 390 int retval = 0; 391 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 392 struct SessionHandle *data = conn->data; 393 char buf[120]; /* We will use this for the OpenSSL error buffer, so it has 394 to be at least 120 bytes long. */ 395 ssize_t nread; 396 397 infof(conn->data, " Curl_axtls_shutdown\n"); 398 399 /* This has only been tested on the proftpd server, and the mod_tls code 400 sends a close notify alert without waiting for a close notify alert in 401 response. Thus we wait for a close notify alert from the server, but 402 we do not send one. Let's hope other servers do the same... */ 403 404 /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too 405 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) 406 (void)SSL_shutdown(connssl->ssl); 407 */ 408 409 if(connssl->ssl) { 410 int what = Curl_socket_ready(conn->sock[sockindex], 411 CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); 412 if(what > 0) { 413 /* Something to read, let's do it and hope that it is the close 414 notify alert from the server */ 415 nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf, 416 sizeof(buf)); 417 418 if(nread < SSL_OK){ 419 failf(data, "close notify alert not received during shutdown"); 420 retval = -1; 421 } 422 } 423 else if(0 == what) { 424 /* timeout */ 425 failf(data, "SSL shutdown timeout"); 426 } 427 else { 428 /* anything that gets here is fatally bad */ 429 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 430 retval = -1; 431 } 432 433 ssl_free (connssl->ssl); 434 connssl->ssl = NULL; 435 } 436 return retval; 437} 438 439static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ 440 int num, /* socketindex */ 441 char *buf, /* store read data here */ 442 size_t buffersize, /* max amount to read */ 443 CURLcode *err) 444{ 445 struct ssl_connect_data *connssl = &conn->ssl[num]; 446 ssize_t ret = 0; 447 448 infof(conn->data, " axtls_recv\n"); 449 450 if(connssl){ 451 ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize); 452 453 /* axTLS isn't terribly generous about error reporting */ 454 /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS 455 team approves proposed fix. */ 456 if(ret == -3 ){ 457 Curl_axtls_close(conn, num); 458 } 459 else if(ret < 0) { 460 failf(conn->data, "axTLS recv error (%d)", (int)ret); 461 *err = map_error_to_curl(ret); 462 return -1; 463 } 464 } 465 466 *err = CURLE_OK; 467 return ret; 468} 469 470/* 471 * Return codes: 472 * 1 means the connection is still in place 473 * 0 means the connection has been closed 474 * -1 means the connection status is unknown 475 */ 476int Curl_axtls_check_cxn(struct connectdata *conn) 477{ 478 /* ssluse.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1); 479 axTLS compat layer always returns the last argument, so connection is 480 always alive? */ 481 482 infof(conn->data, " Curl_axtls_check_cxn\n"); 483 return 1; /* connection still in place */ 484} 485 486void Curl_axtls_session_free(void *ptr) 487{ 488 (void)ptr; 489 /* free the ID */ 490 /* both ssluse.c and gtls.c do something here, but axTLS's OpenSSL 491 compatibility layer does nothing, so we do nothing too. */ 492} 493 494size_t Curl_axtls_version(char *buffer, size_t size) 495{ 496 return snprintf(buffer, size, "axTLS/%s", ssl_version()); 497} 498 499#endif /* USE_AXTLS */ 500