18
18
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
* KIND, either express or implied.
21
* $Id: ssluse.c,v 1.223 2009-05-04 21:57:14 bagder Exp $
21
* $Id: ssluse.c,v 1.243 2009-10-14 02:32:27 gknauf Exp $
22
22
***************************************************************************/
89
91
#if OPENSSL_VERSION_NUMBER >= 0x00907001L
90
92
/* ENGINE_load_private_key() takes four arguments */
91
93
#define HAVE_ENGINE_LOAD_FOUR_ARGS
94
#include <openssl/ui.h>
93
96
/* ENGINE_load_private_key() takes three arguments */
94
97
#undef HAVE_ENGINE_LOAD_FOUR_ARGS
222
225
/* If we get here, it means we need to seed the PRNG using a "silly"
224
227
#ifdef HAVE_RAND_SCREEN
225
/* This one gets a random value by reading the currently shown screen */
228
/* if RAND_screen() is present, it was called during global init */
227
229
nread = 100; /* just a value */
572
574
return 1; /* alloc failed! */
574
rc = X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_CPLUS_SPC);
576
rc = X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC);
575
577
BIO_get_mem_ptr(bio_out, &biomem);
577
579
if((size_t)biomem->length < size)
633
635
/* Lets get nice error messages */
634
636
SSL_load_error_strings();
636
/* Setup all the global SSL stuff */
638
/* Init the global ciphers and digests */
637
639
if(!SSLeay_add_ssl_algorithms())
642
OpenSSL_add_all_algorithms();
644
#ifdef HAVE_RAND_SCREEN
645
/* This one gets a random value by reading the currently shown screen.
646
RAND_screen() is not thread-safe according to OpenSSL devs - although not
647
mentioned in documentation. */
1047
1056
static CURLcode verifyhost(struct connectdata *conn,
1048
1057
X509 *server_cert)
1050
bool matched = FALSE; /* no alternative match yet */
1059
int matched = -1; /* -1 is no alternative match yet, 1 means match and 0
1051
1061
int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
1052
1062
size_t addrlen = 0;
1053
1063
struct SessionHandle *data = conn->data;
1084
1094
numalts = sk_GENERAL_NAME_num(altnames);
1086
1096
/* loop through all alternatives while none has matched */
1087
for (i=0; (i<numalts) && !matched; i++) {
1097
for (i=0; (i<numalts) && (matched != 1); i++) {
1088
1098
/* get a handle to alternative name number i */
1089
1099
const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
1092
1102
if(check->type == target) {
1093
1103
/* get data and length */
1094
1104
const char *altptr = (char *)ASN1_STRING_data(check->d.ia5);
1105
size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
1097
1107
switch(target) {
1098
1108
case GEN_DNS: /* name/pattern comparison */
1106
1116
"I checked the 0.9.6 and 0.9.8 sources before my patch and
1107
1117
it always 0-terminates an IA5String."
1109
if(cert_hostcheck(altptr, conn->host.name))
1119
if((altlen == strlen(altptr)) &&
1120
/* if this isn't true, there was an embedded zero in the name
1121
string and we cannot match it. */
1122
cert_hostcheck(altptr, conn->host.name))
1113
1128
case GEN_IPADD: /* IP address comparison */
1114
1129
/* compare alternative IP address if the data chunk is the same size
1115
1130
our server IP address is */
1116
altlen = (size_t) ASN1_STRING_length(check->d.ia5);
1117
1131
if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
1123
1139
GENERAL_NAMES_free(altnames);
1127
1143
/* an alternative name matched the server hostname */
1128
1144
infof(data, "\t subjectAltName: %s matched\n", conn->host.dispname);
1145
else if(matched == 0) {
1146
/* an alternative name field existed, but didn't match and then
1148
infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname);
1149
res = CURLE_PEER_FAILED_VERIFICATION;
1130
1152
/* we have to look to the last occurence of a commonName in the
1131
1153
distinguished one to get the most significant one. */
1139
1161
X509_NAME *name = X509_get_subject_name(server_cert) ;
1141
while((j=X509_NAME_get_index_by_NID(name,NID_commonName,i))>=0)
1163
while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i))>=0)
1144
1166
/* we have the name entry and we will now convert this to a string
1153
1175
string manually to avoid the problem. This code can be made
1154
1176
conditional in the future when OpenSSL has been fixed. Work-around
1155
1177
brought by Alexis S. L. Carvalho. */
1156
if(tmp && ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
1157
j = ASN1_STRING_length(tmp);
1159
peer_CN = OPENSSL_malloc(j+1);
1161
memcpy(peer_CN, ASN1_STRING_data(tmp), j);
1179
if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
1180
j = ASN1_STRING_length(tmp);
1182
peer_CN = OPENSSL_malloc(j+1);
1184
memcpy(peer_CN, ASN1_STRING_data(tmp), j);
1189
else /* not a UTF8 name */
1190
j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
1192
if(peer_CN && ((int)strlen((char *)peer_CN) != j)) {
1193
/* there was a terminating zero before the end of string, this
1194
cannot match and we return failure! */
1195
failf(data, "SSL: illegal cert name field");
1196
res = CURLE_PEER_FAILED_VERIFICATION;
1166
else /* not a UTF8 name */
1167
j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
1170
1201
if(peer_CN == nulstr)
1183
1214
#endif /* CURL_DOES_CONVERSIONS */
1217
/* error already detected, pass through */
1187
1221
"SSL: unable to obtain common name from peer certificate");
1188
return CURLE_PEER_FAILED_VERIFICATION;
1222
res = CURLE_PEER_FAILED_VERIFICATION;
1190
1224
else if(!cert_hostcheck((const char *)peer_CN, conn->host.name)) {
1191
1225
if(data->set.ssl.verifyhost > 1) {
1319
1353
#ifdef USE_SSLEAY
1320
1354
/* ====================================================== */
1356
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1357
# define use_sni(x) sni = (x)
1359
# define use_sni(x) do { } while (0)
1322
1362
static CURLcode
1323
1363
ossl_connect_step1(struct connectdata *conn,
1350
1391
case CURL_SSLVERSION_DEFAULT:
1351
1392
/* we try to figure out version */
1352
1393
req_method = SSLv23_client_method();
1354
1396
case CURL_SSLVERSION_TLSv1:
1355
1397
req_method = TLSv1_client_method();
1357
1400
case CURL_SSLVERSION_SSLv2:
1358
1401
req_method = SSLv2_client_method();
1360
1404
case CURL_SSLVERSION_SSLv3:
1361
1405
req_method = SSLv3_client_method();
1491
1536
* revocation */
1492
1537
lookup=X509_STORE_add_lookup(connssl->ctx->cert_store,X509_LOOKUP_file());
1493
1538
if ( !lookup ||
1494
(X509_load_crl_file(lookup,data->set.str[STRING_SSL_CRLFILE],
1495
X509_FILETYPE_PEM)!=1) ) {
1539
(!X509_load_crl_file(lookup,data->set.str[STRING_SSL_CRLFILE],
1540
X509_FILETYPE_PEM)) ) {
1496
1541
failf(data,"error loading CRL file :\n"
1497
1542
" CRLfile: %s\n",
1498
1543
data->set.str[STRING_SSL_CRLFILE]?
1545
1590
#ifdef ENABLE_IPV6
1546
1591
(0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr)) &&
1548
1594
!SSL_set_tlsext_host_name(connssl->handle, conn->host.name))
1549
1595
infof(data, "WARNING: failed to configure server name indication (SNI) "
1550
1596
"TLS extension\n");
1565
1611
/* pass the raw socket into the SSL layers */
1566
if(!SSL_set_fd(connssl->handle, sockfd)) {
1612
if(!SSL_set_fd(connssl->handle, (int)sockfd)) {
1567
1613
failf(data, "SSL: SSL_set_fd failed: %s",
1568
1614
ERR_error_string(ERR_get_error(),NULL));
1569
1615
return CURLE_SSL_CONNECT_ERROR;
1689
1735
size_t valuelen)
1691
1737
struct curl_certinfo *ci = &data->info.certs;
1693
1739
struct curl_slist *nl;
1694
1740
CURLcode res = CURLE_OK;
1695
1741
size_t labellen = strlen(label);
1696
1742
size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
1698
outp = malloc(outlen);
1744
output = malloc(outlen);
1700
1746
return CURLE_OUT_OF_MEMORY;
1702
1748
/* sprintf the label and colon */
1703
snprintf(outp, outlen, "%s:", label);
1749
snprintf(output, outlen, "%s:", label);
1705
1751
/* memcpy the value (it might not be zero terminated) */
1706
memcpy(&outp[labellen+1], value, valuelen);
1752
memcpy(&output[labellen+1], value, valuelen);
1708
1754
/* zero terminate the output */
1709
outp[labellen + 1 + valuelen] = 0;
1755
output[labellen + 1 + valuelen] = 0;
1711
1757
/* TODO: we should rather introduce an internal API that can do the
1712
1758
equivalent of curl_slist_append but doesn't strdup() the given data as
1713
1759
like in this place the extra malloc/free is totally pointless */
1714
nl = curl_slist_append(ci->certinfo[certnum], outp);
1760
nl = curl_slist_append(ci->certinfo[certnum], output);
1716
1762
curl_slist_free_all(ci->certinfo[certnum]);
1717
1763
res = CURLE_OUT_OF_MEMORY;
1786
1832
for (i=0; i<sk_X509_EXTENSION_num(exts); i++) {
1787
1833
ASN1_OBJECT *obj;
1788
1834
X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i);
1789
BIO *bio_out = BIO_new(BIO_s_mem());
1790
1835
BUF_MEM *biomem;
1793
1838
char namebuf[128];
1839
BIO *bio_out = BIO_new(BIO_s_mem());
1795
1844
obj = X509_EXTENSION_get_object(ext);
2289
2338
curl_socket_t readfd = ssl_connect_2_reading==
2290
2339
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
2293
int what = Curl_socket_ready(readfd, writefd,
2294
nonblocking?0:(int)timeout_ms);
2296
/* readable or writable, go loop in the outer loop */
2298
else if(0 == what) {
2305
failf(data, "SSL connection timeout");
2306
return CURLE_OPERATION_TIMEDOUT;
2341
what = Curl_socket_ready(readfd, writefd,
2342
nonblocking?0:(int)timeout_ms);
2345
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
2346
return CURLE_SSL_CONNECT_ERROR;
2348
else if(0 == what) {
2310
/* anything that gets here is fatally bad */
2311
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
2312
return CURLE_SSL_CONNECT_ERROR;
2355
failf(data, "SSL connection timeout");
2356
return CURLE_OPERATION_TIMEDOUT;
2314
} /* while()-loop for the select() */
2359
/* socket is readable or writable */
2317
/* get the timeout from step2 to avoid computing it twice. */
2318
2362
retcode = ossl_connect_step2(conn, sockindex);
2320
2364
return retcode;