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