Project

General

Profile

Download (16 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	$Id$
4

    
5
        xmlrpc.php
6
        Copyright (C) 2009, 2010 Scott Ullrich
7
        Copyright (C) 2005 Colin Smith
8
        All rights reserved.
9

    
10
        Redistribution and use in source and binary forms, with or without
11
        modification, are permitted provided that the following conditions are met:
12

    
13
        1. Redistributions of source code must retain the above copyright notice,
14
           this list of conditions and the following disclaimer.
15

    
16
        2. Redistributions in binary form must reproduce the above copyright
17
           notice, this list of conditions and the following disclaimer in the
18
           documentation and/or other materials provided with the distribution.
19

    
20
        THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
        INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
        AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
        AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
        OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
        SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
        INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
        CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
        ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
        POSSIBILITY OF SUCH DAMAGE.
30
*/
31

    
32
##|+PRIV
33
##|*IDENT=page-xmlrpclibrary
34
##|*NAME=XMLRPC Library page
35
##|*DESCR=Allow access to the 'XMLRPC Library' page.
36
##|*MATCH=xmlrpc.php*
37
##|-PRIV
38

    
39
require("config.inc");
40
require("functions.inc");
41
require("filter.inc");
42
require("shaper.inc");
43
require("xmlrpc_server.inc");
44
require("xmlrpc.inc");
45
require("array_intersect_key.inc");
46

    
47
/* grab sync to ip if enabled */
48
if($config['installedpackages']['carpsettings']) {
49
	if ($config['installedpackages']['carpsettings']['config']) {
50
		foreach ($config['installedpackages']['carpsettings']['config'] as $carp) {
51
			$synchronizetoip = $carp['synchronizetoip'];
52
		}
53
	}
54
}
55

    
56
if($synchronizetoip) {
57
	if($synchronizetoip == $_SERVER['REMOTE_ADDR']) {
58
		log_error(gettext("Disallowing CARP sync loop."));
59
		die;	
60
	}
61
}
62

    
63
$xmlrpc_g = array(
64
	"return" => array(
65
		"true" => new XML_RPC_Response(new XML_RPC_Value(true, $XML_RPC_Boolean)),
66
		"false" => new XML_RPC_Response(new XML_RPC_Value(false, $XML_RPC_Boolean)),
67
		"authfail" => new XML_RPC_Response(new XML_RPC_Value(gettext("Authentication failed"), $XML_RPC_String))
68
	)
69
);
70

    
71
/*
72
 *   pfSense XMLRPC errors
73
 *   $XML_RPC_erruser + 1 = Auth failure
74
 */
75
$XML_RPC_erruser = 200;
76

    
77
/* EXPOSED FUNCTIONS */
78
$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.");
79
$exec_php_sig = array(
80
	array(
81
		$XML_RPC_Boolean, // First signature element is return value.
82
		$XML_RPC_String, // password
83
		$XML_RPC_String, // shell code to exec
84
	)
85
);
86

    
87
function exec_php_xmlrpc($raw_params) {
88
	global $config, $xmlrpc_g;
89

    
90
	$params = xmlrpc_params_to_php($raw_params);
91
	if(!xmlrpc_auth($params))
92
		return $xmlrpc_g['return']['authfail'];
93
	$exec_php = $params[0];
94
	eval($exec_php);
95
	if($toreturn) {
96
		$response = XML_RPC_encode($toreturn);
97
		return new XML_RPC_Response($response);
98
	} else
99
		return $xmlrpc_g['return']['true'];
100
}
101

    
102
/*****************************/
103
$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.");
104
$exec_shell_sig = array(
105
	array(
106
		$XML_RPC_Boolean, // First signature element is return value.
107
		$XML_RPC_String, // password
108
		$XML_RPC_String, // shell code to exec
109
	)
110
);
111

    
112
function exec_shell_xmlrpc($raw_params) {
113
	global $config, $xmlrpc_g;
114

    
115
	$params = xmlrpc_params_to_php($raw_params);
116
	if(!xmlrpc_auth($params))
117
		return $xmlrpc_g['return']['authfail'];
118
	$shell_cmd = $params[0];
119
	mwexec($shell_cmd);
120

    
121
	return $xmlrpc_g['return']['true'];
122
}
123

    
124
/*****************************/
125
$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.");
126
$backup_config_section_sig = array(
127
	array(
128
		$XML_RPC_Struct, // First signature element is return value.
129
		$XML_RPC_String,
130
		$XML_RPC_Array
131
	)
132
);
133

    
134
function backup_config_section_xmlrpc($raw_params) {
135
	global $config, $xmlrpc_g;
136

    
137
	$params = xmlrpc_params_to_php($raw_params);
138
	if(!xmlrpc_auth($params))
139
		return $xmlrpc_g['return']['authfail'];
140
	$val = array_intersect_key($config, array_flip($params[0]));
141

    
142
	return new XML_RPC_Response(XML_RPC_encode($val));
143
}
144

    
145
/*****************************/
146
$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.");
147
$restore_config_section_sig = array(
148
	array(
149
		$XML_RPC_Boolean,
150
		$XML_RPC_String,
151
		$XML_RPC_Struct
152
	)
153
);
154

    
155
function restore_config_section_xmlrpc($raw_params) {
156
	global $config, $xmlrpc_g;
157

    
158
	$params = xmlrpc_params_to_php($raw_params);
159
	if(!xmlrpc_auth($params))
160
		return $xmlrpc_g['return']['authfail'];
161

    
162
	$vipbackup = array();
163
	$oldvips = array();
164
	if (isset($params[0]['virtualip'])) {
165
		if(is_array($config['virtualip']['vip'])) {
166
			foreach ($config['virtualip']['vip'] as $vipindex => $vip) {
167
				if ($vip['mode'] == "carp")
168
					$oldvips[$vip['vhid']] = "{$vip['password']}{$vip['advskew']}{$vip['subnet']}{$vip['subnet_bits']}{$vip['advbase']}";
169
				else if ($vip['mode'] == "ipalias" && substr($vip['interface'], 0, 3) == "vip")
170
					$oldvips[$vip['subnet']] = "{$vip['interface']}{$vip['subnet']}{$vip['subnet_bits']}";
171
				else if (($vip['mode'] == "ipalias" || $vip['mode'] == 'proxyarp') && substr($vip['interface'], 0, 3) != "vip")
172
					$vipbackup[] = $vip;
173
			}
174
		}
175
	}
176

    
177
        // For vip section, first keep items sent from the master
178
	$config = array_merge_recursive_unique($config, $params[0]);
179

    
180
        /* Then add ipalias and proxyarp types already defined on the backup */
181
	if (is_array($vipbackup) && !empty($vipbackup)) {
182
		if (!is_array($config['virtualip']))
183
			$config['virtualip'] = array();
184
		if (!is_array($config['virtualip']['vip']))
185
			$config['virtualip']['vip'] = array();
186
		foreach ($vipbackup as $vip)
187
			array_unshift($config['virtualip']['vip'], $vip);
188
	}
189

    
190
	/* Log what happened */
191
	$mergedkeys = implode(",", array_keys($params[0]));
192
	write_config(sprintf(gettext("Merged in config (%s sections) from XMLRPC client."),$mergedkeys));
193

    
194
	/* 
195
	 * The real work on handling the vips specially
196
	 * This is a copy of intefaces_vips_configure with addition of not reloading existing/not changed carps
197
	 */
198
	if (isset($params[0]['virtualip']) && is_array($config['virtualip']) && is_array($config['virtualip']['vip'])) {
199
		$carp_setuped = false;
200
		$anyproxyarp = false;
201
		foreach ($config['virtualip']['vip'] as $vip) {
202
			if ($vip['mode'] == "carp" && isset($oldvips[$vip['vhid']])) {
203
				if ($oldvips[$vip['vhid']] == "{$vip['password']}{$vip['advskew']}{$vip['subnet']}{$vip['subnet_bits']}{$vip['advbase']}") {
204
					if (does_vip_exist($vip)) {
205
						unset($oldvips[$vip['vhid']]);
206
						continue; // Skip reconfiguring this vips since nothing has changed.
207
					}
208
				}
209
				unset($oldvips[$vip['vhid']]);
210
			} else if ($vip['mode'] == "ipalias" && substr($vip['interface'], 0, 3) == "vip" && isset($oldvips[$vip['subnet']])) {
211
				if ($oldvips[$vip['subnet']] = "{$vip['interface']}{$vip['subnet']}{$vip['subnet_bits']}") {
212
					if (does_vip_exist($vip)) {
213
						unset($oldvips[$vip['subnet']]);
214
						continue; // Skip reconfiguring this vips since nothing has changed.
215
					}
216
				}
217
				unset($oldvips[$vip['subnet']]);
218
			}
219

    
220
			switch ($vip['mode']) {
221
			case "proxyarp":
222
				$anyproxyarp = true;
223
				break;
224
			case "ipalias":
225
				interface_ipalias_configure(&$vip);
226
				break;
227
			case "carp":
228
				if ($carp_setuped == false)
229
                                        $carp_setuped = true;
230
				interface_carp_configure($vip);
231
				break;
232
			case "carpdev-dhcp":
233
				interface_carpdev_configure($vip);
234
				break;
235
			}
236
		}
237
		/* Cleanup remaining old carps */
238
		foreach ($oldvips as $oldvipif => $oldvippar) {
239
			if (!is_ipaddr($oldvipif) && does_interface_exist("vip{$oldvipif}"))
240
				pfSense_interface_destroy("vip{$oldvipif}");
241
		}
242
		if ($carp_setuped == true)
243
			interfaces_carp_setup();
244
		if ($anyproxyarp == true)
245
			interface_proxyarp_configure();
246
	}
247

    
248
	return $xmlrpc_g['return']['true'];
249
}
250

    
251
/*****************************/
252
$merge_config_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.");
253
$merge_config_section_sig = array(
254
	array(
255
		$XML_RPC_Boolean,
256
		$XML_RPC_String,
257
		$XML_RPC_Struct
258
	)
259
);
260

    
261
function merge_installedpackages_section_xmlrpc($raw_params) {
262
	global $config, $xmlrpc_g;
263

    
264
	$params = xmlrpc_params_to_php($raw_params);
265
	if(!xmlrpc_auth($params))
266
		return $xmlrpc_g['return']['authfail'];
267
	$config['installedpackages'] = array_merge($config['installedpackages'], $params[0]);
268
	$mergedkeys = implode(",", array_keys($params[0]));
269
	write_config(sprintf(gettext("Merged in config (%s sections) from XMLRPC client."),$mergedkeys));
270

    
271
	return $xmlrpc_g['return']['true'];
272
}
273

    
274
/*****************************/
275
$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.");
276
$merge_config_section_sig = array(
277
	array(
278
		$XML_RPC_Boolean,
279
		$XML_RPC_String,
280
		$XML_RPC_Struct
281
	)
282
);
283

    
284
function merge_config_section_xmlrpc($raw_params) {
285
	global $config, $xmlrpc_g;
286
	$params = xmlrpc_params_to_php($raw_params);
287
	if(!xmlrpc_auth($params))
288
		return $xmlrpc_g['return']['authfail'];
289
	$config_new = array_overlay($config, $params[0]);
290
	$config = $config_new;
291
	$mergedkeys = implode(",", array_keys($params[0]));
292
	write_config(sprintf(gettext("Merged in config (%s sections) from XMLRPC client."), $mergedkeys));
293
	return $xmlrpc_g['return']['true'];
294
}
295

    
296
/*****************************/
297
$filter_configure_doc = gettext("Basic XMLRPC wrapper for filter_configure. This method must be called with one paramater: a string containing the local system\'s password. This function returns true upon completion.");
298
$filter_configure_sig = array(
299
	array(
300
		$XML_RPC_Boolean,
301
		$XML_RPC_String
302
	)
303
);
304

    
305
function filter_configure_xmlrpc($raw_params) {
306
	global $xmlrpc_g;
307

    
308
	$params = xmlrpc_params_to_php($raw_params);
309
	if(!xmlrpc_auth($params))
310
		return $xmlrpc_g['return']['authfail'];
311
	filter_configure();
312
	system_routing_configure();
313
	setup_gateways_monitor();
314
	relayd_configure();
315
	require_once("openvpn.inc");
316
	openvpn_resync_all();
317
	services_dhcpd_configure();
318
	services_dnsmasq_configure();
319
	local_sync_accounts();
320

    
321
	return $xmlrpc_g['return']['true'];
322
}
323

    
324
/*****************************/
325
$carp_configure_doc = gettext("Basic XMLRPC wrapper for configuring CARP interfaces.");
326
$carp_configure_sig = array(
327
	array(
328
		$XML_RPC_Boolean,
329
		$XML_RPC_String
330
	)
331
);
332

    
333
function interfaces_carp_configure_xmlrpc($raw_params) {
334
	global $xmlrpc_g;
335

    
336
	$params = xmlrpc_params_to_php($raw_params);
337
	if(!xmlrpc_auth($params))
338
		return $xmlrpc_g['return']['authfail'];
339
	interfaces_vips_configure();
340

    
341
	return $xmlrpc_g['return']['true'];
342
}
343

    
344
/*****************************/
345
$check_firmware_version_doc = gettext("Basic XMLRPC wrapper for check_firmware_version. This function will return the output of check_firmware_version upon completion.");
346

    
347
$check_firmware_version_sig = array(
348
	array(
349
		$XML_RPC_String,
350
		$XML_RPC_String
351
	)
352
);
353

    
354
function check_firmware_version_xmlrpc($raw_params) {
355
	global $xmlrpc_g, $XML_RPC_String;
356

    
357
	$params = xmlrpc_params_to_php($raw_params);
358
	if(!xmlrpc_auth($params))
359
		return $xmlrpc_g['return']['authfail'];
360

    
361
	return new XML_RPC_Response(new XML_RPC_Value(check_firmware_version(false), $XML_RPC_String));
362
}
363

    
364
/*****************************/
365
$pfsense_firmware_version_doc = gettext("Basic XMLRPC wrapper for check_firmware_version. This function will return the output of check_firmware_version upon completion.");
366

    
367
$pfsense_firmware_version_sig = array (
368
        array (
369
                $XML_RPC_Struct,
370
                $XML_RPC_String
371
        )
372
);
373

    
374
function pfsense_firmware_version_xmlrpc($raw_params) {
375
        global $xmlrpc_g;
376

    
377
        $params = xmlrpc_params_to_php($raw_params);
378
        if(!xmlrpc_auth($params))
379
                return $xmlrpc_g['return']['authfail'];
380

    
381
        return new XML_RPC_Response(XML_RPC_encode(host_firmware_version()));
382
}
383

    
384
/*****************************/
385
$reboot_doc = gettext("Basic XMLRPC wrapper for rc.reboot.");
386
$reboot_sig = array(array($XML_RPC_Boolean, $XML_RPC_String));
387
function reboot_xmlrpc($raw_params) {
388
	global $xmlrpc_g;
389

    
390
	$params = xmlrpc_params_to_php($raw_params);
391
	if(!xmlrpc_auth($params))
392
		return $xmlrpc_g['return']['authfail'];
393
	mwexec_bg("/etc/rc.reboot");
394

    
395
	return $xmlrpc_g['return']['true'];
396
}
397

    
398
/*****************************/
399
$get_notices_sig = array(
400
	array(
401
		$XML_RPC_Array,
402
		$XML_RPC_String
403
	),
404
	array(
405
		$XML_RPC_Array
406
	)
407
);
408

    
409
function get_notices_xmlrpc($raw_params) {
410
	global $g, $xmlrpc_g;
411

    
412
	$params = xmlrpc_params_to_php($raw_params);
413
	if(!xmlrpc_auth($params)) return $xmlrpc_g['return']['authfail'];
414
	require("notices.inc");
415
	if(!$params) {
416
		$toreturn = get_notices();
417
	} else {
418
		$toreturn = get_notices($params);
419
	}
420
	$response = new XML_RPC_Response(XML_RPC_encode($toreturn));
421

    
422
	return $response;
423
}
424

    
425
$xmlrpclockkey = lock('xmlrpc', LOCK_EX);
426

    
427
/*****************************/
428
$server = new XML_RPC_Server(
429
        array(
430
		'pfsense.exec_shell' => array('function' => 'exec_shell_xmlrpc',
431
			'signature' => $exec_shell_sig,
432
			'docstring' => $exec_shell_doc),
433
		'pfsense.exec_php' => array('function' => 'exec_php_xmlrpc',
434
			'signature' => $exec_php_sig,
435
			'docstring' => $exec_php_doc),	
436
		'pfsense.filter_configure' => array('function' => 'filter_configure_xmlrpc',
437
			'signature' => $filter_configure_sig,
438
			'docstring' => $filter_configure_doc),
439
		'pfsense.interfaces_carp_configure' => array('function' => 'interfaces_carp_configure_xmlrpc',
440
			'docstring' => $carp_configure_sig),
441
		'pfsense.backup_config_section' => array('function' => 'backup_config_section_xmlrpc',
442
			'signature' => $backup_config_section_sig,
443
			'docstring' => $backup_config_section_doc),
444
		'pfsense.restore_config_section' => array('function' => 'restore_config_section_xmlrpc',
445
			'signature' => $restore_config_section_sig,
446
			'docstring' => $restore_config_section_doc),
447
		'pfsense.merge_config_section' => array('function' => 'merge_config_section_xmlrpc',
448
			'signature' => $merge_config_section_sig,
449
			'docstring' => $merge_config_section_doc),
450
		'pfsense.merge_installedpackages_section_xmlrpc' => array('function' => 'merge_installedpackages_section_xmlrpc',
451
			'signature' => $merge_config_section_sig,
452
			'docstring' => $merge_config_section_doc),							
453
		'pfsense.check_firmware_version' => array('function' => 'check_firmware_version_xmlrpc',
454
			'signature' => $check_firmware_version_sig,
455
			'docstring' => $check_firmware_version_doc),
456
		'pfsense.host_firmware_version' => array('function' => 'pfsense_firmware_version_xmlrpc',
457
			'signature' => $pfsense_firmware_version_sig,
458
			'docstring' => $host_firmware_version_doc),
459
		'pfsense.reboot' => array('function' => 'reboot_xmlrpc',
460
			'signature' => $reboot_sig,
461
			'docstring' => $reboot_doc),
462
		'pfsense.get_notices' => array('function' => 'get_notices_xmlrpc',
463
			'signature' => $get_notices_sig)
464
        )
465
);
466

    
467
unlock($xmlrpclockkey);
468

    
469
    function array_overlay($a1,$a2)
470
    {
471
        foreach($a1 as $k => $v) {
472
            if(!array_key_exists($k,$a2)) continue;
473
            if(is_array($v) && is_array($a2[$k])){
474
                $a1[$k] = array_overlay($v,$a2[$k]);
475
            }else{
476
                $a1[$k] = $a2[$k];
477
            }
478
        }
479
        return $a1;
480
    }
481

    
482
?>
(232-232/232)