os400sys.c 32 KB

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