Home | History | Annotate | Download | only in OS400
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel (at) haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.haxx.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  *
     22  ***************************************************************************/
     23 
     24 /* OS/400 additional support. */
     25 
     26 #include <curl/curl.h>
     27 #include "config-os400.h"  /* Not curl_setup.h: we only need some defines. */
     28 
     29 #include <sys/types.h>
     30 #include <sys/socket.h>
     31 #include <sys/un.h>
     32 
     33 #include <stdlib.h>
     34 #include <stddef.h>
     35 #include <string.h>
     36 #include <pthread.h>
     37 #include <netdb.h>
     38 #include <qadrt.h>
     39 #include <errno.h>
     40 
     41 #ifdef HAVE_ZLIB_H
     42 #include <zlib.h>
     43 #endif
     44 
     45 #ifdef USE_GSKIT
     46 #include <gskssl.h>
     47 #include <qsoasync.h>
     48 #endif
     49 
     50 #ifdef HAVE_GSSAPI
     51 #include <gssapi.h>
     52 #endif
     53 
     54 #ifndef CURL_DISABLE_LDAP
     55 #include <ldap.h>
     56 #endif
     57 
     58 #include <netinet/in.h>
     59 #include <arpa/inet.h>
     60 
     61 #include "os400sys.h"
     62 
     63 
     64 /**
     65 ***     QADRT OS/400 ASCII runtime defines only the most used procedures, but
     66 ***             but a lot of them are not supported. This module implements
     67 ***             ASCII wrappers for those that are used by libcurl, but not
     68 ***             defined by QADRT.
     69 **/
     70 
     71 #pragma convert(0)                              /* Restore EBCDIC. */
     72 
     73 
     74 #define MIN_BYTE_GAIN   1024    /* Minimum gain when shortening a buffer. */
     75 
     76 typedef struct {
     77         unsigned long   size;                   /* Buffer size. */
     78         char *          buf;                    /* Buffer address. */
     79 }               buffer_t;
     80 
     81 
     82 static char *   buffer_undef(localkey_t key, long size);
     83 static char *   buffer_threaded(localkey_t key, long size);
     84 static char *   buffer_unthreaded(localkey_t key, long size);
     85 
     86 static pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;
     87 static pthread_key_t    thdkey;
     88 static buffer_t *       locbufs;
     89 
     90 char *  (* Curl_thread_buffer)(localkey_t key, long size) = buffer_undef;
     91 
     92 
     93 static void
     94 thdbufdestroy(void * private)
     95 
     96 {
     97   if(private) {
     98     buffer_t * p = (buffer_t *) private;
     99     localkey_t i;
    100 
    101     for(i = (localkey_t) 0; i < LK_LAST; i++) {
    102       free(p->buf);
    103       p++;
    104       }
    105 
    106     free(private);
    107     }
    108 }
    109 
    110 
    111 static void
    112 terminate(void)
    113 
    114 {
    115   if(Curl_thread_buffer == buffer_threaded) {
    116     locbufs = pthread_getspecific(thdkey);
    117     pthread_setspecific(thdkey, (void *) NULL);
    118     pthread_key_delete(thdkey);
    119     }
    120 
    121   if(Curl_thread_buffer != buffer_undef) {
    122     thdbufdestroy((void *) locbufs);
    123     locbufs = (buffer_t *) NULL;
    124     }
    125 
    126   Curl_thread_buffer = buffer_undef;
    127 }
    128 
    129 
    130 static char *
    131 get_buffer(buffer_t * buf, long size)
    132 
    133 {
    134   char * cp;
    135 
    136   /* If `size' >= 0, make sure buffer at `buf' is at least `size'-byte long.
    137      Return the buffer address. */
    138 
    139   if(size < 0)
    140     return buf->buf;
    141 
    142   if(!buf->buf) {
    143     buf->buf = malloc(size);
    144     if(buf->buf)
    145       buf->size = size;
    146 
    147     return buf->buf;
    148   }
    149 
    150   if((unsigned long) size <= buf->size) {
    151     /* Shorten the buffer only if it frees a significant byte count. This
    152        avoids some realloc() overhead. */
    153 
    154     if(buf->size - size < MIN_BYTE_GAIN)
    155       return buf->buf;
    156   }
    157 
    158   /* Resize the buffer. */
    159 
    160   cp = realloc(buf->buf, size);
    161   if(cp) {
    162     buf->buf = cp;
    163     buf->size = size;
    164   }
    165   else if(size <= buf->size)
    166     cp = buf->buf;
    167 
    168   return cp;
    169 }
    170 
    171 
    172 static char *
    173 buffer_unthreaded(localkey_t key, long size)
    174 
    175 {
    176   return get_buffer(locbufs + key, size);
    177 }
    178 
    179 
    180 static char *
    181 buffer_threaded(localkey_t key, long size)
    182 
    183 {
    184   buffer_t * bufs;
    185 
    186   /* Get the buffer for the given local key in the current thread, and
    187      make sure it is at least `size'-byte long. Set `size' to < 0 to get
    188      its address only. */
    189 
    190   bufs = (buffer_t *) pthread_getspecific(thdkey);
    191 
    192   if(!bufs) {
    193     if(size < 0)
    194       return (char *) NULL;             /* No buffer yet. */
    195 
    196     /* Allocate buffer descriptors for the current thread. */
    197 
    198     bufs = calloc((size_t) LK_LAST, sizeof *bufs);
    199     if(!bufs)
    200       return (char *) NULL;
    201 
    202     if(pthread_setspecific(thdkey, (void *) bufs)) {
    203       free(bufs);
    204       return (char *) NULL;
    205     }
    206   }
    207 
    208   return get_buffer(bufs + key, size);
    209 }
    210 
    211 
    212 static char *
    213 buffer_undef(localkey_t key, long size)
    214 
    215 {
    216   /* Define the buffer system, get the buffer for the given local key in
    217      the current thread, and make sure it is at least `size'-byte long.
    218      Set `size' to < 0 to get its address only. */
    219 
    220   pthread_mutex_lock(&mutex);
    221 
    222   /* Determine if we can use pthread-specific data. */
    223 
    224   if(Curl_thread_buffer == buffer_undef) {      /* If unchanged during lock. */
    225     if(!pthread_key_create(&thdkey, thdbufdestroy))
    226       Curl_thread_buffer = buffer_threaded;
    227     else if(!(locbufs = calloc((size_t) LK_LAST, sizeof *locbufs))) {
    228       pthread_mutex_unlock(&mutex);
    229       return (char *) NULL;
    230       }
    231     else
    232         Curl_thread_buffer = buffer_unthreaded;
    233 
    234     atexit(terminate);
    235     }
    236 
    237   pthread_mutex_unlock(&mutex);
    238   return Curl_thread_buffer(key, size);
    239 }
    240 
    241 
    242 static char *
    243 set_thread_string(localkey_t key, const char * s)
    244 
    245 {
    246   int i;
    247   char * cp;
    248 
    249   if(!s)
    250     return (char *) NULL;
    251 
    252   i = strlen(s) + 1;
    253   cp = Curl_thread_buffer(key, MAX_CONV_EXPANSION * i + 1);
    254 
    255   if(cp) {
    256     i = QadrtConvertE2A(cp, s, MAX_CONV_EXPANSION * i, i);
    257     cp[i] = '\0';
    258   }
    259 
    260   return cp;
    261 }
    262 
    263 
    264 int
    265 Curl_getnameinfo_a(const struct sockaddr * sa, curl_socklen_t salen,
    266               char * nodename, curl_socklen_t nodenamelen,
    267               char * servname, curl_socklen_t servnamelen,
    268               int flags)
    269 
    270 {
    271   char * enodename;
    272   char * eservname;
    273   int status;
    274   int i;
    275 
    276   enodename = (char *) NULL;
    277   eservname = (char *) NULL;
    278 
    279   if(nodename && nodenamelen) {
    280     enodename = malloc(nodenamelen);
    281     if(!enodename)
    282       return EAI_MEMORY;
    283   }
    284 
    285   if(servname && servnamelen) {
    286     eservname = malloc(servnamelen);
    287     if(!eservname) {
    288       free(enodename);
    289       return EAI_MEMORY;
    290     }
    291   }
    292 
    293   status = getnameinfo(sa, salen, enodename, nodenamelen,
    294                        eservname, servnamelen, flags);
    295 
    296   if(!status) {
    297     if(enodename) {
    298       i = QadrtConvertE2A(nodename, enodename,
    299         nodenamelen - 1, strlen(enodename));
    300       nodename[i] = '\0';
    301       }
    302 
    303     if(eservname) {
    304       i = QadrtConvertE2A(servname, eservname,
    305         servnamelen - 1, strlen(eservname));
    306       servname[i] = '\0';
    307       }
    308     }
    309 
    310   free(enodename);
    311   free(eservname);
    312   return status;
    313 }
    314 
    315 
    316 int
    317 Curl_getaddrinfo_a(const char * nodename, const char * servname,
    318             const struct addrinfo * hints,
    319             struct addrinfo * * res)
    320 
    321 {
    322   char * enodename;
    323   char * eservname;
    324   int status;
    325   int i;
    326 
    327   enodename = (char *) NULL;
    328   eservname = (char *) NULL;
    329 
    330   if(nodename) {
    331     i = strlen(nodename);
    332 
    333     enodename = malloc(i + 1);
    334     if(!enodename)
    335       return EAI_MEMORY;
    336 
    337     i = QadrtConvertA2E(enodename, nodename, i, i);
    338     enodename[i] = '\0';
    339   }
    340 
    341   if(servname) {
    342     i = strlen(servname);
    343 
    344     eservname = malloc(i + 1);
    345     if(!eservname) {
    346       free(enodename);
    347       return EAI_MEMORY;
    348     }
    349 
    350     QadrtConvertA2E(eservname, servname, i, i);
    351     eservname[i] = '\0';
    352   }
    353 
    354   status = getaddrinfo(enodename, eservname, hints, res);
    355   free(enodename);
    356   free(eservname);
    357   return status;
    358 }
    359 
    360 
    361 #ifdef USE_GSKIT
    362 
    363 /* ASCII wrappers for the GSKit procedures. */
    364 
    365 /*
    366  * EBCDIC --> ASCII string mapping table.
    367  * Some strings returned by GSKit are dynamically allocated and automatically
    368  * released when closing the handle.
    369  * To provide the same functionality, we use a "private" handle that
    370  * holds the GSKit handle and a list of string mappings. This will allow
    371  * avoid conversion of already converted strings and releasing them upon
    372  * close time.
    373  */
    374 
    375 struct gskstrlist {
    376   struct gskstrlist * next;
    377   const char * ebcdicstr;
    378   const char * asciistr;
    379 };
    380 
    381 struct Curl_gsk_descriptor {
    382   gsk_handle h;
    383   struct gskstrlist * strlist;
    384 };
    385 
    386 
    387 int
    388 Curl_gsk_environment_open(gsk_handle * my_env_handle)
    389 
    390 {
    391   struct Curl_gsk_descriptor * p;
    392   gsk_handle h;
    393   int rc;
    394 
    395   if(!my_env_handle)
    396     return GSK_OS400_ERROR_INVALID_POINTER;
    397   p = (struct Curl_gsk_descriptor *) malloc(sizeof *p);
    398   if(!p)
    399     return GSK_INSUFFICIENT_STORAGE;
    400   p->strlist = (struct gskstrlist *) NULL;
    401   rc = gsk_environment_open(&p->h);
    402   if(rc != GSK_OK)
    403     free(p);
    404   else
    405     *my_env_handle = (gsk_handle) p;
    406   return rc;
    407 }
    408 
    409 
    410 int
    411 Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
    412                          gsk_handle * my_session_handle)
    413 
    414 {
    415   struct Curl_gsk_descriptor * p;
    416   gsk_handle h;
    417   int rc;
    418 
    419   if(!my_env_handle)
    420     return GSK_INVALID_HANDLE;
    421   if(!my_session_handle)
    422     return GSK_OS400_ERROR_INVALID_POINTER;
    423   h = ((struct Curl_gsk_descriptor *) my_env_handle)->h;
    424   p = (struct Curl_gsk_descriptor *) malloc(sizeof *p);
    425   if(!p)
    426     return GSK_INSUFFICIENT_STORAGE;
    427   p->strlist = (struct gskstrlist *) NULL;
    428   rc = gsk_secure_soc_open(h, &p->h);
    429   if(rc != GSK_OK)
    430     free(p);
    431   else
    432     *my_session_handle = (gsk_handle) p;
    433   return rc;
    434 }
    435 
    436 
    437 static void
    438 gsk_free_handle(struct Curl_gsk_descriptor * p)
    439 
    440 {
    441   struct gskstrlist * q;
    442 
    443   while((q = p->strlist)) {
    444     p->strlist = q;
    445     free((void *) q->asciistr);
    446     free(q);
    447   }
    448   free(p);
    449 }
    450 
    451 
    452 int
    453 Curl_gsk_environment_close(gsk_handle * my_env_handle)
    454 
    455 {
    456   struct Curl_gsk_descriptor * p;
    457   int rc;
    458 
    459   if(!my_env_handle)
    460     return GSK_OS400_ERROR_INVALID_POINTER;
    461   if(!*my_env_handle)
    462     return GSK_INVALID_HANDLE;
    463   p = (struct Curl_gsk_descriptor *) *my_env_handle;
    464   rc = gsk_environment_close(&p->h);
    465   if(rc == GSK_OK) {
    466     gsk_free_handle(p);
    467     *my_env_handle = (gsk_handle) NULL;
    468   }
    469   return rc;
    470 }
    471 
    472 
    473 int
    474 Curl_gsk_secure_soc_close(gsk_handle * my_session_handle)
    475 
    476 {
    477   struct Curl_gsk_descriptor * p;
    478   int rc;
    479 
    480   if(!my_session_handle)
    481     return GSK_OS400_ERROR_INVALID_POINTER;
    482   if(!*my_session_handle)
    483     return GSK_INVALID_HANDLE;
    484   p = (struct Curl_gsk_descriptor *) *my_session_handle;
    485   rc = gsk_secure_soc_close(&p->h);
    486   if(rc == GSK_OK) {
    487     gsk_free_handle(p);
    488     *my_session_handle = (gsk_handle) NULL;
    489   }
    490   return rc;
    491 }
    492 
    493 
    494 int
    495 Curl_gsk_environment_init(gsk_handle my_env_handle)
    496 
    497 {
    498   struct Curl_gsk_descriptor * p;
    499 
    500   if(!my_env_handle)
    501     return GSK_INVALID_HANDLE;
    502   p = (struct Curl_gsk_descriptor *) my_env_handle;
    503   return gsk_environment_init(p->h);
    504 }
    505 
    506 
    507 int
    508 Curl_gsk_secure_soc_init(gsk_handle my_session_handle)
    509 
    510 {
    511   struct Curl_gsk_descriptor * p;
    512 
    513   if(!my_session_handle)
    514     return GSK_INVALID_HANDLE;
    515   p = (struct Curl_gsk_descriptor *) my_session_handle;
    516   return gsk_secure_soc_init(p->h);
    517 }
    518 
    519 
    520 int
    521 Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
    522                                 const char * buffer, int bufSize)
    523 
    524 {
    525   struct Curl_gsk_descriptor * p;
    526   char * ebcdicbuf;
    527   int rc;
    528 
    529   if(!my_gsk_handle)
    530     return GSK_INVALID_HANDLE;
    531   if(!buffer)
    532     return GSK_OS400_ERROR_INVALID_POINTER;
    533   if(bufSize < 0)
    534     return GSK_ATTRIBUTE_INVALID_LENGTH;
    535   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
    536   if(!bufSize)
    537     bufSize = strlen(buffer);
    538   ebcdicbuf = malloc(bufSize + 1);
    539   if(!ebcdicbuf)
    540     return GSK_INSUFFICIENT_STORAGE;
    541   QadrtConvertA2E(ebcdicbuf, buffer, bufSize, bufSize);
    542   ebcdicbuf[bufSize] = '\0';
    543   rc = gsk_attribute_set_buffer(p->h, bufID, ebcdicbuf, bufSize);
    544   free(ebcdicbuf);
    545   return rc;
    546 }
    547 
    548 
    549 int
    550 Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID,
    551                             GSK_ENUM_VALUE enumValue)
    552 
    553 {
    554   struct Curl_gsk_descriptor * p;
    555 
    556   if(!my_gsk_handle)
    557     return GSK_INVALID_HANDLE;
    558   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
    559   return gsk_attribute_set_enum(p->h, enumID, enumValue);
    560 }
    561 
    562 
    563 int
    564 Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
    565                                      GSK_NUM_ID numID, int numValue)
    566 
    567 {
    568   struct Curl_gsk_descriptor * p;
    569 
    570   if(!my_gsk_handle)
    571     return GSK_INVALID_HANDLE;
    572   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
    573   return gsk_attribute_set_numeric_value(p->h, numID, numValue);
    574 }
    575 
    576 
    577 int
    578 Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
    579                                 GSK_CALLBACK_ID callBackID,
    580                                 void * callBackAreaPtr)
    581 
    582 {
    583   struct Curl_gsk_descriptor * p;
    584 
    585   if(!my_gsk_handle)
    586     return GSK_INVALID_HANDLE;
    587   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
    588   return gsk_attribute_set_callback(p->h, callBackID, callBackAreaPtr);
    589 }
    590 
    591 
    592 static int
    593 cachestring(struct Curl_gsk_descriptor * p,
    594             const char * ebcdicbuf, int bufsize, const char * * buffer)
    595 
    596 {
    597   int rc;
    598   char * asciibuf;
    599   struct gskstrlist * sp;
    600 
    601   for(sp = p->strlist; sp; sp = sp->next)
    602     if(sp->ebcdicstr == ebcdicbuf)
    603       break;
    604   if(!sp) {
    605     sp = (struct gskstrlist *) malloc(sizeof *sp);
    606     if(!sp)
    607       return GSK_INSUFFICIENT_STORAGE;
    608     asciibuf = malloc(bufsize + 1);
    609     if(!asciibuf) {
    610       free(sp);
    611       return GSK_INSUFFICIENT_STORAGE;
    612     }
    613     QadrtConvertE2A(asciibuf, ebcdicbuf, bufsize, bufsize);
    614     asciibuf[bufsize] = '\0';
    615     sp->ebcdicstr = ebcdicbuf;
    616     sp->asciistr = asciibuf;
    617     sp->next = p->strlist;
    618     p->strlist = sp;
    619   }
    620   *buffer = sp->asciistr;
    621   return GSK_OK;
    622 }
    623 
    624 
    625 int
    626 Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
    627                                 const char * * buffer, int * bufSize)
    628 
    629 {
    630   struct Curl_gsk_descriptor * p;
    631   int rc;
    632   const char * mybuf;
    633   int mylen;
    634 
    635   if(!my_gsk_handle)
    636     return GSK_INVALID_HANDLE;
    637   if(!buffer || !bufSize)
    638     return GSK_OS400_ERROR_INVALID_POINTER;
    639   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
    640   rc = gsk_attribute_get_buffer(p->h, bufID, &mybuf, &mylen);
    641   if(rc != GSK_OK)
    642     return rc;
    643   rc = cachestring(p, mybuf, mylen, buffer);
    644   if(rc == GSK_OK)
    645     *bufSize = mylen;
    646   return rc;
    647 }
    648 
    649 
    650 int
    651 Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID,
    652                             GSK_ENUM_VALUE * enumValue)
    653 
    654 {
    655   struct Curl_gsk_descriptor * p;
    656 
    657   if(!my_gsk_handle)
    658     return GSK_INVALID_HANDLE;
    659   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
    660   return gsk_attribute_get_enum(p->h, enumID, enumValue);
    661 }
    662 
    663 
    664 int
    665 Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
    666                                      GSK_NUM_ID numID, int * numValue)
    667 
    668 {
    669   struct Curl_gsk_descriptor * p;
    670 
    671   if(!my_gsk_handle)
    672     return GSK_INVALID_HANDLE;
    673   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
    674   return gsk_attribute_get_numeric_value(p->h, numID, numValue);
    675 }
    676 
    677 
    678 int
    679 Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
    680                                  GSK_CERT_ID certID,
    681                                  const gsk_cert_data_elem * * certDataElem,
    682                                  int * certDataElementCount)
    683 
    684 {
    685   struct Curl_gsk_descriptor * p;
    686 
    687   if(!my_gsk_handle)
    688     return GSK_INVALID_HANDLE;
    689   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
    690   /* No need to convert code: text results are already in ASCII. */
    691   return gsk_attribute_get_cert_info(p->h, certID,
    692                                      certDataElem, certDataElementCount);
    693 }
    694 
    695 
    696 int
    697 Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, GSK_MISC_ID miscID)
    698 
    699 {
    700   struct Curl_gsk_descriptor * p;
    701 
    702   if(!my_session_handle)
    703     return GSK_INVALID_HANDLE;
    704   p = (struct Curl_gsk_descriptor *) my_session_handle;
    705   return gsk_secure_soc_misc(p->h, miscID);
    706 }
    707 
    708 
    709 int
    710 Curl_gsk_secure_soc_read(gsk_handle my_session_handle, char * readBuffer,
    711                          int readBufSize, int * amtRead)
    712 
    713 {
    714   struct Curl_gsk_descriptor * p;
    715 
    716   if(!my_session_handle)
    717     return GSK_INVALID_HANDLE;
    718   p = (struct Curl_gsk_descriptor *) my_session_handle;
    719   return gsk_secure_soc_read(p->h, readBuffer, readBufSize, amtRead);
    720 }
    721 
    722 
    723 int
    724 Curl_gsk_secure_soc_write(gsk_handle my_session_handle, char * writeBuffer,
    725                           int writeBufSize, int * amtWritten)
    726 
    727 {
    728   struct Curl_gsk_descriptor * p;
    729 
    730   if(!my_session_handle)
    731     return GSK_INVALID_HANDLE;
    732   p = (struct Curl_gsk_descriptor *) my_session_handle;
    733   return gsk_secure_soc_write(p->h, writeBuffer, writeBufSize, amtWritten);
    734 }
    735 
    736 
    737 const char *
    738 Curl_gsk_strerror_a(int gsk_return_value)
    739 
    740 {
    741   return set_thread_string(LK_GSK_ERROR, gsk_strerror(gsk_return_value));
    742 }
    743 
    744 int
    745 Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,
    746                               int IOCompletionPort,
    747                               Qso_OverlappedIO_t * communicationsArea)
    748 
    749 {
    750   struct Curl_gsk_descriptor * p;
    751 
    752   if(!my_session_handle)
    753     return GSK_INVALID_HANDLE;
    754   p = (struct Curl_gsk_descriptor *) my_session_handle;
    755   return gsk_secure_soc_startInit(p->h, IOCompletionPort, communicationsArea);
    756 }
    757 
    758 #endif /* USE_GSKIT */
    759 
    760 
    761 
    762 #ifdef HAVE_GSSAPI
    763 
    764 /* ASCII wrappers for the GSSAPI procedures. */
    765 
    766 static int
    767 Curl_gss_convert_in_place(OM_uint32 * minor_status, gss_buffer_t buf)
    768 
    769 {
    770   unsigned int i;
    771   char * t;
    772 
    773   /* Convert `buf' in place, from EBCDIC to ASCII.
    774      If error, release the buffer and return -1. Else return 0. */
    775 
    776   i = buf->length;
    777 
    778   if(i) {
    779     t = malloc(i);
    780     if(!t) {
    781       gss_release_buffer(minor_status, buf);
    782 
    783       if(minor_status)
    784         *minor_status = ENOMEM;
    785 
    786       return -1;
    787     }
    788 
    789     QadrtConvertE2A(t, buf->value, i, i);
    790     memcpy(buf->value, t, i);
    791     free(t);
    792   }
    793 
    794   return 0;
    795 }
    796 
    797 
    798 OM_uint32
    799 Curl_gss_import_name_a(OM_uint32 * minor_status, gss_buffer_t in_name,
    800                        gss_OID in_name_type, gss_name_t * out_name)
    801 
    802 {
    803   int rc;
    804   unsigned int i;
    805   gss_buffer_desc in;
    806 
    807   if(!in_name || !in_name->value || !in_name->length)
    808     return gss_import_name(minor_status, in_name, in_name_type, out_name);
    809 
    810   memcpy((char *) &in, (char *) in_name, sizeof in);
    811   i = in.length;
    812 
    813   in.value = malloc(i + 1);
    814   if(!in.value) {
    815     if(minor_status)
    816       *minor_status = ENOMEM;
    817 
    818     return GSS_S_FAILURE;
    819   }
    820 
    821   QadrtConvertA2E(in.value, in_name->value, i, i);
    822   ((char *) in.value)[i] = '\0';
    823   rc = gss_import_name(minor_status, &in, in_name_type, out_name);
    824   free(in.value);
    825   return rc;
    826 }
    827 
    828 
    829 OM_uint32
    830 Curl_gss_display_status_a(OM_uint32 * minor_status, OM_uint32 status_value,
    831                    int status_type, gss_OID mech_type,
    832                    gss_msg_ctx_t * message_context, gss_buffer_t status_string)
    833 
    834 {
    835   int rc;
    836 
    837   rc = gss_display_status(minor_status, status_value, status_type,
    838                               mech_type, message_context, status_string);
    839 
    840   if(rc != GSS_S_COMPLETE || !status_string ||
    841      !status_string->length || !status_string->value)
    842     return rc;
    843 
    844   /* No way to allocate a buffer here, because it will be released by
    845      gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
    846      with ASCII to return it. */
    847 
    848   if(Curl_gss_convert_in_place(minor_status, status_string))
    849     return GSS_S_FAILURE;
    850 
    851   return rc;
    852 }
    853 
    854 
    855 OM_uint32
    856 Curl_gss_init_sec_context_a(OM_uint32 * minor_status,
    857                             gss_cred_id_t cred_handle,
    858                             gss_ctx_id_t * context_handle,
    859                             gss_name_t target_name, gss_OID mech_type,
    860                             gss_flags_t req_flags, OM_uint32 time_req,
    861                             gss_channel_bindings_t input_chan_bindings,
    862                             gss_buffer_t input_token,
    863                             gss_OID * actual_mech_type,
    864                             gss_buffer_t output_token, gss_flags_t * ret_flags,
    865                             OM_uint32 * time_rec)
    866 
    867 {
    868   int rc;
    869   unsigned int i;
    870   gss_buffer_desc in;
    871   gss_buffer_t inp;
    872 
    873   in.value = NULL;
    874   inp = input_token;
    875 
    876   if(inp) {
    877     if(inp->length && inp->value) {
    878       i = inp->length;
    879 
    880       in.value = malloc(i + 1);
    881       if(!in.value) {
    882         if(minor_status)
    883           *minor_status = ENOMEM;
    884 
    885         return GSS_S_FAILURE;
    886       }
    887 
    888       QadrtConvertA2E(in.value, input_token->value, i, i);
    889       ((char *) in.value)[i] = '\0';
    890       in.length = i;
    891       inp = &in;
    892     }
    893   }
    894 
    895   rc = gss_init_sec_context(minor_status, cred_handle, context_handle,
    896                              target_name, mech_type, req_flags, time_req,
    897                              input_chan_bindings, inp, actual_mech_type,
    898                              output_token, ret_flags, time_rec);
    899   free(in.value);
    900 
    901   if(rc != GSS_S_COMPLETE || !output_token ||
    902       !output_token->length || !output_token->value)
    903     return rc;
    904 
    905   /* No way to allocate a buffer here, because it will be released by
    906      gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
    907      with ASCII to return it. */
    908 
    909   if(Curl_gss_convert_in_place(minor_status, output_token))
    910     return GSS_S_FAILURE;
    911 
    912   return rc;
    913 }
    914 
    915 
    916 OM_uint32
    917 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
    918                               gss_ctx_id_t * context_handle,
    919                               gss_buffer_t output_token)
    920 
    921 {
    922   int rc;
    923 
    924   rc = gss_delete_sec_context(minor_status, context_handle, output_token);
    925 
    926   if(rc != GSS_S_COMPLETE || !output_token ||
    927       !output_token->length || !output_token->value)
    928     return rc;
    929 
    930   /* No way to allocate a buffer here, because it will be released by
    931      gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
    932      with ASCII to return it. */
    933 
    934   if(Curl_gss_convert_in_place(minor_status, output_token))
    935     return GSS_S_FAILURE;
    936 
    937   return rc;
    938 }
    939 
    940 #endif /* HAVE_GSSAPI */
    941 
    942 
    943 #ifndef CURL_DISABLE_LDAP
    944 
    945 /* ASCII wrappers for the LDAP procedures. */
    946 
    947 void *
    948 Curl_ldap_init_a(char * host, int port)
    949 
    950 {
    951   unsigned int i;
    952   char * ehost;
    953   void * result;
    954 
    955   if(!host)
    956     return (void *) ldap_init(host, port);
    957 
    958   i = strlen(host);
    959 
    960   ehost = malloc(i + 1);
    961   if(!ehost)
    962     return (void *) NULL;
    963 
    964   QadrtConvertA2E(ehost, host, i, i);
    965   ehost[i] = '\0';
    966   result = (void *) ldap_init(ehost, port);
    967   free(ehost);
    968   return result;
    969 }
    970 
    971 
    972 int
    973 Curl_ldap_simple_bind_s_a(void * ld, char * dn, char * passwd)
    974 
    975 {
    976   int i;
    977   char * edn;
    978   char * epasswd;
    979 
    980   edn = (char *) NULL;
    981   epasswd = (char *) NULL;
    982 
    983   if(dn) {
    984     i = strlen(dn);
    985 
    986     edn = malloc(i + 1);
    987     if(!edn)
    988       return LDAP_NO_MEMORY;
    989 
    990     QadrtConvertA2E(edn, dn, i, i);
    991     edn[i] = '\0';
    992   }
    993 
    994   if(passwd) {
    995     i = strlen(passwd);
    996 
    997     epasswd = malloc(i + 1);
    998     if(!epasswd) {
    999       free(edn);
   1000       return LDAP_NO_MEMORY;
   1001     }
   1002 
   1003     QadrtConvertA2E(epasswd, passwd, i, i);
   1004     epasswd[i] = '\0';
   1005   }
   1006 
   1007   i = ldap_simple_bind_s(ld, edn, epasswd);
   1008   free(epasswd);
   1009   free(edn);
   1010   return i;
   1011 }
   1012 
   1013 
   1014 int
   1015 Curl_ldap_search_s_a(void * ld, char * base, int scope, char * filter,
   1016                      char * * attrs, int attrsonly, LDAPMessage * * res)
   1017 
   1018 {
   1019   int i;
   1020   int j;
   1021   char * ebase;
   1022   char * efilter;
   1023   char * * eattrs;
   1024   int status;
   1025 
   1026   ebase = (char *) NULL;
   1027   efilter = (char *) NULL;
   1028   eattrs = (char * *) NULL;
   1029   status = LDAP_SUCCESS;
   1030 
   1031   if(base) {
   1032     i = strlen(base);
   1033 
   1034     ebase = malloc(i + 1);
   1035     if(!ebase)
   1036       status = LDAP_NO_MEMORY;
   1037     else {
   1038       QadrtConvertA2E(ebase, base, i, i);
   1039       ebase[i] = '\0';
   1040     }
   1041   }
   1042 
   1043   if(filter && status == LDAP_SUCCESS) {
   1044     i = strlen(filter);
   1045 
   1046     efilter = malloc(i + 1);
   1047     if(!efilter)
   1048       status = LDAP_NO_MEMORY;
   1049     else {
   1050       QadrtConvertA2E(efilter, filter, i, i);
   1051       efilter[i] = '\0';
   1052     }
   1053   }
   1054 
   1055   if(attrs && status == LDAP_SUCCESS) {
   1056     for(i = 0; attrs[i++];)
   1057       ;
   1058 
   1059     eattrs = calloc(i, sizeof *eattrs);
   1060     if(!eattrs)
   1061       status = LDAP_NO_MEMORY;
   1062     else {
   1063       for(j = 0; attrs[j]; j++) {
   1064         i = strlen(attrs[j]);
   1065 
   1066         eattrs[j] = malloc(i + 1);
   1067         if(!eattrs[j]) {
   1068           status = LDAP_NO_MEMORY;
   1069           break;
   1070         }
   1071 
   1072         QadrtConvertA2E(eattrs[j], attrs[j], i, i);
   1073         eattrs[j][i] = '\0';
   1074         }
   1075       }
   1076     }
   1077 
   1078   if(status == LDAP_SUCCESS)
   1079     status = ldap_search_s(ld, ebase? ebase: "", scope,
   1080                            efilter? efilter: "(objectclass=*)",
   1081                            eattrs, attrsonly, res);
   1082 
   1083   if(eattrs) {
   1084     for(j = 0; eattrs[j]; j++)
   1085       free(eattrs[j]);
   1086 
   1087     free(eattrs);
   1088     }
   1089 
   1090   free(efilter);
   1091   free(ebase);
   1092   return status;
   1093 }
   1094 
   1095 
   1096 struct berval * *
   1097 Curl_ldap_get_values_len_a(void * ld, LDAPMessage * entry, const char * attr)
   1098 
   1099 {
   1100   char * cp;
   1101   struct berval * * result;
   1102 
   1103   cp = (char *) NULL;
   1104 
   1105   if(attr) {
   1106     int i = strlen(attr);
   1107 
   1108     cp = malloc(i + 1);
   1109     if(!cp) {
   1110       ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL,
   1111                        ldap_err2string(LDAP_NO_MEMORY));
   1112       return (struct berval * *) NULL;
   1113     }
   1114 
   1115     QadrtConvertA2E(cp, attr, i, i);
   1116     cp[i] = '\0';
   1117   }
   1118 
   1119   result = ldap_get_values_len(ld, entry, cp);
   1120   free(cp);
   1121 
   1122   /* Result data are binary in nature, so they haven't been
   1123      converted to EBCDIC. Therefore do not convert. */
   1124 
   1125   return result;
   1126 }
   1127 
   1128 
   1129 char *
   1130 Curl_ldap_err2string_a(int error)
   1131 
   1132 {
   1133   return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error));
   1134 }
   1135 
   1136 
   1137 char *
   1138 Curl_ldap_get_dn_a(void * ld, LDAPMessage * entry)
   1139 
   1140 {
   1141   int i;
   1142   char * cp;
   1143   char * cp2;
   1144 
   1145   cp = ldap_get_dn(ld, entry);
   1146 
   1147   if(!cp)
   1148     return cp;
   1149 
   1150   i = strlen(cp);
   1151 
   1152   cp2 = malloc(i + 1);
   1153   if(!cp2)
   1154     return cp2;
   1155 
   1156   QadrtConvertE2A(cp2, cp, i, i);
   1157   cp2[i] = '\0';
   1158 
   1159   /* No way to allocate a buffer here, because it will be released by
   1160      ldap_memfree() and ldap_memalloc() does not exist. The solution is to
   1161      overwrite the EBCDIC buffer with ASCII to return it. */
   1162 
   1163   strcpy(cp, cp2);
   1164   free(cp2);
   1165   return cp;
   1166 }
   1167 
   1168 
   1169 char *
   1170 Curl_ldap_first_attribute_a(void * ld,
   1171                             LDAPMessage * entry, BerElement * * berptr)
   1172 
   1173 {
   1174   int i;
   1175   char * cp;
   1176   char * cp2;
   1177 
   1178   cp = ldap_first_attribute(ld, entry, berptr);
   1179 
   1180   if(!cp)
   1181     return cp;
   1182 
   1183   i = strlen(cp);
   1184 
   1185   cp2 = malloc(i + 1);
   1186   if(!cp2)
   1187     return cp2;
   1188 
   1189   QadrtConvertE2A(cp2, cp, i, i);
   1190   cp2[i] = '\0';
   1191 
   1192   /* No way to allocate a buffer here, because it will be released by
   1193      ldap_memfree() and ldap_memalloc() does not exist. The solution is to
   1194      overwrite the EBCDIC buffer with ASCII to return it. */
   1195 
   1196   strcpy(cp, cp2);
   1197   free(cp2);
   1198   return cp;
   1199 }
   1200 
   1201 
   1202 char *
   1203 Curl_ldap_next_attribute_a(void * ld,
   1204                            LDAPMessage * entry, BerElement * berptr)
   1205 
   1206 {
   1207   int i;
   1208   char * cp;
   1209   char * cp2;
   1210 
   1211   cp = ldap_next_attribute(ld, entry, berptr);
   1212 
   1213   if(!cp)
   1214     return cp;
   1215 
   1216   i = strlen(cp);
   1217 
   1218   cp2 = malloc(i + 1);
   1219   if(!cp2)
   1220     return cp2;
   1221 
   1222   QadrtConvertE2A(cp2, cp, i, i);
   1223   cp2[i] = '\0';
   1224 
   1225   /* No way to allocate a buffer here, because it will be released by
   1226      ldap_memfree() and ldap_memalloc() does not exist. The solution is to
   1227      overwrite the EBCDIC buffer with ASCII to return it. */
   1228 
   1229   strcpy(cp, cp2);
   1230   free(cp2);
   1231   return cp;
   1232 }
   1233 
   1234 #endif /* CURL_DISABLE_LDAP */
   1235 
   1236 
   1237 static int
   1238 convert_sockaddr(struct sockaddr_storage * dstaddr,
   1239                                 const struct sockaddr * srcaddr, int srclen)
   1240 
   1241 {
   1242   const struct sockaddr_un * srcu;
   1243   struct sockaddr_un * dstu;
   1244   unsigned int i;
   1245   unsigned int dstsize;
   1246 
   1247   /* Convert a socket address into job CCSID, if needed. */
   1248 
   1249   if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) +
   1250      sizeof srcaddr->sa_family || srclen > sizeof *dstaddr) {
   1251     errno = EINVAL;
   1252     return -1;
   1253     }
   1254 
   1255   memcpy((char *) dstaddr, (char *) srcaddr, srclen);
   1256 
   1257   switch (srcaddr->sa_family) {
   1258 
   1259   case AF_UNIX:
   1260     srcu = (const struct sockaddr_un *) srcaddr;
   1261     dstu = (struct sockaddr_un *) dstaddr;
   1262     dstsize = sizeof *dstaddr - offsetof(struct sockaddr_un, sun_path);
   1263     srclen -= offsetof(struct sockaddr_un, sun_path);
   1264     i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, dstsize - 1, srclen);
   1265     dstu->sun_path[i] = '\0';
   1266     i += offsetof(struct sockaddr_un, sun_path);
   1267     srclen = i;
   1268     }
   1269 
   1270   return srclen;
   1271 }
   1272 
   1273 
   1274 int
   1275 Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen)
   1276 
   1277 {
   1278   int i;
   1279   struct sockaddr_storage laddr;
   1280 
   1281   i = convert_sockaddr(&laddr, destaddr, addrlen);
   1282 
   1283   if(i < 0)
   1284     return -1;
   1285 
   1286   return connect(sd, (struct sockaddr *) &laddr, i);
   1287 }
   1288 
   1289 
   1290 int
   1291 Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen)
   1292 
   1293 {
   1294   int i;
   1295   struct sockaddr_storage laddr;
   1296 
   1297   i = convert_sockaddr(&laddr, localaddr, addrlen);
   1298 
   1299   if(i < 0)
   1300     return -1;
   1301 
   1302   return bind(sd, (struct sockaddr *) &laddr, i);
   1303 }
   1304 
   1305 
   1306 int
   1307 Curl_os400_sendto(int sd, char * buffer, int buflen, int flags,
   1308                                 struct sockaddr * dstaddr, int addrlen)
   1309 
   1310 {
   1311   int i;
   1312   struct sockaddr_storage laddr;
   1313 
   1314   i = convert_sockaddr(&laddr, dstaddr, addrlen);
   1315 
   1316   if(i < 0)
   1317     return -1;
   1318 
   1319   return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i);
   1320 }
   1321 
   1322 
   1323 int
   1324 Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
   1325                                 struct sockaddr * fromaddr, int * addrlen)
   1326 
   1327 {
   1328   int i;
   1329   int rcvlen;
   1330   int laddrlen;
   1331   const struct sockaddr_un * srcu;
   1332   struct sockaddr_un * dstu;
   1333   struct sockaddr_storage laddr;
   1334 
   1335   if(!fromaddr || !addrlen || *addrlen <= 0)
   1336     return recvfrom(sd, buffer, buflen, flags, fromaddr, addrlen);
   1337 
   1338   laddrlen = sizeof laddr;
   1339   laddr.ss_family = AF_UNSPEC;          /* To detect if unused. */
   1340   rcvlen = recvfrom(sd, buffer, buflen, flags,
   1341                     (struct sockaddr *) &laddr, &laddrlen);
   1342 
   1343   if(rcvlen < 0)
   1344     return rcvlen;
   1345 
   1346   switch (laddr.ss_family) {
   1347 
   1348   case AF_UNIX:
   1349     srcu = (const struct sockaddr_un *) &laddr;
   1350     dstu = (struct sockaddr_un *) fromaddr;
   1351     i = *addrlen - offsetof(struct sockaddr_un, sun_path);
   1352     laddrlen -= offsetof(struct sockaddr_un, sun_path);
   1353     i = QadrtConvertE2A(dstu->sun_path, srcu->sun_path, i, laddrlen);
   1354     laddrlen = i + offsetof(struct sockaddr_un, sun_path);
   1355 
   1356     if(laddrlen < *addrlen)
   1357       dstu->sun_path[i] = '\0';
   1358 
   1359     break;
   1360 
   1361   case AF_UNSPEC:
   1362     break;
   1363 
   1364   default:
   1365     if(laddrlen > *addrlen)
   1366       laddrlen = *addrlen;
   1367 
   1368     if(laddrlen)
   1369       memcpy((char *) fromaddr, (char *) &laddr, laddrlen);
   1370 
   1371     break;
   1372     }
   1373 
   1374   *addrlen = laddrlen;
   1375   return rcvlen;
   1376 }
   1377 
   1378 
   1379 #ifdef HAVE_LIBZ
   1380 const char *
   1381 Curl_os400_zlibVersion(void)
   1382 
   1383 {
   1384   return set_thread_string(LK_ZLIB_VERSION, zlibVersion());
   1385 }
   1386 
   1387 
   1388 int
   1389 Curl_os400_inflateInit_(z_streamp strm, const char * version, int stream_size)
   1390 
   1391 {
   1392   z_const char * msgb4 = strm->msg;
   1393   int ret;
   1394 
   1395   ret = inflateInit(strm);
   1396 
   1397   if(strm->msg != msgb4)
   1398     strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
   1399 
   1400   return ret;
   1401 }
   1402 
   1403 
   1404 int
   1405 Curl_os400_inflateInit2_(z_streamp strm, int windowBits,
   1406                                         const char * version, int stream_size)
   1407 
   1408 {
   1409   z_const char * msgb4 = strm->msg;
   1410   int ret;
   1411 
   1412   ret = inflateInit2(strm, windowBits);
   1413 
   1414   if(strm->msg != msgb4)
   1415     strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
   1416 
   1417   return ret;
   1418 }
   1419 
   1420 
   1421 int
   1422 Curl_os400_inflate(z_streamp strm, int flush)
   1423 
   1424 {
   1425   z_const char * msgb4 = strm->msg;
   1426   int ret;
   1427 
   1428   ret = inflate(strm, flush);
   1429 
   1430   if(strm->msg != msgb4)
   1431     strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
   1432 
   1433   return ret;
   1434 }
   1435 
   1436 
   1437 int
   1438 Curl_os400_inflateEnd(z_streamp strm)
   1439 
   1440 {
   1441   z_const char * msgb4 = strm->msg;
   1442   int ret;
   1443 
   1444   ret = inflateEnd(strm);
   1445 
   1446   if(strm->msg != msgb4)
   1447     strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
   1448 
   1449   return ret;
   1450 }
   1451 
   1452 #endif
   1453