Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of wolfSSL by
io.c
00001 /* io.c 00002 * 00003 * Copyright (C) 2006-2016 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 00024 #ifdef HAVE_CONFIG_H 00025 #include <config.h> 00026 #endif 00027 00028 #include <wolfssl/wolfcrypt/settings.h> 00029 00030 #ifndef WOLFCRYPT_ONLY 00031 00032 #ifdef _WIN32_WCE 00033 /* On WinCE winsock2.h must be included before windows.h for socket stuff */ 00034 #include <winsock2.h> 00035 #endif 00036 00037 #include <wolfssl/internal.h> 00038 #include <wolfssl/error-ssl.h> 00039 #include <wolfssl/io.h> 00040 00041 #if defined(HAVE_HTTP_CLIENT) 00042 #include <stdlib.h> /* atoi(), strtol() */ 00043 #endif 00044 00045 /* 00046 Possible IO enable options: 00047 * WOLFSSL_USER_IO: Disables default Embed* callbacks and default: off 00048 allows user to define their own using 00049 wolfSSL_SetIORecv and wolfSSL_SetIOSend 00050 * USE_WOLFSSL_IO: Enables the wolfSSL IO functions default: off 00051 * HAVE_HTTP_CLIENT: Enables HTTP client API's default: off 00052 (unless HAVE_OCSP or HAVE_CRL_IO defined) 00053 * HAVE_IO_TIMEOUT: Enables support for connect timeout default: off 00054 */ 00055 00056 00057 /* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove 00058 automatic setting of default I/O functions EmbedSend() and EmbedReceive() 00059 but they'll still need SetCallback xxx() at end of file 00060 */ 00061 00062 #if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT) 00063 00064 /* Translates return codes returned from 00065 * send() and recv() if need be. 00066 */ 00067 static INLINE int TranslateReturnCode(int old, int sd) 00068 { 00069 (void)sd; 00070 00071 #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) 00072 if (old == 0) { 00073 errno = SOCKET_EWOULDBLOCK; 00074 return -1; /* convert to BSD style wouldblock as error */ 00075 } 00076 00077 if (old < 0) { 00078 errno = RTCS_geterror(sd); 00079 if (errno == RTCSERR_TCP_CONN_CLOSING) 00080 return 0; /* convert to BSD style closing */ 00081 if (errno == RTCSERR_TCP_CONN_RLSD) 00082 errno = SOCKET_ECONNRESET; 00083 if (errno == RTCSERR_TCP_TIMED_OUT) 00084 errno = SOCKET_EAGAIN; 00085 } 00086 #endif 00087 00088 return old; 00089 } 00090 00091 static INLINE int LastError(void) 00092 { 00093 #ifdef USE_WINDOWS_API 00094 return WSAGetLastError(); 00095 #elif defined(EBSNET) 00096 return xn_getlasterror(); 00097 #else 00098 return errno; 00099 #endif 00100 } 00101 00102 #endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */ 00103 00104 00105 #ifdef USE_WOLFSSL_IO 00106 00107 /* The receive embedded callback 00108 * return : nb bytes read, or error 00109 */ 00110 int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) 00111 { 00112 int sd = *(int*)ctx; 00113 int recvd; 00114 00115 #ifdef WOLFSSL_DTLS 00116 { 00117 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); 00118 if (wolfSSL_dtls(ssl) 00119 && !wolfSSL_get_using_nonblock(ssl) 00120 && dtls_timeout != 0) { 00121 #ifdef USE_WINDOWS_API 00122 DWORD timeout = dtls_timeout * 1000; 00123 #else 00124 struct timeval timeout; 00125 XMEMSET(&timeout, 0, sizeof(timeout)); 00126 timeout.tv_sec = dtls_timeout; 00127 #endif 00128 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, 00129 sizeof(timeout)) != 0) { 00130 WOLFSSL_MSG("setsockopt rcvtimeo failed"); 00131 } 00132 } 00133 } 00134 #endif 00135 00136 recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags); 00137 if (recvd < 0) { 00138 int err = LastError(); 00139 WOLFSSL_MSG("Embed Receive error"); 00140 00141 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { 00142 if (!wolfSSL_dtls(ssl) || wolfSSL_get_using_nonblock(ssl)) { 00143 WOLFSSL_MSG("\tWould block"); 00144 return WOLFSSL_CBIO_ERR_WANT_READ; 00145 } 00146 else { 00147 WOLFSSL_MSG("\tSocket timeout"); 00148 return WOLFSSL_CBIO_ERR_TIMEOUT; 00149 } 00150 } 00151 else if (err == SOCKET_ECONNRESET) { 00152 WOLFSSL_MSG("\tConnection reset"); 00153 return WOLFSSL_CBIO_ERR_CONN_RST; 00154 } 00155 else if (err == SOCKET_EINTR) { 00156 WOLFSSL_MSG("\tSocket interrupted"); 00157 return WOLFSSL_CBIO_ERR_ISR; 00158 } 00159 else if (err == SOCKET_ECONNREFUSED) { 00160 WOLFSSL_MSG("\tConnection refused"); 00161 return WOLFSSL_CBIO_ERR_WANT_READ; 00162 } 00163 else if (err == SOCKET_ECONNABORTED) { 00164 WOLFSSL_MSG("\tConnection aborted"); 00165 return WOLFSSL_CBIO_ERR_CONN_CLOSE; 00166 } 00167 else { 00168 WOLFSSL_MSG("\tGeneral error"); 00169 return WOLFSSL_CBIO_ERR_GENERAL; 00170 } 00171 } 00172 else if (recvd == 0) { 00173 WOLFSSL_MSG("Embed receive connection closed"); 00174 return WOLFSSL_CBIO_ERR_CONN_CLOSE; 00175 } 00176 00177 return recvd; 00178 } 00179 00180 /* The send embedded callback 00181 * return : nb bytes sent, or error 00182 */ 00183 int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) 00184 { 00185 int sd = *(int*)ctx; 00186 int sent; 00187 00188 sent = wolfIO_Send(sd, buf, sz, ssl->wflags); 00189 if (sent < 0) { 00190 int err = LastError(); 00191 WOLFSSL_MSG("Embed Send error"); 00192 00193 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { 00194 WOLFSSL_MSG("\tWould Block"); 00195 return WOLFSSL_CBIO_ERR_WANT_WRITE; 00196 } 00197 else if (err == SOCKET_ECONNRESET) { 00198 WOLFSSL_MSG("\tConnection reset"); 00199 return WOLFSSL_CBIO_ERR_CONN_RST; 00200 } 00201 else if (err == SOCKET_EINTR) { 00202 WOLFSSL_MSG("\tSocket interrupted"); 00203 return WOLFSSL_CBIO_ERR_ISR; 00204 } 00205 else if (err == SOCKET_EPIPE) { 00206 WOLFSSL_MSG("\tSocket EPIPE"); 00207 return WOLFSSL_CBIO_ERR_CONN_CLOSE; 00208 } 00209 else { 00210 WOLFSSL_MSG("\tGeneral error"); 00211 return WOLFSSL_CBIO_ERR_GENERAL; 00212 } 00213 } 00214 00215 return sent; 00216 } 00217 00218 00219 #ifdef WOLFSSL_DTLS 00220 00221 #include <wolfssl/wolfcrypt/sha.h> 00222 00223 #define SENDTO_FUNCTION sendto 00224 #define RECVFROM_FUNCTION recvfrom 00225 00226 00227 /* The receive embedded callback 00228 * return : nb bytes read, or error 00229 */ 00230 int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) 00231 { 00232 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; 00233 int recvd; 00234 int err; 00235 int sd = dtlsCtx->rfd; 00236 int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); 00237 SOCKADDR_S peer; 00238 XSOCKLENT peerSz = sizeof(peer); 00239 00240 WOLFSSL_ENTER("EmbedReceiveFrom()"); 00241 00242 if (ssl->options.handShakeDone) 00243 dtls_timeout = 0; 00244 00245 if (!wolfSSL_get_using_nonblock(ssl)) { 00246 #ifdef USE_WINDOWS_API 00247 DWORD timeout = dtls_timeout * 1000; 00248 #else 00249 struct timeval timeout; 00250 XMEMSET(&timeout, 0, sizeof(timeout)); 00251 timeout.tv_sec = dtls_timeout; 00252 #endif 00253 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, 00254 sizeof(timeout)) != 0) { 00255 WOLFSSL_MSG("setsockopt rcvtimeo failed"); 00256 } 00257 } 00258 00259 recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, 00260 (SOCKADDR*)&peer, &peerSz); 00261 00262 recvd = TranslateReturnCode(recvd, sd); 00263 00264 if (recvd < 0) { 00265 err = LastError(); 00266 WOLFSSL_MSG("Embed Receive From error"); 00267 00268 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { 00269 if (wolfSSL_get_using_nonblock(ssl)) { 00270 WOLFSSL_MSG("\tWould block"); 00271 return WOLFSSL_CBIO_ERR_WANT_READ; 00272 } 00273 else { 00274 WOLFSSL_MSG("\tSocket timeout"); 00275 return WOLFSSL_CBIO_ERR_TIMEOUT; 00276 } 00277 } 00278 else if (err == SOCKET_ECONNRESET) { 00279 WOLFSSL_MSG("\tConnection reset"); 00280 return WOLFSSL_CBIO_ERR_CONN_RST; 00281 } 00282 else if (err == SOCKET_EINTR) { 00283 WOLFSSL_MSG("\tSocket interrupted"); 00284 return WOLFSSL_CBIO_ERR_ISR; 00285 } 00286 else if (err == SOCKET_ECONNREFUSED) { 00287 WOLFSSL_MSG("\tConnection refused"); 00288 return WOLFSSL_CBIO_ERR_WANT_READ; 00289 } 00290 else { 00291 WOLFSSL_MSG("\tGeneral error"); 00292 return WOLFSSL_CBIO_ERR_GENERAL; 00293 } 00294 } 00295 else { 00296 if (dtlsCtx->peer.sz > 0 00297 && peerSz != (XSOCKLENT)dtlsCtx->peer.sz 00298 && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) { 00299 WOLFSSL_MSG("\tIgnored packet from invalid peer"); 00300 return WOLFSSL_CBIO_ERR_WANT_READ; 00301 } 00302 } 00303 00304 return recvd; 00305 } 00306 00307 00308 /* The send embedded callback 00309 * return : nb bytes sent, or error 00310 */ 00311 int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) 00312 { 00313 WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; 00314 int sd = dtlsCtx->wfd; 00315 int sent; 00316 int len = sz; 00317 int err; 00318 00319 WOLFSSL_ENTER("EmbedSendTo()"); 00320 00321 sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags, 00322 (const SOCKADDR*)dtlsCtx->peer.sa, 00323 dtlsCtx->peer.sz); 00324 00325 sent = TranslateReturnCode(sent, sd); 00326 00327 if (sent < 0) { 00328 err = LastError(); 00329 WOLFSSL_MSG("Embed Send To error"); 00330 00331 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { 00332 WOLFSSL_MSG("\tWould Block"); 00333 return WOLFSSL_CBIO_ERR_WANT_WRITE; 00334 } 00335 else if (err == SOCKET_ECONNRESET) { 00336 WOLFSSL_MSG("\tConnection reset"); 00337 return WOLFSSL_CBIO_ERR_CONN_RST; 00338 } 00339 else if (err == SOCKET_EINTR) { 00340 WOLFSSL_MSG("\tSocket interrupted"); 00341 return WOLFSSL_CBIO_ERR_ISR; 00342 } 00343 else if (err == SOCKET_EPIPE) { 00344 WOLFSSL_MSG("\tSocket EPIPE"); 00345 return WOLFSSL_CBIO_ERR_CONN_CLOSE; 00346 } 00347 else { 00348 WOLFSSL_MSG("\tGeneral error"); 00349 return WOLFSSL_CBIO_ERR_GENERAL; 00350 } 00351 } 00352 00353 return sent; 00354 } 00355 00356 00357 /* The DTLS Generate Cookie callback 00358 * return : number of bytes copied into buf, or error 00359 */ 00360 int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) 00361 { 00362 int sd = ssl->wfd; 00363 SOCKADDR_S peer; 00364 XSOCKLENT peerSz = sizeof(peer); 00365 byte digest[SHA_DIGEST_SIZE]; 00366 int ret = 0; 00367 00368 (void)ctx; 00369 00370 XMEMSET(&peer, 0, sizeof(peer)); 00371 if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) { 00372 WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie"); 00373 return GEN_COOKIE_E; 00374 } 00375 00376 ret = wc_ShaHash((byte*)&peer, peerSz, digest); 00377 if (ret != 0) 00378 return ret; 00379 00380 if (sz > SHA_DIGEST_SIZE) 00381 sz = SHA_DIGEST_SIZE; 00382 XMEMCPY(buf, digest, sz); 00383 00384 return sz; 00385 } 00386 00387 #ifdef WOLFSSL_SESSION_EXPORT 00388 00389 /* get the peer information in human readable form (ip, port, family) 00390 * default function assumes BSD sockets 00391 * can be overriden with wolfSSL_CTX_SetIOGetPeer 00392 */ 00393 int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, 00394 unsigned short* port, int* fam) 00395 { 00396 SOCKADDR_S peer; 00397 word32 peerSz; 00398 int ret; 00399 00400 if (ssl == NULL || ip == NULL || ipSz == NULL || 00401 port == NULL || fam == NULL) { 00402 return BAD_FUNC_ARG; 00403 } 00404 00405 /* get peer information stored in ssl struct */ 00406 peerSz = sizeof(SOCKADDR_S); 00407 if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz)) 00408 != SSL_SUCCESS) { 00409 return ret; 00410 } 00411 00412 /* extract family, ip, and port */ 00413 *fam = ((SOCKADDR_S*)&peer)->ss_family; 00414 switch (*fam) { 00415 case WOLFSSL_IP4: 00416 if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr), 00417 ip, *ipSz) == NULL) { 00418 WOLFSSL_MSG("XINET_NTOP error"); 00419 return SOCKET_ERROR_E; 00420 } 00421 *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port); 00422 break; 00423 00424 case WOLFSSL_IP6: 00425 #ifdef WOLFSSL_IPV6 00426 if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr), 00427 ip, *ipSz) == NULL) { 00428 WOLFSSL_MSG("XINET_NTOP error"); 00429 return SOCKET_ERROR_E; 00430 } 00431 *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port); 00432 #endif /* WOLFSSL_IPV6 */ 00433 break; 00434 00435 default: 00436 WOLFSSL_MSG("Unknown family type"); 00437 return SOCKET_ERROR_E; 00438 } 00439 ip[*ipSz - 1] = '\0'; /* make sure has terminator */ 00440 *ipSz = (word16)XSTRLEN(ip); 00441 00442 return SSL_SUCCESS; 00443 } 00444 00445 /* set the peer information in human readable form (ip, port, family) 00446 * default function assumes BSD sockets 00447 * can be overriden with wolfSSL_CTX_SetIOSetPeer 00448 */ 00449 int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, 00450 unsigned short port, int fam) 00451 { 00452 int ret; 00453 SOCKADDR_S addr; 00454 00455 /* sanity checks on arguments */ 00456 if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) { 00457 return BAD_FUNC_ARG; 00458 } 00459 00460 addr.ss_family = fam; 00461 switch (addr.ss_family) { 00462 case WOLFSSL_IP4: 00463 if (XINET_PTON(addr.ss_family, ip, 00464 &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) { 00465 WOLFSSL_MSG("XINET_PTON error"); 00466 return SOCKET_ERROR_E; 00467 } 00468 ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port); 00469 00470 /* peer sa is free'd in SSL_ResourceFree */ 00471 if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr, 00472 sizeof(SOCKADDR_IN)))!= SSL_SUCCESS) { 00473 WOLFSSL_MSG("Import DTLS peer info error"); 00474 return ret; 00475 } 00476 break; 00477 00478 case WOLFSSL_IP6: 00479 #ifdef WOLFSSL_IPV6 00480 if (XINET_PTON(addr.ss_family, ip, 00481 &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) { 00482 WOLFSSL_MSG("XINET_PTON error"); 00483 return SOCKET_ERROR_E; 00484 } 00485 ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port); 00486 00487 /* peer sa is free'd in SSL_ResourceFree */ 00488 if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr, 00489 sizeof(SOCKADDR_IN6)))!= SSL_SUCCESS) { 00490 WOLFSSL_MSG("Import DTLS peer info error"); 00491 return ret; 00492 } 00493 #endif /* WOLFSSL_IPV6 */ 00494 break; 00495 00496 default: 00497 WOLFSSL_MSG("Unknown address family"); 00498 return BUFFER_E; 00499 } 00500 00501 return SSL_SUCCESS; 00502 } 00503 #endif /* WOLFSSL_SESSION_EXPORT */ 00504 #endif /* WOLFSSL_DTLS */ 00505 00506 00507 int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags) 00508 { 00509 int recvd; 00510 00511 recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags); 00512 recvd = TranslateReturnCode(recvd, sd); 00513 00514 return recvd; 00515 } 00516 00517 int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags) 00518 { 00519 int sent; 00520 int len = sz; 00521 00522 sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, wrFlags); 00523 sent = TranslateReturnCode(sent, sd); 00524 00525 return sent; 00526 } 00527 00528 #endif /* USE_WOLFSSL_IO */ 00529 00530 00531 #ifdef HAVE_HTTP_CLIENT 00532 00533 #ifndef HAVE_IO_TIMEOUT 00534 #define io_timeout_sec 0 00535 #else 00536 00537 #ifndef DEFAULT_TIMEOUT_SEC 00538 #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */ 00539 #endif 00540 00541 static int io_timeout_sec = DEFAULT_TIMEOUT_SEC; 00542 00543 void wolfIO_SetTimeout(int to_sec) 00544 { 00545 io_timeout_sec = to_sec; 00546 } 00547 00548 int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking) 00549 { 00550 int ret = 0; 00551 00552 #ifdef USE_WINDOWS_API 00553 unsigned long blocking = non_blocking; 00554 ret = ioctlsocket(sockfd, FIONBIO, &blocking); 00555 if (ret == SOCKET_ERROR) 00556 ret = -1; 00557 #else 00558 ret = fcntl(sockfd, F_GETFL, 0); 00559 if (ret >= 0) { 00560 if (non_blocking) 00561 ret |= O_NONBLOCK; 00562 else 00563 ret &= ~O_NONBLOCK; 00564 ret = fcntl(sockfd, F_SETFL, ret); 00565 } 00566 #endif 00567 if (ret < 0) { 00568 WOLFSSL_MSG("wolfIO_SetBlockingMode failed"); 00569 } 00570 00571 return ret; 00572 } 00573 00574 #ifdef _MSC_VER 00575 /* 4204: non-constant aggregate initializer (nfds = sockfd + 1) */ 00576 #pragma warning(disable: 4204) 00577 #endif 00578 int wolfIO_Select(SOCKET_T sockfd, int to_sec) 00579 { 00580 fd_set fds; 00581 SOCKET_T nfds = sockfd + 1; 00582 struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0}; 00583 int ret; 00584 00585 FD_ZERO(&fds); 00586 FD_SET(sockfd, &fds); 00587 00588 ret = select(nfds, &fds, &fds, NULL, &timeout); 00589 if (ret == 0) { 00590 #ifdef DEBUG_HTTP 00591 printf("Timeout: %d\n", ret); 00592 #endif 00593 return HTTP_TIMEOUT; 00594 } 00595 else if (ret > 0) { 00596 if (FD_ISSET(sockfd, &fds)) 00597 return 0; 00598 } 00599 return SOCKET_ERROR_E; 00600 } 00601 #endif /* HAVE_IO_TIMEOUT */ 00602 00603 static int wolfIO_Word16ToString(char* d, word16 number) 00604 { 00605 int i = 0; 00606 word16 order = 10000; 00607 word16 digit; 00608 00609 if (d == NULL) 00610 return i; 00611 00612 if (number == 0) 00613 d[i++] = '0'; 00614 else { 00615 while (order) { 00616 digit = number / order; 00617 if (i > 0 || digit != 0) 00618 d[i++] = (char)digit + '0'; 00619 if (digit != 0) 00620 number %= digit * order; 00621 00622 order = (order > 1) ? order / 10 : 0; 00623 } 00624 } 00625 d[i] = 0; /* null terminate */ 00626 00627 return i; 00628 } 00629 00630 int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec) 00631 { 00632 #ifdef HAVE_SOCKADDR 00633 int ret = 0; 00634 SOCKADDR_S addr; 00635 int sockaddr_len = sizeof(SOCKADDR_IN); 00636 #ifdef HAVE_GETADDRINFO 00637 ADDRINFO hints; 00638 ADDRINFO* answer = NULL; 00639 char strPort[6]; 00640 #else 00641 HOSTENT* entry; 00642 SOCKADDR_IN *sin; 00643 #endif 00644 00645 XMEMSET(&addr, 0, sizeof(addr)); 00646 00647 #ifdef WOLFIO_DEBUG 00648 printf("TCP Connect: %s:%d\n", ip, port); 00649 #endif 00650 00651 #ifdef HAVE_GETADDRINFO 00652 XMEMSET(&hints, 0, sizeof(hints)); 00653 hints.ai_family = AF_UNSPEC; 00654 hints.ai_socktype = SOCK_STREAM; 00655 hints.ai_protocol = IPPROTO_TCP; 00656 00657 if (wolfIO_Word16ToString(strPort, port) == 0) { 00658 WOLFSSL_MSG("invalid port number for responder"); 00659 return -1; 00660 } 00661 00662 if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) { 00663 WOLFSSL_MSG("no addr info for responder"); 00664 return -1; 00665 } 00666 00667 sockaddr_len = answer->ai_addrlen; 00668 XMEMCPY(&addr, answer->ai_addr, sockaddr_len); 00669 freeaddrinfo(answer); 00670 #else 00671 entry = gethostbyname(ip); 00672 sin = (SOCKADDR_IN *)&addr; 00673 00674 if (entry) { 00675 sin->sin_family = AF_INET; 00676 sin->sin_port = XHTONS(port); 00677 XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length); 00678 } 00679 else { 00680 WOLFSSL_MSG("no addr info for responder"); 00681 return -1; 00682 } 00683 #endif 00684 00685 *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0); 00686 00687 #ifdef USE_WINDOWS_API 00688 if (*sockfd == INVALID_SOCKET) { 00689 WOLFSSL_MSG("bad socket fd, out of fds?"); 00690 return -1; 00691 } 00692 #else 00693 if (*sockfd < 0) { 00694 WOLFSSL_MSG("bad socket fd, out of fds?"); 00695 return -1; 00696 } 00697 #endif 00698 00699 #ifdef HAVE_IO_TIMEOUT 00700 /* if timeout value provided then set socket non-blocking */ 00701 if (to_sec > 0) { 00702 wolfIO_SetBlockingMode(*sockfd, 1); 00703 } 00704 #else 00705 (void)to_sec; 00706 #endif 00707 00708 ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len); 00709 #ifdef HAVE_IO_TIMEOUT 00710 if (ret != 0) { 00711 if ((errno == EINPROGRESS) && (to_sec > 0)) { 00712 /* wait for connect to complete */ 00713 ret = wolfIO_Select(*sockfd, to_sec); 00714 00715 /* restore blocking mode */ 00716 wolfIO_SetBlockingMode(*sockfd, 0); 00717 } 00718 } 00719 #endif 00720 if (ret != 0) { 00721 WOLFSSL_MSG("Responder tcp connect failed"); 00722 return -1; 00723 } 00724 return ret; 00725 #else 00726 (void)sockfd; 00727 (void)ip; 00728 (void)port; 00729 (void)to_sec; 00730 return -1; 00731 #endif /* HAVE_SOCKADDR */ 00732 } 00733 00734 #ifndef HTTP_SCRATCH_BUFFER_SIZE 00735 #define HTTP_SCRATCH_BUFFER_SIZE 512 00736 #endif 00737 #ifndef MAX_URL_ITEM_SIZE 00738 #define MAX_URL_ITEM_SIZE 80 00739 #endif 00740 00741 int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath, 00742 word16* outPort) 00743 { 00744 int result = -1; 00745 00746 if (url == NULL || urlSz == 0) { 00747 if (outName) 00748 *outName = 0; 00749 if (outPath) 00750 *outPath = 0; 00751 if (outPort) 00752 *outPort = 0; 00753 } 00754 else { 00755 int i, cur; 00756 00757 /* need to break the url down into scheme, address, and port */ 00758 /* "http://example.com:8080/" */ 00759 /* "http://[::1]:443/" */ 00760 if (XSTRNCMP(url, "http://", 7) == 0) { 00761 cur = 7; 00762 } else cur = 0; 00763 00764 i = 0; 00765 if (url[cur] == '[') { 00766 cur++; 00767 /* copy until ']' */ 00768 while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) { 00769 if (outName) 00770 outName[i] = url[cur]; 00771 i++; cur++; 00772 } 00773 cur++; /* skip ']' */ 00774 } 00775 else { 00776 while (url[cur] != 0 && url[cur] != ':' && 00777 url[cur] != '/' && cur < urlSz) { 00778 if (outName) 00779 outName[i] = url[cur]; 00780 i++; cur++; 00781 } 00782 } 00783 if (outName) 00784 outName[i] = 0; 00785 /* Need to pick out the path after the domain name */ 00786 00787 if (cur < urlSz && url[cur] == ':') { 00788 char port[6]; 00789 int j; 00790 word32 bigPort = 0; 00791 i = 0; 00792 cur++; 00793 while (cur < urlSz && url[cur] != 0 && url[cur] != '/' && 00794 i < 6) { 00795 port[i++] = url[cur++]; 00796 } 00797 00798 for (j = 0; j < i; j++) { 00799 if (port[j] < '0' || port[j] > '9') return -1; 00800 bigPort = (bigPort * 10) + (port[j] - '0'); 00801 } 00802 if (outPort) 00803 *outPort = (word16)bigPort; 00804 } 00805 else if (outPort) 00806 *outPort = 80; 00807 00808 00809 if (cur < urlSz && url[cur] == '/') { 00810 i = 0; 00811 while (cur < urlSz && url[cur] != 0 && i < MAX_URL_ITEM_SIZE) { 00812 if (outPath) 00813 outPath[i] = url[cur]; 00814 i++; cur++; 00815 } 00816 if (outPath) 00817 outPath[i] = 0; 00818 } 00819 else if (outPath) { 00820 outPath[0] = '/'; 00821 outPath[1] = 0; 00822 } 00823 00824 result = 0; 00825 } 00826 00827 return result; 00828 } 00829 00830 static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, int* recvBufSz, 00831 int chunkSz, char* start, int len, int dynType, void* heap) 00832 { 00833 byte* newRecvBuf = NULL; 00834 int newRecvSz = *recvBufSz + chunkSz; 00835 int pos = 0; 00836 00837 WOLFSSL_MSG("Processing HTTP response"); 00838 #ifdef WOLFIO_DEBUG 00839 printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz); 00840 #endif 00841 00842 newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType); 00843 if (newRecvBuf == NULL) { 00844 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed"); 00845 return MEMORY_E; 00846 } 00847 00848 /* if buffer already exists, then we are growing it */ 00849 if (*recvBuf) { 00850 XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz); 00851 XFREE(*recvBuf, heap, dynType); 00852 pos += *recvBufSz; 00853 *recvBuf = NULL; 00854 } 00855 00856 /* copy the remainder of the httpBuf into the respBuf */ 00857 if (len != 0) { 00858 XMEMCPY(&newRecvBuf[pos], start, len); 00859 pos += len; 00860 } 00861 00862 /* receive the remainder of chunk */ 00863 while (len < chunkSz) { 00864 int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0); 00865 if (rxSz > 0) { 00866 len += rxSz; 00867 pos += rxSz; 00868 } 00869 else { 00870 WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed"); 00871 XFREE(newRecvBuf, heap, dynType); 00872 return -1; 00873 } 00874 } 00875 00876 *recvBuf = newRecvBuf; 00877 *recvBufSz = newRecvSz; 00878 00879 return 0; 00880 } 00881 00882 int wolfIO_HttpProcessResponse(int sfd, const char* appStr, 00883 byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap) 00884 { 00885 int result = 0; 00886 int len = 0; 00887 char *start, *end; 00888 int respBufSz = 0; 00889 int isChunked = 0, chunkSz = 0; 00890 enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type, 00891 phr_wait_end, phr_get_chunk_len, phr_get_chunk_data, 00892 phr_http_end 00893 } state = phr_init; 00894 00895 *respBuf = NULL; 00896 start = end = NULL; 00897 do { 00898 if (state == phr_get_chunk_data) { 00899 /* get chunk of data */ 00900 result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, 00901 chunkSz, start, len, dynType, heap); 00902 00903 state = (result != 0) ? phr_http_end : phr_get_chunk_len; 00904 end = NULL; 00905 len = 0; 00906 } 00907 00908 /* read data if no \r\n or first time */ 00909 if (end == NULL) { 00910 result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); 00911 if (result > 0) { 00912 len += result; 00913 start = (char*)httpBuf; 00914 start[len] = 0; 00915 } 00916 else { 00917 WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed"); 00918 return -1; 00919 } 00920 } 00921 end = XSTRSTR(start, "\r\n"); /* locate end */ 00922 00923 /* handle incomplete rx */ 00924 if (end == NULL) { 00925 if (len != 0) 00926 XMEMMOVE(httpBuf, start, len); 00927 start = end = NULL; 00928 } 00929 /* when start is "\r\n" */ 00930 else if (end == start) { 00931 /* if waiting for end or need chunk len */ 00932 if (state == phr_wait_end || state == phr_get_chunk_len) { 00933 state = (isChunked) ? phr_get_chunk_len : phr_http_end; 00934 len -= 2; start += 2; /* skip \r\n */ 00935 } 00936 else { 00937 WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early"); 00938 return -1; 00939 } 00940 } 00941 else { 00942 *end = 0; /* null terminate */ 00943 len -= (int)(end - start) + 2; 00944 /* adjust len to remove the first line including the /r/n */ 00945 00946 #ifdef WOLFIO_DEBUG 00947 printf("HTTP Resp: %s\n", start); 00948 #endif 00949 00950 switch (state) { 00951 case phr_init: 00952 if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { 00953 start += 9; 00954 if (XSTRNCASECMP(start, "200 OK", 6) != 0) { 00955 WOLFSSL_MSG("wolfIO_HttpProcessResponse not OK"); 00956 return -1; 00957 } 00958 state = phr_http_start; 00959 } 00960 break; 00961 case phr_http_start: 00962 case phr_have_length: 00963 case phr_have_type: 00964 if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { 00965 start += 13; 00966 while (*start == ' ' && *start != '\0') start++; 00967 if (XSTRNCASECMP(start, appStr, XSTRLEN(appStr)) != 0) { 00968 WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch"); 00969 return -1; 00970 } 00971 state = (state == phr_http_start) ? phr_have_type : phr_wait_end; 00972 } 00973 else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { 00974 start += 15; 00975 while (*start == ' ' && *start != '\0') start++; 00976 chunkSz = atoi(start); 00977 state = (state == phr_http_start) ? phr_have_length : phr_wait_end; 00978 } 00979 else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) { 00980 start += 18; 00981 while (*start == ' ' && *start != '\0') start++; 00982 if (XSTRNCASECMP(start, "chunked", 7) == 0) { 00983 isChunked = 1; 00984 state = (state == phr_http_start) ? phr_have_length : phr_wait_end; 00985 } 00986 } 00987 break; 00988 case phr_get_chunk_len: 00989 chunkSz = (int)strtol(start, NULL, 16); /* hex format */ 00990 state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data; 00991 break; 00992 case phr_get_chunk_data: 00993 /* processing for chunk data done above, since \r\n isn't required */ 00994 case phr_wait_end: 00995 case phr_http_end: 00996 /* do nothing */ 00997 break; 00998 } /* switch (state) */ 00999 01000 /* skip to end plus \r\n */ 01001 start = end + 2; 01002 } 01003 } while (state != phr_http_end); 01004 01005 if (!isChunked) { 01006 result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz, 01007 start, len, dynType, heap); 01008 } 01009 01010 if (result >= 0) { 01011 result = respBufSz; 01012 } 01013 else { 01014 WOLFSSL_ERROR(result); 01015 } 01016 01017 return result; 01018 } 01019 01020 int wolfIO_HttpBuildRequest(const char* reqType, const char* domainName, 01021 const char* path, int pathLen, int reqSz, const char* contentType, 01022 byte* buf, int bufSize) 01023 { 01024 word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, maxLen; 01025 char reqSzStr[6]; 01026 char* req = (char*)buf; 01027 const char* blankStr = " "; 01028 const char* http11Str = " HTTP/1.1"; 01029 const char* hostStr = "\r\nHost: "; 01030 const char* contentLenStr = "\r\nContent-Length: "; 01031 const char* contentTypeStr = "\r\nContent-Type: "; 01032 const char* doubleCrLfStr = "\r\n\r\n"; 01033 word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen, 01034 contentTypeStrLen, doubleCrLfStrLen; 01035 01036 reqTypeLen = (word32)XSTRLEN(reqType); 01037 domainNameLen = (word32)XSTRLEN(domainName); 01038 reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz); 01039 contentTypeLen = (word32)XSTRLEN(contentType); 01040 01041 blankStrLen = (word32)XSTRLEN(blankStr); 01042 http11StrLen = (word32)XSTRLEN(http11Str); 01043 hostStrLen = (word32)XSTRLEN(hostStr); 01044 contentLenStrLen = (word32)XSTRLEN(contentLenStr); 01045 contentTypeStrLen = (word32)XSTRLEN(contentTypeStr); 01046 doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr); 01047 01048 /* determine max length and check it */ 01049 maxLen = 01050 reqTypeLen + 01051 blankStrLen + 01052 pathLen + 01053 http11StrLen + 01054 hostStrLen + 01055 domainNameLen + 01056 contentLenStrLen + 01057 reqSzStrLen + 01058 contentTypeStrLen + 01059 contentTypeLen + 01060 doubleCrLfStrLen + 01061 1 /* null term */; 01062 if (maxLen > (word32)bufSize) 01063 return 0; 01064 01065 XSTRNCPY((char*)buf, reqType, reqTypeLen); 01066 buf += reqTypeLen; 01067 XSTRNCPY((char*)buf, blankStr, blankStrLen+1); 01068 buf += blankStrLen; 01069 XSTRNCPY((char*)buf, path, pathLen); 01070 buf += pathLen; 01071 XSTRNCPY((char*)buf, http11Str, http11StrLen+1); 01072 buf += http11StrLen; 01073 if (domainNameLen > 0) { 01074 XSTRNCPY((char*)buf, hostStr, hostStrLen+1); 01075 buf += hostStrLen; 01076 XSTRNCPY((char*)buf, domainName, domainNameLen); 01077 buf += domainNameLen; 01078 } 01079 if (reqSz > 0 && reqSzStrLen > 0) { 01080 XSTRNCPY((char*)buf, contentLenStr, contentLenStrLen+1); 01081 buf += contentLenStrLen; 01082 XSTRNCPY((char*)buf, reqSzStr, reqSzStrLen); 01083 buf += reqSzStrLen; 01084 } 01085 if (contentTypeLen > 0) { 01086 XSTRNCPY((char*)buf, contentTypeStr, contentTypeStrLen+1); 01087 buf += contentTypeStrLen; 01088 XSTRNCPY((char*)buf, contentType, contentTypeLen); 01089 buf += contentTypeLen; 01090 } 01091 XSTRNCPY((char*)buf, doubleCrLfStr, doubleCrLfStrLen+1); 01092 buf += doubleCrLfStrLen; 01093 01094 #ifdef WOLFIO_DEBUG 01095 printf("HTTP %s: %s", reqType, req); 01096 #endif 01097 01098 /* calculate actual length based on original and new pointer */ 01099 return (int)((char*)buf - req); 01100 } 01101 01102 01103 #ifdef HAVE_OCSP 01104 01105 int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path, 01106 int ocspReqSz, byte* buf, int bufSize) 01107 { 01108 return wolfIO_HttpBuildRequest("POST", domainName, path, (int)XSTRLEN(path), 01109 ocspReqSz, "application/ocsp-request", buf, bufSize); 01110 } 01111 01112 /* return: >0 OCSP Response Size 01113 * -1 error */ 01114 int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf, 01115 byte* httpBuf, int httpBufSz, void* heap) 01116 { 01117 return wolfIO_HttpProcessResponse(sfd, "application/ocsp-response", 01118 respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap); 01119 } 01120 01121 /* in default wolfSSL callback ctx is the heap pointer */ 01122 int EmbedOcspLookup(void* ctx, const char* url, int urlSz, 01123 byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf) 01124 { 01125 SOCKET_T sfd = 0; 01126 word16 port; 01127 int ret = -1; 01128 #ifdef WOLFSSL_SMALL_STACK 01129 char* path; 01130 char* domainName; 01131 #else 01132 char path[MAX_URL_ITEM_SIZE]; 01133 char domainName[MAX_URL_ITEM_SIZE]; 01134 #endif 01135 01136 #ifdef WOLFSSL_SMALL_STACK 01137 path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01138 if (path == NULL) 01139 return MEMORY_E; 01140 01141 domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01142 if (domainName == NULL) { 01143 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01144 return MEMORY_E; 01145 } 01146 #endif 01147 01148 if (ocspReqBuf == NULL || ocspReqSz == 0) { 01149 WOLFSSL_MSG("OCSP request is required for lookup"); 01150 } 01151 else if (ocspRespBuf == NULL) { 01152 WOLFSSL_MSG("Cannot save OCSP response"); 01153 } 01154 else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) { 01155 WOLFSSL_MSG("Unable to decode OCSP URL"); 01156 } 01157 else { 01158 /* Note, the library uses the EmbedOcspRespFree() callback to 01159 * free this buffer. */ 01160 int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE; 01161 byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP); 01162 01163 if (httpBuf == NULL) { 01164 WOLFSSL_MSG("Unable to create OCSP response buffer"); 01165 } 01166 else { 01167 httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz, 01168 httpBuf, httpBufSz); 01169 01170 ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); 01171 if ((ret != 0) || (sfd <= 0)) { 01172 WOLFSSL_MSG("OCSP Responder connection failed"); 01173 } 01174 else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) != 01175 httpBufSz) { 01176 WOLFSSL_MSG("OCSP http request failed"); 01177 } 01178 else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) != 01179 ocspReqSz) { 01180 WOLFSSL_MSG("OCSP ocsp request failed"); 01181 } 01182 else { 01183 ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf, 01184 HTTP_SCRATCH_BUFFER_SIZE, ctx); 01185 } 01186 01187 close(sfd); 01188 XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP); 01189 } 01190 } 01191 01192 #ifdef WOLFSSL_SMALL_STACK 01193 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01194 XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER); 01195 #endif 01196 01197 return ret; 01198 } 01199 01200 /* in default callback ctx is heap hint */ 01201 void EmbedOcspRespFree(void* ctx, byte *resp) 01202 { 01203 if (resp) 01204 XFREE(resp, ctx, DYNAMIC_TYPE_OCSP); 01205 01206 (void)ctx; 01207 } 01208 #endif /* HAVE_OCSP */ 01209 01210 01211 #if defined(HAVE_CRL) && defined(HAVE_CRL_IO) 01212 01213 int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz, 01214 const char* domainName, byte* buf, int bufSize) 01215 { 01216 return wolfIO_HttpBuildRequest("GET", domainName, url, urlSz, 0, "", 01217 buf, bufSize); 01218 } 01219 01220 int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf, 01221 int httpBufSz) 01222 { 01223 int result; 01224 byte *respBuf = NULL; 01225 01226 result = wolfIO_HttpProcessResponse(sfd, "application/pkix-crl", 01227 &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap); 01228 if (result >= 0) { 01229 result = BufferLoadCRL(crl, respBuf, result, SSL_FILETYPE_ASN1); 01230 } 01231 XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL); 01232 01233 return result; 01234 } 01235 01236 int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz) 01237 { 01238 SOCKET_T sfd = 0; 01239 word16 port; 01240 int ret = -1; 01241 #ifdef WOLFSSL_SMALL_STACK 01242 char* domainName; 01243 #else 01244 char domainName[MAX_URL_ITEM_SIZE]; 01245 #endif 01246 01247 #ifdef WOLFSSL_SMALL_STACK 01248 domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap, 01249 DYNAMIC_TYPE_TMP_BUFFER); 01250 if (domainName == NULL) { 01251 return MEMORY_E; 01252 } 01253 #endif 01254 01255 if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) { 01256 WOLFSSL_MSG("Unable to decode CRL URL"); 01257 } 01258 else { 01259 int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE; 01260 byte* httpBuf = (byte*)XMALLOC(httpBufSz, crl->heap, 01261 DYNAMIC_TYPE_CRL); 01262 if (httpBuf == NULL) { 01263 WOLFSSL_MSG("Unable to create CRL response buffer"); 01264 } 01265 else { 01266 httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName, 01267 httpBuf, httpBufSz); 01268 01269 ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); 01270 if ((ret != 0) || (sfd <= 0)) { 01271 WOLFSSL_MSG("CRL connection failed"); 01272 } 01273 else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) 01274 != httpBufSz) { 01275 WOLFSSL_MSG("CRL http get failed"); 01276 } 01277 else { 01278 ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf, 01279 HTTP_SCRATCH_BUFFER_SIZE); 01280 } 01281 01282 close(sfd); 01283 XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL); 01284 } 01285 } 01286 01287 #ifdef WOLFSSL_SMALL_STACK 01288 XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER); 01289 #endif 01290 01291 return ret; 01292 } 01293 #endif /* HAVE_CRL && HAVE_CRL_IO */ 01294 01295 #endif /* HAVE_HTTP_CLIENT */ 01296 01297 01298 01299 WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv) 01300 { 01301 ctx->CBIORecv = CBIORecv; 01302 } 01303 01304 01305 WOLFSSL_API void wolfSSL_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend) 01306 { 01307 ctx->CBIOSend = CBIOSend; 01308 } 01309 01310 01311 WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx) 01312 { 01313 ssl->IOCB_ReadCtx = rctx; 01314 } 01315 01316 01317 WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx) 01318 { 01319 ssl->IOCB_WriteCtx = wctx; 01320 } 01321 01322 01323 WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl) 01324 { 01325 if (ssl) 01326 return ssl->IOCB_ReadCtx; 01327 01328 return NULL; 01329 } 01330 01331 01332 WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl) 01333 { 01334 if (ssl) 01335 return ssl->IOCB_WriteCtx; 01336 01337 return NULL; 01338 } 01339 01340 01341 WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags) 01342 { 01343 ssl->rflags = flags; 01344 } 01345 01346 01347 WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags) 01348 { 01349 ssl->wflags = flags; 01350 } 01351 01352 01353 #ifdef WOLFSSL_DTLS 01354 01355 WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb) 01356 { 01357 ctx->CBIOCookie = cb; 01358 } 01359 01360 01361 WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx) 01362 { 01363 ssl->IOCB_CookieCtx = ctx; 01364 } 01365 01366 01367 WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl) 01368 { 01369 if (ssl) 01370 return ssl->IOCB_CookieCtx; 01371 01372 return NULL; 01373 } 01374 01375 #ifdef WOLFSSL_SESSION_EXPORT 01376 01377 WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb) 01378 { 01379 ctx->CBGetPeer = cb; 01380 } 01381 01382 01383 WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb) 01384 { 01385 ctx->CBSetPeer = cb; 01386 } 01387 01388 #endif /* WOLFSSL_SESSION_EXPORT */ 01389 #endif /* WOLFSSL_DTLS */ 01390 01391 01392 #ifdef HAVE_NETX 01393 01394 /* The NetX receive callback 01395 * return : bytes read, or error 01396 */ 01397 int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx) 01398 { 01399 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx; 01400 ULONG left; 01401 ULONG total; 01402 ULONG copied = 0; 01403 UINT status; 01404 01405 if (nxCtx == NULL || nxCtx->nxSocket == NULL) { 01406 WOLFSSL_MSG("NetX Recv NULL parameters"); 01407 return WOLFSSL_CBIO_ERR_GENERAL; 01408 } 01409 01410 if (nxCtx->nxPacket == NULL) { 01411 status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket, 01412 nxCtx->nxWait); 01413 if (status != NX_SUCCESS) { 01414 WOLFSSL_MSG("NetX Recv receive error"); 01415 return WOLFSSL_CBIO_ERR_GENERAL; 01416 } 01417 } 01418 01419 if (nxCtx->nxPacket) { 01420 status = nx_packet_length_get(nxCtx->nxPacket, &total); 01421 if (status != NX_SUCCESS) { 01422 WOLFSSL_MSG("NetX Recv length get error"); 01423 return WOLFSSL_CBIO_ERR_GENERAL; 01424 } 01425 01426 left = total - nxCtx->nxOffset; 01427 status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset, 01428 buf, sz, &copied); 01429 if (status != NX_SUCCESS) { 01430 WOLFSSL_MSG("NetX Recv data extract offset error"); 01431 return WOLFSSL_CBIO_ERR_GENERAL; 01432 } 01433 01434 nxCtx->nxOffset += copied; 01435 01436 if (copied == left) { 01437 WOLFSSL_MSG("NetX Recv Drained packet"); 01438 nx_packet_release(nxCtx->nxPacket); 01439 nxCtx->nxPacket = NULL; 01440 nxCtx->nxOffset = 0; 01441 } 01442 } 01443 01444 return copied; 01445 } 01446 01447 01448 /* The NetX send callback 01449 * return : bytes sent, or error 01450 */ 01451 int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx) 01452 { 01453 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx; 01454 NX_PACKET* packet; 01455 NX_PACKET_POOL* pool; /* shorthand */ 01456 UINT status; 01457 01458 if (nxCtx == NULL || nxCtx->nxSocket == NULL) { 01459 WOLFSSL_MSG("NetX Send NULL parameters"); 01460 return WOLFSSL_CBIO_ERR_GENERAL; 01461 } 01462 01463 pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool; 01464 status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET, 01465 nxCtx->nxWait); 01466 if (status != NX_SUCCESS) { 01467 WOLFSSL_MSG("NetX Send packet alloc error"); 01468 return WOLFSSL_CBIO_ERR_GENERAL; 01469 } 01470 01471 status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait); 01472 if (status != NX_SUCCESS) { 01473 nx_packet_release(packet); 01474 WOLFSSL_MSG("NetX Send data append error"); 01475 return WOLFSSL_CBIO_ERR_GENERAL; 01476 } 01477 01478 status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait); 01479 if (status != NX_SUCCESS) { 01480 nx_packet_release(packet); 01481 WOLFSSL_MSG("NetX Send socket send error"); 01482 return WOLFSSL_CBIO_ERR_GENERAL; 01483 } 01484 01485 return sz; 01486 } 01487 01488 01489 /* like set_fd, but for default NetX context */ 01490 void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption) 01491 { 01492 if (ssl) { 01493 ssl->nxCtx.nxSocket = nxSocket; 01494 ssl->nxCtx.nxWait = waitOption; 01495 } 01496 } 01497 01498 #endif /* HAVE_NETX */ 01499 01500 #endif /* WOLFCRYPT_ONLY */ 01501
Generated on Tue Jul 12 2022 23:30:58 by
1.7.2
