Revert "Update to 7.40.1"
[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, sizeof *locbufs))) {
233       pthread_mutex_unlock(&mutex);
234       return (char *) NULL;
235       }
236     else
237         Curl_thread_buffer = buffer_unthreaded;
238
239     atexit(terminate);
240     }
241
242   pthread_mutex_unlock(&mutex);
243   return Curl_thread_buffer(key, size);
244 }
245
246
247 static char *
248 set_thread_string(localkey_t key, const char * s)
249
250 {
251   int i;
252   char * cp;
253
254   if(!s)
255     return (char *) NULL;
256
257   i = strlen(s) + 1;
258   cp = Curl_thread_buffer(key, MAX_CONV_EXPANSION * i + 1);
259
260   if(cp) {
261     i = QadrtConvertE2A(cp, s, MAX_CONV_EXPANSION * i, i);
262     cp[i] = '\0';
263   }
264
265   return cp;
266 }
267
268
269 int
270 Curl_getnameinfo_a(const struct sockaddr * sa, curl_socklen_t salen,
271               char * nodename, curl_socklen_t nodenamelen,
272               char * servname, curl_socklen_t servnamelen,
273               int flags)
274
275 {
276   char * enodename;
277   char * eservname;
278   int status;
279   int i;
280
281   enodename = (char *) NULL;
282   eservname = (char *) NULL;
283
284   if(nodename && nodenamelen)
285     if(!(enodename = malloc(nodenamelen)))
286       return EAI_MEMORY;
287
288   if(servname && servnamelen)
289     if(!(eservname = malloc(servnamelen))) {
290       if(enodename)
291         free(enodename);
292
293       return EAI_MEMORY;
294       }
295
296   status = getnameinfo(sa, salen, enodename, nodenamelen,
297                        eservname, servnamelen, flags);
298
299   if(!status) {
300     if(enodename) {
301       i = QadrtConvertE2A(nodename, enodename,
302         nodenamelen - 1, strlen(enodename));
303       nodename[i] = '\0';
304       }
305
306     if(eservname) {
307       i = QadrtConvertE2A(servname, eservname,
308         servnamelen - 1, strlen(eservname));
309       servname[i] = '\0';
310       }
311     }
312
313   if(enodename)
314     free(enodename);
315
316   if(eservname)
317     free(eservname);
318
319   return status;
320 }
321
322
323 int
324 Curl_getaddrinfo_a(const char * nodename, const char * servname,
325             const struct addrinfo * hints,
326             struct addrinfo * * res)
327
328 {
329   char * enodename;
330   char * eservname;
331   int status;
332   int i;
333
334   enodename = (char *) NULL;
335   eservname = (char *) NULL;
336
337   if(nodename) {
338     i = strlen(nodename);
339
340     if(!(enodename = malloc(i + 1)))
341       return EAI_MEMORY;
342
343     i = QadrtConvertA2E(enodename, nodename, i, i);
344     enodename[i] = '\0';
345     }
346
347   if(servname) {
348     i = strlen(servname);
349
350     if(!(eservname = malloc(i + 1))) {
351       if(enodename)
352         free(enodename);
353
354       return EAI_MEMORY;
355       }
356
357     QadrtConvertA2E(eservname, servname, i, i);
358     eservname[i] = '\0';
359     }
360
361   status = getaddrinfo(enodename, eservname, hints, res);
362
363   if(enodename)
364     free(enodename);
365
366   if(eservname)
367     free(eservname);
368
369   return status;
370 }
371
372
373 #ifdef USE_QSOSSL
374
375 /* ASCII wrappers for the SSL procedures. */
376
377 int
378 Curl_SSL_Init_Application_a(SSLInitApp * init_app)
379
380 {
381   int rc;
382   unsigned int i;
383   SSLInitApp ia;
384
385   if(!init_app || !init_app->applicationID || !init_app->applicationIDLen)
386     return SSL_Init_Application(init_app);
387
388   memcpy((char *) &ia, (char *) init_app, sizeof ia);
389   i = ia.applicationIDLen;
390
391   if(!(ia.applicationID = malloc(i + 1))) {
392     errno = ENOMEM;
393     return SSL_ERROR_IO;
394     }
395
396   QadrtConvertA2E(ia.applicationID, init_app->applicationID, i, i);
397   ia.applicationID[i] = '\0';
398   rc = SSL_Init_Application(&ia);
399   free(ia.applicationID);
400   init_app->localCertificateLen = ia.localCertificateLen;
401   init_app->sessionType = ia.sessionType;
402   return rc;
403 }
404
405
406 int
407 Curl_SSL_Init_a(SSLInit * init)
408
409 {
410   int rc;
411   unsigned int i;
412   SSLInit ia;
413
414   if(!init || (!init->keyringFileName && !init->keyringPassword))
415     return SSL_Init(init);
416
417   memcpy((char *) &ia, (char *) init, sizeof ia);
418
419   if(ia.keyringFileName) {
420     i = strlen(ia.keyringFileName);
421
422     if(!(ia.keyringFileName = malloc(i + 1))) {
423       errno = ENOMEM;
424       return SSL_ERROR_IO;
425       }
426
427     QadrtConvertA2E(ia.keyringFileName, init->keyringFileName, i, i);
428     ia.keyringFileName[i] = '\0';
429     }
430
431   if(ia.keyringPassword) {
432     i = strlen(ia.keyringPassword);
433
434     if(!(ia.keyringPassword = malloc(i + 1))) {
435       if(ia.keyringFileName)
436         free(ia.keyringFileName);
437
438       errno = ENOMEM;
439       return SSL_ERROR_IO;
440       }
441
442     QadrtConvertA2E(ia.keyringPassword, init->keyringPassword, i, i);
443     ia.keyringPassword[i] = '\0';
444     }
445
446   rc = SSL_Init(&ia);
447
448   if(ia.keyringFileName)
449     free(ia.keyringFileName);
450
451   if(ia.keyringPassword)
452     free(ia.keyringPassword);
453
454   return rc;
455 }
456
457
458 char *
459 Curl_SSL_Strerror_a(int sslreturnvalue, SSLErrorMsg * serrmsgp)
460
461 {
462   return set_thread_string(LK_SSL_ERROR,
463                            SSL_Strerror(sslreturnvalue, serrmsgp));
464 }
465
466 #endif /* USE_QSOSSL */
467
468
469 #ifdef USE_GSKIT
470
471 /* ASCII wrappers for the GSKit procedures. */
472
473 /*
474  * EBCDIC --> ASCII string mapping table.
475  * Some strings returned by GSKit are dynamically allocated and automatically
476  * released when closing the handle.
477  * To provide the same functionality, we use a "private" handle that
478  * holds the GSKit handle and a list of string mappings. This will allow
479  * avoid conversion of already converted strings and releasing them upon
480  * close time.
481  */
482
483 struct gskstrlist {
484   struct gskstrlist * next;
485   const char * ebcdicstr;
486   const char * asciistr;
487 };
488
489 struct Curl_gsk_descriptor {
490   gsk_handle h;
491   struct gskstrlist * strlist;
492 };
493
494
495 int
496 Curl_gsk_environment_open(gsk_handle * my_env_handle)
497
498 {
499   struct Curl_gsk_descriptor * p;
500   gsk_handle h;
501   int rc;
502
503   if(!my_env_handle)
504     return GSK_OS400_ERROR_INVALID_POINTER;
505   if(!(p = (struct Curl_gsk_descriptor *) malloc(sizeof *p)))
506     return GSK_INSUFFICIENT_STORAGE;
507   p->strlist = (struct gskstrlist *) NULL;
508   if((rc = gsk_environment_open(&p->h)) != GSK_OK)
509     free(p);
510   else
511     *my_env_handle = (gsk_handle) p;
512   return rc;
513 }
514
515
516 int
517 Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
518                          gsk_handle * my_session_handle)
519
520 {
521   struct Curl_gsk_descriptor * p;
522   gsk_handle h;
523   int rc;
524
525   if(!my_env_handle)
526     return GSK_INVALID_HANDLE;
527   if(!my_session_handle)
528     return GSK_OS400_ERROR_INVALID_POINTER;
529   h = ((struct Curl_gsk_descriptor *) my_env_handle)->h;
530   if(!(p = (struct Curl_gsk_descriptor *) malloc(sizeof *p)))
531     return GSK_INSUFFICIENT_STORAGE;
532   p->strlist = (struct gskstrlist *) NULL;
533   if((rc = gsk_secure_soc_open(h, &p->h)) != GSK_OK)
534     free(p);
535   else
536     *my_session_handle = (gsk_handle) p;
537   return rc;
538 }
539
540
541 static void
542 gsk_free_handle(struct Curl_gsk_descriptor * p)
543
544 {
545   struct gskstrlist * q;
546
547   while((q = p->strlist)) {
548     p->strlist = q;
549     free((void *) q->asciistr);
550     free(q);
551   }
552   free(p);
553 }
554
555
556 int
557 Curl_gsk_environment_close(gsk_handle * my_env_handle)
558
559 {
560   struct Curl_gsk_descriptor * p;
561   int rc;
562
563   if(!my_env_handle)
564     return GSK_OS400_ERROR_INVALID_POINTER;
565   if(!*my_env_handle)
566     return GSK_INVALID_HANDLE;
567   p = (struct Curl_gsk_descriptor *) *my_env_handle;
568   if((rc = gsk_environment_close(&p->h)) == GSK_OK) {
569     gsk_free_handle(p);
570     *my_env_handle = (gsk_handle) NULL;
571   }
572   return rc;
573 }
574
575
576 int
577 Curl_gsk_secure_soc_close(gsk_handle * my_session_handle)
578
579 {
580   struct Curl_gsk_descriptor * p;
581   int rc;
582
583   if(!my_session_handle)
584     return GSK_OS400_ERROR_INVALID_POINTER;
585   if(!*my_session_handle)
586     return GSK_INVALID_HANDLE;
587   p = (struct Curl_gsk_descriptor *) *my_session_handle;
588   if((rc = gsk_secure_soc_close(&p->h)) == GSK_OK) {
589     gsk_free_handle(p);
590     *my_session_handle = (gsk_handle) NULL;
591   }
592   return rc;
593 }
594
595
596 int
597 Curl_gsk_environment_init(gsk_handle my_env_handle)
598
599 {
600   struct Curl_gsk_descriptor * p;
601
602   if(!my_env_handle)
603     return GSK_INVALID_HANDLE;
604   p = (struct Curl_gsk_descriptor *) my_env_handle;
605   return gsk_environment_init(p->h);
606 }
607
608
609 int
610 Curl_gsk_secure_soc_init(gsk_handle my_session_handle)
611
612 {
613   struct Curl_gsk_descriptor * p;
614
615   if(!my_session_handle)
616     return GSK_INVALID_HANDLE;
617   p = (struct Curl_gsk_descriptor *) my_session_handle;
618   return gsk_secure_soc_init(p->h);
619 }
620
621
622 int
623 Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
624                                 const char * buffer, int bufSize)
625
626 {
627   struct Curl_gsk_descriptor * p;
628   char * ebcdicbuf;
629   int rc;
630
631   if(!my_gsk_handle)
632     return GSK_INVALID_HANDLE;
633   if(!buffer)
634     return GSK_OS400_ERROR_INVALID_POINTER;
635   if(bufSize < 0)
636     return GSK_ATTRIBUTE_INVALID_LENGTH;
637   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
638   if(!bufSize)
639     bufSize = strlen(buffer);
640   if(!(ebcdicbuf = malloc(bufSize + 1)))
641       return GSK_INSUFFICIENT_STORAGE;
642   QadrtConvertA2E(ebcdicbuf, buffer, bufSize, bufSize);
643   ebcdicbuf[bufSize] = '\0';
644   rc = gsk_attribute_set_buffer(p->h, bufID, ebcdicbuf, bufSize);
645   free(ebcdicbuf);
646   return rc;
647 }
648
649
650 int
651 Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID,
652                             GSK_ENUM_VALUE enumValue)
653
654 {
655   struct Curl_gsk_descriptor * p;
656
657   if(!my_gsk_handle)
658     return GSK_INVALID_HANDLE;
659   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
660   return gsk_attribute_set_enum(p->h, enumID, enumValue);
661 }
662
663
664 int
665 Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle,
666                                      GSK_NUM_ID numID, int numValue)
667
668 {
669   struct Curl_gsk_descriptor * p;
670
671   if(!my_gsk_handle)
672     return GSK_INVALID_HANDLE;
673   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
674   return gsk_attribute_set_numeric_value(p->h, numID, numValue);
675 }
676
677
678 int
679 Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle,
680                                 GSK_CALLBACK_ID callBackID,
681                                 void * callBackAreaPtr)
682
683 {
684   struct Curl_gsk_descriptor * p;
685
686   if(!my_gsk_handle)
687     return GSK_INVALID_HANDLE;
688   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
689   return gsk_attribute_set_callback(p->h, callBackID, callBackAreaPtr);
690 }
691
692
693 static int
694 cachestring(struct Curl_gsk_descriptor * p,
695             const char * ebcdicbuf, int bufsize, const char * * buffer)
696
697 {
698   int rc;
699   char * asciibuf;
700   struct gskstrlist * sp;
701
702   for(sp = p->strlist; sp; sp = sp->next)
703     if(sp->ebcdicstr == ebcdicbuf)
704       break;
705   if(!sp) {
706     if(!(sp = (struct gskstrlist *) malloc(sizeof *sp)))
707       return GSK_INSUFFICIENT_STORAGE;
708     if(!(asciibuf = malloc(bufsize + 1))) {
709       free(sp);
710       return GSK_INSUFFICIENT_STORAGE;
711     }
712     QadrtConvertE2A(asciibuf, ebcdicbuf, bufsize, bufsize);
713     asciibuf[bufsize] = '\0';
714     sp->ebcdicstr = ebcdicbuf;
715     sp->asciistr = asciibuf;
716     sp->next = p->strlist;
717     p->strlist = sp;
718   }
719   *buffer = sp->asciistr;
720   return GSK_OK;
721 }
722
723
724 int
725 Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, GSK_BUF_ID bufID,
726                                 const char * * buffer, int * bufSize)
727
728 {
729   struct Curl_gsk_descriptor * p;
730   int rc;
731   const char * mybuf;
732   int mylen;
733
734   if(!my_gsk_handle)
735     return GSK_INVALID_HANDLE;
736   if(!buffer || !bufSize)
737     return GSK_OS400_ERROR_INVALID_POINTER;
738   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
739   if((rc = gsk_attribute_get_buffer(p->h, bufID, &mybuf, &mylen)) != GSK_OK)
740     return rc;
741   if((rc = cachestring(p, mybuf, mylen, buffer)) == GSK_OK)
742     *bufSize = mylen;
743   return rc;
744 }
745
746
747 int
748 Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, GSK_ENUM_ID enumID,
749                             GSK_ENUM_VALUE * enumValue)
750
751 {
752   struct Curl_gsk_descriptor * p;
753
754   if(!my_gsk_handle)
755     return GSK_INVALID_HANDLE;
756   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
757   return gsk_attribute_get_enum(p->h, enumID, enumValue);
758 }
759
760
761 int
762 Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle,
763                                      GSK_NUM_ID numID, int * numValue)
764
765 {
766   struct Curl_gsk_descriptor * p;
767
768   if(!my_gsk_handle)
769     return GSK_INVALID_HANDLE;
770   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
771   return gsk_attribute_get_numeric_value(p->h, numID, numValue);
772 }
773
774
775 int
776 Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle,
777                                  GSK_CERT_ID certID,
778                                  const gsk_cert_data_elem * * certDataElem,
779                                  int * certDataElementCount)
780
781 {
782   struct Curl_gsk_descriptor * p;
783
784   if(!my_gsk_handle)
785     return GSK_INVALID_HANDLE;
786   p = (struct Curl_gsk_descriptor *) my_gsk_handle;
787   /* No need to convert code: text results are already in ASCII. */
788   return gsk_attribute_get_cert_info(p->h, certID,
789                                      certDataElem, certDataElementCount);
790 }
791
792
793 int
794 Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, GSK_MISC_ID miscID)
795
796 {
797   struct Curl_gsk_descriptor * p;
798
799   if(!my_session_handle)
800     return GSK_INVALID_HANDLE;
801   p = (struct Curl_gsk_descriptor *) my_session_handle;
802   return gsk_secure_soc_misc(p->h, miscID);
803 }
804
805
806 int
807 Curl_gsk_secure_soc_read(gsk_handle my_session_handle, char * readBuffer,
808                          int readBufSize, int * amtRead)
809
810 {
811   struct Curl_gsk_descriptor * p;
812
813   if(!my_session_handle)
814     return GSK_INVALID_HANDLE;
815   p = (struct Curl_gsk_descriptor *) my_session_handle;
816   return gsk_secure_soc_read(p->h, readBuffer, readBufSize, amtRead);
817 }
818
819
820 int
821 Curl_gsk_secure_soc_write(gsk_handle my_session_handle, char * writeBuffer,
822                           int writeBufSize, int * amtWritten)
823
824 {
825   struct Curl_gsk_descriptor * p;
826
827   if(!my_session_handle)
828     return GSK_INVALID_HANDLE;
829   p = (struct Curl_gsk_descriptor *) my_session_handle;
830   return gsk_secure_soc_write(p->h, writeBuffer, writeBufSize, amtWritten);
831 }
832
833
834 const char *
835 Curl_gsk_strerror_a(int gsk_return_value)
836
837 {
838   return set_thread_string(LK_GSK_ERROR, gsk_strerror(gsk_return_value));
839 }
840
841 int
842 Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle,
843                               int IOCompletionPort,
844                               Qso_OverlappedIO_t * communicationsArea)
845
846 {
847   struct Curl_gsk_descriptor * p;
848
849   if(!my_session_handle)
850     return GSK_INVALID_HANDLE;
851   p = (struct Curl_gsk_descriptor *) my_session_handle;
852   return gsk_secure_soc_startInit(p->h, IOCompletionPort, communicationsArea);
853 }
854
855 #endif /* USE_GSKIT */
856
857
858
859 #ifdef HAVE_GSSAPI
860
861 /* ASCII wrappers for the GSSAPI procedures. */
862
863 static int
864 Curl_gss_convert_in_place(OM_uint32 * minor_status, gss_buffer_t buf)
865
866 {
867   unsigned int i;
868   char * t;
869
870   /* Convert `buf' in place, from EBCDIC to ASCII.
871      If error, release the buffer and return -1. Else return 0. */
872
873   i = buf->length;
874
875   if(i) {
876     if(!(t = malloc(i))) {
877       gss_release_buffer(minor_status, buf);
878
879       if(minor_status)
880         *minor_status = ENOMEM;
881
882       return -1;
883       }
884
885     QadrtConvertE2A(t, buf->value, i, i);
886     memcpy(buf->value, t, i);
887     free(t);
888     }
889
890   return 0;
891 }
892
893
894 OM_uint32
895 Curl_gss_import_name_a(OM_uint32 * minor_status, gss_buffer_t in_name,
896                        gss_OID in_name_type, gss_name_t * out_name)
897
898 {
899   int rc;
900   unsigned int i;
901   gss_buffer_desc in;
902
903   if(!in_name || !in_name->value || !in_name->length)
904     return gss_import_name(minor_status, in_name, in_name_type, out_name);
905
906   memcpy((char *) &in, (char *) in_name, sizeof in);
907   i = in.length;
908
909   if(!(in.value = malloc(i + 1))) {
910     if(minor_status)
911       *minor_status = ENOMEM;
912
913     return GSS_S_FAILURE;
914     }
915
916   QadrtConvertA2E(in.value, in_name->value, i, i);
917   ((char *) in.value)[i] = '\0';
918   rc = gss_import_name(minor_status, &in, in_name_type, out_name);
919   free(in.value);
920   return rc;
921 }
922
923
924 OM_uint32
925 Curl_gss_display_status_a(OM_uint32 * minor_status, OM_uint32 status_value,
926                    int status_type, gss_OID mech_type,
927                    gss_msg_ctx_t * message_context, gss_buffer_t status_string)
928
929 {
930   int rc;
931
932   rc = gss_display_status(minor_status, status_value, status_type,
933                               mech_type, message_context, status_string);
934
935   if(rc != GSS_S_COMPLETE || !status_string ||
936      !status_string->length || !status_string->value)
937     return rc;
938
939   /* No way to allocate a buffer here, because it will be released by
940      gss_release_buffer(). The solution is to overwrite the EBCDIC buffer
941      with ASCII to return it. */
942
943   if(Curl_gss_convert_in_place(minor_status, status_string))
944     return GSS_S_FAILURE;
945
946   return rc;
947 }
948
949
950 OM_uint32
951 Curl_gss_init_sec_context_a(OM_uint32 * minor_status,
952                             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
1223      converted to EBCDIC. 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