aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPatrick Monnerat <pm@datasphere.ch>2013-07-15 19:00:36 +0200
committerPatrick Monnerat <pm@datasphere.ch>2013-07-15 19:00:36 +0200
commit0eba02fd41263218a0eaedbe65af739a9bb2da63 (patch)
tree9ed6cb8bda345c6dc5b2ceeea00e747b9d425389 /lib
parent464c8693d2f6f2b45b84951feb9414da698206be (diff)
OS400: new SSL backend GSKit
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.inc5
-rw-r--r--lib/config-os400.h3
-rw-r--r--lib/curl_setup.h2
-rw-r--r--lib/gskit.c906
-rw-r--r--lib/gskit.h64
-rw-r--r--lib/hostcheck.c7
-rw-r--r--lib/setup-os400.h92
-rw-r--r--lib/sslgen.c2
-rw-r--r--lib/url.c2
-rw-r--r--lib/urldata.h9
-rw-r--r--lib/x509asn1.c4
-rw-r--r--lib/x509asn1.h4
12 files changed, 1088 insertions, 12 deletions
diff --git a/lib/Makefile.inc b/lib/Makefile.inc
index 0ba39a25f..586d94ad3 100644
--- a/lib/Makefile.inc
+++ b/lib/Makefile.inc
@@ -25,7 +25,8 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
http_proxy.c non-ascii.c asyn-ares.c asyn-thread.c curl_gssapi.c \
curl_ntlm.c curl_ntlm_wb.c curl_ntlm_core.c curl_ntlm_msgs.c \
curl_sasl.c curl_schannel.c curl_multibyte.c curl_darwinssl.c \
- hostcheck.c bundles.c conncache.c pipeline.c dotdot.c x509asn1.c
+ hostcheck.c bundles.c conncache.c pipeline.c dotdot.c x509asn1.c \
+ gskit.c
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
@@ -44,4 +45,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
asyn.h curl_ntlm.h curl_gssapi.h curl_ntlm_wb.h curl_ntlm_core.h \
curl_ntlm_msgs.h curl_sasl.h curl_schannel.h curl_multibyte.h \
curl_darwinssl.h hostcheck.h bundles.h conncache.h curl_setup_once.h \
- multihandle.h setup-vms.h pipeline.h dotdot.h x509asn1.h
+ multihandle.h setup-vms.h pipeline.h dotdot.h x509asn1.h gskit.h
diff --git a/lib/config-os400.h b/lib/config-os400.h
index 4381f9a30..a290fe43d 100644
--- a/lib/config-os400.h
+++ b/lib/config-os400.h
@@ -531,6 +531,9 @@
/* Define to use the QsoSSL package. */
#define USE_QSOSSL
+/* Define to use the GSKit package. */
+#undef USE_GSKIT
+
/* Use the system keyring as the default CA bundle. */
#define CURL_CA_BUNDLE "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB"
diff --git a/lib/curl_setup.h b/lib/curl_setup.h
index a18d085f6..a46a60828 100644
--- a/lib/curl_setup.h
+++ b/lib/curl_setup.h
@@ -617,7 +617,7 @@ int netware_init(void);
#if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS) || \
defined(USE_QSOSSL) || defined(USE_POLARSSL) || defined(USE_AXTLS) || \
defined(USE_CYASSL) || defined(USE_SCHANNEL) || \
- defined(USE_DARWINSSL)
+ defined(USE_DARWINSSL) || defined(USE_GSKIT)
#define USE_SSL /* SSL support has been enabled */
#endif
diff --git a/lib/gskit.c b/lib/gskit.c
new file mode 100644
index 000000000..5cda85b9b
--- /dev/null
+++ b/lib/gskit.c
@@ -0,0 +1,906 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, 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.
+ *
+ ***************************************************************************/
+
+#include "curl_setup.h"
+
+#ifdef USE_GSKIT
+
+#include <gskssl.h>
+#include <qsoasync.h>
+
+/* Some symbols are undefined/unsupported on OS400 versions < V7R1. */
+#ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST
+#define GSK_SSL_EXTN_SERVERNAME_REQUEST 230
+#endif
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#include <curl/curl.h>
+#include "urldata.h"
+#include "sendf.h"
+#include "gskit.h"
+#include "sslgen.h"
+#include "connect.h" /* for the connect timeout */
+#include "select.h"
+#include "strequal.h"
+#include "x509asn1.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
+
+
+/* Supported ciphers. */
+typedef struct {
+ const char * name; /* Cipher name. */
+ const char * gsktoken; /* Corresponding token for GSKit String. */
+ int sslver; /* SSL version. */
+} gskit_cipher;
+
+static const gskit_cipher ciphertable[] = {
+ { "null-md5", "01", CURL_SSLVERSION_SSLv3 },
+ { "null-sha", "02", CURL_SSLVERSION_SSLv3 },
+ { "exp-rc4-md5", "03", CURL_SSLVERSION_SSLv3 },
+ { "rc4-md5", "04", CURL_SSLVERSION_SSLv3 },
+ { "rc4-sha", "05", CURL_SSLVERSION_SSLv3 },
+ { "exp-rc2-cbc-md5", "06", CURL_SSLVERSION_SSLv3 },
+ { "exp-des-cbc-sha", "09", CURL_SSLVERSION_SSLv3 },
+ { "des-cbc3-sha", "0A", CURL_SSLVERSION_SSLv3 },
+ { "aes128-sha", "2F", CURL_SSLVERSION_TLSv1 },
+ { "aes256-sha", "35", CURL_SSLVERSION_TLSv1 },
+ { "rc4-md5", "1", CURL_SSLVERSION_SSLv2 },
+ { "exp-rc4-md5", "2", CURL_SSLVERSION_SSLv2 },
+ { "rc2-md5", "3", CURL_SSLVERSION_SSLv2 },
+ { "exp-rc2-md5", "4", CURL_SSLVERSION_SSLv2 },
+ { "des-cbc-md5", "6", CURL_SSLVERSION_SSLv2 },
+ { "des-cbc3-md5", "7", CURL_SSLVERSION_SSLv2 },
+ { (const char *) NULL, (const char *) NULL, 0 }
+};
+
+
+static bool is_separator(char c)
+{
+ /* Return whether character is a cipher list separator. */
+ switch (c) {
+ case ' ':
+ case '\t':
+ case ':':
+ case ',':
+ case ';':
+ return true;
+ }
+ return false;
+}
+
+
+static CURLcode gskit_status(struct SessionHandle * data, int rc,
+ const char * procname, CURLcode defcode)
+{
+ CURLcode cc;
+
+ /* Process GSKit status and map it to a CURLcode. */
+ switch (rc) {
+ case GSK_OK:
+ case GSK_OS400_ASYNCHRONOUS_SOC_INIT:
+ return CURLE_OK;
+ case GSK_KEYRING_OPEN_ERROR:
+ case GSK_OS400_ERROR_NO_ACCESS:
+ return CURLE_SSL_CACERT_BADFILE;
+ case GSK_INSUFFICIENT_STORAGE:
+ return CURLE_OUT_OF_MEMORY;
+ case GSK_ERROR_BAD_V2_CIPHER:
+ case GSK_ERROR_BAD_V3_CIPHER:
+ case GSK_ERROR_NO_CIPHERS:
+ return CURLE_SSL_CIPHER;
+ case GSK_OS400_ERROR_NOT_TRUSTED_ROOT:
+ case GSK_ERROR_CERT_VALIDATION:
+ return CURLE_PEER_FAILED_VERIFICATION;
+ case GSK_OS400_ERROR_TIMED_OUT:
+ return CURLE_OPERATION_TIMEDOUT;
+ case GSK_WOULD_BLOCK:
+ return CURLE_AGAIN;
+ case GSK_OS400_ERROR_NOT_REGISTERED:
+ break;
+ case GSK_ERROR_IO:
+ switch (errno) {
+ case ENOMEM:
+ return CURLE_OUT_OF_MEMORY;
+ default:
+ failf(data, "%s I/O error: %s", procname, strerror(errno));
+ break;
+ }
+ break;
+ default:
+ failf(data, "%s: %s", procname, gsk_strerror(rc));
+ break;
+ }
+ return defcode;
+}
+
+
+static CURLcode set_enum(struct SessionHandle * data,
+ gsk_handle h, GSK_ENUM_ID id, GSK_ENUM_VALUE value)
+{
+ int rc = gsk_attribute_set_enum(h, id, value);
+
+ switch (rc) {
+ case GSK_OK:
+ return CURLE_OK;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno));
+ break;
+ default:
+ failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc));
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
+static CURLcode set_buffer(struct SessionHandle * data,
+ gsk_handle h, GSK_BUF_ID id, const char * buffer)
+{
+ int rc = gsk_attribute_set_buffer(h, id, buffer, 0);
+
+ switch (rc) {
+ case GSK_OK:
+ return CURLE_OK;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
+ break;
+ default:
+ failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
+static CURLcode set_numeric(struct SessionHandle * data,
+ gsk_handle h, GSK_NUM_ID id, int value)
+{
+ int rc = gsk_attribute_set_numeric_value(h, id, value);
+
+ switch (rc) {
+ case GSK_OK:
+ return CURLE_OK;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_numeric_value() I/O error: %s",
+ strerror(errno));
+ break;
+ default:
+ failf(data, "gsk_attribute_set_numeric_value(): %s", gsk_strerror(rc));
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
+static CURLcode set_callback(struct SessionHandle * data,
+ gsk_handle h, GSK_CALLBACK_ID id, void * info)
+{
+ int rc = gsk_attribute_set_callback(h, id, info);
+
+ switch (rc) {
+ case GSK_OK:
+ return CURLE_OK;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_callback() I/O error: %s", strerror(errno));
+ break;
+ default:
+ failf(data, "gsk_attribute_set_callback(): %s", gsk_strerror(rc));
+ break;
+ }
+ return CURLE_SSL_CONNECT_ERROR;
+}
+
+
+static CURLcode set_ciphers(struct SessionHandle * data, gsk_handle h)
+{
+ const char * cipherlist = data->set.str[STRING_SSL_CIPHER_LIST];
+ char * sslv2ciphers;
+ char * sslv3ciphers;
+ const char * clp;
+ const gskit_cipher * ctp;
+ char * v2p;
+ char * v3p;
+ int i;
+ CURLcode cc;
+
+ /* Compile cipher list into GSKit-compatible cipher lists. */
+
+ if(!cipherlist)
+ return CURLE_OK;
+ while(is_separator(*cipherlist)) /* Skip initial separators. */
+ cipherlist++;
+ if(!*cipherlist)
+ return CURLE_OK;
+
+ /* We allocate GSKit buffers of the same size as the input string: since
+ GSKit tokens are always shorter than their cipher names, allocated buffers
+ will always be large enough to accomodate the result. */
+ i = strlen(cipherlist) + 1;
+ v2p = malloc(i);
+ if(!v2p)
+ return CURLE_OUT_OF_MEMORY;
+ v3p = malloc(i);
+ if(!v3p) {
+ free(v2p);
+ return CURLE_OUT_OF_MEMORY;
+ }
+ sslv2ciphers = v2p;
+ sslv3ciphers = v3p;
+
+ /* Process each cipher in input string. */
+ for(;;) {
+ for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
+ cipherlist++;
+ i = cipherlist - clp;
+ if(!i)
+ break;
+ /* Search the cipher in our table. */
+ for(ctp = ciphertable; ctp->name; ctp++)
+ if(strnequal(ctp->name, clp, i) && !ctp->name[i])
+ break;
+ if(!ctp->name)
+ failf(data, "Unknown cipher %.*s: ignored", i, clp);
+ else {
+ switch (ctp->sslver) {
+ case CURL_SSLVERSION_SSLv2:
+ strcpy(v2p, ctp->gsktoken);
+ v2p += strlen(v2p);
+ break;
+ default:
+ /* GSKit wants TLSv1 ciphers with SSLv3 ciphers. */
+ strcpy(v3p, ctp->gsktoken);
+ v3p += strlen(v3p);
+ break;
+ }
+ }
+
+ /* Advance to next cipher name or end of string. */
+ while(is_separator(*cipherlist))
+ cipherlist++;
+ }
+ *v2p = '\0';
+ *v3p = '\0';
+ cc = set_buffer(data, h, GSK_V2_CIPHER_SPECS, sslv2ciphers);
+ if(cc == CURLE_OK)
+ cc = set_buffer(data, h, GSK_V3_CIPHER_SPECS, sslv3ciphers);
+ free(sslv2ciphers);
+ free(sslv3ciphers);
+ return cc;
+}
+
+
+int Curl_gskit_init(void)
+{
+ /* No initialisation needed. */
+
+ return 1;
+}
+
+
+void Curl_gskit_cleanup(void)
+{
+ /* Nothing to do. */
+}
+
+
+static CURLcode init_environment(struct SessionHandle * data,
+ gsk_handle * envir, const char * appid,
+ const char * file, const char * label,
+ const char * password)
+{
+ int rc;
+ CURLcode c;
+ gsk_handle h;
+
+ /* Creates the GSKit environment. */
+
+ rc = gsk_environment_open(&h);
+ switch (rc) {
+ case GSK_OK:
+ break;
+ case GSK_INSUFFICIENT_STORAGE:
+ return CURLE_OUT_OF_MEMORY;
+ default:
+ failf(data, "gsk_environment_open(): %s", gsk_strerror(rc));
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+
+ c = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION);
+ if(c == CURLE_OK && appid)
+ c = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid);
+ if(c == CURLE_OK && file)
+ c = set_buffer(data, h, GSK_KEYRING_FILE, file);
+ if(c == CURLE_OK && label)
+ c = set_buffer(data, h, GSK_KEYRING_LABEL, label);
+ if(c == CURLE_OK && password)
+ c = set_buffer(data, h, GSK_KEYRING_PW, password);
+
+ if(c == CURLE_OK) {
+ /* Locate CAs, Client certificate and key according to our settings.
+ Note: this call may be blocking for some tenths of seconds. */
+ c = gskit_status(data, gsk_environment_init(h),
+ "gsk_environment_init()", CURLE_SSL_CERTPROBLEM);
+ if(c == CURLE_OK) {
+ *envir = h;
+ return c;
+ }
+ }
+ /* Error: rollback. */
+ gsk_environment_close(&h);
+ return c;
+}
+
+
+static void cancel_async_handshake(struct connectdata * conn, int sockindex)
+{
+ struct ssl_connect_data * connssl = &conn->ssl[sockindex];
+ Qso_OverlappedIO_t cstat;
+
+ if(QsoCancelOperation(conn->sock[sockindex], 0) > 0)
+ QsoWaitForIOCompletion(connssl->iocport, &cstat, (struct timeval *) NULL);
+}
+
+
+static void close_async_handshake(struct ssl_connect_data * connssl)
+{
+ QsoDestroyIOCompletionPort(connssl->iocport);
+ connssl->iocport = -1;
+}
+
+
+static void close_one(struct ssl_connect_data * conn,
+ struct SessionHandle * data)
+{
+ if(conn->handle) {
+ gskit_status(data, gsk_secure_soc_close(&conn->handle),
+ "gsk_secure_soc_close()", 0);
+ conn->handle = (gsk_handle) NULL;
+ }
+ if(conn->iocport >= 0)
+ close_async_handshake(conn);
+}
+
+
+static ssize_t gskit_send(struct connectdata * conn, int sockindex,
+ const void * mem, size_t len, CURLcode * curlcode)
+{
+ struct SessionHandle * data = conn->data;
+ CURLcode cc;
+ int written;
+
+ cc = gskit_status(data,
+ gsk_secure_soc_write(conn->ssl[sockindex].handle,
+ (char *) mem, (int) len, &written),
+ "gsk_secure_soc_write()", CURLE_SEND_ERROR);
+ if(cc != CURLE_OK) {
+ *curlcode = cc;
+ written = -1;
+ }
+ return (ssize_t) written; /* number of bytes */
+}
+
+
+static ssize_t gskit_recv(struct connectdata * conn, int num, char * buf,
+ size_t buffersize, CURLcode * curlcode)
+{
+ struct SessionHandle * data = conn->data;
+ int buffsize;
+ int nread;
+ CURLcode cc;
+
+ buffsize = buffersize > (size_t) INT_MAX? INT_MAX: (int) buffersize;
+ cc = gskit_status(data, gsk_secure_soc_read(conn->ssl[num].handle,
+ buf, buffsize, &nread),
+ "gsk_secure_soc_read()", CURLE_RECV_ERROR);
+ if(cc != CURLE_OK) {
+ *curlcode = cc;
+ nread = -1;
+ }
+ return (ssize_t) nread;
+}
+
+
+static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex)
+{
+ struct SessionHandle * data = conn->data;
+ struct ssl_connect_data * connssl = &conn->ssl[sockindex];
+ gsk_handle envir;
+ CURLcode cc;
+ int rc;
+ char * keyringfile;
+ char * keyringpwd;
+ char * keyringlabel;
+ char * v2ciphers;
+ char * v3ciphers;
+ char * sni;
+ bool sslv2enable, sslv3enable, tlsv1enable;
+ long timeout;
+ Qso_OverlappedIO_t commarea;
+
+ /* Create SSL environment, start (preferably asynchronous) handshake. */
+
+ connssl->handle = (gsk_handle) NULL;
+ connssl->iocport = -1;
+
+ /* GSKit supports two ways of specifying an SSL context: either by
+ * application identifier (that should have been defined at the system
+ * level) or by keyring file, password and certificate label.
+ * Local certificate name (CURLOPT_SSLCERT) is used to hold either the
+ * application identifier of the certificate label.
+ * Key password (CURLOPT_KEYPASSWD) holds the keyring password.
+ * It is not possible to have different keyrings for the CAs and the
+ * local certificate. We thus use the CA file (CURLOPT_CAINFO) to identify
+ * the keyring file.
+ * If no key password is given and the keyring is the system keyring,
+ * application identifier mode is tried first, as recommended in IBM doc.
+ */
+
+ keyringfile = data->set.str[STRING_SSL_CAFILE];
+ keyringpwd = data->set.str[STRING_KEY_PASSWD];
+ keyringlabel = data->set.str[STRING_CERT];
+ envir = (gsk_handle) NULL;
+
+ if(keyringlabel && *keyringlabel && !keyringpwd &&
+ !strcmp(keyringfile, CURL_CA_BUNDLE)) {
+ /* Try application identifier mode. */
+ init_environment(data, &envir, keyringlabel, (const char *) NULL,
+ (const char *) NULL, (const char *) NULL);
+ }
+
+ if(!envir) {
+ /* Use keyring mode. */
+ cc = init_environment(data, &envir, (const char *) NULL,
+ keyringfile, keyringlabel, keyringpwd);
+ if(cc != CURLE_OK)
+ return cc;
+ }
+
+ /* Create secure session. */
+ cc = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
+ "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
+ gsk_environment_close(&envir);
+ if(cc != CURLE_OK)
+ return cc;
+
+ /* Determine which SSL/TLS version should be enabled. */
+ sslv2enable = sslv3enable = tlsv1enable = false;
+ sni = conn->host.name;
+ switch (data->set.ssl.version) {
+ case CURL_SSLVERSION_SSLv2:
+ sslv2enable = true;
+ sni = (char *) NULL;
+ break;
+ case CURL_SSLVERSION_SSLv3:
+ sslv3enable = true;
+ sni = (char *) NULL;
+ break;
+ case CURL_SSLVERSION_TLSv1:
+ tlsv1enable = true;
+ break;
+ default: /* CURL_SSLVERSION_DEFAULT. */
+ sslv3enable = true;
+ tlsv1enable = true;
+ break;
+ }
+
+ /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
+ if(sni) {
+ rc = gsk_attribute_set_buffer(connssl->handle,
+ GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, 0);
+ switch (rc) {
+ case GSK_OK:
+ case GSK_ATTRIBUTE_INVALID_ID:
+ break;
+ case GSK_ERROR_IO:
+ failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno));
+ cc = CURLE_SSL_CONNECT_ERROR;
+ break;
+ default:
+ failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc));
+ cc = CURLE_SSL_CONNECT_ERROR;
+ break;
+ }
+ }
+
+ /* Set session parameters. */
+ if(cc == CURLE_OK) {
+ /* Compute the handshake timeout. Since GSKit granularity is 1 second,
+ we round up the required value. */
+ timeout = Curl_timeleft(data, NULL, TRUE);
+ if(timeout < 0)
+ cc = CURLE_OPERATION_TIMEDOUT;
+ else
+ cc = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
+ (timeout + 999) / 1000);
+ }
+ if(cc == CURLE_OK)
+ cc = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]);
+ if(cc == CURLE_OK)
+ cc = set_ciphers(data, connssl->handle);
+ if(cc == CURLE_OK)
+ cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
+ sslv2enable? GSK_PROTOCOL_SSLV2_ON:
+ GSK_PROTOCOL_SSLV2_OFF);
+ if(cc == CURLE_OK)
+ cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
+ sslv3enable? GSK_PROTOCOL_SSLV3_ON:
+ GSK_PROTOCOL_SSLV3_OFF);
+ if(cc == CURLE_OK)
+ cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
+ sslv3enable? GSK_PROTOCOL_TLSV1_ON:
+ GSK_PROTOCOL_TLSV1_OFF);
+ if(cc == CURLE_OK)
+ cc = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
+ data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL:
+ GSK_SERVER_AUTH_PASSTHRU);
+
+ if(cc == CURLE_OK) {
+ /* Start handshake. Try asynchronous first. */
+ memset(&commarea, 0, sizeof commarea);
+ connssl->iocport = QsoCreateIOCompletionPort();
+ if(connssl->iocport != -1) {
+ cc = gskit_status(data, gsk_secure_soc_startInit(connssl->handle,
+ connssl->iocport, &commarea),
+ "gsk_secure_soc_startInit()", CURLE_SSL_CONNECT_ERROR);
+ if(cc == CURLE_OK) {
+ connssl->connecting_state = ssl_connect_2;
+ return CURLE_OK;
+ }
+ else
+ close_async_handshake(connssl);
+ }
+ else if(errno != ENOBUFS)
+ cc = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0);
+ else {
+ /* No more completion port available. Use synchronous IO. */
+ cc = gskit_status(data, gsk_secure_soc_init(connssl->handle),
+ "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
+ if(cc == CURLE_OK) {
+ connssl->connecting_state = ssl_connect_3;
+ return CURLE_OK;
+ }
+ }
+ }
+
+ /* Error: rollback. */
+ close_one(connssl, data);
+ return cc;
+}
+
+
+static CURLcode gskit_connect_step2(struct connectdata * conn, int sockindex,
+ bool nonblocking)
+{
+ struct SessionHandle * data = conn->data;
+ struct ssl_connect_data * connssl = &conn->ssl[sockindex];
+ Qso_OverlappedIO_t cstat;
+ long timeout_ms;
+ struct timeval stmv;
+ CURLcode cc;
+
+ /* Poll or wait for end of SSL asynchronous handshake. */
+
+ for(;;) {
+ timeout_ms = nonblocking? 0: Curl_timeleft(data, NULL, TRUE);
+ if(timeout_ms < 0)
+ timeout_ms = 0;
+ stmv.tv_sec = timeout_ms / 1000;
+ stmv.tv_usec = (timeout_ms - stmv.tv_sec * 1000) * 1000;
+ switch (QsoWaitForIOCompletion(connssl->iocport, &cstat, &stmv)) {
+ case 1: /* Operation complete. */
+ break;
+ case -1: /* An error occurred: handshake still in progress. */
+ if(errno == EINTR) {
+ if(nonblocking)
+ return CURLE_OK;
+ continue; /* Retry. */
+ }
+ if(errno != ETIME) {
+ failf(data, "QsoWaitForIOCompletion() I/O error: %s", strerror(errno));
+ cancel_async_handshake(conn, sockindex);
+ close_async_handshake(connssl);
+ return CURLE_SSL_CONNECT_ERROR;
+ }
+ /* FALL INTO... */
+ case 0: /* Handshake in progress, timeout occurred. */
+ if(nonblocking)
+ return CURLE_OK;
+ cancel_async_handshake(conn, sockindex);
+ close_async_handshake(connssl);
+ return CURLE_OPERATION_TIMEDOUT;
+ }
+ break;
+ }
+ cc = gskit_status(data, cstat.returnValue, "SSL handshake",
+ CURLE_SSL_CONNECT_ERROR);
+ if(cc == CURLE_OK)
+ connssl->connecting_state = ssl_connect_3;
+ close_async_handshake(connssl);
+ return cc;
+}
+
+
+static CURLcode gskit_connect_step3(struct connectdata * conn, int sockindex)
+{
+ struct SessionHandle * data = conn->data;
+ struct ssl_connect_data * connssl = &conn->ssl[sockindex];
+ const gsk_cert_data_elem * cdev;
+ int cdec;
+ const gsk_cert_data_elem * p;
+ const char * cert = (const char *) NULL;
+ const char * certend;
+ int i;
+ CURLcode cc;
+
+ /* SSL handshake done: gather certificate info and verify host. */
+
+ if(gskit_status(data, gsk_attribute_get_cert_info(connssl->handle,
+ GSK_PARTNER_CERT_INFO,
+ &cdev, &cdec),
+ "gsk_attribute_get_cert_info()", CURLE_SSL_CONNECT_ERROR) ==
+ CURLE_OK) {
+ infof(data, "Server certificate:\n");
+ p = cdev;
+ for(i = 0; i++ < cdec; p++)
+ switch (p->cert_data_id) {
+ case CERT_BODY_DER:
+ cert = p->cert_data_p;
+ certend = cert + cdev->cert_data_l;
+ break;
+ case CERT_DN_PRINTABLE:
+ infof(data, "\t subject: %.*s\n", p->cert_data_l, p->cert_data_p);
+ break;
+ case CERT_ISSUER_DN_PRINTABLE:
+ infof(data, "\t issuer: %.*s\n", p->cert_data_l, p->cert_data_p);
+ break;
+ case CERT_VALID_FROM:
+ infof(data, "\t start date: %.*s\n", p->cert_data_l, p->cert_data_p);
+ break;
+ case CERT_VALID_TO:
+ infof(data, "\t expire date: %.*s\n", p->cert_data_l, p->cert_data_p);
+ break;
+ }
+ }
+
+ /* Verify host. */
+ cc = Curl_verifyhost(conn, cert, certend);
+ if(cc != CURLE_OK)
+ return cc;
+
+ /* The only place GSKit can get the whole CA chain is a validation
+ callback where no user data pointer is available. Therefore it's not
+ possible to copy this chain into our structures for CAINFO.
+ However the server certificate may be available, thus we can return
+ info about it. */
+ if(data->set.ssl.certinfo) {
+ if(Curl_ssl_init_certinfo(data, 1))
+ return CURLE_OUT_OF_MEMORY;
+ if(cert) {
+ cc = Curl_extract_certinfo(conn, 0, cert, certend);
+ if(cc != CURLE_OK)
+ return cc;
+ }
+ }
+
+ connssl->connecting_state = ssl_connect_done;
+ return CURLE_OK;
+}
+
+
+static CURLcode gskit_connect_common(struct connectdata * conn, int sockindex,
+ bool nonblocking, bool * done)
+{
+ struct SessionHandle * data = conn->data;
+ struct ssl_connect_data * connssl = &conn->ssl[sockindex];
+ long timeout_ms;
+ Qso_OverlappedIO_t cstat;
+ CURLcode cc = CURLE_OK;
+
+ *done = connssl->state == ssl_connection_complete;
+ if(*done)
+ return CURLE_OK;
+
+ /* Step 1: create session, start handshake. */
+ if(connssl->connecting_state == ssl_connect_1) {
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ cc = CURLE_OPERATION_TIMEDOUT;
+ }
+ else
+ cc = gskit_connect_step1(conn, sockindex);
+ }
+
+ /* Step 2: check if handshake is over. */
+ if(cc == CURLE_OK && connssl->connecting_state == ssl_connect_2) {
+ /* check allowed time left */
+ timeout_ms = Curl_timeleft(data, NULL, TRUE);
+
+ if(timeout_ms < 0) {
+ /* no need to continue if time already is up */
+ failf(data, "SSL connection timeout");
+ cc = CURLE_OPERATION_TIMEDOUT;
+ }
+ else
+ cc = gskit_connect_step2(conn, sockindex, nonblocking);
+ }
+
+ /* Step 3: gather certificate info, verify host. */
+ if(cc == CURLE_OK && connssl->connecting_state == ssl_connect_3)
+ cc = gskit_connect_step3(conn, sockindex);
+
+ if(cc != CURLE_OK)
+ close_one(connssl, data);
+ else if(connssl->connecting_state == ssl_connect_done) {
+ connssl->state = ssl_connection_complete;
+ connssl->connecting_state = ssl_connect_1;
+ conn->recv[sockindex] = gskit_recv;
+ conn->send[sockindex] = gskit_send;
+ *done = TRUE;
+ }
+
+ return cc;
+}
+
+
+CURLcode Curl_gskit_connect_nonblocking(struct connectdata * conn,
+ int sockindex,
+ bool * done)
+{
+ CURLcode cc;
+
+ cc = gskit_connect_common(conn, sockindex, TRUE, done);
+ if(*done || cc != CURLE_OK)
+ conn->ssl[sockindex].connecting_state = ssl_connect_1;
+ return cc;
+}
+
+
+CURLcode Curl_gskit_connect(struct connectdata * conn, int sockindex)
+{
+ CURLcode retcode;
+ bool done;
+
+ conn->ssl[sockindex].connecting_state = ssl_connect_1;
+ retcode = gskit_connect_common(conn, sockindex, FALSE, &done);
+ if(retcode)
+ return retcode;
+
+ DEBUGASSERT(done);
+
+ return CURLE_OK;
+}
+
+
+void Curl_gskit_close(struct connectdata * conn, int sockindex)
+{
+ struct SessionHandle * data = conn->data;
+ struct ssl_connect_data * connssl = &conn->ssl[sockindex];
+
+ if(connssl->use)
+ close_one(connssl, data);
+}
+
+
+int Curl_gskit_close_all(struct SessionHandle * data)
+{
+ /* Unimplemented. */
+ (void) data;
+ return 0;
+}
+
+
+int Curl_gskit_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;
+
+ close_one(connssl, data);
+ 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 gsk_secure_soc_read() now, so
+ use read(). */
+
+ nread = read(conn->sock[sockindex], buf, sizeof(buf));
+
+ if(nread < 0) {
+ failf(data, "read: %s", strerror(errno));
+ rc = -1;
+ }
+
+ if(nread <= 0)
+ break;
+
+ what = Curl_socket_ready(conn->sock[sockindex], CURL_SOCKET_BAD, 0);
+ }
+
+ return rc;
+}
+
+
+size_t Curl_gskit_version(char * buffer, size_t size)
+{
+ strncpy(buffer, "GSKit", size);
+ return strlen(buffer);
+}
+
+
+int Curl_gskit_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_GSKIT */
diff --git a/lib/gskit.h b/lib/gskit.h
new file mode 100644
index 000000000..0d59aa709
--- /dev/null
+++ b/lib/gskit.h
@@ -0,0 +1,64 @@
+#ifndef HEADER_CURL_GSKIT_H
+#define HEADER_CURL_GSKIT_H
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2013, 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.
+ *
+ ***************************************************************************/
+#include "curl_setup.h"
+
+/*
+ * This header should only be needed to get included by sslgen.c and gskit.c
+ */
+
+#include "urldata.h"
+
+#ifdef USE_GSKIT
+int Curl_gskit_init(void);
+void Curl_gskit_cleanup(void);
+CURLcode Curl_gskit_connect(struct connectdata * conn, int sockindex);
+CURLcode Curl_gskit_connect_nonblocking(struct connectdata * conn,
+ int sockindex, bool * done);
+void Curl_gskit_close(struct connectdata *conn, int sockindex);
+int Curl_gskit_close_all(struct SessionHandle * data);
+int Curl_gskit_shutdown(struct connectdata * conn, int sockindex);
+
+size_t Curl_gskit_version(char * buffer, size_t size);
+int Curl_gskit_check_cxn(struct connectdata * cxn);
+
+/* API setup for GSKit */
+#define curlssl_init Curl_gskit_init
+#define curlssl_cleanup Curl_gskit_cleanup
+#define curlssl_connect Curl_gskit_connect
+#define curlssl_connect_nonblocking Curl_gskit_connect_nonblocking
+
+/* No session handling for GSKit */
+#define curlssl_session_free(x) Curl_nop_stmt
+#define curlssl_close_all Curl_gskit_close_all
+#define curlssl_close Curl_gskit_close
+#define curlssl_shutdown(x,y) Curl_gskit_shutdown(x,y)
+#define curlssl_set_engine(x,y) CURLE_NOT_BUILT_IN
+#define curlssl_set_engine_default(x) CURLE_NOT_BUILT_IN
+#define curlssl_engines_list(x) NULL
+#define curlssl_version Curl_gskit_version
+#define curlssl_check_cxn(x) Curl_gskit_check_cxn(x)
+#define curlssl_data_pending(x,y) 0
+#endif /* USE_GSKIT */
+
+#endif /* HEADER_CURL_GSKIT_H */
diff --git a/lib/hostcheck.c b/lib/hostcheck.c
index ef32d8cff..abd1fa0c3 100644
--- a/lib/hostcheck.c
+++ b/lib/hostcheck.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2013, 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
@@ -22,7 +22,8 @@
#include "curl_setup.h"
-#if defined(USE_SSLEAY) || defined(USE_AXTLS) || defined(USE_QSOSSL)
+#if defined(USE_SSLEAY) || defined(USE_AXTLS) || defined(USE_QSOSSL) || \
+ defined(USE_GSKIT)
/* these backends use functions from this file */
#include "hostcheck.h"
@@ -93,4 +94,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
return 0;
}
-#endif /* SSLEAY or AXTLS or QSOSSL */
+#endif /* SSLEAY or AXTLS or QSOSSL or GSKIT */
diff --git a/lib/setup-os400.h b/lib/setup-os400.h
index cdeefe3dd..319efec92 100644
--- a/lib/setup-os400.h
+++ b/lib/setup-os400.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2013, 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
@@ -38,6 +38,8 @@ typedef unsigned long u_int32_t;
#include <sys/socket.h>
#include <netdb.h>
#include <qsossl.h>
+#include <gskssl.h>
+#include <qsoasync.h>
#include <gssapi.h>
extern int Curl_getaddrinfo_a(const char * nodename, const char * servname,
@@ -68,6 +70,93 @@ extern char * Curl_SSL_Strerror_a(int sslreturnvalue, SSLErrorMsg * serrmsgp);
#define SSL_Strerror Curl_SSL_Strerror_a
+/* GSKit wrappers. */
+
+extern int Curl_gsk_environment_open(gsk_handle * my_env_handle);
+#define gsk_environment_open Curl_gsk_environment_open
+
+extern int Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
+ gsk_handle * my_session_handle);
+#define gsk_secure_soc_open Curl_gsk_secure_soc_open
+
+extern int Curl_gsk_environment_close(gsk_handle * my_env_handle);
+#define gsk_environment_close Curl_gsk_environment_close
+
+extern int Curl_gsk_secure_soc_close(gsk_handle * my_session_handle);
+#define gsk_secure_soc_close Curl_gsk_secure_soc_close
+
+extern int Curl_gsk_environment_init(gsk_handle my_env_handle);
+#define gsk_environment_init Curl_gsk_environment_init
+
+extern int Curl_gsk_secure_soc_init(gsk_handle my_session_handle);
+#define gsk_secure_soc_init Curl_gsk_secure_soc_init
+
+extern int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle,
+ GSK_BUF_ID bufID,
+ const char * buffer,
+ int bufSize);
+#define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a
+
+extern int Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle,
+ GSK_ENUM_ID enumID,
+ GSK_ENUM_VALUE enumValue);
+#define gsk_attribute_set_enum Curl_gsk_attribute_set_enum
+
+extern int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
+ GSK_NUM_ID numID,
+ int numValue);
+#define gsk_attribute_set_numeric_value Curl_gsk_attribute_set_numeric_value
+
+extern int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
+ GSK_CALLBACK_ID callBackID,
+ void * callBackAreaPtr);
+#define gsk_attribute_set_callback Curl_gsk_attribute_set_callback
+
+extern int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle,
+ GSK_BUF_ID bufID,
+ const char * * buffer,
+ int * bufSize);
+#define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a
+
+extern int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle,
+ GSK_ENUM_ID enumID,
+ GSK_ENUM_VALUE * enumValue);
+#define gsk_attribute_get_enum Curl_gsk_attribute_get_enum
+
+extern int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
+ GSK_NUM_ID numID,
+ int * numValue);
+#define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value
+
+extern int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
+ GSK_CERT_ID certID,
+ const gsk_cert_data_elem * * certDataElem,
+ int * certDataElementCount);
+#define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info
+
+extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,
+ GSK_MISC_ID miscID);
+#define gsk_secure_soc_misc Curl_gsk_secure_soc_misc
+
+extern int Curl_gsk_secure_soc_read(gsk_handle my_session_handle,
+ char * readBuffer,
+ int readBufSize, int * amtRead);
+#define gsk_secure_soc_read Curl_gsk_secure_soc_read
+
+extern int Curl_gsk_secure_soc_write(gsk_handle my_session_handle,
+ char * writeBuffer,
+ int writeBufSize, int * amtWritten);
+#define gsk_secure_soc_write Curl_gsk_secure_soc_write
+
+extern const char * Curl_gsk_strerror_a(int gsk_return_value);
+#define gsk_strerror Curl_gsk_strerror_a
+
+extern int Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,
+ int IOCompletionPort,
+ Qso_OverlappedIO_t * communicationsArea);
+#define gsk_secure_soc_startInit Curl_gsk_secure_soc_startInit
+
+
/* GSSAPI wrappers. */
extern OM_uint32 Curl_gss_import_name_a(OM_uint32 * minor_status,
@@ -107,6 +196,7 @@ extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
gss_buffer_t output_token);
#define gss_delete_sec_context Curl_gss_delete_sec_context_a
+
/* LDAP wrappers. */
#define BerValue struct berval
diff --git a/lib/sslgen.c b/lib/sslgen.c
index d9b5c4715..d2d0e303e 100644
--- a/lib/sslgen.c
+++ b/lib/sslgen.c
@@ -32,6 +32,7 @@
Curl_gtls_ - prefix for GnuTLS ones
Curl_nss_ - prefix for NSS ones
Curl_qssl_ - prefix for QsoSSL ones
+ Curl_gskit_ - prefix for GSKit ones
Curl_polarssl_ - prefix for PolarSSL ones
Curl_cyassl_ - prefix for CyaSSL ones
Curl_schannel_ - prefix for Schannel SSPI ones
@@ -63,6 +64,7 @@
#include "gtls.h" /* GnuTLS versions */
#include "nssg.h" /* NSS versions */
#include "qssl.h" /* QSOSSL versions */
+#include "gskit.h" /* Global Secure ToolKit versions */
#include "polarssl.h" /* PolarSSL versions */
#include "axtls.h" /* axTLS versions */
#include "cyassl.h" /* CyaSSL versions */
diff --git a/lib/url.c b/lib/url.c
index b6e986055..c2bbfb30b 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -1901,7 +1901,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->set.ssl.fsslctxp = va_arg(param, void *);
break;
#endif
-#if defined(USE_SSLEAY) || defined(USE_QSOSSL)
+#if defined(USE_SSLEAY) || defined(USE_QSOSSL) || defined(USE_GSKIT)
case CURLOPT_CERTINFO:
data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE;
break;
diff --git a/lib/urldata.h b/lib/urldata.h
index 0c07cab70..47841e1f4 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -134,6 +134,10 @@
#include <qsossl.h>
#endif
+#ifdef USE_GSKIT
+#include <gskssl.h>
+#endif
+
#ifdef USE_AXTLS
#include <axTLS/ssl.h>
#undef malloc
@@ -322,6 +326,11 @@ struct ssl_connect_data {
#ifdef USE_QSOSSL
SSLHandle *handle;
#endif /* USE_QSOSSL */
+#ifdef USE_GSKIT
+ gsk_handle handle;
+ int iocport;
+ ssl_connect_state connecting_state;
+#endif
#ifdef USE_AXTLS
SSL_CTX* ssl_ctx;
SSL* ssl;
diff --git a/lib/x509asn1.c b/lib/x509asn1.c
index 060697997..94b89b2be 100644
--- a/lib/x509asn1.c
+++ b/lib/x509asn1.c
@@ -22,7 +22,7 @@
#include "curl_setup.h"
-#if defined(USE_QSOSSL)
+#if defined(USE_QSOSSL) || defined(USE_GSKIT)
#include <curl/curl.h>
#include "urldata.h"
@@ -1148,4 +1148,4 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
return CURLE_PEER_FAILED_VERIFICATION;
}
-#endif /* USE_QSOSSL */
+#endif /* USE_QSOSSL or USE_GSKIT */
diff --git a/lib/x509asn1.h b/lib/x509asn1.h
index 8eabf8b0b..2276b5b64 100644
--- a/lib/x509asn1.h
+++ b/lib/x509asn1.h
@@ -25,7 +25,7 @@
#include "curl_setup.h"
-#if defined(USE_QSOSSL)
+#if defined(USE_QSOSSL) || defined(USE_GSKIT)
#include "urldata.h"
@@ -125,5 +125,5 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum,
CURLcode Curl_verifyhost(struct connectdata * conn,
const char * beg, const char * end);
-#endif /* USE_QSOSSL */
+#endif /* USE_QSOSSL or USE_GSKIT */
#endif /* HEADER_CURL_X509ASN1_H */