]> granicus.if.org Git - curl/commitdiff
Implemented the parts of Patrick Monnerat's OS/400 patch that introduces
authorDaniel Stenberg <daniel@haxx.se>
Mon, 23 Jul 2007 21:46:26 +0000 (21:46 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 23 Jul 2007 21:46:26 +0000 (21:46 +0000)
support for the OS/400 Secure Sockets Layer library

CHANGES
RELEASE-NOTES
lib/Makefile.inc
lib/qssl.c [new file with mode: 0644]
lib/qssl.h [new file with mode: 0644]
lib/sslgen.c

diff --git a/CHANGES b/CHANGES
index b88683ef683860342e49776ae1e8b6463f321395..9bd83b9853de1ffc6d78f4bee6f244a859700d57 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,10 @@
 
                                   Changelog
 
+Daniel S (23 July 2007)
+- Implemented the parts of Patrick Monnerat's OS/400 patch that introduces
+  support for the OS/400 Secure Sockets Layer library.
+
 Dan F (23 July 2007)
 - Implemented only the parts of Patrick Monnerat's OS/400 patch that renamed
   some few internal identifiers to avoid conflicts, which could be useful on
index 48b4365b5734854e121590393cddcaa39848cec3..66ea4130694bf778c01ca6f4a86b5a400c6d2b0f 100644 (file)
@@ -11,7 +11,7 @@ Curl and libcurl 7.16.5
 
 This release includes the following changes:
  
- o 
+ o support for OS/400 Secure Sockets Layer library
 
 This release includes the following bugfixes:
 
index 714b15f8addb617f56d32a72692f5981ab232962..759c923d55352f1e346a8b8805030197f5530445 100644 (file)
@@ -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 (file)
index 0000000..9e2aee7
--- /dev/null
@@ -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 (file)
index 0000000..61ff80a
--- /dev/null
@@ -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
index faabeeb0d19da36c8d0ff605299bcca710c71929..56f626ac2ccdc99fb4bb069b383aeb1e3cba1d9b 100644 (file)
@@ -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"
@@ -171,9 +172,13 @@ int Curl_ssl_init(void)
 #else
 #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 */
@@ -239,11 +253,16 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
 #ifdef USE_NSS
   *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;
   }
 }
@@ -434,9 +464,14 @@ CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
 #ifdef USE_GNUTLS
     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 */
   }
@@ -461,11 +496,18 @@ CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine)
   (void)data;
   (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 */
@@ -487,10 +529,16 @@ CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data)
   /* A no-op for NSS */
   (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 */
@@ -512,9 +560,15 @@ struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)
    * would just confuse things */
   (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 */
@@ -534,12 +588,16 @@ ssize_t Curl_ssl_send(struct connectdata *conn,
 #else
 #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 */
@@ -631,10 +693,14 @@ size_t Curl_ssl_version(char *buffer, size_t size)
 #else
 #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 */
@@ -656,10 +722,14 @@ int Curl_ssl_check_cxn(struct connectdata *conn)
 #else
 #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 */
 }