os400sys.c 32 KB

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