Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion appsec/src/extension/commands/request_shutdown.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "request_shutdown.h"
#include "../commands_helpers.h"
#include "../configuration.h"
#include "../ddappsec.h"
#include "../ddtrace.h"
#include "../entity_body.h"
Expand Down Expand Up @@ -62,7 +63,12 @@ static dd_result _request_pack(mpack_writer_t *nonnull w, void *nonnull ctx)
}
}

mpack_start_map(w, 2 + (Z_TYPE(resp_body) != IS_NULL ? 1 : 0));
bool send_raw_body = get_global_DD_APPSEC_RAW_RESPONSE_BODY_ENABLED() &&
req_info->entity != NULL && req_info->entity->len > 0;

uint32_t num_entries =
2 + (Z_TYPE(resp_body) != IS_NULL ? 1 : 0) + (send_raw_body ? 1 : 0);
mpack_start_map(w, num_entries);

// 1.1.
{
Expand Down Expand Up @@ -94,6 +100,13 @@ static dd_result _request_pack(mpack_writer_t *nonnull w, void *nonnull ctx)
}
}

// 1.4.?
if (send_raw_body) {
dd_mpack_write_lstr(w, "server.response.body.raw");
mpack_write_str(w, ZSTR_VAL(req_info->entity),
(uint32_t)ZSTR_LEN(req_info->entity));
}

mpack_finish_map(w);

