VirtualBox

source: vbox/trunk/src/libs/curl-8.0.1/lib/vtls/gskit.c@ 99344

Last change on this file since 99344 was 99344, checked in by vboxsync, 22 months ago

curl-8.0.1: Applied and adjusted our curl changes to 7.87.0 bugref:10417

  • Property svn:eol-style set to native
File size: 39.8 KB
Line 
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9 *
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.
13 *
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.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24
25#include "curl_setup.h"
26
27#ifdef USE_GSKIT
28
29#include <gskssl.h>
30#include <qsoasync.h>
31#undef HAVE_SOCKETPAIR /* because the native one isn't good enough */
32#include "socketpair.h"
33#include "strerror.h"
34
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
38#endif
39
40#ifndef GSK_TLSV10_CIPHER_SPECS
41#define GSK_TLSV10_CIPHER_SPECS 236
42#endif
43
44#ifndef GSK_TLSV11_CIPHER_SPECS
45#define GSK_TLSV11_CIPHER_SPECS 237
46#endif
47
48#ifndef GSK_TLSV12_CIPHER_SPECS
49#define GSK_TLSV12_CIPHER_SPECS 238
50#endif
51
52#ifndef GSK_PROTOCOL_TLSV11
53#define GSK_PROTOCOL_TLSV11 437
54#endif
55
56#ifndef GSK_PROTOCOL_TLSV12
57#define GSK_PROTOCOL_TLSV12 438
58#endif
59
60#ifndef GSK_FALSE
61#define GSK_FALSE 0
62#endif
63
64#ifndef GSK_TRUE
65#define GSK_TRUE 1
66#endif
67
68
69#include <limits.h>
70
71#include <curl/curl.h>
72#include "urldata.h"
73#include "sendf.h"
74#include "gskit.h"
75#include "vtls.h"
76#include "vtls_int.h"
77#include "connect.h" /* for the connect timeout */
78#include "select.h"
79#include "strcase.h"
80#include "timediff.h"
81#include "x509asn1.h"
82#include "curl_printf.h"
83
84#include "curl_memory.h"
85/* The last #include file should be: */
86#include "memdebug.h"
87
88
89/* Directions. */
90#define SOS_READ 0x01
91#define SOS_WRITE 0x02
92
93/* SSL version flags. */
94#define CURL_GSKPROTO_SSLV2 0
95#define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2)
96#define CURL_GSKPROTO_SSLV3 1
97#define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3)
98#define CURL_GSKPROTO_TLSV10 2
99#define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10)
100#define CURL_GSKPROTO_TLSV11 3
101#define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11)
102#define CURL_GSKPROTO_TLSV12 4
103#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12)
104#define CURL_GSKPROTO_LAST 5
105
106struct ssl_backend_data {
107 gsk_handle handle;
108 int iocport;
109 int localfd;
110 int remotefd;
111};
112
113#define BACKEND connssl->backend
114
115/* Supported ciphers. */
116struct gskit_cipher {
117 const char *name; /* Cipher name. */
118 const char *gsktoken; /* Corresponding token for GSKit String. */
119 unsigned int versions; /* SSL version flags. */
120};
121
122static const struct gskit_cipher ciphertable[] = {
123 { "null-md5", "01",
124 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
125 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
126 { "null-sha", "02",
127 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
128 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
129 { "exp-rc4-md5", "03",
130 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
131 { "rc4-md5", "04",
132 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
133 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
134 { "rc4-sha", "05",
135 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
136 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
137 { "exp-rc2-cbc-md5", "06",
138 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK },
139 { "exp-des-cbc-sha", "09",
140 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
141 CURL_GSKPROTO_TLSV11_MASK },
142 { "des-cbc3-sha", "0A",
143 CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
144 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK },
145 { "aes128-sha", "2F",
146 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
147 CURL_GSKPROTO_TLSV12_MASK },
148 { "aes256-sha", "35",
149 CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK |
150 CURL_GSKPROTO_TLSV12_MASK },
151 { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK },
152 { "aes128-sha256", "3C", CURL_GSKPROTO_TLSV12_MASK },
153 { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK },
154 { "aes128-gcm-sha256",
155 "9C", CURL_GSKPROTO_TLSV12_MASK },
156 { "aes256-gcm-sha384",
157 "9D", CURL_GSKPROTO_TLSV12_MASK },
158 { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK },
159 { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK },
160 { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK },
161 { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK },
162 { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK },
163 { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK },
164 { (const char *) NULL, (const char *) NULL, 0 }
165};
166
167
168static bool is_separator(char c)
169{
170 /* Return whether character is a cipher list separator. */
171 switch(c) {
172 case ' ':
173 case '\t':
174 case ':':
175 case ',':
176 case ';':
177 return true;
178 }
179 return false;
180}
181
182
183static CURLcode gskit_status(struct Curl_easy *data, int rc,
184 const char *procname, CURLcode defcode)
185{
186 char buffer[STRERROR_LEN];
187 /* Process GSKit status and map it to a CURLcode. */
188 switch(rc) {
189 case GSK_OK:
190 case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
191 return CURLE_OK;
192 case GSK_KEYRING_OPEN_ERROR:
193 case GSK_OS400_ERROR_NO_ACCESS:
194 return CURLE_SSL_CACERT_BADFILE;
195 case GSK_INSUFFICIENT_STORAGE:
196 return CURLE_OUT_OF_MEMORY;
197 case GSK_ERROR_BAD_V2_CIPHER:
198 case GSK_ERROR_BAD_V3_CIPHER:
199 case GSK_ERROR_NO_CIPHERS:
200 return CURLE_SSL_CIPHER;
201 case GSK_OS400_ERROR_NOT_TRUSTED_ROOT:
202 case GSK_ERROR_CERT_VALIDATION:
203 return CURLE_PEER_FAILED_VERIFICATION;
204 case GSK_OS400_ERROR_TIMED_OUT:
205 return CURLE_OPERATION_TIMEDOUT;
206 case GSK_WOULD_BLOCK:
207 return CURLE_AGAIN;
208 case GSK_OS400_ERROR_NOT_REGISTERED:
209 break;
210 case GSK_ERROR_IO:
211 switch(errno) {
212 case ENOMEM:
213 return CURLE_OUT_OF_MEMORY;
214 default:
215 failf(data, "%s I/O error: %s", procname,
216 Curl_strerror(errno, buffer, sizeof(buffer)));
217 break;
218 }
219 break;
220 default:
221 failf(data, "%s: %s", procname, gsk_strerror(rc));
222 break;
223 }
224 return defcode;
225}
226
227
228static CURLcode set_enum(struct Curl_easy *data, gsk_handle h,
229 GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok)
230{
231 char buffer[STRERROR_LEN];
232 int rc = gsk_attribute_set_enum(h, id, value);
233
234 switch(rc) {
235 case GSK_OK:
236 return CURLE_OK;
237 case GSK_ERROR_IO:
238 failf(data, "gsk_attribute_set_enum() I/O error: %s",
239 Curl_strerror(errno, buffer, sizeof(buffer)));
240 break;
241 case GSK_ATTRIBUTE_INVALID_ID:
242 if(unsupported_ok)
243 return CURLE_UNSUPPORTED_PROTOCOL;
244 default:
245 failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
246 break;
247 }
248 return CURLE_SSL_CONNECT_ERROR;
249}
250
251
252static CURLcode set_buffer(struct Curl_easy *data, gsk_handle h,
253 GSK_BUF_ID id, const char *buf, bool unsupported_ok)
254{
255 char buffer[STRERROR_LEN];
256 int rc = gsk_attribute_set_buffer(h, id, buf, 0);
257
258 switch(rc) {
259 case GSK_OK:
260 return CURLE_OK;
261 case GSK_ERROR_IO:
262 failf(data, "gsk_attribute_set_buffer() I/O error: %s",
263 Curl_strerror(errno, buffer, sizeof(buffer)));
264 break;
265 case GSK_ATTRIBUTE_INVALID_ID:
266 if(unsupported_ok)
267 return CURLE_UNSUPPORTED_PROTOCOL;
268 default:
269 failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
270 break;
271 }
272 return CURLE_SSL_CONNECT_ERROR;
273}
274
275
276static CURLcode set_numeric(struct Curl_easy *data,
277 gsk_handle h, GSK_NUM_ID id, int value)
278{
279 char buffer[STRERROR_LEN];
280 int rc = gsk_attribute_set_numeric_value(h, id, value);
281
282 switch(rc) {
283 case GSK_OK:
284 return CURLE_OK;
285 case GSK_ERROR_IO:
286 failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
287 Curl_strerror(errno, buffer, sizeof(buffer)));
288 break;
289 default:
290 failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
291 break;
292 }
293 return CURLE_SSL_CONNECT_ERROR;
294}
295
296
297static CURLcode set_ciphers(struct Curl_cfilter *cf, struct Curl_easy *data,
298 gsk_handle h, unsigned int *protoflags)
299{
300 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
301 struct connectdata *conn = data->conn;
302 const char *cipherlist = conn_config->cipher_list;
303 const char *clp;
304 const struct gskit_cipher *ctp;
305 int i;
306 int l;
307 bool unsupported;
308 CURLcode result;
309 struct {
310 char *buf;
311 char *ptr;
312 } ciphers[CURL_GSKPROTO_LAST];
313
314 /* Compile cipher list into GSKit-compatible cipher lists. */
315
316 if(!cipherlist)
317 return CURLE_OK;
318 while(is_separator(*cipherlist)) /* Skip initial separators. */
319 cipherlist++;
320 if(!*cipherlist)
321 return CURLE_OK;
322
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(ciphers, 0, sizeof(ciphers));
328 for(i = 0; i < CURL_GSKPROTO_LAST; i++) {
329 ciphers[i].buf = malloc(l);
330 if(!ciphers[i].buf) {
331 while(i--)
332 free(ciphers[i].buf);
333 return CURLE_OUT_OF_MEMORY;
334 }
335 ciphers[i].ptr = ciphers[i].buf;
336 *ciphers[i].ptr = '\0';
337 }
338
339 /* Process each cipher in input string. */
340 unsupported = FALSE;
341 result = CURLE_OK;
342 for(;;) {
343 for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
344 cipherlist++;
345 l = cipherlist - clp;
346 if(!l)
347 break;
348 /* Search the cipher in our table. */
349 for(ctp = ciphertable; ctp->name; ctp++)
350 if(strncasecompare(ctp->name, clp, l) && !ctp->name[l])
351 break;
352 if(!ctp->name) {
353 failf(data, "Unknown cipher %.*s", l, clp);
354 result = CURLE_SSL_CIPHER;
355 }
356 else {
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);
363 }
364 }
365 }
366
367 /* Advance to next cipher name or end of string. */
368 while(is_separator(*cipherlist))
369 cipherlist++;
370 }
371
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';
377 }
378 }
379
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) {
385 result = CURLE_OK;
386 if(unsupported) {
387 failf(data, "TLSv1.1-only ciphers are not yet supported");
388 result = CURLE_SSL_CIPHER;
389 }
390 }
391 }
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) {
396 result = CURLE_OK;
397 if(unsupported) {
398 failf(data, "TLSv1.2-only ciphers are not yet supported");
399 result = CURLE_SSL_CIPHER;
400 }
401 }
402 }
403
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) {
410 result = CURLE_OK;
411 strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr,
412 ciphers[CURL_GSKPROTO_TLSV10].ptr);
413 }
414 }
415
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);
423
424 /* Clean-up. */
425 for(i = 0; i < CURL_GSKPROTO_LAST; i++)
426 free(ciphers[i].buf);
427
428 return result;
429}
430
431
432static int gskit_init(void)
433{
434 /* No initialization needed. */
435 return 1;
436}
437
438
439static void gskit_cleanup(void)
440{
441 /* Nothing to do. */
442}
443
444
445static 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)
449{
450 int rc;
451 CURLcode result;
452 gsk_handle h;
453
454 /* Creates the GSKit environment. */
455
456 rc = gsk_environment_open(&h);
457 switch(rc) {
458 case GSK_OK:
459 break;
460 case GSK_INSUFFICIENT_STORAGE:
461 return CURLE_OUT_OF_MEMORY;
462 default:
463 failf(data, "gsk_environment_open(): %s", gsk_strerror(rc));
464 return CURLE_SSL_CONNECT_ERROR;
465 }
466
467 result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
468 if(!result && appid)
469 result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
470 if(!result && file)
471 result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
472 if(!result && label)
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);
476
477 if(!result) {
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);
482 if(!result) {
483 *envir = h;
484 return result;
485 }
486 }
487 /* Error: rollback. */
488 gsk_environment_close(&h);
489 return result;
490}
491
492
493static void cancel_async_handshake(struct Curl_cfilter *cf,
494 struct Curl_easy *data)
495{
496 struct ssl_connect_data *connssl = cf->ctx;
497 Qso_OverlappedIO_t cstat;
498
499 (void)data;
500 DEBUGASSERT(BACKEND);
501
502 if(QsoCancelOperation(Curl_conn_cf_get_socket(cf, data), 0) > 0)
503 QsoWaitForIOCompletion(BACKEND->iocport, &cstat, (struct timeval *) NULL);
504}
505
506
507static void close_async_handshake(struct ssl_connect_data *connssl)
508{
509 DEBUGASSERT(BACKEND);
510 QsoDestroyIOCompletionPort(BACKEND->iocport);
511 BACKEND->iocport = -1;
512}
513
514static int pipe_ssloverssl(struct Curl_cfilter *cf, int directions)
515{
516 struct ssl_connect_data *connssl = cf->ctx;
517 struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
518 struct ssl_connect_data *connssl_next = cf_ssl_next?
519 cf_ssl_next->ctx : NULL;
520 struct pollfd fds[2];
521 int n;
522 int m;
523 int i;
524 int ret = 0;
525 char buf[CURL_MAX_WRITE_SIZE];
526
527 DEBUGASSERT(BACKEND);
528
529 if(!connssl_next)
530 return 0; /* No SSL over SSL: OK. */
531
532 DEBUGASSERT(connssl_next->backend);
533 n = 1;
534 fds[0].fd = BACKEND->remotefd;
535 fds[1].fd = Curl_conn_cf_get_socket(cf, data);
536
537 if(directions & SOS_READ) {
538 fds[0].events |= POLLOUT;
539 }
540 if(directions & SOS_WRITE) {
541 n = 2;
542 fds[0].events |= POLLIN;
543 fds[1].events |= POLLOUT;
544 }
545 i = Curl_poll(fds, n, 0);
546 if(i < 0)
547 return -1; /* Select error. */
548
549 if(fds[0].revents & POLLOUT) {
550 /* Try getting data from HTTPS proxy and pipe it upstream. */
551 n = 0;
552 i = gsk_secure_soc_read(connssl_next->backend->handle,
553 buf, sizeof(buf), &n);
554 switch(i) {
555 case GSK_OK:
556 if(n) {
557 i = write(BACKEND->remotefd, buf, n);
558 if(i < 0)
559 return -1;
560 ret = 1;
561 }
562 break;
563 case GSK_OS400_ERROR_TIMED_OUT:
564 case GSK_WOULD_BLOCK:
565 break;
566 default:
567 return -1;
568 }
569 }
570
571 if((fds[0].revents & POLLIN) && (fds[1].revents & POLLOUT)) {
572 /* Pipe data to HTTPS proxy. */
573 n = read(BACKEND->remotefd, buf, sizeof(buf));
574 if(n < 0)
575 return -1;
576 if(n) {
577 i = gsk_secure_soc_write(connssl_next->backend->handle, buf, n, &m);
578 if(i != GSK_OK || n != m)
579 return -1;
580 ret = 1;
581 }
582 }
583
584 return ret; /* OK */
585}
586
587
588static void close_one(struct Curl_cfilter *cf, struct Curl_easy *data)
589{
590 struct ssl_connect_data *connssl = cf->ctx;
591
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(cf, SOS_WRITE) > 0)
598 ;
599 BACKEND->handle = (gsk_handle) NULL;
600 if(BACKEND->localfd >= 0) {
601 close(BACKEND->localfd);
602 BACKEND->localfd = -1;
603 }
604 if(BACKEND->remotefd >= 0) {
605 close(BACKEND->remotefd);
606 BACKEND->remotefd = -1;
607 }
608 }
609 if(BACKEND->iocport >= 0)
610 close_async_handshake(connssl);
611}
612
613
614static ssize_t gskit_send(struct Curl_cfilter *cf, struct Curl_easy *data,
615 const void *mem, size_t len, CURLcode *curlcode)
616{
617 struct connectdata *conn = cf->conn;
618 struct ssl_connect_data *connssl = cf->ctx;
619 CURLcode cc = CURLE_SEND_ERROR;
620 int written;
621
622 DEBUGASSERT(BACKEND);
623
624 if(pipe_ssloverssl(cf, 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);
629 if(cc == CURLE_OK)
630 if(pipe_ssloverssl(cf, SOS_WRITE) < 0)
631 cc = CURLE_SEND_ERROR;
632 }
633 if(cc != CURLE_OK) {
634 *curlcode = cc;
635 written = -1;
636 }
637 return (ssize_t) written; /* number of bytes */
638}
639
640
641static ssize_t gskit_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
642 char *buf, size_t buffersize, CURLcode *curlcode)
643{
644 struct connectdata *conn = cf->conn;
645 struct ssl_connect_data *connssl = cf->ctx;
646 int nread;
647 CURLcode cc = CURLE_RECV_ERROR;
648
649 (void)data;
650 DEBUGASSERT(BACKEND);
651
652 if(pipe_ssloverssl(cf, SOS_READ) >= 0) {
653 int buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
654 cc = gskit_status(data, gsk_secure_soc_read(BACKEND->handle,
655 buf, buffsize, &nread),
656 "gsk_secure_soc_read()", CURLE_RECV_ERROR);
657 }
658 switch(cc) {
659 case CURLE_OK:
660 break;
661 case CURLE_OPERATION_TIMEDOUT:
662 cc = CURLE_AGAIN;
663 default:
664 *curlcode = cc;
665 nread = -1;
666 break;
667 }
668 return (ssize_t) nread;
669}
670
671static CURLcode
672set_ssl_version_min_max(unsigned int *protoflags,
673 struct Curl_cfilter *cf,
674 struct Curl_easy *data)
675{
676 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
677 struct connectdata *conn = data->conn;
678 long ssl_version = conn_config->version;
679 long ssl_version_max = conn_config->version_max;
680 long i = ssl_version;
681 switch(ssl_version_max) {
682 case CURL_SSLVERSION_MAX_NONE:
683 case CURL_SSLVERSION_MAX_DEFAULT:
684 ssl_version_max = CURL_SSLVERSION_TLSv1_2;
685 break;
686 }
687 for(; i <= (ssl_version_max >> 16); ++i) {
688 switch(i) {
689 case CURL_SSLVERSION_TLSv1_0:
690 *protoflags |= CURL_GSKPROTO_TLSV10_MASK;
691 break;
692 case CURL_SSLVERSION_TLSv1_1:
693 *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
694 break;
695 case CURL_SSLVERSION_TLSv1_2:
696 *protoflags |= CURL_GSKPROTO_TLSV11_MASK;
697 break;
698 case CURL_SSLVERSION_TLSv1_3:
699 failf(data, "GSKit: TLS 1.3 is not yet supported");
700 return CURLE_SSL_CONNECT_ERROR;
701 }
702 }
703
704 return CURLE_OK;
705}
706
707static CURLcode gskit_connect_step1(struct Curl_cfilter *cf,
708 struct Curl_easy *data)
709{
710 struct ssl_connect_data *connssl = cf->ctx;
711 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
712 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
713 struct Curl_cfilter *cf_ssl_next = Curl_ssl_cf_get_ssl(cf->next);
714 struct ssl_connect_data *connssl_next = cf_ssl_next?
715 cf_ssl_next->ctx : NULL;
716 gsk_handle envir;
717 CURLcode result;
718 const char * const keyringfile = conn_config->CAfile;
719 const char * const keyringpwd = conn_config->key_passwd;
720 const char * const keyringlabel = ssl_config->primary.clientcert;
721 const long int ssl_version = conn_config->version;
722 const bool verifypeer = conn_config->verifypeer;
723 const char *hostname = connssl->hostname;
724 const char *sni;
725 unsigned int protoflags = 0;
726 Qso_OverlappedIO_t commarea;
727 int sockpair[2];
728 static const int sobufsize = CURL_MAX_WRITE_SIZE;
729
730 /* Create SSL environment, start (preferably asynchronous) handshake. */
731 DEBUGASSERT(BACKEND);
732
733 BACKEND->handle = (gsk_handle) NULL;
734 BACKEND->iocport = -1;
735 BACKEND->localfd = -1;
736 BACKEND->remotefd = -1;
737
738 /* GSKit supports two ways of specifying an SSL context: either by
739 * application identifier (that should have been defined at the system
740 * level) or by keyring file, password and certificate label.
741 * Local certificate name (CURLOPT_SSLCERT) is used to hold either the
742 * application identifier of the certificate label.
743 * Key password (CURLOPT_KEYPASSWD) holds the keyring password.
744 * It is not possible to have different keyrings for the CAs and the
745 * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify
746 * the keyring file.
747 * If no key password is given and the keyring is the system keyring,
748 * application identifier mode is tried first, as recommended in IBM doc.
749 */
750
751 envir = (gsk_handle) NULL;
752
753 if(keyringlabel && *keyringlabel && !keyringpwd &&
754 !strcmp(keyringfile, CURL_CA_BUNDLE)) {
755 /* Try application identifier mode. */
756 init_environment(data, &envir, keyringlabel, (const char *) NULL,
757 (const char *) NULL, (const char *) NULL);
758 }
759
760 if(!envir) {
761 /* Use keyring mode. */
762 result = init_environment(data, &envir, (const char *) NULL,
763 keyringfile, keyringlabel, keyringpwd);
764 if(result)
765 return result;
766 }
767
768 /* Create secure session. */
769 result = gskit_status(data, gsk_secure_soc_open(envir, &BACKEND->handle),
770 "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
771 gsk_environment_close(&envir);
772 if(result)
773 return result;
774
775 /* Establish a pipelining socket pair for SSL over SSL. */
776 if(connssl_next) {
777 if(Curl_socketpair(0, 0, 0, sockpair))
778 return CURLE_SSL_CONNECT_ERROR;
779 BACKEND->localfd = sockpair[0];
780 BACKEND->remotefd = sockpair[1];
781 setsockopt(BACKEND->localfd, SOL_SOCKET, SO_RCVBUF,
782 (void *) &sobufsize, sizeof(sobufsize));
783 setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_RCVBUF,
784 (void *) &sobufsize, sizeof(sobufsize));
785 setsockopt(BACKEND->localfd, SOL_SOCKET, SO_SNDBUF,
786 (void *) &sobufsize, sizeof(sobufsize));
787 setsockopt(BACKEND->remotefd, SOL_SOCKET, SO_SNDBUF,
788 (void *) &sobufsize, sizeof(sobufsize));
789 curlx_nonblock(BACKEND->localfd, TRUE);
790 curlx_nonblock(BACKEND->remotefd, TRUE);
791 }
792
793 /* Determine which SSL/TLS version should be enabled. */
794 sni = hostname;
795 switch(ssl_version) {
796 case CURL_SSLVERSION_SSLv2:
797 protoflags = CURL_GSKPROTO_SSLV2_MASK;
798 sni = NULL;
799 break;
800 case CURL_SSLVERSION_SSLv3:
801 protoflags = CURL_GSKPROTO_SSLV3_MASK;
802 sni = NULL;
803 break;
804 case CURL_SSLVERSION_DEFAULT:
805 case CURL_SSLVERSION_TLSv1:
806 protoflags = CURL_GSKPROTO_TLSV10_MASK |
807 CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK;
808 break;
809 case CURL_SSLVERSION_TLSv1_0:
810 case CURL_SSLVERSION_TLSv1_1:
811 case CURL_SSLVERSION_TLSv1_2:
812 case CURL_SSLVERSION_TLSv1_3:
813 result = set_ssl_version_min_max(&protoflags, cf, data);
814 if(result != CURLE_OK)
815 return result;
816 break;
817 default:
818 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
819 return CURLE_SSL_CONNECT_ERROR;
820 }
821
822 /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
823 if(sni) {
824 char *snihost = Curl_ssl_snihost(data, sni, NULL);
825 if(!snihost) {
826 failf(data, "Failed to set SNI");
827 return CURLE_SSL_CONNECT_ERROR;
828 }
829 result = set_buffer(data, BACKEND->handle,
830 GSK_SSL_EXTN_SERVERNAME_REQUEST, snihost, TRUE);
831 if(result == CURLE_UNSUPPORTED_PROTOCOL)
832 result = CURLE_OK;
833 }
834
835 /* Set session parameters. */
836 if(!result) {
837 /* Compute the handshake timeout. Since GSKit granularity is 1 second,
838 we round up the required value. */
839 timediff_t timeout = Curl_timeleft(data, NULL, TRUE);
840 if(timeout < 0)
841 result = CURLE_OPERATION_TIMEDOUT;
842 else
843 result = set_numeric(data, BACKEND->handle, GSK_HANDSHAKE_TIMEOUT,
844 (timeout + 999) / 1000);
845 }
846 if(!result)
847 result = set_numeric(data, BACKEND->handle, GSK_OS400_READ_TIMEOUT, 1);
848 if(!result)
849 result = set_numeric(data, BACKEND->handle, GSK_FD, BACKEND->localfd >= 0?
850 BACKEND->localfd: Curl_conn_cf_get_socket(cf, data));
851 if(!result)
852 result = set_ciphers(cf, data, BACKEND->handle, &protoflags);
853 if(!protoflags) {
854 failf(data, "No SSL protocol/cipher combination enabled");
855 result = CURLE_SSL_CIPHER;
856 }
857 if(!result)
858 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV2,
859 (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
860 GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
861 if(!result)
862 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_SSLV3,
863 (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
864 GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
865 if(!result)
866 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV1,
867 (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
868 GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
869 if(!result) {
870 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV11,
871 (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
872 GSK_TRUE: GSK_FALSE, TRUE);
873 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
874 result = CURLE_OK;
875 if(protoflags == CURL_GSKPROTO_TLSV11_MASK) {
876 failf(data, "TLS 1.1 not yet supported");
877 result = CURLE_SSL_CIPHER;
878 }
879 }
880 }
881 if(!result) {
882 result = set_enum(data, BACKEND->handle, GSK_PROTOCOL_TLSV12,
883 (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
884 GSK_TRUE: GSK_FALSE, TRUE);
885 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
886 result = CURLE_OK;
887 if(protoflags == CURL_GSKPROTO_TLSV12_MASK) {
888 failf(data, "TLS 1.2 not yet supported");
889 result = CURLE_SSL_CIPHER;
890 }
891 }
892 }
893 if(!result)
894 result = set_enum(data, BACKEND->handle, GSK_SERVER_AUTH_TYPE,
895 verifypeer? GSK_SERVER_AUTH_FULL:
896 GSK_SERVER_AUTH_PASSTHRU, FALSE);
897
898 if(!result) {
899 /* Start handshake. Try asynchronous first. */
900 memset(&commarea, 0, sizeof(commarea));
901 BACKEND->iocport = QsoCreateIOCompletionPort();
902 if(BACKEND->iocport != -1) {
903 result = gskit_status(data,
904 gsk_secure_soc_startInit(BACKEND->handle,
905 BACKEND->iocport,
906 &commarea),
907 "gsk_secure_soc_startInit()",
908 CURLE_SSL_CONNECT_ERROR);
909 if(!result) {
910 connssl->connecting_state = ssl_connect_2;
911 return CURLE_OK;
912 }
913 else
914 close_async_handshake(connssl);
915 }
916 else if(errno != ENOBUFS)
917 result = gskit_status(data, GSK_ERROR_IO,
918 "QsoCreateIOCompletionPort()", 0);
919 else if(connssl_next) {
920 /* Cannot pipeline while handshaking synchronously. */
921 result = CURLE_SSL_CONNECT_ERROR;
922 }
923 else {
924 /* No more completion port available. Use synchronous IO. */
925 result = gskit_status(data, gsk_secure_soc_init(BACKEND->handle),
926 "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
927 if(!result) {
928 connssl->connecting_state = ssl_connect_3;
929 return CURLE_OK;
930 }
931 }
932 }
933
934 /* Error: rollback. */
935 close_one(connssl, data, conn, sockindex);
936 return result;
937}
938
939
940static CURLcode gskit_connect_step2(struct Curl_cfilter *cf,
941 struct Curl_easy *data,
942 bool nonblocking)
943{
944 struct ssl_connect_data *connssl = cf->ctx;
945 Qso_OverlappedIO_t cstat;
946 struct timeval stmv;
947 CURLcode result;
948
949 /* Poll or wait for end of SSL asynchronous handshake. */
950 DEBUGASSERT(BACKEND);
951
952 for(;;) {
953 timediff_t timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
954 stmv.tv_sec = 0;
955 stmv.tv_usec = 0;
956 if(timeout_ms < 0)
957 timeout_ms = 0;
958 switch(QsoWaitForIOCompletion(BACKEND->iocport, &cstat,
959 curlx_mstotv(&stmv, timeout_ms))) {
960 case 1: /* Operation complete. */
961 break;
962 case -1: /* An error occurred: handshake still in progress. */
963 if(errno == EINTR) {
964 if(nonblocking)
965 return CURLE_OK;
966 continue; /* Retry. */
967 }
968 if(errno != ETIME) {
969 char buffer[STRERROR_LEN];
970 failf(data, "QsoWaitForIOCompletion() I/O error: %s",
971 Curl_strerror(errno, buffer, sizeof(buffer)));
972 cancel_async_handshake(cf, data);
973 close_async_handshake(connssl);
974 return CURLE_SSL_CONNECT_ERROR;
975 }
976 /* FALL INTO... */
977 case 0: /* Handshake in progress, timeout occurred. */
978 if(nonblocking)
979 return CURLE_OK;
980 cancel_async_handshake(cf, data);
981 close_async_handshake(connssl);
982 return CURLE_OPERATION_TIMEDOUT;
983 }
984 break;
985 }
986 result = gskit_status(data, cstat.returnValue, "SSL handshake",
987 CURLE_SSL_CONNECT_ERROR);
988 if(!result)
989 connssl->connecting_state = ssl_connect_3;
990 close_async_handshake(connssl);
991 return result;
992}
993
994
995static CURLcode gskit_connect_step3(struct Curl_cfilter *cf,
996 struct Curl_easy *data)
997{
998 struct ssl_connect_data *connssl = cf->ctx;
999 const gsk_cert_data_elem *cdev;
1000 int cdec;
1001 const gsk_cert_data_elem *p;
1002 const char *cert = (const char *) NULL;
1003 const char *certend = (const char *) NULL;
1004 const char *ptr;
1005 CURLcode result;
1006
1007 /* SSL handshake done: gather certificate info and verify host. */
1008 DEBUGASSERT(BACKEND);
1009
1010 if(gskit_status(data, gsk_attribute_get_cert_info(BACKEND->handle,
1011 GSK_PARTNER_CERT_INFO,
1012 &cdev, &cdec),
1013 "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
1014 CURLE_OK) {
1015 int i;
1016
1017 infof(data, "Server certificate:");
1018 p = cdev;
1019 for(i = 0; i++ < cdec; p++)
1020 switch(p->cert_data_id) {
1021 case CERT_BODY_DER:
1022 cert = p->cert_data_p;
1023 certend = cert + cdev->cert_data_l;
1024 break;
1025 case CERT_DN_PRINTABLE:
1026 infof(data, "\t subject: %.*s", p->cert_data_l, p->cert_data_p);
1027 break;
1028 case CERT_ISSUER_DN_PRINTABLE:
1029 infof(data, "\t issuer: %.*s", p->cert_data_l, p->cert_data_p);
1030 break;
1031 case CERT_VALID_FROM:
1032 infof(data, "\t start date: %.*s", p->cert_data_l, p->cert_data_p);
1033 break;
1034 case CERT_VALID_TO:
1035 infof(data, "\t expire date: %.*s", p->cert_data_l, p->cert_data_p);
1036 break;
1037 }
1038 }
1039
1040 /* Verify host. */
1041 result = Curl_verifyhost(cf, data, cert, certend);
1042 if(result)
1043 return result;
1044
1045 /* The only place GSKit can get the whole CA chain is a validation
1046 callback where no user data pointer is available. Therefore it's not
1047 possible to copy this chain into our structures for CAINFO.
1048 However the server certificate may be available, thus we can return
1049 info about it. */
1050 if(data->set.ssl.certinfo) {
1051 result = Curl_ssl_init_certinfo(data, 1);
1052 if(result)
1053 return result;
1054
1055 if(cert) {
1056 result = Curl_extract_certinfo(data, 0, cert, certend);
1057 if(result)
1058 return result;
1059 }
1060 }
1061
1062 /* Check pinned public key. */
1063 ptr = Curl_ssl_cf_is_proxy(cf)?
1064 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
1065 data->set.str[STRING_SSL_PINNEDPUBLICKEY];
1066 if(!result && ptr) {
1067 struct Curl_X509certificate x509;
1068 struct Curl_asn1Element *p;
1069
1070 memset(&x509, 0, sizeof(x509));
1071 if(Curl_parseX509(&x509, cert, certend))
1072 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1073 p = &x509.subjectPublicKeyInfo;
1074 result = Curl_pin_peer_pubkey(data, ptr, p->header, p->end - p->header);
1075 if(result) {
1076 failf(data, "SSL: public key does not match pinned public key");
1077 return result;
1078 }
1079 }
1080
1081 connssl->connecting_state = ssl_connect_done;
1082 return CURLE_OK;
1083}
1084
1085
1086static CURLcode gskit_connect_common(struct Curl_cfilter *cf,
1087 struct Curl_easy *data,
1088 bool nonblocking, bool *done)
1089{
1090 struct ssl_connect_data *connssl = cf->ctx;
1091 timediff_t timeout_ms;
1092 CURLcode result = CURLE_OK;
1093
1094 *done = connssl->state == ssl_connection_complete;
1095 if(*done)
1096 return CURLE_OK;
1097
1098 /* Step 1: create session, start handshake. */
1099 if(connssl->connecting_state == ssl_connect_1) {
1100 /* check allowed time left */
1101 timeout_ms = Curl_timeleft(data, NULL, TRUE);
1102
1103 if(timeout_ms < 0) {
1104 /* no need to continue if time already is up */
1105 failf(data, "SSL connection timeout");
1106 result = CURLE_OPERATION_TIMEDOUT;
1107 }
1108 else
1109 result = gskit_connect_step1(cf, data);
1110 }
1111
1112 /* Handle handshake pipelining. */
1113 if(!result)
1114 if(pipe_ssloverssl(cf, SOS_READ | SOS_WRITE) < 0)
1115 result = CURLE_SSL_CONNECT_ERROR;
1116
1117 /* Step 2: check if handshake is over. */
1118 if(!result && connssl->connecting_state == ssl_connect_2) {
1119 /* check allowed time left */
1120 timeout_ms = Curl_timeleft(data, NULL, TRUE);
1121
1122 if(timeout_ms < 0) {
1123 /* no need to continue if time already is up */
1124 failf(data, "SSL connection timeout");
1125 result = CURLE_OPERATION_TIMEDOUT;
1126 }
1127 else
1128 result = gskit_connect_step2(cf, data, nonblocking);
1129 }
1130
1131 /* Handle handshake pipelining. */
1132 if(!result)
1133 if(pipe_ssloverssl(cf, SOS_READ | SOS_WRITE) < 0)
1134 result = CURLE_SSL_CONNECT_ERROR;
1135
1136 /* Step 3: gather certificate info, verify host. */
1137 if(!result && connssl->connecting_state == ssl_connect_3)
1138 result = gskit_connect_step3(cf, data);
1139
1140 if(result)
1141 close_one(connssl, data, conn, sockindex);
1142 else if(connssl->connecting_state == ssl_connect_done) {
1143 connssl->state = ssl_connection_complete;
1144 connssl->connecting_state = ssl_connect_1;
1145 *done = TRUE;
1146 }
1147
1148 return result;
1149}
1150
1151
1152static CURLcode gskit_connect_nonblocking(struct Curl_cfilter *cf,
1153 struct Curl_easy *data,
1154 bool *done)
1155{
1156 struct ssl_connect_data *connssl = cf->ctx;
1157 CURLcode result;
1158
1159 result = gskit_connect_common(cf, data, TRUE, done);
1160 if(*done || result)
1161 connssl->connecting_state = ssl_connect_1;
1162 return result;
1163}
1164
1165
1166static CURLcode gskit_connect(struct Curl_cfilter *cf,
1167 struct Curl_easy *data)
1168{
1169 struct ssl_connect_data *connssl = cf->ctx;
1170 CURLcode result;
1171 bool done;
1172
1173 connssl->connecting_state = ssl_connect_1;
1174 result = gskit_connect_common(cf, data, FALSE, &done);
1175 if(result)
1176 return result;
1177
1178 DEBUGASSERT(done);
1179
1180 return CURLE_OK;
1181}
1182
1183
1184static void gskit_close(struct Curl_cfilter *cf, struct Curl_easy *data)
1185{
1186 close_one(cf, data);
1187}
1188
1189
1190static int gskit_shutdown(struct Curl_cfilter *cf,
1191 struct Curl_easy *data)
1192{
1193 struct ssl_connect_data *connssl = cf->ctx;
1194 int what;
1195 int rc;
1196 char buf[120];
1197 int loop = 10; /* don't get stuck */
1198
1199 DEBUGASSERT(BACKEND);
1200
1201 if(!BACKEND->handle)
1202 return 0;
1203
1204#ifndef CURL_DISABLE_FTP
1205 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
1206 return 0;
1207#endif
1208
1209 close_one(cf, data);
1210 rc = 0;
1211 what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
1212 SSL_SHUTDOWN_TIMEOUT);
1213
1214 while(loop--) {
1215 ssize_t nread;
1216
1217 if(what < 0) {
1218 /* anything that gets here is fatally bad */
1219 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1220 rc = -1;
1221 break;
1222 }
1223
1224 if(!what) { /* timeout */
1225 failf(data, "SSL shutdown timeout");
1226 break;
1227 }
1228
1229 /* Something to read, let's do it and hope that it is the close
1230 notify alert from the server. No way to gsk_secure_soc_read() now, so
1231 use read(). */
1232
1233 nread = read(Curl_conn_cf_get_socket(cf, data), buf, sizeof(buf));
1234
1235 if(nread < 0) {
1236 char buffer[STRERROR_LEN];
1237 failf(data, "read: %s", Curl_strerror(errno, buffer, sizeof(buffer)));
1238 rc = -1;
1239 }
1240
1241 if(nread <= 0)
1242 break;
1243
1244 what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data), 0);
1245 }
1246
1247 return rc;
1248}
1249
1250
1251static size_t gskit_version(char *buffer, size_t size)
1252{
1253 return msnprintf(buffer, size, "GSKit");
1254}
1255
1256
1257static int gskit_check_cxn(struct Curl_cfilter *cf,
1258 struct Curl_easy *data)
1259{
1260 struct ssl_connect_data *connssl = cf->ctx;
1261 int err;
1262 int errlen;
1263
1264 (void)data;
1265 /* The only thing that can be tested here is at the socket level. */
1266 DEBUGASSERT(BACKEND);
1267
1268 if(!BACKEND->handle)
1269 return 0; /* connection has been closed */
1270
1271 err = 0;
1272 errlen = sizeof(err);
1273
1274 if(getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR,
1275 (unsigned char *) &err, &errlen) ||
1276 errlen != sizeof(err) || err)
1277 return 0; /* connection has been closed */
1278
1279 return -1; /* connection status unknown */
1280}
1281
1282static void *gskit_get_internals(struct ssl_connect_data *connssl,
1283 CURLINFO info UNUSED_PARAM)
1284{
1285 (void)info;
1286 DEBUGASSERT(BACKEND);
1287 return BACKEND->handle;
1288}
1289
1290const struct Curl_ssl Curl_ssl_gskit = {
1291 { CURLSSLBACKEND_GSKIT, "gskit" }, /* info */
1292
1293 SSLSUPP_CERTINFO |
1294 SSLSUPP_PINNEDPUBKEY,
1295
1296 sizeof(struct ssl_backend_data),
1297
1298 gskit_init, /* init */
1299 gskit_cleanup, /* cleanup */
1300 gskit_version, /* version */
1301 gskit_check_cxn, /* check_cxn */
1302 gskit_shutdown, /* shutdown */
1303 Curl_none_data_pending, /* data_pending */
1304 Curl_none_random, /* random */
1305 Curl_none_cert_status_request, /* cert_status_request */
1306 gskit_connect, /* connect */
1307 gskit_connect_nonblocking, /* connect_nonblocking */
1308 Curl_ssl_get_select_socks, /* getsock */
1309 gskit_get_internals, /* get_internals */
1310 gskit_close, /* close_one */
1311 Curl_none_close_all, /* close_all */
1312 /* No session handling for GSKit */
1313 Curl_none_session_free, /* session_free */
1314 Curl_none_set_engine, /* set_engine */
1315 Curl_none_set_engine_default, /* set_engine_default */
1316 Curl_none_engines_list, /* engines_list */
1317 Curl_none_false_start, /* false_start */
1318 NULL, /* sha256sum */
1319 NULL, /* associate_connection */
1320 NULL, /* disassociate_connection */
1321 NULL, /* free_multi_ssl_backend_data */
1322 gskit_recv, /* recv decrypted data */
1323 gskit_send, /* send data to encrypt */
1324};
1325
1326#endif /* USE_GSKIT */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette