1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2017, 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
66 #include <curl/curl.h>
71 #include "connect.h" /* for the connect timeout */
75 #include "curl_printf.h"
77 #include "curl_memory.h"
78 /* The last #include file should be: */
84 #define SOS_WRITE 0x02
86 /* SSL version flags. */
87 #define CURL_GSKPROTO_SSLV2 0
88 #define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
89 #define CURL_GSKPROTO_SSLV3 1
90 #define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3)
91 #define CURL_GSKPROTO_TLSV10 2
92 #define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10)
93 #define CURL_GSKPROTO_TLSV11 3
94 #define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11)
95 #define CURL_GSKPROTO_TLSV12 4
96 #define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
97 #define CURL_GSKPROTO_LAST 5
99 struct ssl_backend_data {
106 #define BACKEND connssl->backend
108 /* Supported ciphers. */
110 const char *name; /* Cipher name. */
111 const char *gsktoken; /* Corresponding token for GSKit String. */
112 unsigned int versions; /* SSL version flags. */
115 static const gskit_cipher ciphertable[] = {
117 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
118 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
120 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
121 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
122 { "exp-rc4-md5", "03",
123 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
125 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
126 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
128 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
129 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
130 { "exp-rc2-cbc-md5", "06",
131 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
132 { "exp-des-cbc-sha", "09",
133 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
134 CURL_GSKPROTO_TLSV11_MASK },
135 { "des-cbc3-sha", "0A",
136 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
137 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
138 { "aes128-sha", "2F",
139 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
140 CURL_GSKPROTO_TLSV12_MASK },
141 { "aes256-sha", "35",
142 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
143 CURL_GSKPROTO_TLSV12_MASK },
144 { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK },
145 { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK },
146 { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK },
147 { "aes128-gcm-sha256",
148 "9C", CURL_GSKPROTO_TLSV12_MASK },
149 { "aes256-gcm-sha384",
150 "9D", CURL_GSKPROTO_TLSV12_MASK },
151 { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK },
152 { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK },
153 { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK },
154 { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK },
155 { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK },
156 { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK },
157 { (const char *) NULL, (const char *) NULL, 0 }
161 static bool is_separator(char c)
163 /* Return whether character is a cipher list separator. */
176 static CURLcode gskit_status(struct Curl_easy *data, int rc,
177 const char *procname, CURLcode defcode)
179 /* Process GSKit status and map it to a CURLcode. */
182 case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
184 case GSK_KEYRING_OPEN_ERROR:
185 case GSK_OS400_ERROR_NO_ACCESS:
186 return CURLE_SSL_CACERT_BADFILE;
187 case GSK_INSUFFICIENT_STORAGE:
188 return CURLE_OUT_OF_MEMORY;
189 case GSK_ERROR_BAD_V2_CIPHER:
190 case GSK_ERROR_BAD_V3_CIPHER:
191 case GSK_ERROR_NO_CIPHERS:
192 return CURLE_SSL_CIPHER;
193 case GSK_OS400_ERROR_NOT_TRUSTED_ROOT:
194 case GSK_ERROR_CERT_VALIDATION:
195 return CURLE_PEER_FAILED_VERIFICATION;
196 case GSK_OS400_ERROR_TIMED_OUT:
197 return CURLE_OPERATION_TIMEDOUT;
198 case GSK_WOULD_BLOCK:
200 case GSK_OS400_ERROR_NOT_REGISTERED:
205 return CURLE_OUT_OF_MEMORY;
207 failf(data, "%s I/O error: %s", procname, strerror(errno));
212 failf(data, "%s: %s", procname, gsk_strerror(rc));
219 static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
220 GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
222 int rc = gsk_attribute_set_enum(h, id, value);
228 failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
230 case GSK_ATTRIBUTE_INVALID_ID:
232 return CURLE_UNSUPPORTED_PROTOCOL;
234 failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
237 return CURLE_SSL_CONNECT_ERROR;
241 static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
242 GSK_BUF_ID id, const char *buffer, bool unsupported_ok)
244 int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
250 failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
252 case GSK_ATTRIBUTE_INVALID_ID:
254 return CURLE_UNSUPPORTED_PROTOCOL;
256 failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
259 return CURLE_SSL_CONNECT_ERROR;
263 static CURLcode set_numeric(struct Curl_easy *data,
264 gsk_handle h, GSK_NUM_ID id, int value)
266 int rc = gsk_attribute_set_numeric_value(h, id, value);
272 failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
276 failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
279 return CURLE_SSL_CONNECT_ERROR;
283 static CURLcode set_callback(struct Curl_easy *data,
284 gsk_handle h, GSK_CALLBACK_ID id, void *info)
286 int rc = gsk_attribute_set_callback(h, id, info);
292 failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno));
295 failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
298 return CURLE_SSL_CONNECT_ERROR;
302 static CURLcode set_ciphers(struct connectdata *conn,
303 gsk_handle h, unsigned int *protoflags)
305 struct Curl_easy *data = conn->data;
306 const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
308 const gskit_cipher *ctp;
316 } ciphers[CURL_GSKPROTO_LAST];
318 /* Compile cipher list into GSKit-compatible cipher lists. */
322 while(is_separator(*cipherlist)) /* Skip initial separators. */
327 /* We allocate GSKit buffers of the same size as the input string: since
328 GSKit tokens are always shorter than their cipher names, allocated buffers
329 will always be large enough to accommodate the result. */
330 l = strlen(cipherlist) + 1;
331 memset((char *) ciphers, 0, sizeof ciphers);
332 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
333 ciphers[i].buf = malloc(l);
334 if(!ciphers[i].buf) {
336 free(ciphers[i].buf);
337 return CURLE_OUT_OF_MEMORY;
339 ciphers[i].ptr = ciphers[i].buf;
340 *ciphers[i].ptr = '\0';
343 /* Process each cipher in input string. */
347 for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
349 l = cipherlist - clp;
352 /* Search the cipher in our table. */
353 for(ctp = ciphertable; ctp->name; ctp++)
354 if(strncasecompare(ctp->name, clp, l) && !ctp->name[l])
357 failf(data, "Unknown cipher %.*s", l, clp);
358 result = CURLE_SSL_CIPHER;
361 unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK |
362 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK));
363 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
364 if(ctp->versions & (1 << i)) {
365 strcpy(ciphers[i].ptr, ctp->gsktoken);
366 ciphers[i].ptr += strlen(ctp->gsktoken);
371 /* Advance to next cipher name or end of string. */
372 while(is_separator(*cipherlist))
376 /* Disable protocols with empty cipher lists. */
377 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
378 if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) {
379 *protoflags &= ~(1 << i);
380 ciphers[i].buf[0] = '\0';
384 /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */
385 if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) {
386 result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS,
387 ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE);
388 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
391 failf(data, "TLSv1.1-only ciphers are not yet supported");
392 result = CURLE_SSL_CIPHER;
396 if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) {
397 result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS,
398 ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE);
399 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
402 failf(data, "TLSv1.2-only ciphers are not yet supported");
403 result = CURLE_SSL_CIPHER;
408 /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to
409 the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */
410 if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) {
411 result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS,
412 ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE);
413 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
415 strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr,
416 ciphers[CURL_GSKPROTO_TLSV10].ptr);
420 /* Set-up other ciphers. */
421 if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK))
422 result = set_buffer(data, h, GSK_V3_CIPHER_SPECS,
423 ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE);
424 if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK))
425 result = set_buffer(data, h, GSK_V2_CIPHER_SPECS,
426 ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE);
429 for(i = 0; i < CURL_GSKPROTO_LAST; i++)
430 free(ciphers[i].buf);
436 static int Curl_gskit_init(void)
438 /* No initialisation needed. */
444 static void Curl_gskit_cleanup(void)
450 static CURLcode init_environment(struct Curl_easy *data,
451 gsk_handle *envir, const char *appid,
452 const char *file, const char *label,
453 const char *password)
459 /* Creates the GSKit environment. */
461 rc = gsk_environment_open(&h);
465 case GSK_INSUFFICIENT_STORAGE:
466 return CURLE_OUT_OF_MEMORY;
468 failf(data, "gsk_environment_open(): %s", gsk_strerror(rc));
469 return CURLE_SSL_CONNECT_ERROR;
472 result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
474 result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
476 result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
478 result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE);
479 if(!result && password)
480 result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);
483 /* Locate CAs, Client certificate and key according to our settings.
484 Note: this call may be blocking for some tenths of seconds. */
485 result = gskit_status(data, gsk_environment_init(h),
486 "gsk_environment_init()", CURLE_SSL_CERTPROBLEM);
492 /* Error: rollback. */
493 gsk_environment_close(&h);
498 static void cancel_async_handshake(struct connectdata *conn, int sockindex)
500 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
501 Qso_OverlappedIO_t cstat;
503 if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
504 QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL);
508 static void close_async_handshake(struct ssl_connect_data *connssl)
510 QsoDestroyIOCompletionPort(BACKEND->iocport);
511 BACKEND->iocport = -1;
516 * 1) GSKit can only perform SSL on an AF_INET or AF_INET6 stream socket. To
517 * pipe an SSL stream into another, it is therefore needed to have a pair
518 * of such communicating sockets and handle the pipelining explicitly.
519 * 2) OS/400 socketpair() is only implemented for domain AF_UNIX, thus cannot
520 * be used to produce the pipeline.
521 * The solution is to simulate socketpair() for AF_INET with low-level API
522 * listen(), bind() and connect().
526 inetsocketpair(int sv[2])
528 int lfd; /* Listening socket. */
529 int sfd; /* Server socket. */
530 int cfd; /* Client socket. */
532 struct sockaddr_in addr1;
533 struct sockaddr_in addr2;
535 /* Create listening socket on a local dynamic port. */
536 lfd = socket(AF_INET, SOCK_STREAM, 0);
539 memset((char *) &addr1, 0, sizeof addr1);
540 addr1.sin_family = AF_INET;
541 addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
543 if(bind(lfd, (struct sockaddr *) &addr1, sizeof addr1) ||
544 listen(lfd, 2) < 0) {
549 /* Get the allocated port. */
551 if(getsockname(lfd, (struct sockaddr *) &addr1, &len) < 0) {
556 /* Create the client socket. */
557 cfd = socket(AF_INET, SOCK_STREAM, 0);
563 /* Request unblocking connection to the listening socket. */
564 curlx_nonblock(cfd, TRUE);
565 if(connect(cfd, (struct sockaddr *) &addr1, sizeof addr1) < 0 &&
566 errno != EINPROGRESS) {
572 /* Get the client dynamic port for intrusion check below. */
574 if(getsockname(cfd, (struct sockaddr *) &addr2, &len) < 0) {
580 /* Accept the incoming connection and get the server socket. */
581 curlx_nonblock(lfd, TRUE);
584 sfd = accept(lfd, (struct sockaddr *) &addr1, &len);
591 /* Check for possible intrusion from an external process. */
592 if(addr1.sin_addr.s_addr == addr2.sin_addr.s_addr &&
593 addr1.sin_port == addr2.sin_port)
596 /* Intrusion: reject incoming connection. */
600 /* Done, return sockets and succeed. */
602 curlx_nonblock(cfd, FALSE);
608 static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
611 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
612 struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex];
619 struct timeval tv = {0, 0};
620 char buf[CURL_MAX_WRITE_SIZE];
622 if(!connssl->use || !connproxyssl->use)
623 return 0; /* No SSL over SSL: OK. */
628 if(directions & SOS_READ) {
629 FD_SET(BACKEND->remotefd, &fds_write);
630 n = BACKEND->remotefd;
632 if(directions & SOS_WRITE) {
633 FD_SET(BACKEND->remotefd, &fds_read);
634 n = BACKEND->remotefd;
635 FD_SET(conn->sock[sockindex], &fds_write);
636 if(n < conn->sock[sockindex])
637 n = conn->sock[sockindex];
639 i = select(n + 1, &fds_read, &fds_write, NULL, &tv);
641 return -1; /* Select error. */
643 if(FD_ISSET(BACKEND->remotefd, &fds_write)) {
644 /* Try getting data from HTTPS proxy and pipe it upstream. */
646 i = gsk_secure_soc_read(connproxyssl->backend->handle,
647 buf, sizeof buf, &n);
651 i = write(BACKEND->remotefd, buf, n);
657 case GSK_OS400_ERROR_TIMED_OUT:
658 case GSK_WOULD_BLOCK:
665 if(FD_ISSET(BACKEND->remotefd, &fds_read) &&
666 FD_ISSET(conn->sock[sockindex], &fds_write)) {
667 /* Pipe data to HTTPS proxy. */
668 n = read(BACKEND->remotefd, buf, sizeof buf);
672 i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m);
673 if(i != GSK_OK || n != m)
683 static void close_one(struct ssl_connect_data *connssl,
684 struct connectdata *conn, int sockindex)
686 if(BACKEND->handle) {
687 gskit_status(conn->data, gsk_secure_soc_close(&BACKEND->handle),
688 "gsk_secure_soc_close()", 0);
689 /* Last chance to drain output. */
690 while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
692 BACKEND->handle = (gsk_handle) NULL;
693 if(BACKEND->localfd >= 0) {
694 close(BACKEND->localfd);
695 BACKEND->localfd = -1;
697 if(BACKEND->remotefd >= 0) {
698 close(BACKEND->remotefd);
699 BACKEND->remotefd = -1;
702 if(BACKEND->iocport >= 0)
703 close_async_handshake(connssl);
707 static ssize_t gskit_send(struct connectdata *conn, int sockindex,
708 const void *mem, size_t len, CURLcode *curlcode)
710 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
711 struct Curl_easy *data = conn->data;
712 CURLcode cc = CURLE_SEND_ERROR;
715 if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
716 cc = gskit_status(data,
717 gsk_secure_soc_write(BACKEND->handle,
718 (char *) mem, (int) len, &written),
719 "gsk_secure_soc_write()", CURLE_SEND_ERROR);
721 if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
722 cc = CURLE_SEND_ERROR;
728 return (ssize_t) written; /* number of bytes */
732 static ssize_t gskit_recv(struct connectdata *conn, int num, char *buf,
733 size_t buffersize, CURLcode *curlcode)
735 struct ssl_connect_data *connssl = &conn->ssl[num];
736 struct Curl_easy *data = conn->data;
739 CURLcode cc = CURLE_RECV_ERROR;
741 if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
742 buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
743 cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
744 buf, buffsize, &nread),
745 "gsk_secure_soc_read()", CURLE_RECV_ERROR);
750 case CURLE_OPERATION_TIMEDOUT:
757 return (ssize_t) nread;
761 set_ssl_version_min_max(unsigned int *protoflags, struct connectdata *conn)
763 struct Curl_easy *data = conn->data;
764 long ssl_version = SSL_CONN_CONFIG(version);
765 long ssl_version_max = SSL_CONN_CONFIG(version_max);
766 long i = ssl_version;
767 switch(ssl_version_max) {
768 case CURL_SSLVERSION_MAX_NONE:
769 ssl_version_max = ssl_version;
771 case CURL_SSLVERSION_MAX_DEFAULT:
772 ssl_version_max = CURL_SSLVERSION_TLSv1_2;
775 for(; i <= (ssl_version_max >> 16); ++i) {
777 case CURL_SSLVERSION_TLSv1_0:
778 *protoflags |= CURL_GSKPROTO_TLSV10_MASK;
780 case CURL_SSLVERSION_TLSv1_1:
781 *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
783 case CURL_SSLVERSION_TLSv1_2:
784 *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
786 case CURL_SSLVERSION_TLSv1_3:
787 failf(data, "GSKit: TLS 1.3 is not yet supported");
788 return CURLE_SSL_CONNECT_ERROR;
795 static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
797 struct Curl_easy *data = conn->data;
798 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
802 const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
803 const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
804 const char * const keyringlabel = SSL_SET_OPTION(cert);
805 const long int ssl_version = SSL_CONN_CONFIG(version);
806 const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
807 const char * const hostname = SSL_IS_PROXY()? conn->http_proxy.host.name:
810 unsigned int protoflags = 0;
812 Qso_OverlappedIO_t commarea;
814 static const int sobufsize = CURL_MAX_WRITE_SIZE;
816 /* Create SSL environment, start (preferably asynchronous) handshake. */
818 BACKEND->handle = (gsk_handle) NULL;
819 BACKEND->iocport = -1;
820 BACKEND->localfd = -1;
821 BACKEND->remotefd = -1;
823 /* GSKit supports two ways of specifying an SSL context: either by
824 * application identifier (that should have been defined at the system
825 * level) or by keyring file, password and certificate label.
826 * Local certificate name (CURLOPT_SSLCERT) is used to hold either the
827 * application identifier of the certificate label.
828 * Key password (CURLOPT_KEYPASSWD) holds the keyring password.
829 * It is not possible to have different keyrings for the CAs and the
830 * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify
832 * If no key password is given and the keyring is the system keyring,
833 * application identifier mode is tried first, as recommended in IBM doc.
836 envir = (gsk_handle) NULL;
838 if(keyringlabel && *keyringlabel && !keyringpwd &&
839 !strcmp(keyringfile, CURL_CA_BUNDLE)) {
840 /* Try application identifier mode. */
841 init_environment(data, &envir, keyringlabel, (const char *) NULL,
842 (const char *) NULL, (const char *) NULL);
846 /* Use keyring mode. */
847 result = init_environment(data, &envir, (const char *) NULL,
848 keyringfile, keyringlabel, keyringpwd);
853 /* Create secure session. */
854 result = gskit_status(data, gsk_secure_soc_open(envir, &BACKEND->handle),
855 "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
856 gsk_environment_close(&envir);
860 /* Establish a pipelining socket pair for SSL over SSL. */
861 if(conn->proxy_ssl[sockindex].use) {
862 if(inetsocketpair(sockpair))
863 return CURLE_SSL_CONNECT_ERROR;
864 BACKEND->localfd = sockpair[0];
865 BACKEND->remotefd = sockpair[1];
866 setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
867 (void *) sobufsize, sizeof sobufsize);
868 setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
869 (void *) sobufsize, sizeof sobufsize);
870 setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
871 (void *) sobufsize, sizeof sobufsize);
872 setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
873 (void *) sobufsize, sizeof sobufsize);
874 curlx_nonblock(BACKEND->localfd, TRUE);
875 curlx_nonblock(BACKEND->remotefd, TRUE);
878 /* Determine which SSL/TLS version should be enabled. */
880 switch(ssl_version) {
881 case CURL_SSLVERSION_SSLv2:
882 protoflags = CURL_GSKPROTO_SSLV2_MASK;
885 case CURL_SSLVERSION_SSLv3:
886 protoflags = CURL_GSKPROTO_SSLV3_MASK;
889 case CURL_SSLVERSION_DEFAULT:
890 case CURL_SSLVERSION_TLSv1:
891 protoflags = CURL_GSKPROTO_TLSV10_MASK |
892 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
894 case CURL_SSLVERSION_TLSv1_0:
895 case CURL_SSLVERSION_TLSv1_1:
896 case CURL_SSLVERSION_TLSv1_2:
897 case CURL_SSLVERSION_TLSv1_3:
898 result = set_ssl_version_min_max(&protoflags, conn);
899 if(result != CURLE_OK)
903 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
904 return CURLE_SSL_CONNECT_ERROR;
907 /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
909 result = set_buffer(data, BACKEND->handle,
910 GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
911 if(result == CURLE_UNSUPPORTED_PROTOCOL)
915 /* Set session parameters. */
917 /* Compute the handshake timeout. Since GSKit granularity is 1 second,
918 we round up the required value. */
919 timeout = Curl_timeleft(data, NULL, TRUE);
921 result = CURLE_OPERATION_TIMEDOUT;
923 result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT,
924 (timeout + 999) / 1000);
927 result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
929 result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
930 BACKEND->localfd: conn->sock[sockindex]);
932 result = set_ciphers(conn, BACKEND->handle, &protoflags);
934 failf(data, "No SSL protocol/cipher combination enabled");
935 result = CURLE_SSL_CIPHER;
938 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2,
939 (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
940 GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
942 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV3,
943 (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
944 GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
946 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV1,
947 (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
948 GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
950 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV11,
951 (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
952 GSK_TRUE: GSK_FALSE, TRUE);
953 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
955 if(protoflags == CURL_GSKPROTO_TLSV11_MASK) {
956 failf(data, "TLS 1.1 not yet supported");
957 result = CURLE_SSL_CIPHER;
962 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV12,
963 (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
964 GSK_TRUE: GSK_FALSE, TRUE);
965 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
967 if(protoflags == CURL_GSKPROTO_TLSV12_MASK) {
968 failf(data, "TLS 1.2 not yet supported");
969 result = CURLE_SSL_CIPHER;
974 result = set_enum(data, BACKEND->handle, GSK_SERVER_AUTH_TYPE,
975 verifypeer? GSK_SERVER_AUTH_FULL:
976 GSK_SERVER_AUTH_PASSTHRU, FALSE);
979 /* Start handshake. Try asynchronous first. */
980 memset(&commarea, 0, sizeof commarea);
981 BACKEND->iocport = QsoCreateIOCompletionPort();
982 if(BACKEND->iocport != -1) {
983 result = gskit_status(data,
984 gsk_secure_soc_startInit(BACKEND->handle,
987 "gsk_secure_soc_startInit()",
988 CURLE_SSL_CONNECT_ERROR);
990 connssl->connecting_state = ssl_connect_2;
994 close_async_handshake(connssl);
996 else if(errno != ENOBUFS)
997 result = gskit_status(data, GSK_ERROR_IO,
998 "QsoCreateIOCompletionPort()", 0);
999 else if(conn->proxy_ssl[sockindex].use) {
1000 /* Cannot pipeline while handshaking synchronously. */
1001 result = CURLE_SSL_CONNECT_ERROR;
1004 /* No more completion port available. Use synchronous IO. */
1005 result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle),
1006 "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
1008 connssl->connecting_state = ssl_connect_3;
1014 /* Error: rollback. */
1015 close_one(connssl, conn, sockindex);
1020 static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
1023 struct Curl_easy *data = conn->data;
1024 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1025 Qso_OverlappedIO_t cstat;
1027 struct timeval stmv;
1030 /* Poll or wait for end of SSL asynchronous handshake. */
1033 timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
1036 stmv.tv_sec = timeout_ms / 1000;
1037 stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
1038 switch(QsoWaitForIOCompletion(BACKEND->iocport, &cstat, &stmv)) {
1039 case 1: /* Operation complete. */
1041 case -1: /* An error occurred: handshake still in progress. */
1042 if(errno == EINTR) {
1045 continue; /* Retry. */
1047 if(errno != ETIME) {
1048 failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno));
1049 cancel_async_handshake(conn, sockindex);
1050 close_async_handshake(connssl);
1051 return CURLE_SSL_CONNECT_ERROR;
1054 case 0: /* Handshake in progress, timeout occurred. */
1057 cancel_async_handshake(conn, sockindex);
1058 close_async_handshake(connssl);
1059 return CURLE_OPERATION_TIMEDOUT;
1063 result = gskit_status(data, cstat.returnValue, "SSL handshake",
1064 CURLE_SSL_CONNECT_ERROR);
1066 connssl->connecting_state = ssl_connect_3;
1067 close_async_handshake(connssl);
1072 static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
1074 struct Curl_easy *data = conn->data;
1075 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1076 const gsk_cert_data_elem *cdev;
1078 const gsk_cert_data_elem *p;
1079 const char *cert = (const char *) NULL;
1080 const char *certend;
1085 /* SSL handshake done: gather certificate info and verify host. */
1087 if(gskit_status(data, gsk_attribute_get_cert_info(BACKEND->handle,
1088 GSK_PARTNER_CERT_INFO,
1090 "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
1092 infof(data, "Server certificate:\n");
1094 for(i = 0; i++ < cdec; p++)
1095 switch(p->cert_data_id) {
1097 cert = p->cert_data_p;
1098 certend = cert + cdev->cert_data_l;
1100 case CERT_DN_PRINTABLE:
1101 infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p);
1103 case CERT_ISSUER_DN_PRINTABLE:
1104 infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p);
1106 case CERT_VALID_FROM:
1107 infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p);
1110 infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p);
1116 result = Curl_verifyhost(conn, cert, certend);
1120 /* The only place GSKit can get the whole CA chain is a validation
1121 callback where no user data pointer is available. Therefore it's not
1122 possible to copy this chain into our structures for CAINFO.
1123 However the server certificate may be available, thus we can return
1125 if(data->set.ssl.certinfo) {
1126 result = Curl_ssl_init_certinfo(data, 1);
1131 result = Curl_extract_certinfo(conn, 0, cert, certend);
1137 /* Check pinned public key. */
1138 ptr = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
1139 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
1140 if(!result && ptr) {
1141 curl_X509certificate x509;
1142 curl_asn1Element *p;
1144 if(Curl_parseX509(&x509, cert, certend))
1145 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1146 p = &x509.subjectPublicKeyInfo;
1147 result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header);
1149 failf(data, "SSL: public key does not match pinned public key!");
1154 connssl->connecting_state = ssl_connect_done;
1159 static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
1160 bool nonblocking, bool *done)
1162 struct Curl_easy *data = conn->data;
1163 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1165 Qso_OverlappedIO_t cstat;
1166 CURLcode result = CURLE_OK;
1168 *done = connssl->state == ssl_connection_complete;
1172 /* Step 1: create session, start handshake. */
1173 if(connssl->connecting_state == ssl_connect_1) {
1174 /* check allowed time left */
1175 timeout_ms = Curl_timeleft(data, NULL, TRUE);
1177 if(timeout_ms < 0) {
1178 /* no need to continue if time already is up */
1179 failf(data, "SSL connection timeout");
1180 result = CURLE_OPERATION_TIMEDOUT;
1183 result = gskit_connect_step1(conn, sockindex);
1186 /* Handle handshake pipelining. */
1188 if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
1189 result = CURLE_SSL_CONNECT_ERROR;
1191 /* Step 2: check if handshake is over. */
1192 if(!result && connssl->connecting_state == ssl_connect_2) {
1193 /* check allowed time left */
1194 timeout_ms = Curl_timeleft(data, NULL, TRUE);
1196 if(timeout_ms < 0) {
1197 /* no need to continue if time already is up */
1198 failf(data, "SSL connection timeout");
1199 result = CURLE_OPERATION_TIMEDOUT;
1202 result = gskit_connect_step2(conn, sockindex, nonblocking);
1205 /* Handle handshake pipelining. */
1207 if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
1208 result = CURLE_SSL_CONNECT_ERROR;
1210 /* Step 3: gather certificate info, verify host. */
1211 if(!result && connssl->connecting_state == ssl_connect_3)
1212 result = gskit_connect_step3(conn, sockindex);
1215 close_one(connssl, conn, sockindex);
1216 else if(connssl->connecting_state == ssl_connect_done) {
1217 connssl->state = ssl_connection_complete;
1218 connssl->connecting_state = ssl_connect_1;
1219 conn->recv[sockindex] = gskit_recv;
1220 conn->send[sockindex] = gskit_send;
1228 static CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
1229 int sockindex, bool *done)
1233 result = gskit_connect_common(conn, sockindex, TRUE, done);
1235 conn->ssl[sockindex].connecting_state = ssl_connect_1;
1240 static CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
1245 conn->ssl[sockindex].connecting_state = ssl_connect_1;
1246 result = gskit_connect_common(conn, sockindex, FALSE, &done);
1256 static void Curl_gskit_close(struct connectdata *conn, int sockindex)
1258 close_one(&conn->ssl[sockindex], conn, sockindex);
1259 close_one(&conn->proxy_ssl[sockindex], conn, sockindex);
1263 static int Curl_gskit_shutdown(struct connectdata *conn, int sockindex)
1265 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1266 struct Curl_easy *data = conn->data;
1272 if(!BACKEND->handle)
1275 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
1278 close_one(connssl, conn, sockindex);
1280 what = SOCKET_READABLE(conn->sock[sockindex],
1281 SSL_SHUTDOWN_TIMEOUT);
1285 /* anything that gets here is fatally bad */
1286 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1291 if(!what) { /* timeout */
1292 failf(data, "SSL shutdown timeout");
1296 /* Something to read, let's do it and hope that it is the close
1297 notify alert from the server. No way to gsk_secure_soc_read() now, so
1300 nread = read(conn->sock[sockindex], buf, sizeof(buf));
1303 failf(data, "read: %s", strerror(errno));
1310 what = SOCKET_READABLE(conn->sock[sockindex], 0);
1317 static size_t Curl_gskit_version(char *buffer, size_t size)
1319 strncpy(buffer, "GSKit", size);
1320 return strlen(buffer);
1324 static int Curl_gskit_check_cxn(struct connectdata *cxn)
1326 struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
1330 /* The only thing that can be tested here is at the socket level. */
1332 if(!BACKEND->handle)
1333 return 0; /* connection has been closed */
1336 errlen = sizeof err;
1338 if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
1339 (unsigned char *) &err, &errlen) ||
1340 errlen != sizeof err || err)
1341 return 0; /* connection has been closed */
1343 return -1; /* connection status unknown */
1346 static void *Curl_gskit_get_internals(struct ssl_connect_data *connssl,
1347 CURLINFO info UNUSED_PARAM)
1350 return BACKEND->handle;
1353 const struct Curl_ssl Curl_ssl_gskit = {
1354 { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */
1356 0, /* have_ca_path */
1357 1, /* have_certinfo */
1358 1, /* have_pinnedpubkey */
1359 0, /* have_ssl_ctx */
1360 /* TODO: convert to 1 and fix test #1014 (if need) */
1361 0, /* support_https_proxy */
1363 sizeof(struct ssl_backend_data),
1365 Curl_gskit_init, /* init */
1366 Curl_gskit_cleanup, /* cleanup */
1367 Curl_gskit_version, /* version */
1368 Curl_gskit_check_cxn, /* check_cxn */
1369 Curl_gskit_shutdown, /* shutdown */
1370 Curl_none_data_pending, /* data_pending */
1371 Curl_none_random, /* random */
1372 Curl_none_cert_status_request, /* cert_status_request */
1373 Curl_gskit_connect, /* connect */
1374 Curl_gskit_connect_nonblocking, /* connect_nonblocking */
1375 Curl_gskit_get_internals, /* get_internals */
1376 Curl_gskit_close, /* close_one */
1377 Curl_none_close_all, /* close_all */
1378 /* No session handling for GSKit */
1379 Curl_none_session_free, /* session_free */
1380 Curl_none_set_engine, /* set_engine */
1381 Curl_none_set_engine_default, /* set_engine_default */
1382 Curl_none_engines_list, /* engines_list */
1383 Curl_none_false_start, /* false_start */
1384 Curl_none_md5sum, /* md5sum */
1385 NULL /* sha256sum */
1388 #endif /* USE_GSKIT */