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