OCSP Updates
1. Add option to example server and client to check the OCSP responder. 2. Add option to example server and client to override the URL to use when checking the OCSP responder. 3. Copy the certificate serial number correctly into OCSP request. Add leading zero only if MS bit is set. 4. Fix responder address used when Auth Info extension is present. 5. Update EmbedOcspLookup callback to better handle the HTTP response and obtain the complete OCSP response.
This commit is contained in:
parent
e0a84521c5
commit
0c34ecb451
@ -4847,10 +4847,20 @@ static int SetSerialNumber(const byte* sn, word32 snSz, byte* output)
|
||||
|
||||
if (snSz <= EXTERNAL_SERIAL_SIZE) {
|
||||
output[0] = ASN_INTEGER;
|
||||
output[1] = snSz + 1;
|
||||
output[2] = 0;
|
||||
XMEMCPY(&output[3], sn, snSz);
|
||||
result = snSz + 3;
|
||||
/* The serial number is always positive. When encoding the
|
||||
* INTEGER, if the MSB is 1, add a padding zero to keep the
|
||||
* number positive. */
|
||||
if (sn[0] & 0x80) {
|
||||
output[1] = snSz + 1;
|
||||
output[2] = 0;
|
||||
XMEMCPY(&output[3], sn, snSz);
|
||||
result = snSz + 3;
|
||||
}
|
||||
else {
|
||||
output[1] = snSz;
|
||||
XMEMCPY(&output[2], sn, snSz);
|
||||
result = snSz + 2;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -131,6 +131,10 @@ static void Usage(void)
|
||||
printf("-z Print structure sizes\n");
|
||||
#endif
|
||||
printf("-S <str> Use Host Name Indication\n");
|
||||
#ifdef HAVE_OCSP
|
||||
printf("-o Perform OCSP lookup on peer certificate\n");
|
||||
printf("-O <url> Perform OCSP lookup using <url> as responder\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CYASSL_MDK_SHELL
|
||||
@ -186,6 +190,11 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
|
||||
char* sniHostName = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OCSP
|
||||
int useOcsp = 0;
|
||||
char* ocspUrl = NULL;
|
||||
#endif
|
||||
|
||||
int argc = ((func_args*)args)->argc;
|
||||
char** argv = ((func_args*)args)->argv;
|
||||
|
||||
@ -203,7 +212,8 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
|
||||
|
||||
StackTrap();
|
||||
|
||||
while ((ch = mygetopt(argc, argv, "?gdusmNrtfxh:p:v:l:A:c:k:b:zS:")) != -1){
|
||||
while ((ch = mygetopt(argc, argv,
|
||||
"?gdusmNrtfxh:p:v:l:A:c:k:b:zS:oO:")) != -1) {
|
||||
switch (ch) {
|
||||
case '?' :
|
||||
Usage();
|
||||
@ -308,6 +318,19 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'o' :
|
||||
#ifdef HAVE_OCSP
|
||||
useOcsp = 1;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'O' :
|
||||
#ifdef HAVE_OCSP
|
||||
useOcsp = 1;
|
||||
ocspUrl = myoptarg;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
Usage();
|
||||
exit(MY_EX_USAGE);
|
||||
@ -429,6 +452,15 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OCSP
|
||||
if (useOcsp) {
|
||||
CyaSSL_CTX_OCSP_set_options(ctx,
|
||||
CYASSL_OCSP_ENABLE | CYASSL_OCSP_NO_NONCE);
|
||||
if (ocspUrl != NULL)
|
||||
CyaSSL_CTX_OCSP_set_override_url(ctx, ocspUrl);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USER_CA_CB
|
||||
CyaSSL_CTX_SetCACb(ctx, CaCb);
|
||||
#endif
|
||||
|
@ -123,6 +123,10 @@ static void Usage(void)
|
||||
printf("-f Fewer packets/group messages\n");
|
||||
printf("-N Use Non-blocking sockets\n");
|
||||
printf("-S <str> Use Host Name Indication\n");
|
||||
#ifdef HAVE_OCSP
|
||||
printf("-o Perform OCSP lookup on peer certificate\n");
|
||||
printf("-O <url> Perform OCSP lookup using <url> as responder\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CYASSL_MDK_SHELL
|
||||
@ -164,6 +168,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
||||
char* sniHostName = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OCSP
|
||||
int useOcsp = 0;
|
||||
char* ocspUrl = NULL;
|
||||
#endif
|
||||
|
||||
((func_args*)args)->return_code = -1; /* error state */
|
||||
|
||||
#ifdef NO_RSA
|
||||
@ -173,7 +182,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
||||
#endif
|
||||
(void)trackMemory;
|
||||
|
||||
while ((ch = mygetopt(argc, argv, "?dbstnNufp:v:l:A:c:k:S:")) != -1) {
|
||||
while ((ch = mygetopt(argc, argv, "?dbstnNufp:v:l:A:c:k:S:oO:")) != -1) {
|
||||
switch (ch) {
|
||||
case '?' :
|
||||
Usage();
|
||||
@ -251,6 +260,19 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'o' :
|
||||
#ifdef HAVE_OCSP
|
||||
useOcsp = 1;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'O' :
|
||||
#ifdef HAVE_OCSP
|
||||
useOcsp = 1;
|
||||
ocspUrl = myoptarg;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
Usage();
|
||||
exit(MY_EX_USAGE);
|
||||
@ -424,6 +446,15 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args)
|
||||
CYASSL_CRL_START_MON);
|
||||
CyaSSL_SetCRL_Cb(ssl, CRL_CallBack);
|
||||
#endif
|
||||
#ifdef HAVE_OCSP
|
||||
if (useOcsp) {
|
||||
CyaSSL_CTX_OCSP_set_options(ctx,
|
||||
CYASSL_OCSP_ENABLE | CYASSL_OCSP_NO_NONCE);
|
||||
if (ocspUrl != NULL)
|
||||
CyaSSL_CTX_OCSP_set_override_url(ctx, ocspUrl);
|
||||
}
|
||||
#endif
|
||||
|
||||
tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr, doDTLS);
|
||||
if (!doDTLS)
|
||||
CloseSocket(sockfd);
|
||||
|
192
src/io.c
192
src/io.c
@ -562,69 +562,6 @@ static int build_http_request(const char* domainName, const char* path,
|
||||
}
|
||||
|
||||
|
||||
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 (XSTRNCASECMP(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 (XSTRNCASECMP(&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 &&
|
||||
XSTRNCASECMP(&buf[idx], "Content-Type:", 13) == 0) {
|
||||
idx += 13;
|
||||
if (buf[idx] == ' ') idx++;
|
||||
if (XSTRNCASECMP(&buf[idx],
|
||||
"application/ocsp-response", 25) != 0) {
|
||||
return 0;
|
||||
}
|
||||
idx += 27;
|
||||
}
|
||||
else if (contentLength == NULL &&
|
||||
XSTRNCASECMP(&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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
*dst = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_IN_BUFFER);
|
||||
XMEMCPY(*dst, httpBuf + idx, len);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int decode_url(const char* url, int urlSz,
|
||||
char* outName, char* outPath, int* outPort)
|
||||
{
|
||||
@ -694,7 +631,124 @@ static int decode_url(const char* url, int urlSz,
|
||||
}
|
||||
|
||||
|
||||
#define SCRATCH_BUFFER_SIZE 2048
|
||||
/* 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, httpBuf+len, httpBufSz-len-1, 0);
|
||||
if (result > 0) {
|
||||
len += result;
|
||||
start = (char*)httpBuf;
|
||||
start[len+1] = 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 -= end - start + 2;
|
||||
|
||||
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 = 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, 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;
|
||||
}
|
||||
|
||||
|
||||
#define SCRATCH_BUFFER_SIZE 512
|
||||
|
||||
int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
|
||||
byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf)
|
||||
@ -721,6 +775,8 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Note, the library uses the EmbedOcspRespFree() callback to
|
||||
* free this buffer. */
|
||||
httpBufSz = SCRATCH_BUFFER_SIZE;
|
||||
httpBuf = (byte*)XMALLOC(httpBufSz, NULL, DYNAMIC_TYPE_IN_BUFFER);
|
||||
|
||||
@ -728,7 +784,6 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
|
||||
CYASSL_MSG("Unable to create OCSP response buffer");
|
||||
return -1;
|
||||
}
|
||||
*ocspRespBuf = httpBuf;
|
||||
|
||||
httpBufSz = build_http_request(domainName, path, ocspReqSz,
|
||||
httpBuf, httpBufSz);
|
||||
@ -739,11 +794,8 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz,
|
||||
if (written == httpBufSz) {
|
||||
written = (int)send(sfd, ocspReqBuf, ocspReqSz, 0);
|
||||
if (written == ocspReqSz) {
|
||||
httpBufSz = (int)recv(sfd, httpBuf, SCRATCH_BUFFER_SIZE, 0);
|
||||
if (httpBufSz > 0) {
|
||||
ocspRespSz = decode_http_response(httpBuf, httpBufSz,
|
||||
ocspRespBuf);
|
||||
}
|
||||
ocspRespSz = process_http_response(sfd, ocspRespBuf,
|
||||
httpBuf, SCRATCH_BUFFER_SIZE);
|
||||
}
|
||||
}
|
||||
close(sfd);
|
||||
|
@ -283,7 +283,7 @@ int CyaSSL_OCSP_Lookup_Cert(CYASSL_OCSP* ocsp, DecodedCert* cert)
|
||||
else
|
||||
return OCSP_NEED_URL;
|
||||
}
|
||||
else if (cert->extAuthInfoSz == 0 || cert->extAuthInfo == NULL) {
|
||||
else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) {
|
||||
url = (const char *)cert->extAuthInfo;
|
||||
urlSz = cert->extAuthInfoSz;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user