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