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