Project

General

Profile

« Previous | Next » 

Revision f81e7cc4

Added by Renato Botelho almost 9 years ago

Ticket #3734: Convert xmlrpc.php to use XML/RPC2/Server.php

View differences:

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