1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2022, 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.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 * SPDX-License-Identifier: curl
23 ***************************************************************************/
25 #include "curl_setup.h"
31 #undef HAVE_SOCKETPAIR /* because the native one isn't good enough */
32 #include "socketpair.h"
35 /* Some symbols are undefined/unsupported on OS400 versions < V7R1. */
36 #ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
37 #define GSK_SSL_EXTN_SERVERNAME_REQUEST 230
40 #ifndef GSK_TLSV10_CIPHER_SPECS
41 #define GSK_TLSV10_CIPHER_SPECS 236
44 #ifndef GSK_TLSV11_CIPHER_SPECS
45 #define GSK_TLSV11_CIPHER_SPECS 237
48 #ifndef GSK_TLSV12_CIPHER_SPECS
49 #define GSK_TLSV12_CIPHER_SPECS 238
52 #ifndef GSK_PROTOCOL_TLSV11
53 #define GSK_PROTOCOL_TLSV11 437
56 #ifndef GSK_PROTOCOL_TLSV12
57 #define GSK_PROTOCOL_TLSV12 438
71 #include <curl/curl.h>
76 #include "connect.h" /* for the connect timeout */
81 #include "curl_printf.h"
83 #include "curl_memory.h"
84 /* The last #include file should be: */
90 #define SOS_WRITE 0x02
92 /* SSL version flags. */
93 #define CURL_GSKPROTO_SSLV2 0
94 #define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
95 #define CURL_GSKPROTO_SSLV3 1
96 #define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3)
97 #define CURL_GSKPROTO_TLSV10 2
98 #define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10)
99 #define CURL_GSKPROTO_TLSV11 3
100 #define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11)
101 #define CURL_GSKPROTO_TLSV12 4
102 #define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
103 #define CURL_GSKPROTO_LAST 5
105 struct ssl_backend_data {
108 #ifndef CURL_DISABLE_PROXY
114 #define BACKEND connssl->backend
116 /* Supported ciphers. */
117 struct gskit_cipher {
118 const char *name; /* Cipher name. */
119 const char *gsktoken; /* Corresponding token for GSKit String. */
120 unsigned int versions; /* SSL version flags. */
123 static const struct gskit_cipher ciphertable[] = {
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-rc4-md5", "03",
131 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
133 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
134 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
136 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
137 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
138 { "exp-rc2-cbc-md5", "06",
139 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
140 { "exp-des-cbc-sha", "09",
141 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
142 CURL_GSKPROTO_TLSV11_MASK },
143 { "des-cbc3-sha", "0A",
144 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
145 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
146 { "aes128-sha", "2F",
147 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
148 CURL_GSKPROTO_TLSV12_MASK },
149 { "aes256-sha", "35",
150 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
151 CURL_GSKPROTO_TLSV12_MASK },
152 { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK },
153 { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK },
154 { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK },
155 { "aes128-gcm-sha256",
156 "9C", CURL_GSKPROTO_TLSV12_MASK },
157 { "aes256-gcm-sha384",
158 "9D", CURL_GSKPROTO_TLSV12_MASK },
159 { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK },
160 { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK },
161 { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK },
162 { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK },
163 { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK },
164 { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK },
165 { (const char *) NULL, (const char *) NULL, 0 }
169 static bool is_separator(char c)
171 /* Return whether character is a cipher list separator. */
184 static CURLcode gskit_status(struct Curl_easy *data, int rc,
185 const char *procname, CURLcode defcode)
187 char buffer[STRERROR_LEN];
188 /* Process GSKit status and map it to a CURLcode. */
191 case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
193 case GSK_KEYRING_OPEN_ERROR:
194 case GSK_OS400_ERROR_NO_ACCESS:
195 return CURLE_SSL_CACERT_BADFILE;
196 case GSK_INSUFFICIENT_STORAGE:
197 return CURLE_OUT_OF_MEMORY;
198 case GSK_ERROR_BAD_V2_CIPHER:
199 case GSK_ERROR_BAD_V3_CIPHER:
200 case GSK_ERROR_NO_CIPHERS:
201 return CURLE_SSL_CIPHER;
202 case GSK_OS400_ERROR_NOT_TRUSTED_ROOT:
203 case GSK_ERROR_CERT_VALIDATION:
204 return CURLE_PEER_FAILED_VERIFICATION;
205 case GSK_OS400_ERROR_TIMED_OUT:
206 return CURLE_OPERATION_TIMEDOUT;
207 case GSK_WOULD_BLOCK:
209 case GSK_OS400_ERROR_NOT_REGISTERED:
214 return CURLE_OUT_OF_MEMORY;
216 failf(data, "%s I/O error: %s", procname,
217 Curl_strerror(errno, buffer, sizeof(buffer)));
222 failf(data, "%s: %s", procname, gsk_strerror(rc));
229 static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
230 GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
232 char buffer[STRERROR_LEN];
233 int rc = gsk_attribute_set_enum(h, id, value);
239 failf(data, "gsk_attribute_set_enum() I/O error: %s",
240 Curl_strerror(errno, buffer, sizeof(buffer)));
242 case GSK_ATTRIBUTE_INVALID_ID:
244 return CURLE_UNSUPPORTED_PROTOCOL;
246 failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
249 return CURLE_SSL_CONNECT_ERROR;
253 static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
254 GSK_BUF_ID id, const char *buf, bool unsupported_ok)
256 char buffer[STRERROR_LEN];
257 int rc = gsk_attribute_set_buffer(h, id, buf, 0);
263 failf(data, "gsk_attribute_set_buffer() I/O error: %s",
264 Curl_strerror(errno, buffer, sizeof(buffer)));
266 case GSK_ATTRIBUTE_INVALID_ID:
268 return CURLE_UNSUPPORTED_PROTOCOL;
270 failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
273 return CURLE_SSL_CONNECT_ERROR;
277 static CURLcode set_numeric(struct Curl_easy *data,
278 gsk_handle h, GSK_NUM_ID id, int value)
280 char buffer[STRERROR_LEN];
281 int rc = gsk_attribute_set_numeric_value(h, id, value);
287 failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
288 Curl_strerror(errno, buffer, sizeof(buffer)));
291 failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
294 return CURLE_SSL_CONNECT_ERROR;
298 static CURLcode set_ciphers(struct Curl_easy *data,
299 gsk_handle h, unsigned int *protoflags)
301 struct connectdata *conn = data->conn;
302 const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
304 const struct gskit_cipher *ctp;
312 } ciphers[CURL_GSKPROTO_LAST];
314 /* Compile cipher list into GSKit-compatible cipher lists. */
318 while(is_separator(*cipherlist)) /* Skip initial separators. */
323 /* We allocate GSKit buffers of the same size as the input string: since
324 GSKit tokens are always shorter than their cipher names, allocated buffers
325 will always be large enough to accommodate the result. */
326 l = strlen(cipherlist) + 1;
327 memset((char *) ciphers, 0, sizeof(ciphers));
328 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
329 ciphers[i].buf = malloc(l);
330 if(!ciphers[i].buf) {
332 free(ciphers[i].buf);
333 return CURLE_OUT_OF_MEMORY;
335 ciphers[i].ptr = ciphers[i].buf;
336 *ciphers[i].ptr = '\0';
339 /* Process each cipher in input string. */
343 for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
345 l = cipherlist - clp;
348 /* Search the cipher in our table. */
349 for(ctp = ciphertable; ctp->name; ctp++)
350 if(strncasecompare(ctp->name, clp, l) && !ctp->name[l])
353 failf(data, "Unknown cipher %.*s", l, clp);
354 result = CURLE_SSL_CIPHER;
357 unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK |
358 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK));
359 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
360 if(ctp->versions & (1 << i)) {
361 strcpy(ciphers[i].ptr, ctp->gsktoken);
362 ciphers[i].ptr += strlen(ctp->gsktoken);
367 /* Advance to next cipher name or end of string. */
368 while(is_separator(*cipherlist))
372 /* Disable protocols with empty cipher lists. */
373 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
374 if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) {
375 *protoflags &= ~(1 << i);
376 ciphers[i].buf[0] = '\0';
380 /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */
381 if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) {
382 result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS,
383 ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE);
384 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
387 failf(data, "TLSv1.1-only ciphers are not yet supported");
388 result = CURLE_SSL_CIPHER;
392 if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) {
393 result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS,
394 ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE);
395 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
398 failf(data, "TLSv1.2-only ciphers are not yet supported");
399 result = CURLE_SSL_CIPHER;
404 /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to
405 the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */
406 if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) {
407 result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS,
408 ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE);
409 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
411 strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr,
412 ciphers[CURL_GSKPROTO_TLSV10].ptr);
416 /* Set-up other ciphers. */
417 if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK))
418 result = set_buffer(data, h, GSK_V3_CIPHER_SPECS,
419 ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE);
420 if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK))
421 result = set_buffer(data, h, GSK_V2_CIPHER_SPECS,
422 ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE);
425 for(i = 0; i < CURL_GSKPROTO_LAST; i++)
426 free(ciphers[i].buf);
432 static int gskit_init(void)
434 /* No initialization needed. */
439 static void gskit_cleanup(void)
445 static CURLcode init_environment(struct Curl_easy *data,
446 gsk_handle *envir, const char *appid,
447 const char *file, const char *label,
448 const char *password)
454 /* Creates the GSKit environment. */
456 rc = gsk_environment_open(&h);
460 case GSK_INSUFFICIENT_STORAGE:
461 return CURLE_OUT_OF_MEMORY;
463 failf(data, "gsk_environment_open(): %s", gsk_strerror(rc));
464 return CURLE_SSL_CONNECT_ERROR;
467 result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
469 result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
471 result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
473 result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE);
474 if(!result && password)
475 result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);
478 /* Locate CAs, Client certificate and key according to our settings.
479 Note: this call may be blocking for some tenths of seconds. */
480 result = gskit_status(data, gsk_environment_init(h),
481 "gsk_environment_init()", CURLE_SSL_CERTPROBLEM);
487 /* Error: rollback. */
488 gsk_environment_close(&h);
493 static void cancel_async_handshake(struct connectdata *conn, int sockindex)
495 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
496 Qso_OverlappedIO_t cstat;
498 DEBUGASSERT(BACKEND);
500 if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
501 QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL);
505 static void close_async_handshake(struct ssl_connect_data *connssl)
507 DEBUGASSERT(BACKEND);
508 QsoDestroyIOCompletionPort(BACKEND->iocport);
509 BACKEND->iocport = -1;
512 static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
515 #ifndef CURL_DISABLE_PROXY
516 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
517 struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex];
518 struct pollfd fds[2];
523 char buf[CURL_MAX_WRITE_SIZE];
525 DEBUGASSERT(BACKEND);
526 DEBUGASSERT(connproxyssl->backend);
528 if(!connssl->use || !connproxyssl->use)
529 return 0; /* No SSL over SSL: OK. */
532 fds[0].fd = BACKEND->remotefd;
533 fds[1].fd = conn->sock[sockindex];
535 if(directions & SOS_READ) {
536 fds[0].events |= POLLOUT;
538 if(directions & SOS_WRITE) {
540 fds[0].events |= POLLIN;
541 fds[1].events |= POLLOUT;
543 i = Curl_poll(fds, n, 0);
545 return -1; /* Select error. */
547 if(fds[0].revents & POLLOUT) {
548 /* Try getting data from HTTPS proxy and pipe it upstream. */
550 i = gsk_secure_soc_read(connproxyssl->backend->handle,
551 buf, sizeof(buf), &n);
555 i = write(BACKEND->remotefd, buf, n);
561 case GSK_OS400_ERROR_TIMED_OUT:
562 case GSK_WOULD_BLOCK:
569 if((fds[0].revents & POLLIN) && (fds[1].revents & POLLOUT)) {
570 /* Pipe data to HTTPS proxy. */
571 n = read(BACKEND->remotefd, buf, sizeof(buf));
575 i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m);
576 if(i != GSK_OK || n != m)
589 static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data,
590 struct connectdata *conn, int sockindex)
592 DEBUGASSERT(BACKEND);
593 if(BACKEND->handle) {
594 gskit_status(data, gsk_secure_soc_close(&BACKEND->handle),
595 "gsk_secure_soc_close()", 0);
596 /* Last chance to drain output. */
597 while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
599 BACKEND->handle = (gsk_handle) NULL;
600 #ifndef CURL_DISABLE_PROXY
601 if(BACKEND->localfd >= 0) {
602 close(BACKEND->localfd);
603 BACKEND->localfd = -1;
605 if(BACKEND->remotefd >= 0) {
606 close(BACKEND->remotefd);
607 BACKEND->remotefd = -1;
611 if(BACKEND->iocport >= 0)
612 close_async_handshake(connssl);
616 static ssize_t gskit_send(struct Curl_easy *data, int sockindex,
617 const void *mem, size_t len, CURLcode *curlcode)
619 struct connectdata *conn = data->conn;
620 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
621 CURLcode cc = CURLE_SEND_ERROR;
624 DEBUGASSERT(BACKEND);
626 if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
627 cc = gskit_status(data,
628 gsk_secure_soc_write(BACKEND->handle,
629 (char *) mem, (int) len, &written),
630 "gsk_secure_soc_write()", CURLE_SEND_ERROR);
632 if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
633 cc = CURLE_SEND_ERROR;
639 return (ssize_t) written; /* number of bytes */
643 static ssize_t gskit_recv(struct Curl_easy *data, int num, char *buf,
644 size_t buffersize, CURLcode *curlcode)
646 struct connectdata *conn = data->conn;
647 struct ssl_connect_data *connssl = &conn->ssl[num];
649 CURLcode cc = CURLE_RECV_ERROR;
651 DEBUGASSERT(BACKEND);
653 if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
654 int buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
655 cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
656 buf, buffsize, &nread),
657 "gsk_secure_soc_read()", CURLE_RECV_ERROR);
662 case CURLE_OPERATION_TIMEDOUT:
669 return (ssize_t) nread;
673 set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data)
675 struct connectdata *conn = data->conn;
676 long ssl_version = SSL_CONN_CONFIG(version);
677 long ssl_version_max = SSL_CONN_CONFIG(version_max);
678 long i = ssl_version;
679 switch(ssl_version_max) {
680 case CURL_SSLVERSION_MAX_NONE:
681 case CURL_SSLVERSION_MAX_DEFAULT:
682 ssl_version_max = CURL_SSLVERSION_TLSv1_2;
685 for(; i <= (ssl_version_max >> 16); ++i) {
687 case CURL_SSLVERSION_TLSv1_0:
688 *protoflags |= CURL_GSKPROTO_TLSV10_MASK;
690 case CURL_SSLVERSION_TLSv1_1:
691 *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
693 case CURL_SSLVERSION_TLSv1_2:
694 *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
696 case CURL_SSLVERSION_TLSv1_3:
697 failf(data, "GSKit: TLS 1.3 is not yet supported");
698 return CURLE_SSL_CONNECT_ERROR;
705 static CURLcode gskit_connect_step1(struct Curl_easy *data,
706 struct connectdata *conn, int sockindex)
708 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
711 const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
712 const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
713 const char * const keyringlabel = SSL_SET_OPTION(primary.clientcert);
714 const long int ssl_version = SSL_CONN_CONFIG(version);
715 const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
716 const char * const hostname = SSL_HOST_NAME();
718 unsigned int protoflags = 0;
719 Qso_OverlappedIO_t commarea;
720 #ifndef CURL_DISABLE_PROXY
722 static const int sobufsize = CURL_MAX_WRITE_SIZE;
725 /* Create SSL environment, start (preferably asynchronous) handshake. */
726 DEBUGASSERT(BACKEND);
728 BACKEND->handle = (gsk_handle) NULL;
729 BACKEND->iocport = -1;
730 #ifndef CURL_DISABLE_PROXY
731 BACKEND->localfd = -1;
732 BACKEND->remotefd = -1;
735 /* GSKit supports two ways of specifying an SSL context: either by
736 * application identifier (that should have been defined at the system
737 * level) or by keyring file, password and certificate label.
738 * Local certificate name (CURLOPT_SSLCERT) is used to hold either the
739 * application identifier of the certificate label.
740 * Key password (CURLOPT_KEYPASSWD) holds the keyring password.
741 * It is not possible to have different keyrings for the CAs and the
742 * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify
744 * If no key password is given and the keyring is the system keyring,
745 * application identifier mode is tried first, as recommended in IBM doc.
748 envir = (gsk_handle) NULL;
750 if(keyringlabel && *keyringlabel && !keyringpwd &&
751 !strcmp(keyringfile, CURL_CA_BUNDLE)) {
752 /* Try application identifier mode. */
753 init_environment(data, &envir, keyringlabel, (const char *) NULL,
754 (const char *) NULL, (const char *) NULL);
758 /* Use keyring mode. */
759 result = init_environment(data, &envir, (const char *) NULL,
760 keyringfile, keyringlabel, keyringpwd);
765 /* Create secure session. */
766 result = gskit_status(data, gsk_secure_soc_open(envir, &BACKEND->handle),
767 "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
768 gsk_environment_close(&envir);
772 #ifndef CURL_DISABLE_PROXY
773 /* Establish a pipelining socket pair for SSL over SSL. */
774 if(conn->proxy_ssl[sockindex].use) {
775 if(Curl_socketpair(0, 0, 0, sockpair))
776 return CURLE_SSL_CONNECT_ERROR;
777 BACKEND->localfd = sockpair[0];
778 BACKEND->remotefd = sockpair[1];
779 setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
780 (void *) &sobufsize, sizeof(sobufsize));
781 setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
782 (void *) &sobufsize, sizeof(sobufsize));
783 setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
784 (void *) &sobufsize, sizeof(sobufsize));
785 setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
786 (void *) &sobufsize, sizeof(sobufsize));
787 curlx_nonblock(BACKEND->localfd, TRUE);
788 curlx_nonblock(BACKEND->remotefd, TRUE);
792 /* Determine which SSL/TLS version should be enabled. */
794 switch(ssl_version) {
795 case CURL_SSLVERSION_SSLv2:
796 protoflags = CURL_GSKPROTO_SSLV2_MASK;
799 case CURL_SSLVERSION_SSLv3:
800 protoflags = CURL_GSKPROTO_SSLV3_MASK;
803 case CURL_SSLVERSION_DEFAULT:
804 case CURL_SSLVERSION_TLSv1:
805 protoflags = CURL_GSKPROTO_TLSV10_MASK |
806 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
808 case CURL_SSLVERSION_TLSv1_0:
809 case CURL_SSLVERSION_TLSv1_1:
810 case CURL_SSLVERSION_TLSv1_2:
811 case CURL_SSLVERSION_TLSv1_3:
812 result = set_ssl_version_min_max(&protoflags, data);
813 if(result != CURLE_OK)
817 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
818 return CURLE_SSL_CONNECT_ERROR;
821 /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
823 char *snihost = Curl_ssl_snihost(data, sni, NULL);
825 failf(data, "Failed to set SNI");
826 return CURLE_SSL_CONNECT_ERROR;
828 result = set_buffer(data, BACKEND->handle,
829 GSK_SSL_EXTN_SERVERNAME_REQUEST, snihost, TRUE);
830 if(result == CURLE_UNSUPPORTED_PROTOCOL)
834 /* Set session parameters. */
836 /* Compute the handshake timeout. Since GSKit granularity is 1 second,
837 we round up the required value. */
838 timediff_t timeout = Curl_timeleft(data, NULL, TRUE);
840 result = CURLE_OPERATION_TIMEDOUT;
842 result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT,
843 (timeout + 999) / 1000);
846 result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
848 #ifndef CURL_DISABLE_PROXY
849 result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
850 BACKEND->localfd: conn->sock[sockindex]);
852 result = set_numeric(data, BACKEND->handle, GSK_FD,
853 conn->sock[sockindex]);
856 result = set_ciphers(data, BACKEND->handle, &protoflags);
858 failf(data, "No SSL protocol/cipher combination enabled");
859 result = CURLE_SSL_CIPHER;
862 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2,
863 (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
864 GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
866 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV3,
867 (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
868 GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
870 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV1,
871 (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
872 GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
874 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV11,
875 (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
876 GSK_TRUE: GSK_FALSE, TRUE);
877 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
879 if(protoflags == CURL_GSKPROTO_TLSV11_MASK) {
880 failf(data, "TLS 1.1 not yet supported");
881 result = CURLE_SSL_CIPHER;
886 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV12,
887 (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
888 GSK_TRUE: GSK_FALSE, TRUE);
889 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
891 if(protoflags == CURL_GSKPROTO_TLSV12_MASK) {
892 failf(data, "TLS 1.2 not yet supported");
893 result = CURLE_SSL_CIPHER;
898 result = set_enum(data, BACKEND->handle, GSK_SERVER_AUTH_TYPE,
899 verifypeer? GSK_SERVER_AUTH_FULL:
900 GSK_SERVER_AUTH_PASSTHRU, FALSE);
903 /* Start handshake. Try asynchronous first. */
904 memset(&commarea, 0, sizeof(commarea));
905 BACKEND->iocport = QsoCreateIOCompletionPort();
906 if(BACKEND->iocport != -1) {
907 result = gskit_status(data,
908 gsk_secure_soc_startInit(BACKEND->handle,
911 "gsk_secure_soc_startInit()",
912 CURLE_SSL_CONNECT_ERROR);
914 connssl->connecting_state = ssl_connect_2;
918 close_async_handshake(connssl);
920 else if(errno != ENOBUFS)
921 result = gskit_status(data, GSK_ERROR_IO,
922 "QsoCreateIOCompletionPort()", 0);
923 #ifndef CURL_DISABLE_PROXY
924 else if(conn->proxy_ssl[sockindex].use) {
925 /* Cannot pipeline while handshaking synchronously. */
926 result = CURLE_SSL_CONNECT_ERROR;
930 /* No more completion port available. Use synchronous IO. */
931 result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle),
932 "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
934 connssl->connecting_state = ssl_connect_3;
940 /* Error: rollback. */
941 close_one(connssl, data, conn, sockindex);
946 static CURLcode gskit_connect_step2(struct Curl_easy *data,
947 struct connectdata *conn, int sockindex,
950 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
951 Qso_OverlappedIO_t cstat;
955 /* Poll or wait for end of SSL asynchronous handshake. */
956 DEBUGASSERT(BACKEND);
959 timediff_t timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
964 switch(QsoWaitForIOCompletion(BACKEND->iocport, &cstat,
965 curlx_mstotv(&stmv, timeout_ms))) {
966 case 1: /* Operation complete. */
968 case -1: /* An error occurred: handshake still in progress. */
972 continue; /* Retry. */
975 char buffer[STRERROR_LEN];
976 failf(data, "QsoWaitForIOCompletion() I/O error: %s",
977 Curl_strerror(errno, buffer, sizeof(buffer)));
978 cancel_async_handshake(conn, sockindex);
979 close_async_handshake(connssl);
980 return CURLE_SSL_CONNECT_ERROR;
983 case 0: /* Handshake in progress, timeout occurred. */
986 cancel_async_handshake(conn, sockindex);
987 close_async_handshake(connssl);
988 return CURLE_OPERATION_TIMEDOUT;
992 result = gskit_status(data, cstat.returnValue, "SSL handshake",
993 CURLE_SSL_CONNECT_ERROR);
995 connssl->connecting_state = ssl_connect_3;
996 close_async_handshake(connssl);
1001 static CURLcode gskit_connect_step3(struct Curl_easy *data,
1002 struct connectdata *conn, int sockindex)
1004 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1005 const gsk_cert_data_elem *cdev;
1007 const gsk_cert_data_elem *p;
1008 const char *cert = (const char *) NULL;
1009 const char *certend;
1013 /* SSL handshake done: gather certificate info and verify host. */
1014 DEBUGASSERT(BACKEND);
1016 if(gskit_status(data, gsk_attribute_get_cert_info(BACKEND->handle,
1017 GSK_PARTNER_CERT_INFO,
1019 "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
1023 infof(data, "Server certificate:");
1025 for(i = 0; i++ < cdec; p++)
1026 switch(p->cert_data_id) {
1028 cert = p->cert_data_p;
1029 certend = cert + cdev->cert_data_l;
1031 case CERT_DN_PRINTABLE:
1032 infof(data, "\t subject: %.*s", p->cert_data_l, p->cert_data_p);
1034 case CERT_ISSUER_DN_PRINTABLE:
1035 infof(data, "\t issuer: %.*s", p->cert_data_l, p->cert_data_p);
1037 case CERT_VALID_FROM:
1038 infof(data, "\t start date: %.*s", p->cert_data_l, p->cert_data_p);
1041 infof(data, "\t expire date: %.*s", p->cert_data_l, p->cert_data_p);
1047 result = Curl_verifyhost(data, conn, cert, certend);
1051 /* The only place GSKit can get the whole CA chain is a validation
1052 callback where no user data pointer is available. Therefore it's not
1053 possible to copy this chain into our structures for CAINFO.
1054 However the server certificate may be available, thus we can return
1056 if(data->set.ssl.certinfo) {
1057 result = Curl_ssl_init_certinfo(data, 1);
1062 result = Curl_extract_certinfo(data, 0, cert, certend);
1068 /* Check pinned public key. */
1069 ptr = SSL_PINNED_PUB_KEY();
1070 if(!result && ptr) {
1071 struct Curl_X509certificate x509;
1072 struct Curl_asn1Element *p;
1074 memset(&x509, 0, sizeof(x509));
1075 if(Curl_parseX509(&x509, cert, certend))
1076 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1077 p = &x509.subjectPublicKeyInfo;
1078 result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header);
1080 failf(data, "SSL: public key does not match pinned public key");
1085 connssl->connecting_state = ssl_connect_done;
1090 static CURLcode gskit_connect_common(struct Curl_easy *data,
1091 struct connectdata *conn, int sockindex,
1092 bool nonblocking, bool *done)
1094 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1095 timediff_t timeout_ms;
1096 CURLcode result = CURLE_OK;
1098 *done = connssl->state == ssl_connection_complete;
1102 /* Step 1: create session, start handshake. */
1103 if(connssl->connecting_state == ssl_connect_1) {
1104 /* check allowed time left */
1105 timeout_ms = Curl_timeleft(data, NULL, TRUE);
1107 if(timeout_ms < 0) {
1108 /* no need to continue if time already is up */
1109 failf(data, "SSL connection timeout");
1110 result = CURLE_OPERATION_TIMEDOUT;
1113 result = gskit_connect_step1(data, conn, sockindex);
1116 /* Handle handshake pipelining. */
1118 if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
1119 result = CURLE_SSL_CONNECT_ERROR;
1121 /* Step 2: check if handshake is over. */
1122 if(!result && connssl->connecting_state == ssl_connect_2) {
1123 /* check allowed time left */
1124 timeout_ms = Curl_timeleft(data, NULL, TRUE);
1126 if(timeout_ms < 0) {
1127 /* no need to continue if time already is up */
1128 failf(data, "SSL connection timeout");
1129 result = CURLE_OPERATION_TIMEDOUT;
1132 result = gskit_connect_step2(data, conn, sockindex, nonblocking);
1135 /* Handle handshake pipelining. */
1137 if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
1138 result = CURLE_SSL_CONNECT_ERROR;
1140 /* Step 3: gather certificate info, verify host. */
1141 if(!result && connssl->connecting_state == ssl_connect_3)
1142 result = gskit_connect_step3(data, conn, sockindex);
1145 close_one(connssl, data, conn, sockindex);
1146 else if(connssl->connecting_state == ssl_connect_done) {
1147 connssl->state = ssl_connection_complete;
1148 connssl->connecting_state = ssl_connect_1;
1149 conn->recv[sockindex] = gskit_recv;
1150 conn->send[sockindex] = gskit_send;
1158 static CURLcode gskit_connect_nonblocking(struct Curl_easy *data,
1159 struct connectdata *conn,
1160 int sockindex, bool *done)
1164 result = gskit_connect_common(data, conn, sockindex, TRUE, done);
1166 conn->ssl[sockindex].connecting_state = ssl_connect_1;
1171 static CURLcode gskit_connect(struct Curl_easy *data,
1172 struct connectdata *conn, int sockindex)
1177 conn->ssl[sockindex].connecting_state = ssl_connect_1;
1178 result = gskit_connect_common(data, conn, sockindex, FALSE, &done);
1188 static void gskit_close(struct Curl_easy *data, struct connectdata *conn,
1191 close_one(&conn->ssl[sockindex], data, conn, sockindex);
1192 #ifndef CURL_DISABLE_PROXY
1193 close_one(&conn->proxy_ssl[sockindex], data, conn, sockindex);
1198 static int gskit_shutdown(struct Curl_easy *data,
1199 struct connectdata *conn, int sockindex)
1201 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1205 int loop = 10; /* don't get stuck */
1207 DEBUGASSERT(BACKEND);
1209 if(!BACKEND->handle)
1212 #ifndef CURL_DISABLE_FTP
1213 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
1217 close_one(connssl, data, conn, sockindex);
1219 what = SOCKET_READABLE(conn->sock[sockindex],
1220 SSL_SHUTDOWN_TIMEOUT);
1226 /* anything that gets here is fatally bad */
1227 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1232 if(!what) { /* timeout */
1233 failf(data, "SSL shutdown timeout");
1237 /* Something to read, let's do it and hope that it is the close
1238 notify alert from the server. No way to gsk_secure_soc_read() now, so
1241 nread = read(conn->sock[sockindex], buf, sizeof(buf));
1244 char buffer[STRERROR_LEN];
1245 failf(data, "read: %s", Curl_strerror(errno, buffer, sizeof(buffer)));
1252 what = SOCKET_READABLE(conn->sock[sockindex], 0);
1259 static size_t gskit_version(char *buffer, size_t size)
1261 return msnprintf(buffer, size, "GSKit");
1265 static int gskit_check_cxn(struct connectdata *cxn)
1267 struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
1271 /* The only thing that can be tested here is at the socket level. */
1272 DEBUGASSERT(BACKEND);
1274 if(!BACKEND->handle)
1275 return 0; /* connection has been closed */
1278 errlen = sizeof(err);
1280 if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
1281 (unsigned char *) &err, &errlen) ||
1282 errlen != sizeof(err) || err)
1283 return 0; /* connection has been closed */
1285 return -1; /* connection status unknown */
1288 static void *gskit_get_internals(struct ssl_connect_data *connssl,
1289 CURLINFO info UNUSED_PARAM)
1292 DEBUGASSERT(BACKEND);
1293 return BACKEND->handle;
1296 const struct Curl_ssl Curl_ssl_gskit = {
1297 { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */
1300 SSLSUPP_PINNEDPUBKEY,
1302 sizeof(struct ssl_backend_data),
1304 gskit_init, /* init */
1305 gskit_cleanup, /* cleanup */
1306 gskit_version, /* version */
1307 gskit_check_cxn, /* check_cxn */
1308 gskit_shutdown, /* shutdown */
1309 Curl_none_data_pending, /* data_pending */
1310 Curl_none_random, /* random */
1311 Curl_none_cert_status_request, /* cert_status_request */
1312 gskit_connect, /* connect */
1313 gskit_connect_nonblocking, /* connect_nonblocking */
1314 Curl_ssl_getsock, /* getsock */
1315 gskit_get_internals, /* get_internals */
1316 gskit_close, /* close_one */
1317 Curl_none_close_all, /* close_all */
1318 /* No session handling for GSKit */
1319 Curl_none_session_free, /* session_free */
1320 Curl_none_set_engine, /* set_engine */
1321 Curl_none_set_engine_default, /* set_engine_default */
1322 Curl_none_engines_list, /* engines_list */
1323 Curl_none_false_start, /* false_start */
1324 NULL, /* sha256sum */
1325 NULL, /* associate_connection */
1326 NULL /* disassociate_connection */
1329 #endif /* USE_GSKIT */