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.
Dependents: HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL
io.c
00001 /* io.c 00002 * 00003 * Copyright (C) 2006-2014 wolfSSL Inc. 00004 * 00005 * This file is part of CyaSSL. 00006 * 00007 * CyaSSL 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 * CyaSSL 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-1301, USA 00020 */ 00021 00022 #ifdef HAVE_CONFIG_H 00023 #include <config.h> 00024 #endif 00025 00026 #include <cyassl/ctaocrypt/settings.h> 00027 00028 #ifdef _WIN32_WCE 00029 /* On WinCE winsock2.h must be included before windows.h for socket stuff */ 00030 #include <winsock2.h> 00031 #endif 00032 00033 #include <cyassl/internal.h> 00034 #include <cyassl/error-ssl.h> 00035 00036 /* if user writes own I/O callbacks they can define CYASSL_USER_IO to remove 00037 automatic setting of default I/O functions EmbedSend() and EmbedReceive() 00038 but they'll still need SetCallback xxx() at end of file 00039 */ 00040 #ifndef CYASSL_USER_IO 00041 00042 #ifdef HAVE_LIBZ 00043 #include "zlib.h" 00044 #endif 00045 00046 #ifndef USE_WINDOWS_API 00047 #ifdef CYASSL_LWIP 00048 /* lwIP needs to be configured to use sockets API in this mode */ 00049 /* LWIP_SOCKET 1 in lwip/opt.h or in build */ 00050 #include "lwip/sockets.h" 00051 #include <errno.h> 00052 #ifndef LWIP_PROVIDE_ERRNO 00053 #define LWIP_PROVIDE_ERRNO 1 00054 #endif 00055 #elif defined(FREESCALE_MQX) 00056 #include <posix.h> 00057 #include <rtcs.h> 00058 #elif defined(CYASSL_MDK_ARM) 00059 #if defined(CYASSL_MDK5) 00060 #include "cmsis_os.h" 00061 #include "rl_fs.h" 00062 #include "rl_net.h" 00063 #else 00064 #include <rtl.h> 00065 #endif 00066 #undef RNG 00067 #include "CYASSL_MDK_ARM.h" 00068 #undef RNG 00069 #define RNG CyaSSL_RNG 00070 /* for avoiding name conflict in "stm32f2xx.h" */ 00071 static int errno; 00072 #elif defined(CYASSL_TIRTOS) 00073 #include <sys/socket.h> 00074 #elif defined(CYASSL_IAR_ARM) 00075 /* nothing */ 00076 #else 00077 #include <sys/types.h> 00078 #include <errno.h> 00079 #ifndef EBSNET 00080 #include <unistd.h> 00081 #endif 00082 #include <fcntl.h> 00083 #if !(defined(DEVKITPRO) || defined(HAVE_RTP_SYS) || defined(EBSNET)) \ 00084 || defined(CYASSL_PICOTCP) 00085 #include <sys/socket.h> 00086 #include <arpa/inet.h> 00087 #include <netinet/in.h> 00088 #include <netdb.h> 00089 #ifdef __PPU 00090 #include <netex/errno.h> 00091 #else 00092 #include <sys/ioctl.h> 00093 #endif 00094 #endif 00095 #ifdef HAVE_RTP_SYS 00096 #include <socket.h> 00097 #endif 00098 #ifdef EBSNET 00099 #include "rtipapi.h" /* errno */ 00100 #include "socket.h" 00101 #endif 00102 #endif 00103 #endif /* USE_WINDOWS_API */ 00104 00105 #ifdef __sun 00106 #include <sys/filio.h> 00107 #endif 00108 00109 #ifdef USE_WINDOWS_API 00110 /* no epipe yet */ 00111 #ifndef WSAEPIPE 00112 #define WSAEPIPE -12345 00113 #endif 00114 #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK 00115 #define SOCKET_EAGAIN WSAETIMEDOUT 00116 #define SOCKET_ECONNRESET WSAECONNRESET 00117 #define SOCKET_EINTR WSAEINTR 00118 #define SOCKET_EPIPE WSAEPIPE 00119 #define SOCKET_ECONNREFUSED WSAENOTCONN 00120 #define SOCKET_ECONNABORTED WSAECONNABORTED 00121 #define close(s) closesocket(s) 00122 #elif defined(__PPU) 00123 #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK 00124 #define SOCKET_EAGAIN SYS_NET_EAGAIN 00125 #define SOCKET_ECONNRESET SYS_NET_ECONNRESET 00126 #define SOCKET_EINTR SYS_NET_EINTR 00127 #define SOCKET_EPIPE SYS_NET_EPIPE 00128 #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED 00129 #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED 00130 #elif defined(FREESCALE_MQX) 00131 /* RTCS doesn't have an EWOULDBLOCK error */ 00132 #define SOCKET_EWOULDBLOCK EAGAIN 00133 #define SOCKET_EAGAIN EAGAIN 00134 #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET 00135 #define SOCKET_EINTR EINTR 00136 #define SOCKET_EPIPE EPIPE 00137 #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED 00138 #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED 00139 #elif defined(CYASSL_MDK_ARM) 00140 #if defined(CYASSL_MDK5) 00141 #define SOCKET_EWOULDBLOCK BSD_ERROR_WOULDBLOCK 00142 #define SOCKET_EAGAIN BSD_ERROR_LOCKED 00143 #define SOCKET_ECONNRESET BSD_ERROR_CLOSED 00144 #define SOCKET_EINTR BSD_ERROR 00145 #define SOCKET_EPIPE BSD_ERROR 00146 #define SOCKET_ECONNREFUSED BSD_ERROR 00147 #define SOCKET_ECONNABORTED BSD_ERROR 00148 #else 00149 #define SOCKET_EWOULDBLOCK SCK_EWOULDBLOCK 00150 #define SOCKET_EAGAIN SCK_ELOCKED 00151 #define SOCKET_ECONNRESET SCK_ECLOSED 00152 #define SOCKET_EINTR SCK_ERROR 00153 #define SOCKET_EPIPE SCK_ERROR 00154 #define SOCKET_ECONNREFUSED SCK_ERROR 00155 #define SOCKET_ECONNABORTED SCK_ERROR 00156 #endif 00157 #elif defined(CYASSL_PICOTCP) 00158 #define SOCKET_EWOULDBLOCK PICO_ERR_EAGAIN 00159 #define SOCKET_EAGAIN PICO_ERR_EAGAIN 00160 #define SOCKET_ECONNRESET PICO_ERR_ECONNRESET 00161 #define SOCKET_EINTR PICO_ERR_EINTR 00162 #define SOCKET_EPIPE PICO_ERR_EIO 00163 #define SOCKET_ECONNREFUSED PICO_ERR_ECONNREFUSED 00164 #define SOCKET_ECONNABORTED PICO_ERR_ESHUTDOWN 00165 #else 00166 #define SOCKET_EWOULDBLOCK EWOULDBLOCK 00167 #define SOCKET_EAGAIN EAGAIN 00168 #define SOCKET_ECONNRESET ECONNRESET 00169 #define SOCKET_EINTR EINTR 00170 #define SOCKET_EPIPE EPIPE 00171 #define SOCKET_ECONNREFUSED ECONNREFUSED 00172 #define SOCKET_ECONNABORTED ECONNABORTED 00173 #endif /* USE_WINDOWS_API */ 00174 00175 00176 #ifdef DEVKITPRO 00177 /* from network.h */ 00178 int net_send(int, const void*, int, unsigned int); 00179 int net_recv(int, void*, int, unsigned int); 00180 #define SEND_FUNCTION net_send 00181 #define RECV_FUNCTION net_recv 00182 #elif defined(CYASSL_LWIP) 00183 #define SEND_FUNCTION lwip_send 00184 #define RECV_FUNCTION lwip_recv 00185 #elif defined(CYASSL_PICOTCP) 00186 #define SEND_FUNCTION pico_send 00187 #define RECV_FUNCTION pico_recv 00188 #else 00189 #define SEND_FUNCTION send 00190 #define RECV_FUNCTION recv 00191 #endif 00192 00193 00194 /* Translates return codes returned from 00195 * send() and recv() if need be. 00196 */ 00197 static INLINE int TranslateReturnCode(int old, int sd) 00198 { 00199 (void)sd; 00200 00201 #ifdef FREESCALE_MQX 00202 if (old == 0) { 00203 errno = SOCKET_EWOULDBLOCK; 00204 return -1; /* convert to BSD style wouldblock as error */ 00205 } 00206 00207 if (old < 0) { 00208 errno = RTCS_geterror(sd); 00209 if (errno == RTCSERR_TCP_CONN_CLOSING) 00210 return 0; /* convert to BSD style closing */ 00211 } 00212 #endif 00213 00214 return old; 00215 } 00216 00217 static INLINE int LastError(void) 00218 { 00219 #ifdef USE_WINDOWS_API 00220 return WSAGetLastError(); 00221 #elif defined(EBSNET) 00222 return xn_getlasterror(); 00223 #else 00224 return errno; 00225 #endif 00226 } 00227 00228 /* The receive embedded callback 00229 * return : nb bytes read, or error 00230 */ 00231 int EmbedReceive(CYASSL *ssl, char *buf, int sz, void *ctx) 00232 { 00233 int recvd; 00234 int err; 00235 int sd = *(int*)ctx; 00236 00237 #ifdef CYASSL_DTLS 00238 { 00239 int dtls_timeout = CyaSSL_dtls_get_current_timeout(ssl); 00240 if (CyaSSL_dtls(ssl) 00241 && !CyaSSL_get_using_nonblock(ssl) 00242 && dtls_timeout != 0) { 00243 #ifdef USE_WINDOWS_API 00244 DWORD timeout = dtls_timeout * 1000; 00245 #else 00246 struct timeval timeout; 00247 XMEMSET(&timeout, 0, sizeof(timeout)); 00248 timeout.tv_sec = dtls_timeout; 00249 #endif 00250 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, 00251 sizeof(timeout)) != 0) { 00252 CYASSL_MSG("setsockopt rcvtimeo failed"); 00253 } 00254 } 00255 } 00256 #endif 00257 00258 recvd = (int)RECV_FUNCTION(sd, buf, sz, ssl->rflags); 00259 00260 recvd = TranslateReturnCode(recvd, sd); 00261 00262 if (recvd < 0) { 00263 err = LastError(); 00264 CYASSL_MSG("Embed Receive error"); 00265 00266 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { 00267 if (!CyaSSL_dtls(ssl) || CyaSSL_get_using_nonblock(ssl)) { 00268 CYASSL_MSG(" Would block"); 00269 return CYASSL_CBIO_ERR_WANT_READ; 00270 } 00271 else { 00272 CYASSL_MSG(" Socket timeout"); 00273 return CYASSL_CBIO_ERR_TIMEOUT; 00274 } 00275 } 00276 else if (err == SOCKET_ECONNRESET) { 00277 CYASSL_MSG(" Connection reset"); 00278 return CYASSL_CBIO_ERR_CONN_RST; 00279 } 00280 else if (err == SOCKET_EINTR) { 00281 CYASSL_MSG(" Socket interrupted"); 00282 return CYASSL_CBIO_ERR_ISR; 00283 } 00284 else if (err == SOCKET_ECONNREFUSED) { 00285 CYASSL_MSG(" Connection refused"); 00286 return CYASSL_CBIO_ERR_WANT_READ; 00287 } 00288 else if (err == SOCKET_ECONNABORTED) { 00289 CYASSL_MSG(" Connection aborted"); 00290 return CYASSL_CBIO_ERR_CONN_CLOSE; 00291 } 00292 else { 00293 CYASSL_MSG(" General error"); 00294 return CYASSL_CBIO_ERR_GENERAL; 00295 } 00296 } 00297 else if (recvd == 0) { 00298 CYASSL_MSG("Embed receive connection closed"); 00299 return CYASSL_CBIO_ERR_CONN_CLOSE; 00300 } 00301 00302 return recvd; 00303 } 00304 00305 /* The send embedded callback 00306 * return : nb bytes sent, or error 00307 */ 00308 int EmbedSend(CYASSL* ssl, char *buf, int sz, void *ctx) 00309 { 00310 int sd = *(int*)ctx; 00311 int sent; 00312 int len = sz; 00313 int err; 00314 00315 sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, ssl->wflags); 00316 00317 if (sent < 0) { 00318 err = LastError(); 00319 CYASSL_MSG("Embed Send error"); 00320 00321 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { 00322 CYASSL_MSG(" Would Block"); 00323 return CYASSL_CBIO_ERR_WANT_WRITE; 00324 } 00325 else if (err == SOCKET_ECONNRESET) { 00326 CYASSL_MSG(" Connection reset"); 00327 return CYASSL_CBIO_ERR_CONN_RST; 00328 } 00329 else if (err == SOCKET_EINTR) { 00330 CYASSL_MSG(" Socket interrupted"); 00331 return CYASSL_CBIO_ERR_ISR; 00332 } 00333 else if (err == SOCKET_EPIPE) { 00334 CYASSL_MSG(" Socket EPIPE"); 00335 return CYASSL_CBIO_ERR_CONN_CLOSE; 00336 } 00337 else { 00338 CYASSL_MSG(" General error"); 00339 return CYASSL_CBIO_ERR_GENERAL; 00340 } 00341 } 00342 00343 return sent; 00344 } 00345 00346 00347 #ifdef CYASSL_DTLS 00348 00349 #include <cyassl/ctaocrypt/sha.h> 00350 00351 #ifdef USE_WINDOWS_API 00352 #define XSOCKLENT int 00353 #else 00354 #define XSOCKLENT socklen_t 00355 #endif 00356 00357 #define SENDTO_FUNCTION sendto 00358 #define RECVFROM_FUNCTION recvfrom 00359 00360 00361 /* The receive embedded callback 00362 * return : nb bytes read, or error 00363 */ 00364 int EmbedReceiveFrom(CYASSL *ssl, char *buf, int sz, void *ctx) 00365 { 00366 CYASSL_DTLS_CTX* dtlsCtx = (CYASSL_DTLS_CTX*)ctx; 00367 int recvd; 00368 int err; 00369 int sd = dtlsCtx->fd; 00370 int dtls_timeout = CyaSSL_dtls_get_current_timeout(ssl); 00371 struct sockaddr_storage peer; 00372 XSOCKLENT peerSz = sizeof(peer); 00373 00374 CYASSL_ENTER("EmbedReceiveFrom()"); 00375 00376 if (!CyaSSL_get_using_nonblock(ssl) && dtls_timeout != 0) { 00377 #ifdef USE_WINDOWS_API 00378 DWORD timeout = dtls_timeout * 1000; 00379 #else 00380 struct timeval timeout; 00381 XMEMSET(&timeout, 0, sizeof(timeout)); 00382 timeout.tv_sec = dtls_timeout; 00383 #endif 00384 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, 00385 sizeof(timeout)) != 0) { 00386 CYASSL_MSG("setsockopt rcvtimeo failed"); 00387 } 00388 } 00389 00390 recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, 00391 (struct sockaddr*)&peer, &peerSz); 00392 00393 recvd = TranslateReturnCode(recvd, sd); 00394 00395 if (recvd < 0) { 00396 err = LastError(); 00397 CYASSL_MSG("Embed Receive From error"); 00398 00399 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { 00400 if (CyaSSL_get_using_nonblock(ssl)) { 00401 CYASSL_MSG(" Would block"); 00402 return CYASSL_CBIO_ERR_WANT_READ; 00403 } 00404 else { 00405 CYASSL_MSG(" Socket timeout"); 00406 return CYASSL_CBIO_ERR_TIMEOUT; 00407 } 00408 } 00409 else if (err == SOCKET_ECONNRESET) { 00410 CYASSL_MSG(" Connection reset"); 00411 return CYASSL_CBIO_ERR_CONN_RST; 00412 } 00413 else if (err == SOCKET_EINTR) { 00414 CYASSL_MSG(" Socket interrupted"); 00415 return CYASSL_CBIO_ERR_ISR; 00416 } 00417 else if (err == SOCKET_ECONNREFUSED) { 00418 CYASSL_MSG(" Connection refused"); 00419 return CYASSL_CBIO_ERR_WANT_READ; 00420 } 00421 else { 00422 CYASSL_MSG(" General error"); 00423 return CYASSL_CBIO_ERR_GENERAL; 00424 } 00425 } 00426 else { 00427 if (dtlsCtx->peer.sz > 0 00428 && peerSz != (XSOCKLENT)dtlsCtx->peer.sz 00429 && memcmp(&peer, dtlsCtx->peer.sa, peerSz) != 0) { 00430 CYASSL_MSG(" Ignored packet from invalid peer"); 00431 return CYASSL_CBIO_ERR_WANT_READ; 00432 } 00433 } 00434 00435 return recvd; 00436 } 00437 00438 00439 /* The send embedded callback 00440 * return : nb bytes sent, or error 00441 */ 00442 int EmbedSendTo(CYASSL* ssl, char *buf, int sz, void *ctx) 00443 { 00444 CYASSL_DTLS_CTX* dtlsCtx = (CYASSL_DTLS_CTX*)ctx; 00445 int sd = dtlsCtx->fd; 00446 int sent; 00447 int len = sz; 00448 int err; 00449 00450 CYASSL_ENTER("EmbedSendTo()"); 00451 00452 sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags, 00453 (const struct sockaddr*)dtlsCtx->peer.sa, 00454 dtlsCtx->peer.sz); 00455 if (sent < 0) { 00456 err = LastError(); 00457 CYASSL_MSG("Embed Send To error"); 00458 00459 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { 00460 CYASSL_MSG(" Would Block"); 00461 return CYASSL_CBIO_ERR_WANT_WRITE; 00462 } 00463 else if (err == SOCKET_ECONNRESET) { 00464 CYASSL_MSG(" Connection reset"); 00465 return CYASSL_CBIO_ERR_CONN_RST; 00466 } 00467 else if (err == SOCKET_EINTR) { 00468 CYASSL_MSG(" Socket interrupted"); 00469 return CYASSL_CBIO_ERR_ISR; 00470 } 00471 else if (err == SOCKET_EPIPE) { 00472 CYASSL_MSG(" Socket EPIPE"); 00473 return CYASSL_CBIO_ERR_CONN_CLOSE; 00474 } 00475 else { 00476 CYASSL_MSG(" General error"); 00477 return CYASSL_CBIO_ERR_GENERAL; 00478 } 00479 } 00480 00481 return sent; 00482 } 00483 00484 00485 /* The DTLS Generate Cookie callback 00486 * return : number of bytes copied into buf, or error 00487 */ 00488 int EmbedGenerateCookie(CYASSL* ssl, byte *buf, int sz, void *ctx) 00489 { 00490 int sd = ssl->wfd; 00491 struct sockaddr_storage peer; 00492 XSOCKLENT peerSz = sizeof(peer); 00493 byte digest[SHA_DIGEST_SIZE]; 00494 int ret = 0; 00495 00496 (void)ctx; 00497 00498 XMEMSET(&peer, 0, sizeof(peer)); 00499 if (getpeername(sd, (struct sockaddr*)&peer, &peerSz) != 0) { 00500 CYASSL_MSG("getpeername failed in EmbedGenerateCookie"); 00501 return GEN_COOKIE_E; 00502 } 00503 00504 ret = ShaHash((byte*)&peer, peerSz, digest); 00505 if (ret != 0) 00506 return ret; 00507 00508 if (sz > SHA_DIGEST_SIZE) 00509 sz = SHA_DIGEST_SIZE; 00510 XMEMCPY(buf, digest, sz); 00511 00512 return sz; 00513 } 00514 00515 #endif /* CYASSL_DTLS */ 00516 00517 #ifdef HAVE_OCSP 00518 00519 00520 static int Word16ToString(char* d, word16 number) 00521 { 00522 int i = 0; 00523 00524 if (d != NULL) { 00525 word16 order = 10000; 00526 word16 digit; 00527 00528 if (number == 0) { 00529 d[i++] = '0'; 00530 } 00531 else { 00532 while (order) { 00533 digit = number / order; 00534 if (i > 0 || digit != 0) { 00535 d[i++] = (char)digit + '0'; 00536 } 00537 if (digit != 0) 00538 number %= digit * order; 00539 if (order > 1) 00540 order /= 10; 00541 else 00542 order = 0; 00543 } 00544 } 00545 d[i] = 0; 00546 } 00547 00548 return i; 00549 } 00550 00551 00552 static int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port) 00553 { 00554 struct sockaddr_storage addr; 00555 int sockaddr_len = sizeof(struct sockaddr_in); 00556 XMEMSET(&addr, 0, sizeof(addr)); 00557 00558 #ifdef HAVE_GETADDRINFO 00559 { 00560 struct addrinfo hints; 00561 struct addrinfo* answer = NULL; 00562 char strPort[6]; 00563 00564 XMEMSET(&hints, 0, sizeof(hints)); 00565 hints.ai_family = AF_UNSPEC; 00566 hints.ai_socktype = SOCK_STREAM; 00567 hints.ai_protocol = IPPROTO_TCP; 00568 00569 if (Word16ToString(strPort, port) == 0) { 00570 CYASSL_MSG("invalid port number for OCSP responder"); 00571 return -1; 00572 } 00573 00574 if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) { 00575 CYASSL_MSG("no addr info for OCSP responder"); 00576 return -1; 00577 } 00578 00579 sockaddr_len = answer->ai_addrlen; 00580 XMEMCPY(&addr, answer->ai_addr, sockaddr_len); 00581 freeaddrinfo(answer); 00582 00583 } 00584 #else /* HAVE_GETADDRINFO */ 00585 { 00586 struct hostent* entry = gethostbyname(ip); 00587 struct sockaddr_in *sin = (struct sockaddr_in *)&addr; 00588 00589 if (entry) { 00590 sin->sin_family = AF_INET; 00591 sin->sin_port = htons(port); 00592 XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], 00593 entry->h_length); 00594 } 00595 else { 00596 CYASSL_MSG("no addr info for OCSP responder"); 00597 return -1; 00598 } 00599 } 00600 #endif /* HAVE_GETADDRINFO */ 00601 00602 *sockfd = socket(addr.ss_family, SOCK_STREAM, 0); 00603 00604 #ifdef USE_WINDOWS_API 00605 if (*sockfd == INVALID_SOCKET) { 00606 CYASSL_MSG("bad socket fd, out of fds?"); 00607 return -1; 00608 } 00609 #else 00610 if (*sockfd < 0) { 00611 CYASSL_MSG("bad socket fd, out of fds?"); 00612 return -1; 00613 } 00614 #endif 00615 00616 if (connect(*sockfd, (struct sockaddr *)&addr, sockaddr_len) != 0) { 00617 CYASSL_MSG("OCSP responder tcp connect failed"); 00618 return -1; 00619 } 00620 00621 return 0; 00622 } 00623 00624 00625 static int build_http_request(const char* domainName, const char* path, 00626 int ocspReqSz, byte* buf, int bufSize) 00627 { 00628 word32 domainNameLen, pathLen, ocspReqSzStrLen, completeLen; 00629 char ocspReqSzStr[6]; 00630 00631 domainNameLen = (word32)XSTRLEN(domainName); 00632 pathLen = (word32)XSTRLEN(path); 00633 ocspReqSzStrLen = Word16ToString(ocspReqSzStr, (word16)ocspReqSz); 00634 00635 completeLen = domainNameLen + pathLen + ocspReqSzStrLen + 84; 00636 if (completeLen > (word32)bufSize) 00637 return 0; 00638 00639 XSTRNCPY((char*)buf, "POST ", 5); 00640 buf += 5; 00641 XSTRNCPY((char*)buf, path, pathLen); 00642 buf += pathLen; 00643 XSTRNCPY((char*)buf, " HTTP/1.1\r\nHost: ", 17); 00644 buf += 17; 00645 XSTRNCPY((char*)buf, domainName, domainNameLen); 00646 buf += domainNameLen; 00647 XSTRNCPY((char*)buf, "\r\nContent-Length: ", 18); 00648 buf += 18; 00649 XSTRNCPY((char*)buf, ocspReqSzStr, ocspReqSzStrLen); 00650 buf += ocspReqSzStrLen; 00651 XSTRNCPY((char*)buf, 00652 "\r\nContent-Type: application/ocsp-request\r\n\r\n", 44); 00653 00654 return completeLen; 00655 } 00656 00657 00658 static int decode_url(const char* url, int urlSz, 00659 char* outName, char* outPath, word16* outPort) 00660 { 00661 int result = -1; 00662 00663 if (outName != NULL && outPath != NULL && outPort != NULL) 00664 { 00665 if (url == NULL || urlSz == 0) 00666 { 00667 *outName = 0; 00668 *outPath = 0; 00669 *outPort = 0; 00670 } 00671 else 00672 { 00673 int i, cur; 00674 00675 /* need to break the url down into scheme, address, and port */ 00676 /* "http://example.com:8080/" */ 00677 /* "http://[::1]:443/" */ 00678 if (XSTRNCMP(url, "http://", 7) == 0) { 00679 cur = 7; 00680 } else cur = 0; 00681 00682 i = 0; 00683 if (url[cur] == '[') { 00684 cur++; 00685 /* copy until ']' */ 00686 while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) { 00687 outName[i++] = url[cur++]; 00688 } 00689 cur++; /* skip ']' */ 00690 } 00691 else { 00692 while (url[cur] != 0 && url[cur] != ':' && 00693 url[cur] != '/' && cur < urlSz) { 00694 outName[i++] = url[cur++]; 00695 } 00696 } 00697 outName[i] = 0; 00698 /* Need to pick out the path after the domain name */ 00699 00700 if (cur < urlSz && url[cur] == ':') { 00701 char port[6]; 00702 int j; 00703 word32 bigPort = 0; 00704 i = 0; 00705 cur++; 00706 while (cur < urlSz && url[cur] != 0 && url[cur] != '/' && 00707 i < 6) { 00708 port[i++] = url[cur++]; 00709 } 00710 00711 for (j = 0; j < i; j++) { 00712 if (port[j] < '0' || port[j] > '9') return -1; 00713 bigPort = (bigPort * 10) + (port[j] - '0'); 00714 } 00715 *outPort = (word16)bigPort; 00716 } 00717 else 00718 *outPort = 80; 00719 00720 if (cur < urlSz && url[cur] == '/') { 00721 i = 0; 00722 while (cur < urlSz && url[cur] != 0 && i < 80) { 00723 outPath[i++] = url[cur++]; 00724 } 00725 outPath[i] = 0; 00726 } 00727 else { 00728 outPath[0] = '/'; 00729 outPath[1] = 0; 00730 } 00731 result = 0; 00732 } 00733 } 00734 00735 return result; 00736 } 00737 00738 00739 /* return: >0 OCSP Response Size 00740 * -1 error */ 00741 static int process_http_response(int sfd, byte** respBuf, 00742 byte* httpBuf, int httpBufSz) 00743 { 00744 int result; 00745 int len = 0; 00746 char *start, *end; 00747 byte *recvBuf = NULL; 00748 int recvBufSz = 0; 00749 enum phr_state { phr_init, phr_http_start, phr_have_length, 00750 phr_have_type, phr_wait_end, phr_http_end 00751 } state = phr_init; 00752 00753 start = end = NULL; 00754 do { 00755 if (end == NULL) { 00756 result = (int)recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); 00757 if (result > 0) { 00758 len += result; 00759 start = (char*)httpBuf; 00760 start[len] = 0; 00761 } 00762 else { 00763 CYASSL_MSG("process_http_response recv http from peer failed"); 00764 return -1; 00765 } 00766 } 00767 end = XSTRSTR(start, "\r\n"); 00768 00769 if (end == NULL) { 00770 if (len != 0) 00771 XMEMMOVE(httpBuf, start, len); 00772 start = end = NULL; 00773 } 00774 else if (end == start) { 00775 if (state == phr_wait_end) { 00776 state = phr_http_end; 00777 len -= 2; 00778 start += 2; 00779 } 00780 else { 00781 CYASSL_MSG("process_http_response header ended early"); 00782 return -1; 00783 } 00784 } 00785 else { 00786 *end = 0; 00787 len -= (int)(end - start) + 2; 00788 /* adjust len to remove the first line including the /r/n */ 00789 00790 if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { 00791 start += 9; 00792 if (XSTRNCASECMP(start, "200 OK", 6) != 0 || 00793 state != phr_init) { 00794 CYASSL_MSG("process_http_response not OK"); 00795 return -1; 00796 } 00797 state = phr_http_start; 00798 } 00799 else if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { 00800 start += 13; 00801 while (*start == ' ' && *start != '\0') start++; 00802 if (XSTRNCASECMP(start, "application/ocsp-response", 25) != 0) { 00803 CYASSL_MSG("process_http_response not ocsp-response"); 00804 return -1; 00805 } 00806 00807 if (state == phr_http_start) state = phr_have_type; 00808 else if (state == phr_have_length) state = phr_wait_end; 00809 else { 00810 CYASSL_MSG("process_http_response type invalid state"); 00811 return -1; 00812 } 00813 } 00814 else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { 00815 start += 15; 00816 while (*start == ' ' && *start != '\0') start++; 00817 recvBufSz = atoi(start); 00818 00819 if (state == phr_http_start) state = phr_have_length; 00820 else if (state == phr_have_type) state = phr_wait_end; 00821 else { 00822 CYASSL_MSG("process_http_response length invalid state"); 00823 return -1; 00824 } 00825 } 00826 00827 start = end + 2; 00828 } 00829 } while (state != phr_http_end); 00830 00831 recvBuf = (byte*)XMALLOC(recvBufSz, NULL, DYNAMIC_TYPE_IN_BUFFER); 00832 if (recvBuf == NULL) { 00833 CYASSL_MSG("process_http_response couldn't create response buffer"); 00834 return -1; 00835 } 00836 00837 /* copy the remainder of the httpBuf into the respBuf */ 00838 if (len != 0) 00839 XMEMCPY(recvBuf, start, len); 00840 00841 /* receive the OCSP response data */ 00842 do { 00843 result = (int)recv(sfd, (char*)recvBuf+len, recvBufSz-len, 0); 00844 if (result > 0) 00845 len += result; 00846 else { 00847 CYASSL_MSG("process_http_response recv ocsp from peer failed"); 00848 return -1; 00849 } 00850 } while (len != recvBufSz); 00851 00852 *respBuf = recvBuf; 00853 return recvBufSz; 00854 } 00855 00856 00857 #define SCRATCH_BUFFER_SIZE 512 00858 00859 int EmbedOcspLookup(void* ctx, const char* url, int urlSz, 00860 byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf) 00861 { 00862 SOCKET_T sfd = 0; 00863 word16 port; 00864 int ret = -1; 00865 #ifdef CYASSL_SMALL_STACK 00866 char* path; 00867 char* domainName; 00868 #else 00869 char path[80]; 00870 char domainName[80]; 00871 #endif 00872 00873 #ifdef CYASSL_SMALL_STACK 00874 path = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00875 if (path == NULL) 00876 return -1; 00877 00878 domainName = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00879 if (domainName == NULL) { 00880 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00881 return -1; 00882 } 00883 #endif 00884 00885 (void)ctx; 00886 00887 if (ocspReqBuf == NULL || ocspReqSz == 0) { 00888 CYASSL_MSG("OCSP request is required for lookup"); 00889 } 00890 else if (ocspRespBuf == NULL) { 00891 CYASSL_MSG("Cannot save OCSP response"); 00892 } 00893 else if (decode_url(url, urlSz, domainName, path, &port) < 0) { 00894 CYASSL_MSG("Unable to decode OCSP URL"); 00895 } 00896 else { 00897 /* Note, the library uses the EmbedOcspRespFree() callback to 00898 * free this buffer. */ 00899 int httpBufSz = SCRATCH_BUFFER_SIZE; 00900 byte* httpBuf = (byte*)XMALLOC(httpBufSz, NULL, 00901 DYNAMIC_TYPE_IN_BUFFER); 00902 00903 if (httpBuf == NULL) { 00904 CYASSL_MSG("Unable to create OCSP response buffer"); 00905 } 00906 else { 00907 httpBufSz = build_http_request(domainName, path, ocspReqSz, 00908 httpBuf, httpBufSz); 00909 00910 if ((tcp_connect(&sfd, domainName, port) != 0) || (sfd <= 0)) { 00911 CYASSL_MSG("OCSP Responder connection failed"); 00912 } 00913 else if ((int)send(sfd, (char*)httpBuf, httpBufSz, 0) != 00914 httpBufSz) { 00915 CYASSL_MSG("OCSP http request failed"); 00916 } 00917 else if ((int)send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) != 00918 ocspReqSz) { 00919 CYASSL_MSG("OCSP ocsp request failed"); 00920 } 00921 else { 00922 ret = process_http_response(sfd, ocspRespBuf, httpBuf, 00923 SCRATCH_BUFFER_SIZE); 00924 } 00925 00926 close(sfd); 00927 XFREE(httpBuf, NULL, DYNAMIC_TYPE_IN_BUFFER); 00928 } 00929 } 00930 00931 #ifdef CYASSL_SMALL_STACK 00932 XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00933 XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00934 #endif 00935 00936 return ret; 00937 } 00938 00939 00940 void EmbedOcspRespFree(void* ctx, byte *resp) 00941 { 00942 (void)ctx; 00943 00944 if (resp) 00945 XFREE(resp, NULL, DYNAMIC_TYPE_IN_BUFFER); 00946 } 00947 00948 00949 #endif 00950 00951 #endif /* CYASSL_USER_IO */ 00952 00953 CYASSL_API void CyaSSL_SetIORecv(CYASSL_CTX *ctx, CallbackIORecv CBIORecv) 00954 { 00955 ctx->CBIORecv = CBIORecv; 00956 } 00957 00958 00959 CYASSL_API void CyaSSL_SetIOSend(CYASSL_CTX *ctx, CallbackIOSend CBIOSend) 00960 { 00961 ctx->CBIOSend = CBIOSend; 00962 } 00963 00964 00965 CYASSL_API void CyaSSL_SetIOReadCtx(CYASSL* ssl, void *rctx) 00966 { 00967 ssl->IOCB_ReadCtx = rctx; 00968 } 00969 00970 00971 CYASSL_API void CyaSSL_SetIOWriteCtx(CYASSL* ssl, void *wctx) 00972 { 00973 ssl->IOCB_WriteCtx = wctx; 00974 } 00975 00976 00977 CYASSL_API void* CyaSSL_GetIOReadCtx(CYASSL* ssl) 00978 { 00979 if (ssl) 00980 return ssl->IOCB_ReadCtx; 00981 00982 return NULL; 00983 } 00984 00985 00986 CYASSL_API void* CyaSSL_GetIOWriteCtx(CYASSL* ssl) 00987 { 00988 if (ssl) 00989 return ssl->IOCB_WriteCtx; 00990 00991 return NULL; 00992 } 00993 00994 00995 CYASSL_API void CyaSSL_SetIOReadFlags(CYASSL* ssl, int flags) 00996 { 00997 ssl->rflags = flags; 00998 } 00999 01000 01001 CYASSL_API void CyaSSL_SetIOWriteFlags(CYASSL* ssl, int flags) 01002 { 01003 ssl->wflags = flags; 01004 } 01005 01006 01007 #ifdef CYASSL_DTLS 01008 01009 CYASSL_API void CyaSSL_CTX_SetGenCookie(CYASSL_CTX* ctx, CallbackGenCookie cb) 01010 { 01011 ctx->CBIOCookie = cb; 01012 } 01013 01014 01015 CYASSL_API void CyaSSL_SetCookieCtx(CYASSL* ssl, void *ctx) 01016 { 01017 ssl->IOCB_CookieCtx = ctx; 01018 } 01019 01020 01021 CYASSL_API void* CyaSSL_GetCookieCtx(CYASSL* ssl) 01022 { 01023 if (ssl) 01024 return ssl->IOCB_CookieCtx; 01025 01026 return NULL; 01027 } 01028 01029 #endif /* CYASSL_DTLS */ 01030 01031 01032 #ifdef HAVE_NETX 01033 01034 /* The NetX receive callback 01035 * return : bytes read, or error 01036 */ 01037 int NetX_Receive(CYASSL *ssl, char *buf, int sz, void *ctx) 01038 { 01039 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx; 01040 ULONG left; 01041 ULONG total; 01042 ULONG copied = 0; 01043 UINT status; 01044 01045 if (nxCtx == NULL || nxCtx->nxSocket == NULL) { 01046 CYASSL_MSG("NetX Recv NULL parameters"); 01047 return CYASSL_CBIO_ERR_GENERAL; 01048 } 01049 01050 if (nxCtx->nxPacket == NULL) { 01051 status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket, 01052 nxCtx->nxWait); 01053 if (status != NX_SUCCESS) { 01054 CYASSL_MSG("NetX Recv receive error"); 01055 return CYASSL_CBIO_ERR_GENERAL; 01056 } 01057 } 01058 01059 if (nxCtx->nxPacket) { 01060 status = nx_packet_length_get(nxCtx->nxPacket, &total); 01061 if (status != NX_SUCCESS) { 01062 CYASSL_MSG("NetX Recv length get error"); 01063 return CYASSL_CBIO_ERR_GENERAL; 01064 } 01065 01066 left = total - nxCtx->nxOffset; 01067 status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset, 01068 buf, sz, &copied); 01069 if (status != NX_SUCCESS) { 01070 CYASSL_MSG("NetX Recv data extract offset error"); 01071 return CYASSL_CBIO_ERR_GENERAL; 01072 } 01073 01074 nxCtx->nxOffset += copied; 01075 01076 if (copied == left) { 01077 CYASSL_MSG("NetX Recv Drained packet"); 01078 nx_packet_release(nxCtx->nxPacket); 01079 nxCtx->nxPacket = NULL; 01080 nxCtx->nxOffset = 0; 01081 } 01082 } 01083 01084 return copied; 01085 } 01086 01087 01088 /* The NetX send callback 01089 * return : bytes sent, or error 01090 */ 01091 int NetX_Send(CYASSL* ssl, char *buf, int sz, void *ctx) 01092 { 01093 NetX_Ctx* nxCtx = (NetX_Ctx*)ctx; 01094 NX_PACKET* packet; 01095 NX_PACKET_POOL* pool; /* shorthand */ 01096 UINT status; 01097 01098 if (nxCtx == NULL || nxCtx->nxSocket == NULL) { 01099 CYASSL_MSG("NetX Send NULL parameters"); 01100 return CYASSL_CBIO_ERR_GENERAL; 01101 } 01102 01103 pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool; 01104 status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET, 01105 nxCtx->nxWait); 01106 if (status != NX_SUCCESS) { 01107 CYASSL_MSG("NetX Send packet alloc error"); 01108 return CYASSL_CBIO_ERR_GENERAL; 01109 } 01110 01111 status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait); 01112 if (status != NX_SUCCESS) { 01113 nx_packet_release(packet); 01114 CYASSL_MSG("NetX Send data append error"); 01115 return CYASSL_CBIO_ERR_GENERAL; 01116 } 01117 01118 status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait); 01119 if (status != NX_SUCCESS) { 01120 nx_packet_release(packet); 01121 CYASSL_MSG("NetX Send socket send error"); 01122 return CYASSL_CBIO_ERR_GENERAL; 01123 } 01124 01125 return sz; 01126 } 01127 01128 01129 /* like set_fd, but for default NetX context */ 01130 void CyaSSL_SetIO_NetX(CYASSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption) 01131 { 01132 if (ssl) { 01133 ssl->nxCtx.nxSocket = nxSocket; 01134 ssl->nxCtx.nxWait = waitOption; 01135 } 01136 } 01137 01138 #endif /* HAVE_NETX */ 01139
Generated on Wed Jul 13 2022 02:33:56 by
1.7.2