wolf SSL / wolfSSL-TLS13-Beta

Fork of wolfSSL by wolf SSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers io.c Source File

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