Project

General

Profile

Download (16.4 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 xmlrpc_authfail() {
88
	log_auth("webConfigurator authentication error for 'admin' from {$_SERVER['REMOTE_ADDR']}");
89
}
90

    
91
function exec_php_xmlrpc($raw_params) {
92
	global $config, $xmlrpc_g;
93

    
94
	$params = xmlrpc_params_to_php($raw_params);
95
	if(!xmlrpc_auth($params)) {
96
		xmlrpc_authfail();
97
		return $xmlrpc_g['return']['authfail'];
98
	}
99
	$exec_php = $params[0];
100
	eval($exec_php);
101
	if($toreturn) {
102
		$response = XML_RPC_encode($toreturn);
103
		return new XML_RPC_Response($response);
104
	} else
105
		return $xmlrpc_g['return']['true'];
106
}
107

    
108
/*****************************/
109
$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.");
110
$exec_shell_sig = array(
111
	array(
112
		$XML_RPC_Boolean, // First signature element is return value.
113
		$XML_RPC_String, // password
114
		$XML_RPC_String, // shell code to exec
115
	)
116
);
117

    
118
function exec_shell_xmlrpc($raw_params) {
119
	global $config, $xmlrpc_g;
120

    
121
	$params = xmlrpc_params_to_php($raw_params);
122
	if(!xmlrpc_auth($params)) {
123
		xmlrpc_authfail();
124
		return $xmlrpc_g['return']['authfail'];
125
	}
126
	$shell_cmd = $params[0];
127
	mwexec($shell_cmd);
128

    
129
	return $xmlrpc_g['return']['true'];
130
}
131

    
132
/*****************************/
133
$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.");
134
$backup_config_section_sig = array(
135
	array(
136
		$XML_RPC_Struct, // First signature element is return value.
137
		$XML_RPC_String,
138
		$XML_RPC_Array
139
	)
140
);
141

    
142
function backup_config_section_xmlrpc($raw_params) {
143
	global $config, $xmlrpc_g;
144

    
145
	$params = xmlrpc_params_to_php($raw_params);
146
	if(!xmlrpc_auth($params)) {
147
		xmlrpc_authfail();
148
		return $xmlrpc_g['return']['authfail'];
149
	}
150
	$val = array_intersect_key($config, array_flip($params[0]));
151

    
152
	return new XML_RPC_Response(XML_RPC_encode($val));
153
}
154

    
155
/*****************************/
156
$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.");
157
$restore_config_section_sig = array(
158
	array(
159
		$XML_RPC_Boolean,
160
		$XML_RPC_String,
161
		$XML_RPC_Struct
162
	)
163
);
164

    
165
function restore_config_section_xmlrpc($raw_params) {
166
	global $config, $xmlrpc_g;
167

    
168
	$params = xmlrpc_params_to_php($raw_params);
169
	if(!xmlrpc_auth($params)) {
170
		xmlrpc_authfail();
171
		return $xmlrpc_g['return']['authfail'];
172
	}
173
	$vipbackup = array();
174
	$oldvips = array();
175
	if (isset($params[0]['virtualip'])) {
176
		if(is_array($config['virtualip']['vip'])) {
177
			foreach ($config['virtualip']['vip'] as $vipindex => $vip) {
178
				if ($vip['mode'] == "carp")
179
					$oldvips[$vip['vhid']] = "{$vip['password']}{$vip['advskew']}{$vip['subnet']}{$vip['subnet_bits']}{$vip['advbase']}";
180
				else if ($vip['mode'] == "ipalias" && substr($vip['interface'], 0, 3) == "vip")
181
					$oldvips[$vip['subnet']] = "{$vip['interface']}{$vip['subnet']}{$vip['subnet_bits']}";
182
				else if (($vip['mode'] == "ipalias" || $vip['mode'] == 'proxyarp') && substr($vip['interface'], 0, 3) != "vip")
183
					$vipbackup[] = $vip;
184
			}
185
		}
186
	}
187

    
188
        // For vip section, first keep items sent from the master
189
	$config = array_merge_recursive_unique($config, $params[0]);
190

    
191
        /* Then add ipalias and proxyarp types already defined on the backup */
192
	if (is_array($vipbackup) && !empty($vipbackup)) {
193
		if (!is_array($config['virtualip']))
194
			$config['virtualip'] = array();
195
		if (!is_array($config['virtualip']['vip']))
196
			$config['virtualip']['vip'] = array();
197
		foreach ($vipbackup as $vip)
198
			array_unshift($config['virtualip']['vip'], $vip);
199
	}
200

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

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

    
231
			switch ($vip['mode']) {
232
			case "proxyarp":
233
				$anyproxyarp = true;
234
				break;
235
			case "ipalias":
236
				interface_ipalias_configure(&$vip);
237
				break;
238
			case "carp":
239
				if ($carp_setuped == false)
240
                                        $carp_setuped = true;
241
				interface_carp_configure($vip);
242
				break;
243
			case "carpdev-dhcp":
244
				interface_carpdev_configure($vip);
245
				break;
246
			}
247
		}
248
		/* Cleanup remaining old carps */
249
		foreach ($oldvips as $oldvipif => $oldvippar) {
250
			if (!is_ipaddr($oldvipif) && does_interface_exist("vip{$oldvipif}"))
251
				pfSense_interface_destroy("vip{$oldvipif}");
252
		}
253
		if ($carp_setuped == true)
254
			interfaces_carp_setup();
255
		if ($anyproxyarp == true)
256
			interface_proxyarp_configure();
257
	}
