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