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