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 31#ifdef USE_AXTLS 32#include <axTLS/ssl.h> 33#include "axtls.h" 34 35#ifdef HAVE_SYS_SOCKET_H 36#include <sys/socket.h> 37#endif 38 39#include "sendf.h" 40#include "inet_pton.h" 41#include "sslgen.h" 42#include "parsedate.h" 43#include "connect.h" /* for the connect timeout */ 44#include "select.h" 45#define _MPRINTF_REPLACE /* use our functions only */ 46#include <curl/mprintf.h> 47#include "curl_memory.h" 48/* The last #include file should be: */ 49#include "memdebug.h" 50 51/* SSL_read is opied from axTLS compat layer */ 52static int SSL_read(SSL *ssl, void *buf, int num) 53{ 54 uint8_t *read_buf; 55 int ret; 56 57 while((ret = ssl_read(ssl, &read_buf)) == SSL_OK); 58 59 if(ret > SSL_OK) { 60 memcpy(buf, read_buf, ret > num ? num : ret); 61 } 62 63 return ret; 64} 65 66/* Global axTLS init, called from Curl_ssl_init() */ 67int Curl_axtls_init(void) 68{ 69/* axTLS has no global init. Everything is done through SSL and SSL_CTX 70 * structs stored in connectdata structure. Perhaps can move to axtls.h. 71 */ 72 return 1; 73} 74 75int Curl_axtls_cleanup(void) 76{ 77 /* axTLS has no global cleanup. Perhaps can move this to axtls.h. */ 78 return 1; 79} 80 81static CURLcode map_error_to_curl(int axtls_err) 82{ 83 switch (axtls_err) { 84 case SSL_ERROR_NOT_SUPPORTED: 85 case SSL_ERROR_INVALID_VERSION: 86 case -70: /* protocol version alert from server */ 87 return CURLE_UNSUPPORTED_PROTOCOL; 88 break; 89 case SSL_ERROR_NO_CIPHER: 90 return CURLE_SSL_CIPHER; 91 break; 92 case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */ 93 case SSL_ERROR_NO_CERT_DEFINED: 94 case -42: /* bad certificate alert from server */ 95 case -43: /* unsupported cert alert from server */ 96 case -44: /* cert revoked alert from server */ 97 case -45: /* cert expired alert from server */ 98 case -46: /* cert unknown alert from server */ 99 return CURLE_SSL_CERTPROBLEM; 100 break; 101 case SSL_X509_ERROR(X509_NOT_OK): 102 case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT): 103 case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE): 104 case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID): 105 case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED): 106 case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED): 107 case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN): 108 case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST): 109 case SSL_X509_ERROR(X509_INVALID_PRIV_KEY): 110 return CURLE_PEER_FAILED_VERIFICATION; 111 break; 112 case -48: /* unknown ca alert from server */ 113 return CURLE_SSL_CACERT; 114 break; 115 case -49: /* access denied alert from server */ 116 return CURLE_REMOTE_ACCESS_DENIED; 117 break; 118 case SSL_ERROR_CONN_LOST: 119 case SSL_ERROR_SOCK_SETUP_FAILURE: 120 case SSL_ERROR_INVALID_HANDSHAKE: 121 case SSL_ERROR_INVALID_PROT_MSG: 122 case SSL_ERROR_INVALID_HMAC: 123 case SSL_ERROR_INVALID_SESSION: 124 case SSL_ERROR_INVALID_KEY: /* it's too bad this doesn't map better */ 125 case SSL_ERROR_FINISHED_INVALID: 126 case SSL_ERROR_NO_CLIENT_RENOG: 127 default: 128 return CURLE_SSL_CONNECT_ERROR; 129 break; 130 } 131} 132 133static Curl_recv axtls_recv; 134static Curl_send axtls_send; 135 136/* 137 * This function is called after the TCP connect has completed. Setup the TLS 138 * layer and do all necessary magic. 139 */ 140CURLcode 141Curl_axtls_connect(struct connectdata *conn, 142 int sockindex) 143 144{ 145 struct SessionHandle *data = conn->data; 146 SSL_CTX *ssl_ctx; 147 SSL *ssl; 148 int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0}; 149 int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0}; 150 int i, ssl_fcn_return; 151 const uint8_t *ssl_sessionid; 152 size_t ssl_idsize; 153 const char *x509; 154 155 /* Assuming users will not compile in custom key/cert to axTLS */ 156 uint32_t client_option = SSL_NO_DEFAULT_KEY|SSL_SERVER_VERIFY_LATER; 157 158 if(conn->ssl[sockindex].state == ssl_connection_complete) 159 /* to make us tolerant against being called more than once for the 160 same connection */ 161 return CURLE_OK; 162 163 /* axTLS only supports TLSv1 */ 164 /* check to see if we've been told to use an explicit SSL/TLS version */ 165 switch(data->set.ssl.version) { 166 case CURL_SSLVERSION_DEFAULT: 167 case CURL_SSLVERSION_TLSv1: 168 break; 169 default: 170 failf(data, "axTLS only supports TLSv1"); 171 return CURLE_SSL_CONNECT_ERROR; 172 } 173 174#ifdef AXTLSDEBUG 175 client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS; 176#endif /* AXTLSDEBUG */ 177 178 /* Allocate an SSL_CTX struct */ 179 ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS); 180 if(ssl_ctx == NULL) { 181 failf(data, "unable to create client SSL context"); 182 return CURLE_SSL_CONNECT_ERROR; 183 } 184 185 /* Load the trusted CA cert bundle file */ 186 if(data->set.ssl.CAfile) { 187 if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT, data->set.ssl.CAfile, NULL) 188 != SSL_OK) { 189 infof(data, "error reading ca cert file %s \n", 190 data->set.ssl.CAfile); 191 if(data->set.ssl.verifypeer) { 192 Curl_axtls_close(conn, sockindex); 193 return CURLE_SSL_CACERT_BADFILE; 194 } 195 } 196 else 197 infof(data, "found certificates in %s\n", data->set.ssl.CAfile); 198 } 199 200 /* gtls.c tasks we're skipping for now: 201 * 1) certificate revocation list checking 202 * 2) dns name assignment to host 203 * 3) set protocol priority. axTLS is TLSv1 only, so can probably ignore 204 * 4) set certificate priority. axTLS ignores type and sends certs in 205 * order added. can probably ignore this. 206 */ 207 208 /* Load client certificate */ 209 if(data->set.str[STRING_CERT]) { 210 i=0; 211 /* Instead of trying to analyze cert type here, let axTLS try them all. */ 212 while(cert_types[i] != 0) { 213 ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i], 214 data->set.str[STRING_CERT], NULL); 215 if(ssl_fcn_return == SSL_OK) { 216 infof(data, "successfully read cert file %s \n", 217 data->set.str[STRING_CERT]); 218 break; 219 } 220 i++; 221 } 222 /* Tried all cert types, none worked. */ 223 if(cert_types[i] == 0) { 224 failf(data, "%s is not x509 or pkcs12 format", 225 data->set.str[STRING_CERT]); 226 Curl_axtls_close(conn, sockindex); 227 return CURLE_SSL_CERTPROBLEM; 228 } 229 } 230 231 /* Load client key. 232 If a pkcs12 file successfully loaded a cert, then there's nothing to do 233 because the key has already been loaded. */ 234 if(data->set.str[STRING_KEY] && cert_types[i] != SSL_OBJ_PKCS12) { 235 i=0; 236 /* Instead of trying to analyze key type here, let axTLS try them all. */ 237 while(key_types[i] != 0) { 238 ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i], 239 data->set.str[STRING_KEY], NULL); 240 if(ssl_fcn_return == SSL_OK) { 241 infof(data, "successfully read key file %s \n", 242 data->set.str[STRING_KEY]); 243 break; 244 } 245 i++; 246 } 247 /* Tried all key types, none worked. */ 248 if(key_types[i] == 0) { 249 failf(data, "Failure: %s is not a supported key file", 250 data->set.str[STRING_KEY]); 251 Curl_axtls_close(conn, sockindex); 252 return CURLE_SSL_CONNECT_ERROR; 253 } 254 } 255 256 /* gtls.c does more here that is being left out for now 257 * 1) set session credentials. can probably ignore since axtls puts this 258 * info in the ssl_ctx struct 259 * 2) setting up callbacks. these seem gnutls specific 260 */ 261 262 /* In axTLS, handshaking happens inside ssl_client_new. */ 263 if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize)) { 264 /* we got a session id, use it! */ 265 infof (data, "SSL re-using session ID\n"); 266 ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], 267 ssl_sessionid, (uint8_t)ssl_idsize); 268 } 269 else 270 ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0); 271 272 /* Check to make sure handshake was ok. */ 273 ssl_fcn_return = ssl_handshake_status(ssl); 274 if(ssl_fcn_return != SSL_OK) { 275 Curl_axtls_close(conn, sockindex); 276 ssl_display_error(ssl_fcn_return); /* goes to stdout. */ 277 return map_error_to_curl(ssl_fcn_return); 278 } 279 infof (data, "handshake completed successfully\n"); 280 281 /* Here, gtls.c gets the peer certificates and fails out depending on 282 * settings in "data." axTLS api doesn't have get cert chain fcn, so omit? 283 */ 284 285 /* Verify server's certificate */ 286 if(data->set.ssl.verifypeer) { 287 if(ssl_verify_cert(ssl) != SSL_OK) { 288 Curl_axtls_close(conn, sockindex); 289 failf(data, "server cert verify failed"); 290 return CURLE_SSL_CONNECT_ERROR; 291 } 292 } 293 else 294 infof(data, "\t server certificate verification SKIPPED\n"); 295 296 /* Here, gtls.c does issuer verification. axTLS has no straightforward 297 * equivalent, so omitting for now.*/ 298 299 /* See if common name was set in server certificate */ 300 x509 = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME); 301 if(x509 == NULL) 302 infof(data, "error fetching CN from cert\n"); 303 304 /* Here, gtls.c does the following 305 * 1) x509 hostname checking per RFC2818. axTLS doesn't support this, but 306 * it seems useful. Omitting for now. 307 * 2) checks cert validity based on time. axTLS does this in ssl_verify_cert 308 * 3) displays a bunch of cert information. axTLS doesn't support most of 309 * this, but a couple fields are available. 310 */ 311 312 /* General housekeeping */ 313 conn->ssl[sockindex].state = ssl_connection_complete; 314 conn->ssl[sockindex].ssl = ssl; 315 conn->ssl[sockindex].ssl_ctx = ssl_ctx; 316 conn->recv[sockindex] = axtls_recv; 317 conn->send[sockindex] = axtls_send; 318 319 /* Put our freshly minted SSL session in cache */ 320 ssl_idsize = ssl_get_session_id_size(ssl); 321 ssl_sessionid = ssl_get_session_id(ssl); 322 if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize) 323 != CURLE_OK) 324 infof (data, "failed to add session to cache\n"); 325 326 return CURLE_OK; 327} 328 329 330/* return number of sent (non-SSL) bytes */ 331static ssize_t axtls_send(struct connectdata *conn, 332 int sockindex, 333 const void *mem, 334 size_t len, 335 CURLcode *err) 336{ 337 /* ssl_write() returns 'int' while write() and send() returns 'size_t' */ 338 int rc = ssl_write(conn->ssl[sockindex].ssl, mem, (int)len); 339 340 infof(conn->data, " axtls_send\n"); 341 342 if(rc < 0 ) { 343 *err = map_error_to_curl(rc); 344 rc = -1; /* generic error code for send failure */ 345 } 346 347 *err = CURLE_OK; 348 return rc; 349} 350 351void Curl_axtls_close_all(struct SessionHandle *data) 352{ 353 (void)data; 354 infof(data, " Curl_axtls_close_all\n"); 355} 356 357void Curl_axtls_close(struct connectdata *conn, int sockindex) 358{ 359 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 360 361 infof(conn->data, " Curl_axtls_close\n"); 362 if(connssl->ssl) { 363 /* line from ssluse.c: (void)SSL_shutdown(connssl->ssl); 364 axTLS compat layer does nothing for SSL_shutdown */ 365 366 /* The following line is from ssluse.c. There seems to be no axTLS 367 equivalent. ssl_free and ssl_ctx_free close things. 368 SSL_set_connect_state(connssl->handle); */ 369 370 ssl_free (connssl->ssl); 371 connssl->ssl = NULL; 372 } 373 if(connssl->ssl_ctx) { 374 ssl_ctx_free (connssl->ssl_ctx); 375 connssl->ssl_ctx = NULL; 376 } 377} 378 379/* 380 * This function is called to shut down the SSL layer but keep the 381 * socket open (CCC - Clear Command Channel) 382 */ 383int Curl_axtls_shutdown(struct connectdata *conn, int sockindex) 384{ 385 /* Outline taken from ssluse.c since functions are in axTLS compat layer. 386 axTLS's error set is much smaller, so a lot of error-handling was removed. 387 */ 388 int retval = 0; 389 struct ssl_connect_data *connssl = &conn->ssl[sockindex]; 390 struct SessionHandle *data = conn->data; 391 char buf[120]; /* We will use this for the OpenSSL error buffer, so it has 392 to be at least 120 bytes long. */ 393 ssize_t nread; 394 395 infof(conn->data, " Curl_axtls_shutdown\n"); 396 397 /* This has only been tested on the proftpd server, and the mod_tls code 398 sends a close notify alert without waiting for a close notify alert in 399 response. Thus we wait for a close notify alert from the server, but 400 we do not send one. Let's hope other servers do the same... */ 401 402 /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too 403 if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) 404 (void)SSL_shutdown(connssl->ssl); 405 */ 406 407 if(connssl->ssl) { 408 int what = Curl_socket_ready(conn->sock[sockindex], 409 CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); 410 if(what > 0) { 411 /* Something to read, let's do it and hope that it is the close 412 notify alert from the server */ 413 nread = (ssize_t)SSL_read(conn->ssl[sockindex].ssl, buf, 414 sizeof(buf)); 415 416 if(nread < SSL_OK) { 417 failf(data, "close notify alert not received during shutdown"); 418 retval = -1; 419 } 420 } 421 else if(0 == what) { 422 /* timeout */ 423 failf(data, "SSL shutdown timeout"); 424 } 425 else { 426 /* anything that gets here is fatally bad */ 427 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 428 retval = -1; 429 } 430 431 ssl_free (connssl->ssl); 432 connssl->ssl = NULL; 433 } 434 return retval; 435} 436 437static ssize_t axtls_recv(struct connectdata *conn, /* connection data */ 438 int num, /* socketindex */ 439 char *buf, /* store read data here */ 440 size_t buffersize, /* max amount to read */ 441 CURLcode *err) 442{ 443 struct ssl_connect_data *connssl = &conn->ssl[num]; 444 ssize_t ret = 0; 445 446 infof(conn->data, " axtls_recv\n"); 447 448 if(connssl) { 449 ret = (ssize_t)SSL_read(conn->ssl[num].ssl, buf, (int)buffersize); 450 451 /* axTLS isn't terribly generous about error reporting */ 452 /* With patched axTLS, SSL_CLOSE_NOTIFY=-3. Hard-coding until axTLS 453 team approves proposed fix. */ 454 if(ret == -3 ) { 455 Curl_axtls_close(conn, num); 456 } 457 else if(ret < 0) { 458 failf(conn->data, "axTLS recv error (%d)", (int)ret); 459 *err = map_error_to_curl(ret); 460 return -1; 461 } 462 } 463 464 *err = CURLE_OK; 465 return ret; 466} 467 468/* 469 * Return codes: 470 * 1 means the connection is still in place 471 * 0 means the connection has been closed 472 * -1 means the connection status is unknown 473 */ 474int Curl_axtls_check_cxn(struct connectdata *conn) 475{ 476 /* ssluse.c line: rc = SSL_peek(conn->ssl[FIRSTSOCKET].ssl, (void*)&buf, 1); 477 axTLS compat layer always returns the last argument, so connection is 478 always alive? */ 479 480 infof(conn->data, " Curl_axtls_check_cxn\n"); 481 return 1; /* connection still in place */ 482} 483 484void Curl_axtls_session_free(void *ptr) 485{ 486 (void)ptr; 487 /* free the ID */ 488 /* both ssluse.c and gtls.c do something here, but axTLS's OpenSSL 489 compatibility layer does nothing, so we do nothing too. */ 490} 491 492size_t Curl_axtls_version(char *buffer, size_t size) 493{ 494 return snprintf(buffer, size, "axTLS/%s", ssl_version()); 495} 496 497#endif /* USE_AXTLS */ 498