summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ocsp/ocsp_ht.c
diff options
context:
space:
mode:
authormiod <>2014-05-17 19:56:35 +0000
committermiod <>2014-05-17 19:56:35 +0000
commit0800c7660118a9e5105bd591666d930d899d0b8c (patch)
treef2d366a23c3131d80591bf9c5de711d2e70b4b6e /src/lib/libcrypto/ocsp/ocsp_ht.c
parente9f9678d1aba19f14521109f545f7847365c2f85 (diff)
downloadopenbsd-0800c7660118a9e5105bd591666d930d899d0b8c.tar.gz
openbsd-0800c7660118a9e5105bd591666d930d899d0b8c.tar.bz2
openbsd-0800c7660118a9e5105bd591666d930d899d0b8c.zip
KNF
Diffstat (limited to '')
-rw-r--r--src/lib/libcrypto/ocsp/ocsp_ht.c275
1 files changed, 113 insertions, 162 deletions
diff --git a/src/lib/libcrypto/ocsp/ocsp_ht.c b/src/lib/libcrypto/ocsp/ocsp_ht.c
index b45eaf6767..fe4a7a1a72 100644
--- a/src/lib/libcrypto/ocsp/ocsp_ht.c
+++ b/src/lib/libcrypto/ocsp/ocsp_ht.c
@@ -79,7 +79,7 @@ struct ocsp_req_ctx_st {
79 BIO *io; /* BIO to perform I/O with */ 79 BIO *io; /* BIO to perform I/O with */
80 BIO *mem; /* Memory BIO response is built into */ 80 BIO *mem; /* Memory BIO response is built into */
81 unsigned long asn1_len; /* ASN1 length of response */ 81 unsigned long asn1_len; /* ASN1 length of response */
82 }; 82};
83 83
84#define OCSP_MAX_REQUEST_LENGTH (100 * 1024) 84#define OCSP_MAX_REQUEST_LENGTH (100 * 1024)
85#define OCSP_MAX_LINE_LEN 4096; 85#define OCSP_MAX_LINE_LEN 4096;
@@ -108,54 +108,57 @@ struct ocsp_req_ctx_st {
108 108
109static int parse_http_line1(char *line); 109static int parse_http_line1(char *line);
110 110
111void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx) 111void
112 { 112OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx)
113{
113 if (rctx->mem) 114 if (rctx->mem)
114 BIO_free(rctx->mem); 115 BIO_free(rctx->mem);
115 if (rctx->iobuf) 116 if (rctx->iobuf)
116 free(rctx->iobuf); 117 free(rctx->iobuf);
117 free(rctx); 118 free(rctx);
118 } 119}
119 120
120int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req) 121int
121 { 122OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req)
123{
122 static const char req_hdr[] = 124 static const char req_hdr[] =
123 "Content-Type: application/ocsp-request\r\n" 125 "Content-Type: application/ocsp-request\r\n"
124 "Content-Length: %d\r\n\r\n"; 126 "Content-Length: %d\r\n\r\n";
125 if (BIO_printf(rctx->mem, req_hdr, i2d_OCSP_REQUEST(req, NULL)) <= 0) 127
128 if (BIO_printf(rctx->mem, req_hdr, i2d_OCSP_REQUEST(req, NULL)) <= 0)
126 return 0; 129 return 0;
127 if (i2d_OCSP_REQUEST_bio(rctx->mem, req) <= 0) 130 if (i2d_OCSP_REQUEST_bio(rctx->mem, req) <= 0)
128 return 0; 131 return 0;
129 rctx->state = OHS_ASN1_WRITE; 132 rctx->state = OHS_ASN1_WRITE;
130 rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL); 133 rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL);
131 return 1; 134 return 1;
132 } 135}
133 136
134int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, 137int
135 const char *name, const char *value) 138OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, const char *name,
136 { 139 const char *value)
140{
137 if (!name) 141 if (!name)
138 return 0; 142 return 0;
139 if (BIO_puts(rctx->mem, name) <= 0) 143 if (BIO_puts(rctx->mem, name) <= 0)
140 return 0; 144 return 0;
141 if (value) 145 if (value) {
142 {
143 if (BIO_write(rctx->mem, ": ", 2) != 2) 146 if (BIO_write(rctx->mem, ": ", 2) != 2)
144 return 0; 147 return 0;
145 if (BIO_puts(rctx->mem, value) <= 0) 148 if (BIO_puts(rctx->mem, value) <= 0)
146 return 0; 149 return 0;
147 } 150 }
148 if (BIO_write(rctx->mem, "\r\n", 2) != 2) 151 if (BIO_write(rctx->mem, "\r\n", 2) != 2)
149 return 0; 152 return 0;
150 return 1; 153 return 1;
151 } 154}
152 155
153OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req, 156OCSP_REQ_CTX *
154 int maxline) 157OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req, int maxline)
155 { 158{
156 static const char post_hdr[] = "POST %s HTTP/1.0\r\n"; 159 static const char post_hdr[] = "POST %s HTTP/1.0\r\n";
157
158 OCSP_REQ_CTX *rctx; 160 OCSP_REQ_CTX *rctx;
161
159 rctx = malloc(sizeof(OCSP_REQ_CTX)); 162 rctx = malloc(sizeof(OCSP_REQ_CTX));
160 rctx->state = OHS_ERROR; 163 rctx->state = OHS_ERROR;
161 rctx->mem = BIO_new(BIO_s_mem()); 164 rctx->mem = BIO_new(BIO_s_mem());
@@ -174,7 +177,7 @@ OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req,
174 if (!path) 177 if (!path)
175 path = "/"; 178 path = "/";
176 179
177 if (BIO_printf(rctx->mem, post_hdr, path) <= 0) { 180 if (BIO_printf(rctx->mem, post_hdr, path) <= 0) {
178 free(rctx->iobuf); 181 free(rctx->iobuf);
179 BIO_free(rctx->mem); 182 BIO_free(rctx->mem);
180 free(rctx); 183 free(rctx);
@@ -189,49 +192,44 @@ OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, char *path, OCSP_REQUEST *req,
189 } 192 }
190 193
191 return rctx; 194 return rctx;
192 } 195}
193 196
194/* Parse the HTTP response. This will look like this: 197/* Parse the HTTP response. This will look like this:
195 * "HTTP/1.0 200 OK". We need to obtain the numeric code and 198 * "HTTP/1.0 200 OK". We need to obtain the numeric code and
196 * (optional) informational message. 199 * (optional) informational message.
197 */ 200 */
198 201static int
199static int parse_http_line1(char *line) 202parse_http_line1(char *line)
200 { 203{
201 int retcode; 204 int retcode;
202 char *p, *q, *r; 205 char *p, *q, *r;
203 /* Skip to first white space (passed protocol info) */
204 206
205 for(p = line; *p && !isspace((unsigned char)*p); p++) 207 /* Skip to first white space (passed protocol info) */
208 for (p = line; *p && !isspace((unsigned char)*p); p++)
206 continue; 209 continue;
207 if(!*p) 210 if (!*p) {
208 {
209 OCSPerr(OCSP_F_PARSE_HTTP_LINE1, 211 OCSPerr(OCSP_F_PARSE_HTTP_LINE1,
210 OCSP_R_SERVER_RESPONSE_PARSE_ERROR); 212 OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
211 return 0; 213 return 0;
212 } 214 }
213 215
214 /* Skip past white space to start of response code */ 216 /* Skip past white space to start of response code */
215 while(*p && isspace((unsigned char)*p)) 217 while (*p && isspace((unsigned char)*p))
216 p++; 218 p++;
217 219 if (!*p) {
218 if(!*p)
219 {
220 OCSPerr(OCSP_F_PARSE_HTTP_LINE1, 220 OCSPerr(OCSP_F_PARSE_HTTP_LINE1,
221 OCSP_R_SERVER_RESPONSE_PARSE_ERROR); 221 OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
222 return 0; 222 return 0;
223 } 223 }
224 224
225 /* Find end of response code: first whitespace after start of code */ 225 /* Find end of response code: first whitespace after start of code */
226 for(q = p; *q && !isspace((unsigned char)*q); q++) 226 for (q = p; *q && !isspace((unsigned char)*q); q++)
227 continue; 227 continue;
228 228 if (!*q) {
229 if(!*q)
230 {
231 OCSPerr(OCSP_F_PARSE_HTTP_LINE1, 229 OCSPerr(OCSP_F_PARSE_HTTP_LINE1,
232 OCSP_R_SERVER_RESPONSE_PARSE_ERROR); 230 OCSP_R_SERVER_RESPONSE_PARSE_ERROR);
233 return 0; 231 return 0;
234 } 232 }
235 233
236 /* Set end of response code and start of message */ 234 /* Set end of response code and start of message */
237 *q++ = 0; 235 *q++ = 0;
@@ -239,94 +237,80 @@ static int parse_http_line1(char *line)
239 /* Attempt to parse numeric code */ 237 /* Attempt to parse numeric code */
240 retcode = strtoul(p, &r, 10); 238 retcode = strtoul(p, &r, 10);
241 239
242 if(*r) 240 if (*r)
243 return 0; 241 return 0;
244 242
245 /* Skip over any leading white space in message */ 243 /* Skip over any leading white space in message */
246 while(*q && isspace((unsigned char)*q)) 244 while (*q && isspace((unsigned char)*q))
247 q++; 245 q++;
248 246 if (*q) {
249 if(*q)
250 {
251 /* Finally zap any trailing white space in message (include 247 /* Finally zap any trailing white space in message (include
252 * CRLF) */ 248 * CRLF) */
253 249
254 /* We know q has a non white space character so this is OK */ 250 /* We know q has a non white space character so this is OK */
255 for(r = q + strlen(q) - 1; isspace((unsigned char)*r); r--) 251 for (r = q + strlen(q) - 1; isspace((unsigned char)*r); r--)
256 *r = 0; 252 *r = 0;
257 } 253 }
258 if(retcode != 200) 254 if (retcode != 200) {
259 {
260 OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_ERROR); 255 OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_ERROR);
261 if(!*q) 256 if (!*q)
262 ERR_asprintf_error_data("Code=%s", p); 257 ERR_asprintf_error_data("Code=%s", p);
263 else 258 else
264 ERR_asprintf_error_data("Code=%s,Reason=%s", p, q); 259 ERR_asprintf_error_data("Code=%s,Reason=%s", p, q);
265 return 0; 260 return 0;
266 } 261 }
267
268 262
269 return 1; 263 return 1;
264}
270 265
271 } 266int
272 267OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx)
273int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx) 268{
274 {
275 int i, n; 269 int i, n;
276 const unsigned char *p; 270 const unsigned char *p;
277 next_io: 271
278 if (!(rctx->state & OHS_NOREAD)) 272next_io:
279 { 273 if (!(rctx->state & OHS_NOREAD)) {
280 n = BIO_read(rctx->io, rctx->iobuf, rctx->iobuflen); 274 n = BIO_read(rctx->io, rctx->iobuf, rctx->iobuflen);
281 275
282 if (n <= 0) 276 if (n <= 0) {
283 {
284 if (BIO_should_retry(rctx->io)) 277 if (BIO_should_retry(rctx->io))
285 return -1; 278 return -1;
286 return 0; 279 return 0;
287 } 280 }
288 281
289 /* Write data to memory BIO */ 282 /* Write data to memory BIO */
290
291 if (BIO_write(rctx->mem, rctx->iobuf, n) != n) 283 if (BIO_write(rctx->mem, rctx->iobuf, n) != n)
292 return 0; 284 return 0;
293 } 285 }
294
295 switch(rctx->state)
296 {
297 286
298 case OHS_ASN1_WRITE: 287 switch (rctx->state) {
288 case OHS_ASN1_WRITE:
299 n = BIO_get_mem_data(rctx->mem, &p); 289 n = BIO_get_mem_data(rctx->mem, &p);
300
301 i = BIO_write(rctx->io, 290 i = BIO_write(rctx->io,
302 p + (n - rctx->asn1_len), rctx->asn1_len); 291 p + (n - rctx->asn1_len), rctx->asn1_len);
303 292 if (i <= 0) {
304 if (i <= 0)
305 {
306 if (BIO_should_retry(rctx->io)) 293 if (BIO_should_retry(rctx->io))
307 return -1; 294 return -1;
308 rctx->state = OHS_ERROR; 295 rctx->state = OHS_ERROR;
309 return 0; 296 return 0;
310 } 297 }
311 298
312 rctx->asn1_len -= i; 299 rctx->asn1_len -= i;
313
314 if (rctx->asn1_len > 0) 300 if (rctx->asn1_len > 0)
315 goto next_io; 301 goto next_io;
316 302
317 rctx->state = OHS_ASN1_FLUSH; 303 rctx->state = OHS_ASN1_FLUSH;
318 304
319 (void)BIO_reset(rctx->mem); 305 (void)BIO_reset(rctx->mem);
306 /* FALLTHROUGH */
320 307
321 case OHS_ASN1_FLUSH: 308 case OHS_ASN1_FLUSH:
322
323 i = BIO_flush(rctx->io); 309 i = BIO_flush(rctx->io);
324 310 if (i > 0) {
325 if (i > 0)
326 {
327 rctx->state = OHS_FIRSTLINE; 311 rctx->state = OHS_FIRSTLINE;
328 goto next_io; 312 goto next_io;
329 } 313 }
330 314
331 if (BIO_should_retry(rctx->io)) 315 if (BIO_should_retry(rctx->io))
332 return -1; 316 return -1;
@@ -334,79 +318,62 @@ int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx)
334 rctx->state = OHS_ERROR; 318 rctx->state = OHS_ERROR;
335 return 0; 319 return 0;
336 320
337 case OHS_ERROR: 321 case OHS_ERROR:
338 return 0; 322 return 0;
339 323
340 case OHS_FIRSTLINE: 324 case OHS_FIRSTLINE:
341 case OHS_HEADERS: 325 case OHS_HEADERS:
342
343 /* Attempt to read a line in */ 326 /* Attempt to read a line in */
344 327next_line:
345 next_line:
346 /* Due to &%^*$" memory BIO behaviour with BIO_gets we 328 /* Due to &%^*$" memory BIO behaviour with BIO_gets we
347 * have to check there's a complete line in there before 329 * have to check there's a complete line in there before
348 * calling BIO_gets or we'll just get a partial read. 330 * calling BIO_gets or we'll just get a partial read.
349 */ 331 */
350 n = BIO_get_mem_data(rctx->mem, &p); 332 n = BIO_get_mem_data(rctx->mem, &p);
351 if ((n <= 0) || !memchr(p, '\n', n)) 333 if ((n <= 0) || !memchr(p, '\n', n)) {
352 { 334 if (n >= rctx->iobuflen) {
353 if (n >= rctx->iobuflen)
354 {
355 rctx->state = OHS_ERROR; 335 rctx->state = OHS_ERROR;
356 return 0; 336 return 0;
357 }
358 goto next_io;
359 } 337 }
338 goto next_io;
339 }
360 n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen); 340 n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen);
361 341 if (n <= 0) {
362 if (n <= 0)
363 {
364 if (BIO_should_retry(rctx->mem)) 342 if (BIO_should_retry(rctx->mem))
365 goto next_io; 343 goto next_io;
366 rctx->state = OHS_ERROR; 344 rctx->state = OHS_ERROR;
367 return 0; 345 return 0;
368 } 346 }
369 347
370 /* Don't allow excessive lines */ 348 /* Don't allow excessive lines */
371 if (n == rctx->iobuflen) 349 if (n == rctx->iobuflen) {
372 {
373 rctx->state = OHS_ERROR; 350 rctx->state = OHS_ERROR;
374 return 0; 351 return 0;
375 } 352 }
376 353
377 /* First line */ 354 /* First line */
378 if (rctx->state == OHS_FIRSTLINE) 355 if (rctx->state == OHS_FIRSTLINE) {
379 { 356 if (parse_http_line1((char *)rctx->iobuf)) {
380 if (parse_http_line1((char *)rctx->iobuf))
381 {
382 rctx->state = OHS_HEADERS; 357 rctx->state = OHS_HEADERS;
383 goto next_line; 358 goto next_line;
384 } 359 } else {
385 else
386 {
387 rctx->state = OHS_ERROR; 360 rctx->state = OHS_ERROR;
388 return 0; 361 return 0;
389 }
390 } 362 }
391 else 363 } else {
392 {
393 /* Look for blank line: end of headers */ 364 /* Look for blank line: end of headers */
394 for (p = rctx->iobuf; *p; p++) 365 for (p = rctx->iobuf; *p; p++) {
395 {
396 if ((*p != '\r') && (*p != '\n')) 366 if ((*p != '\r') && (*p != '\n'))
397 break; 367 break;
398 } 368 }
399 if (*p) 369 if (*p)
400 goto next_line; 370 goto next_line;
401 371
402 rctx->state = OHS_ASN1_HEADER; 372 rctx->state = OHS_ASN1_HEADER;
373 }
374 /* FALLTRHOUGH */
403 375
404 } 376 case OHS_ASN1_HEADER:
405
406 /* Fall thru */
407
408
409 case OHS_ASN1_HEADER:
410 /* Now reading ASN1 header: can read at least 2 bytes which 377 /* Now reading ASN1 header: can read at least 2 bytes which
411 * is enough for ASN1 SEQUENCE header and either length field 378 * is enough for ASN1 SEQUENCE header and either length field
412 * or at least the length of the length field. 379 * or at least the length of the length field.
@@ -416,15 +383,13 @@ int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx)
416 goto next_io; 383 goto next_io;
417 384
418 /* Check it is an ASN1 SEQUENCE */ 385 /* Check it is an ASN1 SEQUENCE */
419 if (*p++ != (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) 386 if (*p++ != (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) {
420 {
421 rctx->state = OHS_ERROR; 387 rctx->state = OHS_ERROR;
422 return 0; 388 return 0;
423 } 389 }
424 390
425 /* Check out length field */ 391 /* Check out length field */
426 if (*p & 0x80) 392 if (*p & 0x80) {
427 {
428 /* If MSB set on initial length octet we can now 393 /* If MSB set on initial length octet we can now
429 * always read 6 octets: make sure we have them. 394 * always read 6 octets: make sure we have them.
430 */ 395 */
@@ -432,78 +397,64 @@ int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx)
432 goto next_io; 397 goto next_io;
433 n = *p & 0x7F; 398 n = *p & 0x7F;
434 /* Not NDEF or excessive length */ 399 /* Not NDEF or excessive length */
435 if (!n || (n > 4)) 400 if (!n || (n > 4)) {
436 {
437 rctx->state = OHS_ERROR; 401 rctx->state = OHS_ERROR;
438 return 0; 402 return 0;
439 } 403 }
440 p++; 404 p++;
441 rctx->asn1_len = 0; 405 rctx->asn1_len = 0;
442 for (i = 0; i < n; i++) 406 for (i = 0; i < n; i++) {
443 {
444 rctx->asn1_len <<= 8; 407 rctx->asn1_len <<= 8;
445 rctx->asn1_len |= *p++; 408 rctx->asn1_len |= *p++;
446 } 409 }
447 410
448 if (rctx->asn1_len > OCSP_MAX_REQUEST_LENGTH) 411 if (rctx->asn1_len > OCSP_MAX_REQUEST_LENGTH) {
449 {
450 rctx->state = OHS_ERROR; 412 rctx->state = OHS_ERROR;
451 return 0; 413 return 0;
452 } 414 }
453 415
454 rctx->asn1_len += n + 2; 416 rctx->asn1_len += n + 2;
455 } 417 } else
456 else
457 rctx->asn1_len = *p + 2; 418 rctx->asn1_len = *p + 2;
458 419
459 rctx->state = OHS_ASN1_CONTENT; 420 rctx->state = OHS_ASN1_CONTENT;
460 421
461 /* Fall thru */ 422 /* FALLTHROUGH */
462 423
463 case OHS_ASN1_CONTENT: 424 case OHS_ASN1_CONTENT:
464 n = BIO_get_mem_data(rctx->mem, &p); 425 n = BIO_get_mem_data(rctx->mem, &p);
465 if (n < (int)rctx->asn1_len) 426 if (n < (int)rctx->asn1_len)
466 goto next_io; 427 goto next_io;
467 428
468
469 *presp = d2i_OCSP_RESPONSE(NULL, &p, rctx->asn1_len); 429 *presp = d2i_OCSP_RESPONSE(NULL, &p, rctx->asn1_len);
470 if (*presp) 430 if (*presp) {
471 {
472 rctx->state = OHS_DONE; 431 rctx->state = OHS_DONE;
473 return 1; 432 return 1;
474 } 433 }
475 434
476 rctx->state = OHS_ERROR; 435 rctx->state = OHS_ERROR;
477 return 0; 436 return 0;
478 437
479 break; 438 case OHS_DONE:
480
481 case OHS_DONE:
482 return 1; 439 return 1;
483 440 }
484 }
485
486
487 441
488 return 0; 442 return 0;
489 443}
490
491 }
492 444
493/* Blocking OCSP request handler: now a special case of non-blocking I/O */ 445/* Blocking OCSP request handler: now a special case of non-blocking I/O */
494 446OCSP_RESPONSE *
495OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req) 447OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req)
496 { 448{
497 OCSP_RESPONSE *resp = NULL; 449 OCSP_RESPONSE *resp = NULL;
498 OCSP_REQ_CTX *ctx; 450 OCSP_REQ_CTX *ctx;
499 int rv; 451 int rv;
500 452
501 ctx = OCSP_sendreq_new(b, path, req, -1); 453 ctx = OCSP_sendreq_new(b, path, req, -1);
502 454
503 do 455 do {
504 {
505 rv = OCSP_sendreq_nbio(&resp, ctx); 456 rv = OCSP_sendreq_nbio(&resp, ctx);
506 } while ((rv == -1) && BIO_should_retry(b)); 457 } while ((rv == -1) && BIO_should_retry(b));
507 458
508 OCSP_REQ_CTX_free(ctx); 459 OCSP_REQ_CTX_free(ctx);
509 460
@@ -511,4 +462,4 @@ OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, char *path, OCSP_REQUEST *req)
511 return resp; 462 return resp;
512 463
513 return NULL; 464 return NULL;
514 } 465}