258

    
259
	return $xmlrpc_g['return']['true'];
260
}
261

    
262
/*****************************/
263
$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.");
264
$merge_config_section_sig = array(
265
	array(
266
		$XML_RPC_Boolean,
267
		$XML_RPC_String,
268
		$XML_RPC_Struct
269
	)
270
);
271

    
272
function merge_installedpackages_section_xmlrpc($raw_params) {
273
	global $config, $xmlrpc_g;
274

    
275
	$params = xmlrpc_params_to_php($raw_params);
276
	if(!xmlrpc_auth($params)) {
277
		xmlrpc_authfail();
278
		return $xmlrpc_g['return']['authfail'];
279
	}
280
	$config['installedpackages'] = array_merge($config['installedpackages'], $params[0]);
281
	$mergedkeys = implode(",", array_keys($params[0]));
282
	write_config(sprintf(gettext("Merged in config (%s sections) from XMLRPC client."),$mergedkeys));
283

    
284
	return $xmlrpc_g['return']['true'];
285
}
286

    
287
/*****************************/
288
$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.");
289
$merge_config_section_sig = array(
290
	array(
291
		$XML_RPC_Boolean,
292
		$XML_RPC_String,
293
		$XML_RPC_Struct
294
	)
295
);
296

    
297
function merge_config_section_xmlrpc($raw_params) {
298
	global $config, $xmlrpc_g;
299
	$params = xmlrpc_params_to_php($raw_params);
300
	if(!xmlrpc_auth($params)) {
301
		xmlrpc_authfail();
302
		return $xmlrpc_g['return']['authfail'];
303
	}
304
	$config_new = array_overlay($config, $params[0]);
305
	$config = $config_new;
306
	$mergedkeys = implode(",", array_keys($params[0]));
307
	write_config(sprintf(gettext("Merged in config (%s sections) from XMLRPC client."), $mergedkeys));
308
	return $xmlrpc_g['return']['true'];
309
}
310

    
311
/*****************************/
312
$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.");
313
$filter_configure_sig = array(
314
	array(
315
		$XML_RPC_Boolean,
316
		$XML_RPC_String
317
	)
318
);
319

    
320
function filter_configure_xmlrpc($raw_params) {
321
	global $xmlrpc_g;
322

    
323
	$params = xmlrpc_params_to_php($raw_params);
324
	if(!xmlrpc_auth($params)) {
325
		xmlrpc_authfail();
326
		return $xmlrpc_g['return']['authfail'];
327
	}
328
	filter_configure();
329
	system_routing_configure();
330
	setup_gateways_monitor();
331
	relayd_configure();
332
	require_once("openvpn.inc");
333
	openvpn_resync_all();
334
	services_dhcpd_configure();
335
	services_dnsmasq_configure();
336
	local_sync_accounts();
337

    
338
	return $xmlrpc_g['return']['true'];
339
}
340

    
341
/*****************************/
342
$carp_configure_doc = gettext("Basic XMLRPC wrapper for configuring CARP interfaces.");
343
$carp_configure_sig = array(
344
	array(
345
		$XML_RPC_Boolean,
346
		$XML_RPC_String
347
	)
348
);
349

    
350
function interfaces_carp_configure_xmlrpc($raw_params) {
351
	global $xmlrpc_g;
352

    
353
	$params = xmlrpc_params_to_php($raw_params);
354
	if(!xmlrpc_auth($params)) {
355
		xmlrpc_authfail();
356
		return $xmlrpc_g['return']['authfail'];
357
	}
358
	interfaces_vips_configure();
359

    
360
	return $xmlrpc_g['return']['true'];
361
}
362

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

    
366
$check_firmware_version_sig = array(
367
	array(
368
		$XML_RPC_String,
369
		$XML_RPC_String
370
	)
371
);
372

    
373
function check_firmware_version_xmlrpc($raw_params) {
374
	global $xmlrpc_g, $XML_RPC_String;
375

    
376
	$params = xmlrpc_params_to_php($raw_params);
377
	if(!xmlrpc_auth($params)) {
378
		xmlrpc_authfail();
379
		return $xmlrpc_g['return']['authfail'];
380
	}
381
	return new XML_RPC_Response(new XML_RPC_Value(check_firmware_version(false), $XML_RPC_String));
382
}
383

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

    
387
$pfsense_firmware_version_sig = array (
388
        array (
389
                $XML_RPC_Struct,
390
                $XML_RPC_String
391
        )
392
);
393

    
394
function pfsense_firmware_version_xmlrpc($raw_params) {
395
        global $xmlrpc_g;
396

    
397
        $params = xmlrpc_params_to_php($raw_params);
398
        if(!xmlrpc_auth($params)) {
399
			xmlrpc_authfail();
400
			return $xmlrpc_g['return']['authfail'];
401
		}
402
        return new XML_RPC_Response(XML_RPC_encode(host_firmware_version()));
403
}
404

    
405
/*****************************/
406
$reboot_doc = gettext("Basic XMLRPC wrapper for rc.reboot.");
407
$reboot_sig = array(array($XML_RPC_Boolean, $XML_RPC_String));
408
function reboot_xmlrpc($raw_params) {
409
	global $xmlrpc_g;
410

    
411
	$params = xmlrpc_params_to_php($raw_params);
412
	if(!xmlrpc_auth($params)) {
413
		xmlrpc_authfail();
414
		return $xmlrpc_g['return']['authfail'];
415
	}
416
	mwexec_bg("/etc/rc.reboot");
417

    
418
	return $xmlrpc_g['return']['true'];
419
}
420

    
421
/*****************************/
422
$get_notices_sig = array(
423
	array(
424
		$XML_RPC_Array,
425
		$XML_RPC_String
426
	),
427
	array(
428
		$XML_RPC_Array
429
	)
430
);
431

    
432
function get_notices_xmlrpc($raw_params) {
433
	global $g, $xmlrpc_g;
434

    
435
	$params = xmlrpc_params_to_php($raw_params);
436
	if(!xmlrpc_auth($params)) {
437
		xmlrpc_authfail();
438
		return $xmlrpc_g['return']['authfail'];
439
	}
440
	require("notices.inc");
441
	if(!$params) {
442
		$toreturn = get_notices();
443
	} else {
444
		$toreturn = get_notices($params);
445
	}
446
	$response = new XML_RPC_Response(XML_RPC_encode($toreturn));
447

    
448
	return $response;
449
}
450

    
451
$xmlrpclockkey = lock('xmlrpc', LOCK_EX);
452

    
453
/*****************************/
454
$server = new XML_RPC_Server(
455
        array(
456
		'pfsense.exec_shell' => array('function' => 'exec_shell_xmlrpc',
457
			'signature' => $exec_shell_sig,
458
			'docstring' => $exec_shell_doc),
459
		'pfsense.exec_php' => array('function' => 'exec_php_xmlrpc',
460
			'signature' => $exec_php_sig,
461
			'docstring' => $exec_php_doc),	
462
		'pfsense.filter_configure' => array('function' => 'filter_configure_xmlrpc',
463
			'signature' => $filter_configure_sig,
464
			'docstring' => $filter_configure_doc),
465
		'pfsense.interfaces_carp_configure' => array('function' => 'interfaces_carp_configure_xmlrpc',
466
			'docstring' => $carp_configure_sig),
467
		'pfsense.backup_config_section' => array('function' => 'backup_config_section_xmlrpc',
468
			'signature' => $backup_config_section_sig,
469
			'docstring' => $backup_config_section_doc),
470
		'pfsense.restore_config_section' => array('function' => 'restore_config_section_xmlrpc',
471
			'signature' => $restore_config_section_sig,
472
			'docstring' => $restore_config_section_doc),
473
		'pfsense.merge_config_section' => array('function' => 'merge_config_section_xmlrpc',
474
			'signature' => $merge_config_section_sig,
475
			'docstring' => $merge_config_section_doc),
476
		'pfsense.merge_installedpackages_section_xmlrpc' => array('function' => 'merge_installedpackages_section_xmlrpc',
477
			'signature' => $merge_config_section_sig,
478
			'docstring' => $merge_config_section_doc),							
479
		'pfsense.check_firmware_version' => array('function' => 'check_firmware_version_xmlrpc',
480
			'signature' => $check_firmware_version_sig,
481
			'docstring' => $check_firmware_version_doc),
482
		'pfsense.host_firmware_version' => array('function' => 'pfsense_firmware_version_xmlrpc',
483
			'signature' => $pfsense_firmware_version_sig,
484
			'docstring' => $host_firmware_version_doc),
485
		'pfsense.reboot' => array('function' => 'reboot_xmlrpc',
486
			'signature' => $reboot_sig,
487
			'docstring' => $reboot_doc),
488
		'pfsense.get_notices' => array('function' => 'get_notices_xmlrpc',
489
			'signature' => $get_notices_sig)
490
        )
491
);
492

    
493
unlock($xmlrpclockkey);
494

    
495
    function array_overlay($a1,$a2)
496
    {
497
        foreach($a1 as $k => $v) {
498
            if(!array_key_exists($k,$a2)) continue;
499
            if(is_array($v) && is_array($a2[$k])){
500
                $a1[$k] = array_overlay($v,$a2[$k]);
501
            }else{
502
                $a1[$k] = $a2[$k];
503
            }
504
        }
505
        return $a1;
506
    }
507

    
508
?>
(233-233/233)