~ubuntu-branches/ubuntu/edgy/curl/edgy

« back to all changes in this revision

Viewing changes to lib/ssluse.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2006-06-29 15:04:24 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20060629150424-pn00qumt9sml8p4m
Tags: 7.15.4-1ubuntu1
Synchronize to Debian. Only change left: Removal of stunnel and
libdb4.2-dev build dependencies.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *                            | (__| |_| |  _ <| |___
6
6
 *                             \___|\___/|_| \_\_____|
7
7
 *
8
 
 * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
 
8
 * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
9
9
 *
10
10
 * This software is licensed as described in the file COPYING, which
11
11
 * you should have received as part of this distribution. The terms
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
21
 
 * $Id: ssluse.c,v 1.138 2005/12/05 15:14:04 bagder Exp $
 
21
 * $Id: ssluse.c,v 1.152 2006-06-09 12:07:34 bagder Exp $
22
22
 ***************************************************************************/
23
23
 
24
24
/*
49
49
#include "url.h" /* for the ssl config check function */
50
50
#include "inet_pton.h"
51
51
#include "ssluse.h"
52
 
#include "connect.h" /* Curl_ourerrno() proto */
 
52
#include "connect.h" /* Curl_sockerrno() proto */
53
53
#include "strequal.h"
54
54
#include "select.h"
55
55
#include "sslgen.h"
68
68
#endif
69
69
 
70
70
#include "memory.h"
 
71
#include "easyif.h" /* for Curl_convert_from_utf8 prototype */
71
72
 
72
73
/* The last #include file should be: */
73
74
#include "memdebug.h"
168
169
}
169
170
#endif
170
171
 
171
 
static
172
 
int random_the_seed(struct SessionHandle *data)
 
172
static int ossl_seed(struct SessionHandle *data)
173
173
{
174
174
  char *buf = data->state.buffer; /* point to the big buffer */
175
175
  int nread=0;
258
258
  return nread;
259
259
}
260
260
 
 
261
int Curl_ossl_seed(struct SessionHandle *data)
 
262
{
 
263
  /* we have the "SSL is seeded" boolean static to prevent multiple
 
264
     time-consuming seedings in vain */
 
265
  static bool ssl_seeded = FALSE;
 
266
 
 
267
  if(!ssl_seeded || data->set.ssl.random_file || data->set.ssl.egdsocket) {
 
268
    ossl_seed(data);
 
269
    ssl_seeded = TRUE;
 
270
  }
 
271
  return 0;
 
272
}
 
273
 
 
274
 
261
275
#ifndef SSL_FILETYPE_ENGINE
262
276
#define SSL_FILETYPE_ENGINE 42
263
277
#endif
530
544
  return (buf);
531
545
}
532
546
 
533
 
/* we have the "SSL is seeded" boolean global for the application to
534
 
   prevent multiple time-consuming seedings in vain */
535
 
static bool ssl_seeded = FALSE;
536
547
#endif /* USE_SSLEAY */
537
548
 
538
549
#ifdef USE_SSLEAY
583
594
#endif
584
595
}
585
596
 
 
597
/*
 
598
 * This function uses SSL_peek to determine connection status.
 
599
 *
 
600
 * Return codes:
 
601
 *     1 means the connection is still in place
 
602
 *     0 means the connection has been closed
 
603
 *    -1 means the connection status is unknown
 
604
 */
 
605
int Curl_ossl_check_cxn(struct connectdata *conn)
 
606
{
 
607
  int rc;
 
608
  char buf;
 
609
 
 
610
  rc = SSL_peek(conn->ssl[FIRSTSOCKET].handle, (void*)&buf, 1);
 
611
  if (rc > 0)
 
612
    return 1; /* connection still in place */
 
613
 
 
614
  if (rc == 0)
 
615
    return 0; /* connection has been closed */
 
616
 
 
617
  return -1; /* connection status unknown */
 
618
}
 
619
 
586
620
#endif /* USE_SSLEAY */
587
621
 