// 2.
Expand Down
1 change: 1 addition & 0 deletions appsec/src/extension/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ extern bool runtime_config_first_init;
CONFIG(STRING, DD_AGENT_HOST, "localhost") \
CONFIG(INT, DD_TRACE_AGENT_PORT, "0") \
CONFIG(INT, DD_APPSEC_MAX_BODY_BUFF_SIZE, "524288") \
SYSCFG(BOOL, DD_APPSEC_RAW_RESPONSE_BODY_ENABLED, "false") \
CONFIG(STRING, DD_TRACE_AGENT_URL, "") \
CONFIG(BOOL, DD_TRACE_ENABLED, "true") \
CALIAS(CUSTOM(STRING), DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE, "ident", \
Expand Down
33 changes: 33 additions & 0 deletions appsec/tests/extension/rshutdown_command_raw_body_disabled.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
--TEST--
request_shutdown — server.response.body.raw not sent when feature is disabled (default)
--INI--
expose_php=0
datadog.appsec.enabled=1
--GET--
a=b
--FILE--
<?php
use function datadog\appsec\testing\{rinit,rshutdown};

include __DIR__ . '/inc/mock_helper.php';

$helper = Helper::createInitedRun([
response_list(response_request_init([[['ok', []]]])),
response_list(response_request_shutdown([[['ok', []]], new ArrayObject(), new ArrayObject()]))
]);

header('content-type: text/plain');
http_response_code(200);
var_dump(rinit());
echo "plain text body\n";
$helper->get_commands(); // ignore

var_dump(rshutdown());
$c = $helper->get_commands();
var_dump(array_key_exists('server.response.body.raw', $c[0][1][0]));
?>
--EXPECT--
bool(true)
plain text body
bool(true)
bool(false)
46 changes: 46 additions & 0 deletions appsec/tests/extension/rshutdown_command_raw_body_json.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
--TEST--
request_shutdown — server.response.body.raw sent alongside parsed server.response.body for JSON
--INI--
expose_php=0
datadog.appsec.enabled=1
datadog.appsec.raw_response_body_enabled=1
--GET--
a=b
--FILE--
<?php
use function datadog\appsec\testing\{rinit,rshutdown};

include __DIR__ . '/inc/mock_helper.php';

$helper = Helper::createInitedRun([
response_list(response_request_init([[['ok', []]]])),
response_list(response_request_shutdown([[['ok', []]], new ArrayObject(), new ArrayObject()]))
]);

header('content-type: application/json');
http_response_code(200);
var_dump(rinit());
echo '{"key":"value"}', "\n";
$helper->get_commands(); // ignore

var_dump(rshutdown());
$c = $helper->get_commands();
$data = $c[0][1][0];

// both structured and raw body are present
var_dump(isset($data['server.response.body']));
var_dump(isset($data['server.response.body.raw']));
print_r($data['server.response.body']);
echo $data['server.response.body.raw'];
?>
--EXPECT--
bool(true)
{"key":"value"}
bool(true)
bool(true)
bool(true)
Array
(
[key] => value
)
{"key":"value"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--TEST--
request_shutdown — server.response.body.raw sent for non-JSON/XML content types
--INI--
expose_php=0
datadog.appsec.enabled=1
datadog.appsec.raw_response_body_enabled=1
--GET--
a=b
--FILE--
<?php
use function datadog\appsec\testing\{rinit,rshutdown};

include __DIR__ . '/inc/mock_helper.php';

$helper = Helper::createInitedRun([
response_list(response_request_init([[['ok', []]]])),
response_list(response_request_shutdown([[['ok', []]], new ArrayObject(), new ArrayObject()]))
]);

header('content-type: text/plain');
http_response_code(200);
var_dump(rinit());
echo "plain text body\n";
$helper->get_commands(); // ignore

var_dump(rshutdown());
$c = $helper->get_commands();
$data = $c[0][1][0];

// server.response.body is absent for non-JSON/XML
var_dump(isset($data['server.response.body']));
// server.response.body.raw is present with the raw text
var_dump(isset($data['server.response.body.raw']));
echo $data['server.response.body.raw'];
?>
--EXPECT--
bool(true)
plain text body
bool(true)
bool(false)
bool(true)
plain text body
61 changes: 61 additions & 0 deletions appsec/tests/extension/rshutdown_command_raw_body_xml.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
--TEST--
request_shutdown — server.response.body.raw sent alongside parsed server.response.body for XML
--INI--
expose_php=0
datadog.appsec.enabled=1
datadog.appsec.raw_response_body_enabled=1
--GET--
a=b
--FILE--
<?php
use function datadog\appsec\testing\{rinit,rshutdown};

include __DIR__ . '/inc/mock_helper.php';

$helper = Helper::createInitedRun([
response_list(response_request_init([[['ok', []]]])),
response_list(response_request_shutdown([[['ok', []]], new ArrayObject(), new ArrayObject()]))
]);

header('content-type: application/xml');
http_response_code(200);
var_dump(rinit());
$xml = <<<XML
<?xml version="1.0" standalone="yes"?>
<foo attr="bar">baz</foo>
XML;
echo "$xml\n";
$helper->get_commands(); // ignore

var_dump(rshutdown());
$c = $helper->get_commands();
$data = $c[0][1][0];

// both structured and raw body are present
var_dump(isset($data['server.response.body']));
var_dump(isset($data['server.response.body.raw']));
print_r($data['server.response.body']);
echo $data['server.response.body.raw'];
?>
--EXPECT--
bool(true)
<?xml version="1.0" standalone="yes"?>
<foo attr="bar">baz</foo>
bool(true)
bool(true)
bool(true)
Array
(
[foo] => Array
(
[0] => Array
(
[@attr] => bar
)

[1] => baz
)

)
<?xml version="1.0" standalone="yes"?>
<foo attr="bar">baz</foo>
7 changes: 7 additions & 0 deletions metadata/supported-configurations.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,13 @@
"default": "true"
}
],
"DD_APPSEC_RAW_RESPONSE_BODY_ENABLED": [
{
"implementation": "A",
"type": "boolean",
"default": "false"
}
],
"DD_APPSEC_RULES": [
{
"implementation": "C",
Expand Down
2 changes: 1 addition & 1 deletion zend_abstract_interface/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ typedef uint16_t zai_config_id;
#include "config_ini.h"
#include "config_stable_file.h"

#define ZAI_CONFIG_ENTRIES_COUNT_MAX 300
#define ZAI_CONFIG_ENTRIES_COUNT_MAX 350
#define ZAI_CONFIG_NAMES_COUNT_MAX 4
#define ZAI_CONFIG_NAME_BUFSIZ 72

Expand Down
Loading