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