PageRenderTime 56ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/src/io.c

https://github.com/andersmalm/cyassl
C | 792 lines | 616 code | 121 blank | 55 comment | 190 complexity | 29191a2e10a94780cfda6b2a14a3f165 MD5 | raw file
Possible License(s): GPL-2.0
  1. /* io.c
  2. *
  3. * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
  4. *
  5. * This file is part of CyaSSL.
  6. *
  7. * CyaSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * CyaSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. #include <config.h>
  23. #endif
  24. #ifdef _WIN32_WCE
  25. /* On WinCE winsock2.h must be included before windows.h for socket stuff */
  26. #include <winsock2.h>
  27. #endif
  28. #include <cyassl/internal.h>
  29. /* if user writes own I/O callbacks they can define CYASSL_USER_IO to remove
  30. automatic setting of default I/O functions EmbedSend() and EmbedReceive()
  31. but they'll still need SetCallback xxx() at end of file
  32. */
  33. #ifndef CYASSL_USER_IO
  34. #ifdef HAVE_LIBZ
  35. #include "zlib.h"
  36. #endif
  37. #ifndef USE_WINDOWS_API
  38. #ifdef CYASSL_LWIP
  39. /* lwIP needs to be configured to use sockets API in this mode */
  40. /* LWIP_SOCKET 1 in lwip/opt.h or in build */
  41. #include "lwip/sockets.h"
  42. #include <errno.h>
  43. #ifndef LWIP_PROVIDE_ERRNO
  44. #define LWIP_PROVIDE_ERRNO 1
  45. #endif
  46. #elif defined(FREESCALE_MQX)
  47. #include <posix.h>
  48. #include <rtcs.h>
  49. #else
  50. #include <sys/types.h>
  51. #include <errno.h>
  52. #ifndef EBSNET
  53. #include <unistd.h>
  54. #endif
  55. #include <fcntl.h>
  56. #if !(defined(DEVKITPRO) || defined(THREADX) || defined(EBSNET))
  57. #include <sys/socket.h>
  58. #include <arpa/inet.h>
  59. #include <netinet/in.h>
  60. #include <netdb.h>
  61. #ifdef __PPU
  62. #include <netex/errno.h>
  63. #else
  64. #include <sys/ioctl.h>
  65. #endif
  66. #endif
  67. #ifdef THREADX
  68. #include <socket.h>
  69. #endif
  70. #ifdef EBSNET
  71. #include "rtipapi.h" /* errno */
  72. #include "socket.h"
  73. #endif
  74. #endif
  75. #endif /* USE_WINDOWS_API */
  76. #ifdef __sun
  77. #include <sys/filio.h>
  78. #endif
  79. #ifdef USE_WINDOWS_API
  80. /* no epipe yet */
  81. #ifndef WSAEPIPE
  82. #define WSAEPIPE -12345
  83. #endif
  84. #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK
  85. #define SOCKET_EAGAIN WSAETIMEDOUT
  86. #define SOCKET_ECONNRESET WSAECONNRESET
  87. #define SOCKET_EINTR WSAEINTR
  88. #define SOCKET_EPIPE WSAEPIPE
  89. #define SOCKET_ECONNREFUSED WSAENOTCONN
  90. #elif defined(__PPU)
  91. #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK
  92. #define SOCKET_EAGAIN SYS_NET_EAGAIN
  93. #define SOCKET_ECONNRESET SYS_NET_ECONNRESET
  94. #define SOCKET_EINTR SYS_NET_EINTR
  95. #define SOCKET_EPIPE SYS_NET_EPIPE
  96. #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED
  97. #elif defined(FREESCALE_MQX)
  98. /* RTCS doesn't have an EWOULDBLOCK error */
  99. #define SOCKET_EWOULDBLOCK EAGAIN
  100. #define SOCKET_EAGAIN EAGAIN
  101. #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET
  102. #define SOCKET_EINTR EINTR
  103. #define SOCKET_EPIPE EPIPE
  104. #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED
  105. #else
  106. #define SOCKET_EWOULDBLOCK EWOULDBLOCK
  107. #define SOCKET_EAGAIN EAGAIN
  108. #define SOCKET_ECONNRESET ECONNRESET
  109. #define SOCKET_EINTR EINTR
  110. #define SOCKET_EPIPE EPIPE
  111. #define SOCKET_ECONNREFUSED ECONNREFUSED
  112. #endif /* USE_WINDOWS_API */
  113. #ifdef DEVKITPRO
  114. /* from network.h */
  115. int net_send(int, const void*, int, unsigned int);
  116. int net_recv(int, void*, int, unsigned int);
  117. #define SEND_FUNCTION net_send
  118. #define RECV_FUNCTION net_recv
  119. #elif defined(CYASSL_LWIP)
  120. #define SEND_FUNCTION lwip_send
  121. #define RECV_FUNCTION lwip_recv
  122. #else
  123. #define SEND_FUNCTION send
  124. #define RECV_FUNCTION recv
  125. #endif
  126. #ifdef CYASSL_DTLS
  127. /* sizeof(struct timeval) will pass uninit bytes to setsockopt if padded */
  128. #ifdef USE_WINDOWS_API
  129. #define TIMEVAL_BYTES sizeof(timeout)
  130. #else
  131. #define TIMEVAL_BYTES sizeof(timeout.tv_sec) + sizeof(timeout.tv_usec)
  132. #endif
  133. #endif
  134. /* Translates return codes returned from
  135. * send() and recv() if need be.
  136. */
  137. static INLINE int TranslateReturnCode(int old, int sd)
  138. {
  139. (void)sd;
  140. #ifdef FREESCALE_MQX
  141. if (old == 0) {
  142. errno = SOCKET_EWOULDBLOCK;
  143. return -1; /* convert to BSD style wouldblock as error */
  144. }
  145. if (old < 0) {
  146. errno = RTCS_geterror(sd);
  147. if (errno == RTCSERR_TCP_CONN_CLOSING)
  148. return 0; /* convert to BSD style closing */
  149. }
  150. #endif
  151. return old;
  152. }
  153. static INLINE int LastError(void)
  154. {
  155. #ifdef USE_WINDOWS_API
  156. return WSAGetLastError();
  157. #elif defined(EBSNET)
  158. return xn_getlasterror();
  159. #else
  160. return errno;
  161. #endif
  162. }
  163. /* The receive embedded callback
  164. * return : nb bytes read, or error
  165. */
  166. int EmbedReceive(CYASSL *ssl, char *buf, int sz, void *ctx)
  167. {
  168. int recvd;
  169. int err;
  170. int sd = *(int*)ctx;
  171. #ifdef CYASSL_DTLS
  172. {
  173. int dtls_timeout = CyaSSL_dtls_get_current_timeout(ssl);
  174. if (CyaSSL_dtls(ssl)
  175. && !CyaSSL_get_using_nonblock(ssl)
  176. && dtls_timeout != 0) {
  177. #ifdef USE_WINDOWS_API
  178. DWORD timeout = dtls_timeout * 1000;
  179. #else
  180. struct timeval timeout = {dtls_timeout, 0};
  181. #endif
  182. setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO,
  183. (char*)&timeout, TIMEVAL_BYTES);
  184. }
  185. }
  186. #endif
  187. recvd = (int)RECV_FUNCTION(sd, buf, sz, ssl->rflags);
  188. recvd = TranslateReturnCode(recvd, sd);
  189. if (recvd < 0) {
  190. err = LastError();
  191. CYASSL_MSG("Embed Receive error");
  192. if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
  193. if (!CyaSSL_dtls(ssl) || CyaSSL_get_using_nonblock(ssl)) {
  194. CYASSL_MSG(" Would block");
  195. return IO_ERR_WANT_READ;
  196. }
  197. else {
  198. CYASSL_MSG(" Socket timeout");
  199. return IO_ERR_TIMEOUT;
  200. }
  201. }
  202. else if (err == SOCKET_ECONNRESET) {
  203. CYASSL_MSG(" Connection reset");
  204. return IO_ERR_CONN_RST;
  205. }
  206. else if (err == SOCKET_EINTR) {
  207. CYASSL_MSG(" Socket interrupted");
  208. return IO_ERR_ISR;
  209. }
  210. else if (err == SOCKET_ECONNREFUSED) {
  211. CYASSL_MSG(" Connection refused");
  212. return IO_ERR_WANT_READ;
  213. }
  214. else {
  215. CYASSL_MSG(" General error");
  216. return IO_ERR_GENERAL;
  217. }
  218. }
  219. else if (recvd == 0) {
  220. CYASSL_MSG("Embed receive connection closed");
  221. return IO_ERR_CONN_CLOSE;
  222. }
  223. return recvd;
  224. }
  225. /* The send embedded callback
  226. * return : nb bytes sent, or error
  227. */
  228. int EmbedSend(CYASSL* ssl, char *buf, int sz, void *ctx)
  229. {
  230. int sd = *(int*)ctx;
  231. int sent;
  232. int len = sz;
  233. int err;
  234. sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, ssl->wflags);
  235. if (sent < 0) {
  236. err = LastError();
  237. CYASSL_MSG("Embed Send error");
  238. if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
  239. CYASSL_MSG(" Would Block");
  240. return IO_ERR_WANT_WRITE;
  241. }
  242. else if (err == SOCKET_ECONNRESET) {
  243. CYASSL_MSG(" Connection reset");
  244. return IO_ERR_CONN_RST;
  245. }
  246. else if (err == SOCKET_EINTR) {
  247. CYASSL_MSG(" Socket interrupted");
  248. return IO_ERR_ISR;
  249. }
  250. else if (err == SOCKET_EPIPE) {
  251. CYASSL_MSG(" Socket EPIPE");
  252. return IO_ERR_CONN_CLOSE;
  253. }
  254. else {
  255. CYASSL_MSG(" General error");
  256. return IO_ERR_GENERAL;
  257. }
  258. }
  259. return sent;
  260. }
  261. #ifdef CYASSL_DTLS
  262. #include <cyassl/ctaocrypt/sha.h>
  263. #ifdef USE_WINDOWS_API
  264. #define XSOCKLENT int
  265. #else
  266. #define XSOCKLENT socklen_t
  267. #endif
  268. #define SENDTO_FUNCTION sendto
  269. #define RECVFROM_FUNCTION recvfrom
  270. /* The receive embedded callback
  271. * return : nb bytes read, or error
  272. */
  273. int EmbedReceiveFrom(CYASSL *ssl, char *buf, int sz, void *ctx)
  274. {
  275. CYASSL_DTLS_CTX* dtlsCtx = (CYASSL_DTLS_CTX*)ctx;
  276. int recvd;
  277. int err;
  278. int sd = dtlsCtx->fd;
  279. int dtls_timeout = CyaSSL_dtls_get_current_timeout(ssl);
  280. struct sockaddr_in peer;
  281. XSOCKLENT peerSz = sizeof(peer);
  282. CYASSL_ENTER("EmbedReceiveFrom()");
  283. if (!CyaSSL_get_using_nonblock(ssl) && dtls_timeout != 0) {
  284. #ifdef USE_WINDOWS_API
  285. DWORD timeout = dtls_timeout * 1000;
  286. #else
  287. struct timeval timeout = { dtls_timeout, 0 };
  288. #endif
  289. setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO,
  290. (char*)&timeout, TIMEVAL_BYTES);
  291. }
  292. recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
  293. (struct sockaddr*)&peer, &peerSz);
  294. recvd = TranslateReturnCode(recvd, sd);
  295. if (recvd < 0) {
  296. err = LastError();
  297. CYASSL_MSG("Embed Receive From error");
  298. if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
  299. if (CyaSSL_get_using_nonblock(ssl)) {
  300. CYASSL_MSG(" Would block");
  301. return IO_ERR_WANT_READ;
  302. }
  303. else {
  304. CYASSL_MSG(" Socket timeout");
  305. return IO_ERR_TIMEOUT;
  306. }
  307. }
  308. else if (err == SOCKET_ECONNRESET) {
  309. CYASSL_MSG(" Connection reset");
  310. return IO_ERR_CONN_RST;
  311. }
  312. else if (err == SOCKET_EINTR) {
  313. CYASSL_MSG(" Socket interrupted");
  314. return IO_ERR_ISR;
  315. }
  316. else if (err == SOCKET_ECONNREFUSED) {
  317. CYASSL_MSG(" Connection refused");
  318. return IO_ERR_WANT_READ;
  319. }
  320. else {
  321. CYASSL_MSG(" General error");
  322. return IO_ERR_GENERAL;
  323. }
  324. }
  325. else {
  326. if (dtlsCtx != NULL
  327. && dtlsCtx->peer.sz > 0
  328. && peerSz != (XSOCKLENT)dtlsCtx->peer.sz
  329. && memcmp(&peer, dtlsCtx->peer.sa, peerSz) != 0) {
  330. CYASSL_MSG(" Ignored packet from invalid peer");
  331. return IO_ERR_WANT_READ;
  332. }
  333. }
  334. return recvd;
  335. }
  336. /* The send embedded callback
  337. * return : nb bytes sent, or error
  338. */
  339. int EmbedSendTo(CYASSL* ssl, char *buf, int sz, void *ctx)
  340. {
  341. CYASSL_DTLS_CTX* dtlsCtx = (CYASSL_DTLS_CTX*)ctx;
  342. int sd = dtlsCtx->fd;
  343. int sent;
  344. int len = sz;
  345. int err;
  346. CYASSL_ENTER("EmbedSendTo()");
  347. sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags,
  348. dtlsCtx->peer.sa, dtlsCtx->peer.sz);
  349. if (sent < 0) {
  350. err = LastError();
  351. CYASSL_MSG("Embed Send To error");
  352. if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
  353. CYASSL_MSG(" Would Block");
  354. return IO_ERR_WANT_WRITE;
  355. }
  356. else if (err == SOCKET_ECONNRESET) {
  357. CYASSL_MSG(" Connection reset");
  358. return IO_ERR_CONN_RST;
  359. }
  360. else if (err == SOCKET_EINTR) {
  361. CYASSL_MSG(" Socket interrupted");
  362. return IO_ERR_ISR;
  363. }
  364. else if (err == SOCKET_EPIPE) {
  365. CYASSL_MSG(" Socket EPIPE");
  366. return IO_ERR_CONN_CLOSE;
  367. }
  368. else {
  369. CYASSL_MSG(" General error");
  370. return IO_ERR_GENERAL;
  371. }
  372. }
  373. return sent;
  374. }
  375. /* The DTLS Generate Cookie callback
  376. * return : number of bytes copied into buf, or error
  377. */
  378. int EmbedGenerateCookie(byte *buf, int sz, void *ctx)
  379. {
  380. CYASSL* ssl = (CYASSL*)ctx;
  381. int sd = ssl->wfd;
  382. struct sockaddr_in peer;
  383. XSOCKLENT peerSz = sizeof(peer);
  384. byte cookieSrc[sizeof(struct in_addr) + sizeof(int)];
  385. int cookieSrcSz = 0;
  386. Sha sha;
  387. getpeername(sd, (struct sockaddr*)&peer, &peerSz);
  388. if (peer.sin_family == AF_INET) {
  389. struct sockaddr_in *s = (struct sockaddr_in*)&peer;
  390. cookieSrcSz = sizeof(struct in_addr) + sizeof(s->sin_port);
  391. XMEMCPY(cookieSrc, &s->sin_port, sizeof(s->sin_port));
  392. XMEMCPY(cookieSrc + sizeof(s->sin_port),
  393. &s->sin_addr, sizeof(struct in_addr));
  394. }
  395. InitSha(&sha);
  396. ShaUpdate(&sha, cookieSrc, cookieSrcSz);
  397. if (sz < SHA_DIGEST_SIZE) {
  398. byte digest[SHA_DIGEST_SIZE];
  399. ShaFinal(&sha, digest);
  400. XMEMCPY(buf, digest, sz);
  401. return sz;
  402. }
  403. ShaFinal(&sha, buf);
  404. return SHA_DIGEST_SIZE;
  405. }
  406. #endif /* CYASSL_DTLS */
  407. #ifdef HAVE_OCSP
  408. #ifdef TEST_IPV6
  409. typedef struct sockaddr_in6 SOCKADDR_IN_T;
  410. #define AF_INET_V AF_INET6
  411. #else
  412. typedef struct sockaddr_in SOCKADDR_IN_T;
  413. #define AF_INET_V AF_INET
  414. #endif
  415. static INLINE int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port)
  416. {
  417. SOCKADDR_IN_T addr;
  418. const char* host = ip;
  419. /* peer could be in human readable form */
  420. if (ip != INADDR_ANY && isalpha(ip[0])) {
  421. struct hostent* entry = gethostbyname(ip);
  422. if (entry) {
  423. struct sockaddr_in tmp;
  424. XMEMSET(&tmp, 0, sizeof(struct sockaddr_in));
  425. XMEMCPY(&tmp.sin_addr.s_addr, entry->h_addr_list[0],
  426. entry->h_length);
  427. host = inet_ntoa(tmp.sin_addr);
  428. }
  429. else {
  430. CYASSL_MSG("no addr entry for OCSP responder");
  431. return -1;
  432. }
  433. }
  434. *sockfd = socket(AF_INET_V, SOCK_STREAM, 0);
  435. XMEMSET(&addr, 0, sizeof(SOCKADDR_IN_T));
  436. addr.sin_family = AF_INET_V;
  437. addr.sin_port = htons(port);
  438. if (host == INADDR_ANY)
  439. addr.sin_addr.s_addr = INADDR_ANY;
  440. else
  441. addr.sin_addr.s_addr = inet_addr(host);
  442. if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) {
  443. CYASSL_MSG("OCSP responder tcp connect failed");
  444. return -1;
  445. }
  446. return 0;
  447. }
  448. static int build_http_request(const char* domainName, const char* path,
  449. int ocspReqSz, byte* buf, int bufSize)
  450. {
  451. return snprintf((char*)buf, bufSize,
  452. "POST %s HTTP/1.1\r\n"
  453. "Host: %s\r\n"
  454. "Content-Length: %d\r\n"
  455. "Content-Type: application/ocsp-request\r\n"
  456. "\r\n",
  457. path, domainName, ocspReqSz);
  458. }
  459. static int decode_http_response(byte* httpBuf, int httpBufSz, byte** dst)
  460. {
  461. int idx = 0;
  462. int stop = 0;
  463. int len = 0;
  464. byte* contentType = NULL;
  465. byte* contentLength = NULL;
  466. char* buf = (char*)httpBuf; /* kludge so I'm not constantly casting */
  467. if (XSTRNCASECMP(buf, "HTTP/1", 6) != 0)
  468. return 0;
  469. idx = 9; /* sets to the first byte after "HTTP/1.X ", which should be the
  470. * HTTP result code */
  471. if (XSTRNCASECMP(&buf[idx], "200 OK", 6) != 0)
  472. return 0;
  473. idx += 8;
  474. while (idx < httpBufSz && !stop) {
  475. if (buf[idx] == '\r' && buf[idx+1] == '\n') {
  476. stop = 1;
  477. idx += 2;
  478. }
  479. else {
  480. if (contentType == NULL &&
  481. XSTRNCASECMP(&buf[idx], "Content-Type:", 13) == 0) {
  482. idx += 13;
  483. if (buf[idx] == ' ') idx++;
  484. if (XSTRNCASECMP(&buf[idx],
  485. "application/ocsp-response", 25) != 0) {
  486. return 0;
  487. }
  488. idx += 27;
  489. }
  490. else if (contentLength == NULL &&
  491. XSTRNCASECMP(&buf[idx], "Content-Length:", 15) == 0) {
  492. idx += 15;
  493. if (buf[idx] == ' ') idx++;
  494. while (buf[idx] >= '0' && buf[idx] <= '9' && idx < httpBufSz) {
  495. len = (len * 10) + (buf[idx] - '0');
  496. idx++;
  497. }
  498. idx += 2; /* skip the crlf */
  499. }
  500. else {
  501. /* Advance idx past the next \r\n */
  502. char* end = XSTRSTR(&buf[idx], "\r\n");
  503. idx = (int)(end - buf + 2);
  504. stop = 1;
  505. }
  506. }
  507. }
  508. if (len > 0) {
  509. *dst = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_IN_BUFFER);
  510. XMEMCPY(*dst, httpBuf + idx, len);
  511. }
  512. return len;
  513. }
  514. static int decode_url(const char* url, int urlSz,
  515. char* outName, char* outPath, int* outPort)
  516. {
  517. if (outName != NULL && outPath != NULL && outPort != NULL)
  518. {
  519. if (url == NULL || urlSz == 0)
  520. {
  521. *outName = 0;
  522. *outPath = 0;
  523. *outPort = 0;
  524. }
  525. else
  526. {
  527. int i, cur;
  528. /* need to break the url down into scheme, address, and port */
  529. /* "http://example.com:8080/" */
  530. if (XSTRNCMP(url, "http://", 7) == 0) {
  531. cur = 7;
  532. } else cur = 0;
  533. i = 0;
  534. while (url[cur] != 0 && url[cur] != ':' && url[cur] != '/') {
  535. outName[i++] = url[cur++];
  536. }
  537. outName[i] = 0;
  538. /* Need to pick out the path after the domain name */
  539. if (cur < urlSz && url[cur] == ':') {
  540. char port[6];
  541. int j;
  542. i = 0;
  543. cur++;
  544. while (cur < urlSz && url[cur] != 0 && url[cur] != '/' &&
  545. i < 6) {
  546. port[i++] = url[cur++];
  547. }
  548. *outPort = 0;
  549. for (j = 0; j < i; j++) {
  550. if (port[j] < '0' || port[j] > '9') return -1;
  551. *outPort = (*outPort * 10) + (port[j] - '0');
  552. }
  553. }
  554. else
  555. *outPort = 80;
  556. if (cur < urlSz && url[cur] == '/') {
  557. i = 0;
  558. while (cur < urlSz && url[cur] != 0 && i < 80) {
  559. outPath[i++] = url[cur++];
  560. }
  561. outPath[i] = 0;
  562. }
  563. else {
  564. outPath[0] = '/';
  565. outPath[1] = 0;
  566. }
  567. }
  568. }
  569. return 0;
  570. }
  571. #define SCRATCH_BUFFER_SIZE 2048
  572. int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
  573. byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
  574. {
  575. char domainName[80], path[80];
  576. int port, httpBufSz, sfd;
  577. int ocspRespSz = 0;
  578. byte* httpBuf = NULL;
  579. (void)ctx;
  580. if (ocspReqBuf == NULL || ocspReqSz == 0) {
  581. CYASSL_MSG("OCSP request is required for lookup");
  582. return -1;
  583. }
  584. if (ocspRespBuf == NULL) {
  585. CYASSL_MSG("Cannot save OCSP response");
  586. return -1;
  587. }
  588. if (decode_url(url, urlSz, domainName, path, &port) < 0) {
  589. CYASSL_MSG("Unable to decode OCSP URL");
  590. return -1;
  591. }
  592. httpBufSz = SCRATCH_BUFFER_SIZE;
  593. httpBuf = (byte*)XMALLOC(httpBufSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
  594. if (httpBuf == NULL) {
  595. CYASSL_MSG("Unable to create OCSP response buffer");
  596. return -1;
  597. }
  598. *ocspRespBuf = httpBuf;
  599. httpBufSz = build_http_request(domainName, path, ocspReqSz,
  600. httpBuf, httpBufSz);
  601. if ((tcp_connect(&sfd, domainName, port) == 0) && (sfd > 0)) {
  602. int written;
  603. written = (int)write(sfd, httpBuf, httpBufSz);
  604. if (written == httpBufSz) {
  605. written = (int)write(sfd, ocspReqBuf, ocspReqSz);
  606. if (written == ocspReqSz) {
  607. httpBufSz = (int)read(sfd, httpBuf, SCRATCH_BUFFER_SIZE);
  608. if (httpBufSz > 0) {
  609. ocspRespSz = decode_http_response(httpBuf, httpBufSz,
  610. ocspRespBuf);
  611. }
  612. }
  613. }
  614. close(sfd);
  615. if (ocspRespSz == 0) {
  616. CYASSL_MSG("OCSP response was not OK, no OCSP response");
  617. return -1;
  618. }
  619. } else {
  620. CYASSL_MSG("OCSP Responder connection failed");
  621. return -1;
  622. }
  623. return ocspRespSz;
  624. }
  625. void EmbedOcspRespFree(void* ctx, byte *resp)
  626. {
  627. (void)ctx;
  628. if (resp)
  629. XFREE(resp, NULL, DYNAMIC_TYPE_IN_BUFFER);
  630. }
  631. #endif
  632. #endif /* CYASSL_USER_IO */
  633. CYASSL_API void CyaSSL_SetIORecv(CYASSL_CTX *ctx, CallbackIORecv CBIORecv)
  634. {
  635. ctx->CBIORecv = CBIORecv;
  636. }
  637. CYASSL_API void CyaSSL_SetIOSend(CYASSL_CTX *ctx, CallbackIOSend CBIOSend)
  638. {
  639. ctx->CBIOSend = CBIOSend;
  640. }
  641. CYASSL_API void CyaSSL_SetIOReadCtx(CYASSL* ssl, void *rctx)
  642. {
  643. ssl->IOCB_ReadCtx = rctx;
  644. }
  645. CYASSL_API void CyaSSL_SetIOWriteCtx(CYASSL* ssl, void *wctx)
  646. {
  647. ssl->IOCB_WriteCtx = wctx;
  648. }
  649. CYASSL_API void CyaSSL_SetIOReadFlags(CYASSL* ssl, int flags)
  650. {
  651. ssl->rflags = flags;
  652. }
  653. CYASSL_API void CyaSSL_SetIOWriteFlags(CYASSL* ssl, int flags)
  654. {
  655. ssl->wflags = flags;
  656. }
  657. #ifdef HAVE_OCSP
  658. CYASSL_API void CyaSSL_SetIOOcsp(CYASSL_CTX* ctx, CallbackIOOcsp cb)
  659. {
  660. ctx->ocsp.CBIOOcsp = cb;
  661. }
  662. CYASSL_API void CyaSSL_SetIOOcspRespFree(CYASSL_CTX* ctx,
  663. CallbackIOOcspRespFree cb)
  664. {
  665. ctx->ocsp.CBIOOcspRespFree = cb;
  666. }
  667. CYASSL_API void CyaSSL_SetIOOcspCtx(CYASSL_CTX* ctx, void *octx)
  668. {
  669. ctx->ocsp.IOCB_OcspCtx = octx;
  670. }
  671. #endif