OS400: sync RPG wrapper, zlib support, fix header file names, ...
authorPatrick Monnerat <pm@datasphere.ch>
Fri, 25 Oct 2013 16:37:37 +0000 (18:37 +0200)
committerPatrick Monnerat <pm@datasphere.ch>
Fri, 25 Oct 2013 16:37:37 +0000 (18:37 +0200)
IFS compilation support, SSL GSKit backend by default, TLSv1.[12] support in
  GSKit for OS400 >= V7R1, no more tabs in make scripts.

12 files changed:
lib/config-os400.h
lib/gskit.c
lib/setup-os400.h
packages/OS400/README.OS400
packages/OS400/ccsidcurl.c
packages/OS400/curl.inc.in
packages/OS400/initscript.sh
packages/OS400/make-include.sh
packages/OS400/make-lib.sh
packages/OS400/make-tests.sh
packages/OS400/os400sys.c
packages/OS400/os400sys.h

index a290fe4..8896277 100644 (file)
 #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"
index 187c58d..d50748e 100644 (file)
 
 /* 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 <limits.h>
 #endif
 #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. */
index 319efec..37dc05b 100644 (file)
@@ -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 */
index 73e81f8..4a39738 100644 (file)
@@ -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.
index a37f790..9049d9e 100644 (file)
@@ -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);
 
index b14d84f..edd5167 100644 (file)
      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'
      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
      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...
      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
      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...
      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)
index c07355f..64147e3 100644 (file)
@@ -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
 }
 
 
index 834ee2f..ad72cf4 100644 (file)
@@ -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)"
index e2a8708..5e1f204 100644 (file)
@@ -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})"
index cee3ed9..9240b7f 100644 (file)
@@ -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`"
 
index ab0c4fb..9016087 100644 (file)
 #include <qadrt.h>
 #include <errno.h>
 
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+
 #ifdef USE_QSOSSL
 #include <qsossl.h>
 #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
index 234bf5e..1144692 100644 (file)
@@ -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;