/src/openssl/crypto/ocsp/ocsp_ht.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* ocsp_ht.c */ |
2 | | /* |
3 | | * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project |
4 | | * 2006. |
5 | | */ |
6 | | /* ==================================================================== |
7 | | * Copyright (c) 2006 The OpenSSL Project. All rights reserved. |
8 | | * |
9 | | * Redistribution and use in source and binary forms, with or without |
10 | | * modification, are permitted provided that the following conditions |
11 | | * are met: |
12 | | * |
13 | | * 1. Redistributions of source code must retain the above copyright |
14 | | * notice, this list of conditions and the following disclaimer. |
15 | | * |
16 | | * 2. Redistributions in binary form must reproduce the above copyright |
17 | | * notice, this list of conditions and the following disclaimer in |
18 | | * the documentation and/or other materials provided with the |
19 | | * distribution. |
20 | | * |
21 | | * 3. All advertising materials mentioning features or use of this |
22 | | * software must display the following acknowledgment: |
23 | | * "This product includes software developed by the OpenSSL Project |
24 | | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" |
25 | | * |
26 | | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
27 | | * endorse or promote products derived from this software without |
28 | | * prior written permission. For written permission, please contact |
29 | | * licensing@OpenSSL.org. |
30 | | * |
31 | | * 5. Products derived from this software may not be called "OpenSSL" |
32 | | * nor may "OpenSSL" appear in their names without prior written |
33 | | * permission of the OpenSSL Project. |
34 | | * |
35 | | * 6. Redistributions of any form whatsoever must retain the following |
36 | | * acknowledgment: |
37 | | * "This product includes software developed by the OpenSSL Project |
38 | | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" |
39 | | * |
40 | | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
41 | | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
42 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
43 | | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
44 | | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
45 | | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
46 | | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
47 | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
49 | | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
50 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
51 | | * OF THE POSSIBILITY OF SUCH DAMAGE. |
52 | | * ==================================================================== |
53 | | * |
54 | | * This product includes cryptographic software written by Eric Young |
55 | | * (eay@cryptsoft.com). This product includes software written by Tim |
56 | | * Hudson (tjh@cryptsoft.com). |
57 | | * |
58 | | */ |
59 | | |
60 | | #include <stdio.h> |
61 | | #include <stdlib.h> |
62 | | #include <ctype.h> |
63 | | #include <string.h> |
64 | | #include "e_os.h" |
65 | | #include <openssl/asn1.h> |
66 | | #include <openssl/ocsp.h> |
67 | | #include <openssl/err.h> |
68 | | #include <openssl/buffer.h> |
69 | | #ifdef OPENSSL_SYS_SUNOS |
70 | | # define strtoul (unsigned long)strtol |
71 | | #endif /* OPENSSL_SYS_SUNOS */ |
72 | | |
73 | | /* Stateful OCSP request code, supporting non-blocking I/O */ |
74 | | |
75 | | /* Opaque OCSP request status structure */ |
76 | | |
77 | | struct ocsp_req_ctx_st { |
78 | | int state; /* Current I/O state */ |
79 | | unsigned char *iobuf; /* Line buffer */ |
80 | | int iobuflen; /* Line buffer length */ |
81 | | BIO *io; /* BIO to perform I/O with */ |
82 | | BIO *mem; /* Memory BIO response is built into */ |
83 | | unsigned long asn1_len; /* ASN1 length of response */ |
84 | | unsigned long max_resp_len; /* Maximum length of response */ |
85 | | }; |
86 | | |
87 | 0 | #define OCSP_MAX_RESP_LENGTH (100 * 1024) |
88 | 0 | #define OCSP_MAX_LINE_LEN 4096; |
89 | | |
90 | | /* OCSP states */ |
91 | | |
92 | | /* If set no reading should be performed */ |
93 | 0 | #define OHS_NOREAD 0x1000 |
94 | | /* Error condition */ |
95 | 0 | #define OHS_ERROR (0 | OHS_NOREAD) |
96 | | /* First line being read */ |
97 | 0 | #define OHS_FIRSTLINE 1 |
98 | | /* MIME headers being read */ |
99 | 0 | #define OHS_HEADERS 2 |
100 | | /* OCSP initial header (tag + length) being read */ |
101 | 0 | #define OHS_ASN1_HEADER 3 |
102 | | /* OCSP content octets being read */ |
103 | 0 | #define OHS_ASN1_CONTENT 4 |
104 | | /* First call: ready to start I/O */ |
105 | 0 | #define OHS_ASN1_WRITE_INIT (5 | OHS_NOREAD) |
106 | | /* Request being sent */ |
107 | 0 | #define OHS_ASN1_WRITE (6 | OHS_NOREAD) |
108 | | /* Request being flushed */ |
109 | 0 | #define OHS_ASN1_FLUSH (7 | OHS_NOREAD) |
110 | | /* Completed */ |
111 | 0 | #define OHS_DONE (8 | OHS_NOREAD) |
112 | | /* Headers set, no final \r\n included */ |
113 | 0 | #define OHS_HTTP_HEADER (9 | OHS_NOREAD) |
114 | | |
115 | | static int parse_http_line1(char *line); |
116 | | |
117 | | OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline) |
118 | 0 | { |
119 | 0 | OCSP_REQ_CTX *rctx; |
120 | 0 | rctx = OPENSSL_malloc(sizeof(OCSP_REQ_CTX)); |
121 | 0 | if (!rctx) |
122 | 0 | return NULL; |
123 | 0 | rctx->state = OHS_ERROR; |
124 | 0 | rctx->max_resp_len = OCSP_MAX_RESP_LENGTH; |
125 | 0 | rctx->mem = BIO_new(BIO_s_mem()); |
126 | 0 | rctx->io = io; |
127 | 0 | rctx->asn1_len = 0; |
128 | 0 | if (maxline > 0) |
129 | 0 | rctx->iobuflen = maxline; |
130 | 0 | else |
131 | 0 | rctx->iobuflen = OCSP_MAX_LINE_LEN; |
132 | 0 | rctx->iobuf = OPENSSL_malloc(rctx->iobuflen); |
133 | 0 | if (!rctx->iobuf || !rctx->mem) { |
134 | 0 | OCSP_REQ_CTX_free(rctx); |
135 | 0 | return NULL; |
136 | 0 | } |
137 | 0 | return rctx; |
138 | 0 | } |
139 | | |
140 | | void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx) |
141 | 0 | { |
142 | 0 | if (rctx->mem) |
143 | 0 | BIO_free(rctx->mem); |
144 | 0 | if (rctx->iobuf) |
145 | 0 | OPENSSL_free(rctx->iobuf); |
146 | 0 | OPENSSL_free(rctx); |
147 | 0 | } |
148 | | |
149 | | BIO *OCSP_REQ_CTX_get0_mem_bio(OCSP_REQ_CTX *rctx) |
150 | 0 | { |
151 | 0 | return rctx->mem; |
152 | 0 | } |
153 | | |
154 | | void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len) |
155 | 0 | { |
156 | 0 | if (len == 0) |
157 | 0 | rctx->max_resp_len = OCSP_MAX_RESP_LENGTH; |
158 | 0 | else |
159 | 0 | rctx->max_resp_len = len; |
160 | 0 | } |
161 | | |
162 | | int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it, ASN1_VALUE *val) |
163 | 0 | { |
164 | 0 | static const char req_hdr[] = |
165 | 0 | "Content-Type: application/ocsp-request\r\n" |
166 | 0 | "Content-Length: %d\r\n\r\n"; |
167 | 0 | int reqlen = ASN1_item_i2d(val, NULL, it); |
168 | 0 | if (BIO_printf(rctx->mem, req_hdr, reqlen) <= 0) |
169 | 0 | return 0; |
170 | 0 | if (ASN1_item_i2d_bio(it, rctx->mem, val) <= 0) |
171 | 0 | return 0; |
172 | 0 | rctx->state = OHS_ASN1_WRITE_INIT; |
173 | 0 | return 1; |
174 | 0 | } |
175 | | |
176 | | int OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx, |
177 | | ASN1_VALUE **pval, const ASN1_ITEM *it) |
178 | 0 | { |
179 | 0 | int rv, len; |
180 | 0 | const unsigned char *p; |
181 | |
|
182 | 0 | rv = OCSP_REQ_CTX_nbio(rctx); |
183 | 0 | if (rv != 1) |
184 | 0 | return rv; |
185 | | |
186 | 0 | len = BIO_get_mem_data(rctx->mem, &p); |
187 | 0 | *pval = ASN1_item_d2i(NULL, &p, len, it); |
188 | 0 | if (*pval == NULL) { |
189 | 0 | rctx->state = OHS_ERROR; |
190 | 0 | return 0; |
191 | 0 | } |
192 | 0 | return 1; |
193 | 0 | } |
194 | | |
195 | | int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx, const char *op, const char *path) |
196 | 0 | { |
197 | 0 | static const char http_hdr[] = "%s %s HTTP/1.0\r\n"; |
198 | |
|
199 | 0 | if (!path) |
200 | 0 | path = "/"; |
201 | |
|
202 | 0 | if (BIO_printf(rctx->mem, http_hdr, op, path) <= 0) |
203 | 0 | return 0; |
204 | 0 | rctx->state = OHS_HTTP_HEADER; |
205 | 0 | return 1; |
206 | 0 | } |
207 | | |
208 | | int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req) |
209 | 0 | { |
210 | 0 | return OCSP_REQ_CTX_i2d(rctx, ASN1_ITEM_rptr(OCSP_REQUEST), |
211 | 0 | (ASN1_VALUE *)req); |
212 | 0 | } |
213 | | |
214 | | int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx, |
215 | | const char *name, const char *value) |
216 | 0 | { |
217 | 0 | if (!name) |
218 | 0 | return 0; |
219 | 0 | if (BIO_puts(rctx->mem, name) <= 0) |
220 | 0 | return 0; |
221 | 0 | if (value) { |
222 | 0 | if (BIO_write(rctx->mem, ": ", 2) != 2) |
223 | 0 | return 0; |
224 | 0 | if (BIO_puts(rctx->mem, value) <= 0) |
225 | 0 | return 0; |
226 | 0 | } |
227 | 0 | if (BIO_write(rctx->mem, "\r\n", 2) != 2) |
228 | 0 | return 0; |
229 | 0 | rctx->state = OHS_HTTP_HEADER; |
230 | 0 | return 1; |
231 | 0 | } |
232 | | |
233 | | OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req, |
234 | | int maxline) |
235 | 0 | { |
236 | |
|
237 | 0 | OCSP_REQ_CTX *rctx = NULL; |
238 | 0 | rctx = OCSP_REQ_CTX_new(io, maxline); |
239 | 0 | if (!rctx) |
240 | 0 | return NULL; |
241 | | |
242 | 0 | if (!OCSP_REQ_CTX_http(rctx, "POST", path)) |
243 | 0 | goto err; |
244 | | |
245 | 0 | if (req && !OCSP_REQ_CTX_set1_req(rctx, req)) |
246 | 0 | goto err; |
247 | | |
248 | 0 | return rctx; |
249 | | |
250 | 0 | err: |
251 | 0 | OCSP_REQ_CTX_free(rctx); |
252 | 0 | return NULL; |
253 | 0 | } |
254 | | |
255 | | /* |
256 | | * Parse the HTTP response. This will look like this: "HTTP/1.0 200 OK". We |
257 | | * need to obtain the numeric code and (optional) informational message. |
258 | | */ |
259 | | |
260 | | static int parse_http_line1(char *line) |
261 | 0 | { |
262 | 0 | int retcode; |
263 | 0 | char *p, *q, *r; |
264 | | /* Skip to first white space (passed protocol info) */ |
265 | |
|
266 | 0 | for (p = line; *p && !isspace((unsigned char)*p); p++) |
267 | 0 | continue; |
268 | 0 | if (!*p) { |
269 | 0 | OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR); |
270 | 0 | return 0; |
271 | 0 | } |
272 | | |
273 | | /* Skip past white space to start of response code */ |
274 | 0 | while (*p && isspace((unsigned char)*p)) |
275 | 0 | p++; |
276 | |
|
277 | 0 | if (!*p) { |
278 | 0 | OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR); |
279 | 0 | return 0; |
280 | 0 | } |
281 | | |
282 | | /* Find end of response code: first whitespace after start of code */ |
283 | 0 | for (q = p; *q && !isspace((unsigned char)*q); q++) |
284 | 0 | continue; |
285 | |
|
286 | 0 | if (!*q) { |
287 | 0 | OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_PARSE_ERROR); |
288 | 0 | return 0; |
289 | 0 | } |
290 | | |
291 | | /* Set end of response code and start of message */ |
292 | 0 | *q++ = 0; |
293 | | |
294 | | /* Attempt to parse numeric code */ |
295 | 0 | retcode = strtoul(p, &r, 10); |
296 | |
|
297 | 0 | if (*r) |
298 | 0 | return 0; |
299 | | |
300 | | /* Skip over any leading white space in message */ |
301 | 0 | while (*q && isspace((unsigned char)*q)) |
302 | 0 | q++; |
303 | |
|
304 | 0 | if (*q) { |
305 | | /* |
306 | | * Finally zap any trailing white space in message (include CRLF) |
307 | | */ |
308 | | |
309 | | /* We know q has a non white space character so this is OK */ |
310 | 0 | for (r = q + strlen(q) - 1; isspace((unsigned char)*r); r--) |
311 | 0 | *r = 0; |
312 | 0 | } |
313 | 0 | if (retcode != 200) { |
314 | 0 | OCSPerr(OCSP_F_PARSE_HTTP_LINE1, OCSP_R_SERVER_RESPONSE_ERROR); |
315 | 0 | if (!*q) |
316 | 0 | ERR_add_error_data(2, "Code=", p); |
317 | 0 | else |
318 | 0 | ERR_add_error_data(4, "Code=", p, ",Reason=", q); |
319 | 0 | return 0; |
320 | 0 | } |
321 | | |
322 | 0 | return 1; |
323 | |
|
324 | 0 | } |
325 | | |
326 | | int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx) |
327 | 0 | { |
328 | 0 | int i, n; |
329 | 0 | const unsigned char *p; |
330 | 0 | next_io: |
331 | 0 | if (!(rctx->state & OHS_NOREAD)) { |
332 | 0 | n = BIO_read(rctx->io, rctx->iobuf, rctx->iobuflen); |
333 | |
|
334 | 0 | if (n <= 0) { |
335 | 0 | if (BIO_should_retry(rctx->io)) |
336 | 0 | return -1; |
337 | 0 | return 0; |
338 | 0 | } |
339 | | |
340 | | /* Write data to memory BIO */ |
341 | | |
342 | 0 | if (BIO_write(rctx->mem, rctx->iobuf, n) != n) |
343 | 0 | return 0; |
344 | 0 | } |
345 | | |
346 | 0 | switch (rctx->state) { |
347 | 0 | case OHS_HTTP_HEADER: |
348 | | /* Last operation was adding headers: need a final \r\n */ |
349 | 0 | if (BIO_write(rctx->mem, "\r\n", 2) != 2) { |
350 | 0 | rctx->state = OHS_ERROR; |
351 | 0 | return 0; |
352 | 0 | } |
353 | 0 | rctx->state = OHS_ASN1_WRITE_INIT; |
354 | |
|
355 | 0 | case OHS_ASN1_WRITE_INIT: |
356 | 0 | rctx->asn1_len = BIO_get_mem_data(rctx->mem, NULL); |
357 | 0 | rctx->state = OHS_ASN1_WRITE; |
358 | |
|
359 | 0 | case OHS_ASN1_WRITE: |
360 | 0 | n = BIO_get_mem_data(rctx->mem, &p); |
361 | |
|
362 | 0 | i = BIO_write(rctx->io, p + (n - rctx->asn1_len), rctx->asn1_len); |
363 | |
|
364 | 0 | if (i <= 0) { |
365 | 0 | if (BIO_should_retry(rctx->io)) |
366 | 0 | return -1; |
367 | 0 | rctx->state = OHS_ERROR; |
368 | 0 | return 0; |
369 | 0 | } |
370 | | |
371 | 0 | rctx->asn1_len -= i; |
372 | |
|
373 | 0 | if (rctx->asn1_len > 0) |
374 | 0 | goto next_io; |
375 | | |
376 | 0 | rctx->state = OHS_ASN1_FLUSH; |
377 | |
|
378 | 0 | (void)BIO_reset(rctx->mem); |
379 | |
|
380 | 0 | case OHS_ASN1_FLUSH: |
381 | |
|
382 | 0 | i = BIO_flush(rctx->io); |
383 | |
|
384 | 0 | if (i > 0) { |
385 | 0 | rctx->state = OHS_FIRSTLINE; |
386 | 0 | goto next_io; |
387 | 0 | } |
388 | | |
389 | 0 | if (BIO_should_retry(rctx->io)) |
390 | 0 | return -1; |
391 | | |
392 | 0 | rctx->state = OHS_ERROR; |
393 | 0 | return 0; |
394 | | |
395 | 0 | case OHS_ERROR: |
396 | 0 | return 0; |
397 | | |
398 | 0 | case OHS_FIRSTLINE: |
399 | 0 | case OHS_HEADERS: |
400 | | |
401 | | /* Attempt to read a line in */ |
402 | |
|
403 | 0 | next_line: |
404 | | /* |
405 | | * Due to &%^*$" memory BIO behaviour with BIO_gets we have to check |
406 | | * there's a complete line in there before calling BIO_gets or we'll |
407 | | * just get a partial read. |
408 | | */ |
409 | 0 | n = BIO_get_mem_data(rctx->mem, &p); |
410 | 0 | if ((n <= 0) || !memchr(p, '\n', n)) { |
411 | 0 | if (n >= rctx->iobuflen) { |
412 | 0 | rctx->state = OHS_ERROR; |
413 | 0 | return 0; |
414 | 0 | } |
415 | 0 | goto next_io; |
416 | 0 | } |
417 | 0 | n = BIO_gets(rctx->mem, (char *)rctx->iobuf, rctx->iobuflen); |
418 | |
|
419 | 0 | if (n <= 0) { |
420 | 0 | if (BIO_should_retry(rctx->mem)) |
421 | 0 | goto next_io; |
422 | 0 | rctx->state = OHS_ERROR; |
423 | 0 | return 0; |
424 | 0 | } |
425 | | |
426 | | /* Don't allow excessive lines */ |
427 | 0 | if (n == rctx->iobuflen) { |
428 | 0 | rctx->state = OHS_ERROR; |
429 | 0 | return 0; |
430 | 0 | } |
431 | | |
432 | | /* First line */ |
433 | 0 | if (rctx->state == OHS_FIRSTLINE) { |
434 | 0 | if (parse_http_line1((char *)rctx->iobuf)) { |
435 | 0 | rctx->state = OHS_HEADERS; |
436 | 0 | goto next_line; |
437 | 0 | } else { |
438 | 0 | rctx->state = OHS_ERROR; |
439 | 0 | return 0; |
440 | 0 | } |
441 | 0 | } else { |
442 | | /* Look for blank line: end of headers */ |
443 | 0 | for (p = rctx->iobuf; *p; p++) { |
444 | 0 | if ((*p != '\r') && (*p != '\n')) |
445 | 0 | break; |
446 | 0 | } |
447 | 0 | if (*p) |
448 | 0 | goto next_line; |
449 | | |
450 | 0 | rctx->state = OHS_ASN1_HEADER; |
451 | |
|
452 | 0 | } |
453 | | |
454 | | /* Fall thru */ |
455 | | |
456 | 0 | case OHS_ASN1_HEADER: |
457 | | /* |
458 | | * Now reading ASN1 header: can read at least 2 bytes which is enough |
459 | | * for ASN1 SEQUENCE header and either length field or at least the |
460 | | * length of the length field. |
461 | | */ |
462 | 0 | n = BIO_get_mem_data(rctx->mem, &p); |
463 | 0 | if (n < 2) |
464 | 0 | goto next_io; |
465 | | |
466 | | /* Check it is an ASN1 SEQUENCE */ |
467 | 0 | if (*p++ != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)) { |
468 | 0 | rctx->state = OHS_ERROR; |
469 | 0 | return 0; |
470 | 0 | } |
471 | | |
472 | | /* Check out length field */ |
473 | 0 | if (*p & 0x80) { |
474 | | /* |
475 | | * If MSB set on initial length octet we can now always read 6 |
476 | | * octets: make sure we have them. |
477 | | */ |
478 | 0 | if (n < 6) |
479 | 0 | goto next_io; |
480 | 0 | n = *p & 0x7F; |
481 | | /* Not NDEF or excessive length */ |
482 | 0 | if (!n || (n > 4)) { |
483 | 0 | rctx->state = OHS_ERROR; |
484 | 0 | return 0; |
485 | 0 | } |
486 | 0 | p++; |
487 | 0 | rctx->asn1_len = 0; |
488 | 0 | for (i = 0; i < n; i++) { |
489 | 0 | rctx->asn1_len <<= 8; |
490 | 0 | rctx->asn1_len |= *p++; |
491 | 0 | } |
492 | |
|
493 | 0 | if (rctx->asn1_len > rctx->max_resp_len) { |
494 | 0 | rctx->state = OHS_ERROR; |
495 | 0 | return 0; |
496 | 0 | } |
497 | | |
498 | 0 | rctx->asn1_len += n + 2; |
499 | 0 | } else |
500 | 0 | rctx->asn1_len = *p + 2; |
501 | | |
502 | 0 | rctx->state = OHS_ASN1_CONTENT; |
503 | | |
504 | | /* Fall thru */ |
505 | |
|
506 | 0 | case OHS_ASN1_CONTENT: |
507 | 0 | n = BIO_get_mem_data(rctx->mem, NULL); |
508 | 0 | if (n < (int)rctx->asn1_len) |
509 | 0 | goto next_io; |
510 | | |
511 | 0 | rctx->state = OHS_DONE; |
512 | 0 | return 1; |
513 | | |
514 | 0 | break; |
515 | | |
516 | 0 | case OHS_DONE: |
517 | 0 | return 1; |
518 | |
|
519 | 0 | } |
520 | | |
521 | 0 | return 0; |
522 | |
|
523 | 0 | } |
524 | | |
525 | | int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx) |
526 | 0 | { |
527 | 0 | return OCSP_REQ_CTX_nbio_d2i(rctx, |
528 | 0 | (ASN1_VALUE **)presp, |
529 | 0 | ASN1_ITEM_rptr(OCSP_RESPONSE)); |
530 | 0 | } |
531 | | |
532 | | /* Blocking OCSP request handler: now a special case of non-blocking I/O */ |
533 | | |
534 | | OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req) |
535 | 0 | { |
536 | 0 | OCSP_RESPONSE *resp = NULL; |
537 | 0 | OCSP_REQ_CTX *ctx; |
538 | 0 | int rv; |
539 | |
|
540 | 0 | ctx = OCSP_sendreq_new(b, path, req, -1); |
541 | |
|
542 | 0 | if (!ctx) |
543 | 0 | return NULL; |
544 | | |
545 | 0 | do { |
546 | 0 | rv = OCSP_sendreq_nbio(&resp, ctx); |
547 | 0 | } while ((rv == -1) && BIO_should_retry(b)); |
548 | |
|
549 | 0 | OCSP_REQ_CTX_free(ctx); |
550 | |
|
551 | 0 | if (rv) |
552 | 0 | return resp; |
553 | | |
554 | 0 | return NULL; |
555 | 0 | } |