1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
30 /* Some symbols are undefined/unsupported on OS400 versions < V7R1. */
31 #ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
32 #define GSK_SSL_EXTN_SERVERNAME_REQUEST 230
35 #ifndef GSK_TLSV10_CIPHER_SPECS
36 #define GSK_TLSV10_CIPHER_SPECS 236
39 #ifndef GSK_TLSV11_CIPHER_SPECS
40 #define GSK_TLSV11_CIPHER_SPECS 237
43 #ifndef GSK_TLSV12_CIPHER_SPECS
44 #define GSK_TLSV12_CIPHER_SPECS 238
47 #ifndef GSK_PROTOCOL_TLSV11
48 #define GSK_PROTOCOL_TLSV11 437
51 #ifndef GSK_PROTOCOL_TLSV12
52 #define GSK_PROTOCOL_TLSV12 438
68 #include <curl/curl.h>
73 #include "connect.h" /* for the connect timeout */
77 #include "curl_printf.h"
79 #include "curl_memory.h"
80 /* The last #include file should be: */
86 #define SOS_WRITE 0x02
88 /* SSL version flags. */
89 #define CURL_GSKPROTO_SSLV2 0
90 #define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
91 #define CURL_GSKPROTO_SSLV3 1
92 #define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3)
93 #define CURL_GSKPROTO_TLSV10 2
94 #define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10)
95 #define CURL_GSKPROTO_TLSV11 3
96 #define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11)
97 #define CURL_GSKPROTO_TLSV12 4
98 #define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
99 #define CURL_GSKPROTO_LAST 5
102 /* Supported ciphers. */
104 const char *name; /* Cipher name. */
105 const char *gsktoken; /* Corresponding token for GSKit String. */
106 unsigned int versions; /* SSL version flags. */
109 static const gskit_cipher ciphertable[] = {
111 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
112 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
114 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
115 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
116 { "exp-rc4-md5", "03",
117 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
119 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
120 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
122 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
123 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
124 { "exp-rc2-cbc-md5", "06",
125 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
126 { "exp-des-cbc-sha", "09",
127 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
128 CURL_GSKPROTO_TLSV11_MASK },
129 { "des-cbc3-sha", "0A",
130 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
131 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
132 { "aes128-sha", "2F",
133 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
134 CURL_GSKPROTO_TLSV12_MASK },
135 { "aes256-sha", "35",
136 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
137 CURL_GSKPROTO_TLSV12_MASK },
138 { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK },
139 { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK },
140 { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK },
141 { "aes128-gcm-sha256",
142 "9C", CURL_GSKPROTO_TLSV12_MASK },
143 { "aes256-gcm-sha384",
144 "9D", CURL_GSKPROTO_TLSV12_MASK },
145 { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK },
146 { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK },
147 { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK },
148 { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK },
149 { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK },
150 { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK },
151 { (const char *) NULL, (const char *) NULL, 0 }
155 static bool is_separator(char c)
157 /* Return whether character is a cipher list separator. */
170 static CURLcode gskit_status(struct Curl_easy *data, int rc,
171 const char *procname, CURLcode defcode)
173 /* Process GSKit status and map it to a CURLcode. */
176 case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
178 case GSK_KEYRING_OPEN_ERROR:
179 case GSK_OS400_ERROR_NO_ACCESS:
180 return CURLE_SSL_CACERT_BADFILE;
181 case GSK_INSUFFICIENT_STORAGE:
182 return CURLE_OUT_OF_MEMORY;
183 case GSK_ERROR_BAD_V2_CIPHER:
184 case GSK_ERROR_BAD_V3_CIPHER:
185 case GSK_ERROR_NO_CIPHERS:
186 return CURLE_SSL_CIPHER;
187 case GSK_OS400_ERROR_NOT_TRUSTED_ROOT:
188 case GSK_ERROR_CERT_VALIDATION:
189 return CURLE_PEER_FAILED_VERIFICATION;
190 case GSK_OS400_ERROR_TIMED_OUT:
191 return CURLE_OPERATION_TIMEDOUT;
192 case GSK_WOULD_BLOCK:
194 case GSK_OS400_ERROR_NOT_REGISTERED:
199 return CURLE_OUT_OF_MEMORY;
201 failf(data, "%s I/O error: %s", procname, strerror(errno));
206 failf(data, "%s: %s", procname, gsk_strerror(rc));
213 static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
214 GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
216 int rc = gsk_attribute_set_enum(h, id, value);
222 failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
224 case GSK_ATTRIBUTE_INVALID_ID:
226 return CURLE_UNSUPPORTED_PROTOCOL;
228 failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
231 return CURLE_SSL_CONNECT_ERROR;
235 static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
236 GSK_BUF_ID id, const char *buffer, bool unsupported_ok)
238 int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
244 failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
246 case GSK_ATTRIBUTE_INVALID_ID:
248 return CURLE_UNSUPPORTED_PROTOCOL;
250 failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
253 return CURLE_SSL_CONNECT_ERROR;
257 static CURLcode set_numeric(struct Curl_easy *data,
258 gsk_handle h, GSK_NUM_ID id, int value)
260 int rc = gsk_attribute_set_numeric_value(h, id, value);
266 failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
270 failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
273 return CURLE_SSL_CONNECT_ERROR;
277 static CURLcode set_callback(struct Curl_easy *data,
278 gsk_handle h, GSK_CALLBACK_ID id, void *info)
280 int rc = gsk_attribute_set_callback(h, id, info);
286 failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno));
289 failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
292 return CURLE_SSL_CONNECT_ERROR;
296 static CURLcode set_ciphers(struct connectdata *conn,
297 gsk_handle h, unsigned int *protoflags)
299 struct Curl_easy *data = conn->data;
300 const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
302 const gskit_cipher *ctp;
310 } ciphers[CURL_GSKPROTO_LAST];
312 /* Compile cipher list into GSKit-compatible cipher lists. */
316 while(is_separator(*cipherlist)) /* Skip initial separators. */
321 /* We allocate GSKit buffers of the same size as the input string: since
322 GSKit tokens are always shorter than their cipher names, allocated buffers
323 will always be large enough to accomodate the result. */
324 l = strlen(cipherlist) + 1;
325 memset((char *) ciphers, 0, sizeof ciphers);
326 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
327 ciphers[i].buf = malloc(l);
328 if(!ciphers[i].buf) {
330 free(ciphers[i].buf);
331 return CURLE_OUT_OF_MEMORY;
333 ciphers[i].ptr = ciphers[i].buf;
334 *ciphers[i].ptr = '\0';
337 /* Process each cipher in input string. */
341 for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
343 l = cipherlist - clp;
346 /* Search the cipher in our table. */
347 for(ctp = ciphertable; ctp->name; ctp++)
348 if(strncasecompare(ctp->name, clp, l) && !ctp->name[l])
351 failf(data, "Unknown cipher %.*s", l, clp);
352 result = CURLE_SSL_CIPHER;
355 unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK |
356 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK));
357 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
358 if(ctp->versions & (1 << i)) {
359 strcpy(ciphers[i].ptr, ctp->gsktoken);
360 ciphers[i].ptr += strlen(ctp->gsktoken);
365 /* Advance to next cipher name or end of string. */
366 while(is_separator(*cipherlist))
370 /* Disable protocols with empty cipher lists. */
371 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
372 if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) {
373 *protoflags &= ~(1 << i);
374 ciphers[i].buf[0] = '\0';
378 /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */
379 if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) {
380 result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS,
381 ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE);
382 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
385 failf(data, "TLSv1.1-only ciphers are not yet supported");
386 result = CURLE_SSL_CIPHER;
390 if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) {
391 result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS,
392 ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE);
393 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
396 failf(data, "TLSv1.2-only ciphers are not yet supported");
397 result = CURLE_SSL_CIPHER;
402 /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to
403 the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */
404 if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) {
405 result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS,
406 ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE);
407 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
409 strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr,
410 ciphers[CURL_GSKPROTO_TLSV10].ptr);
414 /* Set-up other ciphers. */
415 if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK))
416 result = set_buffer(data, h, GSK_V3_CIPHER_SPECS,
417 ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE);
418 if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK))
419 result = set_buffer(data, h, GSK_V2_CIPHER_SPECS,
420 ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE);
423 for(i = 0; i < CURL_GSKPROTO_LAST; i++)
424 free(ciphers[i].buf);
430 int Curl_gskit_init(void)
432 /* No initialisation needed. */
438 void Curl_gskit_cleanup(void)
444 static CURLcode init_environment(struct Curl_easy *data,
445 gsk_handle *envir, const char *appid,
446 const char *file, const char *label,
447 const char *password)
453 /* Creates the GSKit environment. */
455 rc = gsk_environment_open(&h);
459 case GSK_INSUFFICIENT_STORAGE:
460 return CURLE_OUT_OF_MEMORY;
462 failf(data, "gsk_environment_open(): %s", gsk_strerror(rc));
463 return CURLE_SSL_CONNECT_ERROR;
466 result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
468 result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
470 result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
472 result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE);
473 if(!result && password)
474 result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);
477 /* Locate CAs, Client certificate and key according to our settings.
478 Note: this call may be blocking for some tenths of seconds. */
479 result = gskit_status(data, gsk_environment_init(h),
480 "gsk_environment_init()", CURLE_SSL_CERTPROBLEM);
486 /* Error: rollback. */
487 gsk_environment_close(&h);
492 static void cancel_async_handshake(struct connectdata *conn, int sockindex)
494 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
495 Qso_OverlappedIO_t cstat;
497 if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
498 QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL);
502 static void close_async_handshake(struct ssl_connect_data *connssl)
504 QsoDestroyIOCompletionPort(connssl->iocport);
505 connssl->iocport = -1;
510 * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To
511 * pipe an SSL stream into another, it is therefore needed to have a pair
512 * of such communicating sockets and handle the pipelining explicitly.
513 * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot
514 * be used to produce the pipeline.
515 * The solution is to simulate socketpair() for AF_INET with low-level API
516 * listen(), bind() and connect().
520 inetsocketpair(int sv[2])
522 int lfd; /* Listening socket. */
523 int sfd; /* Server socket. */
524 int cfd; /* Client socket. */
526 struct sockaddr_in addr1;
527 struct sockaddr_in addr2;
529 /* Create listening socket on a local dynamic port. */
530 lfd = socket(AF_INET, SOCK_STREAM, 0);
533 memset((char *) &addr1, 0, sizeof addr1);
534 addr1.sin_family = AF_INET;
535 addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
537 if(bind(lfd, (struct sockaddr *) &addr1, sizeof addr1) ||
538 listen(lfd, 2) < 0) {
543 /* Get the allocated port. */
545 if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) {
550 /* Create the client socket. */
551 cfd = socket(AF_INET, SOCK_STREAM, 0);
557 /* Request unblocking connection to the listening socket. */
558 curlx_nonblock(cfd, TRUE);
559 if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 &&
560 errno != EINPROGRESS) {
566 /* Get the client dynamic port for intrusion check below. */
568 if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
574 /* Accept the incoming connection and get the server socket. */
575 curlx_nonblock(lfd, TRUE);
578 sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
585 /* Check for possible intrusion from an external process. */
586 if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr &&
587 addr1.sin_port == addr2.sin_port)
590 /* Intrusion: reject incoming connection. */
594 /* Done, return sockets and succeed. */
596 curlx_nonblock(cfd, FALSE);
602 static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
605 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
606 struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex];
613 struct timeval tv = {0, 0};
614 char buf[CURL_MAX_WRITE_SIZE];
616 if(!connssl->use || !connproxyssl->use)
617 return 0; /* No SSL over SSL: OK. */
622 if(directions & SOS_READ) {
623 FD_SET(connssl->remotefd, &fds_write);
624 n = connssl->remotefd;
626 if(directions & SOS_WRITE) {
627 FD_SET(connssl->remotefd, &fds_read);
628 n = connssl->remotefd;
629 FD_SET(conn->sock[sockindex], &fds_write);
630 if(n < conn->sock[sockindex])
631 n = conn->sock[sockindex];
633 i = select(n + 1, &fds_read, &fds_write, NULL, &tv);
635 return -1; /* Select error. */
637 if(FD_ISSET(connssl->remotefd, &fds_write)) {
638 /* Try getting data from HTTPS proxy and pipe it upstream. */
640 i = gsk_secure_soc_read(connproxyssl->handle, buf, sizeof buf, &n);
644 i = write(connssl->remotefd, buf, n);
650 case GSK_OS400_ERROR_TIMED_OUT:
651 case GSK_WOULD_BLOCK:
658 if(FD_ISSET(connssl->remotefd, &fds_read) &&
659 FD_ISSET(conn->sock[sockindex], &fds_write)) {
660 /* Pipe data to HTTPS proxy. */
661 n = read(connssl->remotefd, buf, sizeof buf);
665 i = gsk_secure_soc_write(connproxyssl->handle, buf, n, &m);
666 if(i != GSK_OK || n != m)
676 static void close_one(struct ssl_connect_data *connssl,
677 struct connectdata *conn, int sockindex)
679 if(connssl->handle) {
680 gskit_status(conn->data, gsk_secure_soc_close(&connssl->handle),
681 "gsk_secure_soc_close()", 0);
682 /* Last chance to drain output. */
683 while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
685 connssl->handle = (gsk_handle) NULL;
686 if(connssl->localfd >= 0) {
687 close(connssl->localfd);
688 connssl->localfd = -1;
690 if(connssl->remotefd >= 0) {
691 close(connssl->remotefd);
692 connssl->remotefd = -1;
695 if(connssl->iocport >= 0)
696 close_async_handshake(connssl);
700 static ssize_t gskit_send(struct connectdata *conn, int sockindex,
701 const void *mem, size_t len, CURLcode *curlcode)
703 struct Curl_easy *data = conn->data;
704 CURLcode cc = CURLE_SEND_ERROR;
707 if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
708 cc = gskit_status(data,
709 gsk_secure_soc_write(conn->ssl[sockindex].handle,
710 (char *) mem, (int) len, &written),
711 "gsk_secure_soc_write()", CURLE_SEND_ERROR);
713 if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
714 cc = CURLE_SEND_ERROR;
720 return (ssize_t) written; /* number of bytes */
724 static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
725 size_t buffersize, CURLcode *curlcode)
727 struct Curl_easy *data = conn->data;
730 CURLcode cc = CURLE_RECV_ERROR;
732 if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
733 buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
734 cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
735 buf, buffsize, &nread),
736 "gsk_secure_soc_read()", CURLE_RECV_ERROR);
741 case CURLE_OPERATION_TIMEDOUT:
748 return (ssize_t) nread;
752 static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
754 struct Curl_easy *data = conn->data;
755 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
759 const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
760 const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
761 const char * const keyringlabel = SSL_SET_OPTION(cert);
762 const long int ssl_version = SSL_CONN_CONFIG(version);
763 const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
764 const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
767 unsigned int protoflags;
769 Qso_OverlappedIO_t commarea;
771 static const int sobufsize = CURL_MAX_WRITE_SIZE;
773 /* Create SSL environment, start (preferably asynchronous) handshake. */
775 connssl->handle = (gsk_handle) NULL;
776 connssl->iocport = -1;
777 connssl->localfd = -1;
778 connssl->remotefd = -1;
780 /* GSKit supports two ways of specifying an SSL context: either by
781 * application identifier (that should have been defined at the system
782 * level) or by keyring file, password and certificate label.
783 * Local certificate name (CURLOPT_SSLCERT) is used to hold either the
784 * application identifier of the certificate label.
785 * Key password (CURLOPT_KEYPASSWD) holds the keyring password.
786 * It is not possible to have different keyrings for the CAs and the
787 * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify
789 * If no key password is given and the keyring is the system keyring,
790 * application identifier mode is tried first, as recommended in IBM doc.
793 envir = (gsk_handle) NULL;
795 if(keyringlabel && *keyringlabel && !keyringpwd &&
796 !strcmp(keyringfile, CURL_CA_BUNDLE)) {
797 /* Try application identifier mode. */
798 init_environment(data, &envir, keyringlabel, (const char *) NULL,
799 (const char *) NULL, (const char *) NULL);
803 /* Use keyring mode. */
804 result = init_environment(data, &envir, (const char *) NULL,
805 keyringfile, keyringlabel, keyringpwd);
810 /* Create secure session. */
811 result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
812 "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
813 gsk_environment_close(&envir);
817 /* Establish a pipelining socket pair for SSL over SSL. */
818 if(conn->proxy_ssl[sockindex].use) {
819 if(inetsocketpair(sockpair))
820 return CURLE_SSL_CONNECT_ERROR;
821 connssl->localfd = sockpair[0];
822 connssl->remotefd = sockpair[1];
823 setsockopt(connssl->localfd, SOL_SOCKET, SO_RCVBUF,
824 (void *) sobufsize, sizeof sobufsize);
825 setsockopt(connssl->remotefd, SOL_SOCKET, SO_RCVBUF,
826 (void *) sobufsize, sizeof sobufsize);
827 setsockopt(connssl->localfd, SOL_SOCKET, SO_SNDBUF,
828 (void *) sobufsize, sizeof sobufsize);
829 setsockopt(connssl->remotefd, SOL_SOCKET, SO_SNDBUF,
830 (void *) sobufsize, sizeof sobufsize);
831 curlx_nonblock(connssl->localfd, TRUE);
832 curlx_nonblock(connssl->remotefd, TRUE);
835 /* Determine which SSL/TLS version should be enabled. */
837 switch(ssl_version) {
838 case CURL_SSLVERSION_SSLv2:
839 protoflags = CURL_GSKPROTO_SSLV2_MASK;
842 case CURL_SSLVERSION_SSLv3:
843 protoflags = CURL_GSKPROTO_SSLV3_MASK;
846 case CURL_SSLVERSION_DEFAULT:
847 case CURL_SSLVERSION_TLSv1:
848 protoflags = CURL_GSKPROTO_TLSV10_MASK |
849 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
851 case CURL_SSLVERSION_TLSv1_0:
852 protoflags = CURL_GSKPROTO_TLSV10_MASK;
854 case CURL_SSLVERSION_TLSv1_1:
855 protoflags = CURL_GSKPROTO_TLSV11_MASK;
857 case CURL_SSLVERSION_TLSv1_2:
858 protoflags = CURL_GSKPROTO_TLSV12_MASK;
860 case CURL_SSLVERSION_TLSv1_3:
861 failf(data, "GSKit: TLS 1.3 is not yet supported");
862 return CURLE_SSL_CONNECT_ERROR;
864 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
865 return CURLE_SSL_CONNECT_ERROR;
868 /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
870 result = set_buffer(data, connssl->handle,
871 GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
872 if(result == CURLE_UNSUPPORTED_PROTOCOL)
876 /* Set session parameters. */
878 /* Compute the handshake timeout. Since GSKit granularity is 1 second,
879 we round up the required value. */
880 timeout = Curl_timeleft(data, NULL, TRUE);
882 result = CURLE_OPERATION_TIMEDOUT;
884 result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
885 (timeout + 999) / 1000);
888 result = set_numeric(data, connssl->handle, GSK_OS400_READ_TIMEOUT, 1);
890 result = set_numeric(data, connssl->handle, GSK_FD, connssl->localfd >= 0?
891 connssl->localfd: conn->sock[sockindex]);
893 result = set_ciphers(conn, connssl->handle, &protoflags);
895 failf(data, "No SSL protocol/cipher combination enabled");
896 result = CURLE_SSL_CIPHER;
899 result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
900 (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
901 GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
903 result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
904 (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
905 GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
907 result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
908 (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
909 GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
911 result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11,
912 (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
913 GSK_TRUE: GSK_FALSE, TRUE);
914 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
916 if(protoflags == CURL_GSKPROTO_TLSV11_MASK) {
917 failf(data, "TLS 1.1 not yet supported");
918 result = CURLE_SSL_CIPHER;
923 result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12,
924 (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
925 GSK_TRUE: GSK_FALSE, TRUE);
926 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
928 if(protoflags == CURL_GSKPROTO_TLSV12_MASK) {
929 failf(data, "TLS 1.2 not yet supported");
930 result = CURLE_SSL_CIPHER;
935 result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
936 verifypeer? GSK_SERVER_AUTH_FULL:
937 GSK_SERVER_AUTH_PASSTHRU, FALSE);
940 /* Start handshake. Try asynchronous first. */
941 memset(&commarea, 0, sizeof commarea);
942 connssl->iocport = QsoCreateIOCompletionPort();
943 if(connssl->iocport != -1) {
944 result = gskit_status(data,
945 gsk_secure_soc_startInit(connssl->handle,
948 "gsk_secure_soc_startInit()",
949 CURLE_SSL_CONNECT_ERROR);
951 connssl->connecting_state = ssl_connect_2;
955 close_async_handshake(connssl);
957 else if(errno != ENOBUFS)
958 result = gskit_status(data, GSK_ERROR_IO,
959 "QsoCreateIOCompletionPort()", 0);
960 else if(conn->proxy_ssl[sockindex].use) {
961 /* Cannot pipeline while handshaking synchronously. */
962 result = CURLE_SSL_CONNECT_ERROR;
965 /* No more completion port available. Use synchronous IO. */
966 result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
967 "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
969 connssl->connecting_state = ssl_connect_3;
975 /* Error: rollback. */
976 close_one(connssl, conn, sockindex);
981 static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
984 struct Curl_easy *data = conn->data;
985 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
986 Qso_OverlappedIO_t cstat;
991 /* Poll or wait for end of SSL asynchronous handshake. */
994 timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
997 stmv.tv_sec = timeout_ms / 1000;
998 stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
999 switch(QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
1000 case 1: /* Operation complete. */
1002 case -1: /* An error occurred: handshake still in progress. */
1003 if(errno == EINTR) {
1006 continue; /* Retry. */
1008 if(errno != ETIME) {
1009 failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno));
1010 cancel_async_handshake(conn, sockindex);
1011 close_async_handshake(connssl);
1012 return CURLE_SSL_CONNECT_ERROR;
1015 case 0: /* Handshake in progress, timeout occurred. */
1018 cancel_async_handshake(conn, sockindex);
1019 close_async_handshake(connssl);
1020 return CURLE_OPERATION_TIMEDOUT;
1024 result = gskit_status(data, cstat.returnValue, "SSL handshake",
1025 CURLE_SSL_CONNECT_ERROR);
1027 connssl->connecting_state = ssl_connect_3;
1028 close_async_handshake(connssl);
1033 static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
1035 struct Curl_easy *data = conn->data;
1036 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1037 const gsk_cert_data_elem *cdev;
1039 const gsk_cert_data_elem *p;
1040 const char *cert = (const char *) NULL;
1041 const char *certend;
1046 /* SSL handshake done: gather certificate info and verify host. */
1048 if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle,
1049 GSK_PARTNER_CERT_INFO,
1051 "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
1053 infof(data, "Server certificate:\n");
1055 for(i = 0; i++ < cdec; p++)
1056 switch(p->cert_data_id) {
1058 cert = p->cert_data_p;
1059 certend = cert + cdev->cert_data_l;
1061 case CERT_DN_PRINTABLE:
1062 infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p);
1064 case CERT_ISSUER_DN_PRINTABLE:
1065 infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p);
1067 case CERT_VALID_FROM:
1068 infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p);
1071 infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p);
1077 result = Curl_verifyhost(conn, cert, certend);
1081 /* The only place GSKit can get the whole CA chain is a validation
1082 callback where no user data pointer is available. Therefore it's not
1083 possible to copy this chain into our structures for CAINFO.
1084 However the server certificate may be available, thus we can return
1086 if(data->set.ssl.certinfo) {
1087 result = Curl_ssl_init_certinfo(data, 1);
1092 result = Curl_extract_certinfo(conn, 0, cert, certend);
1098 /* Check pinned public key. */
1099 ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1100 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
1101 if(!result && ptr) {
1102 curl_X509certificate x509;
1103 curl_asn1Element *p;
1105 if(Curl_parseX509(&x509, cert, certend))
1106 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1107 p = &x509.subjectPublicKeyInfo;
1108 result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header);
1110 failf(data, "SSL: public key does not match pinned public key!");
1115 connssl->connecting_state = ssl_connect_done;
1120 static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
1121 bool nonblocking, bool *done)
1123 struct Curl_easy *data = conn->data;
1124 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1126 Qso_OverlappedIO_t cstat;
1127 CURLcode result = CURLE_OK;
1129 *done = connssl->state == ssl_connection_complete;
1133 /* Step 1: create session, start handshake. */
1134 if(connssl->connecting_state == ssl_connect_1) {
1135 /* check allowed time left */
1136 timeout_ms = Curl_timeleft(data, NULL, TRUE);
1138 if(timeout_ms < 0) {
1139 /* no need to continue if time already is up */
1140 failf(data, "SSL connection timeout");
1141 result = CURLE_OPERATION_TIMEDOUT;
1144 result = gskit_connect_step1(conn, sockindex);
1147 /* Handle handshake pipelining. */
1149 if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
1150 result = CURLE_SSL_CONNECT_ERROR;
1152 /* Step 2: check if handshake is over. */
1153 if(!result && connssl->connecting_state == ssl_connect_2) {
1154 /* check allowed time left */
1155 timeout_ms = Curl_timeleft(data, NULL, TRUE);
1157 if(timeout_ms < 0) {
1158 /* no need to continue if time already is up */
1159 failf(data, "SSL connection timeout");
1160 result = CURLE_OPERATION_TIMEDOUT;
1163 result = gskit_connect_step2(conn, sockindex, nonblocking);
1166 /* Handle handshake pipelining. */
1168 if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
1169 result = CURLE_SSL_CONNECT_ERROR;
1171 /* Step 3: gather certificate info, verify host. */
1172 if(!result && connssl->connecting_state == ssl_connect_3)
1173 result = gskit_connect_step3(conn, sockindex);
1176 close_one(connssl, conn, sockindex);
1177 else if(connssl->connecting_state == ssl_connect_done) {
1178 connssl->state = ssl_connection_complete;
1179 connssl->connecting_state = ssl_connect_1;
1180 conn->recv[sockindex] = gskit_recv;
1181 conn->send[sockindex] = gskit_send;
1189 CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
1195 result = gskit_connect_common(conn, sockindex, TRUE, done);
1197 conn->ssl[sockindex].connecting_state = ssl_connect_1;
1202 CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
1207 conn->ssl[sockindex].connecting_state = ssl_connect_1;
1208 result = gskit_connect_common(conn, sockindex, FALSE, &done);
1218 void Curl_gskit_close(struct connectdata *conn, int sockindex)
1220 close_one(&conn->ssl[sockindex], conn, sockindex);
1221 close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
1225 int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
1227 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1228 struct Curl_easy *data = conn->data;
1234 if(!connssl->handle)
1237 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
1240 close_one(connssl, conn, sockindex);
1242 what = SOCKET_READABLE(conn->sock[sockindex],
1243 SSL_SHUTDOWN_TIMEOUT);
1247 /* anything that gets here is fatally bad */
1248 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1253 if(!what) { /* timeout */
1254 failf(data, "SSL shutdown timeout");
1258 /* Something to read, let's do it and hope that it is the close
1259 notify alert from the server. No way to gsk_secure_soc_read() now, so
1262 nread = read(conn->sock[sockindex], buf, sizeof(buf));
1265 failf(data, "read: %s", strerror(errno));
1272 what = SOCKET_READABLE(conn->sock[sockindex], 0);
1279 size_t Curl_gskit_version(char *buffer, size_t size)
1281 strncpy(buffer, "GSKit", size);
1282 return strlen(buffer);
1286 int Curl_gskit_check_cxn(struct connectdata *cxn)
1291 /* The only thing that can be tested here is at the socket level. */
1293 if(!cxn->ssl[FIRSTSOCKET].handle)
1294 return 0; /* connection has been closed */
1297 errlen = sizeof err;
1299 if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
1300 (unsigned char *) &err, &errlen) ||
1301 errlen != sizeof err || err)
1302 return 0; /* connection has been closed */
1304 return -1; /* connection status unknown */
1307 #endif /* USE_GSKIT */