• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@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
thdbufdestroy(void * private)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
terminate(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 *
get_buffer(buffer_t * buf,long size)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 *
buffer_unthreaded(localkey_t key,long size)173 buffer_unthreaded(localkey_t key, long size)
174 
175 {
176   return get_buffer(locbufs + key, size);
177 }
178 
179 
180 static char *
buffer_threaded(localkey_t key,long size)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 *
buffer_undef(localkey_t key,long size)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 *
set_thread_string(localkey_t key,const char * s)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
Curl_getnameinfo_a(const struct sockaddr * sa,curl_socklen_t salen,char * nodename,curl_socklen_t nodenamelen,char * servname,curl_socklen_t servnamelen,int flags)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 = NULL;
272   char *eservname = NULL;
273   int status;
274 
275   if(nodename && nodenamelen) {
276     enodename = malloc(nodenamelen);
277     if(!enodename)
278       return EAI_MEMORY;
279   }
280 
281   if(servname && servnamelen) {
282     eservname = malloc(servnamelen);
283     if(!eservname) {
284       free(enodename);
285       return EAI_MEMORY;
286     }
287   }
288 
289   status = getnameinfo(sa, salen, enodename, nodenamelen,
290                        eservname, servnamelen, flags);
291 
292   if(!status) {
293     int i;
294     if(enodename) {
295       i = QadrtConvertE2A(nodename, enodename,
296         nodenamelen - 1, strlen(enodename));
297       nodename[i] = '\0';
298       }
299 
300     if(eservname) {
301       i = QadrtConvertE2A(servname, eservname,
302         servnamelen - 1, strlen(eservname));
303       servname[i] = '\0';
304       }
305     }
306 
307   free(enodename);
308   free(eservname);
309   return status;
310 }
311 
312 
313 int
Curl_getaddrinfo_a(const char * nodename,const char * servname,const struct addrinfo * hints,struct addrinfo ** res)314 Curl_getaddrinfo_a(const char * nodename, const char * servname,
315             const struct addrinfo * hints,
316             struct addrinfo * * res)
317 
318 {
319   char * enodename;
320   char * eservname;
321   int status;
322   int i;
323 
324   enodename = (char *) NULL;
325   eservname = (char *) NULL;
326 
327   if(nodename) {
328     i = strlen(nodename);
329 
330     enodename = malloc(i + 1);
331     if(!enodename)
332       return EAI_MEMORY;
333 
334     i = QadrtConvertA2E(enodename, nodename, i, i);
335     enodename[i] = '\0';
336   }
337 
338   if(servname) {
339     i = strlen(servname);
340 
341     eservname = malloc(i + 1);
342     if(!eservname) {
343       free(enodename);
344       return EAI_MEMORY;
345     }
346 
347     QadrtConvertA2E(eservname, servname, i, i);
348     eservname[i] = '\0';
349   }
350 
351   status = getaddrinfo(enodename, eservname, hints, res);
352   free(enodename);
353   free(eservname);
354   return status;
355 }
356 
357 
358 #ifdef USE_GSKIT
359 
360 /* ASCII wrappers for the GSKit procedures. */
361 
362 /*
363  * EBCDIC --> ASCII string mapping table.
364  * Some strings returned by GSKit are dynamically allocated and automatically
365  * released when closing the handle.
366  * To provide the same functionality, we use a "private" handle that
367  * holds the GSKit handle and a list of string mappings. This will allow
368  * avoid conversion of already converted strings and releasing them upon
369  * close time.
370  */
371 
372 struct gskstrlist {
373   struct gskstrlist * next;
374   const char * ebcdicstr;
375   const char * asciistr;
376 };
377 
378 struct Curl_gsk_descriptor {
379   gsk_handle h;
380   struct gskstrlist * strlist;
381 };
382 
383 
384 int
Curl_gsk_environment_open(gsk_handle * my_env_handle)385 Curl_gsk_environment_open(gsk_handle * my_env_handle)
386 
387 {
388   struct Curl_gsk_descriptor * p;
389   int rc;
390 
391   if(!my_env_handle)
392     return GSK_OS400_ERROR_INVALID_POINTER;
393   p = (struct Curl_gsk_descriptor *) malloc(sizeof(*p));
394   if(!p)
395     return GSK_INSUFFICIENT_STORAGE;
396   p->strlist = (struct gskstrlist *) NULL;
397   rc = gsk_environment_open(&p->h);
398   if(rc != GSK_OK)
399     free(p);
400   else
401     *my_env_handle = (gsk_handle) p;
402   return rc;
403 }
404 
405 
406 int
Curl_gsk_secure_soc_open(gsk_handle my_env_handle,gsk_handle * my_session_handle)407 Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
408                          gsk_handle * my_session_handle)
409 
410 {
411   struct Curl_gsk_descriptor * p;
412   gsk_handle h;
413   int rc;
414 
415   if(!my_env_handle)
416     return GSK_INVALID_HANDLE;
417   if(!my_session_handle)
418     return GSK_OS400_ERROR_INVALID_POINTER;
419   h = ((struct Curl_gsk_descriptor *) my_env_handle)->h;
420   p = (struct Curl_gsk_descriptor *) malloc(sizeof(*p));
421   if(!p)
422     return GSK_INSUFFICIENT_STORAGE;
423   p->strlist = (struct gskstrlist *) NULL;
424   rc = gsk_secure_soc_open(h, &p->h);
425   if(rc != GSK_OK)
426     free(p);
427   else
428     *my_session_handle = (gsk_handle) p;
429   return rc;
430 }
431 
432 
433 static void
gsk_free_handle(struct Curl_gsk_descriptor * p)434 gsk_free_handle(struct Curl_gsk_descriptor * p)
435 
436 {
437   struct gskstrlist * q;
438 
439   while((q = p->strlist)) {
440     p->strlist = q;
441     free((void *) q->asciistr);
442     free(q);
443   }
444   free(p);
445 }
446 
447 
448 int
Curl_gsk_environment_close(gsk_handle * my_env_handle)449 Curl_gsk_environment_close(gsk_handle * my_env_handle)
450 
451 {
452   struct Curl_gsk_descriptor * p;
453   int rc;
454 
455   if(!my_env_handle)
456     return GSK_OS400_ERROR_INVALID_POINTER;
457   if(!*my_env_handle)
458     return GSK_INVALID_HANDLE;
459   p = (struct Curl_gsk_descriptor *) *my_env_handle;
460   rc = gsk_environment_close(&p->h);
461   if(rc == GSK_OK) {
462     gsk_free_handle(p);
463     *my_env_handle = (gsk_handle) NULL;
464   }
465   return rc;
466 }
467 
468 
469 int
Curl_gsk_secure_soc_close(gsk_handle * my_session_handle)470 Curl_gsk_secure_soc_close(gsk_handle * my_session_handle)
471 
472 {
473   struct Curl_gsk_descriptor * p;
474   int rc;
475 
476   if(!my_session_handle)
477     return GSK_OS400_ERROR_INVALID_POINTER;
478   if(!*my_session_handle)
479     return GSK_INVALID_HANDLE;
480   p = (struct Curl_gsk_descriptor *) *my_session_handle;
481   rc = gsk_secure_soc_close(&p->h);
482   if(rc == GSK_OK) {
483     gsk_free_handle(p);
484     *my_session_handle = (gsk_handle) NULL;
485   }
486   return rc;
487 }
488 
489 
490 int
Curl_gsk_environment_init(gsk_handle my_env_handle)491 Curl_gsk_environment_init(gsk_handle my_env_handle)
492 
493 {
494   struct Curl_gsk_descriptor * p;
495 
496   if(!my_env_handle)
497     return GSK_INVALID_HANDLE;
498   p = (struct Curl_gsk_descriptor *) my_env_handle;
499   return gsk_environment_init(p->h);
500 }
501 
502 
503 int
Curl_gsk_secure_soc_init(gsk_handle my_session_handle)504 Curl_gsk_secure_soc_init(gsk_handle my_session_handle)
505 
506 {
507   struct Curl_gsk_descriptor * p;
508 
509   if(!my_session_handle)
510     return GSK_INVALID_HANDLE;
511   p = (struct Curl_gsk_descriptor *) my_session_handle;
512   return gsk_secure_soc_init(p->h);
513 }
514 
515 
516 int
Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle,GSK_BUF_ID bufID,const char * buffer,int bufSize)517 Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
518                                 const char * buffer, int bufSize)
519 
520 {
521   struct Curl_gsk_descriptor * p;
522   char * ebcdicbuf;
523   int rc;
524 
525   if(!my_gsk_handle)
526     return GSK_INVALID_HANDLE;
527   if(!buffer)
528     return GSK_OS400_ERROR_INVALID_POINTER;
529   if(bufSize < 0)
530     return GSK_ATTRIBUTE_INVALID_LENGTH;
531   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
532   if(!bufSize)
533     bufSize = strlen(buffer);
534   ebcdicbuf = malloc(bufSize + 1);
535   if(!ebcdicbuf)
536     return GSK_INSUFFICIENT_STORAGE;
537   QadrtConvertA2E(ebcdicbuf, buffer, bufSize, bufSize);
538   ebcdicbuf[bufSize] = '\0';
539   rc = gsk_attribute_set_buffer(p->h, bufID, ebcdicbuf, bufSize);
540   free(ebcdicbuf);
541   return rc;
542 }
543 
544 
545 int
Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle,GSK_ENUM_ID enumID,GSK_ENUM_VALUE enumValue)546 Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID,
547                             GSK_ENUM_VALUE enumValue)
548 
549 {
550   struct Curl_gsk_descriptor * p;
551 
552   if(!my_gsk_handle)
553     return GSK_INVALID_HANDLE;
554   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
555   return gsk_attribute_set_enum(p->h, enumID, enumValue);
556 }
557 
558 
559 int
Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,GSK_NUM_ID numID,int numValue)560 Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
561                                      GSK_NUM_ID numID, int numValue)
562 
563 {
564   struct Curl_gsk_descriptor * p;
565 
566   if(!my_gsk_handle)
567     return GSK_INVALID_HANDLE;
568   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
569   return gsk_attribute_set_numeric_value(p->h, numID, numValue);
570 }
571 
572 
573 int
Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,GSK_CALLBACK_ID callBackID,void * callBackAreaPtr)574 Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
575                                 GSK_CALLBACK_ID callBackID,
576                                 void * callBackAreaPtr)
577 
578 {
579   struct Curl_gsk_descriptor * p;
580 
581   if(!my_gsk_handle)
582     return GSK_INVALID_HANDLE;
583   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
584   return gsk_attribute_set_callback(p->h, callBackID, callBackAreaPtr);
585 }
586 
587 
588 static int
cachestring(struct Curl_gsk_descriptor * p,const char * ebcdicbuf,int bufsize,const char ** buffer)589 cachestring(struct Curl_gsk_descriptor * p,
590             const char * ebcdicbuf, int bufsize, const char * * buffer)
591 
592 {
593   int rc;
594   char * asciibuf;
595   struct gskstrlist * sp;
596 
597   for(sp = p->strlist; sp; sp = sp->next)
598     if(sp->ebcdicstr == ebcdicbuf)
599       break;
600   if(!sp) {
601     sp = (struct gskstrlist *) malloc(sizeof(*sp));
602     if(!sp)
603       return GSK_INSUFFICIENT_STORAGE;
604     asciibuf = malloc(bufsize + 1);
605     if(!asciibuf) {
606       free(sp);
607       return GSK_INSUFFICIENT_STORAGE;
608     }
609     QadrtConvertE2A(asciibuf, ebcdicbuf, bufsize, bufsize);
610     asciibuf[bufsize] = '\0';
611     sp->ebcdicstr = ebcdicbuf;
612     sp->asciistr = asciibuf;
613     sp->next = p->strlist;
614     p->strlist = sp;
615   }
616   *buffer = sp->asciistr;
617   return GSK_OK;
618 }
619 
620 
621 int
Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle,GSK_BUF_ID bufID,const char ** buffer,int * bufSize)622 Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
623                                 const char * * buffer, int * bufSize)
624 
625 {
626   struct Curl_gsk_descriptor * p;
627   int rc;
628   const char * mybuf;
629   int mylen;
630 
631   if(!my_gsk_handle)
632     return GSK_INVALID_HANDLE;
633   if(!buffer || !bufSize)
634     return GSK_OS400_ERROR_INVALID_POINTER;
635   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
636   rc = gsk_attribute_get_buffer(p->h, bufID, &mybuf, &mylen);
637   if(rc != GSK_OK)
638     return rc;
639   rc = cachestring(p, mybuf, mylen, buffer);
640   if(rc == GSK_OK)
641     *bufSize = mylen;
642   return rc;
643 }
644 
645 
646 int
Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle,GSK_ENUM_ID enumID,GSK_ENUM_VALUE * enumValue)647 Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID,
648                             GSK_ENUM_VALUE * enumValue)
649 
650 {
651   struct Curl_gsk_descriptor * p;
652 
653   if(!my_gsk_handle)
654     return GSK_INVALID_HANDLE;
655   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
656   return gsk_attribute_get_enum(p->h, enumID, enumValue);
657 }
658 
659 
660 int
Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,GSK_NUM_ID numID,int * numValue)661 Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
662                                      GSK_NUM_ID numID, int * numValue)
663 
664 {
665   struct Curl_gsk_descriptor * p;
666 
667   if(!my_gsk_handle)
668     return GSK_INVALID_HANDLE;
669   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
670   return gsk_attribute_get_numeric_value(p->h, numID, numValue);
671 }
672 
673 
674 int
Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,GSK_CERT_ID certID,const gsk_cert_data_elem ** certDataElem,int * certDataElementCount)675 Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
676                                  GSK_CERT_ID certID,
677                                  const gsk_cert_data_elem * * certDataElem,
678                                  int * certDataElementCount)
679 
680 {
681   struct Curl_gsk_descriptor * p;
682 
683   if(!my_gsk_handle)
684     return GSK_INVALID_HANDLE;
685   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
686   /* No need to convert code: text results are already in ASCII. */
687   return gsk_attribute_get_cert_info(p->h, certID,
688                                      certDataElem, certDataElementCount);
689 }
690 
691 
692 int
Curl_gsk_secure_soc_misc(gsk_handle my_session_handle,GSK_MISC_ID miscID)693 Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, GSK_MISC_ID miscID)
694 
695 {
696   struct Curl_gsk_descriptor * p;
697 
698   if(!my_session_handle)
699     return GSK_INVALID_HANDLE;
700   p = (struct Curl_gsk_descriptor *) my_session_handle;
701   return gsk_secure_soc_misc(p->h, miscID);
702 }
703 
704 
705 int
Curl_gsk_secure_soc_read(gsk_handle my_session_handle,char * readBuffer,int readBufSize,int * amtRead)706 Curl_gsk_secure_soc_read(gsk_handle my_session_handle, char * readBuffer,
707                          int readBufSize, int * amtRead)
708 
709 {
710   struct Curl_gsk_descriptor * p;
711 
712   if(!my_session_handle)
713     return GSK_INVALID_HANDLE;
714   p = (struct Curl_gsk_descriptor *) my_session_handle;
715   return gsk_secure_soc_read(p->h, readBuffer, readBufSize, amtRead);
716 }
717 
718 
719 int
Curl_gsk_secure_soc_write(gsk_handle my_session_handle,char * writeBuffer,int writeBufSize,int * amtWritten)720 Curl_gsk_secure_soc_write(gsk_handle my_session_handle, char * writeBuffer,
721                           int writeBufSize, int * amtWritten)
722 
723 {
724   struct Curl_gsk_descriptor * p;
725 
726   if(!my_session_handle)
727     return GSK_INVALID_HANDLE;
728   p = (struct Curl_gsk_descriptor *) my_session_handle;
729   return gsk_secure_soc_write(p->h, writeBuffer, writeBufSize, amtWritten);
730 }
731 
732 
733 const char *
Curl_gsk_strerror_a(int gsk_return_value)734 Curl_gsk_strerror_a(int gsk_return_value)
735 
736 {
737   return set_thread_string(LK_GSK_ERROR, gsk_strerror(gsk_return_value));
738 }
739 
740 int
Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,int IOCompletionPort,Qso_OverlappedIO_t * communicationsArea)741 Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,
742                               int IOCompletionPort,
743                               Qso_OverlappedIO_t * communicationsArea)
744 
745 {
746   struct Curl_gsk_descriptor * p;
747 
748   if(!my_session_handle)
749     return GSK_INVALID_HANDLE;
750   p = (struct Curl_gsk_descriptor *) my_session_handle;
751   return gsk_secure_soc_startInit(p->h, IOCompletionPort, communicationsArea);
752 }
753 
754 #endif /* USE_GSKIT */
755 
756 
757 
758 #ifdef HAVE_GSSAPI
759 
760 /* ASCII wrappers for the GSSAPI procedures. */
761 
762 static int
Curl_gss_convert_in_place(OM_uint32 * minor_status,gss_buffer_t buf)763 Curl_gss_convert_in_place(OM_uint32 * minor_status, gss_buffer_t buf)
764 
765 {
766   unsigned int i = buf->length;
767 
768   /* Convert `buf' in place, from EBCDIC to ASCII.
769      If error, release the buffer and return -1. Else return 0. */
770 
771   if(i) {
772     char *t = malloc(i);
773     if(!t) {
774       gss_release_buffer(minor_status, buf);
775 
776       if(minor_status)
777         *minor_status = ENOMEM;
778 
779       return -1;
780     }
781 
782     QadrtConvertE2A(t, buf->value, i, i);
783     memcpy(buf->value, t, i);
784     free(t);
785   }
786 
787   return 0;
788 }
789 
790 
791 OM_uint32
Curl_gss_import_name_a(OM_uint32 * minor_status,gss_buffer_t in_name,gss_OID in_name_type,gss_name_t * out_name)792 Curl_gss_import_name_a(OM_uint32 * minor_status, gss_buffer_t in_name,
793                        gss_OID in_name_type, gss_name_t * out_name)
794 
795 {
796   int rc;
797   unsigned int i;
798   gss_buffer_desc in;
799 
800   if(!in_name || !in_name->value || !in_name->length)
801     return gss_import_name(minor_status, in_name, in_name_type, out_name);
802 
803   memcpy((char *) &in, (char *) in_name, sizeof(in));
804   i = in.length;
805 
806   in.value = malloc(i + 1);
807   if(!in.value) {
808     if(minor_status)
809       *minor_status = ENOMEM;
810 
811     return GSS_S_FAILURE;
812   }
813 
814   QadrtConvertA2E(in.value, in_name->value, i, i);
815   ((char *) in.value)[i] = '\0';
816   rc = gss_import_name(minor_status, &in, in_name_type, out_name);
817   free(in.value);
818   return rc;
819 }
820 
821 
822 OM_uint32
Curl_gss_display_status_a(OM_uint32 * minor_status,OM_uint32 status_value,int status_type,gss_OID mech_type,gss_msg_ctx_t * message_context,gss_buffer_t status_string)823 Curl_gss_display_status_a(OM_uint32 * minor_status, OM_uint32 status_value,
824                    int status_type, gss_OID mech_type,
825                    gss_msg_ctx_t * message_context, gss_buffer_t status_string)
826 
827 {
828   int rc;
829 
830   rc = gss_display_status(minor_status, status_value, status_type,
831                               mech_type, message_context, status_string);
832 
833   if(rc != GSS_S_COMPLETE || !status_string ||
834      !status_string->length || !status_string->value)
835     return rc;
836 
837   /* No way to allocate a buffer here, because it will be released by
838      gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
839      with ASCII to return it. */
840 
841   if(Curl_gss_convert_in_place(minor_status, status_string))
842     return GSS_S_FAILURE;
843 
844   return rc;
845 }
846 
847 
848 OM_uint32
Curl_gss_init_sec_context_a(OM_uint32 * minor_status,gss_cred_id_t cred_handle,gss_ctx_id_t * context_handle,gss_name_t target_name,gss_OID mech_type,gss_flags_t req_flags,OM_uint32 time_req,gss_channel_bindings_t input_chan_bindings,gss_buffer_t input_token,gss_OID * actual_mech_type,gss_buffer_t output_token,gss_flags_t * ret_flags,OM_uint32 * time_rec)849 Curl_gss_init_sec_context_a(OM_uint32 * minor_status,
850                             gss_cred_id_t cred_handle,
851                             gss_ctx_id_t * context_handle,
852                             gss_name_t target_name, gss_OID mech_type,
853                             gss_flags_t req_flags, OM_uint32 time_req,
854                             gss_channel_bindings_t input_chan_bindings,
855                             gss_buffer_t input_token,
856                             gss_OID * actual_mech_type,
857                             gss_buffer_t output_token, gss_flags_t * ret_flags,
858                             OM_uint32 * time_rec)
859 
860 {
861   int rc;
862   gss_buffer_desc in;
863   gss_buffer_t inp;
864 
865   in.value = NULL;
866   inp = input_token;
867 
868   if(inp) {
869     if(inp->length && inp->value) {
870       unsigned int i = inp->length;
871 
872       in.value = malloc(i + 1);
873       if(!in.value) {
874         if(minor_status)
875           *minor_status = ENOMEM;
876 
877         return GSS_S_FAILURE;
878       }
879 
880       QadrtConvertA2E(in.value, input_token->value, i, i);
881       ((char *) in.value)[i] = '\0';
882       in.length = i;
883       inp = &in;
884     }
885   }
886 
887   rc = gss_init_sec_context(minor_status, cred_handle, context_handle,
888                              target_name, mech_type, req_flags, time_req,
889                              input_chan_bindings, inp, actual_mech_type,
890                              output_token, ret_flags, time_rec);
891   free(in.value);
892 
893   if(rc != GSS_S_COMPLETE || !output_token ||
894       !output_token->length || !output_token->value)
895     return rc;
896 
897   /* No way to allocate a buffer here, because it will be released by
898      gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
899      with ASCII to return it. */
900 
901   if(Curl_gss_convert_in_place(minor_status, output_token))
902     return GSS_S_FAILURE;
903 
904   return rc;
905 }
906 
907 
908 OM_uint32
Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,gss_ctx_id_t * context_handle,gss_buffer_t output_token)909 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status,
910                               gss_ctx_id_t * context_handle,
911                               gss_buffer_t output_token)
912 
913 {
914   int rc;
915 
916   rc = gss_delete_sec_context(minor_status, context_handle, output_token);
917 
918   if(rc != GSS_S_COMPLETE || !output_token ||
919       !output_token->length || !output_token->value)
920     return rc;
921 
922   /* No way to allocate a buffer here, because it will be released by
923      gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
924      with ASCII to return it. */
925 
926   if(Curl_gss_convert_in_place(minor_status, output_token))
927     return GSS_S_FAILURE;
928 
929   return rc;
930 }
931 
932 #endif /* HAVE_GSSAPI */
933 
934 
935 #ifndef CURL_DISABLE_LDAP
936 
937 /* ASCII wrappers for the LDAP procedures. */
938 
939 void *
Curl_ldap_init_a(char * host,int port)940 Curl_ldap_init_a(char * host, int port)
941 
942 {
943   unsigned int i;
944   char * ehost;
945   void * result;
946 
947   if(!host)
948     return (void *) ldap_init(host, port);
949 
950   i = strlen(host);
951 
952   ehost = malloc(i + 1);
953   if(!ehost)
954     return (void *) NULL;
955 
956   QadrtConvertA2E(ehost, host, i, i);
957   ehost[i] = '\0';
958   result = (void *) ldap_init(ehost, port);
959   free(ehost);
960   return result;
961 }
962 
963 
964 int
Curl_ldap_simple_bind_s_a(void * ld,char * dn,char * passwd)965 Curl_ldap_simple_bind_s_a(void * ld, char * dn, char * passwd)
966 
967 {
968   int i;
969   char * edn;
970   char * epasswd;
971 
972   edn = (char *) NULL;
973   epasswd = (char *) NULL;
974 
975   if(dn) {
976     i = strlen(dn);
977 
978     edn = malloc(i + 1);
979     if(!edn)
980       return LDAP_NO_MEMORY;
981 
982     QadrtConvertA2E(edn, dn, i, i);
983     edn[i] = '\0';
984   }
985 
986   if(passwd) {
987     i = strlen(passwd);
988 
989     epasswd = malloc(i + 1);
990     if(!epasswd) {
991       free(edn);
992       return LDAP_NO_MEMORY;
993     }
994 
995     QadrtConvertA2E(epasswd, passwd, i, i);
996     epasswd[i] = '\0';
997   }
998 
999   i = ldap_simple_bind_s(ld, edn, epasswd);
1000   free(epasswd);
1001   free(edn);
1002   return i;
1003 }
1004 
1005 
1006 int
Curl_ldap_search_s_a(void * ld,char * base,int scope,char * filter,char ** attrs,int attrsonly,LDAPMessage ** res)1007 Curl_ldap_search_s_a(void * ld, char * base, int scope, char * filter,
1008                      char * * attrs, int attrsonly, LDAPMessage * * res)
1009 
1010 {
1011   int i;
1012   int j;
1013   char * ebase;
1014   char * efilter;
1015   char * * eattrs;
1016   int status;
1017 
1018   ebase = (char *) NULL;
1019   efilter = (char *) NULL;
1020   eattrs = (char * *) NULL;
1021   status = LDAP_SUCCESS;
1022 
1023   if(base) {
1024     i = strlen(base);
1025 
1026     ebase = malloc(i + 1);
1027     if(!ebase)
1028       status = LDAP_NO_MEMORY;
1029     else {
1030       QadrtConvertA2E(ebase, base, i, i);
1031       ebase[i] = '\0';
1032     }
1033   }
1034 
1035   if(filter && status == LDAP_SUCCESS) {
1036     i = strlen(filter);
1037 
1038     efilter = malloc(i + 1);
1039     if(!efilter)
1040       status = LDAP_NO_MEMORY;
1041     else {
1042       QadrtConvertA2E(efilter, filter, i, i);
1043       efilter[i] = '\0';
1044     }
1045   }
1046 
1047   if(attrs && status == LDAP_SUCCESS) {
1048     for(i = 0; attrs[i++];)
1049       ;
1050 
1051     eattrs = calloc(i, sizeof(*eattrs));
1052     if(!eattrs)
1053       status = LDAP_NO_MEMORY;
1054     else {
1055       for(j = 0; attrs[j]; j++) {
1056         i = strlen(attrs[j]);
1057 
1058         eattrs[j] = malloc(i + 1);
1059         if(!eattrs[j]) {
1060           status = LDAP_NO_MEMORY;
1061           break;
1062         }
1063 
1064         QadrtConvertA2E(eattrs[j], attrs[j], i, i);
1065         eattrs[j][i] = '\0';
1066         }
1067       }
1068     }
1069 
1070   if(status == LDAP_SUCCESS)
1071     status = ldap_search_s(ld, ebase? ebase: "", scope,
1072                            efilter? efilter: "(objectclass=*)",
1073                            eattrs, attrsonly, res);
1074 
1075   if(eattrs) {
1076     for(j = 0; eattrs[j]; j++)
1077       free(eattrs[j]);
1078 
1079     free(eattrs);
1080     }
1081 
1082   free(efilter);
1083   free(ebase);
1084   return status;
1085 }
1086 
1087 
1088 struct berval * *
Curl_ldap_get_values_len_a(void * ld,LDAPMessage * entry,const char * attr)1089 Curl_ldap_get_values_len_a(void * ld, LDAPMessage * entry, const char * attr)
1090 
1091 {
1092   char * cp;
1093   struct berval * * result;
1094 
1095   cp = (char *) NULL;
1096 
1097   if(attr) {
1098     int i = strlen(attr);
1099 
1100     cp = malloc(i + 1);
1101     if(!cp) {
1102       ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL,
1103                        ldap_err2string(LDAP_NO_MEMORY));
1104       return (struct berval * *) NULL;
1105     }
1106 
1107     QadrtConvertA2E(cp, attr, i, i);
1108     cp[i] = '\0';
1109   }
1110 
1111   result = ldap_get_values_len(ld, entry, cp);
1112   free(cp);
1113 
1114   /* Result data are binary in nature, so they haven't been
1115      converted to EBCDIC. Therefore do not convert. */
1116 
1117   return result;
1118 }
1119 
1120 
1121 char *
Curl_ldap_err2string_a(int error)1122 Curl_ldap_err2string_a(int error)
1123 
1124 {
1125   return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error));
1126 }
1127 
1128 
1129 char *
Curl_ldap_get_dn_a(void * ld,LDAPMessage * entry)1130 Curl_ldap_get_dn_a(void * ld, LDAPMessage * entry)
1131 
1132 {
1133   int i;
1134   char * cp;
1135   char * cp2;
1136 
1137   cp = ldap_get_dn(ld, entry);
1138 
1139   if(!cp)
1140     return cp;
1141 
1142   i = strlen(cp);
1143 
1144   cp2 = malloc(i + 1);
1145   if(!cp2)
1146     return cp2;
1147 
1148   QadrtConvertE2A(cp2, cp, i, i);
1149   cp2[i] = '\0';
1150 
1151   /* No way to allocate a buffer here, because it will be released by
1152      ldap_memfree() and ldap_memalloc() does not exist. The solution is to
1153      overwrite the EBCDIC buffer with ASCII to return it. */
1154 
1155   strcpy(cp, cp2);
1156   free(cp2);
1157   return cp;
1158 }
1159 
1160 
1161 char *
Curl_ldap_first_attribute_a(void * ld,LDAPMessage * entry,BerElement ** berptr)1162 Curl_ldap_first_attribute_a(void * ld,
1163                             LDAPMessage * entry, BerElement * * berptr)
1164 
1165 {
1166   int i;
1167   char * cp;
1168   char * cp2;
1169 
1170   cp = ldap_first_attribute(ld, entry, berptr);
1171 
1172   if(!cp)
1173     return cp;
1174 
1175   i = strlen(cp);
1176 
1177   cp2 = malloc(i + 1);
1178   if(!cp2)
1179     return cp2;
1180 
1181   QadrtConvertE2A(cp2, cp, i, i);
1182   cp2[i] = '\0';
1183 
1184   /* No way to allocate a buffer here, because it will be released by
1185      ldap_memfree() and ldap_memalloc() does not exist. The solution is to
1186      overwrite the EBCDIC buffer with ASCII to return it. */
1187 
1188   strcpy(cp, cp2);
1189   free(cp2);
1190   return cp;
1191 }
1192 
1193 
1194 char *
Curl_ldap_next_attribute_a(void * ld,LDAPMessage * entry,BerElement * berptr)1195 Curl_ldap_next_attribute_a(void * ld,
1196                            LDAPMessage * entry, BerElement * berptr)
1197 
1198 {
1199   int i;
1200   char * cp;
1201   char * cp2;
1202 
1203   cp = ldap_next_attribute(ld, entry, berptr);
1204 
1205   if(!cp)
1206     return cp;
1207 
1208   i = strlen(cp);
1209 
1210   cp2 = malloc(i + 1);
1211   if(!cp2)
1212     return cp2;
1213 
1214   QadrtConvertE2A(cp2, cp, i, i);
1215   cp2[i] = '\0';
1216 
1217   /* No way to allocate a buffer here, because it will be released by
1218      ldap_memfree() and ldap_memalloc() does not exist. The solution is to
1219      overwrite the EBCDIC buffer with ASCII to return it. */
1220 
1221   strcpy(cp, cp2);
1222   free(cp2);
1223   return cp;
1224 }
1225 
1226 #endif /* CURL_DISABLE_LDAP */
1227 
1228 
1229 static int
sockaddr2ebcdic(struct sockaddr_storage * dstaddr,const struct sockaddr * srcaddr,int srclen)1230 sockaddr2ebcdic(struct sockaddr_storage *dstaddr,
1231                 const struct sockaddr *srcaddr, int srclen)
1232 {
1233   const struct sockaddr_un *srcu;
1234   struct sockaddr_un *dstu;
1235   unsigned int i;
1236   unsigned int dstsize;
1237 
1238   /* Convert a socket address to job CCSID, if needed. */
1239 
1240   if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) +
1241      sizeof(srcaddr->sa_family) || srclen > sizeof(*dstaddr)) {
1242     errno = EINVAL;
1243     return -1;
1244     }
1245 
1246   memcpy((char *) dstaddr, (char *) srcaddr, srclen);
1247 
1248   switch (srcaddr->sa_family) {
1249 
1250   case AF_UNIX:
1251     srcu = (const struct sockaddr_un *) srcaddr;
1252     dstu = (struct sockaddr_un *) dstaddr;
1253     dstsize = sizeof(*dstaddr) - offsetof(struct sockaddr_un, sun_path);
1254     srclen -= offsetof(struct sockaddr_un, sun_path);
1255     i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, dstsize - 1, srclen);
1256     dstu->sun_path[i] = '\0';
1257     srclen = i + offsetof(struct sockaddr_un, sun_path);
1258     }
1259 
1260   return srclen;
1261 }
1262 
1263 
1264 static int
sockaddr2ascii(struct sockaddr * dstaddr,int dstlen,const struct sockaddr_storage * srcaddr,int srclen)1265 sockaddr2ascii(struct sockaddr *dstaddr, int dstlen,
1266                const struct sockaddr_storage *srcaddr, int srclen)
1267 {
1268   const struct sockaddr_un *srcu;
1269   struct sockaddr_un *dstu;
1270   unsigned int dstsize;
1271 
1272   /* Convert a socket address to ASCII, if needed. */
1273 
1274   if(!srclen)
1275     return 0;
1276   if(srclen > dstlen)
1277     srclen = dstlen;
1278   if(!srcaddr || srclen < 0) {
1279     errno = EINVAL;
1280     return -1;
1281     }
1282 
1283   memcpy((char *) dstaddr, (char *) srcaddr, srclen);
1284 
1285   if(srclen >= offsetof(struct sockaddr_storage, ss_family) +
1286      sizeof(srcaddr->ss_family)) {
1287     switch (srcaddr->ss_family) {
1288 
1289     case AF_UNIX:
1290       srcu = (const struct sockaddr_un *) srcaddr;
1291       dstu = (struct sockaddr_un *) dstaddr;
1292       dstsize = dstlen - offsetof(struct sockaddr_un, sun_path);
1293       srclen -= offsetof(struct sockaddr_un, sun_path);
1294       if(dstsize > 0 && srclen > 0) {
1295         srclen = QadrtConvertE2A(dstu->sun_path, srcu->sun_path,
1296                                  dstsize - 1, srclen);
1297         dstu->sun_path[srclen] = '\0';
1298       }
1299       srclen += offsetof(struct sockaddr_un, sun_path);
1300     }
1301   }
1302 
1303   return srclen;
1304 }
1305 
1306 
1307 int
Curl_os400_connect(int sd,struct sockaddr * destaddr,int addrlen)1308 Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen)
1309 {
1310   int i;
1311   struct sockaddr_storage laddr;
1312 
1313   i = sockaddr2ebcdic(&laddr, destaddr, addrlen);
1314 
1315   if(i < 0)
1316     return -1;
1317 
1318   return connect(sd, (struct sockaddr *) &laddr, i);
1319 }
1320 
1321 
1322 int
Curl_os400_bind(int sd,struct sockaddr * localaddr,int addrlen)1323 Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen)
1324 {
1325   int i;
1326   struct sockaddr_storage laddr;
1327 
1328   i = sockaddr2ebcdic(&laddr, localaddr, addrlen);
1329 
1330   if(i < 0)
1331     return -1;
1332 
1333   return bind(sd, (struct sockaddr *) &laddr, i);
1334 }
1335 
1336 
1337 int
Curl_os400_sendto(int sd,char * buffer,int buflen,int flags,struct sockaddr * dstaddr,int addrlen)1338 Curl_os400_sendto(int sd, char * buffer, int buflen, int flags,
1339                                 struct sockaddr * dstaddr, int addrlen)
1340 {
1341   int i;
1342   struct sockaddr_storage laddr;
1343 
1344   i = sockaddr2ebcdic(&laddr, dstaddr, addrlen);
1345 
1346   if(i < 0)
1347     return -1;
1348 
1349   return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i);
1350 }
1351 
1352 
1353 int
Curl_os400_recvfrom(int sd,char * buffer,int buflen,int flags,struct sockaddr * fromaddr,int * addrlen)1354 Curl_os400_recvfrom(int sd, char * buffer, int buflen, int flags,
1355                                 struct sockaddr * fromaddr, int * addrlen)
1356 {
1357   int rcvlen;
1358   struct sockaddr_storage laddr;
1359   int laddrlen = sizeof(laddr);
1360 
1361   if(!fromaddr || !addrlen || *addrlen <= 0)
1362     return recvfrom(sd, buffer, buflen, flags, fromaddr, addrlen);
1363 
1364   laddr.ss_family = AF_UNSPEC;          /* To detect if unused. */
1365   rcvlen = recvfrom(sd, buffer, buflen, flags,
1366                     (struct sockaddr *) &laddr, &laddrlen);
1367 
1368   if(rcvlen < 0)
1369     return rcvlen;
1370 
1371   if(laddr.ss_family == AF_UNSPEC)
1372     laddrlen = 0;
1373   else {
1374     laddrlen = sockaddr2ascii(fromaddr, *addrlen, &laddr, laddrlen);
1375     if(laddrlen < 0)
1376       return laddrlen;
1377   }
1378   *addrlen = laddrlen;
1379   return rcvlen;
1380 }
1381 
1382 
1383 int
Curl_os400_getpeername(int sd,struct sockaddr * addr,int * addrlen)1384 Curl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen)
1385 {
1386   struct sockaddr_storage laddr;
1387   int laddrlen = sizeof(laddr);
1388   int retcode = getpeername(sd, (struct sockaddr *) &laddr, &laddrlen);
1389 
1390   if(!retcode) {
1391     laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen);
1392     if(laddrlen < 0)
1393       return laddrlen;
1394     *addrlen = laddrlen;
1395   }
1396 
1397   return retcode;
1398 }
1399 
1400 
1401 int
Curl_os400_getsockname(int sd,struct sockaddr * addr,int * addrlen)1402 Curl_os400_getsockname(int sd, struct sockaddr *addr, int *addrlen)
1403 {
1404   struct sockaddr_storage laddr;
1405   int laddrlen = sizeof(laddr);
1406   int retcode = getsockname(sd, (struct sockaddr *) &laddr, &laddrlen);
1407 
1408   if(!retcode) {
1409     laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen);
1410     if(laddrlen < 0)
1411       return laddrlen;
1412     *addrlen = laddrlen;
1413   }
1414 
1415   return retcode;
1416 }
1417 
1418 
1419 #ifdef HAVE_LIBZ
1420 const char *
Curl_os400_zlibVersion(void)1421 Curl_os400_zlibVersion(void)
1422 
1423 {
1424   return set_thread_string(LK_ZLIB_VERSION, zlibVersion());
1425 }
1426 
1427 
1428 int
Curl_os400_inflateInit_(z_streamp strm,const char * version,int stream_size)1429 Curl_os400_inflateInit_(z_streamp strm, const char * version, int stream_size)
1430 
1431 {
1432   z_const char * msgb4 = strm->msg;
1433   int ret;
1434 
1435   ret = inflateInit(strm);
1436 
1437   if(strm->msg != msgb4)
1438     strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
1439 
1440   return ret;
1441 }
1442 
1443 
1444 int
Curl_os400_inflateInit2_(z_streamp strm,int windowBits,const char * version,int stream_size)1445 Curl_os400_inflateInit2_(z_streamp strm, int windowBits,
1446                                         const char * version, int stream_size)
1447 
1448 {
1449   z_const char * msgb4 = strm->msg;
1450   int ret;
1451 
1452   ret = inflateInit2(strm, windowBits);
1453 
1454   if(strm->msg != msgb4)
1455     strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
1456 
1457   return ret;
1458 }
1459 
1460 
1461 int
Curl_os400_inflate(z_streamp strm,int flush)1462 Curl_os400_inflate(z_streamp strm, int flush)
1463 
1464 {
1465   z_const char * msgb4 = strm->msg;
1466   int ret;
1467 
1468   ret = inflate(strm, flush);
1469 
1470   if(strm->msg != msgb4)
1471     strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
1472 
1473   return ret;
1474 }
1475 
1476 
1477 int
Curl_os400_inflateEnd(z_streamp strm)1478 Curl_os400_inflateEnd(z_streamp strm)
1479 
1480 {
1481   z_const char * msgb4 = strm->msg;
1482   int ret;
1483 
1484   ret = inflateEnd(strm);
1485 
1486   if(strm->msg != msgb4)
1487     strm->msg = set_thread_string(LK_ZLIB_MSG, strm->msg);
1488 
1489   return ret;
1490 }
1491 
1492 #endif
1493