mirror of https://github.com/ipxe/ipxe.git
[http] Split construction of Authorization header out of http_step()
Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/6/head
parent
46df5c92a8
commit
8f5d44b5c6
|
@ -730,28 +730,57 @@ static void http_socket_close ( struct http_request *http, int rc ) {
|
||||||
http_done ( http );
|
http_done ( http );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate HTTP Basic authorisation string
|
||||||
|
*
|
||||||
|
* @v http HTTP request
|
||||||
|
* @ret auth Authorisation string, or NULL on error
|
||||||
|
*
|
||||||
|
* The authorisation string is dynamically allocated, and must be
|
||||||
|
* freed by the caller.
|
||||||
|
*/
|
||||||
|
static char * http_basic_auth ( struct http_request *http ) {
|
||||||
|
const char *user = http->uri->user;
|
||||||
|
const char *password =
|
||||||
|
( http->uri->password ? http->uri->password : "" );
|
||||||
|
size_t user_pw_len =
|
||||||
|
( strlen ( user ) + 1 /* ":" */ + strlen ( password ) );
|
||||||
|
char user_pw[ user_pw_len + 1 /* NUL */ ];
|
||||||
|
size_t user_pw_base64_len = base64_encoded_len ( user_pw_len );
|
||||||
|
char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ];
|
||||||
|
char *auth;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
assert ( user != NULL );
|
||||||
|
|
||||||
|
/* Make "user:password" string from decoded fields */
|
||||||
|
snprintf ( user_pw, sizeof ( user_pw ), "%s:%s", user, password );
|
||||||
|
|
||||||
|
/* Base64-encode the "user:password" string */
|
||||||
|
base64_encode ( ( void * ) user_pw, user_pw_len, user_pw_base64 );
|
||||||
|
|
||||||
|
/* Generate the authorisation string */
|
||||||
|
len = asprintf ( &auth, "Authorization: Basic %s\r\n",
|
||||||
|
user_pw_base64 );
|
||||||
|
if ( len < 0 )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return auth;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP process
|
* HTTP process
|
||||||
*
|
*
|
||||||
* @v http HTTP request
|
* @v http HTTP request
|
||||||
*/
|
*/
|
||||||
static void http_step ( struct http_request *http ) {
|
static void http_step ( struct http_request *http ) {
|
||||||
const char *host = http->uri->host;
|
size_t uri_len;
|
||||||
const char *user = http->uri->user;
|
char *method;
|
||||||
const char *password =
|
char *uri;
|
||||||
( http->uri->password ? http->uri->password : "" );
|
char *range;
|
||||||
size_t user_pw_len = ( user ? ( strlen ( user ) + 1 /* ":" */ +
|
char *auth;
|
||||||
strlen ( password ) ) : 0 );
|
int len;
|
||||||
size_t user_pw_base64_len = base64_encoded_len ( user_pw_len );
|
|
||||||
int request_len = unparse_uri ( NULL, 0, http->uri,
|
|
||||||
URI_PATH_BIT | URI_QUERY_BIT );
|
|
||||||
struct {
|
|
||||||
uint8_t user_pw[ user_pw_len + 1 /* NUL */ ];
|
|
||||||
char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ];
|
|
||||||
char request[ request_len + 1 /* NUL */ ];
|
|
||||||
char range[48]; /* Enough for two 64-bit integers in decimal */
|
|
||||||
} *dynamic;
|
|
||||||
int partial;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Do nothing if we have already transmitted the request */
|
/* Do nothing if we have already transmitted the request */
|
||||||
|
@ -762,74 +791,84 @@ static void http_step ( struct http_request *http ) {
|
||||||
if ( ! xfer_window ( &http->socket ) )
|
if ( ! xfer_window ( &http->socket ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Allocate dynamic storage */
|
|
||||||
dynamic = malloc ( sizeof ( *dynamic ) );
|
|
||||||
if ( ! dynamic ) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto err_alloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Construct path?query request */
|
|
||||||
unparse_uri ( dynamic->request, sizeof ( dynamic->request ), http->uri,
|
|
||||||
URI_PATH_BIT | URI_QUERY_BIT );
|
|
||||||
|
|
||||||
/* Construct authorisation, if applicable */
|
|
||||||
if ( user ) {
|
|
||||||
/* Make "user:password" string from decoded fields */
|
|
||||||
snprintf ( ( ( char * ) dynamic->user_pw ),
|
|
||||||
sizeof ( dynamic->user_pw ), "%s:%s",
|
|
||||||
user, password );
|
|
||||||
|
|
||||||
/* Base64-encode the "user:password" string */
|
|
||||||
base64_encode ( dynamic->user_pw, user_pw_len,
|
|
||||||
dynamic->user_pw_base64 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Force a HEAD request if we have nowhere to send any received data */
|
/* Force a HEAD request if we have nowhere to send any received data */
|
||||||
if ( ( xfer_window ( &http->xfer ) == 0 ) &&
|
if ( ( xfer_window ( &http->xfer ) == 0 ) &&
|
||||||
( http->rx_buffer == UNULL ) ) {
|
( http->rx_buffer == UNULL ) ) {
|
||||||
http->flags |= ( HTTP_HEAD_ONLY | HTTP_CLIENT_KEEPALIVE );
|
http->flags |= ( HTTP_HEAD_ONLY | HTTP_CLIENT_KEEPALIVE );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine type of request */
|
/* Determine method */
|
||||||
partial = ( http->partial_len != 0 );
|
method = ( ( http->flags & HTTP_HEAD_ONLY ) ? "HEAD" : "GET" );
|
||||||
snprintf ( dynamic->range, sizeof ( dynamic->range ),
|
|
||||||
"%zd-%zd", http->partial_start,
|
/* Construct path?query request */
|
||||||
( http->partial_start + http->partial_len - 1 ) );
|
uri_len = ( unparse_uri ( NULL, 0, http->uri,
|
||||||
|
URI_PATH_BIT | URI_QUERY_BIT )
|
||||||
|
+ 1 /* possible "/" */ + 1 /* NUL */ );
|
||||||
|
uri = malloc ( uri_len );
|
||||||
|
if ( ! uri ) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto err_uri;
|
||||||
|
}
|
||||||
|
unparse_uri ( uri, uri_len, http->uri, URI_PATH_BIT | URI_QUERY_BIT );
|
||||||
|
if ( ! uri[0] ) {
|
||||||
|
uri[0] = '/';
|
||||||
|
uri[1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate range request parameters if applicable */
|
||||||
|
if ( http->partial_len ) {
|
||||||
|
len = asprintf ( &range, "Range: bytes=%zd-%zd\r\n",
|
||||||
|
http->partial_start,
|
||||||
|
( http->partial_start + http->partial_len
|
||||||
|
- 1 ) );
|
||||||
|
if ( len < 0 ) {
|
||||||
|
rc = len;
|
||||||
|
goto err_range;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
range = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Construct authorisation, if applicable */
|
||||||
|
if ( http->uri->user ) {
|
||||||
|
auth = http_basic_auth ( http );
|
||||||
|
if ( ! auth ) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto err_auth;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auth = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mark request as transmitted */
|
/* Mark request as transmitted */
|
||||||
http->flags &= ~HTTP_TX_PENDING;
|
http->flags &= ~HTTP_TX_PENDING;
|
||||||
|
|
||||||
/* Send GET request */
|
/* Send request */
|
||||||
if ( ( rc = xfer_printf ( &http->socket,
|
if ( ( rc = xfer_printf ( &http->socket,
|
||||||
"%s %s%s HTTP/1.1\r\n"
|
"%s %s HTTP/1.1\r\n"
|
||||||
"User-Agent: iPXE/" VERSION "\r\n"
|
"User-Agent: iPXE/" VERSION "\r\n"
|
||||||
"Host: %s%s%s\r\n"
|
"Host: %s%s%s\r\n"
|
||||||
"%s%s%s%s%s%s%s"
|
"%s%s%s"
|
||||||
"\r\n",
|
"\r\n",
|
||||||
( ( http->flags & HTTP_HEAD_ONLY ) ?
|
method, uri, http->uri->host,
|
||||||
"HEAD" : "GET" ),
|
|
||||||
( http->uri->path ? "" : "/" ),
|
|
||||||
dynamic->request, host,
|
|
||||||
( http->uri->port ?
|
( http->uri->port ?
|
||||||
":" : "" ),
|
":" : "" ),
|
||||||
( http->uri->port ?
|
( http->uri->port ?
|
||||||
http->uri->port : "" ),
|
http->uri->port : "" ),
|
||||||
( ( http->flags & HTTP_CLIENT_KEEPALIVE ) ?
|
( ( http->flags & HTTP_CLIENT_KEEPALIVE ) ?
|
||||||
"Connection: keep-alive\r\n" : "" ),
|
"Connection: keep-alive\r\n" : "" ),
|
||||||
( partial ? "Range: bytes=" : "" ),
|
( range ? range : "" ),
|
||||||
( partial ? dynamic->range : "" ),
|
( auth ? auth : "" ) ) ) != 0 ) {
|
||||||
( partial ? "\r\n" : "" ),
|
|
||||||
( user ?
|
|
||||||
"Authorization: Basic " : "" ),
|
|
||||||
( user ? dynamic->user_pw_base64 : "" ),
|
|
||||||
( user ? "\r\n" : "" ) ) ) != 0 ) {
|
|
||||||
goto err_xfer;
|
goto err_xfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
err_xfer:
|
err_xfer:
|
||||||
free ( dynamic );
|
free ( auth );
|
||||||
err_alloc:
|
err_auth:
|
||||||
|
free ( range );
|
||||||
|
err_range:
|
||||||
|
free ( uri );
|
||||||
|
err_uri:
|
||||||
if ( rc != 0 )
|
if ( rc != 0 )
|
||||||
http_close ( http, rc );
|
http_close ( http, rc );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue