blob: c80f01080b31c26d7957c5bcf341eaaa1f0d44fe [file] [log] [blame]
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
Elliott Hughes82be86d2017-09-20 17:00:17 -07008 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
Lucas Eckels9bd90e62012-08-06 15:07:02 -07009 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
Alex Deymo8f1a2142016-06-28 14:49:26 -070012 * are also available at https://curl.haxx.se/docs/copyright.html.
Lucas Eckels9bd90e62012-08-06 15:07:02 -070013 *
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
Elliott Hughes82be86d2017-09-20 17:00:17 -070026#include <curl/curl.h>
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070027#include "config-os400.h" /* Not curl_setup.h: we only need some defines. */
Lucas Eckels9bd90e62012-08-06 15:07:02 -070028
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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070041#ifdef HAVE_ZLIB_H
42#include <zlib.h>
43#endif
44
45#ifdef USE_GSKIT
46#include <gskssl.h>
47#include <qsoasync.h>
Lucas Eckels9bd90e62012-08-06 15:07:02 -070048#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
76typedef struct {
77 unsigned long size; /* Buffer size. */
78 char * buf; /* Buffer address. */
79} buffer_t;
80
81
82static char * buffer_undef(localkey_t key, long size);
83static char * buffer_threaded(localkey_t key, long size);
84static char * buffer_unthreaded(localkey_t key, long size);
85
86static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
87static pthread_key_t thdkey;
88static buffer_t * locbufs;
89
90char * (* Curl_thread_buffer)(localkey_t key, long size) = buffer_undef;
91
92
93static void
94thdbufdestroy(void * private)
95
96{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -070097 if(private) {
98 buffer_t * p = (buffer_t *) private;
99 localkey_t i;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700100
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700101 for(i = (localkey_t) 0; i < LK_LAST; i++) {
102 free(p->buf);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700103 p++;
104 }
105
106 free(private);
107 }
108}
109
110
111static void
112terminate(void)
113
114{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700115 if(Curl_thread_buffer == buffer_threaded) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700116 locbufs = pthread_getspecific(thdkey);
117 pthread_setspecific(thdkey, (void *) NULL);
118 pthread_key_delete(thdkey);
119 }
120
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700121 if(Curl_thread_buffer != buffer_undef) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700122 thdbufdestroy((void *) locbufs);
123 locbufs = (buffer_t *) NULL;
124 }
125
126 Curl_thread_buffer = buffer_undef;
127}
128
129
130static char *
131get_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700139 if(size < 0)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700140 return buf->buf;
141
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700142 if(!buf->buf) {
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700143 buf->buf = malloc(size);
144 if(buf->buf)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700145 buf->size = size;
146
147 return buf->buf;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700148 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700149
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700150 if((unsigned long) size <= buf->size) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700151 /* Shorten the buffer only if it frees a significant byte count. This
152 avoids some realloc() overhead. */
153
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700154 if(buf->size - size < MIN_BYTE_GAIN)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700155 return buf->buf;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700156 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700157
158 /* Resize the buffer. */
159
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700160 cp = realloc(buf->buf, size);
161 if(cp) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700162 buf->buf = cp;
163 buf->size = size;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700164 }
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700165 else if(size <= buf->size)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700166 cp = buf->buf;
167
168 return cp;
169}
170
171
172static char *
173buffer_unthreaded(localkey_t key, long size)
174
175{
176 return get_buffer(locbufs + key, size);
177}
178
179
180static char *
181buffer_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700192 if(!bufs) {
193 if(size < 0)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700194 return (char *) NULL; /* No buffer yet. */
195
196 /* Allocate buffer descriptors for the current thread. */
197
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700198 bufs = calloc((size_t) LK_LAST, sizeof *bufs);
199 if(!bufs)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700200 return (char *) NULL;
201
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700202 if(pthread_setspecific(thdkey, (void *) bufs)) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700203 free(bufs);
204 return (char *) NULL;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700205 }
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700206 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700207
208 return get_buffer(bufs + key, size);
209}
210
211
212static char *
213buffer_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700224 if(Curl_thread_buffer == buffer_undef) { /* If unchanged during lock. */
225 if(!pthread_key_create(&thdkey, thdbufdestroy))
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700226 Curl_thread_buffer = buffer_threaded;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700227 else if(!(locbufs = calloc((size_t) LK_LAST, sizeof *locbufs))) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700228 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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700242static char *
243set_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
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700264int
265Curl_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
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700279 if(nodename && nodenamelen) {
280 enodename = malloc(nodenamelen);
281 if(!enodename)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700282 return EAI_MEMORY;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700283 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700284
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700285 if(servname && servnamelen) {
286 eservname = malloc(servnamelen);
287 if(!eservname) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700288 free(enodename);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700289 return EAI_MEMORY;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700290 }
291 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700292
293 status = getnameinfo(sa, salen, enodename, nodenamelen,
294 eservname, servnamelen, flags);
295
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700296 if(!status) {
297 if(enodename) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700298 i = QadrtConvertE2A(nodename, enodename,
299 nodenamelen - 1, strlen(enodename));
300 nodename[i] = '\0';
301 }
302
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700303 if(eservname) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700304 i = QadrtConvertE2A(servname, eservname,
305 servnamelen - 1, strlen(eservname));
306 servname[i] = '\0';
307 }
308 }
309
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700310 free(enodename);
311 free(eservname);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700312 return status;
313}
314
315
316int
317Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700330 if(nodename) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700331 i = strlen(nodename);
332
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700333 enodename = malloc(i + 1);
334 if(!enodename)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700335 return EAI_MEMORY;
336
337 i = QadrtConvertA2E(enodename, nodename, i, i);
338 enodename[i] = '\0';
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700339 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700340
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700341 if(servname) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700342 i = strlen(servname);
343
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700344 eservname = malloc(i + 1);
345 if(!eservname) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700346 free(enodename);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700347 return EAI_MEMORY;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700348 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700349
350 QadrtConvertA2E(eservname, servname, i, i);
351 eservname[i] = '\0';
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700352 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700353
354 status = getaddrinfo(enodename, eservname, hints, res);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700355 free(enodename);
356 free(eservname);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700357 return status;
358}
359
360
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700361#ifdef USE_GSKIT
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700362
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700363/* 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
375struct gskstrlist {
376 struct gskstrlist * next;
377 const char * ebcdicstr;
378 const char * asciistr;
379};
380
381struct Curl_gsk_descriptor {
382 gsk_handle h;
383 struct gskstrlist * strlist;
384};
385
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700386
387int
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700388Curl_gsk_environment_open(gsk_handle * my_env_handle)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700389
390{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700391 struct Curl_gsk_descriptor * p;
392 gsk_handle h;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700393 int rc;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700394
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700395 if(!my_env_handle)
396 return GSK_OS400_ERROR_INVALID_POINTER;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700397 p = (struct Curl_gsk_descriptor *) malloc(sizeof *p);
398 if(!p)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700399 return GSK_INSUFFICIENT_STORAGE;
400 p->strlist = (struct gskstrlist *) NULL;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700401 rc = gsk_environment_open(&p->h);
402 if(rc != GSK_OK)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700403 free(p);
404 else
405 *my_env_handle = (gsk_handle) p;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700406 return rc;
407}
408
409
410int
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700411Curl_gsk_secure_soc_open(gsk_handle my_env_handle,
412 gsk_handle * my_session_handle)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700413
414{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700415 struct Curl_gsk_descriptor * p;
416 gsk_handle h;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700417 int rc;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700418
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700419 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;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700424 p = (struct Curl_gsk_descriptor *) malloc(sizeof *p);
425 if(!p)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700426 return GSK_INSUFFICIENT_STORAGE;
427 p->strlist = (struct gskstrlist *) NULL;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700428 rc = gsk_secure_soc_open(h, &p->h);
429 if(rc != GSK_OK)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700430 free(p);
431 else
432 *my_session_handle = (gsk_handle) p;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700433 return rc;
434}
435
436
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700437static void
438gsk_free_handle(struct Curl_gsk_descriptor * p)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700439
440{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700441 struct gskstrlist * q;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700442
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700443 while((q = p->strlist)) {
444 p->strlist = q;
445 free((void *) q->asciistr);
446 free(q);
447 }
448 free(p);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700449}
450
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700451
452int
453Curl_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;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700464 rc = gsk_environment_close(&p->h);
465 if(rc == GSK_OK) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700466 gsk_free_handle(p);
467 *my_env_handle = (gsk_handle) NULL;
468 }
469 return rc;
470}
471
472
473int
474Curl_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;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700485 rc = gsk_secure_soc_close(&p->h);
486 if(rc == GSK_OK) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700487 gsk_free_handle(p);
488 *my_session_handle = (gsk_handle) NULL;
489 }
490 return rc;
491}
492
493
494int
495Curl_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
507int
508Curl_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
520int
521Curl_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);
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700538 ebcdicbuf = malloc(bufSize + 1);
539 if(!ebcdicbuf)
540 return GSK_INSUFFICIENT_STORAGE;
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700541 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
549int
550Curl_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
563int
564Curl_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
577int
578Curl_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
592static int
593cachestring(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) {
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700605 sp = (struct gskstrlist *) malloc(sizeof *sp);
606 if(!sp)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700607 return GSK_INSUFFICIENT_STORAGE;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700608 asciibuf = malloc(bufsize + 1);
609 if(!asciibuf) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700610 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
625int
626Curl_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;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700640 rc = gsk_attribute_get_buffer(p->h, bufID, &mybuf, &mylen);
641 if(rc != GSK_OK)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700642 return rc;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700643 rc = cachestring(p, mybuf, mylen, buffer);
644 if(rc == GSK_OK)
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700645 *bufSize = mylen;
646 return rc;
647}
648
649
650int
651Curl_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
664int
665Curl_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
678int
679Curl_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
696int
697Curl_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
709int
710Curl_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
723int
724Curl_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
737const char *
738Curl_gsk_strerror_a(int gsk_return_value)
739
740{
741 return set_thread_string(LK_GSK_ERROR, gsk_strerror(gsk_return_value));
742}
743
744int
745Curl_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
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700760
761
762#ifdef HAVE_GSSAPI
763
764/* ASCII wrappers for the GSSAPI procedures. */
765
766static int
767Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700778 if(i) {
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700779 t = malloc(i);
780 if(!t) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700781 gss_release_buffer(minor_status, buf);
782
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700783 if(minor_status)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700784 *minor_status = ENOMEM;
785
786 return -1;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700787 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700788
789 QadrtConvertE2A(t, buf->value, i, i);
790 memcpy(buf->value, t, i);
791 free(t);
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700792 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700793
794 return 0;
795}
796
797
798OM_uint32
799Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700807 if(!in_name || !in_name->value || !in_name->length)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700808 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
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700813 in.value = malloc(i + 1);
814 if(!in.value) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700815 if(minor_status)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700816 *minor_status = ENOMEM;
817
818 return GSS_S_FAILURE;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700819 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700820
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
829OM_uint32
830Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700840 if(rc != GSS_S_COMPLETE || !status_string ||
841 !status_string->length || !status_string->value)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700842 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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700848 if(Curl_gss_convert_in_place(minor_status, status_string))
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700849 return GSS_S_FAILURE;
850
851 return rc;
852}
853
854
855OM_uint32
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700856Curl_gss_init_sec_context_a(OM_uint32 * minor_status,
857 gss_cred_id_t cred_handle,
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700858 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;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700874 inp = input_token;
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700875
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700876 if(inp) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700877 if(inp->length && inp->value) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700878 i = inp->length;
879
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700880 in.value = malloc(i + 1);
881 if(!in.value) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700882 if(minor_status)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700883 *minor_status = ENOMEM;
884
885 return GSS_S_FAILURE;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700886 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700887
888 QadrtConvertA2E(in.value, input_token->value, i, i);
889 ((char *) in.value)[i] = '\0';
890 in.length = i;
891 inp = &in;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700892 }
893 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700894
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);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700899 free(in.value);
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700900
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700901 if(rc != GSS_S_COMPLETE || !output_token ||
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700902 !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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700909 if(Curl_gss_convert_in_place(minor_status, output_token))
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700910 return GSS_S_FAILURE;
911
912 return rc;
913}
914
915
916OM_uint32
917Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700926 if(rc != GSS_S_COMPLETE || !output_token ||
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700927 !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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700934 if(Curl_gss_convert_in_place(minor_status, output_token))
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700935 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
947void *
948Curl_ldap_init_a(char * host, int port)
949
950{
951 unsigned int i;
952 char * ehost;
953 void * result;
954
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700955 if(!host)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700956 return (void *) ldap_init(host, port);
957
958 i = strlen(host);
959
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700960 ehost = malloc(i + 1);
961 if(!ehost)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700962 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
972int
973Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700983 if(dn) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700984 i = strlen(dn);
985
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700986 edn = malloc(i + 1);
987 if(!edn)
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700988 return LDAP_NO_MEMORY;
989
990 QadrtConvertA2E(edn, dn, i, i);
991 edn[i] = '\0';
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700992 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700993
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700994 if(passwd) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -0700995 i = strlen(passwd);
996
Elliott Hughes1ef06ba2018-05-30 15:43:58 -0700997 epasswd = malloc(i + 1);
998 if(!epasswd) {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -0700999 free(edn);
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001000 return LDAP_NO_MEMORY;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001001 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001002
1003 QadrtConvertA2E(epasswd, passwd, i, i);
1004 epasswd[i] = '\0';
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001005 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001006
1007 i = ldap_simple_bind_s(ld, edn, epasswd);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001008 free(epasswd);
1009 free(edn);
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001010 return i;
1011}
1012
1013
1014int
1015Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001031 if(base) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001032 i = strlen(base);
1033
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001034 ebase = malloc(i + 1);
1035 if(!ebase)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001036 status = LDAP_NO_MEMORY;
1037 else {
1038 QadrtConvertA2E(ebase, base, i, i);
1039 ebase[i] = '\0';
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001040 }
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001041 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001042
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001043 if(filter && status == LDAP_SUCCESS) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001044 i = strlen(filter);
1045
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001046 efilter = malloc(i + 1);
1047 if(!efilter)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001048 status = LDAP_NO_MEMORY;
1049 else {
1050 QadrtConvertA2E(efilter, filter, i, i);
1051 efilter[i] = '\0';
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001052 }
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001053 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001054
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001055 if(attrs && status == LDAP_SUCCESS) {
1056 for(i = 0; attrs[i++];)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001057 ;
1058
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001059 eattrs = calloc(i, sizeof *eattrs);
1060 if(!eattrs)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001061 status = LDAP_NO_MEMORY;
1062 else {
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001063 for(j = 0; attrs[j]; j++) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001064 i = strlen(attrs[j]);
1065
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001066 eattrs[j] = malloc(i + 1);
1067 if(!eattrs[j]) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001068 status = LDAP_NO_MEMORY;
1069 break;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001070 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001071
1072 QadrtConvertA2E(eattrs[j], attrs[j], i, i);
1073 eattrs[j][i] = '\0';
1074 }
1075 }
1076 }
1077
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001078 if(status == LDAP_SUCCESS)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001079 status = ldap_search_s(ld, ebase? ebase: "", scope,
1080 efilter? efilter: "(objectclass=*)",
1081 eattrs, attrsonly, res);
1082
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001083 if(eattrs) {
1084 for(j = 0; eattrs[j]; j++)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001085 free(eattrs[j]);
1086
1087 free(eattrs);
1088 }
1089
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001090 free(efilter);
1091 free(ebase);
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001092 return status;
1093}
1094
1095
1096struct berval * *
1097Curl_ldap_get_values_len_a(void * ld, LDAPMessage * entry, const char * attr)
1098
1099{
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001100 char * cp;
1101 struct berval * * result;
1102
1103 cp = (char *) NULL;
1104
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001105 if(attr) {
1106 int i = strlen(attr);
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001107
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001108 cp = malloc(i + 1);
1109 if(!cp) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001110 ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL,
1111 ldap_err2string(LDAP_NO_MEMORY));
1112 return (struct berval * *) NULL;
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001113 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001114
1115 QadrtConvertA2E(cp, attr, i, i);
1116 cp[i] = '\0';
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001117 }
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001118
1119 result = ldap_get_values_len(ld, entry, cp);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001120 free(cp);
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001121
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001122 /* Result data are binary in nature, so they haven't been
1123 converted to EBCDIC. Therefore do not convert. */
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001124
1125 return result;
1126}
1127
1128
1129char *
1130Curl_ldap_err2string_a(int error)
1131
1132{
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001133 return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error));
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001134}
1135
1136
1137char *
1138Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001147 if(!cp)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001148 return cp;
1149
1150 i = strlen(cp);
1151
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001152 cp2 = malloc(i + 1);
1153 if(!cp2)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001154 return cp2;
1155
1156 QadrtConvertE2A(cp2, cp, i, i);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001157 cp2[i] = '\0';
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001158
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
1169char *
1170Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001180 if(!cp)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001181 return cp;
1182
1183 i = strlen(cp);
1184
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001185 cp2 = malloc(i + 1);
1186 if(!cp2)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001187 return cp2;
1188
1189 QadrtConvertE2A(cp2, cp, i, i);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001190 cp2[i] = '\0';
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001191
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
1202char *
1203Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001213 if(!cp)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001214 return cp;
1215
1216 i = strlen(cp);
1217
Elliott Hughes1ef06ba2018-05-30 15:43:58 -07001218 cp2 = malloc(i + 1);
1219 if(!cp2)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001220 return cp2;
1221
1222 QadrtConvertE2A(cp2, cp, i, i);
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001223 cp2[i] = '\0';
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001224
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
1237static int
1238convert_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001249 if(!srcaddr || srclen < offsetof(struct sockaddr, sa_family) +
1250 sizeof srcaddr->sa_family || srclen > sizeof *dstaddr) {
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001251 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
1274int
1275Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001283 if(i < 0)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001284 return -1;
1285
1286 return connect(sd, (struct sockaddr *) &laddr, i);
1287}
1288
1289
1290int
1291Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001299 if(i < 0)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001300 return -1;
1301
1302 return bind(sd, (struct sockaddr *) &laddr, i);
1303}
1304
1305
1306int
1307Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001316 if(i < 0)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001317 return -1;
1318
1319 return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i);
1320}
1321
1322
1323int
1324Curl_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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001335 if(!fromaddr || !addrlen || *addrlen <= 0)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001336 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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001343 if(rcvlen < 0)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001344 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
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001356 if(laddrlen < *addrlen)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001357 dstu->sun_path[i] = '\0';
1358
1359 break;
1360
1361 case AF_UNSPEC:
1362 break;
1363
1364 default:
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001365 if(laddrlen > *addrlen)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001366 laddrlen = *addrlen;
1367
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001368 if(laddrlen)
Lucas Eckels9bd90e62012-08-06 15:07:02 -07001369 memcpy((char *) fromaddr, (char *) &laddr, laddrlen);
1370
1371 break;
1372 }
1373
1374 *addrlen = laddrlen;
1375 return rcvlen;
1376}
Bertrand SIMONNETe6cd7382015-07-01 15:39:44 -07001377
1378
1379#ifdef HAVE_LIBZ
1380const char *
1381Curl_os400_zlibVersion(void)
1382
1383{
1384 return set_thread_string(LK_ZLIB_VERSION, zlibVersion());
1385}
1386
1387
1388int
1389Curl_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
1404int
1405Curl_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
1421int
1422Curl_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
1437int
1438Curl_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