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