From 2cc9246477285d16d21086dfed5cc4adeee0dbc9 Mon Sep 17 00:00:00 2001 From: Patrick Monnerat Date: Fri, 25 Oct 2013 18:37:37 +0200 Subject: OS400: sync RPG wrapper, zlib support, fix header file names, ... IFS compilation support, SSL GSKit backend by default, TLSv1.[12] support in GSKit for OS400 >= V7R1, no more tabs in make scripts. --- lib/config-os400.h | 4 +- lib/gskit.c | 342 +++++++++++++++++++++++++++++------------ lib/setup-os400.h | 7 + packages/OS400/README.OS400 | 1 + packages/OS400/ccsidcurl.c | 7 +- packages/OS400/curl.inc.in | 29 +++- packages/OS400/initscript.sh | 71 ++++++--- packages/OS400/make-include.sh | 52 +++++-- packages/OS400/make-lib.sh | 14 +- packages/OS400/make-tests.sh | 6 +- packages/OS400/os400sys.c | 157 +++++++++++++------ packages/OS400/os400sys.h | 2 + 12 files changed, 482 insertions(+), 210 deletions(-) diff --git a/lib/config-os400.h b/lib/config-os400.h index a290fe43d..889627780 100644 --- a/lib/config-os400.h +++ b/lib/config-os400.h @@ -529,10 +529,10 @@ #define SEND_TYPE_RETV int /* Define to use the QsoSSL package. */ -#define USE_QSOSSL +#undef USE_QSOSSL /* Define to use the GSKit package. */ -#undef USE_GSKIT +#define 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/gskit.c b/lib/gskit.c index 187c58d7a..d50748e3a 100644 --- a/lib/gskit.c +++ b/lib/gskit.c @@ -29,9 +29,38 @@ /* Some symbols are undefined/unsupported on OS400 versions < V7R1. */ #ifndef GSK_SSL_EXTN_SERVERNAME_REQUEST -#define GSK_SSL_EXTN_SERVERNAME_REQUEST 230 +#define GSK_SSL_EXTN_SERVERNAME_REQUEST 230 #endif +#ifndef GSK_TLSV10_CIPHER_SPECS +#define GSK_TLSV10_CIPHER_SPECS 236 +#endif + +#ifndef GSK_TLSV11_CIPHER_SPECS +#define GSK_TLSV11_CIPHER_SPECS 237 +#endif + +#ifndef GSK_TLSV12_CIPHER_SPECS +#define GSK_TLSV12_CIPHER_SPECS 238 +#endif + +#ifndef GSK_PROTOCOL_TLSV11 +#define GSK_PROTOCOL_TLSV11 437 +#endif + +#ifndef GSK_PROTOCOL_TLSV12 +#define GSK_PROTOCOL_TLSV12 438 +#endif + +#ifndef GSK_FALSE +#define GSK_FALSE 0 +#endif + +#ifndef GSK_TRUE +#define GSK_TRUE 1 +#endif + + #ifdef HAVE_LIMITS_H # include #endif @@ -54,30 +83,65 @@ #include "memdebug.h" +/* SSL version flags. */ +#define CURL_GSKPROTO_SSLV2 0 +#define CURL_GSKPROTO_SSLV2_MASK (1 << CURL_GSKPROTO_SSLV2) +#define CURL_GSKPROTO_SSLV3 1 +#define CURL_GSKPROTO_SSLV3_MASK (1 << CURL_GSKPROTO_SSLV3) +#define CURL_GSKPROTO_TLSV10 2 +#define CURL_GSKPROTO_TLSV10_MASK (1 << CURL_GSKPROTO_TLSV10) +#define CURL_GSKPROTO_TLSV11 3 +#define CURL_GSKPROTO_TLSV11_MASK (1 << CURL_GSKPROTO_TLSV11) +#define CURL_GSKPROTO_TLSV12 4 +#define CURL_GSKPROTO_TLSV12_MASK (1 << CURL_GSKPROTO_TLSV12) +#define CURL_GSKPROTO_LAST 5 + + /* Supported ciphers. */ typedef struct { const char * name; /* Cipher name. */ const char * gsktoken; /* Corresponding token for GSKit String. */ - int sslver; /* SSL version. */ + unsigned int versions; /* SSL version flags. */ } 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 }, + { "null-md5", "01", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "null-sha", "02", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "exp-rc4-md5", "03", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, + { "rc4-md5", "04", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "rc4-sha", "05", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "exp-rc2-cbc-md5", "06", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK }, + { "exp-des-cbc-sha", "09", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK }, + { "des-cbc3-sha", "0A", + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK }, + { "aes128-sha", "2F", + CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | + CURL_GSKPROTO_TLSV12_MASK }, + { "aes256-sha", "35", + CURL_GSKPROTO_TLSV10_MASK | CURL_GSKPROTO_TLSV11_MASK | + CURL_GSKPROTO_TLSV12_MASK }, + { "null-sha256", "3B", CURL_GSKPROTO_TLSV12_MASK }, + { "aes128-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK }, + { "aes256-sha256", "3D", CURL_GSKPROTO_TLSV12_MASK }, + { "rc4-md5", "1", CURL_GSKPROTO_SSLV2_MASK }, + { "exp-rc4-md5", "2", CURL_GSKPROTO_SSLV2_MASK }, + { "rc2-md5", "3", CURL_GSKPROTO_SSLV2_MASK }, + { "exp-rc2-md5", "4", CURL_GSKPROTO_SSLV2_MASK }, + { "des-cbc-md5", "6", CURL_GSKPROTO_SSLV2_MASK }, + { "des-cbc3-md5", "7", CURL_GSKPROTO_SSLV2_MASK }, { (const char *) NULL, (const char *) NULL, 0 } }; @@ -142,8 +206,8 @@ static CURLcode gskit_status(struct SessionHandle * data, int rc, } -static CURLcode set_enum(struct SessionHandle * data, - gsk_handle h, GSK_ENUM_ID id, GSK_ENUM_VALUE value) +static CURLcode set_enum(struct SessionHandle * data, gsk_handle h, + GSK_ENUM_ID id, GSK_ENUM_VALUE value, bool unsupported_ok) { int rc = gsk_attribute_set_enum(h, id, value); @@ -153,6 +217,9 @@ static CURLcode set_enum(struct SessionHandle * data, case GSK_ERROR_IO: failf(data, "gsk_attribute_set_enum() I/O error: %s", strerror(errno)); break; + case GSK_ATTRIBUTE_INVALID_ID: + if(unsupported_ok) + return CURLE_UNSUPPORTED_PROTOCOL; default: failf(data, "gsk_attribute_set_enum(): %s", gsk_strerror(rc)); break; @@ -161,8 +228,8 @@ static CURLcode set_enum(struct SessionHandle * data, } -static CURLcode set_buffer(struct SessionHandle * data, - gsk_handle h, GSK_BUF_ID id, const char * buffer) +static CURLcode set_buffer(struct SessionHandle * data, gsk_handle h, + GSK_BUF_ID id, const char * buffer, bool unsupported_ok) { int rc = gsk_attribute_set_buffer(h, id, buffer, 0); @@ -172,6 +239,9 @@ static CURLcode set_buffer(struct SessionHandle * data, case GSK_ERROR_IO: failf(data, "gsk_attribute_set_buffer() I/O error: %s", strerror(errno)); break; + case GSK_ATTRIBUTE_INVALID_ID: + if(unsupported_ok) + return CURLE_UNSUPPORTED_PROTOCOL; default: failf(data, "gsk_attribute_set_buffer(): %s", gsk_strerror(rc)); break; @@ -219,17 +289,20 @@ static CURLcode set_callback(struct SessionHandle * data, } -static CURLcode set_ciphers(struct SessionHandle * data, gsk_handle h) +static CURLcode set_ciphers(struct SessionHandle * data, + gsk_handle h, unsigned int * protoflags) { 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; + int l; + bool unsupported; CURLcode cc; + struct { + char * buf; + char * ptr; + } ciphers[CURL_GSKPROTO_LAST]; /* Compile cipher list into GSKit-compatible cipher lists. */ @@ -243,42 +316,44 @@ static CURLcode set_ciphers(struct SessionHandle * data, gsk_handle h) /* 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; + l = strlen(cipherlist) + 1; + memset((char *) ciphers, 0, sizeof ciphers); + for(i = 0; i < CURL_GSKPROTO_LAST; i++) { + ciphers[i].buf = malloc(l); + if(!ciphers[i].buf) { + while(i--) + free(ciphers[i].buf); + return CURLE_OUT_OF_MEMORY; + } + ciphers[i].ptr = ciphers[i].buf; + *ciphers[i].ptr = '\0'; } - sslv2ciphers = v2p; - sslv3ciphers = v3p; /* Process each cipher in input string. */ + unsupported = FALSE; + cc = CURLE_OK; for(;;) { for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);) cipherlist++; - i = cipherlist - clp; - if(!i) + l = cipherlist - clp; + if(!l) break; /* Search the cipher in our table. */ for(ctp = ciphertable; ctp->name; ctp++) - if(strnequal(ctp->name, clp, i) && !ctp->name[i]) + if(strnequal(ctp->name, clp, l) && !ctp->name[l]) break; - if(!ctp->name) - failf(data, "Unknown cipher %.*s: ignored", i, clp); + if(!ctp->name) { + failf(data, "Unknown cipher %.*s", l, clp); + cc = CURLE_SSL_CIPHER; + } 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; + unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK | + CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK)); + for(i = 0; i < CURL_GSKPROTO_LAST; i++) { + if(ctp->versions & (1 << i)) { + strcpy(ciphers[i].ptr, ctp->gsktoken); + ciphers[i].ptr += strlen(ctp->gsktoken); + } } } @@ -286,13 +361,63 @@ static CURLcode set_ciphers(struct SessionHandle * data, gsk_handle h) 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); + + /* Disable protocols with empty cipher lists. */ + for(i = 0; i < CURL_GSKPROTO_LAST; i++) { + if(!(*protoflags & (1 << i)) || !ciphers[i].buf[0]) { + *protoflags &= ~(1 << i); + ciphers[i].buf[0] = '\0'; + } + } + + /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */ + if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) { + cc = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE); + if(cc == CURLE_UNSUPPORTED_PROTOCOL) { + cc = CURLE_OK; + if(unsupported) { + failf(data, "TLSv1.1-only ciphers are not yet supported"); + cc = CURLE_SSL_CIPHER; + } + } + } + if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) { + cc = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE); + if(cc == CURLE_UNSUPPORTED_PROTOCOL) { + cc = CURLE_OK; + if(unsupported) { + failf(data, "TLSv1.2-only ciphers are not yet supported"); + cc = CURLE_SSL_CIPHER; + } + } + } + + /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to + the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */ + if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) { + cc = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE); + if(cc == CURLE_UNSUPPORTED_PROTOCOL) { + cc = CURLE_OK; + strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr, + ciphers[CURL_GSKPROTO_TLSV10].ptr); + } + } + + /* Set-up other ciphers. */ + if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_SSLV3_MASK)) + cc = set_buffer(data, h, GSK_V3_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE); + if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_SSLV2_MASK)) + cc = set_buffer(data, h, GSK_V2_CIPHER_SPECS, + ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE); + + /* Clean-up. */ + for(i = 0; i < CURL_GSKPROTO_LAST; i++) + free(ciphers[i].buf); + return cc; } @@ -333,15 +458,15 @@ static CURLcode init_environment(struct SessionHandle * data, return CURLE_SSL_CONNECT_ERROR; } - c = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION); + c = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE); if(c == CURLE_OK && appid) - c = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid); + c = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE); if(c == CURLE_OK && file) - c = set_buffer(data, h, GSK_KEYRING_FILE, file); + c = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE); if(c == CURLE_OK && label) - c = set_buffer(data, h, GSK_KEYRING_LABEL, label); + c = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE); if(c == CURLE_OK && password) - c = set_buffer(data, h, GSK_KEYRING_PW, password); + c = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE); if(c == CURLE_OK) { /* Locate CAs, Client certificate and key according to our settings. @@ -438,10 +563,8 @@ static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex) char * keyringfile; char * keyringpwd; char * keyringlabel; - char * v2ciphers; - char * v3ciphers; char * sni; - bool sslv2enable, sslv3enable, tlsv1enable; + unsigned int protoflags; long timeout; Qso_OverlappedIO_t commarea; @@ -491,52 +614,39 @@ static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex) return cc; /* Determine which SSL/TLS version should be enabled. */ - sslv2enable = sslv3enable = tlsv1enable = false; + protoflags = CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK; sni = conn->host.name; switch (data->set.ssl.version) { case CURL_SSLVERSION_SSLv2: - sslv2enable = true; + protoflags = CURL_GSKPROTO_SSLV2_MASK; sni = (char *) NULL; break; case CURL_SSLVERSION_SSLv3: - sslv3enable = true; + protoflags = CURL_GSKPROTO_SSLV2_MASK; sni = (char *) NULL; break; case CURL_SSLVERSION_TLSv1: + protoflags = CURL_GSKPROTO_TLSV10_MASK | + CURL_GSKPROTO_TLSV11_MASK | CURL_GSKPROTO_TLSV12_MASK; + break; case CURL_SSLVERSION_TLSv1_0: - tlsv1enable = true; + protoflags = CURL_GSKPROTO_TLSV10_MASK; break; case CURL_SSLVERSION_TLSv1_1: - failf(data, "GSKit doesn't support TLS 1.1!"); - cc = CURLE_SSL_CONNECT_ERROR; + protoflags = CURL_GSKPROTO_TLSV11_MASK; break; case CURL_SSLVERSION_TLSv1_2: - failf(data, "GSKit doesn't support TLS 1.2!"); - cc = CURLE_SSL_CONNECT_ERROR; - break; - default: /* CURL_SSLVERSION_DEFAULT. */ - sslv3enable = true; - tlsv1enable = true; + protoflags = CURL_GSKPROTO_TLSV12_MASK; 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; - } + cc = set_buffer(data, connssl->handle, + GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE); + if(cc == CURLE_UNSUPPORTED_PROTOCOL) + cc = CURLE_OK; } /* Set session parameters. */ @@ -553,23 +663,51 @@ static CURLcode gskit_connect_step1(struct connectdata * conn, int sockindex) 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); + cc = set_ciphers(data, connssl->handle, &protoflags); + if(!protoflags) { + failf(data, "No SSL protocol/cipher combination enabled"); + cc = CURLE_SSL_CIPHER; + } if(cc == CURLE_OK) cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2, - sslv2enable? GSK_PROTOCOL_SSLV2_ON: - GSK_PROTOCOL_SSLV2_OFF); + (protoflags & CURL_GSKPROTO_SSLV2_MASK)? + GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE); if(cc == CURLE_OK) cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3, - sslv3enable? GSK_PROTOCOL_SSLV3_ON: - GSK_PROTOCOL_SSLV3_OFF); + (protoflags & CURL_GSKPROTO_SSLV3_MASK)? + GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE); if(cc == CURLE_OK) cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1, - tlsv1enable? GSK_PROTOCOL_TLSV1_ON: - GSK_PROTOCOL_TLSV1_OFF); + (protoflags & CURL_GSKPROTO_TLSV10_MASK)? + GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE); + if(cc == CURLE_OK) { + cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11, + (protoflags & CURL_GSKPROTO_TLSV11_MASK)? + GSK_TRUE: GSK_FALSE, TRUE); + if(cc == CURLE_UNSUPPORTED_PROTOCOL) { + cc = CURLE_OK; + if(protoflags == CURL_GSKPROTO_TLSV11_MASK) { + failf(data, "TLS 1.1 not yet supported"); + cc = CURLE_SSL_CIPHER; + } + } + } + if(cc == CURLE_OK) { + cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12, + (protoflags & CURL_GSKPROTO_TLSV12_MASK)? + GSK_TRUE: GSK_FALSE, TRUE); + if(cc == CURLE_UNSUPPORTED_PROTOCOL) { + cc = CURLE_OK; + if(protoflags == CURL_GSKPROTO_TLSV12_MASK) { + failf(data, "TLS 1.2 not yet supported"); + cc = CURLE_SSL_CIPHER; + } + } + } 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); + GSK_SERVER_AUTH_PASSTHRU, FALSE); if(cc == CURLE_OK) { /* Start handshake. Try asynchronous first. */ diff --git a/lib/setup-os400.h b/lib/setup-os400.h index 319efec92..37dc05b2b 100644 --- a/lib/setup-os400.h +++ b/lib/setup-os400.h @@ -226,5 +226,12 @@ extern int Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags, #define sendto Curl_os400_sendto #define recvfrom Curl_os400_recvfrom +#ifdef HAVE_LIBZ +#define zlibVersion Curl_os400_zlibVersion +#define inflateInit_ Curl_os400_inflateInit_ +#define inflateInit2_ Curl_os400_inflateInit2_ +#define inflate Curl_os400_inflate +#define inflateEnd Curl_os400_inflateEnd +#endif #endif /* HEADER_CURL_SETUP_OS400_H */ diff --git a/packages/OS400/README.OS400 b/packages/OS400/README.OS400 index 73e81f8c3..4a39738a9 100644 --- a/packages/OS400/README.OS400 +++ b/packages/OS400/README.OS400 @@ -118,6 +118,7 @@ options: CURLOPT_USERAGENT CURLOPT_USERNAME CURLOPT_USERPWD + CURLOPT_XOAUTH2_BEARER Else it is the same as for curl_easy_setopt(). Note that CURLOPT_ERRORBUFFER is not in the list above, since it gives the address of an (empty) character buffer, not the address of a string. diff --git a/packages/OS400/ccsidcurl.c b/packages/OS400/ccsidcurl.c index a37f79027..9049d9e49 100644 --- a/packages/OS400/ccsidcurl.c +++ b/packages/OS400/ccsidcurl.c @@ -1111,11 +1111,7 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...) if(testwarn) { testwarn = 0; -#ifdef USE_TLS_SRP - if((int) STRING_LAST != (int) STRING_TLSAUTH_PASSWORD + 1) -#else - if((int) STRING_LAST != (int) STRING_MAIL_AUTH + 1) -#endif + if((int) STRING_LAST != (int) STRING_BEARER + 1) curl_mfprintf(stderr, "*** WARNING: curl_easy_setopt_ccsid() should be reworked ***\n"); } @@ -1176,6 +1172,7 @@ curl_easy_setopt_ccsid(CURL * curl, CURLoption tag, ...) case CURLOPT_USERAGENT: case CURLOPT_USERNAME: case CURLOPT_USERPWD: + case CURLOPT_XOAUTH2_BEARER: s = va_arg(arg, char *); ccsid = va_arg(arg, unsigned int); diff --git a/packages/OS400/curl.inc.in b/packages/OS400/curl.inc.in index b14d84f83..edd516740 100644 --- a/packages/OS400/curl.inc.in +++ b/packages/OS400/curl.inc.in @@ -115,6 +115,8 @@ d c X'00004000' d CURL_VERSION_NTLM_WB... d c X'00008000' + d CURL_VERSION_HTTP2... + d c X'00010000' * d HTTPPOST_FILENAME... d c X'00000001' @@ -212,6 +214,8 @@ d c 1 d CURL_HTTP_VERSION_1_1... d c 2 + d CURL_HTTP_VERSION_2_0... + d c 3 * d CURL_NETRC_IGNORED... d c 0 @@ -1168,6 +1172,14 @@ d c 00218 d CURLOPT_XFERINFOFUNCTION... d c 20219 + d CURLOPT_XOAUTH2_BEARER... + d c 10220 + d CURLOPT_DNS_INTERFACE... + d c 10221 + d CURLOPT_DNS_LOCAL_IP4... + d c 10222 + d CURLOPT_DNS_LOCAL_IP6... + d c 10223 * /if not defined(CURL_NO_OLDIES) d CURLOPT_SSLKEYPASSWD... @@ -1457,7 +1469,9 @@ d c 5 d CURLM_UNKNOWN_OPTION... d c 6 - d CURLM_LAST c 7 + d CURLM_ADDED_ALREADY... + d c 7 + d CURLM_LAST c 8 * d CURLMSG s 10i 0 based(######ptr######) Enum d CURLMSG_NONE c 0 @@ -1566,12 +1580,7 @@ d addrlen 10u 0 d addr 16 struct sockaddr * - d curl_khkey ds based(######ptr######) - d qualified - d key * const char * - d len 10u 0 - d keytype 10i 0 - * + d curl_khtype s 10i 0 based(######ptr######) enum d CURLKHTYPE_UNKNOWN... d c 0 d CURLKHTYPE_RSA1... @@ -1581,6 +1590,12 @@ d CURLKHTYPE_DSS... d c 3 * + d curl_khkey ds based(######ptr######) + d qualified + d key * const char * + d len 10u 0 + d keytype like(curl_khtype) + * d curl_forms ds based(######ptr######) d qualified d option like(CURLformoption) diff --git a/packages/OS400/initscript.sh b/packages/OS400/initscript.sh index c07355fc0..64147e393 100644 --- a/packages/OS400/initscript.sh +++ b/packages/OS400/initscript.sh @@ -1,6 +1,16 @@ #!/bin/sh +setenv() + +{ + # Define and export. + + eval ${1}="${2}" + export ${1} +} + + case "${SCRIPTDIR}" in /*) ;; *) SCRIPTDIR="`pwd`/${SCRIPTDIR}" @@ -32,18 +42,23 @@ export SONAME # ################################################################################ -TARGETLIB='CURL' # Target OS/400 program library -STATBNDDIR='CURL_A' # Static binding directory. -DYNBNDDIR='CURL' # Dynamic binding directory. -SRVPGM="CURL.${SONAME}" # Service program. -TGTCCSID='500' # Target CCSID of objects -DEBUG='*ALL' # Debug level -OPTIMIZE='10' # Optimisation level -OUTPUT='*NONE' # Compilation output option. -TGTRLS='V5R3M0' # Target OS release +setenv TARGETLIB 'CURL' # Target OS/400 program library. +setenv STATBNDDIR 'CURL_A' # Static binding directory. +setenv DYNBNDDIR 'CURL' # Dynamic binding directory. +setenv SRVPGM "CURL.${SONAME}" # Service program. +setenv TGTCCSID '500' # Target CCSID of objects. +setenv DEBUG '*ALL' # Debug level. +setenv OPTIMIZE '10' # Optimisation level +setenv OUTPUT '*NONE' # Compilation output option. +setenv TGTRLS 'V5R3M0' # Target OS release. +setenv IFSDIR '/curl' # Installation IFS directory. + +# Define ZLIB availability and locations. -export TARGETLIB STATBNDDIR DYNBNDDIR SRVPGM TGTCCSID DEBUG OPTIMIZE OUTPUT -export TGTRLS +setenv WITH_ZLIB 0 # Define to 1 to enable. +setenv ZLIB_INCLUDE '/zlib/include' # ZLIB include IFS directory. +setenv ZLIB_LIB 'ZLIB' # ZLIB library. +setenv ZLIB_BNDDIR 'ZLIB_A' # ZLIB binding directory. ################################################################################ @@ -133,14 +148,26 @@ make_module() CMD="${CMD} LOCALETYPE(*LOCALE)" CMD="${CMD} INCDIR('/qibm/proddata/qadrt/include'" CMD="${CMD} '${TOPDIR}/include/curl' '${TOPDIR}/include'" - CMD="${CMD} '${TOPDIR}/packages/OS400' ${INCLUDES})" + CMD="${CMD} '${TOPDIR}/packages/OS400'" + + if [ "${WITH_ZLIB}" != "0" ] + then CMD="${CMD} '${ZLIB_INCLUDE}'" + fi + + CMD="${CMD} ${INCLUDES})" CMD="${CMD} TGTCCSID(${TGTCCSID}) TGTRLS(${TGTRLS})" CMD="${CMD} OUTPUT(${OUTPUT})" CMD="${CMD} OPTIMIZE(${OPTIMIZE})" CMD="${CMD} DBGVIEW(${DEBUG})" - if [ "${3}" ] - then CMD="${CMD} DEFINE(${3})" + DEFINES="${3}" + + if [ "${WITH_ZLIB}" != "0" ] + then DEFINES="${DEFINES} HAVE_LIBZ HAVE_ZLIB_H" + fi + + if [ "${DEFINES}" ] + then CMD="${CMD} DEFINE(${DEFINES})" fi system "${CMD}" @@ -154,11 +181,17 @@ make_module() db2_name() { - basename "${1}" | - tr 'a-z-' 'A-Z_' | - sed -e 's/\..*//' \ - -e 's/^CURL_*/C/' \ - -e 's/^\(.\).*\(.........\)$/\1\2/' + if [ "${2}" = 'nomangle' ] + then basename "${1}" | + tr 'a-z-' 'A-Z_' | + sed -e 's/\..*//' \ + -e 's/^\(.\).*\(.........\)$/\1\2/' + else basename "${1}" | + tr 'a-z-' 'A-Z_' | + sed -e 's/\..*//' \ + -e 's/^CURL_*/C/' \ + -e 's/^\(.\).*\(.........\)$/\1\2/' + fi } diff --git a/packages/OS400/make-include.sh b/packages/OS400/make-include.sh index 834ee2fce..ad72cf4a7 100644 --- a/packages/OS400/make-include.sh +++ b/packages/OS400/make-include.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Installation of the include files in the OS/400 library. +# Installation of the header files in the OS/400 library. # SCRIPTDIR=`dirname "${0}"` @@ -8,16 +8,16 @@ SCRIPTDIR=`dirname "${0}"` cd "${TOPDIR}/include" -# Produce the curlbuild.h include file if not yet in distribution (CVS). +# Produce the curlbuild.h header file if not yet in distribution (CVS). if action_needed curl/curlbuild.h -then if action_needed curl/curlbuild.h curl/curlbuild.h.dist - then cp -p curl/curlbuild.h.dist curl/curlbuild.h - fi +then if action_needed curl/curlbuild.h curl/curlbuild.h.dist + then cp -p curl/curlbuild.h.dist curl/curlbuild.h + fi fi -# Create the OS/400 source program file for the include files. +# Create the OS/400 source program file for the header files. SRCPF="${LIBIFSNAME}/H.FILE" @@ -28,16 +28,25 @@ then CMD="CRTSRCPF FILE(${TARGETLIB}/H) RCDLEN(112)" fi +# Create the IFS directory for the header files. + +IFSINCLUDE="${IFSDIR}/include/curl" + +if action_needed "${IFSINCLUDE}" +then mkdir -p "${IFSINCLUDE}" +fi + + # Enumeration values are used as va_arg tagfields, so they MUST be # integers. copy_hfile() { - destfile="${1}" - srcfile="${2}" - shift - shift + destfile="${1}" + srcfile="${2}" + shift + shift sed -e '1i\ #pragma enum(int)\ ' "${@}" -e '$a\ @@ -48,23 +57,34 @@ copy_hfile() # Copy the header files. for HFILE in curl/*.h ${SCRIPTDIR}/ccsidcurl.h -do DEST="${SRCPF}/`db2_name \"${HFILE}\"`.MBR" +do case "`basename \"${HFILE}\" .h`" in + stdcheaders|typecheck-gcc) + continue;; + esac + + DEST="${SRCPF}/`db2_name \"${HFILE}\" nomangle`.MBR" + if action_needed "${DEST}" "${HFILE}" then copy_hfile "${DEST}" "${HFILE}" + IFSDEST="${IFSINCLUDE}/`basename \"${HFILE}\"`" + rm -f "${IFSDEST}" + ln -s "${DEST}" "${IFSDEST}" fi done -# Copy the ILE/RPG include file, setting-up version number. +# Copy the ILE/RPG header file, setting-up version number. - versioned_copy "${SCRIPTDIR}/curl.inc.in" "${SRCPF}/CURL.INC.MBR" +versioned_copy "${SCRIPTDIR}/curl.inc.in" "${SRCPF}/CURL.INC.MBR" +rm -f "${IFSINCLUDE}/curl.inc.rpgle" +ln -s "${SRCPF}/CURL.INC.MBR" "${IFSINCLUDE}/curl.inc.rpgle" -# Duplicate file H as CURL to support more include path forms. +# Duplicate file H as CURL to support more include path forms. if action_needed "${LIBIFSNAME}/CURL.FILE" -then : -else system "DLTF FILE(${TARGETLIB}/CURL)" +then : +else system "DLTF FILE(${TARGETLIB}/CURL)" fi CMD="CRTDUPOBJ OBJ(H) FROMLIB(${TARGETLIB}) OBJTYPE(*FILE) TOLIB(*FROMLIB)" diff --git a/packages/OS400/make-lib.sh b/packages/OS400/make-lib.sh index e2a87082d..5e1f2042b 100644 --- a/packages/OS400/make-lib.sh +++ b/packages/OS400/make-lib.sh @@ -83,12 +83,12 @@ fi # Gather the list of symbols to export. -EXPORTS=`grep '^CURL_EXTERN[ ]' \ +EXPORTS=`grep '^CURL_EXTERN[[:space:]]' \ "${TOPDIR}"/include/curl/*.h \ "${SCRIPTDIR}/ccsidcurl.h" | - sed -e 's/^.*CURL_EXTERN[ ]\(.*\)(.*$/\1/' \ - -e 's/[ ]*$//' \ - -e 's/^.*[ ][ ]*//' \ + sed -e 's/^.*CURL_EXTERN[[:space:]]\(.*\)(.*$/\1/' \ + -e 's/[[:space:]]*$//' \ + -e 's/^.*[[:space:]][[:space:]]*//' \ -e 's/^\*//' \ -e 's/(\(.*\))/\1/'` @@ -121,7 +121,11 @@ if [ "${LINK}" ] then CMD="CRTSRVPGM SRVPGM(${TARGETLIB}/${SRVPGM})" CMD="${CMD} SRCFILE(${TARGETLIB}/TOOLS) SRCMBR(BNDSRC)" CMD="${CMD} MODULE(${TARGETLIB}/OS400)" - CMD="${CMD} BNDDIR(${TARGETLIB}/${STATBNDDIR})" + CMD="${CMD} BNDDIR(${TARGETLIB}/${STATBNDDIR}" + if [ "${WITH_ZLIB}" != 0 ] + then CMD="${CMD} ${ZLIB_LIB}/${ZLIB_BNDDIR}" + fi + CMD="${CMD})" CMD="${CMD} BNDSRVPGM(QADRTTS QGLDCLNT QGLDBRDR)" CMD="${CMD} TEXT('curl API library')" CMD="${CMD} TGTRLS(${TGTRLS})" diff --git a/packages/OS400/make-tests.sh b/packages/OS400/make-tests.sh index cee3ed95d..9240b7ff6 100644 --- a/packages/OS400/make-tests.sh +++ b/packages/OS400/make-tests.sh @@ -28,11 +28,11 @@ eval "`sed -e ': begin' \ -e 's/\\\\\\n/ /' \ -e 'b begin' \ -e '}' \ - -e '/^[A-Za-z_][A-Za-z0-9_]*[ ]*[=]/b keep' \ + -e '/^[A-Za-z_][A-Za-z0-9_]*[[:space:]]*[=]/b keep' \ -e 'd' \ -e ': keep' \ - -e 's/[ ]*=[ ]*/=/' \ - -e 's/=\\(.*[^ ]\\)[ ]*$/=\\"\\1\\"/' \ + -e 's/[[:space:]]*=[[:space:]]*/=/' \ + -e 's/=\\(.*[^[:space:]]\\)[[:space:]]*$/=\\"\\1\\"/' \ -e 's/\\$(\\([^)]*\\))/${\\1}/g' \ < Makefile.inc`" diff --git a/packages/OS400/os400sys.c b/packages/OS400/os400sys.c index ab0c4fb29..90160878d 100644 --- a/packages/OS400/os400sys.c +++ b/packages/OS400/os400sys.c @@ -38,6 +38,10 @@ #include #include +#ifdef HAVE_ZLIB_H +#include +#endif + #ifdef USE_QSOSSL #include #endif @@ -241,6 +245,28 @@ buffer_undef(localkey_t key, long size) } +static char * +set_thread_string(localkey_t key, const char * s) + +{ + int i; + char * cp; + + if(!s) + return (char *) NULL; + + i = strlen(s) + 1; + cp = Curl_thread_buffer(key, MAX_CONV_EXPANSION * i + 1); + + if(cp) { + i = QadrtConvertE2A(cp, s, MAX_CONV_EXPANSION * i, i); + cp[i] = '\0'; + } + + return cp; +} + + int Curl_getnameinfo_a(const struct sockaddr * sa, curl_socklen_t salen, char * nodename, curl_socklen_t nodenamelen, @@ -434,23 +460,8 @@ char * Curl_SSL_Strerror_a(int sslreturnvalue, SSLErrorMsg * serrmsgp) { - int i; - char * cp; - char * cp2; - - cp = SSL_Strerror(sslreturnvalue, serrmsgp); - - if (!cp) - return cp; - - i = strlen(cp); - - if (!(cp2 = Curl_thread_buffer(LK_SSL_ERROR, MAX_CONV_EXPANSION * i + 1))) - return cp2; - - i = QadrtConvertE2A(cp2, cp, MAX_CONV_EXPANSION * i, i); - cp2[i] = '\0'; - return cp2; + return set_thread_string(LK_SSL_ERROR, + SSL_Strerror(sslreturnvalue, serrmsgp)); } #endif /* USE_QSOSSL */ @@ -825,23 +836,7 @@ const char * Curl_gsk_strerror_a(int gsk_return_value) { - int i; - const char * cp; - char * cp2; - - cp = gsk_strerror(gsk_return_value); - - if (!cp) - return cp; - - i = strlen(cp); - - if (!(cp2 = Curl_thread_buffer(LK_GSK_ERROR, MAX_CONV_EXPANSION * i + 1))) - return cp2; - - i = QadrtConvertE2A(cp2, cp, MAX_CONV_EXPANSION * i, i); - cp2[i] = '\0'; - return cp2; + return set_thread_string(LK_GSK_ERROR, gsk_strerror(gsk_return_value)); } int @@ -1235,23 +1230,7 @@ char * Curl_ldap_err2string_a(int error) { - int i; - char * cp; - char * cp2; - - cp = ldap_err2string(error); - - if (!cp) - return cp; - - i = strlen(cp); - - if (!(cp2 = Curl_thread_buffer(LK_LDAP_ERROR, MAX_CONV_EXPANSION * i + 1))) - return cp2; - - i = QadrtConvertE2A(cp2, cp, MAX_CONV_EXPANSION * i, i); - cp2[i] = '\0'; - return cp2; + return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error)); } @@ -1492,3 +1471,79 @@ Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags, *addrlen = laddrlen; return rcvlen; } + + +#ifdef HAVE_LIBZ +const char * +Curl_os400_zlibVersion(void) + +{ + return set_thread_string(LK_ZLIB_VERSION, zlibVersion()); +} + + +int +Curl_os400_inflateInit_(z_streamp strm, const char * version, int stream_size) + +{ + z_const char * msgb4 = strm->msg; + int ret; + + ret = inflateInit(strm); + + if(strm->msg != msgb4) + strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); + + return ret; +} + + +int +Curl_os400_inflateInit2_(z_streamp strm, int windowBits, + const char * version, int stream_size) + +{ + z_const char * msgb4 = strm->msg; + int ret; + + ret = inflateInit2(strm, windowBits); + + if(strm->msg != msgb4) + strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); + + return ret; +} + + +int +Curl_os400_inflate(z_streamp strm, int flush) + +{ + z_const char * msgb4 = strm->msg; + int ret; + + ret = inflate(strm, flush); + + if(strm->msg != msgb4) + strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); + + return ret; +} + + +int +Curl_os400_inflateEnd(z_streamp strm) + +{ + z_const char * msgb4 = strm->msg; + int ret; + + ret = inflateEnd(strm); + + if(strm->msg != msgb4) + strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg); + + return ret; +} + +#endif diff --git a/packages/OS400/os400sys.h b/packages/OS400/os400sys.h index 234bf5e80..114469222 100644 --- a/packages/OS400/os400sys.h +++ b/packages/OS400/os400sys.h @@ -39,6 +39,8 @@ typedef enum { LK_EASY_STRERROR, LK_SHARE_STRERROR, LK_MULTI_STRERROR, + LK_ZLIB_VERSION, + LK_ZLIB_MSG, LK_LAST } localkey_t; -- cgit v1.2.3