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