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