1/* 2 * Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10#include "e_os.h" 11#include <stdio.h> 12#include <stdlib.h> 13#include "crypto/ctype.h" 14#include <string.h> 15#include <openssl/asn1.h> 16#include <openssl/ocsp.h> 17#include <openssl/err.h> 18#include <openssl/buffer.h> 19 20/* Stateful OCSP request code, supporting non-blocking I/O */ 21 22/* Opaque OCSP request status structure */ 23 24struct ocsp_req_ctx_st { 25 int state; /* Current I/O state */ 26 unsigned char *iobuf; /* Line buffer */ 27 int iobuflen; /* Line buffer length */ 28 BIO *io; /* BIO to perform I/O with */ 29 BIO *mem; /* Memory BIO response is built into */ 30 unsigned long asn1_len; /* ASN1 length of response */ 31 unsigned long max_resp_len; /* Maximum length of response */ 32}; 33 34#define OCSP_MAX_RESP_LENGTH (100 * 1024) 35#define OCSP_MAX_LINE_LEN 4096; 36 37/* OCSP states */ 38 39/* If set no reading should be performed */ 40#define OHS_NOREAD 0x1000 41/* Error condition */ 42#define OHS_ERROR (0 | OHS_NOREAD) 43/* First line being read */ 44#define OHS_FIRSTLINE 1 45/* MIME headers being read */ 46#define OHS_HEADERS 2 47/* OCSP initial header (tag + length) being read */ 48#define OHS_ASN1_HEADER 3 49/* OCSP content octets being read */ 50#define OHS_ASN1_CONTENT 4 51/* First call: ready to start I/O */ 52#define OHS_ASN1_WRITE_INIT (5 | OHS_NOREAD) 53/* Request being sent */ 54#define OHS_ASN1_WRITE (6 | OHS_NOREAD) 55/* Request being flushed */ 56#define OHS_ASN1_FLUSH (7 | OHS_NOREAD) 57/* Completed */ 58#define OHS_DONE (8 | OHS_NOREAD) 59/* Headers set, no final \r\n included */ 60#define OHS_HTTP_HEADER (9 | OHS_NOREAD) 61 62static int parse_http_line1(char *line); 63 64OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline) 65{ 66 OCSP_REQ_CTX *rctx = OPENSSL_zalloc(sizeof(*rctx)); 67 68 if (rctx == NULL) 69 return NULL; 70 rctx->state = OHS_ERROR; 71 rctx->max_resp_len = OCSP_MAX_RESP_LENGTH; 72 rctx->mem = BIO_new(BIO_s_mem()); 73 rctx->io = io; 74 if (maxline > 0) 75 rctx->iobuflen = maxline; 76 else 77 rctx->iobuflen = OCSP_MAX_LINE_LEN; 78 rctx->iobuf = OPENSSL_malloc(rctx->iobuflen); 79 if (rctx->iobuf == NULL || rctx->mem == NULL) { 80 OCSP_REQ_CTX_free(rctx); 81 return NULL; 82 } 83 return rctx; 84} 85 86void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx) 87{ 88 if (!rctx) 89 return; 90 BIO_free(rctx->mem); 91 OPENSSL_free(rctx->iobuf); 92 OPENSSL_free(rctx); 93} 94 95BIO *OCSP_REQ_CTX_get0_mem_bio(OCSP_REQ_CTX *rctx) 96{ 97 return rctx->mem; 98} 99 100void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len) 101{ 102 if (len == 0) 103 rctx->max_resp_len = OCSP_MAX_RESP_LENGTH; 104 else 105 rctx->max_resp_len = len; 106} 107 108int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it, ASN1_VALUE *val) 109{ 110 static const char req_hdr[] = 111 "Content-Type: application/ocsp-request\r\n" 112 "Content-Length: %d\r\n\r\n"; 113 int reqlen = ASN1_item_i2d(val, NULL, it); 114 if (BIO_printf(rctx->mem, req_hdr, reqlen) <= 0) 115 return 0; 116 if (ASN1_item_i2d_bio(it, rctx->mem, val) <= 0) 117 return 0; 118 rctx->state = OHS_ASN1_WRITE_INIT; 119 return 1; 120} 121 122int OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx, 123 ASN1_VALUE **pval, const ASN1_ITEM *it) 124{ 125 int rv, len; 126 const unsigned char *p; 127 128 rv = OCSP_REQ_CTX_nbio(rctx); 129 if (rv != 1) 130 return rv; 131 132 len = BIO_get_mem_data(rctx->mem, &p); 133 *pval = ASN1_item_d2i(NULL, &p, len, it); 134 if (*pval == NULL) { 135 rctx->state = OHS_ERROR; 136 return 0; 137 } 138 return 1; 139} 140 141int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx, const char *op, const char *path) 142{ 143 static const char http_hdr[] = "%s %s HTTP/1.0\r\n"; 144 145 if (!path) 146 path = "/"; 147 148 if (BIO_printf(rctx->mem, http_hdr, op, path) <= 0) 149 return 0; 150 rctx->state = OHS_HTTP_HEADER; 151 return 1; 152} 153 154int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req) 155{ 156 return OCSP_REQ_CTX_i2d(rctx, ASN1_ITEM_rptr(OCSP_REQUEST), 157 (ASN1_VALUE *)req); 158} 159 160int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, 161 const char *name, const char *value) 162{ 163 if (!name) 164 return 0; 165 if (BIO_puts(rctx->mem, name) <= 0) 166 return 0; 167 if (value) { 168 if (BIO_write(rctx->mem, ": ", 2) != 2) 169 return 0; 170 if (BIO_puts(rctx->mem, value) <= 0) 171 return 0; 172 } 173 if (BIO_write(rctx->mem, "\r\n", 2) != 2) 174 return 0; 175 rctx->state = OHS_HTTP_HEADER; 176 return 1; 177} 178 179OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req, 180 int maxline) 181{ 182 183 OCSP_REQ_CTX *rctx = NULL; 184 rctx = OCSP_REQ_CTX_new(io, maxline); 185 if (rctx == NULL) 186 return NULL; 187 188 if (!OCSP_REQ_CTX_http(rctx, "POST", path)) 189 goto err; 190 191 if (req && !OCSP_REQ_CTX_set1_req(rctx, req)) 192 goto err; 193 194 return rctx; 195 196 err: 197 OCSP_REQ_CTX_free(rctx); 198 return NULL; 199} 200 201/* 202 * Parse the HTTP response. This will look like this: "HTTP/1.0 200 OK". We 203 * need to obtain the numeric code and (optional) informational message. 204 */ 205 206static int parse_http_line1(char *line) 207{ 208 int retcode; 209 char *p, *q, *r; 210 /* Skip to first white space (passed protocol info) */ 211 212 for (p = line; *p && !ossl_isspace(*p); p++) 213 continue; 214 if (!*p) { 215 OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR); 216 return 0; 217 } 218 219 /* Skip past white space to start of response code */ 220 while (*p && ossl_isspace(*p)) 221 p++; 222 223 if (!*p) { 224 OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR); 225 return 0; 226 } 227 228 /* Find end of response code: first whitespace after start of code */ 229 for (q = p; *q && !ossl_isspace(*q); q++) 230 continue; 231 232 if (!*q) { 233 OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR); 234 return 0; 235 } 236 237 /* Set end of response code and start of message */ 238 *q++ = 0; 239 240 /* Attempt to parse numeric code */ 241 retcode = strtoul(p, &r, 10); 242 243 if (*r) 244 return 0; 245 246 /* Skip over any leading white space in message */ 247 while (*q && ossl_isspace(*q)) 248 q++; 249 250 if (*q) { 251 /* 252 * Finally zap any trailing white space in message (include CRLF) 253 */ 254 255 /* We know q has a non white space character so this is OK */ 256 for (r = q + strlen(q) - 1; ossl_isspace(*r); r--) 257 *r = 0; 258 } 259 if (retcode != 200) { 260 OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_ERROR); 261 if (!*q) 262 ERR_add_error_data(2, "Code=", p); 263 else 264 ERR_add_error_data(4, "Code=", p, ",Reason=", q); 265 return 0; 266 } 267 268 return 1; 269 270} 271 272int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx) 273{ 274 int i, n; 275 const unsigned char *p; 276 next_io: 277 if (!(rctx->state & OHS_NOREAD)) { 278 n = BIO_read(rctx->io, rctx->iobuf, rctx->iobuflen); 279 280 if (n <= 0) { 281 if (BIO_should_retry(rctx->io)) 282 return -1; 283 return 0; 284 } 285 286 /* Write data to memory BIO */ 287 288 if (BIO_write(rctx->mem, rctx->iobuf, n) != n) 289 return 0; 290 } 291 292 switch (rctx->state) { 293 case OHS_HTTP_HEADER: 294 /* Last operation was adding headers: need a final \r\n */ 295 if (BIO_write(rctx->mem, "\r\n", 2) != 2) { 296 rctx->state = OHS_ERROR; 297 return 0; 298 } 299 rctx->state = OHS_ASN1_WRITE_INIT; 300 301 /* fall thru */ 302 case OHS_ASN1_WRITE_INIT: 303 rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL); 304 rctx->state = OHS_ASN1_WRITE; 305 306 /* fall thru */ 307 case OHS_ASN1_WRITE: 308 n = BIO_get_mem_data(rctx->mem, &p); 309 310 i = BIO_write(rctx->io, p + (n - rctx->asn1_len), rctx->asn1_len); 311 312 if (i <= 0) { 313 if (BIO_should_retry(rctx->io)) 314 return -1; 315 rctx->state = OHS_ERROR; 316 return 0; 317 } 318 319 rctx->asn1_len -= i; 320 321 if (rctx->asn1_len > 0) 322 goto next_io; 323 324 rctx->state = OHS_ASN1_FLUSH; 325 326 (void)BIO_reset(rctx->mem); 327 328 /* fall thru */ 329 case OHS_ASN1_FLUSH: 330 331 i = BIO_flush(rctx->io); 332 333 if (i > 0) { 334 rctx->state = OHS_FIRSTLINE; 335 goto next_io; 336 } 337 338 if (BIO_should_retry(rctx->io)) 339 return -1; 340 341 rctx->state = OHS_ERROR; 342 return 0; 343 344 case OHS_ERROR: 345 return 0; 346 347 case OHS_FIRSTLINE: 348 case OHS_HEADERS: 349 350 /* Attempt to read a line in */ 351 352 next_line: 353 /* 354 * Due to &%^*$" memory BIO behaviour with BIO_gets we have to check 355 * there's a complete line in there before calling BIO_gets or we'll 356 * just get a partial read. 357 */ 358 n = BIO_get_mem_data(rctx->mem, &p); 359 if ((n <= 0) || !memchr(p, '\n', n)) { 360 if (n >= rctx->iobuflen) { 361 rctx->state = OHS_ERROR; 362 return 0; 363 } 364 goto next_io; 365 } 366 n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen); 367 368 if (n <= 0) { 369 if (BIO_should_retry(rctx->mem)) 370 goto next_io; 371 rctx->state = OHS_ERROR; 372 return 0; 373 } 374 375 /* Don't allow excessive lines */ 376 if (n == rctx->iobuflen) { 377 rctx->state = OHS_ERROR; 378 return 0; 379 } 380 381 /* First line */ 382 if (rctx->state == OHS_FIRSTLINE) { 383 if (parse_http_line1((char *)rctx->iobuf)) { 384 rctx->state = OHS_HEADERS; 385 goto next_line; 386 } else { 387 rctx->state = OHS_ERROR; 388 return 0; 389 } 390 } else { 391 /* Look for blank line: end of headers */ 392 for (p = rctx->iobuf; *p; p++) { 393 if ((*p != '\r') && (*p != '\n')) 394 break; 395 } 396 if (*p) 397 goto next_line; 398 399 rctx->state = OHS_ASN1_HEADER; 400 401 } 402 403 /* Fall thru */ 404 405 case OHS_ASN1_HEADER: 406 /* 407 * Now reading ASN1 header: can read at least 2 bytes which is enough 408 * for ASN1 SEQUENCE header and either length field or at least the 409 * length of the length field. 410 */ 411 n = BIO_get_mem_data(rctx->mem, &p); 412 if (n < 2) 413 goto next_io; 414 415 /* Check it is an ASN1 SEQUENCE */ 416 if (*p++ != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) { 417 rctx->state = OHS_ERROR; 418 return 0; 419 } 420 421 /* Check out length field */ 422 if (*p & 0x80) { 423 /* 424 * If MSB set on initial length octet we can now always read 6 425 * octets: make sure we have them. 426 */ 427 if (n < 6) 428 goto next_io; 429 n = *p & 0x7F; 430 /* Not NDEF or excessive length */ 431 if (!n || (n > 4)) { 432 rctx->state = OHS_ERROR; 433 return 0; 434 } 435 p++; 436 rctx->asn1_len = 0; 437 for (i = 0; i < n; i++) { 438 rctx->asn1_len <<= 8; 439 rctx->asn1_len |= *p++; 440 } 441 442 if (rctx->asn1_len > rctx->max_resp_len) { 443 rctx->state = OHS_ERROR; 444 return 0; 445 } 446 447 rctx->asn1_len += n + 2; 448 } else 449 rctx->asn1_len = *p + 2; 450 451 rctx->state = OHS_ASN1_CONTENT; 452 453 /* Fall thru */ 454 455 case OHS_ASN1_CONTENT: 456 n = BIO_get_mem_data(rctx->mem, NULL); 457 if (n < (int)rctx->asn1_len) 458 goto next_io; 459 460 rctx->state = OHS_DONE; 461 return 1; 462 463 case OHS_DONE: 464 return 1; 465 466 } 467 468 return 0; 469 470} 471 472int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx) 473{ 474 return OCSP_REQ_CTX_nbio_d2i(rctx, 475 (ASN1_VALUE **)presp, 476 ASN1_ITEM_rptr(OCSP_RESPONSE)); 477} 478 479/* Blocking OCSP request handler: now a special case of non-blocking I/O */ 480 481OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req) 482{ 483 OCSP_RESPONSE *resp = NULL; 484 OCSP_REQ_CTX *ctx; 485 int rv; 486 487 ctx = OCSP_sendreq_new(b, path, req, -1); 488 489 if (ctx == NULL) 490 return NULL; 491 492 do { 493 rv = OCSP_sendreq_nbio(&resp, ctx); 494 } while ((rv == -1) && BIO_should_retry(b)); 495 496 OCSP_REQ_CTX_free(ctx); 497 498 if (rv) 499 return resp; 500 501 return NULL; 502} 503