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