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