This is a port of cyaSSL 2.7.0.
Dependents: CyaSSL_DTLS_Cellular CyaSSL_DTLS_Ethernet
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 "bsd_socket.h" 00027 00028 #include <cyassl/ctaocrypt/settings.h> 00029 00030 #ifdef _WIN32_WCE 00031 /* On WinCE winsock2.h must be included before windows.h for socket stuff */ 00032 #include <winsock2.h> 00033 #endif 00034 00035 #include <cyassl/internal.h> 00036 #include <cyassl/ctaoerror.h> 00037 00038 /* if user writes own I/O callbacks they can define CYASSL_USER_IO to remove 00039 automatic setting of default I/O functions EmbedSend() and EmbedReceive() 00040 but they'll still need SetCallback xxx() at end of file 00041 */ 00042 #ifndef CYASSL_USER_IO 00043 00044 #ifdef HAVE_LIBZ 00045 #include "zlib.h" 00046 #endif 00047 00048 #ifndef USE_WINDOWS_API 00049 #ifdef CYASSL_LWIP 00050 /* lwIP needs to be configured to use sockets API in this mode */ 00051 /* LWIP_SOCKET 1 in lwip/opt.h or in build */ 00052 #include "lwip/sockets.h" 00053 #include <errno.h> 00054 #ifndef LWIP_PROVIDE_ERRNO 00055 #define LWIP_PROVIDE_ERRNO 1 00056 #endif 00057 #elif defined(FREESCALE_MQX) 00058 #include <posix.h> 00059 #include <rtcs.h> 00060 #elif defined(CYASSL_MDK_ARM) 00061 #include <rtl.h> 00062 #undef RNG 00063 #include "CYASSL_MDK_ARM.h" 00064 #undef RNG 00065 #define RNG CyaSSL_RNG 00066 /* for avoiding name conflict in "stm32f2xx.h" */ 00067 static int errno; 00068 #else 00069 // #include <sys/types.h> 00070 #include <errno.h> 00071 #ifndef EBSNET 00072 // #include <unistd.h> 00073 #endif 00074 #include <fcntl.h> 00075 #if !(defined(DEVKITPRO) || defined(HAVE_RTP_SYS) || defined(EBSNET)) 00076 #include <sys/socket.h> 00077 #include <arpa/inet.h> 00078 #include <netinet/in.h> 00079 #include <netdb.h> 00080 #ifdef __PPU 00081 #include <netex/errno.h> 00082 #else 00083 #include <sys/ioctl.h> 00084 #endif 00085 #endif 00086 #ifdef HAVE_RTP_SYS 00087 #include <socket.h> 00088 #endif 00089 #ifdef EBSNET 00090 #include "rtipapi.h" /* errno */ 00091 #include "socket.h" 00092 #endif 00093 #endif 00094 #endif /* USE_WINDOWS_API */ 00095 00096 #ifdef __sun 00097 #include <sys/filio.h> 00098 #endif 00099 00100 #ifdef USE_WINDOWS_API 00101 /* no epipe yet */ 00102 #ifndef WSAEPIPE 00103 #define WSAEPIPE -12345 00104 #endif 00105 #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK 00106 #define SOCKET_EAGAIN WSAETIMEDOUT 00107 #define SOCKET_ECONNRESET WSAECONNRESET 00108 #define SOCKET_EINTR WSAEINTR 00109 #define SOCKET_EPIPE WSAEPIPE 00110 #define SOCKET_ECONNREFUSED WSAENOTCONN 00111 #define SOCKET_ECONNABORTED WSAECONNABORTED 00112 #elif defined(__PPU) 00113 #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK 00114 #define SOCKET_EAGAIN SYS_NET_EAGAIN 00115 #define SOCKET_ECONNRESET SYS_NET_ECONNRESET 00116 #define SOCKET_EINTR SYS_NET_EINTR 00117 #define SOCKET_EPIPE SYS_NET_EPIPE 00118 #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED 00119 #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED 00120 #elif defined(FREESCALE_MQX) 00121 /* RTCS doesn't have an EWOULDBLOCK error */ 00122 #define SOCKET_EWOULDBLOCK EAGAIN 00123 #define SOCKET_EAGAIN EAGAIN 00124 #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET 00125 #define SOCKET_EINTR EINTR 00126 #define SOCKET_EPIPE EPIPE 00127 #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED 00128 #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED 00129 #elif defined(CYASSL_MDK_ARM) 00130 #define SOCKET_EWOULDBLOCK SCK_EWOULDBLOCK 00131 #define SOCKET_EAGAIN SCK_ELOCKED 00132 #define SOCKET_ECONNRESET SCK_ECLOSED 00133 #define SOCKET_EINTR SCK_ERROR 00134 #define SOCKET_EPIPE SCK_ERROR 00135 #define SOCKET_ECONNREFUSED SCK_ERROR 00136 #define SOCKET_ECONNABORTED SCK_ERROR 00137 #else 00138 #define SOCKET_EWOULDBLOCK EWOULDBLOCK 00139 #define SOCKET_EAGAIN EAGAIN 00140 #define SOCKET_ECONNRESET ECONNRESET 00141 #define SOCKET_EINTR EINTR 00142 #define SOCKET_EPIPE EPIPE 00143 #define SOCKET_ECONNREFUSED ECONNREFUSED 00144 #define SOCKET_ECONNABORTED ECONNABORTED 00145 #endif /* USE_WINDOWS_API */ 00146 00147 00148 #ifdef DEVKITPRO 00149 /* from network.h */ 00150 int net_send(int, const void*, int, unsigned int); 00151 int net_recv(int, void*, int, unsigned int); 00152 #define SEND_FUNCTION net_send 00153 #define RECV_FUNCTION net_recv 00154 #elif defined(CYASSL_LWIP) 00155 #define SEND_FUNCTION lwip_send 00156 #define RECV_FUNCTION lwip_recv 00157 #else 00158 #define SEND_FUNCTION send 00159 #define RECV_FUNCTION recv 00160 #endif 00161 00162 00163 /* Translates return codes returned from 00164 * send() and recv() if need be. 00165 */ 00166 static INLINE int TranslateReturnCode(int old, int sd) 00167 { 00168 (void)sd; 00169 00170 #ifdef FREESCALE_MQX 00171 if (old == 0) { 00172 errno = SOCKET_EWOULDBLOCK; 00173 return -1; /* convert to BSD style wouldblock as error */ 00174 } 00175 00176 if (old < 0) { 00177 errno = RTCS_geterror(sd); 00178 if (errno == RTCSERR_TCP_CONN_CLOSING) 00179 return 0; /* convert to BSD style closing */ 00180 } 00181 #endif 00182 00183 return old; 00184 } 00185 00186 static INLINE int LastError(void) 00187 { 00188 #ifdef USE_WINDOWS_API 00189 return WSAGetLastError(); 00190 #elif defined(EBSNET) 00191 return xn_getlasterror(); 00192 #else 00193 return errno; 00194 #endif 00195 } 00196 00197 /* The receive embedded callback 00198 * return : nb bytes read, or error 00199 */ 00200 int EmbedReceive(CYASSL *ssl, char *buf, int sz, void *ctx) 00201 { 00202 int recvd; 00203 int err; 00204 int sd = *(int*)ctx; 00205 00206 #ifdef CYASSL_DTLS 00207 { 00208 int dtls_timeout = CyaSSL_dtls_get_current_timeout(ssl); 00209 if (CyaSSL_dtls(ssl) 00210 && !CyaSSL_get_using_nonblock(ssl) 00211 && dtls_timeout != 0) { 00212 #ifdef USE_WINDOWS_API 00213 DWORD timeout = dtls_timeout * 1000; 00214 #else 00215 struct timeval timeout; 00216 XMEMSET(&timeout, 0, sizeof(timeout)); 00217 timeout.tv_sec = dtls_timeout; 00218 #endif 00219 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, 00220 sizeof(timeout)) != 0) { 00221 CYASSL_MSG("setsockopt rcvtimeo failed"); 00222 } 00223 } 00224 } 00225 #endif 00226 00227 recvd = (int)RECV_FUNCTION(sd, buf, sz, ssl->rflags); 00228 00229 recvd = TranslateReturnCode(recvd, sd); 00230 00231 if (recvd < 0) { 00232 err = LastError(); 00233 CYASSL_MSG("Embed Receive error"); 00234 00235 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { 00236 if (!CyaSSL_dtls(ssl) || CyaSSL_get_using_nonblock(ssl)) { 00237 CYASSL_MSG(" Would block"); 00238 return CYASSL_CBIO_ERR_WANT_READ; 00239 } 00240 else { 00241 CYASSL_MSG(" Socket timeout"); 00242 return CYASSL_CBIO_ERR_TIMEOUT; 00243 } 00244 } 00245 else if (err == SOCKET_ECONNRESET) { 00246 CYASSL_MSG(" Connection reset"); 00247 return CYASSL_CBIO_ERR_CONN_RST; 00248 } 00249 else if (err == SOCKET_EINTR) { 00250 CYASSL_MSG(" Socket interrupted"); 00251 return CYASSL_CBIO_ERR_ISR; 00252 } 00253 else if (err == SOCKET_ECONNREFUSED) { 00254 CYASSL_MSG(" Connection refused"); 00255 return CYASSL_CBIO_ERR_WANT_READ; 00256 } 00257 else if (err == SOCKET_ECONNABORTED) { 00258 CYASSL_MSG(" Connection aborted"); 00259 return CYASSL_CBIO_ERR_CONN_CLOSE; 00260 } 00261 else { 00262 CYASSL_MSG(" General error"); 00263 return CYASSL_CBIO_ERR_GENERAL; 00264 } 00265 } 00266 else if (recvd == 0) { 00267 CYASSL_MSG("Embed receive connection closed"); 00268 return CYASSL_CBIO_ERR_CONN_CLOSE; 00269 } 00270 00271 return recvd; 00272 } 00273 00274 /* The send embedded callback 00275 * return : nb bytes sent, or error 00276 */ 00277 int EmbedSend(CYASSL* ssl, char *buf, int sz, void *ctx) 00278 { 00279 int sd = *(int*)ctx; 00280 int sent; 00281 int len = sz; 00282 int err; 00283 00284 sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, ssl->wflags); 00285 00286 if (sent < 0) { 00287 err = LastError(); 00288 CYASSL_MSG("Embed Send error"); 00289 00290 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { 00291 CYASSL_MSG(" Would Block"); 00292 return CYASSL_CBIO_ERR_WANT_WRITE; 00293 } 00294 else if (err == SOCKET_ECONNRESET) { 00295 CYASSL_MSG(" Connection reset"); 00296 return CYASSL_CBIO_ERR_CONN_RST; 00297 } 00298 else if (err == SOCKET_EINTR) { 00299 CYASSL_MSG(" Socket interrupted"); 00300 return CYASSL_CBIO_ERR_ISR; 00301 } 00302 else if (err == SOCKET_EPIPE) { 00303 CYASSL_MSG(" Socket EPIPE"); 00304 return CYASSL_CBIO_ERR_CONN_CLOSE; 00305 } 00306 else { 00307 CYASSL_MSG(" General error"); 00308 return CYASSL_CBIO_ERR_GENERAL; 00309 } 00310 } 00311 00312 return sent; 00313 } 00314 00315 00316 #ifdef CYASSL_DTLS 00317 00318 #include <cyassl/ctaocrypt/sha.h> 00319 00320 #ifdef USE_WINDOWS_API 00321 #define XSOCKLENT int 00322 #else 00323 #define XSOCKLENT socklen_t 00324 #endif 00325 00326 #define SENDTO_FUNCTION sendto 00327 #define RECVFROM_FUNCTION recvfrom 00328 00329 00330 /* The receive embedded callback 00331 * return : nb bytes read, or error 00332 */ 00333 int EmbedReceiveFrom(CYASSL *ssl, char *buf, int sz, void *ctx) 00334 { 00335 CYASSL_DTLS_CTX* dtlsCtx = (CYASSL_DTLS_CTX*)ctx; 00336 int recvd; 00337 int err; 00338 int sd = dtlsCtx->fd; 00339 int dtls_timeout = CyaSSL_dtls_get_current_timeout(ssl); 00340 struct sockaddr_in peer; 00341 XSOCKLENT peerSz = sizeof(peer); 00342 00343 CYASSL_ENTER("EmbedReceiveFrom()"); 00344 00345 if (!CyaSSL_get_using_nonblock(ssl) && dtls_timeout != 0) { 00346 #ifdef USE_WINDOWS_API 00347 DWORD timeout = dtls_timeout * 1000; 00348 #else 00349 struct timeval timeout; 00350 XMEMSET(&timeout, 0, sizeof(timeout)); 00351 timeout.tv_sec = dtls_timeout; 00352 #endif 00353 if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, 00354 sizeof(timeout)) != 0) { 00355 CYASSL_MSG("setsockopt rcvtimeo failed"); 00356 } 00357 } 00358 00359 recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, 00360 (struct sockaddr*)&peer, &peerSz); 00361 recvd = TranslateReturnCode(recvd, sd); 00362 00363 if (recvd < 0) { 00364 err = LastError(); 00365 CYASSL_MSG("Embed Receive From error"); 00366 00367 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { 00368 if (CyaSSL_get_using_nonblock(ssl)) { 00369 CYASSL_MSG(" Would block"); 00370 return CYASSL_CBIO_ERR_WANT_READ; 00371 } 00372 else { 00373 CYASSL_MSG(" Socket timeout"); 00374 return CYASSL_CBIO_ERR_TIMEOUT; 00375 } 00376 } 00377 else if (err == SOCKET_ECONNRESET) { 00378 CYASSL_MSG(" Connection reset"); 00379 return CYASSL_CBIO_ERR_CONN_RST; 00380 } 00381 else if (err == SOCKET_EINTR) { 00382 CYASSL_MSG(" Socket interrupted"); 00383 return CYASSL_CBIO_ERR_ISR; 00384 } 00385 else if (err == SOCKET_ECONNREFUSED) { 00386 CYASSL_MSG(" Connection refused"); 00387 return CYASSL_CBIO_ERR_WANT_READ; 00388 } 00389 else { 00390 CYASSL_MSG(" General error"); 00391 return CYASSL_CBIO_ERR_GENERAL; 00392 } 00393 } 00394 else { 00395 if (dtlsCtx->peer.sz > 0 00396 && peerSz != (XSOCKLENT)dtlsCtx->peer.sz 00397 && memcmp(&peer, dtlsCtx->peer.sa, peerSz) != 0) { 00398 CYASSL_MSG(" Ignored packet from invalid peer"); 00399 return CYASSL_CBIO_ERR_WANT_READ; 00400 } 00401 } 00402 00403 return recvd; 00404 } 00405 00406 00407 /* The send embedded callback 00408 * return : nb bytes sent, or error 00409 */ 00410 int EmbedSendTo(CYASSL* ssl, char *buf, int sz, void *ctx) 00411 { 00412 CYASSL_DTLS_CTX* dtlsCtx = (CYASSL_DTLS_CTX*)ctx; 00413 int sd = dtlsCtx->fd; 00414 int sent; 00415 int len = sz; 00416 int err; 00417 00418 CYASSL_ENTER("EmbedSendTo()"); 00419 00420 sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags, 00421 dtlsCtx->peer.sa, dtlsCtx->peer.sz); 00422 if (sent < 0) { 00423 err = LastError(); 00424 CYASSL_MSG("Embed Send To error"); 00425 00426 if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { 00427 CYASSL_MSG(" Would Block"); 00428 return CYASSL_CBIO_ERR_WANT_WRITE; 00429 } 00430 else if (err == SOCKET_ECONNRESET) { 00431 CYASSL_MSG(" Connection reset"); 00432 return CYASSL_CBIO_ERR_CONN_RST; 00433 } 00434 else if (err == SOCKET_EINTR) { 00435 CYASSL_MSG(" Socket interrupted"); 00436 return CYASSL_CBIO_ERR_ISR; 00437 } 00438 else if (err == SOCKET_EPIPE) { 00439 CYASSL_MSG(" Socket EPIPE"); 00440 return CYASSL_CBIO_ERR_CONN_CLOSE; 00441 } 00442 else { 00443 CYASSL_MSG(" General error"); 00444 return CYASSL_CBIO_ERR_GENERAL; 00445 } 00446 } 00447 00448 return sent; 00449 } 00450 00451 00452 /* The DTLS Generate Cookie callback 00453 * return : number of bytes copied into buf, or error 00454 */ 00455 int EmbedGenerateCookie(CYASSL* ssl, byte *buf, int sz, void *ctx) 00456 { 00457 int sd = ssl->wfd; 00458 struct sockaddr_in peer; 00459 XSOCKLENT peerSz = sizeof(peer); 00460 byte cookieSrc[sizeof(struct in_addr) + sizeof(int)]; 00461 int cookieSrcSz = 0; 00462 Sha sha; 00463 00464 (void)ctx; 00465 00466 if (getpeername(sd, (struct sockaddr*)&peer, &peerSz) != 0) { 00467 CYASSL_MSG("getpeername failed in EmbedGenerateCookie"); 00468 return GEN_COOKIE_E; 00469 } 00470 00471 if (peer.sin_family == AF_INET) { 00472 struct sockaddr_in *s = (struct sockaddr_in*)&peer; 00473 00474 cookieSrcSz = sizeof(struct in_addr) + sizeof(s->sin_port); 00475 XMEMCPY(cookieSrc, &s->sin_port, sizeof(s->sin_port)); 00476 XMEMCPY(cookieSrc + sizeof(s->sin_port), 00477 &s->sin_addr, sizeof(struct in_addr)); 00478 } 00479 00480 InitSha(&sha); 00481 ShaUpdate(&sha, cookieSrc, cookieSrcSz); 00482 00483 if (sz < SHA_DIGEST_SIZE) { 00484 byte digest[SHA_DIGEST_SIZE]; 00485 ShaFinal(&sha, digest); 00486 XMEMCPY(buf, digest, sz); 00487 return sz; 00488 } 00489 00490 ShaFinal(&sha, buf); 00491 00492 return SHA_DIGEST_SIZE; 00493 } 00494 00495 #endif /* CYASSL_DTLS */ 00496 00497 #ifdef HAVE_OCSP 00498 00499 #ifdef TEST_IPV6 00500 typedef struct sockaddr_in6 SOCKADDR_IN_T; 00501 #define AF_INET_V AF_INET6 00502 #else 00503 typedef struct sockaddr_in SOCKADDR_IN_T; 00504 #define AF_INET_V AF_INET 00505 #endif 00506 00507 00508 static INLINE int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port) 00509 { 00510 SOCKADDR_IN_T addr; 00511 const char* host = ip; 00512 00513 /* peer could be in human readable form */ 00514 if (ip != INADDR_ANY && isalpha(ip[0])) { 00515 struct hostent* entry = gethostbyname(ip); 00516 00517 if (entry) { 00518 struct sockaddr_in tmp; 00519 XMEMSET(&tmp, 0, sizeof(struct sockaddr_in)); 00520 XMEMCPY(&tmp.sin_addr.s_addr, entry->h_addr_list[0], 00521 entry->h_length); 00522 host = inet_ntoa(tmp.sin_addr); 00523 } 00524 else { 00525 CYASSL_MSG("no addr entry for OCSP responder"); 00526 return -1; 00527 } 00528 } 00529 00530 *sockfd = socket(AF_INET_V, SOCK_STREAM, 0); 00531 if (*sockfd < 0) { 00532 CYASSL_MSG("bad socket fd, out of fds?"); 00533 return -1; 00534 } 00535 XMEMSET(&addr, 0, sizeof(SOCKADDR_IN_T)); 00536 00537 addr.sin_family = AF_INET_V; 00538 addr.sin_port = htons(port); 00539 if (host == INADDR_ANY) 00540 addr.sin_addr.s_addr = INADDR_ANY; 00541 else 00542 addr.sin_addr.s_addr = inet_addr(host); 00543 00544 if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) { 00545 CYASSL_MSG("OCSP responder tcp connect failed"); 00546 return -1; 00547 } 00548 00549 return 0; 00550 } 00551 00552 00553 static int build_http_request(const char* domainName, const char* path, 00554 int ocspReqSz, byte* buf, int bufSize) 00555 { 00556 return snprintf((char*)buf, bufSize, 00557 "POST %s HTTP/1.1\r\n" 00558 "Host: %s\r\n" 00559 "Content-Length: %d\r\n" 00560 "Content-Type: application/ocsp-request\r\n" 00561 "\r\n", 00562 path, domainName, ocspReqSz); 00563 } 00564 00565 00566 static int decode_http_response(byte* httpBuf, int httpBufSz, byte** dst) 00567 { 00568 int idx = 0; 00569 int stop = 0; 00570 int len = 0; 00571 byte* contentType = NULL; 00572 byte* contentLength = NULL; 00573 char* buf = (char*)httpBuf; /* kludge so I'm not constantly casting */ 00574 00575 if (XSTRNCASECMP(buf, "HTTP/1", 6) != 0) 00576 return 0; 00577 00578 idx = 9; /* sets to the first byte after "HTTP/1.X ", which should be the 00579 * HTTP result code */ 00580 00581 if (XSTRNCASECMP(&buf[idx], "200 OK", 6) != 0) 00582 return 0; 00583 00584 idx += 8; 00585 00586 while (idx < httpBufSz && !stop) { 00587 if (buf[idx] == '\r' && buf[idx+1] == '\n') { 00588 stop = 1; 00589 idx += 2; 00590 } 00591 else { 00592 if (contentType == NULL && 00593 XSTRNCASECMP(&buf[idx], "Content-Type:", 13) == 0) { 00594 idx += 13; 00595 if (buf[idx] == ' ') idx++; 00596 if (XSTRNCASECMP(&buf[idx], 00597 "application/ocsp-response", 25) != 0) { 00598 return 0; 00599 } 00600 idx += 27; 00601 } 00602 else if (contentLength == NULL && 00603 XSTRNCASECMP(&buf[idx], "Content-Length:", 15) == 0) { 00604 idx += 15; 00605 if (buf[idx] == ' ') idx++; 00606 while (buf[idx] >= '0' && buf[idx] <= '9' && idx < httpBufSz) { 00607 len = (len * 10) + (buf[idx] - '0'); 00608 idx++; 00609 } 00610 idx += 2; /* skip the crlf */ 00611 } 00612 else { 00613 /* Advance idx past the next \r\n */ 00614 char* end = XSTRSTR(&buf[idx], "\r\n"); 00615 idx = (int)(end - buf + 2); 00616 } 00617 } 00618 } 00619 00620 if (len > 0) { 00621 *dst = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_IN_BUFFER); 00622 XMEMCPY(*dst, httpBuf + idx, len); 00623 } 00624 00625 return len; 00626 } 00627 00628 00629 static int decode_url(const char* url, int urlSz, 00630 char* outName, char* outPath, int* outPort) 00631 { 00632 int result = -1; 00633 00634 if (outName != NULL && outPath != NULL && outPort != NULL) 00635 { 00636 if (url == NULL || urlSz == 0) 00637 { 00638 *outName = 0; 00639 *outPath = 0; 00640 *outPort = 0; 00641 } 00642 else 00643 { 00644 int i, cur; 00645 00646 /* need to break the url down into scheme, address, and port */ 00647 /* "http://example.com:8080/" */ 00648 if (XSTRNCMP(url, "http://", 7) == 0) { 00649 cur = 7; 00650 } else cur = 0; 00651 00652 i = 0; 00653 while (url[cur] != 0 && url[cur] != ':' && 00654 url[cur] != '/' && cur < urlSz) { 00655 outName[i++] = url[cur++]; 00656 } 00657 outName[i] = 0; 00658 /* Need to pick out the path after the domain name */ 00659 00660 if (cur < urlSz && url[cur] == ':') { 00661 char port[6]; 00662 int j; 00663 i = 0; 00664 cur++; 00665 while (cur < urlSz && url[cur] != 0 && url[cur] != '/' && 00666 i < 6) { 00667 port[i++] = url[cur++]; 00668 } 00669 00670 *outPort = 0; 00671 for (j = 0; j < i; j++) { 00672 if (port[j] < '0' || port[j] > '9') return -1; 00673 *outPort = (*outPort * 10) + (port[j] - '0'); 00674 } 00675 } 00676 else 00677 *outPort = 80; 00678 00679 if (cur < urlSz && url[cur] == '/') { 00680 i = 0; 00681 while (cur < urlSz && url[cur] != 0 && i < 80) { 00682 outPath[i++] = url[cur++]; 00683 } 00684 outPath[i] = 0; 00685 } 00686 else { 00687 outPath[0] = '/'; 00688 outPath[1] = 0; 00689 } 00690 result = 0; 00691 } 00692 } 00693 00694 return result; 00695 } 00696 00697 00698 #define SCRATCH_BUFFER_SIZE 2048 00699 00700 int EmbedOcspLookup(void* ctx, const char* url, int urlSz, 00701 byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf) 00702 { 00703 char domainName[80], path[80]; 00704 int port, httpBufSz, sfd = -1; 00705 int ocspRespSz = 0; 00706 byte* httpBuf = NULL; 00707 00708 (void)ctx; 00709 00710 if (ocspReqBuf == NULL || ocspReqSz == 0) { 00711 CYASSL_MSG("OCSP request is required for lookup"); 00712 return -1; 00713 } 00714 00715 if (ocspRespBuf == NULL) { 00716 CYASSL_MSG("Cannot save OCSP response"); 00717 return -1; 00718 } 00719 00720 if (decode_url(url, urlSz, domainName, path, &port) < 0) { 00721 CYASSL_MSG("Unable to decode OCSP URL"); 00722 return -1; 00723 } 00724 00725 httpBufSz = SCRATCH_BUFFER_SIZE; 00726 httpBuf = (byte*)XMALLOC(httpBufSz, NULL, DYNAMIC_TYPE_IN_BUFFER); 00727 00728 if (httpBuf == NULL) { 00729 CYASSL_MSG("Unable to create OCSP response buffer"); 00730 return -1; 00731 } 00732 *ocspRespBuf = httpBuf; 00733 00734 httpBufSz = build_http_request(domainName, path, ocspReqSz, 00735 httpBuf, httpBufSz); 00736 00737 if ((tcp_connect(&sfd, domainName, port) == 0) && (sfd > 0)) { 00738 int written; 00739 written = (int)send(sfd, httpBuf, httpBufSz, 0); 00740 if (written == httpBufSz) { 00741 written = (int)send(sfd, ocspReqBuf, ocspReqSz, 0); 00742 if (written == ocspReqSz) { 00743 httpBufSz = (int)recv(sfd, httpBuf, SCRATCH_BUFFER_SIZE, 0); 00744 if (httpBufSz > 0) { 00745 ocspRespSz = decode_http_response(httpBuf, httpBufSz, 00746 ocspRespBuf); 00747 } 00748 } 00749 } 00750 close(sfd); 00751 if (ocspRespSz == 0) { 00752 CYASSL_MSG("OCSP response was not OK, no OCSP response"); 00753 return -1; 00754 } 00755 } else { 00756 CYASSL_MSG("OCSP Responder connection failed"); 00757 close(sfd); 00758 return -1; 00759 } 00760 00761 return ocspRespSz; 00762 } 00763 00764 00765 void EmbedOcspRespFree(void* ctx, byte *resp) 00766 { 00767 (void)ctx; 00768 00769 if (resp) 00770 XFREE(resp, NULL, DYNAMIC_TYPE_IN_BUFFER); 00771 } 00772 00773 00774 #endif 00775 00776 #endif /* CYASSL_USER_IO */ 00777 00778 CYASSL_API void CyaSSL_SetIORecv(CYASSL_CTX *ctx, CallbackIORecv CBIORecv) 00779 { 00780 ctx->CBIORecv = CBIORecv; 00781 } 00782 00783 00784 CYASSL_API void CyaSSL_SetIOSend(CYASSL_CTX *ctx, CallbackIOSend CBIOSend) 00785 { 00786 ctx->CBIOSend = CBIOSend; 00787 } 00788 00789 00790 CYASSL_API void CyaSSL_SetIOReadCtx(CYASSL* ssl, void *rctx) 00791 { 00792 ssl->IOCB_ReadCtx = rctx; 00793 } 00794 00795 00796 CYASSL_API void CyaSSL_SetIOWriteCtx(CYASSL* ssl, void *wctx) 00797 { 00798 ssl->IOCB_WriteCtx = wctx; 00799 } 00800 00801 00802 CYASSL_API void CyaSSL_SetIOReadFlags(CYASSL* ssl, int flags) 00803 { 00804 ssl->rflags = flags; 00805 } 00806 00807 00808 CYASSL_API void CyaSSL_SetIOWriteFlags(CYASSL* ssl, int flags) 00809 { 00810 ssl->wflags = flags; 00811 } 00812 00813 00814 #ifdef CYASSL_DTLS 00815 00816 CYASSL_API void CyaSSL_CTX_SetGenCookie(CYASSL_CTX* ctx, CallbackGenCookie cb) 00817 { 00818 ctx->CBIOCookie = cb; 00819 } 00820 00821 00822 CYASSL_API void CyaSSL_SetCookieCtx(CYASSL* ssl, void *ctx) 00823 { 00824 ssl->IOCB_CookieCtx = ctx; 00825 } 00826 00827 #endif /* CYASSL_DTLS */ 00828 00829 00830 #ifdef HAVE_OCSP 00831 00832 CYASSL_API void CyaSSL_SetIOOcsp(CYASSL_CTX* ctx, CallbackIOOcsp cb) 00833 { 00834 ctx->ocsp.CBIOOcsp = cb; 00835 } 00836 00837 CYASSL_API void CyaSSL_SetIOOcspRespFree(CYASSL_CTX* ctx, 00838 CallbackIOOcspRespFree cb) 00839 { 00840 ctx->ocsp.CBIOOcspRespFree = cb; 00841 } 00842 00843 CYASSL_API void CyaSSL_SetIOOcspCtx(CYASSL_CTX* ctx, void *octx) 00844 { 00845 ctx->ocsp.IOCB_OcspCtx = octx; 00846 } 00847 00848 #endif
Generated on Tue Jul 12 2022 20:44:51 by 1.7.2