mirror of
https://github.com/openappsec/attachment.git
synced 2025-06-28 16:41:03 +03:00
sync code
This commit is contained in:
parent
711bf5686a
commit
c72a54546c
@ -173,6 +173,12 @@ getReqBodySizeTrigger()
|
||||
return conf_data.getNumericalValue("body_size_trigger");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getRemoveResServerHeader()
|
||||
{
|
||||
return conf_data.getNumericalValue("remove_server_header");
|
||||
}
|
||||
|
||||
int
|
||||
isIPAddress(c_str ip_str)
|
||||
{
|
||||
|
@ -218,7 +218,7 @@ compression_data_filter(
|
||||
if (output->data == NULL) {
|
||||
// Failed to allocate a new buffer.
|
||||
write_dbg(DBG_LEVEL_WARNING, "Failed to allocate a new buffer");
|
||||
|
||||
free(compression_result.output);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,8 @@ init_cp_session_data(ngx_http_request_t *request)
|
||||
session_id++;
|
||||
session_data->remaining_messages_to_reply = 0;
|
||||
session_data->response_data.response_data_status = NGX_OK;
|
||||
session_data->response_data.original_compressed_body = NULL;
|
||||
session_data->response_data.request_pool = NULL;
|
||||
if (!metric_timeout.tv_sec) {
|
||||
metric_timeout = get_timeout_val_sec(METRIC_TIMEOUT_VAL);
|
||||
}
|
||||
@ -107,6 +109,75 @@ fini_cp_session_data(ngx_http_cp_session_data *session_data)
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// @brief Cleans up session data.
|
||||
/// @param[in] data Pointer to the session data to be cleaned up.
|
||||
///
|
||||
static void
|
||||
ngx_session_data_cleanup(void *data)
|
||||
{
|
||||
if (data == NULL) return;
|
||||
ngx_http_cp_session_data *session_data = (ngx_http_cp_session_data *)data;
|
||||
write_dbg(DBG_LEVEL_TRACE, "Cleaning up session data for session ID %d", session_data->session_id);
|
||||
|
||||
if (session_data->response_data.original_compressed_body != NULL) {
|
||||
ngx_chain_t *current = session_data->response_data.original_compressed_body;
|
||||
while (current != NULL) {
|
||||
ngx_chain_t *next = current->next;
|
||||
ngx_free_chain(session_data->response_data.request_pool, current);
|
||||
current = next;
|
||||
}
|
||||
session_data->response_data.original_compressed_body = NULL;
|
||||
}
|
||||
|
||||
fini_cp_session_data(session_data);
|
||||
}
|
||||
|
||||
///
|
||||
/// @brief initializes session data with response_data chain allocation and cleanup from given ngx pool
|
||||
/// \param session_data
|
||||
/// \param request
|
||||
/// \return
|
||||
///
|
||||
static ngx_int_t
|
||||
init_cp_session_original_body(ngx_http_cp_session_data *session_data, ngx_pool_t *pool)
|
||||
{
|
||||
ngx_pool_cleanup_t *cln;
|
||||
|
||||
write_dbg(DBG_LEVEL_TRACE, "Initializing original compressed body for session ID %d", session_data->session_id);
|
||||
|
||||
session_data->response_data.original_compressed_body = ngx_alloc_chain_link(pool);
|
||||
|
||||
if (session_data->response_data.original_compressed_body == NULL) {
|
||||
write_dbg(
|
||||
DBG_LEVEL_WARNING,
|
||||
"Failed to allocate memory for original compressed body in session ID %d\n",
|
||||
session_data->session_id
|
||||
);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
session_data->response_data.request_pool = pool;
|
||||
ngx_memset(session_data->response_data.original_compressed_body, 0, sizeof(ngx_chain_t));
|
||||
|
||||
cln = ngx_pool_cleanup_add(pool, 0);
|
||||
if (cln == NULL) {
|
||||
write_dbg(
|
||||
DBG_LEVEL_WARNING,
|
||||
"Failed to allocate cleanup memory for original compressed body in session ID %d\n",
|
||||
session_data->session_id
|
||||
);
|
||||
ngx_free_chain(session_data->response_data.request_pool, session_data->response_data.original_compressed_body);
|
||||
session_data->response_data.original_compressed_body = NULL;
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
write_dbg(DBG_LEVEL_TRACE, "Adding session_data cleanup handler for session ID %d", session_data->session_id);
|
||||
cln->handler = ngx_session_data_cleanup;
|
||||
cln->data = session_data;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
///
|
||||
/// @brief Recovers a session data pointer.
|
||||
/// @param[in] request NGINX request.
|
||||
@ -721,6 +792,43 @@ ngx_http_cp_req_body_filter(ngx_http_request_t *request, ngx_chain_t *request_bo
|
||||
return ngx_http_next_request_body_filter(request, request_body_chain);
|
||||
}
|
||||
|
||||
///
|
||||
/// @brief Removes the "Server" header from the HTTP response.
|
||||
///
|
||||
/// This function modifies the `headers_out` structure of the given HTTP request
|
||||
/// to remove the "Server" header. If the header is already removed, it returns `NGX_OK`.
|
||||
/// Otherwise, it allocates a new header entry, sets its key to "Server" and its value to an
|
||||
/// empty string, and updates the `headers_out` structure accordingly.
|
||||
///
|
||||
/// @param r The HTTP request object containing the headers to be modified.
|
||||
/// @return `NGX_OK` if the header was successfully removed or was already removed,
|
||||
/// `NGX_ERROR` if there was an error allocating memory for the new header entry.
|
||||
///
|
||||
static ngx_int_t
|
||||
remove_server_header(ngx_http_request_t *r)
|
||||
{
|
||||
ngx_table_elt_t *header, **server_header_slot;
|
||||
ngx_uint_t offset = offsetof(ngx_http_headers_out_t, server);
|
||||
|
||||
server_header_slot = (ngx_table_elt_t **) ((char *) &r->headers_out + offset);
|
||||
if (*server_header_slot != NULL) return NGX_OK;
|
||||
|
||||
header = ngx_list_push(&r->headers_out.headers);
|
||||
if (header == NULL) return NGX_ERROR;
|
||||
|
||||
header->hash = 0;
|
||||
ngx_str_set(&header->key, "Server");
|
||||
ngx_str_set(&header->value, "");
|
||||
|
||||
header->lowcase_key = ngx_pnalloc(r->pool, header->key.len);
|
||||
if (header->lowcase_key == NULL) return NGX_ERROR;
|
||||
|
||||
ngx_strlow(header->lowcase_key, header->key.data, header->key.len);
|
||||
*server_header_slot = header;
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_cp_res_header_filter(ngx_http_request_t *request)
|
||||
{
|
||||
@ -733,6 +841,8 @@ ngx_http_cp_res_header_filter(ngx_http_request_t *request)
|
||||
|
||||
session_data_p = recover_cp_session_data(request);
|
||||
|
||||
if (remove_res_server_header) remove_server_header(request);
|
||||
|
||||
if (session_data_p == NULL) return ngx_http_next_response_header_filter(request);
|
||||
|
||||
set_current_session_id(session_data_p->session_id);
|
||||
@ -856,8 +966,7 @@ ngx_http_cp_res_body_filter(ngx_http_request_t *request, ngx_chain_t *body_chain
|
||||
{
|
||||
struct ngx_http_cp_event_thread_ctx_t ctx;
|
||||
ngx_http_cp_session_data *session_data_p;
|
||||
ngx_chain_t *original_compressed_body = NULL;
|
||||
ngx_int_t compression_result;
|
||||
ngx_int_t compression_result = NGX_ERROR;
|
||||
ngx_chain_t *chain_elem = NULL;
|
||||
ngx_int_t final_res;
|
||||
int is_last_decompressed_part = 0;
|
||||
@ -920,25 +1029,23 @@ ngx_http_cp_res_body_filter(ngx_http_request_t *request, ngx_chain_t *body_chain
|
||||
}
|
||||
|
||||
if (body_chain->buf->pos != NULL && session_data_p->response_data.new_compression_type != NO_COMPRESSION) {
|
||||
// Decompress and re-compress non-empty buffer to maintain consistent compression stream
|
||||
original_compressed_body = ngx_alloc_chain_link(request->pool);
|
||||
ngx_memset(original_compressed_body, 0, sizeof(ngx_chain_t));
|
||||
if (init_cp_session_original_body(session_data_p, request->pool) == NGX_OK) {
|
||||
if (session_data_p->response_data.decompression_stream == NULL) {
|
||||
session_data_p->response_data.decompression_stream = initCompressionStream();
|
||||
}
|
||||
|
||||
if (session_data_p->response_data.decompression_stream == NULL) {
|
||||
session_data_p->response_data.decompression_stream = initCompressionStream();
|
||||
compression_result = decompress_body(
|
||||
session_data_p->response_data.decompression_stream,
|
||||
RESPONSE_BODY,
|
||||
&is_last_decompressed_part,
|
||||
&body_chain,
|
||||
&session_data_p->response_data.original_compressed_body,
|
||||
request->pool
|
||||
);
|
||||
}
|
||||
|
||||
compression_result = decompress_body(
|
||||
session_data_p->response_data.decompression_stream,
|
||||
RESPONSE_BODY,
|
||||
&is_last_decompressed_part,
|
||||
&body_chain,
|
||||
&original_compressed_body,
|
||||
request->pool
|
||||
);
|
||||
|
||||
if (compression_result != NGX_OK) {
|
||||
copy_chain_buffers(body_chain, original_compressed_body);
|
||||
copy_chain_buffers(body_chain, session_data_p->response_data.original_compressed_body);
|
||||
handle_inspection_failure(inspection_failure_weight, fail_mode_verdict, session_data_p);
|
||||
fini_cp_session_data(session_data_p);
|
||||
session_data_p->response_data.response_data_status = NGX_ERROR;
|
||||
@ -1004,8 +1111,14 @@ ngx_http_cp_res_body_filter(ngx_http_request_t *request, ngx_chain_t *body_chain
|
||||
return ngx_http_next_response_body_filter(request, body_chain);
|
||||
}
|
||||
|
||||
init_thread_ctx(&ctx, request, session_data_p,
|
||||
original_compressed_body == NULL ? body_chain : original_compressed_body);
|
||||
init_thread_ctx(
|
||||
&ctx,
|
||||
request,
|
||||
session_data_p,
|
||||
session_data_p->response_data.original_compressed_body == NULL
|
||||
? body_chain
|
||||
: session_data_p->response_data.original_compressed_body
|
||||
);
|
||||
|
||||
write_dbg(DBG_LEVEL_DEBUG, "spawn ngx_http_cp_res_body_filter_thread");
|
||||
// Open threads while unprocessed chain elements still exist, up to num of elements in the chain iterations
|
||||
@ -1122,8 +1235,8 @@ ngx_http_cp_res_body_filter(ngx_http_request_t *request, ngx_chain_t *body_chain
|
||||
!ctx.modifications
|
||||
) {
|
||||
session_data_p->response_data.new_compression_type = NO_COMPRESSION;
|
||||
if (original_compressed_body) {
|
||||
copy_chain_buffers(body_chain, original_compressed_body);
|
||||
if (session_data_p->response_data.original_compressed_body) {
|
||||
copy_chain_buffers(body_chain, session_data_p->response_data.original_compressed_body);
|
||||
}
|
||||
return ngx_http_next_response_body_filter(request, body_chain);
|
||||
}
|
||||
|
@ -40,6 +40,12 @@ typedef struct {
|
||||
/// - #ZLIB
|
||||
CompressionType new_compression_type;
|
||||
|
||||
///< Original compressed body.
|
||||
ngx_chain_t* original_compressed_body;
|
||||
|
||||
///< NGINX pool.
|
||||
ngx_pool_t* request_pool;
|
||||
|
||||
/// Compression stream
|
||||
CompressionStream *compression_stream;
|
||||
|
||||
|
@ -103,6 +103,7 @@ ngx_msec_t keep_alive_interval_msec = DEFAULT_KEEP_ALIVE_INTERVAL_MSEC;
|
||||
ngx_uint_t min_retries_for_verdict = 3; ///< Minimum number of retries for verdict.
|
||||
ngx_uint_t max_retries_for_verdict = 15; ///< Maximum number of retries for verdict.
|
||||
ngx_uint_t body_size_trigger = 200000; ///< Request body size in bytes to switch to maximum retries for verdict.
|
||||
ngx_uint_t remove_res_server_header = 0; ///< Remove server header flag.
|
||||
|
||||
static struct timeval
|
||||
getCurrTimeFast()
|
||||
@ -954,6 +955,7 @@ init_general_config(const char *conf_path)
|
||||
min_retries_for_verdict = getMinRetriesForVerdict();
|
||||
max_retries_for_verdict = getMaxRetriesForVerdict();
|
||||
body_size_trigger = getReqBodySizeTrigger();
|
||||
remove_res_server_header = getRemoveResServerHeader();
|
||||
|
||||
num_of_nginx_ipc_elements = getNumOfNginxIpcElements();
|
||||
keep_alive_interval_msec = (ngx_msec_t) getKeepAliveIntervalMsec();
|
||||
|
@ -65,6 +65,7 @@ extern ngx_uint_t num_of_nginx_ipc_elements;
|
||||
extern ngx_uint_t min_retries_for_verdict;
|
||||
extern ngx_uint_t max_retries_for_verdict;
|
||||
extern ngx_uint_t body_size_trigger;
|
||||
extern ngx_uint_t remove_res_server_header;
|
||||
|
||||
///
|
||||
/// @struct ngx_http_cp_list_iterator
|
||||
|
@ -111,7 +111,8 @@ HttpAttachmentConfiguration::save(cereal::JSONOutputArchive &archive) const
|
||||
cereal::make_nvp("keep_alive_interval_msec", getNumericalValue("keep_alive_interval_msec")),
|
||||
cereal::make_nvp("min_retries_for_verdict", getNumericalValue("min_retries_for_verdict")),
|
||||
cereal::make_nvp("max_retries_for_verdict", getNumericalValue("max_retries_for_verdict")),
|
||||
cereal::make_nvp("body_size_trigger", getNumericalValue("body_size_trigger"))
|
||||
cereal::make_nvp("body_size_trigger", getNumericalValue("body_size_trigger")),
|
||||
cereal::make_nvp("remove_server_header", getNumericalValue("remove_server_header"))
|
||||
);
|
||||
}
|
||||
|
||||
@ -167,6 +168,7 @@ HttpAttachmentConfiguration::load(cereal::JSONInputArchive &archive)
|
||||
loadNumericalValue(archive, "min_retries_for_verdict", 3);
|
||||
loadNumericalValue(archive, "max_retries_for_verdict", 15);
|
||||
loadNumericalValue(archive, "body_size_trigger", 200000);
|
||||
loadNumericalValue(archive, "remove_server_header", 0);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -57,6 +57,7 @@ unsigned int getResBodyThreadTimeout();
|
||||
unsigned int getMinRetriesForVerdict();
|
||||
unsigned int getMaxRetriesForVerdict();
|
||||
unsigned int getReqBodySizeTrigger();
|
||||
unsigned int getRemoveResServerHeader();
|
||||
|
||||
unsigned int getWaitingForVerdictThreadTimeout();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user