588
622
/* Selects an OpenSSL crypto engine
802
836
        if (hostmatch(hostname++,pattern) == HOST_MATCH)
803
837
          return HOST_MATCH;
804
838
      }
805
 
      return HOST_NOMATCH;
 
839
      break;
806
840
    }
807
841
 
808
842
    if (toupper(c) != toupper(*hostname++))
809
 
      return HOST_NOMATCH;
 
843
      break;
810
844
  }
 
845
  return HOST_NOMATCH;
811
846
}
812
847
 
813
848
static int
971
1006
 
972
1007
    if (peer_CN == nulstr)
973
1008
       peer_CN = NULL;
 
1009
#ifdef CURL_DOES_CONVERSIONS
 
1010
    else {
 
1011
      /* convert peer_CN from UTF8 */
 
1012
      size_t rc;
 
1013
      rc = Curl_convert_from_utf8(data, peer_CN, strlen(peer_CN));
 
1014
      /* Curl_convert_from_utf8 calls failf if unsuccessful */
 
1015
      if (rc != CURLE_OK) {
 
1016
        return(rc);
 
1017
      }
 
1018
    }
 
1019
#endif /* CURL_DOES_CONVERSIONS */
974
1020
 
975
1021
    if (!peer_CN) {
976
1022
      if(data->set.ssl.verifyhost > 1) {
1115
1161
 
1116
1162
#ifdef USE_SSLEAY
1117
1163
/* ====================================================== */
1118
 
CURLcode
1119
 
Curl_ossl_connect(struct connectdata *conn,
1120
 
                  int sockindex)
 
1164
 
 
1165
static CURLcode
 
1166
Curl_ossl_connect_step1(struct connectdata *conn,
 
1167
                        int sockindex)
1121
1168
{
1122
1169
  CURLcode retcode = CURLE_OK;
1123
1170
 
1124
1171
  struct SessionHandle *data = conn->data;
1125
 
  int err;
1126
 
  long lerr;
1127
 
  int what;
1128
 
  char * str;
1129
1172
  SSL_METHOD_QUAL SSL_METHOD *req_method=NULL;
1130
1173
  void *ssl_sessionid=NULL;
1131
 
  ASN1_TIME *certdate;
1132
1174
  curl_socket_t sockfd = conn->sock[sockindex];
1133
1175
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1134
1176
 
1135
 
  if(!ssl_seeded || data->set.ssl.random_file || data->set.ssl.egdsocket) {
1136
 
    /* Make funny stuff to get random input */
1137
 
    random_the_seed(data);
 
1177
  curlassert(ssl_connect_1 == connssl->connecting_state);
1138
1178
 
1139
 
    ssl_seeded = TRUE;
1140
 
  }
 
1179
  /* Make funny stuff to get random input */
 
1180
  Curl_ossl_seed(data);
1141
1181
 
1142
1182
  /* check to see if we've been told to use an explicit SSL/TLS version */
1143
1183
  switch(data->set.ssl.version) {
1157
1197
    break;
1158
1198
  }
1159
1199
 
 
1200
  if (connssl->ctx)
 
1201
    SSL_CTX_free(connssl->ctx);
1160
1202
  connssl->ctx = SSL_CTX_new(req_method);
1161
1203
 
1162
1204
  if(!connssl->ctx) {
1166
1208
 
1167
1209
#ifdef SSL_CTRL_SET_MSG_CALLBACK
1168
1210
  if (data->set.fdebug) {
 
1211
    /* the SSL trace callback is only used for verbose logging so we only
 
1212
       inform about failures of setting it */
1169
1213
    if (!SSL_CTX_callback_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK,
1170
1214
                               (void (*)(void))ssl_tls_trace)) {
1171
 
      failf(data, "SSL: couldn't set callback!");
1172
 
      return CURLE_SSL_CONNECT_ERROR;
 
1215
      infof(data, "SSL: couldn't set callback!\n");
1173
1216
    }
1174
 
 
1175
 
    if (!SSL_CTX_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, conn)) {
1176
 
      failf(data, "SSL: couldn't set callback argument!");
1177
 
      return CURLE_SSL_CONNECT_ERROR;
 
1217
    else if (!SSL_CTX_ctrl(connssl->ctx, SSL_CTRL_SET_MSG_CALLBACK_ARG, 0,
 
1218
                           conn)) {
 
1219
      infof(data, "SSL: couldn't set callback argument!\n");
1178
1220
    }
1179
1221
  }
1180
1222
#endif
1182
1224
  /* OpenSSL contains code to work-around lots of bugs and flaws in various
1183
1225
     SSL-implementations. SSL_CTX_set_options() is used to enabled those
1184
1226
     work-arounds. The man page for this option states that SSL_OP_ALL enables
1185
 
     ll the work-arounds and that "It is usually safe to use SSL_OP_ALL to
 
1227
     all the work-arounds and that "It is usually safe to use SSL_OP_ALL to
1186
1228
     enable the bug workaround options if compatibility with somewhat broken
1187
1229
     implementations is desired."
1188
1230
 
1268
1310
  }
1269
1311
 
1270
1312
  /* Lets make an SSL structure */
 
1313
  if (connssl->handle)
 
1314
    SSL_free(connssl->handle);
1271
1315
  connssl->handle = SSL_new(connssl->ctx);
1272
1316
  if (!connssl->handle) {
1273
1317
    failf(data, "SSL: couldn't create a context (handle)!");
1296
1340
     return CURLE_SSL_CONNECT_ERROR;
1297
1341
  }
1298
1342
 
1299
 
  while(1) {
1300
 
    int writefd;
1301
 
    int readfd;
1302
 
    long timeout_ms;
1303
 
    long has_passed;
1304
 
 
1305
 
    /* Find out if any timeout is set. If not, use 300 seconds.
1306
 
       Otherwise, figure out the most strict timeout of the two possible one
1307
 
       and then how much time that has elapsed to know how much time we
1308
 
       allow for the connect call */
1309
 
    if(data->set.timeout || data->set.connecttimeout) {
1310
 
 
1311
 
      /* get the most strict timeout of the ones converted to milliseconds */
1312
 
      if(data->set.timeout &&
1313
 
         (data->set.timeout>data->set.connecttimeout))
1314
 
        timeout_ms = data->set.timeout*1000;
1315
 
      else
1316
 
        timeout_ms = data->set.connecttimeout*1000;
1317
 
    }
 
1343
  connssl->connecting_state = ssl_connect_2;
 
1344
  return CURLE_OK;
 
1345
}
 
1346
 
 
1347
static CURLcode
 
1348
Curl_ossl_connect_step2(struct connectdata *conn,
 
1349
                        int sockindex, long *timeout_ms)
 
1350
{
 
1351
  struct SessionHandle *data = conn->data;
 
1352
  int err;
 
1353
  long has_passed;
 
1354
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
1355
 
 
1356
  curlassert(ssl_connect_2 == connssl->connecting_state
 
1357
             || ssl_connect_2_reading == connssl->connecting_state
 
1358
             || ssl_connect_2_writing == connssl->connecting_state);
 
1359
 
 
1360
  /* Find out if any timeout is set. If not, use 300 seconds.
 
1361
     Otherwise, figure out the most strict timeout of the two possible one
 
1362
     and then how much time that has elapsed to know how much time we
 
1363
     allow for the connect call */
 
1364
  if(data->set.timeout && data->set.connecttimeout) {
 
1365
    /* get the most strict timeout of the ones converted to milliseconds */
 
1366
    if(data->set.timeout<data->set.connecttimeout)
 
1367
      *timeout_ms = data->set.timeout*1000;
1318
1368
    else
1319
 
      /* no particular time-out has been set */
1320
 
      timeout_ms= DEFAULT_CONNECT_TIMEOUT;
1321
 
 
1322
 
    /* Evaluate in milliseconds how much time that has passed */
1323
 
    has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
1324
 
 
1325
 
    /* subtract the passed time */
1326
 
    timeout_ms -= has_passed;
1327
 
 
1328
 
    if(timeout_ms < 0) {
1329
 
      /* a precaution, no need to continue if time already is up */
1330
 
      failf(data, "SSL connection timeout");
1331
 
      return CURLE_OPERATION_TIMEOUTED;
1332
 
    }
1333
 
 
1334
 
    readfd = CURL_SOCKET_BAD;
1335
 
    writefd = CURL_SOCKET_BAD;
1336
 
 
1337
 
    err = SSL_connect(connssl->handle);
1338
 
 
1339
 
    /* 1  is fine
1340
 
       0  is "not successful but was shut down controlled"
1341
 
       <0 is "handshake was not successful, because a fatal error occurred" */
1342
 
    if(1 != err) {
1343
 
      int detail = SSL_get_error(connssl->handle, err);
1344
 
 
1345
 
      if(SSL_ERROR_WANT_READ == detail)
1346
 
        readfd = sockfd;
1347
 
      else if(SSL_ERROR_WANT_WRITE == detail)
1348
 
        writefd = sockfd;
1349
 
      else {
1350
 
        /* untreated error */
1351
 
        unsigned long errdetail;
1352
 
        char error_buffer[120]; /* OpenSSL documents that this must be at least
1353
 
                                   120 bytes long. */
1354
 
        CURLcode rc;
1355
 
        const char *cert_problem = NULL;
1356
 
 
1357
 
        errdetail = ERR_get_error(); /* Gets the earliest error code from the
1358
 
                                        thread's error queue and removes the
1359
 
                                        entry. */
1360
 
 
1361
 
        switch(errdetail) {
1362
 
        case 0x1407E086:
1363
 
          /* 1407E086:
1364
 
             SSL routines:
1365
 
             SSL2_SET_CERTIFICATE:
1366
 
             certificate verify failed */
1367
 
          /* fall-through */
1368
 
        case 0x14090086:
1369
 
          /* 14090086:
1370
 
             SSL routines:
1371
 
             SSL3_GET_SERVER_CERTIFICATE:
1372
 
             certificate verify failed */
1373
 
          cert_problem = "SSL certificate problem, verify that the CA cert is"
1374
 
                         " OK. Details:\n";
1375
 
          rc = CURLE_SSL_CACERT;
1376
 
          break;
1377
 
        default:
1378
 
          rc = CURLE_SSL_CONNECT_ERROR;
1379
 
          break;
1380
 
        }
1381
 
 
1382
 
          /* detail is already set to the SSL error above */
1383
 
 
1384
 
        /* If we e.g. use SSLv2 request-method and the server doesn't like us
1385
 
         * (RST connection etc.), OpenSSL gives no explanation whatsoever and
1386
 
         * the SO_ERROR is also lost.
1387
 
         */
1388
 
        if (CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) {
1389
 
          failf(data, "Unknown SSL protocol error in connection to %s:%d ",
1390
 
                conn->host.name, conn->port);
1391
 
          return rc;
1392
 
        }
1393
 
        /* Could be a CERT problem */
1394
 
 
1395
 
        SSL_strerror(errdetail, error_buffer, sizeof(error_buffer));
1396
 
        failf(data, "%s%s", cert_problem ? cert_problem : "", error_buffer);
 
1369
      *timeout_ms = data->set.connecttimeout*1000;
 
1370
  }
 
1371
  else if(data->set.timeout)
 
1372
    *timeout_ms = data->set.timeout*1000;
 
1373
  else if(data->set.connecttimeout)
 
1374
    *timeout_ms = data->set.connecttimeout*1000;
 
1375
  else
 
1376
    /* no particular time-out has been set */
 
1377
    *timeout_ms= DEFAULT_CONNECT_TIMEOUT;
 
1378
 
 
1379
  /* Evaluate in milliseconds how much time that has passed */
 
1380
  has_passed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
 
1381
 
 
1382
  /* subtract the passed time */
 
1383
  *timeout_ms -= has_passed;
 
1384
 
 
1385
  if(*timeout_ms < 0) {
 
1386
    /* a precaution, no need to continue if time already is up */
 
1387
    failf(data, "SSL connection timeout");
 
1388
    return CURLE_OPERATION_TIMEOUTED;
 
1389
  }
 
1390
 
 
1391
  err = SSL_connect(connssl->handle);
 
1392
 
 
1393
  /* 1  is fine
 
1394
     0  is "not successful but was shut down controlled"
 
1395
     <0 is "handshake was not successful, because a fatal error occurred" */
 
1396
  if(1 != err) {
 
1397
    int detail = SSL_get_error(connssl->handle, err);
 
1398
 
 
1399
    if(SSL_ERROR_WANT_READ == detail) {
 
1400
      connssl->connecting_state = ssl_connect_2_reading;
 
1401
      return CURLE_OK;
 
1402
    }
 
1403
    else if(SSL_ERROR_WANT_WRITE == detail) {
 
1404
      connssl->connecting_state = ssl_connect_2_writing;
 
1405
      return CURLE_OK;
 
1406
    }
 
1407
    else {
 
1408
      /* untreated error */
 
1409
      unsigned long errdetail;
 
1410
      char error_buffer[120]; /* OpenSSL documents that this must be at least
 
1411
                                 120 bytes long. */
 
1412
      CURLcode rc;
 
1413
      const char *cert_problem = NULL;
 
1414
 
 
1415
      connssl->connecting_state = ssl_connect_2; /* the connection failed,
 
1416
                                                    we're not waiting for
 
1417
                                                    anything else. */
 
1418
 
 
1419
      errdetail = ERR_get_error(); /* Gets the earliest error code from the
 
1420
                                      thread's error queue and removes the
 
1421
                                      entry. */
 
1422
 
 
1423
      switch(errdetail) {
 
1424
      case 0x1407E086:
 
1425
        /* 1407E086:
 
1426
           SSL routines:
 
1427
           SSL2_SET_CERTIFICATE:
 
1428
           certificate verify failed */
 
1429
        /* fall-through */
 
1430
      case 0x14090086:
 
1431
        /* 14090086:
 
1432
           SSL routines:
 
1433
           SSL3_GET_SERVER_CERTIFICATE:
 
1434
           certificate verify failed */
 
1435
        cert_problem = "SSL certificate problem, verify that the CA cert is"
 
1436
          " OK. Details:\n";
 
1437
        rc = CURLE_SSL_CACERT;
 
1438
        break;
 
1439
      default:
 
1440
        rc = CURLE_SSL_CONNECT_ERROR;
 
1441
        break;
 
1442
      }
 
1443
 
 
1444
      /* detail is already set to the SSL error above */
 
1445
 
 
1446
      /* If we e.g. use SSLv2 request-method and the server doesn't like us
 
1447
       * (RST connection etc.), OpenSSL gives no explanation whatsoever and
 
1448
       * the SO_ERROR is also lost.
 
1449
       */
 
1450
      if (CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) {
 
1451
        failf(data, "Unknown SSL protocol error in connection to %s:%d ",
 
1452
              conn->host.name, conn->port);
1397
1453
        return rc;
1398
1454
      }
 
1455
      /* Could be a CERT problem */
 
1456
 
 
1457
      SSL_strerror(errdetail, error_buffer, sizeof(error_buffer));
 
1458
      failf(data, "%s%s", cert_problem ? cert_problem : "", error_buffer);
 
1459
      return rc;
1399
1460
    }
1400
 
    else
1401
 
      /* we have been connected fine, get out of the connect loop */
1402
 
      break;
1403
 
 
1404
 
    while(1) {
1405
 
      what = Curl_select(readfd, writefd, (int)timeout_ms);
1406
 
      if(what > 0)
1407
 
        /* reabable or writable, go loop in the outer loop */
1408
 
        break;
1409
 
      else if(0 == what) {
1410
 
        /* timeout */
1411
 
        failf(data, "SSL connection timeout");
1412
 
        return CURLE_OPERATION_TIMEDOUT;
1413
 
      }
1414
 
      else {
1415
 
        /* anything that gets here is fatally bad */
1416
 
        failf(data, "select on SSL socket, errno: %d", Curl_ourerrno());
1417
 
        return CURLE_SSL_CONNECT_ERROR;
1418
 
      }
1419
 
    } /* while()-loop for the select() */
1420
 
  } /* while()-loop for the SSL_connect() */
1421
 
 
1422
 
  /* Informational message */
1423
 
  infof (data, "SSL connection using %s\n",
1424
 
         SSL_get_cipher(connssl->handle));
1425
 
 
1426
 
  if(!ssl_sessionid) {
 
1461
  }
 
1462
  else {
 
1463
    /* we have been connected fine, we're not waiting for anything else. */
 
1464
    connssl->connecting_state = ssl_connect_3;
 
1465
 
 
1466
    /* Informational message */
 
1467
    infof (data, "SSL connection using %s\n",
 
1468
           SSL_get_cipher(connssl->handle));
 
1469
 
 
1470
    return CURLE_OK;
 
1471
  }
 
1472
}
 
1473
 
 
1474
static CURLcode
 
1475
Curl_ossl_connect_step3(struct connectdata *conn,
 
1476
                  int sockindex)
 
1477
{
 
1478
  CURLcode retcode = CURLE_OK;
 
1479
  char * str;
 
1480
  long lerr;
 
1481
  ASN1_TIME *certdate;
 
1482
  void *ssl_sessionid=NULL;
 
1483
  struct SessionHandle *data = conn->data;
 
1484
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
1485
 
 
1486
  curlassert(ssl_connect_3 == connssl->connecting_state);
 
1487
 
 
1488
  if(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
1427
1489
    /* Since this is not a cached session ID, then we want to stach this one
1428
1490
       in the cache! */
1429
1491
    SSL_SESSION *ssl_sessionid;
1520
1582
      else
1521
1583
        infof(data, "SSL certificate verify result: %s (%ld),"
1522
1584
              " continuing anyway.\n",
1523
 
              X509_verify_cert_error_string(err), lerr);
 
1585
              X509_verify_cert_error_string(lerr), lerr);
1524
1586
    }
1525
1587
    else
1526
1588
      infof(data, "SSL certificate verify ok.\n");
1528
1590
 
1529
1591
  X509_free(connssl->server_cert);
1530
1592
  connssl->server_cert = NULL;
 
1593
  connssl->connecting_state = ssl_connect_done;
1531
1594
  return retcode;
1532
1595
}
1533
1596
 
 
1597
static CURLcode
 
1598
Curl_ossl_connect_common(struct connectdata *conn,
 
1599
                         int sockindex,
 
1600
                         bool nonblocking,
 
1601
                         bool *done)
 
1602
{
 
1603
  CURLcode retcode;
 
1604
  struct SessionHandle *data = conn->data;
 
1605
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
 
1606
  curl_socket_t sockfd = conn->sock[sockindex];
 
1607
  long timeout_ms;
 
1608
 
 
1609
  if (ssl_connect_1==connssl->connecting_state) {
 
1610
    retcode = Curl_ossl_connect_step1(conn, sockindex);
 
1611
    if (retcode)
 
1612
      return retcode;
 
1613
  }
 
1614
 
 
1615
  timeout_ms = 0;
 
1616
  while (ssl_connect_2 == connssl->connecting_state ||
 
1617
         ssl_connect_2_reading == connssl->connecting_state ||
 
1618
         ssl_connect_2_writing == connssl->connecting_state) {
 
1619
 
 
1620
    /* if ssl is expecting something, check if it's available. */
 
1621
    if (connssl->connecting_state == ssl_connect_2_reading
 
1622
        || connssl->connecting_state == ssl_connect_2_writing) {
 
1623
 
 
1624
      int writefd = ssl_connect_2_writing==
 
1625
        connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
 
1626
      int readfd = ssl_connect_2_reading==
 
1627
        connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
 
1628
 
 
1629
      while(1) {
 
1630
        int what = Curl_select(readfd, writefd, nonblocking?0:(int)timeout_ms);
 
1631
        if(what > 0)
 
1632
          /* reabable or writable, go loop in the outer loop */
 
1633
          break;
 
1634
        else if(0 == what) {
 
1635
          if (nonblocking) {
 
1636
            *done = FALSE;
 
1637
            return CURLE_OK;
 
1638
          }
 
1639
          else {
 
1640
            /* timeout */
 
1641
            failf(data, "SSL connection timeout");
 
1642
            return CURLE_OPERATION_TIMEDOUT;
 
1643
          }
 
1644
        }
 
1645
        else {
 
1646
          /* anything that gets here is fatally bad */
 
1647
          failf(data, "select on SSL socket, errno: %d", Curl_sockerrno());
 
1648
          return CURLE_SSL_CONNECT_ERROR;
 
1649
        }
 
1650
      } /* while()-loop for the select() */
 
1651
    }
 
1652
 
 
1653
    /* get the timeout from step2 to avoid computing it twice. */
 
1654
    retcode = Curl_ossl_connect_step2(conn, sockindex, &timeout_ms);
 
1655
    if (retcode)
 
1656
      return retcode;
 
1657
 
 
1658
  } /* repeat step2 until all transactions are done. */
 
1659
 
 
1660
 
 
1661
  if (ssl_connect_3==connssl->connecting_state) {
 
1662
    retcode = Curl_ossl_connect_step3(conn, sockindex);
 
1663
    if (retcode)
 
1664
      return retcode;
 
1665
  }
 
1666
 
 
1667
  if (ssl_connect_done==connssl->connecting_state) {
 
1668
    *done = TRUE;
 
1669
  }
 
1670
  else {
 
1671
    *done = FALSE;
 
1672
  }
 
1673
 
 
1674
  /* Reset our connect state machine */
 
1675
  connssl->connecting_state = ssl_connect_1;
 
1676
 
 
1677
  return CURLE_OK;
 
1678
}
 
1679
 
 
1680
CURLcode
 
1681
Curl_ossl_connect_nonblocking(struct connectdata *conn,
 
1682
                              int sockindex,
 
1683
                              bool *done)
 
1684
{
 
1685
  return Curl_ossl_connect_common(conn, sockindex, TRUE, done);
 
1686
}
 
1687
 
 
1688
CURLcode
 
1689
Curl_ossl_connect(struct connectdata *conn,
 
1690
                  int sockindex)
 
1691
{
 
1692
  CURLcode retcode;
 
1693
  bool done = FALSE;
 
1694
 
 
1695
  retcode = Curl_ossl_connect_common(conn, sockindex, FALSE, &done);
 
1696
  if (retcode)
 
1697
    return retcode;
 
1698
 
 
1699
  curlassert(done);
 
1700
 
 
1701
  return CURLE_OK;
 
1702
}
 
1703
 
1534
1704
/* return number of sent (non-SSL) bytes */
1535
1705
int Curl_ossl_send(struct connectdata *conn,
1536
1706
                   int sockindex,
1557
1727
      return 0;
1558
1728
    case SSL_ERROR_SYSCALL:
1559
1729
      failf(conn->data, "SSL_write() returned SYSCALL, errno = %d\n",
1560
 
            Curl_ourerrno());
 
1730
            Curl_sockerrno());
1561
1731
      return -1;
1562
1732
    case SSL_ERROR_SSL:
1563
1733
      /*  A failure in the SSL library occurred, usually a protocol error.
1609
1779
      sslerror = ERR_get_error();
1610
1780
      failf(conn->data, "SSL read: %s, errno %d",
1611
1781
            ERR_error_string(sslerror, error_buffer),
1612
 
            Curl_ourerrno() );
 
1782
            Curl_sockerrno() );
1613
1783
      return -1;
1614
1784
    }
1615
1785
  }