Revision f81e7cc4
Added by Renato Botelho almost 9 years ago
src/usr/local/www/xmlrpc.php | ||
---|---|---|
29 | 29 |
|
30 | 30 |
require_once("config.inc"); |
31 | 31 |
require_once("functions.inc"); |
32 |
require_once("auth.inc"); |
|
32 | 33 |
require_once("filter.inc"); |
33 | 34 |
require_once("ipsec.inc"); |
34 | 35 |
require_once("vpn.inc"); |
35 | 36 |
require_once("shaper.inc"); |
36 |
require_once("xmlrpc_server.inc"); |
|
37 |
require_once("xmlrpc.inc"); |
|
37 |
require_once("XML/RPC2/Server.php"); |
|
38 | 38 |
|
39 |
function xmlrpc_loop_detect() { |
|
40 |
global $config; |
|
39 |
class pfsense_xmlrpc_server { |
|
41 | 40 |
|
42 |
/* grab sync to ip if enabled */ |
|
43 |
if ($config['hasync']) { |
|
44 |
$synchronizetoip = $config['hasync']['synchronizetoip']; |
|
45 |
} |
|
46 |
if ($synchronizetoip) { |
|
47 |
if ($synchronizetoip == $_SERVER['REMOTE_ADDR']) { |
|
48 |
return true; |
|
49 |
} |
|
50 |
} |
|
41 |
private $loop_detected = false; |
|
42 |
private $remote_addr; |
|
51 | 43 |
|
52 |
return false; |
|
53 |
} |
|
54 |
|
|
55 |
$xmlrpc_g = array( |
|
56 |
"return" => array( |
|
57 |
"true" => new XML_RPC_Response(new XML_RPC_Value(true, $XML_RPC_Boolean)), |
|
58 |
"false" => new XML_RPC_Response(new XML_RPC_Value(false, $XML_RPC_Boolean)), |
|
59 |
"authfail" => new XML_RPC_Response(new XML_RPC_Value(gettext("Authentication failed"), $XML_RPC_String)) |
|
60 |
) |
|
61 |
); |
|
44 |
private function auth($username, $password) { |
|
45 |
global $config; |
|
62 | 46 |
|
63 |
/* |
|
64 |
* pfSense XMLRPC errors |
|
65 |
* $XML_RPC_erruser + 1 = Auth failure |
|
66 |
*/ |
|
67 |
$XML_RPC_erruser = 200; |
|
68 |
|
|
69 |
/* EXPOSED FUNCTIONS */ |
|
70 |
$exec_php_doc = gettext("XMLRPC wrapper for eval(). This method must be called with two parameters: a string containing the local system\'s password followed by the PHP code to evaluate."); |
|
71 |
$exec_php_sig = array( |
|
72 |
array( |
|
73 |
$XML_RPC_Boolean, // First signature element is return value. |
|
74 |
$XML_RPC_String, // password |
|
75 |
$XML_RPC_String, // shell code to exec |
|
76 |
) |
|
77 |
); |
|
47 |
if (!empty($username) && !empty($password)) { |
|
48 |
$attributes = array(); |
|
49 |
$authcfg = auth_get_authserver( |
|
50 |
$config['system']['webgui']['authmode']); |
|
78 | 51 |
|
79 |
function xmlrpc_authfail() { |
|
80 |
log_auth("webConfigurator authentication error for 'admin' from {$_SERVER['REMOTE_ADDR']}"); |
|
81 |
} |
|
52 |
if (authenticate_user($username, $password, |
|
53 |
$authcfg, $attributes) || |
|
54 |
authenticate_user($username, $password)) { |
|
55 |
return; |
|
56 |
} |
|
57 |
} |
|
82 | 58 |
|
83 |
function exec_php_xmlrpc($raw_params) {
|
|
84 |
global $config, $xmlrpc_g;
|
|
59 |
log_auth("webConfigurator authentication error for '" .
|
|
60 |
$username . "' from " . $this->remote_addr);
|
|
85 | 61 |
|
86 |
$params = xmlrpc_params_to_php($raw_params); |
|
87 |
if (!xmlrpc_auth($params)) { |
|
88 |
xmlrpc_authfail(); |
|
89 |
return $xmlrpc_g['return']['authfail']; |
|
62 |
require_once("XML/RPC2/Exception.php"); |
|
63 |
throw new XML_RPC2_FaultException( |
|
64 |
gettext('Authentication failed'), -1); |
|
90 | 65 |
} |
91 |
$exec_php = $params[0]; |
|
92 |
eval($exec_php); |
|
93 |
if ($toreturn) { |
|
94 |
$response = XML_RPC_encode($toreturn); |
|
95 |
return new XML_RPC_Response($response); |
|
96 |
} else { |
|
97 |
return $xmlrpc_g['return']['true']; |
|
66 |
|
|
67 |
private function array_overlay($a1, $a2) { |
|
68 |
foreach ($a1 as $k => $v) { |
|
69 |
if (!array_key_exists($k, $a2)) { |
|
70 |
continue; |
|
71 |
} |
|
72 |
if (is_array($v) && is_array($a2[$k])) { |
|
73 |
$a1[$k] = $this->array_overlay($v, $a2[$k]); |
|
74 |
} else { |
|
75 |
$a1[$k] = $a2[$k]; |
|
76 |
} |
|
77 |
} |
|
78 |
|
|
79 |
return $a1; |
|
98 | 80 |
} |
99 |
} |
|
100 | 81 |
|
101 |
/*****************************/ |
|
102 |
$exec_shell_doc = gettext("XMLRPC wrapper for mwexec(). This method must be called with two parameters: a string containing the local system\'s password followed by an shell command to execute."); |
|
103 |
$exec_shell_sig = array( |
|
104 |
array( |
|
105 |
$XML_RPC_Boolean, // First signature element is return value. |
|
106 |
$XML_RPC_String, // password |
|
107 |
$XML_RPC_String, // shell code to exec |
|
108 |
) |
|
109 |
); |
|
82 |
public function __construct() { |
|
83 |
global $config; |
|
110 | 84 |
|
111 |
function exec_shell_xmlrpc($raw_params) { |
|
112 |
global $config, $xmlrpc_g; |
|
85 |
$this->remote_addr = $_SERVER['remote_addr']; |
|
113 | 86 |
|
114 |
$params = xmlrpc_params_to_php($raw_params); |
|
115 |
if (!xmlrpc_auth($params)) { |
|
116 |
xmlrpc_authfail(); |
|
117 |
return $xmlrpc_g['return']['authfail']; |
|
87 |
/* grab sync to ip if enabled */ |
|
88 |
if (isset($config['hasync']['synchronizetoip']) && |
|
89 |
$config['hasync']['synchronizetoip'] == $remote_addr) { |
|
90 |
$this->loop_detected = true; |
|
91 |
} |
|
118 | 92 |
} |
119 |
$shell_cmd = $params[0]; |
|
120 |
mwexec($shell_cmd); |
|
121 | 93 |
|
122 |
return $xmlrpc_g['return']['true']; |
|
123 |
} |
|
94 |
/** |
|
95 |
* Get host version information |
|
96 |
* |
|
97 |
* @param string $username |
|
98 |
* @param string $password |
|
99 |
* |
|
100 |
* @return array |
|
101 |
*/ |
|
102 |
public function host_firmware_version($username, $password) { |
|
103 |
$this->auth($username, $password); |
|
124 | 104 |
|
125 |
/*****************************/ |
|
126 |
$backup_config_section_doc = gettext("XMLRPC wrapper for backup_config_section. This method must be called with two parameters: a string containing the local system\'s password followed by an array containing the keys to be backed up."); |
|
127 |
$backup_config_section_sig = array( |
|
128 |
array( |
|
129 |
$XML_RPC_Struct, // First signature element is return value. |
|
130 |
$XML_RPC_String, |
|
131 |
$XML_RPC_Array |
|
132 |
) |
|
133 |
); |
|
105 |
return host_firmware_version(); |
|
106 |
} |
|
134 | 107 |
|
135 |
function backup_config_section_xmlrpc($raw_params) { |
|
136 |
global $config, $xmlrpc_g; |
|
108 |
/** |
|
109 |
* Executes a PHP block of code |
|
110 |
* |
|
111 |
* @param string $username |
|
112 |
* @param string $password |
|
113 |
* @param string $code |
|
114 |
* |
|
115 |
* @return bool |
|
116 |
*/ |
|
117 |
public function exec_php($username, $password, $code) { |
|
118 |
$this->auth($username, $password); |
|
137 | 119 |
|
138 |
if (xmlrpc_loop_detect()) {
|
|
139 |
log_error("Disallowing CARP sync loop");
|
|
140 |
return; |
|
141 |
} |
|
120 |
eval($code);
|
|
121 |
if ($toreturn) {
|
|
122 |
return $toreturn;
|
|
123 |
}
|
|
142 | 124 |
|
143 |
$params = xmlrpc_params_to_php($raw_params); |
|
144 |
if (!xmlrpc_auth($params)) { |
|
145 |
xmlrpc_authfail(); |
|
146 |
return $xmlrpc_g['return']['authfail']; |
|
125 |
return true; |
|
147 | 126 |
} |
148 |
$val = array_intersect_key($config, array_flip($params[0])); |
|
149 | 127 |
|
150 |
return new XML_RPC_Response(XML_RPC_encode($val)); |
|
151 |
} |
|
128 |
/** |
|
129 |
* Executes shell commands |
|
130 |
* |
|
131 |
* @param string $username |
|
132 |
* @param string $password |
|
133 |
* @param string $code |
|
134 |
* |
|
135 |
* @return bool |
|
136 |
*/ |
|
137 |
public function exec_shell($username, $password, $code) { |
|
138 |
$this->auth($username, $password); |
|
152 | 139 |
|
153 |
/*****************************/ |
|
154 |
$restore_config_section_doc = gettext("XMLRPC wrapper for restore_config_section. This method must be called with two parameters: a string containing the local system\'s password and an array to merge into the system\'s config. This function returns true upon completion."); |
|
155 |
$restore_config_section_sig = array( |
|
156 |
array( |
|
157 |
$XML_RPC_Boolean, |
|
158 |
$XML_RPC_String, |
|
159 |
$XML_RPC_Struct |
|
160 |
) |
|
161 |
); |
|
140 |
mwexec($code); |
|
141 |
return true; |
|
142 |
} |
|
162 | 143 |
|
163 |
function restore_config_section_xmlrpc($raw_params) { |
|
164 |
global $config, $xmlrpc_g; |
|
144 |
/** |
|
145 |
* Backup chosen config sections |
|
146 |
* |
|
147 |
* @param string $username |
|
148 |
* @param string $password |
|
149 |
* @param array $section |
|
150 |
* |
|
151 |
* @return array |
|
152 |
*/ |
|
153 |
public function backup_config_section($username, $password, $section) { |
|
154 |
$this->auth($username, $password); |
|
165 | 155 |
|
166 |
$old_config = $config; |
|
167 |
$old_ipsec_enabled = ipsec_enabled(); |
|
156 |
global $config; |
|
168 | 157 |
|
169 |
if (xmlrpc_loop_detect()) { |
|
170 |
log_error("Disallowing CARP sync loop"); |
|
171 |
return; |
|
158 |
return array_intersect_key($config, array_flip($section)); |
|
172 | 159 |
} |
173 | 160 |
|
174 |
$params = xmlrpc_params_to_php($raw_params); |
|
175 |
if (!xmlrpc_auth($params)) { |
|
176 |
xmlrpc_authfail(); |
|
177 |
return $xmlrpc_g['return']['authfail']; |
|
178 |
} |
|
161 |
/** |
|
162 |
* Restore defined config section into local config |
|
163 |
* |
|
164 |
* @param string $username |
|
165 |
* @param string $password |
|
166 |
* @param array $sections |
|
167 |
* |
|
168 |
* @return bool |
|
169 |
*/ |
|
170 |
public function restore_config_section($username, $password, $sections) { |
|
171 |
$this->auth($username, $password); |
|
172 |
|
|
173 |
global $config; |
|
179 | 174 |
|
180 |
// Some sections should just be copied and not merged or we end |
|
181 |
// up unable to sync the deletion of the last item in a section |
|
182 |
$sync_full = array('dnsmasq', 'unbound', 'ipsec', 'aliases', 'wol', 'load_balancer', 'openvpn', 'cert', 'ca', 'crl', 'schedules', 'filter', 'nat', 'dhcpd', 'dhcpv6'); |
|
183 |
$sync_full_done = array(); |
|
184 |
foreach ($sync_full as $syncfull) { |
|
185 |
if (isset($params[0][$syncfull])) { |
|
186 |
$config[$syncfull] = $params[0][$syncfull]; |
|
187 |
unset($params[0][$syncfull]); |
|
188 |
$sync_full_done[] = $syncfull; |
|
175 |
$old_config = $config; |
|
176 |
$old_ipsec_enabled = ipsec_enabled(); |
|
177 |
|
|
178 |
if ($this->loop_detected) { |
|
179 |
log_error("Disallowing CARP sync loop"); |
|
180 |
return true; |
|
181 |
} |
|
182 |
|
|
183 |
/* |
|
184 |
* Some sections should just be copied and not merged or we end |
|
185 |
* up unable to sync the deletion of the last item in a section |
|
186 |
*/ |
|
187 |
$sync_full_sections = array( |
|
188 |
'aliases', |
|
189 |
'ca', |
|
190 |
'cert', |
|
191 |
'crl', |
|
192 |
'dhcpd', |
|
193 |
'dhcpv6', |
|
194 |
'dnsmasq', |
|
195 |
'filter', |
|
196 |
'ipsec', |
|
197 |
'load_balancer', |
|
198 |
'nat', |
|
199 |
'openvpn', |
|
200 |
'schedules', |
|
201 |
'unbound', |
|
202 |
'wol', |
|
203 |
); |
|
204 |
|
|
205 |
$syncd_full_sections = array(); |
|
206 |
|
|
207 |
foreach ($sync_full_sections as $section) { |
|
208 |
if (!isset($sections[$section])) { |
|
209 |
continue; |
|
210 |
} |
|
211 |
|
|
212 |
$config[$section] = $sections[$section]; |
|
213 |
unset($sections[$section]); |
|
214 |
$syncd_full_sections[] = $section; |
|
189 | 215 |
} |
190 |
} |
|
191 | 216 |
|
192 |
$vipbackup = array(); |
|
193 |
$oldvips = array(); |
|
194 |
if (isset($params[0]['virtualip'])) {
|
|
195 |
if (is_array($config['virtualip']['vip'])) {
|
|
196 |
foreach ($config['virtualip']['vip'] as $vipindex => $vip) {
|
|
217 |
$vipbackup = array();
|
|
218 |
$oldvips = array();
|
|
219 |
if (isset($sections['virtualip']) &&
|
|
220 |
is_array($config['virtualip']['vip'])) {
|
|
221 |
foreach ($config['virtualip']['vip'] as $vip) { |
|
197 | 222 |
if ($vip['mode'] == "carp") { |
198 |
$oldvips["{$vip['interface']}_vip{$vip['vhid']}"]['content'] = "{$vip['password']}{$vip['advskew']}{$vip['subnet']}{$vip['subnet_bits']}{$vip['advbase']}"; |
|
199 |
$oldvips["{$vip['interface']}_vip{$vip['vhid']}"]['interface'] = $vip['interface']; |
|
200 |
$oldvips["{$vip['interface']}_vip{$vip['vhid']}"]['subnet'] = $vip['subnet']; |
|
201 |
} else if ($vip['mode'] == "ipalias" && (substr($vip['interface'], 0, 4) == '_vip' || strstr($vip['interface'], "lo0"))) { |
|
202 |
$oldvips[$vip['subnet']]['content'] = "{$vip['interface']}{$vip['subnet']}{$vip['subnet_bits']}"; |
|
203 |
$oldvips[$vip['subnet']]['interface'] = $vip['interface']; |
|
204 |
$oldvips[$vip['subnet']]['subnet'] = $vip['subnet']; |
|
205 |
} else if (($vip['mode'] == "ipalias" || $vip['mode'] == 'proxyarp') && !(substr($vip['interface'], 0, 4) == '_vip') || strstr($vip['interface'], "lo0")) { |
|
223 |
$key = $vip['interface'] . |
|
224 |
"_vip" . $vip['vhid']; |
|
225 |
|
|
226 |
$oldvips[$key]['content'] = |
|
227 |
$vip['password'] . |
|
228 |
$vip['advskew'] . |
|
229 |
$vip['subnet'] . |
|
230 |
$vip['subnet_bits'] . |
|
231 |
$vip['advbase']; |
|
232 |
$oldvips[$key]['interface'] = |
|
233 |
$vip['interface']; |
|
234 |
$oldvips[$key]['subnet'] = |
|
235 |
$vip['subnet']; |
|
236 |
} else if ($vip['mode'] == "ipalias" && |
|
237 |
(substr($vip['interface'], 0, 4) == '_vip' |
|
238 |
|| strstr($vip['interface'], "lo0"))) { |
|
239 |
$oldvips[$vip['subnet']]['content'] = |
|
240 |
$vip['interface'] . |
|
241 |
$vip['subnet'] . |
|
242 |
$vip['subnet_bits']; |
|
243 |
$oldvips[$vip['subnet']]['interface'] = |
|
244 |
$vip['interface']; |
|
245 |
$oldvips[$vip['subnet']]['subnet'] = |
|
246 |
$vip['subnet']; |
|
247 |
} else if (($vip['mode'] == "ipalias" || |
|
248 |
$vip['mode'] == 'proxyarp') && |
|
249 |
!(substr($vip['interface'], 0, 4) == '_vip') |
|
250 |
|| strstr($vip['interface'], "lo0")) { |
|
206 | 251 |
$vipbackup[] = $vip; |
207 | 252 |
} |
208 | 253 |
} |
209 | 254 |
} |
210 |
} |
|
211 | 255 |
|
212 |
// For vip section, first keep items sent from the master
|
|
213 |
$config = array_merge_recursive_unique($config, $params[0]);
|
|
256 |
/* For vip section, first keep items sent from the master */
|
|
257 |
$config = array_merge_recursive_unique($config, $sections);
|
|
214 | 258 |
|
215 |
/* Then add ipalias and proxyarp types already defined on the backup */ |
|
216 |
if (is_array($vipbackup) && !empty($vipbackup)) { |
|
217 |
if (!is_array($config['virtualip'])) { |
|
218 |
$config['virtualip'] = array(); |
|
219 |
} |
|
220 |
if (!is_array($config['virtualip']['vip'])) { |
|
221 |
$config['virtualip']['vip'] = array(); |
|
222 |
} |
|
223 |
foreach ($vipbackup as $vip) { |
|
224 |
array_unshift($config['virtualip']['vip'], $vip); |
|
259 |
/* |
|
260 |
* Then add ipalias and proxyarp types already defined |
|
261 |
* on the backup |
|
262 |
*/ |
|
263 |
if (is_array($vipbackup) && !empty($vipbackup)) { |
|
264 |
if (!is_array($config['virtualip'])) { |
|
265 |
$config['virtualip'] = array(); |
|
266 |
} |
|
267 |
if (!is_array($config['virtualip']['vip'])) { |
|
268 |
$config['virtualip']['vip'] = array(); |
|
269 |
} |
|
270 |
foreach ($vipbackup as $vip) { |
|
271 |
array_unshift($config['virtualip']['vip'], $vip); |
|
272 |
} |
|
225 | 273 |
} |
226 |
} |
|
227 | 274 |
|
228 |
/* Log what happened */ |
|
229 |
$mergedkeys = implode(",", array_merge(array_keys($params[0]), $sync_full_done)); |
|
230 |
write_config(sprintf(gettext("Merged in config (%s sections) from XMLRPC client."), $mergedkeys)); |
|
231 |
|
|
232 |
/* |
|
233 |
* The real work on handling the vips specially |
|
234 |
* This is a copy of intefaces_vips_configure with addition of not reloading existing/not changed carps |
|
235 |
*/ |
|
236 |
if (isset($params[0]['virtualip']) && is_array($config['virtualip']) && is_array($config['virtualip']['vip'])) { |
|
237 |
$carp_setuped = false; |
|
238 |
$anyproxyarp = false; |
|
239 |
foreach ($config['virtualip']['vip'] as $vip) { |
|
240 |
if ($vip['mode'] == "carp" && isset($oldvips["{$vip['interface']}_vip{$vip['vhid']}"])) { |
|
241 |
if ($oldvips["{$vip['interface']}_vip{$vip['vhid']}"]['content'] == "{$vip['password']}{$vip['advskew']}{$vip['subnet']}{$vip['subnet_bits']}{$vip['advbase']}") { |
|
242 |
if (does_vip_exist($vip)) { |
|
243 |
unset($oldvips["{$vip['interface']}_vip{$vip['vhid']}"]); |
|
244 |
continue; // Skip reconfiguring this vips since nothing has changed. |
|
275 |
/* Log what happened */ |
|
276 |
$mergedkeys = implode(",", array_merge(array_keys($sections), |
|
277 |
$syncd_full_sections)); |
|
278 |
write_config(sprintf(gettext( |
|
279 |
"Merged in config (%s sections) from XMLRPC client."), |
|
280 |
$mergedkeys)); |
|
281 |
|
|
282 |
/* |
|
283 |
* The real work on handling the vips specially |
|
284 |
* This is a copy of intefaces_vips_configure with addition of |
|
285 |
* not reloading existing/not changed carps |
|
286 |
*/ |
|
287 |
if (isset($sections['virtualip']) && |
|
288 |
is_array($config['virtualip']) && |
|
289 |
is_array($config['virtualip']['vip'])) { |
|
290 |
$carp_setuped = false; |
|
291 |
$anyproxyarp = false; |
|
292 |
|
|
293 |
foreach ($config['virtualip']['vip'] as $vip) { |
|
294 |
$key = "{$vip['interface']}_vip{$vip['vhid']}"; |
|
295 |
|
|
296 |
if ($vip['mode'] == "carp" && |
|
297 |
isset($oldvips[$key])) { |
|
298 |
if ($oldvips[$key]['content'] == |
|
299 |
$vip['password'] . |
|
300 |
$vip['advskew'] . |
|
301 |
$vip['subnet'] . |
|
302 |
$vip['subnet_bits'] . |
|
303 |
$vip['advbase'] && |
|
304 |
does_vip_exist($vip)) { |
|
305 |
unset($oldvips[$key]); |
|
306 |
/* |
|
307 |
* Skip reconfiguring this vips |
|
308 |
* since nothing has changed. |
|
309 |
*/ |
|
310 |
continue; |
|
245 | 311 |
} |
246 |
} |
|
247 |
} else if ($vip['mode'] == "ipalias" && strstr($vip['interface'], "_vip") && isset($oldvips[$vip['subnet']])) { |
|
248 |
if ($oldvips[$vip['subnet']]['content'] == "{$vip['interface']}{$vip['subnet']}{$vip['subnet_bits']}") { |
|
249 |
if (does_vip_exist($vip)) { |
|
250 |
unset($oldvips[$vip['subnet']]); |
|
251 |
continue; // Skip reconfiguring this vips since nothing has changed. |
|
312 |
} elseif ($vip['mode'] == "ipalias" && |
|
313 |
strstr($vip['interface'], "_vip") && |
|
314 |
isset($oldvips[$vip['subnet']])) { |
|
315 |
|
|
316 |
$key = $vip['subnet']; |
|
317 |
if ($oldvips[$key]['content'] == |
|
318 |
$vip['interface'] . |
|
319 |
$vip['subnet'] . |
|
320 |
$vip['subnet_bits'] && |
|
321 |
does_vip_exist($vip)) { |
|
322 |
unset($oldvips[$key]); |
|
323 |
/* |
|
324 |
* Skip reconfiguring this vips |
|
325 |
* since nothing has changed. |
|
326 |
*/ |
|
327 |
continue; |
|
252 | 328 |
} |
329 |
unset($oldvips[$key]); |
|
253 | 330 |
} |
254 |
unset($oldvips[$vip['subnet']]); |
|
255 |
} |
|
256 | 331 |
|
257 |
switch ($vip['mode']) { |
|
332 |
switch ($vip['mode']) {
|
|
258 | 333 |
case "proxyarp": |
259 | 334 |
$anyproxyarp = true; |
260 | 335 |
break; |
... | ... | |
262 | 337 |
interface_ipalias_configure($vip); |
263 | 338 |
break; |
264 | 339 |
case "carp": |
265 |
if ($carp_setuped == false) { |
|
266 |
$carp_setuped = true; |
|
267 |
} |
|
340 |
$carp_setuped = true; |
|
268 | 341 |
interface_carp_configure($vip); |
269 | 342 |
break; |
343 |
} |
|
270 | 344 |
} |
271 |
} |
|
272 |
/* Cleanup remaining old carps */ |
|
273 |
foreach ($oldvips as $oldvipar) { |
|
274 |
$oldvipif = get_real_interface($oldvipar['interface']); |
|
275 |
if (!empty($oldvipif)) { |
|
345 |
|
|
346 |
/* Cleanup remaining old carps */ |
|
347 |
foreach ($oldvips as $oldvipar) { |
|
348 |
$oldvipif = get_real_interface( |
|
349 |
$oldvipar['interface']); |
|
350 |
|
|
351 |
if (empty($oldvipif)) { |
|
352 |
continue; |
|
353 |
} |
|
354 |
|
|
276 | 355 |
if (is_ipaddrv6($oldvipar['subnet'])) { |
277 |
mwexec("/sbin/ifconfig " . escapeshellarg($oldvipif) . " inet6 " . escapeshellarg($oldvipar['subnet']) . " delete"); |
|
356 |
mwexec("/sbin/ifconfig " . |
|
357 |
escapeshellarg($oldvipif) . |
|
358 |
" inet6 " . |
|
359 |
escapeshellarg($oldvipar['subnet']) . |
|
360 |
" delete"); |
|
278 | 361 |
} else { |
279 |
pfSense_interface_deladdress($oldvipif, $oldvipar['subnet']); |
|
362 |
pfSense_interface_deladdress($oldvipif, |
|
363 |
$oldvipar['subnet']); |
|
280 | 364 |
} |
281 | 365 |
} |
366 |
if ($carp_setuped == true) { |
|
367 |
interfaces_sync_setup(); |
|
368 |
} |
|
369 |
if ($anyproxyarp == true) { |
|
370 |
interface_proxyarp_configure(); |
|
371 |
} |
|
282 | 372 |
} |
283 |
if ($carp_setuped == true) { |
|
284 |
interfaces_sync_setup(); |
|
285 |
} |
|
286 |
if ($anyproxyarp == true) { |
|
287 |
interface_proxyarp_configure(); |
|
373 |
|
|
374 |
if ($old_ipsec_enabled !== ipsec_enabled()) { |
|
375 |
vpn_ipsec_configure(); |
|
288 | 376 |
} |
289 |
} |
|
290 | 377 |
|
291 |
if ($old_ipsec_enabled !== ipsec_enabled()) { |
|
292 |
vpn_ipsec_configure(); |
|
378 |
unset($old_config); |
|
379 |
|
|
380 |
return true; |
|
293 | 381 |
} |
294 | 382 |
|
295 |
unset($old_config); |
|
383 |
/** |
|
384 |
* Merge items into installedpackages config section |
|
385 |
* |
|
386 |
* @param string $username |
|
387 |
* @param string $password |
|
388 |
* @param array $section |
|
389 |
* |
|
390 |
* @return bool |
|
391 |
*/ |
|
392 |
public function merge_installedpackages_section($username, $password, $section) { |
|
393 |
$this->auth($username, $password); |
|
296 | 394 |
|
297 |
return $xmlrpc_g['return']['true']; |
|
298 |
} |
|
395 |
global $config; |
|
299 | 396 |
|
300 |
/*****************************/ |
|
301 |
$merge_installedpackages_section_doc = gettext("XMLRPC wrapper for merging package sections. This method must be called with two parameters: a string containing the local system\'s password and an array to merge into the system\'s config. This function returns true upon completion."); |
|
302 |
$merge_installedpackages_section_sig = array( |
|
303 |
array( |
|
304 |
$XML_RPC_Boolean, |
|
305 |
$XML_RPC_String, |
|
306 |
$XML_RPC_Struct |
|
307 |
) |
|
308 |
); |
|
397 |
if ($this->loop_detected) { |
|
398 |
log_error("Disallowing CARP sync loop"); |
|
399 |
return true; |
|
400 |
} |
|
309 | 401 |
|
310 |
function merge_installedpackages_section_xmlrpc($raw_params) { |
|
311 |
global $config, $xmlrpc_g; |
|
402 |
$config['installedpackages'] = array_merge( |
|
403 |
$config['installedpackages'], $section); |
|
404 |
$mergedkeys = implode(",", array_keys($section)); |
|
405 |
write_config(sprintf(gettext( |
|
406 |
"Merged in config (%s sections) from XMLRPC client."), |
|
407 |
$mergedkeys)); |
|
312 | 408 |
|
313 |
if (xmlrpc_loop_detect()) { |
|
314 |
log_error("Disallowing CARP sync loop"); |
|
315 |
return; |
|
409 |
return true; |
|
316 | 410 |
} |
317 | 411 |
|
318 |
$params = xmlrpc_params_to_php($raw_params); |
|
319 |
if (!xmlrpc_auth($params)) { |
|
320 |
xmlrpc_authfail(); |
|
321 |
return $xmlrpc_g['return']['authfail']; |
|
322 |
} |
|
323 |
$config['installedpackages'] = array_merge($config['installedpackages'], $params[0]); |
|
324 |
$mergedkeys = implode(",", array_keys($params[0])); |
|
325 |
write_config(sprintf(gettext("Merged in config (%s sections) from XMLRPC client."), $mergedkeys)); |
|
412 |
/** |
|
413 |
* Merge items into config |
|
414 |
* |
|
415 |
* @param string $username |
|
416 |
* @param string $password |
|
417 |
* @param array $section |
|
418 |
* |
|
419 |
* @return bool |
|
420 |
*/ |
|
421 |
public function merge_config_section($username, $password, $section) { |
|
422 |
$this->auth($username, $password); |
|
326 | 423 |
|
327 |
return $xmlrpc_g['return']['true']; |
|
328 |
} |
|
424 |
global $config; |
|
329 | 425 |
|
330 |
/*****************************/ |
|
331 |
$merge_config_section_doc = gettext("XMLRPC wrapper for merge_config_section. This method must be called with two parameters: a string containing the local system\'s password and an array to merge into the system\'s config. This function returns true upon completion."); |
|
332 |
$merge_config_section_sig = array( |
|
333 |
array( |
|
334 |
$XML_RPC_Boolean, |
|
335 |
$XML_RPC_String, |
|
336 |
$XML_RPC_Struct |
|
337 |
) |
|
338 |
); |
|
426 |
if ($this->loop_detected) { |
|
427 |
log_error("Disallowing CARP sync loop"); |
|
428 |
return true; |
|
429 |
} |
|
339 | 430 |
|
340 |
function merge_config_section_xmlrpc($raw_params) { |
|
341 |
global $config, $xmlrpc_g; |
|
431 |
$config_new = $this->array_overlay($config, $section); |
|
432 |
$config = $config_new; |
|
433 |
$mergedkeys = implode(",", array_keys($section)); |
|
434 |
write_config(sprintf(gettext( |
|
435 |
"Merged in config (%s sections) from XMLRPC client."), |
|
436 |
$mergedkeys)); |
|
342 | 437 |
|
343 |
if (xmlrpc_loop_detect()) { |
|
344 |
log_error("Disallowing CARP sync loop"); |
|
345 |
return; |
|
438 |
return true; |
|
346 | 439 |
} |
347 | 440 |
|
348 |
$params = xmlrpc_params_to_php($raw_params); |
|
349 |
if (!xmlrpc_auth($params)) { |
|
350 |
xmlrpc_authfail(); |
|
351 |
return $xmlrpc_g['return']['authfail']; |
|
352 |
} |
|
353 |
$config_new = array_overlay($config, $params[0]); |
|
354 |
$config = $config_new; |
|
355 |
$mergedkeys = implode(",", array_keys($params[0])); |
|
356 |
write_config(sprintf(gettext("Merged in config (%s sections) from XMLRPC client."), $mergedkeys)); |
|
357 |
return $xmlrpc_g['return']['true']; |
|
358 |
} |
|
359 |
|
|
360 |
/*****************************/ |
|
361 |
$filter_configure_doc = gettext("Basic XMLRPC wrapper for filter_configure. This method must be called with one parameter: a string containing the local system\'s password. This function returns true upon completion."); |
|
362 |
$filter_configure_sig = array( |
|
363 |
array( |
|
364 |
$XML_RPC_Boolean, |
|
365 |
$XML_RPC_String |
|
366 |
) |
|
367 |
); |
|
368 |
|
|
369 |
function filter_configure_xmlrpc($raw_params) { |
|
370 |
global $xmlrpc_g, $g, $config; |
|
371 |
|
|
372 |
$params = xmlrpc_params_to_php($raw_params); |
|
373 |
if (!xmlrpc_auth($params)) { |
|
374 |
xmlrpc_authfail(); |
|
375 |
return $xmlrpc_g['return']['authfail']; |
|
376 |
} |
|
377 |
filter_configure(); |
|
378 |
system_routing_configure(); |
|
379 |
setup_gateways_monitor(); |
|
380 |
relayd_configure(); |
|
381 |
require_once("openvpn.inc"); |
|
382 |
openvpn_resync_all(); |
|
383 |
|
|
384 |
/* The DNS Resolver and the DNS Forwarder may both be active so long as |
|
385 |
* they are running on different ports. See ticket #5882 |
|
441 |
/** |
|
442 |
* Wrapper for filter_configure() |
|
443 |
* |
|
444 |
* @param string $username |
|
445 |
* @param string $password |
|
446 |
* |
|
447 |
* @return bool |
|
386 | 448 |
*/ |
387 |
$need_dhcp_start = true; |
|
388 |
if (isset($config['dnsmasq']['enable'])) { |
|
389 |
/* Configure dnsmasq but tell it NOT to restart DHCP */ |
|
390 |
services_dnsmasq_configure(false); |
|
391 |
} else { |
|
392 |
/* kill any running dnsmasq since it is not enabled. */ |
|
393 |
if (file_exists("{$g['varrun_path']}/dnsmasq.pid")) { |
|
394 |
sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", "TERM"); |
|
449 |
public function filter_configure($username, $password) { |
|
450 |
$this->auth($username, $password); |
|
451 |
|
|
452 |
global $g, $config; |
|
453 |
|
|
454 |
filter_configure(); |
|
455 |
system_routing_configure(); |
|
456 |
setup_gateways_monitor(); |
|
457 |
relayd_configure(); |
|
458 |
require_once("openvpn.inc"); |
|
459 |
openvpn_resync_all(); |
|
460 |
|
|
461 |
/* |
|
462 |
* The DNS Resolver and the DNS Forwarder may both be active so |
|
463 |
* long as * they are running on different ports. |
|
464 |
* See ticket #5882 |
|
465 |
*/ |
|
466 |
if (isset($config['dnsmasq']['enable'])) { |
|
467 |
/* Configure dnsmasq but tell it NOT to restart DHCP */ |
|
468 |
services_dnsmasq_configure(false); |
|
469 |
} else { |
|
470 |
/* kill any running dnsmasq instance */ |
|
471 |
if (isvalidpid("{$g['varrun_path']}/dnsmasq.pid")) { |
|
472 |
sigkillbypid("{$g['varrun_path']}/dnsmasq.pid", |
|
473 |
"TERM"); |
|
474 |
} |
|
395 | 475 |
} |
396 |
} |
|
397 |
if (isset($config['unbound']['enable'])) { |
|
398 |
/* Configure unbound but tell it NOT to restart DHCP */ |
|
399 |
services_unbound_configure(false); |
|
400 |
} else { |
|
401 |
/* kill any running Unbound instance since it is not enabled. */ |
|
402 |
if (file_exists("{$g['varrun_path']}/unbound.pid")) { |
|
403 |
sigkillbypid("{$g['varrun_path']}/unbound.pid", "TERM"); |
|
476 |
if (isset($config['unbound']['enable'])) { |
|
477 |
/* Configure unbound but tell it NOT to restart DHCP */ |
|
478 |
services_unbound_configure(false); |
|
479 |
} else { |
|
480 |
/* kill any running Unbound instance */ |
|
481 |
if (isvalidpid("{$g['varrun_path']}/unbound.pid")) { |
|
482 |
sigkillbypid("{$g['varrun_path']}/unbound.pid", |
|
483 |
"TERM"); |
|
484 |
} |
|
404 | 485 |
} |
405 |
} |
|
406 |
|
|
407 |
/* Call this separately since the above are manually set to skip the DHCP restart they normally perform. |
|
408 |
* This avoids restarting dhcpd twice as described on ticket #3797 |
|
409 |
*/ |
|
410 |
services_dhcpd_configure(); |
|
411 |
|
|
412 |
local_sync_accounts(); |
|
413 | 486 |
|
414 |
return $xmlrpc_g['return']['true']; |
|
415 |
} |
|
416 |
|
|
417 |
/*****************************/ |
|
418 |
$carp_configure_doc = gettext("Basic XMLRPC wrapper for configuring CARP interfaces."); |
|
419 |
$carp_configure_sig = array( |
|
420 |
array( |
|
421 |
$XML_RPC_Boolean, |
|
422 |
$XML_RPC_String |
|
423 |
) |
|
424 |
); |
|
425 |
|
|
426 |
function interfaces_carp_configure_xmlrpc($raw_params) { |
|
427 |
global $xmlrpc_g; |
|
487 |
/* |
|
488 |
* Call this separately since the above are manually set to |
|
489 |
* skip the DHCP restart they normally perform. |
|
490 |
* This avoids restarting dhcpd twice as described on |
|
491 |
* ticket #3797 |
|
492 |
*/ |
|
493 |
services_dhcpd_configure(); |
|
428 | 494 |
|
429 |
if (xmlrpc_loop_detect()) { |
|
430 |
log_error("Disallowing CARP sync loop"); |
|
431 |
return; |
|
432 |
} |
|
495 |
local_sync_accounts(); |
|
433 | 496 |
|
434 |
$params = xmlrpc_params_to_php($raw_params); |
|
435 |
if (!xmlrpc_auth($params)) { |
|
436 |
xmlrpc_authfail(); |
|
437 |
return $xmlrpc_g['return']['authfail']; |
|
497 |
return true; |
|
438 | 498 |
} |
439 |
interfaces_vips_configure(); |
|
440 | 499 |
|
441 |
return $xmlrpc_g['return']['true']; |
|
442 |
} |
|
500 |
/** |
|
501 |
* Wrapper for configuring CARP interfaces |
|
502 |
* |
|
503 |
* @param string $username |
|
504 |
* @param string $password |
|
505 |
* |
|
506 |
* @return bool |
|
507 |
*/ |
|
508 |
public function interfaces_carp_configure($username, $password) { |
|
509 |
$this->auth($username, $password); |
|
443 | 510 |
|
444 |
/*****************************/ |
|
445 |
$pfsense_firmware_version_doc = gettext("Basic XMLRPC wrapper for host_firmware_version. This function will return the output of host_firmware_version upon completion."); |
|
511 |
if ($this->loop_detected) { |
|
512 |
log_error("Disallowing CARP sync loop"); |
|
513 |
return true; |
|
514 |
} |
|
446 | 515 |
|
447 |
$pfsense_firmware_version_sig = array ( |
|
448 |
array ( |
|
449 |
$XML_RPC_Struct, |
|
450 |
$XML_RPC_String |
|
451 |
) |
|
452 |
); |
|
516 |
interfaces_vips_configure(); |
|
453 | 517 |
|
454 |
function pfsense_firmware_version_xmlrpc($raw_params) {
|
|
455 |
global $xmlrpc_g;
|
|
518 |
return true;
|
|
519 |
}
|
|
456 | 520 |
|
457 |
$params = xmlrpc_params_to_php($raw_params); |
|
458 |
if (!xmlrpc_auth($params)) { |
|
459 |
xmlrpc_authfail(); |
|
460 |
return $xmlrpc_g['return']['authfail']; |
|
461 |
} |
|
462 |
return new XML_RPC_Response(XML_RPC_encode(host_firmware_version())); |
|
463 |
} |
|
521 |
/** |
|
522 |
* Wrapper for rc.reboot |
|
523 |
* |
|
524 |
* @param string $username |
|
525 |
* @param string $password |
|
526 |
* |
|
527 |
* @return bool |
|
528 |
*/ |
|
529 |
public function reboot($username, $password) { |
|
530 |
$this->auth($username, $password); |
|
464 | 531 |
|
465 |
/*****************************/ |
|
466 |
$reboot_doc = gettext("Basic XMLRPC wrapper for rc.reboot."); |
|
467 |
$reboot_sig = array(array($XML_RPC_Boolean, $XML_RPC_String)); |
|
468 |
function reboot_xmlrpc($raw_params) { |
|
469 |
global $xmlrpc_g; |
|
532 |
mwexec_bg("/etc/rc.reboot"); |
|
470 | 533 |
|
471 |
$params = xmlrpc_params_to_php($raw_params); |
|
472 |
if (!xmlrpc_auth($params)) { |
|
473 |
xmlrpc_authfail(); |
|
474 |
return $xmlrpc_g['return']['authfail']; |
|
534 |
return true; |
|
475 | 535 |
} |
476 |
mwexec_bg("/etc/rc.reboot"); |
|
477 | 536 |
|
478 |
return $xmlrpc_g['return']['true']; |
|
479 |
} |
|
537 |
/** |
|
538 |
* Wrapper for get_notices() |
|
539 |
* |
|
540 |
* @param string $username |
|
541 |
* @param string $password |
|
542 |
* @param string $category |
|
543 |
* |
|
544 |
* @return bool |
|
545 |
*/ |
|
546 |
public function get_notices($username, $password, $category = 'all') { |
|
547 |
$this->auth($username, $password); |
|
480 | 548 |
|
481 |
/*****************************/ |
|
482 |
$get_notices_sig = array( |
|
483 |
array( |
|
484 |
$XML_RPC_Array, |
|
485 |
$XML_RPC_String |
|
486 |
), |
|
487 |
array( |
|
488 |
$XML_RPC_Array |
|
489 |
) |
|
490 |
); |
|
549 |
global $g; |
|
491 | 550 |
|
492 |
function get_notices_xmlrpc($raw_params) { |
|
493 |
global $g, $xmlrpc_g; |
|
551 |
if (!function_exists("get_notices")) { |
|
552 |
require_once("notices.inc"); |
|
553 |
} |
|
554 |
if (!$params) { |
|
555 |
$toreturn = get_notices(); |
|
556 |
} else { |
|
557 |
$toreturn = get_notices($params); |
|
558 |
} |
|
494 | 559 |
|
495 |
$params = xmlrpc_params_to_php($raw_params); |
|
496 |
if (!xmlrpc_auth($params)) { |
|
497 |
xmlrpc_authfail(); |
|
498 |
return $xmlrpc_g['return']['authfail']; |
|
560 |
return $toreturn; |
|
499 | 561 |
} |
500 |
if (!function_exists("get_notices")) { |
|
501 |
require_once("notices.inc"); |
|
502 |
} |
|
503 |
if (!$params) { |
|
504 |
$toreturn = get_notices(); |
|
505 |
} else { |
|
506 |
$toreturn = get_notices($params); |
|
507 |
} |
|
508 |
$response = new XML_RPC_Response(XML_RPC_encode($toreturn)); |
|
509 |
|
|
510 |
return $response; |
|
511 | 562 |
} |
512 | 563 |
|
513 | 564 |
$xmlrpclockkey = lock('xmlrpc', LOCK_EX); |
514 | 565 |
|
515 |
/*****************************/ |
|
516 |
$server = new XML_RPC_Server( |
|
517 |
array( |
|
518 |
'pfsense.exec_shell' => array('function' => 'exec_shell_xmlrpc', |
|
519 |
'signature' => $exec_shell_sig, |
|
520 |
'docstring' => $exec_shell_doc), |
|
521 |
'pfsense.exec_php' => array('function' => 'exec_php_xmlrpc', |
|
522 |
'signature' => $exec_php_sig, |
|
523 |
'docstring' => $exec_php_doc), |
|
524 |
'pfsense.filter_configure' => array('function' => 'filter_configure_xmlrpc', |
|
525 |
'signature' => $filter_configure_sig, |
|
526 |
'docstring' => $filter_configure_doc), |
|
527 |
'pfsense.interfaces_carp_configure' => array('function' => 'interfaces_carp_configure_xmlrpc', |
|
528 |
'signature' => $carp_configure_sig, |
|
529 |
'docstring' => $carp_configure_doc), |
|
530 |
'pfsense.backup_config_section' => array('function' => 'backup_config_section_xmlrpc', |
|
531 |
'signature' => $backup_config_section_sig, |
|
532 |
'docstring' => $backup_config_section_doc), |
|
533 |
'pfsense.restore_config_section' => array('function' => 'restore_config_section_xmlrpc', |
|
534 |
'signature' => $restore_config_section_sig, |
|
535 |
'docstring' => $restore_config_section_doc), |
|
536 |
'pfsense.merge_config_section' => array('function' => 'merge_config_section_xmlrpc', |
|
537 |
'signature' => $merge_config_section_sig, |
|
538 |
'docstring' => $merge_config_section_doc), |
|
539 |
'pfsense.merge_installedpackages_section_xmlrpc' => array('function' => 'merge_installedpackages_section_xmlrpc', |
|
540 |
'signature' => $merge_installedpackages_section_sig, |
|
541 |
'docstring' => $merge_installedpackages_section_doc), |
|
542 |
'pfsense.host_firmware_version' => array('function' => 'pfsense_firmware_version_xmlrpc', |
|
543 |
'signature' => $pfsense_firmware_version_sig, |
|
544 |
'docstring' => $pfsense_firmware_version_doc), |
|
545 |
'pfsense.reboot' => array('function' => 'reboot_xmlrpc', |
|
546 |
'signature' => $reboot_sig, |
|
547 |
'docstring' => $reboot_doc), |
|
548 |
'pfsense.get_notices' => array('function' => 'get_notices_xmlrpc', |
|
549 |
'signature' => $get_notices_sig) |
|
550 |
) |
|
566 |
XML_RPC2_Backend::setBackend('php'); |
|
567 |
$HTTP_RAW_POST_DATA = file_get_contents('php://input'); |
|
568 |
|
|
569 |
$options = array( |
|
570 |
'prefix' => 'pfsense.', |
|
571 |
'encoding' => 'utf-8', |
|
572 |
'autoDocument' => true, |
|
551 | 573 |
); |
552 | 574 |
|
553 |
unlock($xmlrpclockkey); |
|
575 |
$server = XML_RPC2_Server::create(new pfsense_xmlrpc_server(), $options); |
|
576 |
$server->handleCall(); |
|
554 | 577 |
|
555 |
function array_overlay($a1, $a2) { |
|
556 |
foreach ($a1 as $k => $v) { |
|
557 |
if (!array_key_exists($k, $a2)) { |
|
558 |
continue; |
|
559 |
} |
|
560 |
if (is_array($v) && is_array($a2[$k])) { |
|
561 |
$a1[$k] = array_overlay($v, $a2[$k]); |
|
562 |
} else { |
|
563 |
$a1[$k] = $a2[$k]; |
|
564 |
} |
|
565 |
} |
|
566 |
return $a1; |
|
567 |
} |
|
578 |
unlock($xmlrpclockkey); |
|
568 | 579 |
|
569 | 580 |
?> |
Also available in: Unified diff
Ticket #3734: Convert xmlrpc.php to use XML/RPC2/Server.php