mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -05:00
Implemented the parts of Patrick Monnerat's OS/400 patch that introduces
support for the OS/400 Secure Sockets Layer library
This commit is contained in:
parent
5ecd56d964
commit
b3461bab1d
4
CHANGES
4
CHANGES
@ -6,6 +6,10 @@
|
|||||||
|
|
||||||
Changelog
|
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)
|
Dan F (23 July 2007)
|
||||||
- Implemented only the parts of Patrick Monnerat's OS/400 patch that renamed
|
- 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
|
some few internal identifiers to avoid conflicts, which could be useful on
|
||||||
|
@ -11,7 +11,7 @@ Curl and libcurl 7.16.5
|
|||||||
|
|
||||||
This release includes the following changes:
|
This release includes the following changes:
|
||||||
|
|
||||||
o
|
o support for OS/400 Secure Sockets Layer library
|
||||||
|
|
||||||
This release includes the following bugfixes:
|
This release includes the following bugfixes:
|
||||||
|
|
||||||
|
@ -4,20 +4,20 @@ 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 \
|
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 \
|
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 \
|
netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c \
|
||||||
krb5.c \
|
krb5.c memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c \
|
||||||
memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c multi.c \
|
multi.c content_encoding.c share.c http_digest.c md5.c \
|
||||||
content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
|
http_negotiate.c http_ntlm.c inet_pton.c strtoofft.c strerror.c \
|
||||||
http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \
|
hostares.c hostasyn.c hostip4.c hostip6.c hostsyn.c hostthre.c \
|
||||||
hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c \
|
inet_ntop.c parsedate.c select.c gtls.c sslgen.c tftp.c splay.c \
|
||||||
select.c gtls.c sslgen.c tftp.c splay.c strdup.c socks.c ssh.c nss.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 \
|
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 \
|
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 \
|
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 \
|
getinfo.h strequal.h krb4.h memdebug.h inet_ntoa_r.h http_chunks.h \
|
||||||
http_chunks.h strtok.h connect.h llist.h hash.h content_encoding.h \
|
strtok.h connect.h llist.h hash.h content_encoding.h share.h md5.h \
|
||||||
share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h \
|
http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h inet_pton.h \
|
||||||
inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h \
|
strtoofft.h strerror.h inet_ntop.h curlx.h memory.h setup.h \
|
||||||
setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h \
|
transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h gtls.h \
|
||||||
gtls.h tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h \
|
tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h nssg.h \
|
||||||
nssg.h
|
qssl.h
|
||||||
|
496
lib/qssl.c
Normal file
496
lib/qssl.c
Normal file
@ -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 */
|
52
lib/qssl.h
Normal file
52
lib/qssl.h
Normal file
@ -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
|
70
lib/sslgen.c
70
lib/sslgen.c
@ -52,6 +52,7 @@
|
|||||||
#include "ssluse.h" /* OpenSSL versions */
|
#include "ssluse.h" /* OpenSSL versions */
|
||||||
#include "gtls.h" /* GnuTLS versions */
|
#include "gtls.h" /* GnuTLS versions */
|
||||||
#include "nssg.h" /* NSS versions */
|
#include "nssg.h" /* NSS versions */
|
||||||
|
#include "qssl.h" /* QSOSSL versions */
|
||||||
#include "sendf.h"
|
#include "sendf.h"
|
||||||
#include "strequal.h"
|
#include "strequal.h"
|
||||||
#include "url.h"
|
#include "url.h"
|
||||||
@ -171,9 +172,13 @@ int Curl_ssl_init(void)
|
|||||||
#else
|
#else
|
||||||
#ifdef USE_NSS
|
#ifdef USE_NSS
|
||||||
return Curl_nss_init();
|
return Curl_nss_init();
|
||||||
|
#else
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
return Curl_qsossl_init();
|
||||||
#else
|
#else
|
||||||
/* no SSL support */
|
/* no SSL support */
|
||||||
return 1;
|
return 1;
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
@ -190,8 +195,13 @@ void Curl_ssl_cleanup(void)
|
|||||||
#else
|
#else
|
||||||
#ifdef USE_GNUTLS
|
#ifdef USE_GNUTLS
|
||||||
Curl_gtls_cleanup();
|
Curl_gtls_cleanup();
|
||||||
|
#else
|
||||||
#ifdef USE_NSS
|
#ifdef USE_NSS
|
||||||
Curl_nss_cleanup();
|
Curl_nss_cleanup();
|
||||||
|
#else
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
Curl_qsossl_cleanup();
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
@ -214,6 +224,10 @@ Curl_ssl_connect(struct connectdata *conn, int sockindex)
|
|||||||
#else
|
#else
|
||||||
#ifdef USE_NSS
|
#ifdef USE_NSS
|
||||||
return Curl_nss_connect(conn, sockindex);
|
return Curl_nss_connect(conn, sockindex);
|
||||||
|
#else
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
return Curl_qsossl_connect(conn, sockindex);
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
@ -239,11 +253,16 @@ Curl_ssl_connect_nonblocking(struct connectdata *conn, int sockindex,
|
|||||||
#ifdef USE_NSS
|
#ifdef USE_NSS
|
||||||
*done = TRUE; /* fallback to BLOCKING */
|
*done = TRUE; /* fallback to BLOCKING */
|
||||||
return Curl_nss_connect(conn, sockindex);
|
return Curl_nss_connect(conn, sockindex);
|
||||||
|
#else
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
*done = TRUE; /* fallback to BLOCKING */
|
||||||
|
return Curl_qsossl_connect(conn, sockindex);
|
||||||
#else
|
#else
|
||||||
/* not implemented!
|
/* not implemented!
|
||||||
fallback to BLOCKING call. */
|
fallback to BLOCKING call. */
|
||||||
*done = TRUE;
|
*done = TRUE;
|
||||||
return Curl_ssl_connect(conn, sockindex);
|
return Curl_ssl_connect(conn, sockindex);
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
}
|
}
|
||||||
@ -302,9 +321,13 @@ static int kill_session(struct curl_ssl_session *session)
|
|||||||
#ifdef USE_GNUTLS
|
#ifdef USE_GNUTLS
|
||||||
Curl_gtls_session_free(session->sessionid);
|
Curl_gtls_session_free(session->sessionid);
|
||||||
#else
|
#else
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
/* No session handling for QsoSSL. */
|
||||||
|
#else
|
||||||
#ifdef USE_NSS
|
#ifdef USE_NSS
|
||||||
/* NSS has its own session ID cache */
|
/* NSS has its own session ID cache */
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
session->sessionid=NULL;
|
session->sessionid=NULL;
|
||||||
@ -400,6 +423,10 @@ void Curl_ssl_close_all(struct SessionHandle *data)
|
|||||||
#else
|
#else
|
||||||
#ifdef USE_NSS
|
#ifdef USE_NSS
|
||||||
Curl_nss_close_all(data);
|
Curl_nss_close_all(data);
|
||||||
|
#else
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
Curl_qsossl_close_all(data);
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
@ -420,6 +447,9 @@ void Curl_ssl_close(struct connectdata *conn)
|
|||||||
#ifdef USE_NSS
|
#ifdef USE_NSS
|
||||||
Curl_nss_close(conn);
|
Curl_nss_close(conn);
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
Curl_qsossl_close(conn);
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
conn->ssl[FIRSTSOCKET].use = FALSE;
|
conn->ssl[FIRSTSOCKET].use = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,9 +464,14 @@ CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex)
|
|||||||
#ifdef USE_GNUTLS
|
#ifdef USE_GNUTLS
|
||||||
if(Curl_gtls_shutdown(conn, sockindex))
|
if(Curl_gtls_shutdown(conn, sockindex))
|
||||||
return CURLE_SSL_SHUTDOWN_FAILED;
|
return CURLE_SSL_SHUTDOWN_FAILED;
|
||||||
|
#else
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
if(Curl_qsossl_shutdown(conn, sockindex))
|
||||||
|
return CURLE_SSL_SHUTDOWN_FAILED;
|
||||||
#else
|
#else
|
||||||
(void)conn;
|
(void)conn;
|
||||||
(void)sockindex;
|
(void)sockindex;
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
}
|
}
|
||||||
@ -461,11 +496,18 @@ CURLcode Curl_ssl_set_engine(struct SessionHandle *data, const char *engine)
|
|||||||
(void)data;
|
(void)data;
|
||||||
(void)engine;
|
(void)engine;
|
||||||
return CURLE_FAILED_INIT;
|
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
|
#else
|
||||||
/* no SSL layer */
|
/* no SSL layer */
|
||||||
(void)data;
|
(void)data;
|
||||||
(void)engine;
|
(void)engine;
|
||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
@ -487,10 +529,16 @@ CURLcode Curl_ssl_set_engine_default(struct SessionHandle *data)
|
|||||||
/* A no-op for NSS */
|
/* A no-op for NSS */
|
||||||
(void)data;
|
(void)data;
|
||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
|
#else
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
/* A no-op for QSOSSL */
|
||||||
|
(void)data;
|
||||||
|
return CURLE_FAILED_INIT;
|
||||||
#else
|
#else
|
||||||
/* No SSL layer */
|
/* No SSL layer */
|
||||||
(void)data;
|
(void)data;
|
||||||
return CURLE_FAILED_INIT;
|
return CURLE_FAILED_INIT;
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
@ -513,8 +561,14 @@ struct curl_slist *Curl_ssl_engines_list(struct SessionHandle *data)
|
|||||||
(void)data;
|
(void)data;
|
||||||
return NULL;
|
return NULL;
|
||||||
#else
|
#else
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
/* No engine support in QSOSSL. */
|
||||||
(void)data;
|
(void)data;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
#else
|
||||||
|
(void)data;
|
||||||
|
return NULL;
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
@ -534,12 +588,16 @@ ssize_t Curl_ssl_send(struct connectdata *conn,
|
|||||||
#else
|
#else
|
||||||
#ifdef USE_NSS
|
#ifdef USE_NSS
|
||||||
return Curl_nss_send(conn, sockindex, mem, len);
|
return Curl_nss_send(conn, sockindex, mem, len);
|
||||||
|
#else
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
return Curl_qsossl_send(conn, sockindex, mem, len);
|
||||||
#else
|
#else
|
||||||
(void)conn;
|
(void)conn;
|
||||||
(void)sockindex;
|
(void)sockindex;
|
||||||
(void)mem;
|
(void)mem;
|
||||||
(void)len;
|
(void)len;
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
@ -568,6 +626,10 @@ ssize_t Curl_ssl_recv(struct connectdata *conn, /* connection data */
|
|||||||
#else
|
#else
|
||||||
#ifdef USE_NSS
|
#ifdef USE_NSS
|
||||||
nread = Curl_nss_recv(conn, sockindex, mem, len, &block);
|
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_NSS */
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
@ -631,10 +693,14 @@ size_t Curl_ssl_version(char *buffer, size_t size)
|
|||||||
#else
|
#else
|
||||||
#ifdef USE_NSS
|
#ifdef USE_NSS
|
||||||
return Curl_nss_version(buffer, size);
|
return Curl_nss_version(buffer, size);
|
||||||
|
#else
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
return Curl_qsossl_version(buffer, size);
|
||||||
#else
|
#else
|
||||||
(void)buffer;
|
(void)buffer;
|
||||||
(void)size;
|
(void)size;
|
||||||
return 0; /* no SSL support */
|
return 0; /* no SSL support */
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
@ -656,10 +722,14 @@ int Curl_ssl_check_cxn(struct connectdata *conn)
|
|||||||
#else
|
#else
|
||||||
#ifdef USE_NSS
|
#ifdef USE_NSS
|
||||||
return Curl_nss_check_cxn(conn);
|
return Curl_nss_check_cxn(conn);
|
||||||
|
#else
|
||||||
|
#ifdef USE_QSOSSL
|
||||||
|
return Curl_qsossl_check_cxn(conn);
|
||||||
#else
|
#else
|
||||||
(void)conn;
|
(void)conn;
|
||||||
/* TODO: we lack implementation of this for GnuTLS */
|
/* TODO: we lack implementation of this for GnuTLS */
|
||||||
return -1; /* connection status unknown */
|
return -1; /* connection status unknown */
|
||||||
|
#endif /* USE_QSOSSL */
|
||||||
#endif /* USE_NSS */
|
#endif /* USE_NSS */
|
||||||
#endif /* USE_SSLEAY */
|
#endif /* USE_SSLEAY */
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user