1 /****************************************************************************
2 * *
3 * cryptlib HTTP Read Routines *
4 * Copyright Peter Gutmann 1998-2014 *
5 * *
6 ****************************************************************************/
7
8 #include <ctype.h>
9 #include <stdio.h>
10 #if defined( INC_ALL )
11 #include "crypt.h"
12 #include "misc_rw.h"
13 #include "http.h"
14 #else
15 #include "crypt.h"
16 #include "enc_dec/misc_rw.h"
17 #include "io/http.h"
18 #endif /* Compiler-specific includes */
19
20 #ifdef USE_HTTP
21
22 /* HTTP request line parsing information */
23
24 typedef struct {
25 BUFFER_FIXED( reqNameLen ) \
26 const char *reqName; /* Request name */
27 int reqNameLen; /* Length of request name */
28 STREAM_HTTPREQTYPE_TYPE reqType; /* Request type */
29 int reqTypeFlag; /* Stream flag for this request type */
30 } HTTP_REQUEST_INFO;
31
32 static const HTTP_REQUEST_INFO FAR_BSS httpReqInfo[] = {
33 { "GET", 3, STREAM_HTTPREQTYPE_GET, STREAM_NFLAG_HTTPGET },
34 { "POST", 4, STREAM_HTTPREQTYPE_POST, STREAM_NFLAG_HTTPPOST },
35 { NULL, 0, 0 }, { NULL, 0, 0 }
36 };
37
38 /****************************************************************************
39 * *
40 * Utility Functions *
41 * *
42 ****************************************************************************/
43
44 /* Callback function used by readTextLine() to read characters from a
45 stream. When reading text data over a network we don't know how much
46 more data is to come so we have to read a byte at a time looking for an
47 EOL. In addition we can't use the simple optimisation of reading two
48 bytes at a time because some servers only send a LF even though the spec
49 requires a CRLF. This is horribly inefficient but is pretty much
50 eliminated through the use of opportunistic read-ahead buffering */
51
52 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
readCharFunction(INOUT TYPECAST (STREAM *)void * streamPtr)53 static int readCharFunction( INOUT TYPECAST( STREAM * ) void *streamPtr )
54 {
55 STREAM *stream = streamPtr;
56 NET_STREAM_INFO *netStream = ( NET_STREAM_INFO * ) stream->netStreamInfo;
57 const STM_BUFFEREDTRANSPORTREAD_FUNCTION bufferedTransportReadFunction = \
58 FNPTR_GET( netStream->bufferedTransportReadFunction );
59 BYTE ch;
60 int length, status;
61
62 assert( isWritePtr( stream, sizeof( STREAM ) ) );
63
64 REQUIRES( bufferedTransportReadFunction != NULL );
65
66 status = bufferedTransportReadFunction( stream, &ch, 1, &length,
67 TRANSPORT_FLAG_NONE );
68 return( cryptStatusError( status ) ? status : ch );
69 }
70
71 /* Clear the HTTP input stream after a soft error has occurred so that
72 further HTTP transactions can be read */
73
74 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
75 static int clearInputStream( INOUT STREAM *stream,
76 OUT_BUFFER_FIXED( lineBufSize ) char *lineBuffer,
77 IN_LENGTH_SHORT_MIN( 256 ) const int lineBufSize )
78 {
79 HTTP_HEADER_INFO headerInfo;
80 BOOLEAN isSoftError;
81
82 assert( isWritePtr( stream, sizeof( STREAM ) ) );
83 assert( isWritePtr( lineBuffer, lineBufSize ) );
84
85 REQUIRES( lineBufSize >= 256 && lineBufSize < MAX_INTLENGTH_SHORT );
86
87 /* Perform a dummy read to clear any remaining HTTP header lines */
88 initHeaderInfo( &headerInfo, 1, 8192, HTTP_FLAG_NOOP );
89 return( readHeaderLines( stream, lineBuffer, lineBufSize,
90 &headerInfo, &isSoftError ) );
91 }
92
93 /****************************************************************************
94 * *
95 * Read Request Header *
96 * *
97 ****************************************************************************/
98
99 /* Read an HTTP request header */
100
101 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \
102 static int readRequestHeader( INOUT STREAM *stream,
103 OUT_BUFFER_FIXED( lineBufSize ) char *lineBuffer,
104 IN_LENGTH_SHORT_MIN( 256 ) const int lineBufSize,
105 INOUT HTTP_DATA_INFO *httpDataInfo,
106 OUT_FLAGS_Z( HTTP ) int *flags )
107 {
108 NET_STREAM_INFO *netStream = ( NET_STREAM_INFO * ) stream->netStreamInfo;
109 HTTP_HEADER_INFO headerInfo;
110 HTTP_URI_INFO *uriInfo = httpDataInfo->reqInfo;
111 STREAM_HTTPREQTYPE_TYPE reqType = STREAM_HTTPREQTYPE_NONE;
112 BOOLEAN isTextDataError, isSoftError;
113 char *bufPtr;
114 int length, offset, reqNameLen DUMMY_INIT, i, status;
115
116 assert( isWritePtr( stream, sizeof( STREAM ) ) );
117 assert( isWritePtr( lineBuffer, lineBufSize ) );
118 assert( isWritePtr( httpDataInfo, sizeof( HTTP_DATA_INFO ) ) );
119 assert( isWritePtr( flags, sizeof( int ) ) );
120
121 REQUIRES( netStream->nFlags & STREAM_NFLAG_ISSERVER );
122 REQUIRES( ( ( netStream->nFlags & STREAM_NFLAG_HTTPGET ) && \
123 uriInfo != NULL ) || \
124 ( !( netStream->nFlags & STREAM_NFLAG_HTTPGET ) && \
125 uriInfo == NULL ) );
126 REQUIRES( lineBufSize >= 256 && lineBufSize < MAX_INTLENGTH_SHORT );
127
128 /* Clear return values */
129 memset( lineBuffer, 0, min( 16, lineBufSize ) );
130 *flags = HTTP_FLAG_NONE;
131
132 /* Read the header and check for "POST/GET x HTTP/1.x". In theory this
133 could be a bit risky because the original CERN server required an
134 extra (spurious) CRLF after a POST, so that various early clients sent
135 an extra CRLF that isn't included in the Content-Length header and
136 ends up preceding the start of the next load of data. We don't check
137 for this because it only applies to very old pure-HTTP (rather than
138 HTTP-as-a-transport-layer) clients, which are unlikely to be hitting a
139 PKI responder */
140 status = readTextLine( readCharFunction, stream, lineBuffer,
141 lineBufSize, &length, &isTextDataError, FALSE );
142 if( cryptStatusError( status ) )
143 {
144 /* If it's an HTTP-level error (e.g. line too long), send back an
145 HTTP-level error response */
146 if( status != CRYPT_ERROR_COMPLETE )
147 {
148 sendHTTPError( stream, lineBuffer, lineBufSize,
149 ( status == CRYPT_ERROR_OVERFLOW ) ? \
150 414 : 400 );
151 }
152
153 return( retTextLineError( stream, status, isTextDataError,
154 "Invalid HTTP request header line 1: ",
155 0 ) );
156 }
157 for( i = 0; httpReqInfo[ i ].reqName != NULL && \
158 i < FAILSAFE_ARRAYSIZE( httpReqInfo, HTTP_REQUEST_INFO );
159 i++ )
160 {
161 const HTTP_REQUEST_INFO *reqInfoPtr = &httpReqInfo[ i ];
162
163 if( ( reqInfoPtr->reqTypeFlag & netStream->nFlags ) && \
164 length >= reqInfoPtr->reqNameLen && \
165 !strCompare( lineBuffer, reqInfoPtr->reqName, \
166 reqInfoPtr->reqNameLen ) )
167 {
168 reqType = reqInfoPtr->reqType;
169 reqNameLen = reqInfoPtr->reqNameLen;
170 break;
171 }
172 }
173 ENSURES( i < FAILSAFE_ARRAYSIZE( httpReqInfo, HTTP_REQUEST_INFO ) );
174 if( reqType == STREAM_HTTPREQTYPE_NONE )
175 {
176 char reqNameBuffer[ 16 + 8 ];
177
178 /* Return the extended error information */
179 if( length <= 0 )
180 {
181 sendHTTPError( stream, lineBuffer, lineBufSize, 501 );
182 retExt( CRYPT_ERROR_BADDATA,
183 ( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO,
184 "Invalid empty HTTP request" ) );
185 }
186 if( ( offset = strSkipNonWhitespace( lineBuffer, length ) ) > 0 )
187 length = offset;
188 memcpy( reqNameBuffer, lineBuffer, min( 16, length ) );
189 sendHTTPError( stream, lineBuffer, lineBufSize, 501 );
190 retExt( CRYPT_ERROR_BADDATA,
191 ( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO,
192 "Invalid HTTP request '%s'",
193 sanitiseString( reqNameBuffer, 16, length ) ) );
194 }
195 bufPtr = lineBuffer + reqNameLen;
196 length -= reqNameLen;
197
198 /* Process the ' '* * ' '* and check for the HTTP ID */
199 if( length <= 0 || ( offset = strSkipWhitespace( bufPtr, length ) ) < 0 )
200 {
201 sendHTTPError( stream, lineBuffer, lineBufSize, 400 );
202 retExt( CRYPT_ERROR_BADDATA,
203 ( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO,
204 "Missing HTTP request URI" ) );
205 }
206 bufPtr += offset;
207 length -= offset;
208 if( reqType == STREAM_HTTPREQTYPE_GET )
209 {
210 /* Safety check, make sure that we can handle the HTTP GET */
211 REQUIRES( uriInfo != NULL );
212
213 /* If it's an indempotent read the client is sending a GET rather
214 than submitting a POST, process the request details. This
215 performs in-place decoding of (possibly encoded) data, so it
216 returns two length values, the new length after the in-place
217 decoding has occurred, and the offset of the next character of
218 data as usual */
219 status = offset = parseUriInfo( bufPtr, length, &length, uriInfo );
220 }
221 else
222 {
223 /* For non-idempotent queries we don't care what the location is
224 since it's not relevant for anything, so we just skip the URI.
225 This also avoids complications with absolute vs. relative URLs,
226 character encoding/escape sequences, and so on */
227 status = offset = strSkipNonWhitespace( bufPtr, length );
228 }
229 if( cryptStatusError( status ) )
230 {
231 sendHTTPError( stream, lineBuffer, lineBufSize, 400 );
232 retExt( CRYPT_ERROR_BADDATA,
233 ( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO,
234 "Invalid HTTP GET request URI" ) );
235 }
236 bufPtr += offset;
237 length -= offset;
238 if( length <= 0 || ( offset = strSkipWhitespace( bufPtr, length ) ) < 0 )
239 {
240 sendHTTPError( stream, lineBuffer, lineBufSize, 400 );
241 retExt( CRYPT_ERROR_BADDATA,
242 ( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO,
243 "Missing HTTP request ID/version" ) );
244 }
245 bufPtr += offset;
246 length -= offset;
247 if( length <= 0 || \
248 cryptStatusError( checkHTTPID( bufPtr, length, stream ) ) )
249 {
250 sendHTTPError( stream, lineBuffer, lineBufSize, 505 );
251 retExt( CRYPT_ERROR_BADDATA,
252 ( CRYPT_ERROR_BADDATA, NETSTREAM_ERRINFO,
253 "Invalid HTTP request ID/version" ) );
254 }
255
256 /* Process the remaining header lines. ~32 bytes is the minimum-size
257 object that can be returned from any HTTP-based message which is
258 exchanged by cryptlib, this being a TSP request */
259 initHeaderInfo( &headerInfo, 32, httpDataInfo->bufSize, *flags );
260 if( reqType == STREAM_HTTPREQTYPE_GET )
261 {
262 /* It's an HTTP GET, make sure that we don't try and read a body */
263 headerInfo.flags |= HTTP_FLAG_GET;
264 }
265 status = readHeaderLines( stream, lineBuffer, lineBufSize,
266 &headerInfo, &isSoftError );
267 if( cryptStatusError( status ) )
268 {
269 /* If it's a soft error, clear the input stream of any remaining
270 header lines */
271 if( isSoftError )
272 clearInputStream( stream, lineBuffer, lineBufSize );
273
274 /* We always (try and) send an HTTP error response once we get to
275 this stage since chances are that it'll be a problem with an
276 HTTP header rather than a low-level network read problem */
277 sendHTTPError( stream, lineBuffer, lineBufSize,
278 headerInfo.httpStatus );
279 return( status );
280 }
281
282 /* Copy any status info back to the caller */
283 httpDataInfo->reqType = reqType;
284 if( reqType != STREAM_HTTPREQTYPE_GET )
285 httpDataInfo->bytesAvail = headerInfo.contentLength;
286 *flags = headerInfo.flags;
287
288 return( CRYPT_OK );
289 }
290
291 /****************************************************************************
292 * *
293 * Read Response Header *
294 * *
295 ****************************************************************************/
296
297 /* Read an HTTP response header */
298
299 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4, 5 ) ) \
300 static int readResponseHeader( INOUT STREAM *stream,
301 OUT_BUFFER_FIXED( lineBufSize ) char *lineBuffer,
302 IN_LENGTH_SHORT_MIN( 256 ) const int lineBufSize,
303 INOUT HTTP_DATA_INFO *httpDataInfo,
304 OUT_FLAGS_Z( HTTP ) int *flags )
305 {
306 NET_STREAM_INFO *netStream = ( NET_STREAM_INFO * ) stream->netStreamInfo;
307 int repeatCount, persistentStatus = CRYPT_OK, status;
308
309 assert( isWritePtr( stream, sizeof( STREAM ) ) );
310 assert( isWritePtr( lineBuffer, lineBufSize ) );
311 assert( isWritePtr( httpDataInfo, sizeof( HTTP_DATA_INFO ) ) );
312 assert( isWritePtr( flags, sizeof( int ) ) );
313
314 REQUIRES( ( ( netStream->nFlags & STREAM_NFLAG_HTTPGET ) && \
315 httpDataInfo->reqInfo != NULL ) || \
316 ( !( netStream->nFlags & STREAM_NFLAG_HTTPGET ) && \
317 httpDataInfo->reqInfo == NULL ) );
318 REQUIRES( lineBufSize >= 256 && lineBufSize < MAX_INTLENGTH_SHORT );
319
320 /* Clear return value */
321 *flags = HTTP_FLAG_NONE;
322
323 /* If it's a stateless HTTP read, we need to first send the initiating
324 HTTP GET request before we can read anything back */
325 if( netStream->nFlags & STREAM_NFLAG_HTTPGET )
326 {
327 status = writeRequestHeader( stream, httpDataInfo->reqInfo,
328 NULL, 0, 0, FALSE );
329 if( cryptStatusError( status ) )
330 return( status );
331 }
332
333 /* Read the returned response header from the server, taking various
334 special-case conditions into account. In theory we could also handle
335 the 503 "Retry-After" status, but there's no sensible reason why
336 anyone should send us this, and even if they do it'll screw up a lot
337 of the PKI protocols, which have timeliness constraints built in */
338 for( repeatCount = 0; repeatCount < FAILSAFE_ITERATIONS_SMALL; \
339 repeatCount++ )
340 {
341 HTTP_HEADER_INFO headerInfo;
342 BOOLEAN needsSpecialHandling = FALSE;
343 BOOLEAN isSoftError, isResponseSoftError;
344 int httpStatus;
345
346 /* Read the response header */
347 status = readFirstHeaderLine( stream, lineBuffer, lineBufSize,
348 &httpStatus, &isResponseSoftError );
349 if( cryptStatusError( status ) )
350 {
351 /* Some errors like an HTTP 404 aren't necessarily fatal in the
352 same way as (say) a CRYPT_ERROR_BADDATA because while the
353 latter means that the stream has been corrupted and we can't
354 continue, the former merely means that the requested item
355 wasn't found but we can still submit further requests */
356 if( !isResponseSoftError )
357 return( status );
358
359 /* Turn the read into a no-op read that drains the input to get
360 to the next set of data, and if it's a special-case header
361 (e.g. a 100 Continue) remember that it needs special handling
362 later */
363 persistentStatus = status;
364 *flags |= HTTP_FLAG_NOOP;
365 if( status == OK_SPECIAL )
366 needsSpecialHandling = TRUE;
367 }
368
369 /* Process the remaining header lines. 5 bytes is the minimum-size
370 object that can be returned from any HTTP-based message which is
371 exchanged by cryptlib, this being an OCSP response containing a
372 single-byte status value, i.e. SEQUENCE { ENUM x }.
373
374 A soft error at this stage is different from a response soft
375 error (for example one arising from a 403, which is a valid
376 response but not the one desired) because it's an error in an
377 HTTP header line, which is an invalid response but not a fatal
378 error. If we get a soft error at this point we clear the
379 remaining input in order to allow further input to be processed.
380
381 If the read buffer is dynamically allocated then we allow an
382 effectively arbitrary content length, otherwise it has to fit
383 into the fixed-size read buffer. Unfortunately since CRLs can
384 reach > 100MB in size it's not really possible to provide any
385 sensible limit on the length for dynamic-buffer reads, however
386 to avoid DoS issues we limit it to 8MB until someone complains
387 that they can't read the 150MB CRLs that their CA is issuing
388 (yes, there are CAs that are issuing 150MB CRLs) */
389 initHeaderInfo( &headerInfo, 5,
390 httpDataInfo->bufferResize ? \
391 min( MAX_BUFFER_SIZE, 8388608L ) : \
392 httpDataInfo->bufSize,
393 *flags );
394 status = readHeaderLines( stream, lineBuffer, lineBufSize,
395 &headerInfo, &isSoftError );
396 if( cryptStatusError( status ) )
397 {
398 if( isSoftError )
399 clearInputStream( stream, lineBuffer, lineBufSize );
400 return( status );
401 }
402
403 /* Copy any status info back to the caller */
404 *flags = headerInfo.flags & ~HTTP_FLAG_NOOP;
405 httpDataInfo->bytesAvail = headerInfo.contentLength;
406
407 /* If it's not something like a redirect that needs special-case
408 handling, we're done */
409 if( !needsSpecialHandling )
410 {
411 /* If this was a soft error due to not finding the requested
412 item, pass the status on to the caller. The low-level error
413 information will still be present from
414 readFirstHeaderLine() */
415 if( isResponseSoftError )
416 {
417 return( cryptStatusError( persistentStatus ) ? \
418 persistentStatus : CRYPT_ERROR_NOTFOUND );
419 }
420
421 /* There's no special-case handling required, we're done */
422 return( CRYPT_OK );
423 }
424
425 REQUIRES( httpStatus == 100 || httpStatus == 301 || \
426 httpStatus == 302 || httpStatus == 307 );
427
428 /* If we got a 100 Continue response, try for another header that
429 follows the first one */
430 if( httpStatus == 100 )
431 continue;
432
433 /* A redirect isn't permitted for anything other than an HTTP GET */
434 if( !( netStream->nFlags & STREAM_NFLAG_HTTPGET ) )
435 {
436 retExt( CRYPT_ERROR_READ,
437 ( CRYPT_ERROR_READ, NETSTREAM_ERRINFO,
438 "Received invalid HTTP %d redirect during message "
439 "exchange", httpStatus ) );
440 }
441
442 /* If we got a 301, 302, or 307 Redirect then in theory we should
443 proceed roughly as per the code below, however in practice it's
444 not nearly as simple as this, because what we're in effect doing
445 is taking a stream and replacing it with a completely new stream
446 (different host/abs-path/query info, new socket with optional
447 proxy handling, etc etc). One way to do this would be to read
448 the new location into the current stream buffer and pass it back
449 with a special status telling the stream-level code to create a
450 new stream, clean up the old one, and perform a deep copy of the
451 new stream over to the old one. We'll leave this for a time when
452 it's really needed.
453
454 A less problematic variant occurs when the GET redirects to a
455 different abs-path on the same server, which just requires
456 resubmitting the GET with a different abs-path.
457
458 In addition the semantics of the following pseudocode don't quite
459 match those of RFC 2616 because of the HTTP-as-a-substrate use
460 rather than direct use in a browser. Specifically, anything
461 other than a GET for a 302 or 307 isn't supposed to perform an
462 automatic redirect without asking the user, because of concerns
463 that it'll change the semantics of the request. However since
464 we're not an interactive web browser there's no way that we can
465 ask a user for redirect permission, and in any case since we're
466 merely using HTTP as a substrate for a cryptographically
467 protected PKI message (and specifically assuming that the HTTP
468 layer is completely insecure), any problems will be caught by the
469 crypto protocol layer */
470 #if 0
471 if( !*location )
472 return( CRYPT_ERROR_READ );
473 netStream->closeSocketFunction( stream );
474 clFree( "readResponseHeader", netStream->host );
475 netStream->host = NULL;
476 status = parseLocation( stream, location );
477 if( cryptStatusError( status ) )
478 return( CRYPT_ERROR_READ );
479 #endif /* 0 */
480 retExt( CRYPT_ERROR_READ,
481 ( CRYPT_ERROR_READ, NETSTREAM_ERRINFO,
482 "Unable to process HTTP %d redirect", httpStatus ) );
483 }
484
485 /* We used up our maximum number of retries, bail out */
486 retExt( CRYPT_ERROR_READ,
487 ( CRYPT_ERROR_READ, NETSTREAM_ERRINFO,
488 "HTTP retry/redirection loop detected" ) );
489 }
490
491 /****************************************************************************
492 * *
493 * HTTP Access Functions *
494 * *
495 ****************************************************************************/
496
497 /* Read data from an HTTP stream. This has a nonstandard interpretation of
498 the read buffer in that it's not a direct pointer to the read buffer but
499 to an HTTP_DATA_INFO structure that contains additional metadata about
500 the HTTP read. For this reason it's an INOUT_BUFFER rather than an
501 OUT_BUFFER */
502
503 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
readFunction(INOUT STREAM * stream,INOUT_BUFFER (maxLength,* length)void * buffer,IN_LENGTH_FIXED (sizeof (HTTP_DATA_INFO))const int maxLength,OUT_DATALENGTH_Z int * length)504 static int readFunction( INOUT STREAM *stream,
505 INOUT_BUFFER( maxLength, *length ) void *buffer,
506 IN_LENGTH_FIXED( sizeof( HTTP_DATA_INFO ) ) \
507 const int maxLength,
508 OUT_DATALENGTH_Z int *length )
509 {
510 NET_STREAM_INFO *netStream = ( NET_STREAM_INFO * ) stream->netStreamInfo;
511 const STM_BUFFEREDTRANSPORTREAD_FUNCTION bufferedTransportReadFunction = \
512 FNPTR_GET( netStream->bufferedTransportReadFunction );
513 HTTP_DATA_INFO *httpDataInfo = ( HTTP_DATA_INFO * ) buffer;
514 char headerBuffer[ HTTP_LINEBUF_SIZE + 8 ];
515 int flags = HTTP_FLAG_NONE, status;
516
517 assert( isWritePtr( stream, sizeof( STREAM ) ) );
518 assert( isReadPtr( buffer, maxLength ) );
519 assert( isWritePtr( length, sizeof( int ) ) );
520 assert( !( netStream->nFlags & STREAM_NFLAG_HTTPGET ) || \
521 isReadPtr( httpDataInfo->reqInfo, sizeof( HTTP_URI_INFO ) ) );
522
523 REQUIRES( bufferedTransportReadFunction != NULL );
524
525 /* The handling of reqInfo in the httpDataInfo is somewhat complex and
526 runs as follows:
527
528 Action Type reqInfo status
529 ------ ---- --------------
530 readRequest GET Writeable, filled with data from the GET.
531 POST NULL.
532 readResponse GET Read-only (used to create the initial GET
533 that triggers the response).
534 POST NULL */
535 REQUIRES( maxLength == sizeof( HTTP_DATA_INFO ) );
536 REQUIRES( ( ( netStream->nFlags & STREAM_NFLAG_HTTPGET ) && \
537 httpDataInfo->reqInfo != NULL ) || \
538 ( !( netStream->nFlags & STREAM_NFLAG_HTTPGET ) && \
539 httpDataInfo->reqInfo == NULL ) );
540
541 /* Clear return value */
542 *length = 0;
543
544 /* Check whether the other side has indicated that it closed the
545 connection after the previous message was read. This operates at a
546 different level to the usual stream-level connection management
547 because the network connection may still be open but any further
548 attempts to do anything with it will return an error */
549 if( netStream->nFlags & STREAM_NFLAG_LASTMSGR )
550 {
551 retExt( CRYPT_ERROR_COMPLETE,
552 ( CRYPT_ERROR_COMPLETE, NETSTREAM_ERRINFO,
553 "Peer has closed the connection via HTTP 'Connection: "
554 "close'" ) );
555 }
556
557 /* Read the HTTP packet header */
558 if( netStream->nFlags & STREAM_NFLAG_ISSERVER )
559 {
560 status = readRequestHeader( stream, headerBuffer, HTTP_LINEBUF_SIZE,
561 httpDataInfo, &flags );
562 }
563 else
564 {
565 status = readResponseHeader( stream, headerBuffer, HTTP_LINEBUF_SIZE,
566 httpDataInfo, &flags );
567 if( cryptStatusOK( status ) && \
568 httpDataInfo->bytesAvail > httpDataInfo->bufSize )
569 {
570 void *newBuffer;
571
572 REQUIRES( httpDataInfo->bytesAvail > 0 && \
573 httpDataInfo->bytesAvail < MAX_BUFFER_SIZE );
574
575 /* readResponseHeader() will only allow content larger than the
576 buffer size if it's marked as a resizeable buffer */
577 REQUIRES( httpDataInfo->bufferResize );
578
579 /* Adjust the read buffer size to handle the extra data and
580 record the details of the resized buffer */
581 if( ( newBuffer = clAlloc( "readFunction", \
582 httpDataInfo->bytesAvail ) ) == NULL )
583 return( CRYPT_ERROR_MEMORY );
584 zeroise( httpDataInfo->buffer, httpDataInfo->bufSize );
585 clFree( "readFunction", httpDataInfo->buffer );
586 httpDataInfo->buffer = newBuffer;
587 httpDataInfo->bufSize = httpDataInfo->bytesAvail;
588 }
589 else
590 {
591 /* We didn't dynically resize the buffer, let the caller know */
592 httpDataInfo->bufferResize = FALSE;
593 }
594 }
595 if( cryptStatusError( status ) )
596 return( status );
597 ENSURES( httpDataInfo->bytesAvail <= httpDataInfo->bufSize );
598
599 REQUIRES( !( netStream->nFlags & STREAM_NFLAG_ISSERVER ) || \
600 ( httpDataInfo->reqType != STREAM_HTTPREQTYPE_NONE ) );
601
602 /* If we're the server and the client sends us an HTTP GET, all of the
603 information was contained in the header and we're done */
604 if( ( netStream->nFlags & STREAM_NFLAG_ISSERVER ) && \
605 ( httpDataInfo->reqType == STREAM_HTTPREQTYPE_GET ) )
606 {
607 *length = maxLength;
608 return( CRYPT_OK );
609 }
610
611 /* Read the payload data from the client/server */
612 status = bufferedTransportReadFunction( stream, httpDataInfo->buffer,
613 httpDataInfo->bytesAvail,
614 &httpDataInfo->bytesTransferred, TRANSPORT_FLAG_NONE );
615 if( cryptStatusError( status ) )
616 return( status );
617 if( httpDataInfo->bytesTransferred < httpDataInfo->bytesAvail )
618 {
619 /* We timed out before reading all of the data. Usually this will
620 be reported as a CRYPT_ERROR_TIMEOUT by the lower-level read
621 routines, however due to the multiple layers of I/O and special
622 case timeout handling when (for example) a cryptlib transport
623 session is layered over the network I/O layer, we perform an
624 explicit check here to make sure that we got everything */
625 retExt( CRYPT_ERROR_TIMEOUT,
626 ( CRYPT_ERROR_TIMEOUT, NETSTREAM_ERRINFO,
627 "HTTP read timed out before all data could be read, only "
628 "got %d of %d bytes", httpDataInfo->bytesTransferred,
629 httpDataInfo->bytesAvail ) );
630 }
631
632 /* If it's a plain-text error message, return it to the caller */
633 if( ( flags & HTTP_FLAG_TEXTMSG ) && !httpDataInfo->responseIsText )
634 {
635 BYTE *byteBufPtr = httpDataInfo->buffer;
636
637 /* Usually a body returned as plain text is an error message that
638 (for some reason) is sent as content rather than an HTTP error,
639 however in some unusual cases the content will be the requested
640 object marked as plain text. We try and filter out genuine PKI
641 data erroneously marked as text by requiring that the request is
642 over a minimum size (most error messages are quite short) and
643 that the first bytes match what would be seen in a PKI object
644 such as a cert or CRL */
645 if( httpDataInfo->bytesAvail < 256 || ( byteBufPtr[ 0 ] != 0x30 ) || \
646 !( byteBufPtr[ 1 ] & 0x80 ) || \
647 ( isAlpha( byteBufPtr[ 2 ] ) && isAlpha( byteBufPtr[ 3 ] ) && \
648 isAlpha( byteBufPtr[ 4 ] ) ) )
649 {
650 retExt( CRYPT_ERROR_READ,
651 ( CRYPT_ERROR_READ, NETSTREAM_ERRINFO,
652 "HTTP server reported: '%s'",
653 sanitiseString( byteBufPtr, \
654 httpDataInfo->bufSize,
655 min( httpDataInfo->bytesTransferred, \
656 MAX_ERRMSG_SIZE - 32 ) ) ) );
657 }
658 }
659
660 /* If we're reading chunked data, drain the input by processing the
661 trailer. The reason why there can be extra header lines at the end
662 of the chunked data is because it's designed to be an indefinite-
663 length streamable format that doesn't require buffering the entire
664 message before emitting it. Since some header information may not be
665 available until the entire message has been generated, the HTTP spec.
666 makes provisions for adding further header lines as a trailer. In
667 theory we should check for the HTTP_FLAG_TRAILER flag before reading
668 trailer lines rather than just swallowing the last CRLF, however the
669 "Trailer:" header wasn't added until RFC 2616 (RFC 2068 didn't have
670 it) so we can't rely on its presence. Normally we wouldn't have to
671 worry about trailer data, but if it's an HTTP 1.1 persistent
672 connection we then need to clear the way for the next lot of data */
673 if( flags & HTTP_FLAG_CHUNKED )
674 {
675 status = readTrailerLines( stream, headerBuffer,
676 HTTP_LINEBUF_SIZE );
677 if( cryptStatusError( status ) )
678 return( status );
679 }
680
681 *length = maxLength;
682 return( CRYPT_OK );
683 }
684
685 STDC_NONNULL_ARG( ( 1 ) ) \
setStreamLayerHTTP(INOUT NET_STREAM_INFO * netStream)686 void setStreamLayerHTTP( INOUT NET_STREAM_INFO *netStream )
687 {
688 assert( isWritePtr( netStream, sizeof( NET_STREAM_INFO ) ) );
689
690 /* Set the access method pointers */
691 FNPTR_SET( netStream->readFunction, readFunction );
692 setStreamLayerHTTPwrite( netStream );
693
694 /* The default HTTP operation type is POST, since in most cases it's
695 being used as a substrate by a PKI protocol */
696 netStream->nFlags |= STREAM_NFLAG_HTTPPOST;
697
698 /* HTTP provides its own data-size and flow-control indicators so we
699 don't want the higher-level code to try and do this for us */
700 netStream->nFlags |= STREAM_NFLAG_ENCAPS;
701 }
702 #endif /* USE_HTTP */
703