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