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