00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #ifdef USE_GSKIT
00026
00027 #include <gskssl.h>
00028 #include <qsoasync.h>
00029
00030
00031 #ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
00032 #define GSK_SSL_EXTN_SERVERNAME_REQUEST 230
00033 #endif
00034
00035 #ifndef GSK_TLSV10_CIPHER_SPECS
00036 #define GSK_TLSV10_CIPHER_SPECS 236
00037 #endif
00038
00039 #ifndef GSK_TLSV11_CIPHER_SPECS
00040 #define GSK_TLSV11_CIPHER_SPECS 237
00041 #endif
00042
00043 #ifndef GSK_TLSV12_CIPHER_SPECS
00044 #define GSK_TLSV12_CIPHER_SPECS 238
00045 #endif
00046
00047 #ifndef GSK_PROTOCOL_TLSV11
00048 #define GSK_PROTOCOL_TLSV11 437
00049 #endif
00050
00051 #ifndef GSK_PROTOCOL_TLSV12
00052 #define GSK_PROTOCOL_TLSV12 438
00053 #endif
00054
00055 #ifndef GSK_FALSE
00056 #define GSK_FALSE 0
00057 #endif
00058
00059 #ifndef GSK_TRUE
00060 #define GSK_TRUE 1
00061 #endif
00062
00063
00064 #ifdef HAVE_LIMITS_H
00065 # include <limits.h>
00066 #endif
00067
00068 #include <curl/curl.h>
00069 #include "urldata.h"
00070 #include "sendf.h"
00071 #include "gskit.h"
00072 #include "vtls.h"
00073 #include "connect.h"
00074 #include "select.h"
00075 #include "strcase.h"
00076 #include "x509asn1.h"
00077 #include "curl_printf.h"
00078
00079 #include "curl_memory.h"
00080
00081 #include "memdebug.h"
00082
00083
00084
00085 #define SOS_READ 0x01
00086 #define SOS_WRITE 0x02
00087
00088
00089 #define CURL_GSKPROTO_SSLV2 0
00090 #define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
00091 #define CURL_GSKPROTO_SSLV3 1
00092 #define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3)
00093 #define CURL_GSKPROTO_TLSV10 2
00094 #define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10)
00095 #define CURL_GSKPROTO_TLSV11 3
00096 #define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11)
00097 #define CURL_GSKPROTO_TLSV12 4
00098 #define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
00099 #define CURL_GSKPROTO_LAST 5
00100
00101
00102
00103 typedef struct {
00104 const char *name;
00105 const char *gsktoken;
00106 unsigned int versions;
00107 } gskit_cipher;
00108
00109 static const gskit_cipher ciphertable[] = {
00110 { "null-md5", "01",
00111 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
00112 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
00113 { "null-sha", "02",
00114 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
00115 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
00116 { "exp-rc4-md5", "03",
00117 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
00118 { "rc4-md5", "04",
00119 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
00120 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
00121 { "rc4-sha", "05",
00122 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
00123 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
00124 { "exp-rc2-cbc-md5", "06",
00125 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
00126 { "exp-des-cbc-sha", "09",
00127 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
00128 CURL_GSKPROTO_TLSV11_MASK },
00129 { "des-cbc3-sha", "0A",
00130 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
00131 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
00132 { "aes128-sha", "2F",
00133 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
00134 CURL_GSKPROTO_TLSV12_MASK },
00135 { "aes256-sha", "35",
00136 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
00137 CURL_GSKPROTO_TLSV12_MASK },
00138 { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK },
00139 { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK },
00140 { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK },
00141 { "aes128-gcm-sha256",
00142 "9C", CURL_GSKPROTO_TLSV12_MASK },
00143 { "aes256-gcm-sha384",
00144 "9D", CURL_GSKPROTO_TLSV12_MASK },
00145 { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK },
00146 { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK },
00147 { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK },
00148 { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK },
00149 { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK },
00150 { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK },
00151 { (const char *) NULL, (const char *) NULL, 0 }
00152 };
00153
00154
00155 static bool is_separator(char c)
00156 {
00157
00158 switch(c) {
00159 case ' ':
00160 case '\t':
00161 case ':':
00162 case ',':
00163 case ';':
00164 return true;
00165 }
00166 return false;
00167 }
00168
00169
00170 static CURLcode gskit_status(struct Curl_easy *data, int rc,
00171 const char *procname, CURLcode defcode)
00172 {
00173
00174 switch(rc) {
00175 case GSK_OK:
00176 case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
00177 return CURLE_OK;
00178 case GSK_KEYRING_OPEN_ERROR:
00179 case GSK_OS400_ERROR_NO_ACCESS:
00180 return CURLE_SSL_CACERT_BADFILE;
00181 case GSK_INSUFFICIENT_STORAGE:
00182 return CURLE_OUT_OF_MEMORY;
00183 case GSK_ERROR_BAD_V2_CIPHER:
00184 case GSK_ERROR_BAD_V3_CIPHER:
00185 case GSK_ERROR_NO_CIPHERS:
00186 return CURLE_SSL_CIPHER;
00187 case GSK_OS400_ERROR_NOT_TRUSTED_ROOT:
00188 case GSK_ERROR_CERT_VALIDATION:
00189 return CURLE_PEER_FAILED_VERIFICATION;
00190 case GSK_OS400_ERROR_TIMED_OUT:
00191 return CURLE_OPERATION_TIMEDOUT;
00192 case GSK_WOULD_BLOCK:
00193 return CURLE_AGAIN;
00194 case GSK_OS400_ERROR_NOT_REGISTERED:
00195 break;
00196 case GSK_ERROR_IO:
00197 switch(errno) {
00198 case ENOMEM:
00199 return CURLE_OUT_OF_MEMORY;
00200 default:
00201 failf(data, "%s I/O error: %s", procname, strerror(errno));
00202 break;
00203 }
00204 break;
00205 default:
00206 failf(data, "%s: %s", procname, gsk_strerror(rc));
00207 break;
00208 }
00209 return defcode;
00210 }
00211
00212
00213 static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
00214 GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
00215 {
00216 int rc = gsk_attribute_set_enum(h, id, value);
00217
00218 switch(rc) {
00219 case GSK_OK:
00220 return CURLE_OK;
00221 case GSK_ERROR_IO:
00222 failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
00223 break;
00224 case GSK_ATTRIBUTE_INVALID_ID:
00225 if(unsupported_ok)
00226 return CURLE_UNSUPPORTED_PROTOCOL;
00227 default:
00228 failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
00229 break;
00230 }
00231 return CURLE_SSL_CONNECT_ERROR;
00232 }
00233
00234
00235 static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
00236 GSK_BUF_ID id, const char *buffer, bool unsupported_ok)
00237 {
00238 int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
00239
00240 switch(rc) {
00241 case GSK_OK:
00242 return CURLE_OK;
00243 case GSK_ERROR_IO:
00244 failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
00245 break;
00246 case GSK_ATTRIBUTE_INVALID_ID:
00247 if(unsupported_ok)
00248 return CURLE_UNSUPPORTED_PROTOCOL;
00249 default:
00250 failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
00251 break;
00252 }
00253 return CURLE_SSL_CONNECT_ERROR;
00254 }
00255
00256
00257 static CURLcode set_numeric(struct Curl_easy *data,
00258 gsk_handle h, GSK_NUM_ID id, int value)
00259 {
00260 int rc = gsk_attribute_set_numeric_value(h, id, value);
00261
00262 switch(rc) {
00263 case GSK_OK:
00264 return CURLE_OK;
00265 case GSK_ERROR_IO:
00266 failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
00267 strerror(errno));
00268 break;
00269 default:
00270 failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
00271 break;
00272 }
00273 return CURLE_SSL_CONNECT_ERROR;
00274 }
00275
00276
00277 static CURLcode set_callback(struct Curl_easy *data,
00278 gsk_handle h, GSK_CALLBACK_ID id, void *info)
00279 {
00280 int rc = gsk_attribute_set_callback(h, id, info);
00281
00282 switch(rc) {
00283 case GSK_OK:
00284 return CURLE_OK;
00285 case GSK_ERROR_IO:
00286 failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno));
00287 break;
00288 default:
00289 failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
00290 break;
00291 }
00292 return CURLE_SSL_CONNECT_ERROR;
00293 }
00294
00295
00296 static CURLcode set_ciphers(struct connectdata *conn,
00297 gsk_handle h, unsigned int *protoflags)
00298 {
00299 struct Curl_easy *data = conn->data;
00300 const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
00301 const char *clp;
00302 const gskit_cipher *ctp;
00303 int i;
00304 int l;
00305 bool unsupported;
00306 CURLcode result;
00307 struct {
00308 char *buf;
00309 char *ptr;
00310 } ciphers[CURL_GSKPROTO_LAST];
00311
00312
00313
00314 if(!cipherlist)
00315 return CURLE_OK;
00316 while(is_separator(*cipherlist))
00317 cipherlist++;
00318 if(!*cipherlist)
00319 return CURLE_OK;
00320
00321
00322
00323
00324 l = strlen(cipherlist) + 1;
00325 memset((char *) ciphers, 0, sizeof ciphers);
00326 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
00327 ciphers[i].buf = malloc(l);
00328 if(!ciphers[i].buf) {
00329 while(i--)
00330 free(ciphers[i].buf);
00331 return CURLE_OUT_OF_MEMORY;
00332 }
00333 ciphers[i].ptr = ciphers[i].buf;
00334 *ciphers[i].ptr = '\0';
00335 }
00336
00337
00338 unsupported = FALSE;
00339 result = CURLE_OK;
00340 for(;;) {
00341 for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
00342 cipherlist++;
00343 l = cipherlist - clp;
00344 if(!l)
00345 break;
00346
00347 for(ctp = ciphertable; ctp->name; ctp++)
00348 if(strncasecompare(ctp->name, clp, l) && !ctp->name[l])
00349 break;
00350 if(!ctp->name) {
00351 failf(data, "Unknown cipher %.*s", l, clp);
00352 result = CURLE_SSL_CIPHER;
00353 }
00354 else {
00355 unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK |
00356 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK));
00357 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
00358 if(ctp->versions & (1 << i)) {
00359 strcpy(ciphers[i].ptr, ctp->gsktoken);
00360 ciphers[i].ptr += strlen(ctp->gsktoken);
00361 }
00362 }
00363 }
00364
00365
00366 while(is_separator(*cipherlist))
00367 cipherlist++;
00368 }
00369
00370
00371 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
00372 if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) {
00373 *protoflags &= ~(1 << i);
00374 ciphers[i].buf[0] = '\0';
00375 }
00376 }
00377
00378
00379 if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) {
00380 result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS,
00381 ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE);
00382 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
00383 result = CURLE_OK;
00384 if(unsupported) {
00385 failf(data, "TLSv1.1-only ciphers are not yet supported");
00386 result = CURLE_SSL_CIPHER;
00387 }
00388 }
00389 }
00390 if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) {
00391 result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS,
00392 ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE);
00393 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
00394 result = CURLE_OK;
00395 if(unsupported) {
00396 failf(data, "TLSv1.2-only ciphers are not yet supported");
00397 result = CURLE_SSL_CIPHER;
00398 }
00399 }
00400 }
00401
00402
00403
00404 if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) {
00405 result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS,
00406 ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE);
00407 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
00408 result = CURLE_OK;
00409 strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr,
00410 ciphers[CURL_GSKPROTO_TLSV10].ptr);
00411 }
00412 }
00413
00414
00415 if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK))
00416 result = set_buffer(data, h, GSK_V3_CIPHER_SPECS,
00417 ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE);
00418 if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK))
00419 result = set_buffer(data, h, GSK_V2_CIPHER_SPECS,
00420 ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE);
00421
00422
00423 for(i = 0; i < CURL_GSKPROTO_LAST; i++)
00424 free(ciphers[i].buf);
00425
00426 return result;
00427 }
00428
00429
00430 int Curl_gskit_init(void)
00431 {
00432
00433
00434 return 1;
00435 }
00436
00437
00438 void Curl_gskit_cleanup(void)
00439 {
00440
00441 }
00442
00443
00444 static CURLcode init_environment(struct Curl_easy *data,
00445 gsk_handle *envir, const char *appid,
00446 const char *file, const char *label,
00447 const char *password)
00448 {
00449 int rc;
00450 CURLcode result;
00451 gsk_handle h;
00452
00453
00454
00455 rc = gsk_environment_open(&h);
00456 switch(rc) {
00457 case GSK_OK:
00458 break;
00459 case GSK_INSUFFICIENT_STORAGE:
00460 return CURLE_OUT_OF_MEMORY;
00461 default:
00462 failf(data, "gsk_environment_open(): %s", gsk_strerror(rc));
00463 return CURLE_SSL_CONNECT_ERROR;
00464 }
00465
00466 result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
00467 if(!result && appid)
00468 result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
00469 if(!result && file)
00470 result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
00471 if(!result && label)
00472 result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE);
00473 if(!result && password)
00474 result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);
00475
00476 if(!result) {
00477
00478
00479 result = gskit_status(data, gsk_environment_init(h),
00480 "gsk_environment_init()", CURLE_SSL_CERTPROBLEM);
00481 if(!result) {
00482 *envir = h;
00483 return result;
00484 }
00485 }
00486
00487 gsk_environment_close(&h);
00488 return result;
00489 }
00490
00491
00492 static void cancel_async_handshake(struct connectdata *conn, int sockindex)
00493 {
00494 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00495 Qso_OverlappedIO_t cstat;
00496
00497 if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
00498 QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL);
00499 }
00500
00501
00502 static void close_async_handshake(struct ssl_connect_data *connssl)
00503 {
00504 QsoDestroyIOCompletionPort(connssl->iocport);
00505 connssl->iocport = -1;
00506 }
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519 static int
00520 inetsocketpair(int sv[2])
00521 {
00522 int lfd;
00523 int sfd;
00524 int cfd;
00525 int len;
00526 struct sockaddr_in addr1;
00527 struct sockaddr_in addr2;
00528
00529
00530 lfd = socket(AF_INET, SOCK_STREAM, 0);
00531 if(lfd < 0)
00532 return -1;
00533 memset((char *) &addr1, 0, sizeof addr1);
00534 addr1.sin_family = AF_INET;
00535 addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
00536 addr1.sin_port = 0;
00537 if(bind(lfd, (struct sockaddr *) &addr1, sizeof addr1) ||
00538 listen(lfd, 2) < 0) {
00539 close(lfd);
00540 return -1;
00541 }
00542
00543
00544 len = sizeof addr1;
00545 if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) {
00546 close(lfd);
00547 return -1;
00548 }
00549
00550
00551 cfd = socket(AF_INET, SOCK_STREAM, 0);
00552 if(cfd < 0) {
00553 close(lfd);
00554 return -1;
00555 }
00556
00557
00558 curlx_nonblock(cfd, TRUE);
00559 if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 &&
00560 errno != EINPROGRESS) {
00561 close(lfd);
00562 close(cfd);
00563 return -1;
00564 }
00565
00566
00567 len = sizeof addr2;
00568 if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
00569 close(lfd);
00570 close(cfd);
00571 return -1;
00572 }
00573
00574
00575 curlx_nonblock(lfd, TRUE);
00576 for(;;) {
00577 len = sizeof addr1;
00578 sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
00579 if(sfd < 0) {
00580 close(lfd);
00581 close(cfd);
00582 return -1;
00583 }
00584
00585
00586 if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr &&
00587 addr1.sin_port == addr2.sin_port)
00588 break;
00589
00590
00591 close(sfd);
00592 }
00593
00594
00595 close(lfd);
00596 curlx_nonblock(cfd, FALSE);
00597 sv[0] = cfd;
00598 sv[1] = sfd;
00599 return 0;
00600 }
00601
00602 static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
00603 int directions)
00604 {
00605 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00606 struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex];
00607 fd_set fds_read;
00608 fd_set fds_write;
00609 int n;
00610 int m;
00611 int i;
00612 int ret = 0;
00613 struct timeval tv = {0, 0};
00614 char buf[CURL_MAX_WRITE_SIZE];
00615
00616 if(!connssl->use || !connproxyssl->use)
00617 return 0;
00618
00619 FD_ZERO(&fds_read);
00620 FD_ZERO(&fds_write);
00621 n = -1;
00622 if(directions & SOS_READ) {
00623 FD_SET(connssl->remotefd, &fds_write);
00624 n = connssl->remotefd;
00625 }
00626 if(directions & SOS_WRITE) {
00627 FD_SET(connssl->remotefd, &fds_read);
00628 n = connssl->remotefd;
00629 FD_SET(conn->sock[sockindex], &fds_write);
00630 if(n < conn->sock[sockindex])
00631 n = conn->sock[sockindex];
00632 }
00633 i = select(n + 1, &fds_read, &fds_write, NULL, &tv);
00634 if(i < 0)
00635 return -1;
00636
00637 if(FD_ISSET(connssl->remotefd, &fds_write)) {
00638
00639 n = 0;
00640 i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n);
00641 switch(i) {
00642 case GSK_OK:
00643 if(n) {
00644 i = write(connssl->remotefd, buf, n);
00645 if(i < 0)
00646 return -1;
00647 ret = 1;
00648 }
00649 break;
00650 case GSK_OS400_ERROR_TIMED_OUT:
00651 case GSK_WOULD_BLOCK:
00652 break;
00653 default:
00654 return -1;
00655 }
00656 }
00657
00658 if(FD_ISSET(connssl->remotefd, &fds_read) &&
00659 FD_ISSET(conn->sock[sockindex], &fds_write)) {
00660
00661 n = read(connssl->remotefd, buf, sizeof buf);
00662 if(n < 0)
00663 return -1;
00664 if(n) {
00665 i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m);
00666 if(i != GSK_OK || n != m)
00667 return -1;
00668 ret = 1;
00669 }
00670 }
00671
00672 return ret;
00673 }
00674
00675
00676 static void close_one(struct ssl_connect_data *connssl,
00677 struct connectdata *conn, int sockindex)
00678 {
00679 if(connssl->handle) {
00680 gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle),
00681 "gsk_secure_soc_close()", 0);
00682
00683 while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
00684 ;
00685 connssl->handle = (gsk_handle) NULL;
00686 if(connssl->localfd >= 0) {
00687 close(connssl->localfd);
00688 connssl->localfd = -1;
00689 }
00690 if(connssl->remotefd >= 0) {
00691 close(connssl->remotefd);
00692 connssl->remotefd = -1;
00693 }
00694 }
00695 if(connssl->iocport >= 0)
00696 close_async_handshake(connssl);
00697 }
00698
00699
00700 static ssize_t gskit_send(struct connectdata *conn, int sockindex,
00701 const void *mem, size_t len, CURLcode *curlcode)
00702 {
00703 struct Curl_easy *data = conn->data;
00704 CURLcode cc = CURLE_SEND_ERROR;
00705 int written;
00706
00707 if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
00708 cc = gskit_status(data,
00709 gsk_secure_soc_write(conn->ssl[sockindex].handle,
00710 (char *) mem, (int) len, &written),
00711 "gsk_secure_soc_write()", CURLE_SEND_ERROR);
00712 if(cc == CURLE_OK)
00713 if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
00714 cc = CURLE_SEND_ERROR;
00715 }
00716 if(cc != CURLE_OK) {
00717 *curlcode = cc;
00718 written = -1;
00719 }
00720 return (ssize_t) written;
00721 }
00722
00723
00724 static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
00725 size_t buffersize, CURLcode *curlcode)
00726 {
00727 struct Curl_easy *data = conn->data;
00728 int buffsize;
00729 int nread;
00730 CURLcode cc = CURLE_RECV_ERROR;
00731
00732 if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
00733 buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
00734 cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
00735 buf, buffsize, &nread),
00736 "gsk_secure_soc_read()", CURLE_RECV_ERROR);
00737 }
00738 switch(cc) {
00739 case CURLE_OK:
00740 break;
00741 case CURLE_OPERATION_TIMEDOUT:
00742 cc = CURLE_AGAIN;
00743 default:
00744 *curlcode = cc;
00745 nread = -1;
00746 break;
00747 }
00748 return (ssize_t) nread;
00749 }
00750
00751
00752 static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
00753 {
00754 struct Curl_easy *data = conn->data;
00755 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00756 gsk_handle envir;
00757 CURLcode result;
00758 int rc;
00759 const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
00760 const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
00761 const char * const keyringlabel = SSL_SET_OPTION(cert);
00762 const long int ssl_version = SSL_CONN_CONFIG(version);
00763 const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
00764 const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
00765 conn->host.name;
00766 const char *sni;
00767 unsigned int protoflags;
00768 long timeout;
00769 Qso_OverlappedIO_t commarea;
00770 int sockpair[2];
00771 static const int sobufsize = CURL_MAX_WRITE_SIZE;
00772
00773
00774
00775 connssl->handle = (gsk_handle) NULL;
00776 connssl->iocport = -1;
00777 connssl->localfd = -1;
00778 connssl->remotefd = -1;
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 envir = (gsk_handle) NULL;
00794
00795 if(keyringlabel && *keyringlabel && !keyringpwd &&
00796 !strcmp(keyringfile, CURL_CA_BUNDLE)) {
00797
00798 init_environment(data, &envir, keyringlabel, (const char *) NULL,
00799 (const char *) NULL, (const char *) NULL);
00800 }
00801
00802 if(!envir) {
00803
00804 result = init_environment(data, &envir, (const char *) NULL,
00805 keyringfile, keyringlabel, keyringpwd);
00806 if(result)
00807 return result;
00808 }
00809
00810
00811 result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
00812 "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
00813 gsk_environment_close(&envir);
00814 if(result)
00815 return result;
00816
00817
00818 if(conn->proxy_ssl[sockindex].use) {
00819 if(inetsocketpair(sockpair))
00820 return CURLE_SSL_CONNECT_ERROR;
00821 connssl->localfd = sockpair[0];
00822 connssl->remotefd = sockpair[1];
00823 setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF,
00824 (void *) sobufsize, sizeof sobufsize);
00825 setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF,
00826 (void *) sobufsize, sizeof sobufsize);
00827 setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF,
00828 (void *) sobufsize, sizeof sobufsize);
00829 setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF,
00830 (void *) sobufsize, sizeof sobufsize);
00831 curlx_nonblock(connssl->localfd, TRUE);
00832 curlx_nonblock(connssl->remotefd, TRUE);
00833 }
00834
00835
00836 sni = hostname;
00837 switch(ssl_version) {
00838 case CURL_SSLVERSION_SSLv2:
00839 protoflags = CURL_GSKPROTO_SSLV2_MASK;
00840 sni = NULL;
00841 break;
00842 case CURL_SSLVERSION_SSLv3:
00843 protoflags = CURL_GSKPROTO_SSLV3_MASK;
00844 sni = NULL;
00845 break;
00846 case CURL_SSLVERSION_DEFAULT:
00847 case CURL_SSLVERSION_TLSv1:
00848 protoflags = CURL_GSKPROTO_TLSV10_MASK |
00849 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
00850 break;
00851 case CURL_SSLVERSION_TLSv1_0:
00852 protoflags = CURL_GSKPROTO_TLSV10_MASK;
00853 break;
00854 case CURL_SSLVERSION_TLSv1_1:
00855 protoflags = CURL_GSKPROTO_TLSV11_MASK;
00856 break;
00857 case CURL_SSLVERSION_TLSv1_2:
00858 protoflags = CURL_GSKPROTO_TLSV12_MASK;
00859 break;
00860 case CURL_SSLVERSION_TLSv1_3:
00861 failf(data, "GSKit: TLS 1.3 is not yet supported");
00862 return CURLE_SSL_CONNECT_ERROR;
00863 default:
00864 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
00865 return CURLE_SSL_CONNECT_ERROR;
00866 }
00867
00868
00869 if(sni) {
00870 result = set_buffer(data, connssl->handle,
00871 GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
00872 if(result == CURLE_UNSUPPORTED_PROTOCOL)
00873 result = CURLE_OK;
00874 }
00875
00876
00877 if(!result) {
00878
00879
00880 timeout = Curl_timeleft(data, NULL, TRUE);
00881 if(timeout < 0)
00882 result = CURLE_OPERATION_TIMEDOUT;
00883 else
00884 result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
00885 (timeout + 999) / 1000);
00886 }
00887 if(!result)
00888 result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1);
00889 if(!result)
00890 result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0?
00891 connssl->localfd: conn->sock[sockindex]);
00892 if(!result)
00893 result = set_ciphers(conn, connssl->handle, &protoflags);
00894 if(!protoflags) {
00895 failf(data, "No SSL protocol/cipher combination enabled");
00896 result = CURLE_SSL_CIPHER;
00897 }
00898 if(!result)
00899 result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
00900 (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
00901 GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
00902 if(!result)
00903 result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
00904 (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
00905 GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
00906 if(!result)
00907 result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
00908 (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
00909 GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
00910 if(!result) {
00911 result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11,
00912 (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
00913 GSK_TRUE: GSK_FALSE, TRUE);
00914 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
00915 result = CURLE_OK;
00916 if(protoflags == CURL_GSKPROTO_TLSV11_MASK) {
00917 failf(data, "TLS 1.1 not yet supported");
00918 result = CURLE_SSL_CIPHER;
00919 }
00920 }
00921 }
00922 if(!result) {
00923 result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12,
00924 (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
00925 GSK_TRUE: GSK_FALSE, TRUE);
00926 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
00927 result = CURLE_OK;
00928 if(protoflags == CURL_GSKPROTO_TLSV12_MASK) {
00929 failf(data, "TLS 1.2 not yet supported");
00930 result = CURLE_SSL_CIPHER;
00931 }
00932 }
00933 }
00934 if(!result)
00935 result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
00936 verifypeer? GSK_SERVER_AUTH_FULL:
00937 GSK_SERVER_AUTH_PASSTHRU, FALSE);
00938
00939 if(!result) {
00940
00941 memset(&commarea, 0, sizeof commarea);
00942 connssl->iocport = QsoCreateIOCompletionPort();
00943 if(connssl->iocport != -1) {
00944 result = gskit_status(data,
00945 gsk_secure_soc_startInit(connssl->handle,
00946 connssl->iocport,
00947 &commarea),
00948 "gsk_secure_soc_startInit()",
00949 CURLE_SSL_CONNECT_ERROR);
00950 if(!result) {
00951 connssl->connecting_state = ssl_connect_2;
00952 return CURLE_OK;
00953 }
00954 else
00955 close_async_handshake(connssl);
00956 }
00957 else if(errno != ENOBUFS)
00958 result = gskit_status(data, GSK_ERROR_IO,
00959 "QsoCreateIOCompletionPort()", 0);
00960 else if(conn->proxy_ssl[sockindex].use) {
00961
00962 result = CURLE_SSL_CONNECT_ERROR;
00963 }
00964 else {
00965
00966 result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
00967 "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
00968 if(!result) {
00969 connssl->connecting_state = ssl_connect_3;
00970 return CURLE_OK;
00971 }
00972 }
00973 }
00974
00975
00976 close_one(connssl, conn, sockindex);
00977 return result;
00978 }
00979
00980
00981 static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
00982 bool nonblocking)
00983 {
00984 struct Curl_easy *data = conn->data;
00985 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00986 Qso_OverlappedIO_t cstat;
00987 long timeout_ms;
00988 struct timeval stmv;
00989 CURLcode result;
00990
00991
00992
00993 for(;;) {
00994 timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
00995 if(timeout_ms < 0)
00996 timeout_ms = 0;
00997 stmv.tv_sec = timeout_ms / 1000;
00998 stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
00999 switch(QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
01000 case 1:
01001 break;
01002 case -1:
01003 if(errno == EINTR) {
01004 if(nonblocking)
01005 return CURLE_OK;
01006 continue;
01007 }
01008 if(errno != ETIME) {
01009 failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno));
01010 cancel_async_handshake(conn, sockindex);
01011 close_async_handshake(connssl);
01012 return CURLE_SSL_CONNECT_ERROR;
01013 }
01014
01015 case 0:
01016 if(nonblocking)
01017 return CURLE_OK;
01018 cancel_async_handshake(conn, sockindex);
01019 close_async_handshake(connssl);
01020 return CURLE_OPERATION_TIMEDOUT;
01021 }
01022 break;
01023 }
01024 result = gskit_status(data, cstat.returnValue, "SSL handshake",
01025 CURLE_SSL_CONNECT_ERROR);
01026 if(!result)
01027 connssl->connecting_state = ssl_connect_3;
01028 close_async_handshake(connssl);
01029 return result;
01030 }
01031
01032
01033 static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
01034 {
01035 struct Curl_easy *data = conn->data;
01036 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
01037 const gsk_cert_data_elem *cdev;
01038 int cdec;
01039 const gsk_cert_data_elem *p;
01040 const char *cert = (const char *) NULL;
01041 const char *certend;
01042 const char *ptr;
01043 int i;
01044 CURLcode result;
01045
01046
01047
01048 if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle,
01049 GSK_PARTNER_CERT_INFO,
01050 &cdev, &cdec),
01051 "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
01052 CURLE_OK) {
01053 infof(data, "Server certificate:\n");
01054 p = cdev;
01055 for(i = 0; i++ < cdec; p++)
01056 switch(p->cert_data_id) {
01057 case CERT_BODY_DER:
01058 cert = p->cert_data_p;
01059 certend = cert + cdev->cert_data_l;
01060 break;
01061 case CERT_DN_PRINTABLE:
01062 infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p);
01063 break;
01064 case CERT_ISSUER_DN_PRINTABLE:
01065 infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p);
01066 break;
01067 case CERT_VALID_FROM:
01068 infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p);
01069 break;
01070 case CERT_VALID_TO:
01071 infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p);
01072 break;
01073 }
01074 }
01075
01076
01077 result = Curl_verifyhost(conn, cert, certend);
01078 if(result)
01079 return result;
01080
01081
01082
01083
01084
01085
01086 if(data->set.ssl.certinfo) {
01087 result = Curl_ssl_init_certinfo(data, 1);
01088 if(result)
01089 return result;
01090
01091 if(cert) {
01092 result = Curl_extract_certinfo(conn, 0, cert, certend);
01093 if(result)
01094 return result;
01095 }
01096 }
01097
01098
01099 ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
01100 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
01101 if(!result && ptr) {
01102 curl_X509certificate x509;
01103 curl_asn1Element *p;
01104
01105 if(Curl_parseX509(&x509, cert, certend))
01106 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
01107 p = &x509.subjectPublicKeyInfo;
01108 result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header);
01109 if(result) {
01110 failf(data, "SSL: public key does not match pinned public key!");
01111 return result;
01112 }
01113 }
01114
01115 connssl->connecting_state = ssl_connect_done;
01116 return CURLE_OK;
01117 }
01118
01119
01120 static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
01121 bool nonblocking, bool *done)
01122 {
01123 struct Curl_easy *data = conn->data;
01124 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
01125 long timeout_ms;
01126 Qso_OverlappedIO_t cstat;
01127 CURLcode result = CURLE_OK;
01128
01129 *done = connssl->state == ssl_connection_complete;
01130 if(*done)
01131 return CURLE_OK;
01132
01133
01134 if(connssl->connecting_state == ssl_connect_1) {
01135
01136 timeout_ms = Curl_timeleft(data, NULL, TRUE);
01137
01138 if(timeout_ms < 0) {
01139
01140 failf(data, "SSL connection timeout");
01141 result = CURLE_OPERATION_TIMEDOUT;
01142 }
01143 else
01144 result = gskit_connect_step1(conn, sockindex);
01145 }
01146
01147
01148 if(!result)
01149 if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
01150 result = CURLE_SSL_CONNECT_ERROR;
01151
01152
01153 if(!result && connssl->connecting_state == ssl_connect_2) {
01154
01155 timeout_ms = Curl_timeleft(data, NULL, TRUE);
01156
01157 if(timeout_ms < 0) {
01158
01159 failf(data, "SSL connection timeout");
01160 result = CURLE_OPERATION_TIMEDOUT;
01161 }
01162 else
01163 result = gskit_connect_step2(conn, sockindex, nonblocking);
01164 }
01165
01166
01167 if(!result)
01168 if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
01169 result = CURLE_SSL_CONNECT_ERROR;
01170
01171
01172 if(!result && connssl->connecting_state == ssl_connect_3)
01173 result = gskit_connect_step3(conn, sockindex);
01174
01175 if(result)
01176 close_one(connssl, conn, sockindex);
01177 else if(connssl->connecting_state == ssl_connect_done) {
01178 connssl->state = ssl_connection_complete;
01179 connssl->connecting_state = ssl_connect_1;
01180 conn->recv[sockindex] = gskit_recv;
01181 conn->send[sockindex] = gskit_send;
01182 *done = TRUE;
01183 }
01184
01185 return result;
01186 }
01187
01188
01189 CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
01190 int sockindex,
01191 bool *done)
01192 {
01193 CURLcode result;
01194
01195 result = gskit_connect_common(conn, sockindex, TRUE, done);
01196 if(*done || result)
01197 conn->ssl[sockindex].connecting_state = ssl_connect_1;
01198 return result;
01199 }
01200
01201
01202 CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
01203 {
01204 CURLcode result;
01205 bool done;
01206
01207 conn->ssl[sockindex].connecting_state = ssl_connect_1;
01208 result = gskit_connect_common(conn, sockindex, FALSE, &done);
01209 if(result)
01210 return result;
01211
01212 DEBUGASSERT(done);
01213
01214 return CURLE_OK;
01215 }
01216
01217
01218 void Curl_gskit_close(struct connectdata *conn, int sockindex)
01219 {
01220 close_one(&conn->ssl[sockindex], conn, sockindex);
01221 close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
01222 }
01223
01224
01225 int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
01226 {
01227 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
01228 struct Curl_easy *data = conn->data;
01229 ssize_t nread;
01230 int what;
01231 int rc;
01232 char buf[120];
01233
01234 if(!connssl->handle)
01235 return 0;
01236
01237 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
01238 return 0;
01239
01240 close_one(connssl, conn, sockindex);
01241 rc = 0;
01242 what = SOCKET_READABLE(conn->sock[sockindex],
01243 SSL_SHUTDOWN_TIMEOUT);
01244
01245 for(;;) {
01246 if(what < 0) {
01247
01248 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
01249 rc = -1;
01250 break;
01251 }
01252
01253 if(!what) {
01254 failf(data, "SSL shutdown timeout");
01255 break;
01256 }
01257
01258
01259
01260
01261
01262 nread = read(conn->sock[sockindex], buf, sizeof(buf));
01263
01264 if(nread < 0) {
01265 failf(data, "read: %s", strerror(errno));
01266 rc = -1;
01267 }
01268
01269 if(nread <= 0)
01270 break;
01271
01272 what = SOCKET_READABLE(conn->sock[sockindex], 0);
01273 }
01274
01275 return rc;
01276 }
01277
01278
01279 size_t Curl_gskit_version(char *buffer, size_t size)
01280 {
01281 strncpy(buffer, "GSKit", size);
01282 return strlen(buffer);
01283 }
01284
01285
01286 int Curl_gskit_check_cxn(struct connectdata *cxn)
01287 {
01288 int err;
01289 int errlen;
01290
01291
01292
01293 if(!cxn->ssl[FIRSTSOCKET].handle)
01294 return 0;
01295
01296 err = 0;
01297 errlen = sizeof err;
01298
01299 if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
01300 (unsigned char *) &err, &errlen) ||
01301 errlen != sizeof err || err)
01302 return 0;
01303
01304 return -1;
01305 }
01306
01307 #endif