Project

General

Profile

Download (5.34 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * xmlrpc_client.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2016 Rubicon Communications, LLC (Netgate)
7
 * All rights reserved.
8
 *
9
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 * you may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 * http://www.apache.org/licenses/LICENSE-2.0
14
 *
15
 * Unless required by applicable law or agreed to in writing, software
16
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 * See the License for the specific language governing permissions and
19
 * limitations under the License.
20
 */
21

    
22
require_once("XML/RPC2/Client.php");
23

    
24
define('PEAR_IGNORE_BACKTRACE', 1);
25

    
26
class pfsense_xmlrpc_client {
27
	
28
	private $username, $password, $url, $filenotice, $error;
29
	
30
	public function __construct() {
31
		global $config;
32
		$hasync = $config['hasync'];
33

    
34
		if (empty($hasync['username'])) {
35
			$username = "admin";
36
		} else {
37
			$username = $hasync['username'];
38
		}
39
		/* if port is empty lets rely on the protocol selection */
40
		$port = $config['system']['webgui']['port'];
41
		if (empty($port)) {
42
			if ($config['system']['webgui']['protocol'] == "http") {
43
				$port = "80";
44
			} else {
45
				$port = "443";
46
			}
47
		}
48
		$this->setConnectionData($hasync['synchronizetoip'], $port, $username, $hasync['password']);
49
	}
50

    
51
	public function setConnectionData($syncip, $port, $username, $password, $scheme = "") {
52
		global $config;
53
		$this->username = $username;
54
		$this->password = $password;
55
		$this->filenotice = "sync_settings";
56
		if (empty($scheme)) {
57
			$scheme = "http";
58
			if ($port == "443") {
59
				$scheme = "https";
60
			} else if (is_array($config['system']) &&
61
				is_array($config['system']['webgui']) &&
62
				!empty($config['system']['webgui']['protocol']) &&
63
				$config['system']['webgui']['protocol'] == "https") {
64
				$scheme = "https";
65
			}
66
		}
67
		if (is_ipaddrv6($syncip)) {
68
			$syncip = "[{$syncip}]";
69
		}
70
		$this->url = "{$scheme}://{$syncip}:{$port}/xmlrpc.php";
71
	}
72

    
73
	public function set_noticefile($noticefile) {
74
		$this->filenotice = $noticefile;
75
	}
76
	
77
	private function xmlrpc_internal($method, $parameter, $timeout = 240) {
78
		$this->error = null;
79
		$options = array(
80
			'prefix' => 'pfsense.',
81
			'sslverify' => false,
82
			'connectionTimeout' => $timeout
83
		);
84
		
85
		$numberofruns = 0;
86
		while ($numberofruns < 2) {
87
			$numberofruns++;
88

    
89
			log_error(sprintf(gettext("Beginning XMLRPC sync data to %s."), $this->url));
90
			$cli = XML_RPC2_Client::create($this->url, $options);
91
			if (!is_object($cli)) {
92
				$this->error = sprintf(gettext("A communications error occurred while attempting XMLRPC sync with %s (pfsense.%s)."), $this->url, $method);
93
				log_error($this->error);
94
				file_notice($this->filenotice, $this->error, "Settings Sync", "");
95
				continue;
96
			}
97
			try {//restore_config_section
98
				$REQUEST_URI = $_SERVER['REQUEST_URI'];
99
				unset($_SERVER['REQUEST_URI']); // force use of 'toText()' when setting XML_RPC2_CurlException message
100
				$resp = $cli->$method($this->username, $this->password, $parameter);
101
			} catch (XML_RPC2_FaultException $e) {
102
				// The XMLRPC server returns a XMLRPC error
103
				$this->error = "Exception calling XMLRPC method {$method} #" . $e->getFaultCode() . ' : ' . $e->getFaultString();
104
				log_error($this->error);
105
				file_notice($this->filenotice, $this->error, "Communications error occurred", "");
106
				continue;
107
			}  catch (XML_RPC2_CurlException $e) {
108
				$previouserror = $e->getPrevious();// HTTP_Request2_ConnectionException
109
				if ($previouserror == null) {
110
					// CurlException doesnt get filled with PreviousError,
111
					// however we dont want to show the stacktrace included in the 'message' to non sysadmin users
112
					$this->error = "CurlException calling XMLRPC method {$method} #" . strtok($e->getMessage(), "\n");
113
				} else {
114
					$this->error = "CurlException calling XMLRPC method {$method} #" . $previouserror->getMessage();
115
				}
116
				log_error($this->error);
117
				file_notice($this->filenotice, $this->error, "Communications error occurred", "");
118
				continue;
119
			} catch (Exception $e) {
120
				// Other errors (HTTP or networking problems...)
121
				$this->error = "Exception calling XMLRPC method {$method} # " . $e->getMessage();
122
				log_error($this->error);
123
				file_notice($this->filenotice, $this->error, gettext("Error code received"), "");
124
				continue;
125
			} finally {
126
				if (isset($REQUEST_URI)) {
127
					// restore the unset variable to its previous state.
128
					$_SERVER['REQUEST_URI'] = $REQUEST_URI;
129
				}
130
			}
131

    
132
			if (!is_array($resp) && trim($resp) == "Authentication failed") {
133
				$this->error = "An authentication failure occurred while trying to access {$this->url} ({$method}).";
134
				log_error($this->error);
135
				file_notice($this->filenotice, $this->error, "Settings Sync", "");
136
				continue;
137
			}
138
			log_error(sprintf(gettext("XMLRPC reload data success with %s (pfsense.{$method})."), $this->url));
139
			return $resp;
140
		}
141
		return null;
142
	}
143
	
144
	public function xmlrpc_exec_php($execcmd, $timeout = 240) {
145
		$resp = $this->xmlrpc_internal("exec_php", $execcmd, $timeout);
146
		return $resp;
147
	}
148
	
149
	public function xmlrpc_method($method, $parameter = "", $timeout = 240) {
150
		$resp = $this->xmlrpc_internal($method, $parameter, $timeout);
151
		return $resp;
152
	}
153
	
154
	public function get_error() {
155
		return $this->error;
156
	}
157
	
158
	public function getUrl() {
159
		return $this->url;
160
	}
161
}
(51-51/51)