From 96bb6ba441653a30729ade38dc6c23bc9e2d2339 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 28 Feb 2023 17:46:13 +0000 Subject: [params] Allow for arbitrary HTTP request headers to be specified Extend the request parameter mechanism to allow for arbitrary HTTP headers to be specified via e.g.: params param --header Referer http://www.example.com imgfetch http://192.168.0.1/script.ipxe##params Signed-off-by: Michael Brown --- src/core/params.c | 11 ++++++++--- src/hci/commands/param_cmd.c | 10 +++++++++- src/include/ipxe/params.h | 11 ++++++++++- src/net/tcp/httpcore.c | 43 ++++++++++++++++++++++++++++++++++--------- src/tests/uri_test.c | 13 ++++++++++++- 5 files changed, 73 insertions(+), 15 deletions(-) diff --git a/src/core/params.c b/src/core/params.c index 23206be..58c829f 100644 --- a/src/core/params.c +++ b/src/core/params.c @@ -123,10 +123,12 @@ struct parameters * create_parameters ( const char *name ) { * @v params Parameter list * @v key Parameter key * @v value Parameter value + * @v flags Parameter flags * @ret param Parameter, or NULL on failure */ struct parameter * add_parameter ( struct parameters *params, - const char *key, const char *value ) { + const char *key, const char *value, + unsigned int flags ) { struct parameter *param; size_t key_len; size_t value_len; @@ -147,11 +149,14 @@ struct parameter * add_parameter ( struct parameters *params, param->key = key_copy; strcpy ( value_copy, value ); param->value = value_copy; + param->flags = flags; /* Add to list of parameters */ list_add_tail ( ¶m->list, ¶ms->entries ); - DBGC ( params, "PARAMS \"%s\" added \"%s\"=\"%s\"\n", - params->name, param->key, param->value ); + DBGC ( params, "PARAMS \"%s\" added \"%s\"=\"%s\"%s%s\n", + params->name, param->key, param->value, + ( ( param->flags & PARAMETER_FORM ) ? " (form)" : "" ), + ( ( param->flags & PARAMETER_HEADER ) ? " (header)" : "" ) ); return param; } diff --git a/src/hci/commands/param_cmd.c b/src/hci/commands/param_cmd.c index 9e3260d..dad99f8 100644 --- a/src/hci/commands/param_cmd.c +++ b/src/hci/commands/param_cmd.c @@ -90,12 +90,16 @@ static int params_exec ( int argc, char **argv ) { struct param_options { /** Parameter list name */ char *params; + /** Parameter is a header */ + int header; }; /** "param" option list */ static struct option_descriptor param_opts[] = { OPTION_DESC ( "params", 'p', required_argument, struct param_options, params, parse_string ), + OPTION_DESC ( "header", 'H', no_argument, + struct param_options, header, parse_flag ), }; /** "param" command descriptor */ @@ -114,6 +118,7 @@ static int param_exec ( int argc, char **argv ) { struct param_options opts; char *key; char *value; + unsigned int flags; struct parameters *params; struct parameter *param; int rc; @@ -132,12 +137,15 @@ static int param_exec ( int argc, char **argv ) { goto err_parse_value; } + /* Construct flags */ + flags = ( opts.header ? PARAMETER_HEADER : PARAMETER_FORM ); + /* Identify parameter list */ if ( ( rc = parse_parameters ( opts.params, ¶ms ) ) != 0 ) goto err_parse_parameters; /* Add parameter */ - param = add_parameter ( params, key, value ); + param = add_parameter ( params, key, value, flags ); if ( ! param ) { rc = -ENOMEM; goto err_add_parameter; diff --git a/src/include/ipxe/params.h b/src/include/ipxe/params.h index 955f57a..61e46e0 100644 --- a/src/include/ipxe/params.h +++ b/src/include/ipxe/params.h @@ -32,8 +32,16 @@ struct parameter { const char *key; /** Value */ const char *value; + /** Flags */ + unsigned int flags; }; +/** Request parameter is a form parameter */ +#define PARAMETER_FORM 0x0001 + +/** Request parameter is a header parameter */ +#define PARAMETER_HEADER 0x0002 + /** * Increment request parameter list reference count * @@ -78,6 +86,7 @@ claim_parameters ( struct parameters *params ) { extern struct parameters * find_parameters ( const char *name ); extern struct parameters * create_parameters ( const char *name ); extern struct parameter * add_parameter ( struct parameters *params, - const char *key, const char *value ); + const char *key, const char *value, + unsigned int flags ); #endif /* _IPXE_PARAMS_H */ diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index c970d54..9ad3965 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -830,7 +830,9 @@ static int http_transfer_complete ( struct http_transaction *http ) { */ static int http_format_headers ( struct http_transaction *http, char *buf, size_t len ) { + struct parameters *params = http->uri->params; struct http_request_header *header; + struct parameter *param; size_t used; size_t remaining; char *line; @@ -844,7 +846,7 @@ static int http_format_headers ( struct http_transaction *http, char *buf, DBGC2 ( http, "HTTP %p TX %s\n", http, buf ); used += ssnprintf ( ( buf + used ), ( len - used ), "\r\n" ); - /* Construct all headers */ + /* Construct all fixed headers */ for_each_table_entry ( header, HTTP_REQUEST_HEADERS ) { /* Determine header value length */ @@ -869,6 +871,23 @@ static int http_format_headers ( struct http_transaction *http, char *buf, used += ssnprintf ( ( buf + used ), ( len - used ), "\r\n" ); } + /* Construct parameter headers, if any */ + if ( params ) { + + /* Construct all parameter headers */ + for_each_param ( param, params ) { + + /* Skip non-header parameters */ + if ( ! ( param->flags & PARAMETER_HEADER ) ) + continue; + + /* Add parameter */ + used += ssnprintf ( ( buf + used ), ( len - used ), + "%s: %s\r\n", param->key, + param->value ); + } + } + /* Construct terminating newline */ used += ssnprintf ( ( buf + used ), ( len - used ), "\r\n" ); @@ -1851,14 +1870,15 @@ static struct http_state http_trailers = { */ /** - * Construct HTTP parameter list + * Construct HTTP form parameter list * * @v params Parameter list * @v buf Buffer to contain HTTP POST parameters * @v len Length of buffer * @ret len Length of parameter list (excluding terminating NUL) */ -static size_t http_params ( struct parameters *params, char *buf, size_t len ) { +static size_t http_form_params ( struct parameters *params, char *buf, + size_t len ) { struct parameter *param; ssize_t remaining = len; size_t frag_len; @@ -1867,6 +1887,10 @@ static size_t http_params ( struct parameters *params, char *buf, size_t len ) { len = 0; for_each_param ( param, params ) { + /* Skip non-form parameters */ + if ( ! ( param->flags & PARAMETER_FORM ) ) + continue; + /* Add the "&", if applicable */ if ( len ) { if ( remaining > 0 ) @@ -1920,25 +1944,26 @@ int http_open_uri ( struct interface *xfer, struct uri *uri ) { size_t check_len; int rc; - /* Calculate length of parameter list, if any */ - len = ( params ? http_params ( params, NULL, 0 ) : 0 ); + /* Calculate length of form parameter list, if any */ + len = ( params ? http_form_params ( params, NULL, 0 ) : 0 ); - /* Use POST if and only if there are parameters */ + /* Use POST if and only if there are form parameters */ if ( len ) { /* Use POST */ method = &http_post; type = "application/x-www-form-urlencoded"; - /* Allocate temporary parameter list */ + /* Allocate temporary form parameter list */ data = zalloc ( len + 1 /* NUL */ ); if ( ! data ) { rc = -ENOMEM; goto err_alloc; } - /* Construct temporary parameter list */ - check_len = http_params ( params, data, ( len + 1 /* NUL */ ) ); + /* Construct temporary form parameter list */ + check_len = http_form_params ( params, data, + ( len + 1 /* NUL */ ) ); assert ( check_len == len ); } else { diff --git a/src/tests/uri_test.c b/src/tests/uri_test.c index 5e70603..9d2f6db 100644 --- a/src/tests/uri_test.c +++ b/src/tests/uri_test.c @@ -98,6 +98,8 @@ struct uri_params_test_list { const char *key; /** Value */ const char *value; + /** Flags */ + unsigned int flags; }; /** A request parameter URI test */ @@ -428,6 +430,7 @@ static void uri_params_list_okx ( struct uri_params_test *test, file, line ); okx ( strcmp ( param->value, list->value ) == 0, file, line ); + okx ( param->flags == list->flags, file, line ); list++; } okx ( list->key == NULL, file, line ); @@ -456,7 +459,8 @@ static void uri_params_okx ( struct uri_params_test *test, const char *file, okx ( params != NULL, file, line ); if ( params ) { for ( list = test->list ; list->key ; list++ ) { - param = add_parameter ( params, list->key, list->value); + param = add_parameter ( params, list->key, list->value, + list->flags ); okx ( param != NULL, file, line ); } } @@ -884,18 +888,22 @@ static struct uri_params_test_list uri_params_list[] = { { "vendor", "10ec", + PARAMETER_FORM, }, { "device", "8139", + PARAMETER_FORM, }, { "uuid", "f59fac00-758f-498f-9fe5-87d790045d94", + PARAMETER_HEADER, }, { NULL, NULL, + 0, } }; @@ -917,14 +925,17 @@ static struct uri_params_test_list uri_named_params_list[] = { { "mac", "00:1e:65:80:d3:b6", + PARAMETER_FORM, }, { "serial", "LXTQ20Z1139322762F2000", + PARAMETER_FORM, }, { NULL, NULL, + 0, } }; -- cgit v1.1