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