diff options
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/http/http.h | 30 | ||||
-rw-r--r-- | src/plugins/http_static/static_server.c | 74 |
2 files changed, 81 insertions, 23 deletions
diff --git a/src/plugins/http/http.h b/src/plugins/http/http.h index 1d2a949c612..434ff965b6a 100644 --- a/src/plugins/http/http.h +++ b/src/plugins/http/http.h @@ -934,21 +934,24 @@ http_init_headers_ctx (http_headers_ctx_t *ctx, u8 *buf, u32 len) * @param name Header name ID (see @ref http_header_name_t). * @param value Header value pointer. * @param value_len Header value length. + * + * @return @c 0 if in case of success, @c -1 otherwise. */ -always_inline void +always_inline int http_add_header (http_headers_ctx_t *ctx, http_header_name_t name, const char *value, uword value_len) { http_app_header_t *header; - ASSERT ((ctx->tail_offset + sizeof (http_app_header_t) + value_len) < - ctx->len); + if ((ctx->tail_offset + sizeof (http_app_header_t) + value_len) > ctx->len) + return -1; header = (http_app_header_t *) (ctx->buf + ctx->tail_offset); header->name = (u32) name; header->value.len = (u32) value_len; clib_memcpy (header->value.token, (u8 *) value, value_len); ctx->tail_offset += sizeof (http_app_header_t) + value_len; + return 0; } /** @@ -959,15 +962,18 @@ http_add_header (http_headers_ctx_t *ctx, http_header_name_t name, * @param name_len Header name length. * @param value Header value pointer. * @param value_len Header value length. + * + * @return @c 0 if in case of success, @c -1 otherwise. */ -always_inline void +always_inline int http_add_custom_header (http_headers_ctx_t *ctx, const char *name, uword name_len, const char *value, uword value_len) { http_custom_token_t *token; - ASSERT ((ctx->tail_offset + 2 * sizeof (http_custom_token_t) + name_len + - value_len) < ctx->len); + if ((ctx->tail_offset + 2 * sizeof (http_custom_token_t) + name_len + + value_len) > ctx->len) + return -1; /* name */ token = (http_custom_token_t *) (ctx->buf + ctx->tail_offset); @@ -980,6 +986,18 @@ http_add_custom_header (http_headers_ctx_t *ctx, const char *name, token->len = (u32) value_len; clib_memcpy (token->token, (u8 *) value, token->len); ctx->tail_offset += sizeof (http_custom_token_t) + value_len; + return 0; +} + +/** + * Truncate the header list + * + * @param ctx Headers list context. + */ +always_inline void +http_truncate_headers_list (http_headers_ctx_t *ctx) +{ + ctx->tail_offset = 0; } typedef enum http_uri_host_type_ diff --git a/src/plugins/http_static/static_server.c b/src/plugins/http_static/static_server.c index 9d416dab558..d7958fd3f1f 100644 --- a/src/plugins/http_static/static_server.c +++ b/src/plugins/http_static/static_server.c @@ -27,9 +27,41 @@ /*? %%clicmd:group_label Static HTTP Server %% ?*/ #define HSS_FIFO_THRESH (16 << 10) - +#define HSS_HEADER_BUF_MAX_SIZE 16192 hss_main_t hss_main; +static int +hss_add_header (hss_session_t *hs, http_header_name_t name, const char *value, + uword value_len) +{ + u32 needed_size = 0; + while (http_add_header (&hs->resp_headers, name, value, value_len) == -1) + { + if (needed_size) + { + http_truncate_headers_list (&hs->resp_headers); + hs->data_len = 0; + return -1; + } + else + needed_size = hs->resp_headers.tail_offset + + sizeof (http_app_header_t) + value_len; + if (needed_size < HSS_HEADER_BUF_MAX_SIZE) + { + vec_resize (hs->headers_buf, sizeof (http_app_header_t) + value_len); + hs->resp_headers.len = needed_size; + hs->resp_headers.buf = hs->headers_buf; + } + else + { + http_truncate_headers_list (&hs->resp_headers); + hs->data_len = 0; + return -1; + } + } + return 0; +} + static hss_session_t * hss_session_alloc (u32 thread_index) { @@ -175,8 +207,9 @@ hss_session_send_data (hss_url_handler_args_t *args) /* Set content type only if we have some response data */ if (hs->data_len) - http_add_header (&hs->resp_headers, HTTP_HEADER_CONTENT_TYPE, - http_content_type_token (args->ct)); + if (hss_add_header (hs, HTTP_HEADER_CONTENT_TYPE, + http_content_type_token (args->ct))) + args->sc = HTTP_STATUS_INTERNAL_ERROR; start_send_data (hs, args->sc); } @@ -305,8 +338,9 @@ try_url_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, /* Set content type only if we have some response data */ if (hs->data_len) - http_add_header (&hs->resp_headers, HTTP_HEADER_CONTENT_TYPE, - http_content_type_token (args.ct)); + if (hss_add_header (hs, HTTP_HEADER_CONTENT_TYPE, + http_content_type_token (args.ct))) + sc = HTTP_STATUS_INTERNAL_ERROR; start_send_data (hs, sc); @@ -383,8 +417,10 @@ try_index_file (hss_main_t *hsm, hss_session_t *hs, u8 *path) vec_free (port_str); - http_add_header (&hs->resp_headers, HTTP_HEADER_LOCATION, - (const char *) redirect, vec_len (redirect)); + if (hss_add_header (hs, HTTP_HEADER_LOCATION, (const char *) redirect, + vec_len (redirect))) + return HTTP_STATUS_INTERNAL_ERROR; + vec_free (redirect); hs->data_len = 0; hs->free_data = 1; @@ -463,13 +499,16 @@ try_file_handler (hss_main_t *hsm, hss_session_t *hs, http_req_method_t rt, * Last-Modified */ type = content_type_from_request (target); - http_add_header (&hs->resp_headers, HTTP_HEADER_CONTENT_TYPE, - http_content_type_token (type)); - http_add_header (&hs->resp_headers, HTTP_HEADER_CACHE_CONTROL, - (const char *) hsm->max_age_formatted, - vec_len (hsm->max_age_formatted)); - http_add_header (&hs->resp_headers, HTTP_HEADER_LAST_MODIFIED, - (const char *) last_modified, vec_len (last_modified)); + if (hss_add_header (hs, HTTP_HEADER_CONTENT_TYPE, + http_content_type_token (type)) || + hss_add_header (hs, HTTP_HEADER_CACHE_CONTROL, + (const char *) hsm->max_age_formatted, + vec_len (hsm->max_age_formatted)) || + hss_add_header (hs, HTTP_HEADER_LAST_MODIFIED, + (const char *) last_modified, vec_len (last_modified))) + { + sc = HTTP_STATUS_INTERNAL_ERROR; + } done: vec_free (sanitized_path); @@ -521,9 +560,10 @@ hss_ts_rx_callback (session_t *ts) if (msg.type != HTTP_MSG_REQUEST || (msg.method_type != HTTP_REQ_GET && msg.method_type != HTTP_REQ_POST)) { - http_add_header (&hs->resp_headers, HTTP_HEADER_ALLOW, - http_token_lit ("GET, POST")); - start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED); + if (hss_add_header (hs, HTTP_HEADER_ALLOW, http_token_lit ("GET, POST"))) + start_send_data (hs, HTTP_STATUS_INTERNAL_ERROR); + else + start_send_data (hs, HTTP_STATUS_METHOD_NOT_ALLOWED); goto err_done; } |