diff options
Diffstat (limited to 'lib/libcrypto/ocsp/ocsp_ht.c')
-rw-r--r-- | lib/libcrypto/ocsp/ocsp_ht.c | 275 |
1 files changed, 113 insertions, 162 deletions
diff --git a/lib/libcrypto/ocsp/ocsp_ht.c b/lib/libcrypto/ocsp/ocsp_ht.c index b45eaf6767a..fe4a7a1a72d 100644 --- a/lib/libcrypto/ocsp/ocsp_ht.c +++ b/lib/libcrypto/ocsp/ocsp_ht.c @@ -79,7 +79,7 @@ struct ocsp_req_ctx_st { BIO *io; /* BIO to perform I/O with */ BIO *mem; /* Memory BIO response is built into */ unsigned long asn1_len; /* ASN1 length of response */ - }; +}; #define OCSP_MAX_REQUEST_LENGTH (100 * 1024) #define OCSP_MAX_LINE_LEN 4096; @@ -108,54 +108,57 @@ struct ocsp_req_ctx_st { static int parse_http_line1(char *line); -void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx) - { +void +OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx) +{ if (rctx->mem) BIO_free(rctx->mem); if (rctx->iobuf) free(rctx->iobuf); free(rctx); - } +} -int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req) - { +int +OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req) +{ static const char req_hdr[] = - "Content-Type: application/ocsp-request\r\n" - "Content-Length: %d\r\n\r\n"; - if (BIO_printf(rctx->mem, req_hdr, i2d_OCSP_REQUEST(req, NULL)) <= 0) + "Content-Type: application/ocsp-request\r\n" + "Content-Length: %d\r\n\r\n"; + + if (BIO_printf(rctx->mem, req_hdr, i2d_OCSP_REQUEST(req, NULL)) <= 0) return 0; - if (i2d_OCSP_REQUEST_bio(rctx->mem, req) <= 0) + if (i2d_OCSP_REQUEST_bio(rctx->mem, req) <= 0) return 0; rctx->state = OHS_ASN1_WRITE; rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL); return 1; - } +} -int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, - const char *name, const char *value) - { +int +OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, const char *name, + const char *value) +{ if (!name) return 0; if (BIO_puts(rctx->mem, name) <= 0) return 0; - if (value) - { + if (value) { if (BIO_write(rctx->mem, ": ", 2) != 2) return 0; if (BIO_puts(rctx->mem, value) <= 0) return 0; - } + } if (BIO_write(rctx->mem, "\r\n", 2) != 2) return 0; return 1; - } +} -OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req, - int maxline) - { +OCSP_REQ_CTX * +OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req, int maxline) +{ static const char post_hdr[] = "POST %s HTTP/1.0\r\n"; - OCSP_REQ_CTX *rctx; + rctx = malloc(sizeof(OCSP_REQ_CTX)); rctx->state = OHS_ERROR; rctx->mem = BIO_new(BIO_s_mem()); @@ -174,7 +177,7 @@ OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req, if (!path) path = "/"; - if (BIO_printf(rctx->mem, post_hdr, path) <= 0) { + if (BIO_printf(rctx->mem, post_hdr, path) <= 0) { free(rctx->iobuf); BIO_free(rctx->mem); free(rctx); @@ -189,49 +192,44 @@ OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req, } return rctx; - } +} /* Parse the HTTP response. This will look like this: * "HTTP/1.0 200 OK". We need to obtain the numeric code and * (optional) informational message. */ - -static int parse_http_line1(char *line) - { +static int +parse_http_line1(char *line) +{ int retcode; char *p, *q, *r; - /* Skip to first white space (passed protocol info) */ - for(p = line; *p && !isspace((unsigned char)*p); p++) + /* Skip to first white space (passed protocol info) */ + for (p = line; *p && !isspace((unsigned char)*p); p++) continue; - if(!*p) - { + if (!*p) { OCSPerr(OCSP_F_PARSE_HTTP_LINE1, - OCSP_R_SERVER_RESPONSE_PARSE_ERROR); + OCSP_R_SERVER_RESPONSE_PARSE_ERROR); return 0; - } + } /* Skip past white space to start of response code */ - while(*p && isspace((unsigned char)*p)) + while (*p && isspace((unsigned char)*p)) p++; - - if(!*p) - { + if (!*p) { OCSPerr(OCSP_F_PARSE_HTTP_LINE1, - OCSP_R_SERVER_RESPONSE_PARSE_ERROR); + OCSP_R_SERVER_RESPONSE_PARSE_ERROR); return 0; - } + } /* Find end of response code: first whitespace after start of code */ - for(q = p; *q && !isspace((unsigned char)*q); q++) + for (q = p; *q && !isspace((unsigned char)*q); q++) continue; - - if(!*q) - { + if (!*q) { OCSPerr(OCSP_F_PARSE_HTTP_LINE1, - OCSP_R_SERVER_RESPONSE_PARSE_ERROR); + OCSP_R_SERVER_RESPONSE_PARSE_ERROR); return 0; - } + } /* Set end of response code and start of message */ *q++ = 0; @@ -239,94 +237,80 @@ static int parse_http_line1(char *line) /* Attempt to parse numeric code */ retcode = strtoul(p, &r, 10); - if(*r) + if (*r) return 0; /* Skip over any leading white space in message */ - while(*q && isspace((unsigned char)*q)) + while (*q && isspace((unsigned char)*q)) q++; - - if(*q) - { + if (*q) { /* Finally zap any trailing white space in message (include * CRLF) */ /* We know q has a non white space character so this is OK */ - for(r = q + strlen(q) - 1; isspace((unsigned char)*r); r--) + for (r = q + strlen(q) - 1; isspace((unsigned char)*r); r--) *r = 0; - } - if(retcode != 200) - { + } + if (retcode != 200) { OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_ERROR); - if(!*q) + if (!*q) ERR_asprintf_error_data("Code=%s", p); else ERR_asprintf_error_data("Code=%s,Reason=%s", p, q); return 0; - } - + } return 1; +} - } - -int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx) - { +int +OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx) +{ int i, n; const unsigned char *p; - next_io: - if (!(rctx->state & OHS_NOREAD)) - { + +next_io: + if (!(rctx->state & OHS_NOREAD)) { n = BIO_read(rctx->io, rctx->iobuf, rctx->iobuflen); - if (n <= 0) - { + if (n <= 0) { if (BIO_should_retry(rctx->io)) return -1; return 0; - } + } /* Write data to memory BIO */ - if (BIO_write(rctx->mem, rctx->iobuf, n) != n) return 0; - } - - switch(rctx->state) - { + } - case OHS_ASN1_WRITE: + switch (rctx->state) { + case OHS_ASN1_WRITE: n = BIO_get_mem_data(rctx->mem, &p); - i = BIO_write(rctx->io, p + (n - rctx->asn1_len), rctx->asn1_len); - - if (i <= 0) - { + if (i <= 0) { if (BIO_should_retry(rctx->io)) return -1; rctx->state = OHS_ERROR; return 0; - } + } rctx->asn1_len -= i; - if (rctx->asn1_len > 0) goto next_io; rctx->state = OHS_ASN1_FLUSH; (void)BIO_reset(rctx->mem); + /* FALLTHROUGH */ - case OHS_ASN1_FLUSH: - + case OHS_ASN1_FLUSH: i = BIO_flush(rctx->io); - - if (i > 0) - { + if (i > 0) { rctx->state = OHS_FIRSTLINE; goto next_io; - } + } if (BIO_should_retry(rctx->io)) return -1; @@ -334,79 +318,62 @@ int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx) rctx->state = OHS_ERROR; return 0; - case OHS_ERROR: + case OHS_ERROR: return 0; - case OHS_FIRSTLINE: - case OHS_HEADERS: - + case OHS_FIRSTLINE: + case OHS_HEADERS: /* Attempt to read a line in */ - - next_line: +next_line: /* Due to &%^*$" memory BIO behaviour with BIO_gets we * have to check there's a complete line in there before * calling BIO_gets or we'll just get a partial read. */ n = BIO_get_mem_data(rctx->mem, &p); - if ((n <= 0) || !memchr(p, '\n', n)) - { - if (n >= rctx->iobuflen) - { + if ((n <= 0) || !memchr(p, '\n', n)) { + if (n >= rctx->iobuflen) { rctx->state = OHS_ERROR; return 0; - } - goto next_io; } + goto next_io; + } n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen); - - if (n <= 0) - { + if (n <= 0) { if (BIO_should_retry(rctx->mem)) goto next_io; rctx->state = OHS_ERROR; return 0; - } + } /* Don't allow excessive lines */ - if (n == rctx->iobuflen) - { + if (n == rctx->iobuflen) { rctx->state = OHS_ERROR; return 0; - } + } /* First line */ - if (rctx->state == OHS_FIRSTLINE) - { - if (parse_http_line1((char *)rctx->iobuf)) - { + if (rctx->state == OHS_FIRSTLINE) { + if (parse_http_line1((char *)rctx->iobuf)) { rctx->state = OHS_HEADERS; goto next_line; - } - else - { + } else { rctx->state = OHS_ERROR; return 0; - } } - else - { + } else { /* Look for blank line: end of headers */ - for (p = rctx->iobuf; *p; p++) - { + for (p = rctx->iobuf; *p; p++) { if ((*p != '\r') && (*p != '\n')) break; - } + } if (*p) goto next_line; rctx->state = OHS_ASN1_HEADER; + } + /* FALLTRHOUGH */ - } - - /* Fall thru */ - - - case OHS_ASN1_HEADER: + case OHS_ASN1_HEADER: /* Now reading ASN1 header: can read at least 2 bytes which * is enough for ASN1 SEQUENCE header and either length field * or at least the length of the length field. @@ -416,15 +383,13 @@ int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx) goto next_io; /* Check it is an ASN1 SEQUENCE */ - if (*p++ != (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) - { + if (*p++ != (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) { rctx->state = OHS_ERROR; return 0; - } + } /* Check out length field */ - if (*p & 0x80) - { + if (*p & 0x80) { /* If MSB set on initial length octet we can now * always read 6 octets: make sure we have them. */ @@ -432,78 +397,64 @@ int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx) goto next_io; n = *p & 0x7F; /* Not NDEF or excessive length */ - if (!n || (n > 4)) - { + if (!n || (n > 4)) { rctx->state = OHS_ERROR; return 0; - } + } p++; rctx->asn1_len = 0; - for (i = 0; i < n; i++) - { + for (i = 0; i < n; i++) { rctx->asn1_len <<= 8; rctx->asn1_len |= *p++; - } + } - if (rctx->asn1_len > OCSP_MAX_REQUEST_LENGTH) - { + if (rctx->asn1_len > OCSP_MAX_REQUEST_LENGTH) { rctx->state = OHS_ERROR; return 0; - } + } rctx->asn1_len += n + 2; - } - else + } else rctx->asn1_len = *p + 2; rctx->state = OHS_ASN1_CONTENT; - /* Fall thru */ + /* FALLTHROUGH */ - case OHS_ASN1_CONTENT: + case OHS_ASN1_CONTENT: n = BIO_get_mem_data(rctx->mem, &p); if (n < (int)rctx->asn1_len) goto next_io; - *presp = d2i_OCSP_RESPONSE(NULL, &p, rctx->asn1_len); - if (*presp) - { + if (*presp) { rctx->state = OHS_DONE; return 1; - } + } rctx->state = OHS_ERROR; return 0; - break; - - case OHS_DONE: + case OHS_DONE: return 1; - - } - - + } return 0; - - - } +} /* Blocking OCSP request handler: now a special case of non-blocking I/O */ - -OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req) - { +OCSP_RESPONSE * +OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req) +{ OCSP_RESPONSE *resp = NULL; OCSP_REQ_CTX *ctx; int rv; ctx = OCSP_sendreq_new(b, path, req, -1); - do - { + do { rv = OCSP_sendreq_nbio(&resp, ctx); - } while ((rv == -1) && BIO_should_retry(b)); + } while ((rv == -1) && BIO_should_retry(b)); OCSP_REQ_CTX_free(ctx); @@ -511,4 +462,4 @@ OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req) return resp; return NULL; - } +} |