static int decode_http_response(byte* httpBuf, int httpBufSz, byte** dst) { int idx = 0; int stop = 0; int len = 0; byte* contentType = NULL; byte* contentLength = NULL; char* buf = (char*)httpBuf; /* kludge so I'm not constantly casting */ if (strncasecmp(buf, "HTTP/1", 6) != 0) return 0; idx = 9; /* sets to the first byte after "HTTP/1.X ", which should be the * HTTP result code */ if (strncasecmp(&buf[idx], "200 OK", 6) != 0) return 0; idx += 8; while (idx < httpBufSz && !stop) { if (buf[idx] == '\r' && buf[idx+1] == '\n') { stop = 1; idx += 2; } else { if (contentType == NULL && strncasecmp(&buf[idx], "Content-Type:", 13) == 0) { idx += 13; if (buf[idx] == ' ') idx++; if (strncasecmp(&buf[idx], "application/ocsp-response", 25) != 0) return 0; idx += 27; } else if (contentLength == NULL && strncasecmp(&buf[idx], "Content-Length:", 15) == 0) { idx += 15; if (buf[idx] == ' ') idx++; while (buf[idx] >= '0' && buf[idx] <= '9' && idx < httpBufSz) { len = (len * 10) + (buf[idx] - '0'); idx++; } idx += 2; /* skip the crlf */ } else { /* Advance idx past the next \r\n */ char* end = XSTRSTR(&buf[idx], "\r\n"); idx = (int)(end - buf + 2); stop = 1; } } } if (len > 0) { *dst = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_IN_BUFFER); XMEMCPY(*dst, httpBuf + idx, len); } return len; }
/* if the cipher suite on line is valid store in suite and return 1, else 0 */ static int IsValidCipherSuite(const char* line, char* suite) { int found = 0; int valid = 0; const char* find = "-l "; const char* begin = strstr(line, find); const char* end; suite[0] = '\0'; if (begin) { begin += 3; end = XSTRSTR(begin, " "); if (end) { long len = end - begin; if (len > MAX_SUITE_SZ) { printf("suite too long!\n"); return 0; } XMEMCPY(suite, begin, len); suite[len] = '\0'; } else XSTRNCPY(suite, begin, MAX_SUITE_SZ); suite[MAX_SUITE_SZ] = '\0'; found = 1; } /* if QSH not enabled then do not use QSH suite */ #ifdef HAVE_QSH if (XSTRNCMP(suite, "QSH", 3) == 0) { if (wolfSSL_CTX_set_cipher_list(cipherSuiteCtx, suite + 4) != SSL_SUCCESS) return 0; } #endif if (found) { if (wolfSSL_CTX_set_cipher_list(cipherSuiteCtx, suite) == SSL_SUCCESS) valid = 1; } return valid; }
/* return: >0 OCSP Response Size * -1 error */ static int process_http_response(int sfd, byte** respBuf, byte* httpBuf, int httpBufSz) { int result; int len = 0; char *start, *end; byte *recvBuf = NULL; int recvBufSz = 0; enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type, phr_wait_end, phr_http_end } state = phr_init; start = end = NULL; do { if (end == NULL) { result = (int)recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); if (result > 0) { len += result; start = (char*)httpBuf; start[len] = 0; } else { CYASSL_MSG("process_http_response recv http from peer failed"); return -1; } } end = XSTRSTR(start, "\r\n"); if (end == NULL) { if (len != 0) XMEMMOVE(httpBuf, start, len); start = end = NULL; } else if (end == start) { if (state == phr_wait_end) { state = phr_http_end; len -= 2; start += 2; } else { CYASSL_MSG("process_http_response header ended early"); return -1; } } else { *end = 0; len -= (int)(end - start) + 2; /* adjust len to remove the first line including the /r/n */ if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { start += 9; if (XSTRNCASECMP(start, "200 OK", 6) != 0 || state != phr_init) { CYASSL_MSG("process_http_response not OK"); return -1; } state = phr_http_start; } else if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { start += 13; while (*start == ' ' && *start != '\0') start++; if (XSTRNCASECMP(start, "application/ocsp-response", 25) != 0) { CYASSL_MSG("process_http_response not ocsp-response"); return -1; } if (state == phr_http_start) state = phr_have_type; else if (state == phr_have_length) state = phr_wait_end; else { CYASSL_MSG("process_http_response type invalid state"); return -1; } } else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { start += 15; while (*start == ' ' && *start != '\0') start++; recvBufSz = atoi(start); if (state == phr_http_start) state = phr_have_length; else if (state == phr_have_type) state = phr_wait_end; else { CYASSL_MSG("process_http_response length invalid state"); return -1; } } start = end + 2; } } while (state != phr_http_end); recvBuf = (byte*)XMALLOC(recvBufSz, NULL, DYNAMIC_TYPE_IN_BUFFER); if (recvBuf == NULL) { CYASSL_MSG("process_http_response couldn't create response buffer"); return -1; } /* copy the remainder of the httpBuf into the respBuf */ if (len != 0) XMEMCPY(recvBuf, start, len); /* receive the OCSP response data */ do { result = (int)recv(sfd, (char*)recvBuf+len, recvBufSz-len, 0); if (result > 0) len += result; else { CYASSL_MSG("process_http_response recv ocsp from peer failed"); return -1; } } while (len != recvBufSz); *respBuf = recvBuf; return recvBufSz; }
/* Load CRL path files of type, SSL_SUCCESS on ok */ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) { struct dirent* entry; DIR* dir; int ret = SSL_SUCCESS; #ifdef WOLFSSL_SMALL_STACK char* name; #else char name[MAX_FILENAME_SZ]; #endif WOLFSSL_ENTER("LoadCRL"); if (crl == NULL) return BAD_FUNC_ARG; dir = opendir(path); if (dir == NULL) { WOLFSSL_MSG("opendir path crl load failed"); return BAD_PATH_ERROR; } #ifdef WOLFSSL_SMALL_STACK name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (name == NULL) return MEMORY_E; #endif while ( (entry = readdir(dir)) != NULL) { struct stat s; XMEMSET(name, 0, MAX_FILENAME_SZ); XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2); XSTRNCAT(name, "/", 1); XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2); if (stat(name, &s) != 0) { WOLFSSL_MSG("stat on name failed"); continue; } if (s.st_mode & S_IFREG) { if (type == SSL_FILETYPE_PEM) { if (XSTRSTR(entry->d_name, ".pem") == NULL) { WOLFSSL_MSG("not .pem file, skipping"); continue; } } else { if (XSTRSTR(entry->d_name, ".der") == NULL && XSTRSTR(entry->d_name, ".crl") == NULL) { WOLFSSL_MSG("not .der or .crl file, skipping"); continue; } } if (ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl) != SSL_SUCCESS) { WOLFSSL_MSG("CRL file load failed, continuing"); } } } #ifdef WOLFSSL_SMALL_STACK XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif if (monitor & WOLFSSL_CRL_MONITOR) { word32 pathLen; char* pathBuf; WOLFSSL_MSG("monitor path requested"); pathLen = (word32)XSTRLEN(path); pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR); if (pathBuf) { XSTRNCPY(pathBuf, path, pathLen); pathBuf[pathLen] = '\0'; /* Null Terminate */ if (type == SSL_FILETYPE_PEM) { crl->monitors[0].path = pathBuf; crl->monitors[0].type = SSL_FILETYPE_PEM; } else { crl->monitors[1].path = pathBuf; crl->monitors[1].type = SSL_FILETYPE_ASN1; } if (monitor & WOLFSSL_CRL_START_MON) { WOLFSSL_MSG("start monitoring requested"); ret = StartMonitorCRL(crl); } } else { ret = MEMORY_E; } } closedir(dir); return ret; }