Home | History | Annotate | Download | only in vtls
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan (at) gmail.com>
      9  * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel (at) haxx.se>, et al.
     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 PolarSSL-specific code for the TLS/SSL layer. No code
     26  * but vtls.c should ever call or use these functions.
     27  *
     28  */
     29 
     30 #include "curl_setup.h"
     31 
     32 #ifdef USE_POLARSSL
     33 
     34 #include <polarssl/net.h>
     35 #include <polarssl/ssl.h>
     36 #include <polarssl/certs.h>
     37 #include <polarssl/x509.h>
     38 #include <polarssl/version.h>
     39 
     40 #if POLARSSL_VERSION_NUMBER < 0x01030000
     41 #error too old PolarSSL
     42 #endif
     43 
     44 #include <polarssl/error.h>
     45 #include <polarssl/entropy.h>
     46 #include <polarssl/ctr_drbg.h>
     47 
     48 #include "urldata.h"
     49 #include "sendf.h"
     50 #include "inet_pton.h"
     51 #include "polarssl.h"
     52 #include "vtls.h"
     53 #include "parsedate.h"
     54 #include "connect.h" /* for the connect timeout */
     55 #include "select.h"
     56 #include "rawstr.h"
     57 #include "polarssl_threadlock.h"
     58 #include "curl_printf.h"
     59 #include "curl_memory.h"
     60 /* The last #include file should be: */
     61 #include "memdebug.h"
     62 
     63 /* apply threading? */
     64 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
     65 #define THREADING_SUPPORT
     66 #endif
     67 
     68 #if defined(THREADING_SUPPORT)
     69 static entropy_context entropy;
     70 
     71 static int  entropy_init_initialized  = 0;
     72 
     73 /* start of entropy_init_mutex() */
     74 static void entropy_init_mutex(entropy_context *ctx)
     75 {
     76   /* lock 0 = entropy_init_mutex() */
     77   polarsslthreadlock_lock_function(0);
     78   if(entropy_init_initialized == 0) {
     79     entropy_init(ctx);
     80     entropy_init_initialized = 1;
     81   }
     82   polarsslthreadlock_unlock_function(0);
     83 }
     84 /* end of entropy_init_mutex() */
     85 
     86 /* start of entropy_func_mutex() */
     87 static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
     88 {
     89     int ret;
     90     /* lock 1 = entropy_func_mutex() */
     91     polarsslthreadlock_lock_function(1);
     92     ret = entropy_func(data, output, len);
     93     polarsslthreadlock_unlock_function(1);
     94 
     95     return ret;
     96 }
     97 /* end of entropy_func_mutex() */
     98 
     99 #endif /* THREADING_SUPPORT */
    100 
    101 /* Define this to enable lots of debugging for PolarSSL */
    102 #undef POLARSSL_DEBUG
    103 
    104 #ifdef POLARSSL_DEBUG
    105 static void polarssl_debug(void *context, int level, const char *line)
    106 {
    107   struct SessionHandle *data = NULL;
    108 
    109   if(!context)
    110     return;
    111 
    112   data = (struct SessionHandle *)context;
    113 
    114   infof(data, "%s", line);
    115   (void) level;
    116 }
    117 #else
    118 #endif
    119 
    120 /* ALPN for http2? */
    121 #ifdef POLARSSL_SSL_ALPN
    122 #  define HAS_ALPN
    123 #endif
    124 
    125 static Curl_recv polarssl_recv;
    126 static Curl_send polarssl_send;
    127 
    128 
    129 static CURLcode
    130 polarssl_connect_step1(struct connectdata *conn,
    131                      int sockindex)
    132 {
    133   struct SessionHandle *data = conn->data;
    134   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
    135 
    136   bool sni = TRUE; /* default is SNI enabled */
    137   int ret = -1;
    138 #ifdef ENABLE_IPV6
    139   struct in6_addr addr;
    140 #else
    141   struct in_addr addr;
    142 #endif
    143   void *old_session = NULL;
    144   size_t old_session_size = 0;
    145   char errorbuf[128];
    146   errorbuf[0]=0;
    147 
    148   /* PolarSSL only supports SSLv3 and TLSv1 */
    149   if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
    150     failf(data, "PolarSSL does not support SSLv2");
    151     return CURLE_SSL_CONNECT_ERROR;
    152   }
    153   else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3)
    154     sni = FALSE; /* SSLv3 has no SNI */
    155 
    156 #ifdef THREADING_SUPPORT
    157   entropy_init_mutex(&entropy);
    158 
    159   if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy,
    160                                connssl->ssn.id, connssl->ssn.length)) != 0) {
    161 #ifdef POLARSSL_ERROR_C
    162      error_strerror(ret, errorbuf, sizeof(errorbuf));
    163 #endif /* POLARSSL_ERROR_C */
    164      failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
    165                                                             -ret, errorbuf);
    166   }
    167 #else
    168   entropy_init(&connssl->entropy);
    169 
    170   if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy,
    171                                 connssl->ssn.id, connssl->ssn.length)) != 0) {
    172 #ifdef POLARSSL_ERROR_C
    173      error_strerror(ret, errorbuf, sizeof(errorbuf));
    174 #endif /* POLARSSL_ERROR_C */
    175      failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
    176                                                             -ret, errorbuf);
    177   }
    178 #endif /* THREADING_SUPPORT */
    179 
    180   /* Load the trusted CA */
    181   memset(&connssl->cacert, 0, sizeof(x509_crt));
    182 
    183   if(data->set.str[STRING_SSL_CAFILE]) {
    184     ret = x509_crt_parse_file(&connssl->cacert,
    185                               data->set.str[STRING_SSL_CAFILE]);
    186 
    187     if(ret<0) {
    188 #ifdef POLARSSL_ERROR_C
    189       error_strerror(ret, errorbuf, sizeof(errorbuf));
    190 #endif /* POLARSSL_ERROR_C */
    191       failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
    192             data->set.str[STRING_SSL_CAFILE], -ret, errorbuf);
    193 
    194       if(data->set.ssl.verifypeer)
    195         return CURLE_SSL_CACERT_BADFILE;
    196     }
    197   }
    198 
    199   if(data->set.str[STRING_SSL_CAPATH]) {
    200     ret = x509_crt_parse_path(&connssl->cacert,
    201                               data->set.str[STRING_SSL_CAPATH]);
    202 
    203     if(ret<0) {
    204 #ifdef POLARSSL_ERROR_C
    205       error_strerror(ret, errorbuf, sizeof(errorbuf));
    206 #endif /* POLARSSL_ERROR_C */
    207       failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s",
    208             data->set.str[STRING_SSL_CAPATH], -ret, errorbuf);
    209 
    210       if(data->set.ssl.verifypeer)
    211         return CURLE_SSL_CACERT_BADFILE;
    212     }
    213   }
    214 
    215   /* Load the client certificate */
    216   memset(&connssl->clicert, 0, sizeof(x509_crt));
    217 
    218   if(data->set.str[STRING_CERT]) {
    219     ret = x509_crt_parse_file(&connssl->clicert,
    220                               data->set.str[STRING_CERT]);
    221 
    222     if(ret) {
    223 #ifdef POLARSSL_ERROR_C
    224       error_strerror(ret, errorbuf, sizeof(errorbuf));
    225 #endif /* POLARSSL_ERROR_C */
    226       failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s",
    227             data->set.str[STRING_CERT], -ret, errorbuf);
    228 
    229       return CURLE_SSL_CERTPROBLEM;
    230     }
    231   }
    232 
    233   /* Load the client private key */
    234   if(data->set.str[STRING_KEY]) {
    235     pk_context pk;
    236     pk_init(&pk);
    237     ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY],
    238                            data->set.str[STRING_KEY_PASSWD]);
    239     if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
    240       ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
    241     if(ret == 0)
    242       rsa_copy(&connssl->rsa, pk_rsa(pk));
    243     else
    244       rsa_free(&connssl->rsa);
    245     pk_free(&pk);
    246 
    247     if(ret) {
    248 #ifdef POLARSSL_ERROR_C
    249       error_strerror(ret, errorbuf, sizeof(errorbuf));
    250 #endif /* POLARSSL_ERROR_C */
    251       failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
    252             data->set.str[STRING_KEY], -ret, errorbuf);
    253 
    254       return CURLE_SSL_CERTPROBLEM;
    255     }
    256   }
    257 
    258   /* Load the CRL */
    259   memset(&connssl->crl, 0, sizeof(x509_crl));
    260 
    261   if(data->set.str[STRING_SSL_CRLFILE]) {
    262     ret = x509_crl_parse_file(&connssl->crl,
    263                               data->set.str[STRING_SSL_CRLFILE]);
    264 
    265     if(ret) {
    266 #ifdef POLARSSL_ERROR_C
    267       error_strerror(ret, errorbuf, sizeof(errorbuf));
    268 #endif /* POLARSSL_ERROR_C */
    269       failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
    270             data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf);
    271 
    272       return CURLE_SSL_CRL_BADFILE;
    273     }
    274   }
    275 
    276   infof(data, "PolarSSL: Connecting to %s:%d\n",
    277         conn->host.name, conn->remote_port);
    278 
    279   if(ssl_init(&connssl->ssl)) {
    280     failf(data, "PolarSSL: ssl_init failed");
    281     return CURLE_SSL_CONNECT_ERROR;
    282   }
    283 
    284   switch(data->set.ssl.version) {
    285   default:
    286   case CURL_SSLVERSION_DEFAULT:
    287   case CURL_SSLVERSION_TLSv1:
    288     ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    289                         SSL_MINOR_VERSION_1);
    290     break;
    291   case CURL_SSLVERSION_SSLv3:
    292     ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    293                         SSL_MINOR_VERSION_0);
    294     ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    295                         SSL_MINOR_VERSION_0);
    296     infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
    297     break;
    298   case CURL_SSLVERSION_TLSv1_0:
    299     ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    300                         SSL_MINOR_VERSION_1);
    301     ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    302                         SSL_MINOR_VERSION_1);
    303     infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n");
    304     break;
    305   case CURL_SSLVERSION_TLSv1_1:
    306     ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    307                         SSL_MINOR_VERSION_2);
    308     ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    309                         SSL_MINOR_VERSION_2);
    310     infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n");
    311     break;
    312   case CURL_SSLVERSION_TLSv1_2:
    313     ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    314                         SSL_MINOR_VERSION_3);
    315     ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3,
    316                         SSL_MINOR_VERSION_3);
    317     infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n");
    318     break;
    319   }
    320 
    321   ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT);
    322   ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL);
    323 
    324   ssl_set_rng(&connssl->ssl, ctr_drbg_random,
    325               &connssl->ctr_drbg);
    326   ssl_set_bio(&connssl->ssl,
    327               net_recv, &conn->sock[sockindex],
    328               net_send, &conn->sock[sockindex]);
    329 
    330   ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites());
    331   if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
    332     memcpy(&connssl->ssn, old_session, old_session_size);
    333     infof(data, "PolarSSL re-using session\n");
    334   }
    335 
    336   ssl_set_session(&connssl->ssl,
    337                   &connssl->ssn);
    338 
    339   ssl_set_ca_chain(&connssl->ssl,
    340                    &connssl->cacert,
    341                    &connssl->crl,
    342                    conn->host.name);
    343 
    344   ssl_set_own_cert_rsa(&connssl->ssl,
    345                        &connssl->clicert, &connssl->rsa);
    346 
    347   if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) &&
    348 #ifdef ENABLE_IPV6
    349      !Curl_inet_pton(AF_INET6, conn->host.name, &addr) &&
    350 #endif
    351      sni && ssl_set_hostname(&connssl->ssl, conn->host.name)) {
    352      infof(data, "WARNING: failed to configure "
    353                  "server name indication (SNI) TLS extension\n");
    354   }
    355 
    356 #ifdef HAS_ALPN
    357   if(data->set.ssl_enable_alpn) {
    358     static const char* protocols[3];
    359     int cur = 0;
    360 
    361 #ifdef USE_NGHTTP2
    362     if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
    363       protocols[cur++] = NGHTTP2_PROTO_VERSION_ID;
    364       infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
    365     }
    366 #endif
    367 
    368     protocols[cur++] = ALPN_HTTP_1_1;
    369     infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
    370 
    371     protocols[cur] = NULL;
    372 
    373     ssl_set_alpn_protocols(&connssl->ssl, protocols);
    374   }
    375 #endif
    376 
    377 #ifdef POLARSSL_DEBUG
    378   ssl_set_dbg(&connssl->ssl, polarssl_debug, data);
    379 #endif
    380 
    381   connssl->connecting_state = ssl_connect_2;
    382 
    383   return CURLE_OK;
    384 }
    385 
    386 static CURLcode
    387 polarssl_connect_step2(struct connectdata *conn,
    388                      int sockindex)
    389 {
    390   int ret;
    391   struct SessionHandle *data = conn->data;
    392   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
    393   char buffer[1024];
    394 
    395   char errorbuf[128];
    396   errorbuf[0] = 0;
    397 
    398   conn->recv[sockindex] = polarssl_recv;
    399   conn->send[sockindex] = polarssl_send;
    400 
    401   ret = ssl_handshake(&connssl->ssl);
    402 
    403   switch(ret) {
    404   case 0:
    405     break;
    406 
    407   case POLARSSL_ERR_NET_WANT_READ:
    408     connssl->connecting_state = ssl_connect_2_reading;
    409     return CURLE_OK;
    410 
    411   case POLARSSL_ERR_NET_WANT_WRITE:
    412     connssl->connecting_state = ssl_connect_2_writing;
    413     return CURLE_OK;
    414 
    415   default:
    416 #ifdef POLARSSL_ERROR_C
    417     error_strerror(ret, errorbuf, sizeof(errorbuf));
    418 #endif /* POLARSSL_ERROR_C */
    419     failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s",
    420           -ret, errorbuf);
    421     return CURLE_SSL_CONNECT_ERROR;
    422   }
    423 
    424   infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
    425         ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) );
    426 
    427   ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
    428 
    429   if(ret && data->set.ssl.verifypeer) {
    430     if(ret & BADCERT_EXPIRED)
    431       failf(data, "Cert verify failed: BADCERT_EXPIRED");
    432 
    433     if(ret & BADCERT_REVOKED) {
    434       failf(data, "Cert verify failed: BADCERT_REVOKED");
    435       return CURLE_SSL_CACERT;
    436     }
    437 
    438     if(ret & BADCERT_CN_MISMATCH)
    439       failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
    440 
    441     if(ret & BADCERT_NOT_TRUSTED)
    442       failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
    443 
    444     return CURLE_PEER_FAILED_VERIFICATION;
    445   }
    446 
    447   if(ssl_get_peer_cert(&(connssl->ssl))) {
    448     /* If the session was resumed, there will be no peer certs */
    449     memset(buffer, 0, sizeof(buffer));
    450 
    451     if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
    452                      ssl_get_peer_cert(&(connssl->ssl))) != -1)
    453       infof(data, "Dumping cert info:\n%s\n", buffer);
    454   }
    455 
    456 #ifdef HAS_ALPN
    457   if(data->set.ssl_enable_alpn) {
    458     const char *next_protocol = ssl_get_alpn_protocol(&connssl->ssl);
    459 
    460     if(next_protocol != NULL) {
    461       infof(data, "ALPN, server accepted to use %s\n", next_protocol);
    462 
    463 #ifdef USE_NGHTTP2
    464       if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
    465                   NGHTTP2_PROTO_VERSION_ID_LEN)) {
    466         conn->negnpn = CURL_HTTP_VERSION_2_0;
    467       }
    468       else
    469 #endif
    470       if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) {
    471         conn->negnpn = CURL_HTTP_VERSION_1_1;
    472       }
    473     }
    474     else
    475       infof(data, "ALPN, server did not agree to a protocol\n");
    476   }
    477 #endif
    478 
    479   connssl->connecting_state = ssl_connect_3;
    480   infof(data, "SSL connected\n");
    481 
    482   return CURLE_OK;
    483 }
    484 
    485 static CURLcode
    486 polarssl_connect_step3(struct connectdata *conn,
    487                      int sockindex)
    488 {
    489   CURLcode result = CURLE_OK;
    490   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    491   struct SessionHandle *data = conn->data;
    492   void *old_ssl_sessionid = NULL;
    493   ssl_session *our_ssl_sessionid = &conn->ssl[sockindex].ssn;
    494   bool incache;
    495 
    496   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
    497 
    498   /* Save the current session data for possible re-use */
    499   incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
    500   if(incache) {
    501     if(old_ssl_sessionid != our_ssl_sessionid) {
    502       infof(data, "old SSL session ID is stale, removing\n");
    503       Curl_ssl_delsessionid(conn, old_ssl_sessionid);
    504       incache = FALSE;
    505     }
    506   }
    507 
    508   if(!incache) {
    509     void *new_session = malloc(sizeof(ssl_session));
    510 
    511     if(new_session) {
    512       memcpy(new_session, our_ssl_sessionid, sizeof(ssl_session));
    513 
    514       result = Curl_ssl_addsessionid(conn, new_session, sizeof(ssl_session));
    515     }
    516     else
    517       result = CURLE_OUT_OF_MEMORY;
    518 
    519     if(result) {
    520       failf(data, "failed to store ssl session");
    521       return result;
    522     }
    523   }
    524 
    525   connssl->connecting_state = ssl_connect_done;
    526 
    527   return CURLE_OK;
    528 }
    529 
    530 static ssize_t polarssl_send(struct connectdata *conn,
    531                              int sockindex,
    532                              const void *mem,
    533                              size_t len,
    534                              CURLcode *curlcode)
    535 {
    536   int ret = -1;
    537 
    538   ret = ssl_write(&conn->ssl[sockindex].ssl,
    539                   (unsigned char *)mem, len);
    540 
    541   if(ret < 0) {
    542     *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ?
    543       CURLE_AGAIN : CURLE_SEND_ERROR;
    544     ret = -1;
    545   }
    546 
    547   return ret;
    548 }
    549 
    550 void Curl_polarssl_close(struct connectdata *conn, int sockindex)
    551 {
    552   rsa_free(&conn->ssl[sockindex].rsa);
    553   x509_crt_free(&conn->ssl[sockindex].clicert);
    554   x509_crt_free(&conn->ssl[sockindex].cacert);
    555   x509_crl_free(&conn->ssl[sockindex].crl);
    556   ssl_free(&conn->ssl[sockindex].ssl);
    557 }
    558 
    559 static ssize_t polarssl_recv(struct connectdata *conn,
    560                              int num,
    561                              char *buf,
    562                              size_t buffersize,
    563                              CURLcode *curlcode)
    564 {
    565   int ret = -1;
    566   ssize_t len = -1;
    567 
    568   memset(buf, 0, buffersize);
    569   ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize);
    570 
    571   if(ret <= 0) {
    572     if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
    573       return 0;
    574 
    575     *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ?
    576       CURLE_AGAIN : CURLE_RECV_ERROR;
    577     return -1;
    578   }
    579 
    580   len = ret;
    581 
    582   return len;
    583 }
    584 
    585 void Curl_polarssl_session_free(void *ptr)
    586 {
    587   free(ptr);
    588 }
    589 
    590 /* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and
    591    higher) will be mbed TLS branded.. */
    592 
    593 size_t Curl_polarssl_version(char *buffer, size_t size)
    594 {
    595   unsigned int version = version_get_number();
    596   return snprintf(buffer, size, "%s/%d.%d.%d",
    597                   version >= 0x01030A00?"mbedTLS":"PolarSSL",
    598                   version>>24, (version>>16)&0xff, (version>>8)&0xff);
    599 }
    600 
    601 static CURLcode
    602 polarssl_connect_common(struct connectdata *conn,
    603                         int sockindex,
    604                         bool nonblocking,
    605                         bool *done)
    606 {
    607   CURLcode result;
    608   struct SessionHandle *data = conn->data;
    609   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
    610   curl_socket_t sockfd = conn->sock[sockindex];
    611   long timeout_ms;
    612   int what;
    613 
    614   /* check if the connection has already been established */
    615   if(ssl_connection_complete == connssl->state) {
    616     *done = TRUE;
    617     return CURLE_OK;
    618   }
    619 
    620   if(ssl_connect_1 == connssl->connecting_state) {
    621     /* Find out how much more time we're allowed */
    622     timeout_ms = Curl_timeleft(data, NULL, TRUE);
    623 
    624     if(timeout_ms < 0) {
    625       /* no need to continue if time already is up */
    626       failf(data, "SSL connection timeout");
    627       return CURLE_OPERATION_TIMEDOUT;
    628     }
    629 
    630     result = polarssl_connect_step1(conn, sockindex);
    631     if(result)
    632       return result;
    633   }
    634 
    635   while(ssl_connect_2 == connssl->connecting_state ||
    636         ssl_connect_2_reading == connssl->connecting_state ||
    637         ssl_connect_2_writing == connssl->connecting_state) {
    638 
    639     /* check allowed time left */
    640     timeout_ms = Curl_timeleft(data, NULL, TRUE);
    641 
    642     if(timeout_ms < 0) {
    643       /* no need to continue if time already is up */
    644       failf(data, "SSL connection timeout");
    645       return CURLE_OPERATION_TIMEDOUT;
    646     }
    647 
    648     /* if ssl is expecting something, check if it's available. */
    649     if(connssl->connecting_state == ssl_connect_2_reading ||
    650        connssl->connecting_state == ssl_connect_2_writing) {
    651 
    652       curl_socket_t writefd = ssl_connect_2_writing==
    653         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
    654       curl_socket_t readfd = ssl_connect_2_reading==
    655         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
    656 
    657       what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
    658       if(what < 0) {
    659         /* fatal error */
    660         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
    661         return CURLE_SSL_CONNECT_ERROR;
    662       }
    663       else if(0 == what) {
    664         if(nonblocking) {
    665           *done = FALSE;
    666           return CURLE_OK;
    667         }
    668         else {
    669           /* timeout */
    670           failf(data, "SSL connection timeout");
    671           return CURLE_OPERATION_TIMEDOUT;
    672         }
    673       }
    674       /* socket is readable or writable */
    675     }
    676 
    677     /* Run transaction, and return to the caller if it failed or if
    678      * this connection is part of a multi handle and this loop would
    679      * execute again. This permits the owner of a multi handle to
    680      * abort a connection attempt before step2 has completed while
    681      * ensuring that a client using select() or epoll() will always
    682      * have a valid fdset to wait on.
    683      */
    684     result = polarssl_connect_step2(conn, sockindex);
    685     if(result || (nonblocking &&
    686                   (ssl_connect_2 == connssl->connecting_state ||
    687                    ssl_connect_2_reading == connssl->connecting_state ||
    688                    ssl_connect_2_writing == connssl->connecting_state)))
    689       return result;
    690 
    691   } /* repeat step2 until all transactions are done. */
    692 
    693   if(ssl_connect_3 == connssl->connecting_state) {
    694     result = polarssl_connect_step3(conn, sockindex);
    695     if(result)
    696       return result;
    697   }
    698 
    699   if(ssl_connect_done == connssl->connecting_state) {
    700     connssl->state = ssl_connection_complete;
    701     conn->recv[sockindex] = polarssl_recv;
    702     conn->send[sockindex] = polarssl_send;
    703     *done = TRUE;
    704   }
    705   else
    706     *done = FALSE;
    707 
    708   /* Reset our connect state machine */
    709   connssl->connecting_state = ssl_connect_1;
    710 
    711   return CURLE_OK;
    712 }
    713 
    714 CURLcode
    715 Curl_polarssl_connect_nonblocking(struct connectdata *conn,
    716                                 int sockindex,
    717                                 bool *done)
    718 {
    719   return polarssl_connect_common(conn, sockindex, TRUE, done);
    720 }
    721 
    722 
    723 CURLcode
    724 Curl_polarssl_connect(struct connectdata *conn,
    725                     int sockindex)
    726 {
    727   CURLcode result;
    728   bool done = FALSE;
    729 
    730   result = polarssl_connect_common(conn, sockindex, FALSE, &done);
    731   if(result)
    732     return result;
    733 
    734   DEBUGASSERT(done);
    735 
    736   return CURLE_OK;
    737 }
    738 
    739 /*
    740  * return 0 error initializing SSL
    741  * return 1 SSL initialized successfully
    742  */
    743 int polarssl_init(void)
    744 {
    745   return polarsslthreadlock_thread_setup();
    746 }
    747 
    748 void polarssl_cleanup(void)
    749 {
    750   (void)polarsslthreadlock_thread_cleanup();
    751 }
    752 
    753 #endif /* USE_POLARSSL */
    754