Skip to content
Merged
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
39 changes: 23 additions & 16 deletions adapters/stormshield/connect.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
require_once 'smsd/sms_common.php';
require_once 'smsd/expect.php';
require_once 'smsd/generic_connection.php';

require_once load_once('stormshield', 'nsrpc.php');

require_once "$db_objects";

class connect extends GenericConnection {
Expand All @@ -21,6 +24,7 @@ class connect extends GenericConnection {
private $response;
private $cookie;
private $session_id;
private $curl_cmd;

public function __construct($ip = null, $login = null, $passwd = null, $admin_password = null, $port = null)
{
Expand Down Expand Up @@ -117,15 +121,6 @@ public function send($origin, $rest_cmd) {

$url = "https://{$this->sd_ip_config}/{$rest_path}";

$headers = '';
foreach ($this->http_header_list as $header) {
$H = trim($header);
$headers .= " -H '{$H}'";
}

// for debug
$curl_cmd = "curl -X {$http_op} {$headers} --connect-timeout {$this->conn_timeout} --max-time {$this->conn_timeout} -k '{$url}'";

if (count($cmd_list) > 2) {
if (isset($this->session_id)) {
$payload = $cmd_list[2];
Expand Down Expand Up @@ -157,14 +152,25 @@ public function send($origin, $rest_cmd) {
$rest_payload = '';
}

$curl_cmd .= " --data-raw '{$rest_payload}'";
$this->execute_curl_command($origin, $http_op, $url, $rest_payload);

debug_dump($curl_cmd, "HTTP REQUEST:\n");
$this->execute_curl_command($origin, $http_op, $url, $rest_payload, $curl_cmd);
debug_dump($this->response, "HTTP RESPONSE:\n");
$ret = is_error_xml($this->response);
if ($ret !== false)
{
throw new SmsException("Response to API {$this->curl_cmd} Failed: \n$ret", ERR_SD_CMDFAILED, $origin);
Comment on lines +157 to +160
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential null reference error. The function is_error_xml() is called with $this->response which may be null or unset. If the HTTP response is empty and the status code is 204, the response object is never initialized (see lines 229-231), but the error checking at line 157 will still execute. Add a check to ensure $this->response is set before calling is_error_xml(), or handle null/unset values within the is_error_xml() function.

Suggested change
$ret = is_error_xml($this->response);
if ($ret !== false)
{
throw new SmsException("Response to API {$this->curl_cmd} Failed: \n$ret", ERR_SD_CMDFAILED, $origin);
if ($this->response !== null && $this->response !== '') {
$ret = is_error_xml($this->response);
if ($ret !== false)
{
throw new SmsException("Response to API {$this->curl_cmd} Failed: \n$ret", ERR_SD_CMDFAILED, $origin);
}

Copilot uses AI. Check for mistakes.
}
}

private function execute_curl_command($origin, $http_op, $url, $rest_payload, $curl_cmd) {
private function execute_curl_command($origin, $http_op, $url, $rest_payload) {

// for debug
$headers = '';
foreach ($this->http_header_list as $h) {
$H = trim($h);
$headers .= " -H '{$H}'";
}
$this->curl_cmd = "curl -X {$http_op} {$headers} --connect-timeout {$this->conn_timeout} --max-time {$this->conn_timeout} -k '{$url}' --data-raw '{$rest_payload}'";
debug_dump($this->curl_cmd, "HTTP REQUEST:\n");

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
Expand Down Expand Up @@ -206,7 +212,7 @@ private function execute_curl_command($origin, $http_op, $url, $rest_payload, $c
if ($http_code < 200 || $http_code > 209) {
$cmd_quote = str_replace("\"", "'", $body);
$cmd_return = str_replace("\n", "", $cmd_quote);
throw new SmsException("Call to API {$curl_cmd} Failed, header = $header, $cmd_return error", ERR_SD_CMDFAILED, $origin);
throw new SmsException("Call to API {$this->curl_cmd} Failed, header = $header, $cmd_return error", ERR_SD_CMDFAILED, $origin);
}

if (!isset($this->cookie)) {
Expand All @@ -221,9 +227,10 @@ private function execute_curl_command($origin, $http_op, $url, $rest_payload, $c
else
{
if ($http_code != 204) {
throw new SmsException ("$origin: Response to API {$curl_cmd} Failed, expected json received empty response, header $header", ERR_SD_CMDFAILED);
throw new SmsException ("$origin: Response to API {$this->curl_cmd} Failed, expected json received empty response, header $header", ERR_SD_CMDFAILED);
}
}
debug_dump($this->response, "HTTP RESPONSE:\n");
Copy link

Copilot AI Jan 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug output moved to after potential exception. The debug_dump for "HTTP RESPONSE" has been moved from before the error checking (original position) to after the curl execution at line 233. This means that if an error occurs at lines 212-215 or 229-230, the response debug output will not be shown. Consider whether this is the intended behavior, as it may make debugging failed requests more difficult.

Copilot uses AI. Check for mistakes.
}
}

Expand Down
79 changes: 65 additions & 14 deletions adapters/stormshield/nsrpc.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@
206 licence restriction
*/

// return code considered as ok
$ok_return_code = array (
"100" => true,
"103" => true,
"104" => true,
"110" => true,
"111" => true,
);

// intermediate return code, it is normally followed by another return code
$not_a_return_code = array (
"101" => true,
"102" => true,
);


function get_return_codes(&$nsrpc_output)
{
define("RC_LEN", 3);
Expand Down Expand Up @@ -73,20 +89,8 @@ function get_return_codes(&$nsrpc_output)
*/
function is_error(&$nsrpc_output)
{
// return code considered as ok
$ok_return_code = array (
"100" => true,
"103" => true,
"104" => true,
"110" => true,
"111" => true,
);

// intermediate return code, it is normaly followed by another return code
$not_a_return_code = array (
"101" => true,
"102" => true,
);
global $ok_return_code;
global $not_a_return_code;

$rc_list = get_return_codes($nsrpc_output);

Expand All @@ -105,6 +109,53 @@ function is_error(&$nsrpc_output)
return false;
}

/*
* Get return codes of a SimpleXMLElement response from the managed entity
* and check if there is an error, stops at the first error
* return an error message if any, false otherwise
*/
function is_error_xml($xml)
{
global $ok_return_code;
global $not_a_return_code;

if (empty($xml))
{
return false;
}

$return_list = array();

if (isset($xml->command))
{
foreach ($xml->command as $command)
{
if (isset($command->serverd))
{
foreach ($command->serverd as $serverd)
{
if (isset($serverd['ret']))
{
$return_list[] = $serverd->attributes();
$rc = (string)$serverd['ret'];
if (empty($ok_return_code[$rc]) && empty($not_a_return_code[$rc]))
{
$err = '';
foreach ($return_list as $ret)
{
$err .= "ret={$ret['ret']}, code={$ret['code']}, msg={$ret['msg']} \n";
}
return $err;
}
}
}
}
}
}

return false;
}

/*
* Get the return code from $nsrpc_output for the command $cmd to see if a reboot is needed
* Assume no error, this means is_error() is called before
Expand Down