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 ***************************************************************************/
23 #include "curl_setup.h"
29 #undef HAVE_SOCKETPAIR /* because the native one isn't good enough */
30 #include "socketpair.h"
33 /* Some symbols are undefined/unsupported on OS400 versions < V7R1. */
34 #ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
35 #define GSK_SSL_EXTN_SERVERNAME_REQUEST 230
38 #ifndef GSK_TLSV10_CIPHER_SPECS
39 #define GSK_TLSV10_CIPHER_SPECS 236
42 #ifndef GSK_TLSV11_CIPHER_SPECS
43 #define GSK_TLSV11_CIPHER_SPECS 237
46 #ifndef GSK_TLSV12_CIPHER_SPECS
47 #define GSK_TLSV12_CIPHER_SPECS 238
50 #ifndef GSK_PROTOCOL_TLSV11
51 #define GSK_PROTOCOL_TLSV11 437
54 #ifndef GSK_PROTOCOL_TLSV12
55 #define GSK_PROTOCOL_TLSV12 438
69 #include <curl/curl.h>
74 #include "connect.h" /* for the connect timeout */
79 #include "curl_printf.h"
81 #include "curl_memory.h"
82 /* The last #include file should be: */
88 #define SOS_WRITE 0x02
90 /* SSL version flags. */
91 #define CURL_GSKPROTO_SSLV2 0
92 #define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
93 #define CURL_GSKPROTO_SSLV3 1
94 #define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3)
95 #define CURL_GSKPROTO_TLSV10 2
96 #define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10)
97 #define CURL_GSKPROTO_TLSV11 3
98 #define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11)
99 #define CURL_GSKPROTO_TLSV12 4
100 #define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
101 #define CURL_GSKPROTO_LAST 5
103 struct ssl_backend_data {
106 #ifndef CURL_DISABLE_PROXY
112 #define BACKEND connssl->backend
114 /* Supported ciphers. */
115 struct gskit_cipher {
116 const char *name; /* Cipher name. */
117 const char *gsktoken; /* Corresponding token for GSKit String. */
118 unsigned int versions; /* SSL version flags. */
121 static const struct gskit_cipher ciphertable[] = {
123 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
124 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
126 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
127 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
128 { "exp-rc4-md5", "03",
129 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
131 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
132 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
134 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
135 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
136 { "exp-rc2-cbc-md5", "06",
137 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
138 { "exp-des-cbc-sha", "09",
139 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
140 CURL_GSKPROTO_TLSV11_MASK },
141 { "des-cbc3-sha", "0A",
142 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
143 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
144 { "aes128-sha", "2F",
145 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
146 CURL_GSKPROTO_TLSV12_MASK },
147 { "aes256-sha", "35",
148 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
149 CURL_GSKPROTO_TLSV12_MASK },
150 { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK },
151 { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK },
152 { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK },
153 { "aes128-gcm-sha256",
154 "9C", CURL_GSKPROTO_TLSV12_MASK },
155 { "aes256-gcm-sha384",
156 "9D", CURL_GSKPROTO_TLSV12_MASK },
157 { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK },
158 { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK },
159 { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK },
160 { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK },
161 { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK },
162 { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK },
163 { (const char *) NULL, (const char *) NULL, 0 }
167 static bool is_separator(char c)
169 /* Return whether character is a cipher list separator. */
182 static CURLcode gskit_status(struct Curl_easy *data, int rc,
183 const char *procname, CURLcode defcode)
185 char buffer[STRERROR_LEN];
186 /* Process GSKit status and map it to a CURLcode. */
189 case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
191 case GSK_KEYRING_OPEN_ERROR:
192 case GSK_OS400_ERROR_NO_ACCESS:
193 return CURLE_SSL_CACERT_BADFILE;
194 case GSK_INSUFFICIENT_STORAGE:
195 return CURLE_OUT_OF_MEMORY;
196 case GSK_ERROR_BAD_V2_CIPHER:
197 case GSK_ERROR_BAD_V3_CIPHER:
198 case GSK_ERROR_NO_CIPHERS:
199 return CURLE_SSL_CIPHER;
200 case GSK_OS400_ERROR_NOT_TRUSTED_ROOT:
201 case GSK_ERROR_CERT_VALIDATION:
202 return CURLE_PEER_FAILED_VERIFICATION;
203 case GSK_OS400_ERROR_TIMED_OUT:
204 return CURLE_OPERATION_TIMEDOUT;
205 case GSK_WOULD_BLOCK:
207 case GSK_OS400_ERROR_NOT_REGISTERED:
212 return CURLE_OUT_OF_MEMORY;
214 failf(data, "%s I/O error: %s", procname,
215 Curl_strerror(errno, buffer, sizeof(buffer)));
220 failf(data, "%s: %s", procname, gsk_strerror(rc));
227 static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
228 GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
230 char buffer[STRERROR_LEN];
231 int rc = gsk_attribute_set_enum(h, id, value);
237 failf(data, "gsk_attribute_set_enum() I/O error: %s",
238 Curl_strerror(errno, buffer, sizeof(buffer)));
240 case GSK_ATTRIBUTE_INVALID_ID:
242 return CURLE_UNSUPPORTED_PROTOCOL;
244 failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
247 return CURLE_SSL_CONNECT_ERROR;
251 static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
252 GSK_BUF_ID id, const char *buf, bool unsupported_ok)
254 char buffer[STRERROR_LEN];
255 int rc = gsk_attribute_set_buffer(h, id, buf, 0);
261 failf(data, "gsk_attribute_set_buffer() I/O error: %s",
262 Curl_strerror(errno, buffer, sizeof(buffer)));
264 case GSK_ATTRIBUTE_INVALID_ID:
266 return CURLE_UNSUPPORTED_PROTOCOL;
268 failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
271 return CURLE_SSL_CONNECT_ERROR;
275 static CURLcode set_numeric(struct Curl_easy *data,
276 gsk_handle h, GSK_NUM_ID id, int value)
278 char buffer[STRERROR_LEN];
279 int rc = gsk_attribute_set_numeric_value(h, id, value);
285 failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
286 Curl_strerror(errno, buffer, sizeof(buffer)));
289 failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
292 return CURLE_SSL_CONNECT_ERROR;
296 static CURLcode set_ciphers(struct Curl_easy *data,
297 gsk_handle h, unsigned int *protoflags)
299 struct connectdata *conn = data->conn;
300 const char *cipherlist = SSL_CONN_CONFIG(cipher_list);
302 const struct 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 accommodate 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 static int gskit_init(void)
432 /* No initialization needed. */
437 static void gskit_cleanup(void)
443 static CURLcode init_environment(struct Curl_easy *data,
444 gsk_handle *envir, const char *appid,
445 const char *file, const char *label,
446 const char *password)
452 /* Creates the GSKit environment. */
454 rc = gsk_environment_open(&h);
458 case GSK_INSUFFICIENT_STORAGE:
459 return CURLE_OUT_OF_MEMORY;
461 failf(data, "gsk_environment_open(): %s", gsk_strerror(rc));
462 return CURLE_SSL_CONNECT_ERROR;
465 result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
467 result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
469 result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
471 result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE);
472 if(!result && password)
473 result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);
476 /* Locate CAs, Client certificate and key according to our settings.
477 Note: this call may be blocking for some tenths of seconds. */
478 result = gskit_status(data, gsk_environment_init(h),
479 "gsk_environment_init()", CURLE_SSL_CERTPROBLEM);
485 /* Error: rollback. */
486 gsk_environment_close(&h);
491 static void cancel_async_handshake(struct connectdata *conn, int sockindex)
493 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
494 Qso_OverlappedIO_t cstat;
496 DEBUGASSERT(BACKEND);
498 if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
499 QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL);
503 static void close_async_handshake(struct ssl_connect_data *connssl)
505 DEBUGASSERT(BACKEND);
506 QsoDestroyIOCompletionPort(BACKEND->iocport);
507 BACKEND->iocport = -1;
510 static int pipe_ssloverssl(struct connectdata *conn, int sockindex,
513 #ifndef CURL_DISABLE_PROXY
514 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
515 struct ssl_connect_data *connproxyssl = &conn->proxy_ssl[sockindex];
516 struct pollfd fds[2];
521 char buf[CURL_MAX_WRITE_SIZE];
523 DEBUGASSERT(BACKEND);
524 DEBUGASSERT(connproxyssl->backend);
526 if(!connssl->use || !connproxyssl->use)
527 return 0; /* No SSL over SSL: OK. */
530 fds[0].fd = BACKEND->remotefd;
531 fds[1].fd = conn->sock[sockindex];
533 if(directions & SOS_READ) {
534 fds[0].events |= POLLOUT;
536 if(directions & SOS_WRITE) {
538 fds[0].events |= POLLIN;
539 fds[1].events |= POLLOUT;
541 i = Curl_poll(fds, n, 0);
543 return -1; /* Select error. */
545 if(fds[0].revents & POLLOUT) {
546 /* Try getting data from HTTPS proxy and pipe it upstream. */
548 i = gsk_secure_soc_read(connproxyssl->backend->handle,
549 buf, sizeof(buf), &n);
553 i = write(BACKEND->remotefd, buf, n);
559 case GSK_OS400_ERROR_TIMED_OUT:
560 case GSK_WOULD_BLOCK:
567 if((fds[0].revents & POLLIN) && (fds[1].revents & POLLOUT)) {
568 /* Pipe data to HTTPS proxy. */
569 n = read(BACKEND->remotefd, buf, sizeof(buf));
573 i = gsk_secure_soc_write(connproxyssl->backend->handle, buf, n, &m);
574 if(i != GSK_OK || n != m)
587 static void close_one(struct ssl_connect_data *connssl, struct Curl_easy *data,
588 struct connectdata *conn, int sockindex)
590 DEBUGASSERT(BACKEND);
591 if(BACKEND->handle) {
592 gskit_status(data, gsk_secure_soc_close(&BACKEND->handle),
593 "gsk_secure_soc_close()", 0);
594 /* Last chance to drain output. */
595 while(pipe_ssloverssl(conn, sockindex, SOS_WRITE) > 0)
597 BACKEND->handle = (gsk_handle) NULL;
598 #ifndef CURL_DISABLE_PROXY
599 if(BACKEND->localfd >= 0) {
600 close(BACKEND->localfd);
601 BACKEND->localfd = -1;
603 if(BACKEND->remotefd >= 0) {
604 close(BACKEND->remotefd);
605 BACKEND->remotefd = -1;
609 if(BACKEND->iocport >= 0)
610 close_async_handshake(connssl);
614 static ssize_t gskit_send(struct Curl_easy *data, int sockindex,
615 const void *mem, size_t len, CURLcode *curlcode)
617 struct connectdata *conn = data->conn;
618 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
619 CURLcode cc = CURLE_SEND_ERROR;
622 DEBUGASSERT(BACKEND);
624 if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) >= 0) {
625 cc = gskit_status(data,
626 gsk_secure_soc_write(BACKEND->handle,
627 (char *) mem, (int) len, &written),
628 "gsk_secure_soc_write()", CURLE_SEND_ERROR);
630 if(pipe_ssloverssl(conn, sockindex, SOS_WRITE) < 0)
631 cc = CURLE_SEND_ERROR;
637 return (ssize_t) written; /* number of bytes */
641 static ssize_t gskit_recv(struct Curl_easy *data, int num, char *buf,
642 size_t buffersize, CURLcode *curlcode)
644 struct connectdata *conn = data->conn;
645 struct ssl_connect_data *connssl = &conn->ssl[num];
647 CURLcode cc = CURLE_RECV_ERROR;
649 DEBUGASSERT(BACKEND);
651 if(pipe_ssloverssl(conn, num, SOS_READ) >= 0) {
652 int buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
653 cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
654 buf, buffsize, &nread),
655 "gsk_secure_soc_read()", CURLE_RECV_ERROR);
660 case CURLE_OPERATION_TIMEDOUT:
667 return (ssize_t) nread;
671 set_ssl_version_min_max(unsigned int *protoflags, struct Curl_easy *data)
673 struct connectdata *conn = data->conn;
674 long ssl_version = SSL_CONN_CONFIG(version);
675 long ssl_version_max = SSL_CONN_CONFIG(version_max);
676 long i = ssl_version;
677 switch(ssl_version_max) {
678 case CURL_SSLVERSION_MAX_NONE:
679 case CURL_SSLVERSION_MAX_DEFAULT:
680 ssl_version_max = CURL_SSLVERSION_TLSv1_2;
683 for(; i <= (ssl_version_max >> 16); ++i) {
685 case CURL_SSLVERSION_TLSv1_0:
686 *protoflags |= CURL_GSKPROTO_TLSV10_MASK;
688 case CURL_SSLVERSION_TLSv1_1:
689 *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
691 case CURL_SSLVERSION_TLSv1_2:
692 *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
694 case CURL_SSLVERSION_TLSv1_3:
695 failf(data, "GSKit: TLS 1.3 is not yet supported");
696 return CURLE_SSL_CONNECT_ERROR;
703 static CURLcode gskit_connect_step1(struct Curl_easy *data,
704 struct connectdata *conn, int sockindex)
706 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
709 const char * const keyringfile = SSL_CONN_CONFIG(CAfile);
710 const char * const keyringpwd = SSL_SET_OPTION(key_passwd);
711 const char * const keyringlabel = SSL_SET_OPTION(primary.clientcert);
712 const long int ssl_version = SSL_CONN_CONFIG(version);
713 const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
714 const char * const hostname = SSL_HOST_NAME();
716 unsigned int protoflags = 0;
717 Qso_OverlappedIO_t commarea;
718 #ifndef CURL_DISABLE_PROXY
720 static const int sobufsize = CURL_MAX_WRITE_SIZE;
723 /* Create SSL environment, start (preferably asynchronous) handshake. */
724 DEBUGASSERT(BACKEND);
726 BACKEND->handle = (gsk_handle) NULL;
727 BACKEND->iocport = -1;
728 #ifndef CURL_DISABLE_PROXY
729 BACKEND->localfd = -1;
730 BACKEND->remotefd = -1;
733 /* GSKit supports two ways of specifying an SSL context: either by
734 * application identifier (that should have been defined at the system
735 * level) or by keyring file, password and certificate label.
736 * Local certificate name (CURLOPT_SSLCERT) is used to hold either the
737 * application identifier of the certificate label.
738 * Key password (CURLOPT_KEYPASSWD) holds the keyring password.
739 * It is not possible to have different keyrings for the CAs and the
740 * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify
742 * If no key password is given and the keyring is the system keyring,
743 * application identifier mode is tried first, as recommended in IBM doc.
746 envir = (gsk_handle) NULL;
748 if(keyringlabel && *keyringlabel && !keyringpwd &&
749 !strcmp(keyringfile, CURL_CA_BUNDLE)) {
750 /* Try application identifier mode. */
751 init_environment(data, &envir, keyringlabel, (const char *) NULL,
752 (const char *) NULL, (const char *) NULL);
756 /* Use keyring mode. */
757 result = init_environment(data, &envir, (const char *) NULL,
758 keyringfile, keyringlabel, keyringpwd);
763 /* Create secure session. */
764 result = gskit_status(data, gsk_secure_soc_open(envir, &BACKEND->handle),
765 "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
766 gsk_environment_close(&envir);
770 #ifndef CURL_DISABLE_PROXY
771 /* Establish a pipelining socket pair for SSL over SSL. */
772 if(conn->proxy_ssl[sockindex].use) {
773 if(Curl_socketpair(0, 0, 0, sockpair))
774 return CURLE_SSL_CONNECT_ERROR;
775 BACKEND->localfd = sockpair[0];
776 BACKEND->remotefd = sockpair[1];
777 setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
778 (void *) &sobufsize, sizeof(sobufsize));
779 setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
780 (void *) &sobufsize, sizeof(sobufsize));
781 setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
782 (void *) &sobufsize, sizeof(sobufsize));
783 setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
784 (void *) &sobufsize, sizeof(sobufsize));
785 curlx_nonblock(BACKEND->localfd, TRUE);
786 curlx_nonblock(BACKEND->remotefd, TRUE);
790 /* Determine which SSL/TLS version should be enabled. */
792 switch(ssl_version) {
793 case CURL_SSLVERSION_SSLv2:
794 protoflags = CURL_GSKPROTO_SSLV2_MASK;
797 case CURL_SSLVERSION_SSLv3:
798 protoflags = CURL_GSKPROTO_SSLV3_MASK;
801 case CURL_SSLVERSION_DEFAULT:
802 case CURL_SSLVERSION_TLSv1:
803 protoflags = CURL_GSKPROTO_TLSV10_MASK |
804 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
806 case CURL_SSLVERSION_TLSv1_0:
807 case CURL_SSLVERSION_TLSv1_1:
808 case CURL_SSLVERSION_TLSv1_2:
809 case CURL_SSLVERSION_TLSv1_3:
810 result = set_ssl_version_min_max(&protoflags, data);
811 if(result != CURLE_OK)
815 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
816 return CURLE_SSL_CONNECT_ERROR;
819 /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
821 char *snihost = Curl_ssl_snihost(data, sni, NULL);
823 failf(data, "Failed to set SNI");
824 return CURLE_SSL_CONNECT_ERROR;
826 result = set_buffer(data, BACKEND->handle,
827 GSK_SSL_EXTN_SERVERNAME_REQUEST, snihost, TRUE);
828 if(result == CURLE_UNSUPPORTED_PROTOCOL)
832 /* Set session parameters. */
834 /* Compute the handshake timeout. Since GSKit granularity is 1 second,
835 we round up the required value. */
836 timediff_t timeout = Curl_timeleft(data, NULL, TRUE);
838 result = CURLE_OPERATION_TIMEDOUT;
840 result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT,
841 (timeout + 999) / 1000);
844 result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
846 #ifndef CURL_DISABLE_PROXY
847 result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
848 BACKEND->localfd: conn->sock[sockindex]);
850 result = set_numeric(data, BACKEND->handle, GSK_FD,
851 conn->sock[sockindex]);
854 result = set_ciphers(data, BACKEND->handle, &protoflags);
856 failf(data, "No SSL protocol/cipher combination enabled");
857 result = CURLE_SSL_CIPHER;
860 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2,
861 (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
862 GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
864 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV3,
865 (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
866 GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
868 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV1,
869 (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
870 GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
872 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV11,
873 (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
874 GSK_TRUE: GSK_FALSE, TRUE);
875 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
877 if(protoflags == CURL_GSKPROTO_TLSV11_MASK) {
878 failf(data, "TLS 1.1 not yet supported");
879 result = CURLE_SSL_CIPHER;
884 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV12,
885 (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
886 GSK_TRUE: GSK_FALSE, TRUE);
887 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
889 if(protoflags == CURL_GSKPROTO_TLSV12_MASK) {
890 failf(data, "TLS 1.2 not yet supported");
891 result = CURLE_SSL_CIPHER;
896 result = set_enum(data, BACKEND->handle, GSK_SERVER_AUTH_TYPE,
897 verifypeer? GSK_SERVER_AUTH_FULL:
898 GSK_SERVER_AUTH_PASSTHRU, FALSE);
901 /* Start handshake. Try asynchronous first. */
902 memset(&commarea, 0, sizeof(commarea));
903 BACKEND->iocport = QsoCreateIOCompletionPort();
904 if(BACKEND->iocport != -1) {
905 result = gskit_status(data,
906 gsk_secure_soc_startInit(BACKEND->handle,
909 "gsk_secure_soc_startInit()",
910 CURLE_SSL_CONNECT_ERROR);
912 connssl->connecting_state = ssl_connect_2;
916 close_async_handshake(connssl);
918 else if(errno != ENOBUFS)
919 result = gskit_status(data, GSK_ERROR_IO,
920 "QsoCreateIOCompletionPort()", 0);
921 #ifndef CURL_DISABLE_PROXY
922 else if(conn->proxy_ssl[sockindex].use) {
923 /* Cannot pipeline while handshaking synchronously. */
924 result = CURLE_SSL_CONNECT_ERROR;
928 /* No more completion port available. Use synchronous IO. */
929 result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle),
930 "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
932 connssl->connecting_state = ssl_connect_3;
938 /* Error: rollback. */
939 close_one(connssl, data, conn, sockindex);
944 static CURLcode gskit_connect_step2(struct Curl_easy *data,
945 struct connectdata *conn, int sockindex,
948 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
949 Qso_OverlappedIO_t cstat;
953 /* Poll or wait for end of SSL asynchronous handshake. */
954 DEBUGASSERT(BACKEND);
957 timediff_t timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
962 switch(QsoWaitForIOCompletion(BACKEND->iocport, &cstat,
963 curlx_mstotv(&stmv, timeout_ms))) {
964 case 1: /* Operation complete. */
966 case -1: /* An error occurred: handshake still in progress. */
970 continue; /* Retry. */
973 char buffer[STRERROR_LEN];
974 failf(data, "QsoWaitForIOCompletion() I/O error: %s",
975 Curl_strerror(errno, buffer, sizeof(buffer)));
976 cancel_async_handshake(conn, sockindex);
977 close_async_handshake(connssl);
978 return CURLE_SSL_CONNECT_ERROR;
981 case 0: /* Handshake in progress, timeout occurred. */
984 cancel_async_handshake(conn, sockindex);
985 close_async_handshake(connssl);
986 return CURLE_OPERATION_TIMEDOUT;
990 result = gskit_status(data, cstat.returnValue, "SSL handshake",
991 CURLE_SSL_CONNECT_ERROR);
993 connssl->connecting_state = ssl_connect_3;
994 close_async_handshake(connssl);
999 static CURLcode gskit_connect_step3(struct Curl_easy *data,
1000 struct connectdata *conn, int sockindex)
1002 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1003 const gsk_cert_data_elem *cdev;
1005 const gsk_cert_data_elem *p;
1006 const char *cert = (const char *) NULL;
1007 const char *certend;
1011 /* SSL handshake done: gather certificate info and verify host. */
1012 DEBUGASSERT(BACKEND);
1014 if(gskit_status(data, gsk_attribute_get_cert_info(BACKEND->handle,
1015 GSK_PARTNER_CERT_INFO,
1017 "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
1021 infof(data, "Server certificate:");
1023 for(i = 0; i++ < cdec; p++)
1024 switch(p->cert_data_id) {
1026 cert = p->cert_data_p;
1027 certend = cert + cdev->cert_data_l;
1029 case CERT_DN_PRINTABLE:
1030 infof(data, "\t subject: %.*s", p->cert_data_l, p->cert_data_p);
1032 case CERT_ISSUER_DN_PRINTABLE:
1033 infof(data, "\t issuer: %.*s", p->cert_data_l, p->cert_data_p);
1035 case CERT_VALID_FROM:
1036 infof(data, "\t start date: %.*s", p->cert_data_l, p->cert_data_p);
1039 infof(data, "\t expire date: %.*s", p->cert_data_l, p->cert_data_p);
1045 result = Curl_verifyhost(data, conn, cert, certend);
1049 /* The only place GSKit can get the whole CA chain is a validation
1050 callback where no user data pointer is available. Therefore it's not
1051 possible to copy this chain into our structures for CAINFO.
1052 However the server certificate may be available, thus we can return
1054 if(data->set.ssl.certinfo) {
1055 result = Curl_ssl_init_certinfo(data, 1);
1060 result = Curl_extract_certinfo(data, 0, cert, certend);
1066 /* Check pinned public key. */
1067 ptr = SSL_PINNED_PUB_KEY();
1068 if(!result && ptr) {
1069 struct Curl_X509certificate x509;
1070 struct Curl_asn1Element *p;
1072 memset(&x509, 0, sizeof(x509));
1073 if(Curl_parseX509(&x509, cert, certend))
1074 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1075 p = &x509.subjectPublicKeyInfo;
1076 result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header);
1078 failf(data, "SSL: public key does not match pinned public key");
1083 connssl->connecting_state = ssl_connect_done;
1088 static CURLcode gskit_connect_common(struct Curl_easy *data,
1089 struct connectdata *conn, int sockindex,
1090 bool nonblocking, bool *done)
1092 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1093 timediff_t timeout_ms;
1094 CURLcode result = CURLE_OK;
1096 *done = connssl->state == ssl_connection_complete;
1100 /* Step 1: create session, start handshake. */
1101 if(connssl->connecting_state == ssl_connect_1) {
1102 /* check allowed time left */
1103 timeout_ms = Curl_timeleft(data, NULL, TRUE);
1105 if(timeout_ms < 0) {
1106 /* no need to continue if time already is up */
1107 failf(data, "SSL connection timeout");
1108 result = CURLE_OPERATION_TIMEDOUT;
1111 result = gskit_connect_step1(data, conn, sockindex);
1114 /* Handle handshake pipelining. */
1116 if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
1117 result = CURLE_SSL_CONNECT_ERROR;
1119 /* Step 2: check if handshake is over. */
1120 if(!result && connssl->connecting_state == ssl_connect_2) {
1121 /* check allowed time left */
1122 timeout_ms = Curl_timeleft(data, NULL, TRUE);
1124 if(timeout_ms < 0) {
1125 /* no need to continue if time already is up */
1126 failf(data, "SSL connection timeout");
1127 result = CURLE_OPERATION_TIMEDOUT;
1130 result = gskit_connect_step2(data, conn, sockindex, nonblocking);
1133 /* Handle handshake pipelining. */
1135 if(pipe_ssloverssl(conn, sockindex, SOS_READ | SOS_WRITE) < 0)
1136 result = CURLE_SSL_CONNECT_ERROR;
1138 /* Step 3: gather certificate info, verify host. */
1139 if(!result && connssl->connecting_state == ssl_connect_3)
1140 result = gskit_connect_step3(data, conn, sockindex);
1143 close_one(connssl, data, conn, sockindex);
1144 else if(connssl->connecting_state == ssl_connect_done) {
1145 connssl->state = ssl_connection_complete;
1146 connssl->connecting_state = ssl_connect_1;
1147 conn->recv[sockindex] = gskit_recv;
1148 conn->send[sockindex] = gskit_send;
1156 static CURLcode gskit_connect_nonblocking(struct Curl_easy *data,
1157 struct connectdata *conn,
1158 int sockindex, bool *done)
1162 result = gskit_connect_common(data, conn, sockindex, TRUE, done);
1164 conn->ssl[sockindex].connecting_state = ssl_connect_1;
1169 static CURLcode gskit_connect(struct Curl_easy *data,
1170 struct connectdata *conn, int sockindex)
1175 conn->ssl[sockindex].connecting_state = ssl_connect_1;
1176 result = gskit_connect_common(data, conn, sockindex, FALSE, &done);
1186 static void gskit_close(struct Curl_easy *data, struct connectdata *conn,
1189 close_one(&conn->ssl[sockindex], data, conn, sockindex);
1190 #ifndef CURL_DISABLE_PROXY
1191 close_one(&conn->proxy_ssl[sockindex], data, conn, sockindex);
1196 static int gskit_shutdown(struct Curl_easy *data,
1197 struct connectdata *conn, int sockindex)
1199 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1203 int loop = 10; /* don't get stuck */
1205 DEBUGASSERT(BACKEND);
1207 if(!BACKEND->handle)
1210 #ifndef CURL_DISABLE_FTP
1211 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
1215 close_one(connssl, data, conn, sockindex);
1217 what = SOCKET_READABLE(conn->sock[sockindex],
1218 SSL_SHUTDOWN_TIMEOUT);
1224 /* anything that gets here is fatally bad */
1225 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1230 if(!what) { /* timeout */
1231 failf(data, "SSL shutdown timeout");
1235 /* Something to read, let's do it and hope that it is the close
1236 notify alert from the server. No way to gsk_secure_soc_read() now, so
1239 nread = read(conn->sock[sockindex], buf, sizeof(buf));
1242 char buffer[STRERROR_LEN];
1243 failf(data, "read: %s", Curl_strerror(errno, buffer, sizeof(buffer)));
1250 what = SOCKET_READABLE(conn->sock[sockindex], 0);
1257 static size_t gskit_version(char *buffer, size_t size)
1259 return msnprintf(buffer, size, "GSKit");
1263 static int gskit_check_cxn(struct connectdata *cxn)
1265 struct ssl_connect_data *connssl = &cxn->ssl[FIRSTSOCKET];
1269 /* The only thing that can be tested here is at the socket level. */
1270 DEBUGASSERT(BACKEND);
1272 if(!BACKEND->handle)
1273 return 0; /* connection has been closed */
1276 errlen = sizeof(err);
1278 if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
1279 (unsigned char *) &err, &errlen) ||
1280 errlen != sizeof(err) || err)
1281 return 0; /* connection has been closed */
1283 return -1; /* connection status unknown */
1286 static void *gskit_get_internals(struct ssl_connect_data *connssl,
1287 CURLINFO info UNUSED_PARAM)
1290 DEBUGASSERT(BACKEND);
1291 return BACKEND->handle;
1294 const struct Curl_ssl Curl_ssl_gskit = {
1295 { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */
1298 SSLSUPP_PINNEDPUBKEY,
1300 sizeof(struct ssl_backend_data),
1302 gskit_init, /* init */
1303 gskit_cleanup, /* cleanup */
1304 gskit_version, /* version */
1305 gskit_check_cxn, /* check_cxn */
1306 gskit_shutdown, /* shutdown */
1307 Curl_none_data_pending, /* data_pending */
1308 Curl_none_random, /* random */
1309 Curl_none_cert_status_request, /* cert_status_request */
1310 gskit_connect, /* connect */
1311 gskit_connect_nonblocking, /* connect_nonblocking */
1312 Curl_ssl_getsock, /* getsock */
1313 gskit_get_internals, /* get_internals */
1314 gskit_close, /* close_one */
1315 Curl_none_close_all, /* close_all */
1316 /* No session handling for GSKit */
1317 Curl_none_session_free, /* session_free */
1318 Curl_none_set_engine, /* set_engine */
1319 Curl_none_set_engine_default, /* set_engine_default */
1320 Curl_none_engines_list, /* engines_list */
1321 Curl_none_false_start, /* false_start */
1322 NULL, /* sha256sum */
1323 NULL, /* associate_connection */
1324 NULL /* disassociate_connection */
1327 #endif /* USE_GSKIT */