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