mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-13 08:09:41 +00:00
System: High Availability - XMLRPC Client / replace file_get_contents() with curl implementation, closes https://github.com/opnsense/core/issues/7561
While here, also offer optional peer tls verification as this is/was disabled by default. In most cases verification isn't very relevant when using a direct attached neighbor, but if someone has infrastructure in between, extra safeguards are now possible. With this inplace, allow_url_fopen can safely be disabled on our end (which was the primary goal here).
This commit is contained in:
parent
0bd12b5549
commit
3cbea52267
@ -72,6 +72,8 @@ function xmlrpc_execute($method, $params = [], $debug = false)
|
||||
$client->setCredentials($username, $hasync['password']);
|
||||
if ($client->query($method, $params)) {
|
||||
return $client->getResponse();
|
||||
} else {
|
||||
throw new Exception($client->error);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -159,11 +161,15 @@ class SimpleXMLRPC_Client
|
||||
*/
|
||||
public function setCredentials($username, $password)
|
||||
{
|
||||
$this->authHeader = 'Authorization: Basic ' . base64_encode("$username:$password") . "\r\n";
|
||||
$this->authHeader = 'Authorization: Basic ' . base64_encode("$username:$password");
|
||||
}
|
||||
|
||||
public function query()
|
||||
{
|
||||
/* XXX: xmlrpc is legacy, callers always import legacy config */
|
||||
global $config;
|
||||
$tls_verify = !empty($config['hasync']) && !empty($config['hasync']['verifypeer']);
|
||||
|
||||
// create xmlrpc request object
|
||||
$args = func_get_args();
|
||||
$method = array_shift($args);
|
||||
@ -171,38 +177,37 @@ class SimpleXMLRPC_Client
|
||||
$request_xml = $request->getXml();
|
||||
|
||||
// setup http headers
|
||||
$headers = 'Host: ' . $this->server . "\r\n";
|
||||
$headers .= "User-Agent: XML_RPC\r\n";
|
||||
$headers .= "Content-Type: text/xml\r\n";
|
||||
$headers .= 'Content-Length: ' . $request->getLength() . "\r\n";
|
||||
$headers = ['Host: ' . $this->server];
|
||||
$headers[] = "User-Agent: XML_RPC";
|
||||
$headers[] = "Content-Type: text/xml";
|
||||
if ($this->authHeader != null) {
|
||||
$headers .= $this->authHeader;
|
||||
$headers[] = $this->authHeader;
|
||||
}
|
||||
|
||||
$this->request_send = $headers . $request_xml;
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $this->url);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
|
||||
if (!$tls_verify) {
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $request_xml);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
$this->response_received = curl_exec($ch);
|
||||
if ($this->debug) {
|
||||
echo sprintf(">>> send %d bytes: \n%s\n", strlen($this->request_send), $this->request_send);
|
||||
print_r(curl_getinfo($ch));
|
||||
}
|
||||
|
||||
// setup a stream context
|
||||
$context = stream_context_create(array('http' => array(
|
||||
'method' => "POST",
|
||||
'header' => $headers,
|
||||
'content' => $request_xml,
|
||||
'timeout' => $this->timeout
|
||||
),
|
||||
"ssl" => array(
|
||||
"verify_peer" => false,
|
||||
"verify_peer_name" => false,
|
||||
)
|
||||
));
|
||||
|
||||
$this->response_received = @file_get_contents($this->url, false, $context);
|
||||
if ($this->response_received === false) {
|
||||
$this->error = 'fetch error. remote host down?';
|
||||
$this->error = 'fetch error. remote host down? (' . curl_error($ch) . ')';
|
||||
curl_close($ch);
|
||||
return false;
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
if ($this->debug) {
|
||||
echo sprintf(">>> received %d bytes: \n%s\n", strlen($this->response_received), $this->response_received);
|
||||
}
|
||||
|
||||
@ -185,7 +185,7 @@ EOF;
|
||||
$php_ini = <<<EOF
|
||||
; File generated via recovery
|
||||
output_buffering = "0"
|
||||
; allow_url_fopen = "0"
|
||||
allow_url_fopen = "0"
|
||||
expose_php = Off
|
||||
enable_dl = Off
|
||||
implicit_flush = true
|
||||
|
||||
@ -50,6 +50,12 @@
|
||||
This should be empty on the backup machine. When an IP address is offered, both web GUI configurations should be equal (port and protocol).
|
||||
</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>hasync.verifypeer</id>
|
||||
<label>Verify peer</label>
|
||||
<type>checkbox</type>
|
||||
<help>In most cases the target host will be a directly attached neighbor in which case TLS verification can be ignored.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>hasync.username</id>
|
||||
<label>Remote System Username</label>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<model>
|
||||
<mount>//hasync</mount>
|
||||
<migration_prefix>MHA</migration_prefix>
|
||||
<version>1.0.1</version>
|
||||
<version>1.0.2</version>
|
||||
<description>HA sync</description>
|
||||
<items>
|
||||
<disablepreempt type="BooleanField">
|
||||
@ -31,6 +31,10 @@
|
||||
</OptionValues>
|
||||
</pfsyncversion>
|
||||
<synchronizetoip type="TextField"/> <!-- XXX: accepts uri or address -->
|
||||
<verifypeer type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</verifypeer>
|
||||
<username type="TextField"/>
|
||||
<password type="TextField"/> <!-- XXX -->
|
||||
<syncitems type="JsonKeyValueStoreField">
|
||||
|
||||
@ -35,37 +35,41 @@ $action = $argv[1] ?? '';
|
||||
$service = $argv[2] ?? '';
|
||||
$service_id = $argv[3] ?? '';
|
||||
|
||||
switch ($action) {
|
||||
case 'stop':
|
||||
$result = xmlrpc_execute('opnsense.stop_service', ['service' => $service, 'id' => $service_id]);
|
||||
echo json_encode(['response' => $result, 'status' => 'ok']);
|
||||
break;
|
||||
case 'start':
|
||||
$result = xmlrpc_execute('opnsense.start_service', ['service' => $service, 'id' => $service_id]);
|
||||
echo json_encode(['response' => $result, 'status' => 'ok']);
|
||||
break;
|
||||
case 'restart':
|
||||
$result = xmlrpc_execute('opnsense.restart_service', ['service' => $service, 'id' => $service_id]);
|
||||
echo json_encode(['response' => $result, 'status' => 'ok']);
|
||||
break;
|
||||
case 'reload_templates':
|
||||
xmlrpc_execute('opnsense.configd_reload_all_templates');
|
||||
echo json_encode(['status' => 'done']);
|
||||
break;
|
||||
case 'exec_sync':
|
||||
configd_run('filter sync');
|
||||
echo json_encode(['status' => 'done']);
|
||||
break;
|
||||
case 'version':
|
||||
$payload = xmlrpc_execute('opnsense.firmware_version');
|
||||
if (isset($payload['firmware'])) {
|
||||
$payload['firmware']['_my_version'] = shell_safe('opnsense-version -v core');
|
||||
}
|
||||
echo json_encode(['response' => $payload]);
|
||||
break;
|
||||
case 'services':
|
||||
echo json_encode(['response' => xmlrpc_execute('opnsense.list_services')]);
|
||||
break;
|
||||
default:
|
||||
echo json_encode(['status' => 'error', 'message' => 'usage ha_xmlrpc_exec.php action [service_id]']);
|
||||
try {
|
||||
switch ($action) {
|
||||
case 'stop':
|
||||
$result = xmlrpc_execute('opnsense.stop_service', ['service' => $service, 'id' => $service_id]);
|
||||
echo json_encode(['response' => $result, 'status' => 'ok']);
|
||||
break;
|
||||
case 'start':
|
||||
$result = xmlrpc_execute('opnsense.start_service', ['service' => $service, 'id' => $service_id]);
|
||||
echo json_encode(['response' => $result, 'status' => 'ok']);
|
||||
break;
|
||||
case 'restart':
|
||||
$result = xmlrpc_execute('opnsense.restart_service', ['service' => $service, 'id' => $service_id]);
|
||||
echo json_encode(['response' => $result, 'status' => 'ok']);
|
||||
break;
|
||||
case 'reload_templates':
|
||||
xmlrpc_execute('opnsense.configd_reload_all_templates');
|
||||
echo json_encode(['status' => 'done']);
|
||||
break;
|
||||
case 'exec_sync':
|
||||
configd_run('filter sync');
|
||||
echo json_encode(['status' => 'done']);
|
||||
break;
|
||||
case 'version':
|
||||
$payload = xmlrpc_execute('opnsense.firmware_version');
|
||||
if (isset($payload['firmware'])) {
|
||||
$payload['firmware']['_my_version'] = shell_safe('opnsense-version -v core');
|
||||
}
|
||||
echo json_encode(['response' => $payload]);
|
||||
break;
|
||||
case 'services':
|
||||
echo json_encode(['response' => xmlrpc_execute('opnsense.list_services')]);
|
||||
break;
|
||||
default:
|
||||
echo json_encode(['status' => 'error', 'message' => 'usage ha_xmlrpc_exec.php action [service_id]']);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
; File generated via configd
|
||||
output_buffering = "0"
|
||||
; allow_url_fopen = "0"
|
||||
allow_url_fopen = "0"
|
||||
expose_php = Off
|
||||
enable_dl = Off
|
||||
implicit_flush = true
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user