• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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