diff options
| author | Daniel Stenberg <daniel@haxx.se> | 2007-07-23 21:46:26 +0000 | 
|---|---|---|
| committer | Daniel Stenberg <daniel@haxx.se> | 2007-07-23 21:46:26 +0000 | 
| commit | b3461bab1df4221abf74d7c159cf5c719b1b9744 (patch) | |
| tree | 380600bf628b97ceb351bccb4a3918989eaa4904 /lib | |
| parent | 5ecd56d9646c2adcc70c0369fb6196f62ecc62f4 (diff) | |
Implemented the parts of Patrick Monnerat's OS/400 patch that introduces
support for the OS/400 Secure Sockets Layer library
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile.inc | 28 | ||||
| -rw-r--r-- | lib/qssl.c | 496 | ||||
| -rw-r--r-- | lib/qssl.h | 52 | ||||
| -rw-r--r-- | lib/sslgen.c | 70 | 
4 files changed, 632 insertions, 14 deletions
| diff --git a/lib/Makefile.inc b/lib/Makefile.inc index 714b15f8a..759c923d5 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -1,23 +1,23 @@  # ./lib/Makefile.inc -  +  CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c	\    cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c	\    ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c	\    netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c	\ -  krb5.c \ -  memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c multi.c	\ -  content_encoding.c share.c http_digest.c md5.c http_negotiate.c	\ -  http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c	\ -  hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c	\ -  select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.c +  krb5.c memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c	\ +  multi.c content_encoding.c share.c http_digest.c md5.c		\ +  http_negotiate.c http_ntlm.c inet_pton.c strtoofft.c strerror.c	\ +  hostares.c hostasyn.c hostip4.c hostip6.c hostsyn.c hostthre.c	\ +  inet_ntop.c parsedate.c select.c gtls.c sslgen.c tftp.c splay.c	\ +  strdup.c socks.c ssh.c nss.c qssl.c  HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h	\    progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h	\    if2ip.h speedcheck.h urldata.h ldap.h ssluse.h escape.h telnet.h	\ -  getinfo.h strequal.h krb4.h memdebug.h inet_ntoa_r.h \ -  http_chunks.h strtok.h connect.h llist.h hash.h content_encoding.h	\ -  share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h	\ -  inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h	\ -  setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h   \ -  gtls.h tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h  \ -  nssg.h +  getinfo.h strequal.h krb4.h memdebug.h inet_ntoa_r.h http_chunks.h	\ +  strtok.h connect.h llist.h hash.h content_encoding.h share.h md5.h	\ +  http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h inet_pton.h	\ +  strtoofft.h strerror.h inet_ntop.h curlx.h memory.h setup.h		\ +  transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h gtls.h	\ +  tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h nssg.h	\ +  qssl.h diff --git a/lib/qssl.c b/lib/qssl.c new file mode 100644 index 000000000..9e2aee767 --- /dev/null +++ b/lib/qssl.c @@ -0,0 +1,496 @@ +/*************************************************************************** + *                                  _   _ ____  _ + *  Project                     ___| | | |  _ \| | + *                             / __| | | | |_) | | + *                            | (__| |_| |  _ <| |___ + *                             \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id$ + ***************************************************************************/ + +#include "setup.h" + +#ifdef USE_QSOSSL +#include <qsossl.h> +#include <errno.h> +#include <string.h> + +#include <curl/curl.h> +#include "urldata.h" +#include "sendf.h" +#include "qssl.h" +#include "sslgen.h" +#include "connect.h" /* for the connect timeout */ +#include "select.h" +#include "memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + + +static bool qsossl_inited = FALSE; + + +int Curl_qsossl_init(void) + +{ +  /* Nothing to do here. We must have connection data to initialize ssl, so +   * defer. +   */ + +  return 1; +} + + +void Curl_qsossl_cleanup(void) + +{ +  /* Nothing to do. */ +} + + +static CURLcode Curl_qsossl_init_session(struct SessionHandle * data) + +{ +  int rc; +  char * certname; +  SSLInit initstr; +  SSLInitApp initappstr; + +  /* Initialize the job for SSL according to the current parameters. +   * QsoSSL offers two ways to do it: SSL_Init_Application() that uses an +   *  application identifier to select certificates in the main certificate +   *  store, and SSL_Init() that uses named keyring files and a password. +   * It is not possible to have different keyrings for the CAs and the +   *  local certificate. We thus use the certificate name to identify the +   *  keyring if given, else the CA file name. +   * If the key file name is given, it is taken as the password for the +   *  keyring in certificate file. +   * We first try to SSL_Init_Application(), then SSL_Init() if it failed. +   */ + +  certname = data->set.cert; + +  if (!certname) { +    certname = data->set.ssl.CAfile; + +    if (!certname) +      return CURLE_OK;          /* Use previous setup. */ +    } + +  memset((char *) &initappstr, 0, sizeof initappstr); +  initappstr.applicationID = certname; +  initappstr.applicationIDLen = strlen(certname); +  initappstr.protocol = SSL_VERSION_CURRENT; +  initappstr.sessionType = SSL_REGISTERED_AS_CLIENT; +  rc = SSL_Init_Application(&initappstr); + +  if (rc == SSL_ERROR_NOT_REGISTERED) { +    initstr.keyringFileName = certname; +    initstr.keyringPassword = data->set.key; +    initstr.cipherSuiteList = NULL;    /* Use default. */ +    initstr.cipherSuiteListLen = 0; +    rc = SSL_Init(&initstr); +    } + +  switch (rc) { + +  case 0:                             /* No error. */ +    break; + +  case SSL_ERROR_IO: +    failf(data, "SSL_Init() I/O error: %s\n", strerror(errno)); +    return CURLE_SSL_CONNECT_ERROR; + +  case SSL_ERROR_BAD_CIPHER_SUITE: +    return CURLE_SSL_CIPHER; + +  case SSL_ERROR_KEYPASSWORD_EXPIRED: +  case SSL_ERROR_NOT_REGISTERED: +    return CURLE_SSL_CONNECT_ERROR; + +  case SSL_ERROR_NO_KEYRING: +    return CURLE_SSL_CACERT; + +  case SSL_ERROR_CERT_EXPIRED: +    return CURLE_SSL_CERTPROBLEM; + +  default: +    failf(data, "SSL_Init(): %s\n", SSL_Strerror(rc, NULL)); +    return CURLE_SSL_CONNECT_ERROR; +  } + +  return CURLE_OK; +} + + +static CURLcode Curl_qsossl_create(struct connectdata * conn, int sockindex) + +{ +  SSLHandle * h; +  struct ssl_connect_data * connssl = &conn->ssl[sockindex]; + +  h = SSL_Create(conn->sock[sockindex], SSL_ENCRYPT); + +  if (!h) { +    failf(conn->data, "SSL_Create() I/O error: %s\n", strerror(errno)); +    return CURLE_SSL_CONNECT_ERROR; +    } + +  connssl->handle = h; +  return CURLE_OK; +} + + +static int Curl_qsossl_trap_cert(SSLHandle * h) + +{ +	return 1;       /* Accept certificate. */ +} + + +static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex) + +{ +  int rc; +  struct SessionHandle * data = conn->data; +  struct ssl_connect_data * connssl = &conn->ssl[sockindex]; +  SSLHandle * h = connssl->handle; +  long timeout_ms; + +  h->exitPgm = NULL; + +  if (!data->set.ssl.verifyhost) +    h->exitPgm = Curl_qsossl_trap_cert; + +  if (data->set.connecttimeout) { +    timeout_ms = data->set.connecttimeout; + +    if (data->set.timeout) +      if (timeout_ms > data->set.timeout) +        timeout_ms = data->set.timeout; +    } +  else if (data->set.timeout) +    timeout_ms = data->set.timeout; +  else +    timeout_ms = DEFAULT_CONNECT_TIMEOUT; + +  /* SSL_Handshake() timeout resolution is second, so round up. */ + +  h->timeout = (timeout_ms + 1000 - 1) / 1000; + +  /* Set-up protocol. */ + +  switch(data->set.ssl.version) { + +  default: +  case CURL_SSLVERSION_DEFAULT: +    h->protocol = SSL_VERSION_CURRENT; +    break; + +  case CURL_SSLVERSION_TLSv1: +    h->protocol = TLS_VERSION_1; +    break; + +  case CURL_SSLVERSION_SSLv2: +    h->protocol = SSL_VERSION_2; +    break; + +  case CURL_SSLVERSION_SSLv3: +    h->protocol = SSL_VERSION_3; +    break; +  } + +  rc = SSL_Handshake(h, SSL_HANDSHAKE_AS_CLIENT); + +  switch (rc) { + +  case 0:                             /* No error. */ +    break; + +  case SSL_ERROR_BAD_CERTIFICATE: +  case SSL_ERROR_BAD_CERT_SIG: +  case SSL_ERROR_NOT_TRUSTED_ROOT: +    return CURLE_SSL_PEER_CERTIFICATE; + +  case SSL_ERROR_BAD_CIPHER_SUITE: +  case SSL_ERROR_NO_CIPHERS: +    return CURLE_SSL_CIPHER; + +  case SSL_ERROR_CERTIFICATE_REJECTED: +  case SSL_ERROR_CERT_EXPIRED: +  case SSL_ERROR_NO_CERTIFICATE: +    return CURLE_SSL_CERTPROBLEM; + +  case SSL_ERROR_IO: +    failf(data, "SSL_Handshake(): %s\n", SSL_Strerror(rc, NULL)); +    return CURLE_SSL_CONNECT_ERROR; + +  default: +    failf(data, "SSL_Init(): %s\n", SSL_Strerror(rc, NULL)); +    return CURLE_SSL_CONNECT_ERROR; +  } + +  return CURLE_OK; +} + + +CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex) + +{ +  struct SessionHandle * data = conn->data; +  struct ssl_connect_data * connssl = &conn->ssl[sockindex]; +  int rc; + +  rc = Curl_qsossl_init_session(data); + +  if (rc == CURLE_OK) { +    rc = Curl_qsossl_create(conn, sockindex); + +    if (rc == CURLE_OK) +      rc = Curl_qsossl_handshake(conn, sockindex); +    else { +      SSL_Destroy(connssl->handle); +      connssl->handle = NULL; +      connssl->use = FALSE; +    } +  } + +  return rc; +} + + +static int Curl_qsossl_close_one(struct ssl_connect_data * conn, +                                 struct SessionHandle * data) + +{ +  int rc; + +  if (!conn->handle) +    return 0; + +  rc = SSL_Destroy(conn->handle); + +  if(rc) { +    if (rc == SSL_ERROR_IO) { +      failf(data, "SSL_Destroy() I/O error: %s\n", strerror(errno)); +      return -1; +    } + +    /* An SSL error. */ +    failf(data, "SSL_Destroy() returned error %d\n", SSL_Strerror(rc, NULL)); +    return -1; +  } + +  conn->use = FALSE;    /* get back to ordinary socket usage */ +  conn->handle = NULL; +  return 0; +} + + +void Curl_qsossl_close(struct connectdata * conn) + +{ +  struct SessionHandle * data = conn->data; +  struct ssl_connect_data * connssl = conn->ssl; + +  if(connssl->use) +    (void) Curl_qsossl_close_one(connssl, data); + +  connssl++; + +  if(connssl->use) +    (void) Curl_qsossl_close_one(connssl, data); +} + + +int Curl_qsossl_close_all(struct SessionHandle * data) + +{ +  /* Unimplemented. */ +  (void) data; +  return 0; +} + + +int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex) + +{ +  struct ssl_connect_data * connssl = &conn->ssl[sockindex]; +  struct SessionHandle *data = conn->data; +  ssize_t nread; +  int what; +  int rc; +  char buf[120]; + +  if (!connssl->handle) +    return 0; + +  if (data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) +    return 0; + +  if (Curl_qsossl_close_one(connssl, data)) +    return -1; + +  rc = 0; + +  what = Curl_socket_ready(conn->sock[sockindex], +                           CURL_SOCKET_BAD, SSL_SHUTDOWN_TIMEOUT); + +  for (;;) { +    if (what < 0) { +      /* anything that gets here is fatally bad */ +      failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); +      rc = -1; +      break; +    } + +    if (!what) {                                /* timeout */ +      failf(data, "SSL shutdown timeout"); +      break; +    } + +    /* Something to read, let's do it and hope that it is the close +       notify alert from the server. No way to SSL_Read now, so use read(). */ + +    nread = read(conn->sock[sockindex], buf, sizeof(buf)); + +    if (nread < 0) { +      failf(data, "read: %s\n", strerror(errno)); +      rc = -1; +    } + +    if (nread <= 0) +      break; + +    what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0); +  } + +  return rc; +} + + +ssize_t Curl_qsossl_send(struct connectdata * conn, int sockindex, void * mem, +                         size_t len) + +{ +  /* SSL_Write() is said to return 'int' while write() and send() returns +     'size_t' */ +  int rc; + +  rc = SSL_Write(conn->ssl[sockindex].handle, mem, (int) len); + +  if(rc < 0) { +    switch(rc) { + +    case SSL_ERROR_BAD_STATE: +      /* The operation did not complete; the same SSL I/O function +         should be called again later. This is basicly an EWOULDBLOCK +         equivalent. */ +      return 0; + +    case SSL_ERROR_IO: +      switch (errno) { +      case EWOULDBLOCK: +      case EINTR: +        return 0; +        } + +      failf(conn->data, "SSL_Write() I/O error: %s\n", strerror(errno)); +      return -1; +    } + +    /* An SSL error. */ +    failf(conn->data, "SSL_Write() returned error %d\n", +          SSL_Strerror(rc, NULL)); +    return -1; +  } + +  return (ssize_t) rc; /* number of bytes */ +} + + +ssize_t Curl_qsossl_recv(struct connectdata * conn, int num, char * buf, +                         size_t buffersize, bool * wouldblock) + +{ +  char error_buffer[120]; /* OpenSSL documents that this must be at +                             least 120 bytes long. */ +  unsigned long sslerror; +  int nread; + +  nread = SSL_Read(conn->ssl[num].handle, buf, (int) buffersize); +  *wouldblock = FALSE; + +  if(nread < 0) { +    /* failed SSL_read */ + +    switch (nread) { + +    case SSL_ERROR_BAD_STATE: +      /* there's data pending, re-invoke SSL_Read(). */ +      *wouldblock = TRUE; +      return -1; /* basically EWOULDBLOCK */ + +    case SSL_ERROR_IO: +      switch (errno) { +      case EWOULDBLOCK: +	*wouldblock = TRUE; +        return -1; +        } + +      failf(conn->data, "SSL_Read() I/O error: %s\n", strerror(errno)); +      return -1; + +    default: +      failf(conn->data, "SSL read error: %s\n", SSL_Strerror(nread, NULL)); +      return -1; +    } +  } +  return (ssize_t) nread; +} + + +size_t Curl_qsossl_version(char * buffer, size_t size) + +{ +  strncpy(buffer, "IBM OS/400 SSL", size); +  return strlen(buffer); +} + + +int Curl_qsossl_check_cxn(struct connectdata * cxn) + +{ +  int err; +  int errlen; + +  /* The only thing that can be tested here is at the socket level. */ + +  if (!cxn->ssl[FIRSTSOCKET].handle) +    return 0; /* connection has been closed */ + +  err = 0; +  errlen = sizeof err; + +  if (getsockopt(cxn->sock[FIRSTSOCKET], SOL_SOCKET, SO_ERROR, +                 (unsigned char *) &err, &errlen) || +      errlen != sizeof err || err) +    return 0; /* connection has been closed */ + +  return -1;  /* connection status unknown */ +} + +#endif /* USE_QSOSSL */ diff --git a/lib/qssl.h b/lib/qssl.h new file mode 100644 index 000000000..61ff80adf --- /dev/null +++ b/lib/qssl.h @@ -0,0 +1,52 @@ +#ifndef __QSSL_H +#define __QSSL_H +/*************************************************************************** + *                                  _   _ ____  _ + *  Project                     ___| | | |  _ \| | + *                             / __| | | | |_) | | + *                            | (__| |_| |  _ <| |___ + *                             \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * $Id$ + ***************************************************************************/ + +/* + * This header should only be needed to get included by sslgen.c and qssl.c + */ + +#include "urldata.h" + +int Curl_qsossl_init(void); +void Curl_qsossl_cleanup(void); +CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex); +void Curl_qsossl_close(struct connectdata * conn); /* close a SSL connection */ +int Curl_qsossl_close_all(struct SessionHandle * data); +int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex); + +ssize_t Curl_qsossl_send(struct connectdata * conn, +                         int sockindex, +                         void * mem, +                         size_t len); +ssize_t Curl_qsossl_recv(struct connectdata * conn, /* connection data */ +                         int num,                   /* socketindex */ +                         char * buf,                /* store read data here */ +                         size_t buffersize,         /* max amount to read */ +                         bool * wouldblock); + +size_t Curl_qsossl_version(char * buffer, size_t size); +int Curl_qsossl_check_cxn(struct connectdata * cxn); + +#endif diff --git a/lib/sslgen.c b/lib/sslgen.c index faabeeb0d..56f626ac2 100644 --- a/lib/sslgen.c +++ b/lib/sslgen.c @@ -52,6 +52,7 @@  #include "ssluse.h" /* OpenSSL versions */  #include "gtls.h"   /* GnuTLS versions */  #include "nssg.h"   /* NSS versions */ +#include "qssl.h"   /* QSOSSL versions */  #include "sendf.h"  #include "strequal.h"  #include "url.h" @@ -172,8 +173,12 @@ int Curl_ssl_init(void)  #ifdef USE_NSS    return Curl_nss_init();  #else +#ifdef USE_QSOSSL +  return Curl_qsossl_init(); +#else    /* no SSL support */    return 1; +#endif /* USE_QSOSSL */  #endif /* USE_NSS */  #endif /* USE_GNUTLS */  #endif /* USE_SSLEAY */ @@ -190,8 +195,13 @@ void Curl_ssl_cleanup(void)  #else  #ifdef USE_GNUTLS      Curl_gtls_cleanup(); +#else  #ifdef USE_NSS      Curl_nss_cleanup(); +#else +#ifdef USE_QSOSSL +    Curl_qsossl_cleanup(); +#endif /* USE_QSOSSL */  #endif /* USE_NSS */  #endif /* USE_GNUTLS */  #endif /* USE_SSLEAY */ @@ -214,6 +224,10 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex)  #else  #ifdef USE_NSS    return Curl_nss_connect(conn, sockindex); +#else +#ifdef USE_QSOSSL +  return Curl_qsossl_connect(conn, sockindex); +#endif /* USE_QSOSSL */  #endif /* USE_NSS */  #endif /* USE_GNUTLS */  #endif /* USE_SSLEAY */ @@ -240,10 +254,15 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,    *done = TRUE; /* fallback to BLOCKING */    return Curl_nss_connect(conn, sockindex);  #else +#ifdef USE_QSOSSL +  *done = TRUE; /* fallback to BLOCKING */ +  return Curl_qsossl_connect(conn, sockindex); +#else    /* not implemented!       fallback to BLOCKING call. */    *done = TRUE;    return Curl_ssl_connect(conn, sockindex); +#endif /* USE_QSOSSL */  #endif /* USE_NSS */  #endif /* USE_SSLEAY */  } @@ -302,9 +321,13 @@ static int kill_session(struct curl_ssl_session *session)  #ifdef USE_GNUTLS      Curl_gtls_session_free(session->sessionid);  #else +#ifdef USE_QSOSSL +    /* No session handling for QsoSSL. */ +#else  #ifdef USE_NSS      /* NSS has its own session ID cache */  #endif /* USE_NSS */ +#endif /* USE_QSOSSL */  #endif /* USE_GNUTLS */  #endif /* USE_SSLEAY */      session->sessionid=NULL; @@ -400,6 +423,10 @@ void Curl_ssl_close_all(struct SessionHandle *data)  #else  #ifdef USE_NSS    Curl_nss_close_all(data); +#else +#ifdef USE_QSOSSL +  Curl_qsossl_close_all(data); +#endif /* USE_QSOSSL */  #endif /* USE_NSS */  #endif /* USE_GNUTLS */  #endif /* USE_SSLEAY */ @@ -420,6 +447,9 @@ void Curl_ssl_close(struct connectdata *conn)  #ifdef USE_NSS      Curl_nss_close(conn);  #endif /* USE_NSS */ +#ifdef USE_QSOSSL +    Curl_qsossl_close(conn); +#endif /* USE_QSOSSL */      conn->ssl[FIRSTSOCKET].use = FALSE;    }  } @@ -435,8 +465,13 @@ CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)      if(Curl_gtls_shutdown(conn, sockindex))        return CURLE_SSL_SHUTDOWN_FAILED;  #else +#ifdef USE_QSOSSL +    if(Curl_qsossl_shutdown(conn, sockindex)) +      return CURLE_SSL_SHUTDOWN_FAILED; +#else      (void)conn;      (void)sockindex; +#endif /* USE_QSOSSL */  #endif /* USE_GNUTLS */  #endif /* USE_SSLEAY */    } @@ -462,10 +497,17 @@ CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine)    (void)engine;    return CURLE_FAILED_INIT;  #else +#ifdef USE_QSOSSL +  /* QSOSSL doesn't set an engine this way */ +  (void)data; +  (void)engine; +  return CURLE_FAILED_INIT; +#else    /* no SSL layer */    (void)data;    (void)engine;    return CURLE_FAILED_INIT; +#endif /* USE_QSOSSL */  #endif /* USE_NSS */  #endif /* USE_GNUTLS */  #endif /* USE_SSLEAY */ @@ -488,9 +530,15 @@ CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data)    (void)data;    return CURLE_FAILED_INIT;  #else +#ifdef USE_QSOSSL +  /* A no-op for QSOSSL */ +  (void)data; +  return CURLE_FAILED_INIT; +#else    /* No SSL layer */    (void)data;    return CURLE_FAILED_INIT; +#endif /* USE_QSOSSL */  #endif /* USE_NSS */  #endif /* USE_GNUTLS */  #endif /* USE_SSLEAY */ @@ -513,8 +561,14 @@ struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)    (void)data;    return NULL;  #else +#ifdef USE_QSOSSL +  /* No engine support in QSOSSL. */ +  (void)data; +  return NULL; +#else    (void)data;    return NULL; +#endif /* USE_QSOSSL */  #endif /* USE_NSS */  #endif /* USE_GNUTLS */  #endif /* USE_SSLEAY */ @@ -535,11 +589,15 @@ ssize_t Curl_ssl_send(struct connectdata *conn,  #ifdef USE_NSS    return Curl_nss_send(conn, sockindex, mem, len);  #else +#ifdef USE_QSOSSL +  return Curl_qsossl_send(conn, sockindex, mem, len); +#else    (void)conn;    (void)sockindex;    (void)mem;    (void)len;    return 0; +#endif /* USE_QSOSSL */  #endif /* USE_NSS */  #endif /* USE_GNUTLS */  #endif /* USE_SSLEAY */ @@ -568,6 +626,10 @@ ssize_t Curl_ssl_recv(struct connectdata *conn, /* connection data */  #else  #ifdef USE_NSS    nread = Curl_nss_recv(conn, sockindex, mem, len, &block); +#else +#ifdef USE_QSOSSL +  nread = Curl_qsossl_recv(conn, sockindex, mem, len, &block); +#endif /* USE_QSOSSL */  #endif /* USE_NSS */  #endif /* USE_GNUTLS */  #endif /* USE_SSLEAY */ @@ -632,9 +694,13 @@ size_t Curl_ssl_version(char *buffer, size_t size)  #ifdef USE_NSS    return Curl_nss_version(buffer, size);  #else +#ifdef USE_QSOSSL +  return Curl_qsossl_version(buffer, size); +#else    (void)buffer;    (void)size;    return 0; /* no SSL support */ +#endif /* USE_QSOSSL */  #endif /* USE_NSS */  #endif /* USE_GNUTLS */  #endif /* USE_SSLEAY */ @@ -657,9 +723,13 @@ int Curl_ssl_check_cxn(struct connectdata *conn)  #ifdef USE_NSS    return Curl_nss_check_cxn(conn);  #else +#ifdef USE_QSOSSL +  return Curl_qsossl_check_cxn(conn); +#else    (void)conn;    /* TODO: we lack implementation of this for GnuTLS */    return -1; /* connection status unknown */ +#endif /* USE_QSOSSL */  #endif /* USE_NSS */  #endif /* USE_SSLEAY */  } | 
