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


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:09