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.
io.c
00001 /* io.c 00002 * 00003 * Copyright (C) 2006-2013 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
Generated on Tue Jul 12 2022 20:12:51 by
