remoting.inc.php 18.7 KB
Newer Older
latham's avatar
latham committed
1
2
3
<?php

/*
4
Copyright (c) 2007 - 2011, Till Brehm, projektfarm Gmbh
latham's avatar
latham committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
All rights reserved.

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

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
    * Neither the name of ISPConfig nor the names of its contributors
      may be used to endorse or promote products derived from this software without
      specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

--UPDATED 08.2009--
Full SOAP support for ISPConfig 3.1.4 b
Updated by Arkadiusz Roch & Artur Edelman
Copyright (c) Tri-Plex technology

*/

class remoting {
38

latham's avatar
latham committed
39
	//* remote session timeout in seconds
40
	private $session_timeout = 1800;
41

latham's avatar
latham committed
42
43
44
	public $oldDataRecord;
	public $dataRecord;
	public $id;
45
46
47

	private $_methods = array();

latham's avatar
latham committed
48
	/*
49
	These variables shall stay global.
latham's avatar
latham committed
50
	Please do not make them private variables.
51

latham's avatar
latham committed
52
53
54
55
	private $app;
    private $conf;
    */

56
57
58
59
60
61
	public function __construct($methods = array())
	{
		global $app;
		$app->uses('remoting_lib');

		$this->_methods = $methods;
62

63
		/*
latham's avatar
latham committed
64
65
66
        $this->app = $app;
        $this->conf = $conf;
		*/
67
68
69
	}

	//* remote login function
70
	public function login($username, $password, $client_login = false)
71
	{
72
		global $app, $conf;
73

74
75
76
77
		// Maintenance mode
		$app->uses('ini_parser,getconf');
		$server_config_array = $app->getconf->get_global_config('misc');
		if($server_config_array['maintenance_mode'] == 'y'){
78
			throw new SoapFault('maintenance_mode', 'This ISPConfig installation is currently under maintenance. We should be back shortly. Thank you for your patience.');
79
80
			return false;
		}
81

latham's avatar
latham committed
82
		if(empty($username)) {
83
			throw new SoapFault('login_username_empty', 'The login username is empty.');
latham's avatar
latham committed
84
85
			return false;
		}
86

latham's avatar
latham committed
87
		if(empty($password)) {
88
			throw new SoapFault('login_password_empty', 'The login password is empty.');
latham's avatar
latham committed
89
90
			return false;
		}
91

latham's avatar
latham committed
92
		//* Delete old remoting sessions
93
		$sql = "DELETE FROM remote_session WHERE tstamp < UNIX_TIMESTAMP()";
latham's avatar
latham committed
94
		$app->db->query($sql);
95
96

		if($client_login == true) {
97
98
			$sql = "SELECT * FROM sys_user WHERE USERNAME = ?";
			$user = $app->db->queryOneRecord($sql, $username);
99
100
101
			if($user) {
				$saved_password = stripslashes($user['passwort']);

102
				if(preg_match('/^\$[156]\$/', $saved_password)) {
103
					//* The password is crypt-md5 encrypted
104
					if(crypt(stripslashes($password), $saved_password) != $saved_password) {
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
						throw new SoapFault('client_login_failed', 'The login failed. Username or password wrong.');
					}
				} else {
					//* The password is md5 encrypted
					if(md5($password) != $saved_password) {
						throw new SoapFault('client_login_failed', 'The login failed. Username or password wrong.');
					}
				}
			} else {
				throw new SoapFault('client_login_failed', 'The login failed. Username or password wrong.');
			}
			if($user['active'] != 1) {
				throw new SoapFault('client_login_failed', 'The login failed. User is blocked.');
			}

			// now we need the client data
121
			$client = $app->db->queryOneRecord("SELECT client.can_use_api FROM sys_group, client WHERE sys_group.client_id = client.client_id and sys_group.groupid = ?", $user['default_group']);
122
123
124
125
126
127
128
129
130
131
132
133
			if(!$client || $client['can_use_api'] != 'y') {
				throw new SoapFault('client_login_failed', 'The login failed. Client may not use api.');
				return false;
			}

			//* Create a remote user session
			//srand ((double)microtime()*1000000);
			$remote_session = md5(mt_rand().uniqid('ispco'));
			$remote_userid = $user['userid'];
			$remote_functions = '';
			$tstamp = time() + $this->session_timeout;
			$sql = 'INSERT INTO remote_session (remote_session,remote_userid,remote_functions,client_login,tstamp'
134
135
				.') VALUES (?, ?, ?, 1, $tstamp)';
			$app->db->query($sql, $remote_session,$remote_userid,$remote_functions,$tstamp);
136
			return $remote_session;
latham's avatar
latham committed
137
		} else {
138
139
			$sql = "SELECT * FROM remote_user WHERE remote_username = ? and remote_password = md5(?)";
			$remote_user = $app->db->queryOneRecord($sql, $username, $password);
140
			if($remote_user['remote_userid'] > 0) {
141
142
143
144
145
146
147
				if (trim($remote_user['remote_ips']) != '') {
					$allowed_ips = explode(',',$remote_user['remote_ips']);
					foreach($allowed_ips as $i => $allowed) { 
						if(!filter_var($allowed, FILTER_VALIDATE_IP)) { 
							// get the ip for a hostname
							unset($allowed_ips[$i]);
							$temp=dns_get_record($allowed, DNS_A+DNS_AAAA);
Florian Schaal's avatar
Florian Schaal committed
148
149
150
151
152
153
							if(is_array($temp) && !empty($temp)) {
								foreach($temp as $t) {
									if(isset($t['ip'])) $allowed_ips[] = $t['ip'];
									if(isset($t['ipv6'])) $allowed_ips[] = $t['ipv6'];
								}
								unset($temp);
154
							}
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
						}
					}
				}
				$allowed_ips[] = '127.0.0.1';
				$allowed_ips[] = '::1';
				$allowed_ips=array_unique($allowed_ips);
				$ip = $_SERVER['REMOTE_ADDR'];
				$remote_allowed = @($ip == '::1' || $ip == '127.0.0.1')?true:false;
				if(!$remote_allowed && $remote_user['remote_access'] == 'y') {
					if(trim($remote_user['remote_ips']) == '') {
						$remote_allowed=true;
					} else {
						$ip = inet_pton($_SERVER['REMOTE_ADDR']);
						foreach($allowed_ips as $allowed) {
							if($ip == inet_pton(trim($allowed))) {
								$remote_allowed=true;
								break;
							}
						}
					}
				}
				if(!$remote_allowed) {
					throw new SoapFault('login_failed', 'The login is not allowed from '.$_SERVER['REMOTE_ADDR']);
					return false;
				}	
180
181
182
183
184
185
186
				//* Create a remote user session
				//srand ((double)microtime()*1000000);
				$remote_session = md5(mt_rand().uniqid('ispco'));
				$remote_userid = $remote_user['remote_userid'];
				$remote_functions = $remote_user['remote_functions'];
				$tstamp = time() + $this->session_timeout;
				$sql = 'INSERT INTO remote_session (remote_session,remote_userid,remote_functions,tstamp'
187
188
					.') VALUES (?, ?, ?, ?)';
				$app->db->query($sql, $remote_session,$remote_userid,$remote_functions,$tstamp);
189
190
191
192
193
194
195
				return $remote_session;
			} else {
				throw new SoapFault('login_failed', 'The login failed. Username or password wrong.');
				return false;
			}
		}

latham's avatar
latham committed
196
	}
197

latham's avatar
latham committed
198
199
	//* remote logout function
	public function logout($session_id)
200
	{
latham's avatar
latham committed
201
		global $app;
202

latham's avatar
latham committed
203
		if(empty($session_id)) {
204
			throw new SoapFault('session_id_empty', 'The SessionID is empty.');
latham's avatar
latham committed
205
206
			return false;
		}
207

208
209
		$sql = "DELETE FROM remote_session WHERE remote_session = ?";
		if($app->db->query($sql, $session_id) != false) {
210
211
212
213
			return true;
		} else {
			return false;
		}
latham's avatar
latham committed
214
	}
215

216
	//** protected functions -----------------------------------------------------------------------------------
217

218
	protected function klientadd($formdef_file, $reseller_id, $params)
219
	{
latham's avatar
latham committed
220
		global $app;
221

222
223
		//* Load the form definition
		$app->remoting_lib->loadFormDef($formdef_file);
224

225
226
		//* load the user profile of the client
		$app->remoting_lib->loadUserProfile($reseller_id);
227

228
		//* Get the SQL query
229
230
		$sql = $app->remoting_lib->getSQL($params, 'INSERT', 0);

231
		//* Check if no system user with that username exists
232
		$username = $params["username"];
233
		$tmp = $app->db->queryOneRecord("SELECT count(userid) as number FROM sys_user WHERE username = ?", $username);
234
		if($tmp['number'] > 0) $app->remoting_lib->errorMessage .= "Duplicate username<br />";
235

236
237
238
		//* Stop on error while preparing the sql query
		if($app->remoting_lib->errorMessage != '') {
			throw new SoapFault('data_processing_error', $app->remoting_lib->errorMessage);
latham's avatar
latham committed
239
240
			return false;
		}
241

242
243
		//* Execute the SQL query
		$app->db->query($sql);
244
245
246
247
		if($app->db->errorMessage != '') {
			throw new SoapFault('database_error', $app->db->errorMessage . ' '.$sql);
			return false;
		}
248
249
250
251
		if ( isset($params['_primary_id'] ))
			$insert_id = $params['_primary_id'];
		else
			$insert_id = $app->db->insertID();
252
253


254
255
256
		//* Stop on error while executing the sql query
		if($app->remoting_lib->errorMessage != '') {
			throw new SoapFault('data_processing_error', $app->remoting_lib->errorMessage);
257
258
			return false;
		}
259

260
261
		$this->id = $insert_id;
		$this->dataRecord = $params;
262
263
264

		$app->plugin->raiseEvent('client:' . (isset($params['limit_client']) && $params['limit_client'] > 0 ? 'reseller' : 'client') . ':on_after_insert', $this);

265
266
267
		/*
		if($app->db->errorMessage != '') {
			throw new SoapFault('database_error', $app->db->errorMessage . ' '.$sql);
268
269
			return false;
		}
270
		*/
271
272

		/* copied from the client_edit php */
273
274
		$app->uses('functions');
		$app->functions->generate_ssh_key($this->id, $username);
275
276
277



278
279
280
281
		//$app->uses('tform');
		//* Save changes to Datalog
		if($app->remoting_lib->formDef["db_history"] == 'yes') {
			$new_rec = $app->remoting_lib->getDataRecord($insert_id);
282
283
			$app->remoting_lib->datalogSave('INSERT', $primary_id, array(), $new_rec);
			$app->remoting_lib->ispconfig_sysuser_add($params, $insert_id);
284

285
			if($reseller_id) {
286
287
				$client_group = $app->db->queryOneRecord("SELECT * FROM sys_group WHERE client_id = ?", $insert_id);
				$reseller_user = $app->db->queryOneRecord("SELECT * FROM sys_user WHERE client_id = ?", $reseller_id);
288
				$app->auth->add_group_to_user($reseller_user['userid'], $client_group['groupid']);
289
				$app->db->query("UPDATE client SET parent_client_id = ? WHERE client_id = ?", $reseller_id, $insert_id);
290
			}
291

292
293
		}
		return $insert_id;
294
295
	}

296
297
298
299
300
301
	protected function insertQuery($formdef_file, $client_id, $params, $event_identifier = '')
	{
		$sql = $this->insertQueryPrepare($formdef_file, $client_id, $params);
		if($sql !== false) return $this->insertQueryExecute($sql, $params, $event_identifier);
		else return false;
	}
302
303

	protected function insertQueryPrepare($formdef_file, $client_id, $params)
304
	{
305
		global $app;
306

307
		$app->uses('remoting_lib');
308

309
310
		//* load the user profile of the client
		$app->remoting_lib->loadUserProfile($client_id);
311

312
313
		//* Load the form definition
		$app->remoting_lib->loadFormDef($formdef_file);
314

315
		//* Get the SQL query
316
		$sql = $app->remoting_lib->getSQL($params, 'INSERT', 0);
317
318
		if($app->remoting_lib->errorMessage != '') {
			throw new SoapFault('data_processing_error', $app->remoting_lib->errorMessage);
319
320
			return false;
		}
321
		$app->log('Executed insertQueryPrepare', LOGLEVEL_DEBUG);
322
		return $sql;
323
	}
324
325
326

	protected function insertQueryExecute($sql, $params, $event_identifier = '')
	{
327
		global $app;
328

329
		$app->uses('remoting_lib');
330

331
		$app->db->query($sql);
332

333
334
		if($app->db->errorMessage != '') {
			throw new SoapFault('database_error', $app->db->errorMessage . ' '.$sql);
335
336
			return false;
		}
337

Marius Burkard's avatar
Marius Burkard committed
338
339
340
341
		if ( isset($params['_primary_id'] ))
			$insert_id = $params['_primary_id'];
		else
			$insert_id = $app->db->insertID();
342

343
344
345
346
		// set a few values for compatibility with tform actions, mostly used by plugins
		$this->id = $insert_id;
		$this->dataRecord = $params;
		$app->log('Executed insertQueryExecute, raising events now if any: ' . $event_identifier, LOGLEVEL_DEBUG);
347
348
		if($event_identifier != '') $app->plugin->raiseEvent($event_identifier, $this);

349
350
351
352
		//$app->uses('tform');
		//* Save changes to Datalog
		if($app->remoting_lib->formDef["db_history"] == 'yes') {
			$new_rec = $app->remoting_lib->getDataRecord($insert_id);
353
354
			$app->remoting_lib->datalogSave('INSERT', $primary_id, array(), $new_rec);
		}
355
		return $insert_id;
356
	}
357

358
	protected function updateQuery($formdef_file, $client_id, $primary_id, $params, $event_identifier = '')
359
	{
latham's avatar
latham committed
360
		global $app;
361

362
		$sql = $this->updateQueryPrepare($formdef_file, $client_id, $primary_id, $params);
363
364
		if($sql !== false) return $this->updateQueryExecute($sql, $primary_id, $params, $event_identifier);
		else return false;
latham's avatar
latham committed
365
	}
366

367
	protected function updateQueryPrepare($formdef_file, $client_id, $primary_id, $params)
368
	{
369
		global $app;
370

371
		$app->uses('remoting_lib');
372

373
374
		//* load the user profile of the client
		$app->remoting_lib->loadUserProfile($client_id);
375

376
377
		//* Load the form definition
		$app->remoting_lib->loadFormDef($formdef_file);
378
379
		
		//* get old record and merge with params, so only new values have to be set in $params
380
               $old_rec = $app->remoting_lib->getDataRecord($primary_id, $client_id);
381
382
383
384
385
386
387
388
		
		foreach ($app->remoting_lib->formDef['fields'] as $fieldName => $fieldConf)
        {
            if ($fieldConf['formtype'] === 'PASSWORD' && empty($params[$fieldName])) {
                unset($old_rec[$fieldName]);
            }
        }
		
389
		$params = $app->functions->array_merge($old_rec,$params);
390

391
		//* Get the SQL query
392
		$sql = $app->remoting_lib->getSQL($params, 'UPDATE', $primary_id);
Marius Cramer's avatar
Marius Cramer committed
393
		
394
395
396
		// throw new SoapFault('debug', $sql);
		if($app->remoting_lib->errorMessage != '') {
			throw new SoapFault('data_processing_error', $app->remoting_lib->errorMessage);
397
398
			return false;
		}
399
400

		return $sql;
401
	}
latham's avatar
latham committed
402

403
	protected function updateQueryExecute($sql, $primary_id, $params, $event_identifier = '')
404
	{
405
		global $app;
406

407
		$app->uses('remoting_lib');
408

409
		$old_rec = $app->remoting_lib->getDataRecord($primary_id);
410

411
412
413
414
		// set a few values for compatibility with tform actions, mostly used by plugins
		$this->oldDataRecord = $old_rec;
		$this->id = $primary_id;
		$this->dataRecord = $params;
415

416
		$app->db->query($sql);
417

418
419
		if($app->db->errorMessage != '') {
			throw new SoapFault('database_error', $app->db->errorMessage . ' '.$sql);
420
421
			return false;
		}
422

423
424
		$affected_rows = $app->db->affectedRows();
		$app->log('Executed updateQueryExecute, raising events now if any: ' . $event_identifier, LOGLEVEL_DEBUG);
425
426
427

		if($event_identifier != '') $app->plugin->raiseEvent($event_identifier, $this);

428
429
430
		//* Save changes to Datalog
		if($app->remoting_lib->formDef["db_history"] == 'yes') {
			$new_rec = $app->remoting_lib->getDataRecord($primary_id);
431
			$app->remoting_lib->datalogSave('UPDATE', $primary_id, $old_rec, $new_rec);
latham's avatar
latham committed
432
		}
433

latham's avatar
latham committed
434
435
436
		return $affected_rows;
	}

437
	protected function deleteQuery($formdef_file, $primary_id, $event_identifier = '')
438
	{
latham's avatar
latham committed
439
		global $app;
440

latham's avatar
latham committed
441
		$app->uses('remoting_lib');
442

443
444
		//* load the user profile of the client
		$app->remoting_lib->loadUserProfile(0);
445

446
447
		//* Load the form definition
		$app->remoting_lib->loadFormDef($formdef_file);
448

449
		$old_rec = $app->remoting_lib->getDataRecord($primary_id);
450

451
452
453
454
455
456
		// set a few values for compatibility with tform actions, mostly used by plugins
		$this->oldDataRecord = $old_rec;
		$this->id = $primary_id;
		$this->dataRecord = $old_rec;
		$app->log('Executed deleteQuery, raising events now if any: ' . $event_identifier, LOGLEVEL_DEBUG);
		//$this->dataRecord = $params;
457

458
459
460
461
462
		//* Get the SQL query
		$sql = $app->remoting_lib->getDeleteSQL($primary_id);
		$app->db->errorMessage = '';
		$app->db->query($sql);
		$affected_rows = $app->db->affectedRows();
463

464
465
		if($app->db->errorMessage != '') {
			throw new SoapFault('database_error', $app->db->errorMessage . ' '.$sql);
latham's avatar
latham committed
466
467
			return false;
		}
468

469
		if($event_identifier != '') {
470
			$app->plugin->raiseEvent($event_identifier, $this);
latham's avatar
latham committed
471
		}
472

473
474
		//* Save changes to Datalog
		if($app->remoting_lib->formDef["db_history"] == 'yes') {
475
			$app->remoting_lib->datalogSave('DELETE', $primary_id, $old_rec, array());
latham's avatar
latham committed
476
		}
477
478


479
		return $affected_rows;
latham's avatar
latham committed
480
	}
481
482


483
	protected function checkPerm($session_id, $function_name)
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
	{
		global $app;
		$dobre=array();
		$session = $this->getSession($session_id);
		if(!$session){
			return false;
		}

		$_SESSION['client_login'] = $session['client_login'];
		if($session['client_login'] == 1) {
			// permissions are checked at an other place
			$_SESSION['client_sys_userid'] = $session['remote_userid'];
			$app->remoting_lib->loadUserProfile(); // load the profile - we ALWAYS need this on client logins!
			return true;
		} else {
			$_SESSION['client_sys_userid'] = 0;
		}

		$dobre= str_replace(';', ',', $session['remote_functions']);
503
504
		$check = in_array($function_name, explode(',', $dobre) );
		if(!$check) {
505
			$app->log("REMOTE-LIB DENY: ".$session_id ." /". $function_name, LOGLEVEL_WARN);
latham's avatar
latham committed
506
		}
507
		return $check;
latham's avatar
latham committed
508
	}
509
510


511
	protected function getSession($session_id)
512
	{
latham's avatar
latham committed
513
		global $app;
514

515
		if(empty($session_id)) {
516
			throw new SoapFault('session_id_empty', 'The SessionID is empty.');
latham's avatar
latham committed
517
518
			return false;
		}
519

520
		$sql = "SELECT * FROM remote_session WHERE remote_session = ? AND tstamp >= UNIX_TIMESTAMP()";
521
		$session = $app->db->queryOneRecord($sql, $session_id);
522
523
		if($session['remote_userid'] > 0) {
			return $session;
latham's avatar
latham committed
524
		} else {
525
			throw new SoapFault('session_does_not_exist', 'The Session is expired or does not exist.');
latham's avatar
latham committed
526
527
528
			return false;
		}
	}
529

530
	public function server_get($session_id, $server_id = null, $section ='') {
531
532
		global $app;
		if(!$this->checkPerm($session_id, 'server_get')) {
533
			throw new SoapFault('permission_denied', 'You do not have the permissions to access this function.');
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
			return false;
		}
		if (!empty($session_id)) {
			if(!empty($server_id)) {
				$app->uses('remoting_lib , getconf');
				$section_config =  $app->getconf->get_server_config($server_id, $section);
				return $section_config;
			} else {
				$servers = array();
				$sql = "SELECT server_id FROM server WHERE 1";
				$all = $app->db->queryAllRecords($sql);
				foreach($all as $s) {
					$servers[$s['server_id']] = $app->getconf->get_server_config($s['server_id'], $section);
				}
				unset($all);
				unset($s);
				return $servers;
			}
		} else {
553
554
			return false;
		}
555
556
557
558
559
560
561
562
563
564
565
566
	}
	
	/**
	    Gets a list of all servers
	    @param int session_id
	    @param int server_name
	    @author Marius Cramer <m.cramer@pixcept.de> 2014
    */
	public function server_get_all($session_id)
    {
        global $app;
		if(!$this->checkPerm($session_id, 'server_get')) {
567
        	throw new SoapFault('permission_denied', 'You do not have the permissions to access this function.');
568
569
570
571
572
573
            return false;
		}
		if (!empty($session_id)) {
			$sql = "SELECT server_id, server_name FROM server WHERE 1";
			$servers = $app->db->queryAllRecords($sql);
			return $servers;
574
575
576
577
578
		} else {
			return false;
		}
	}

579
	/**
580
581
582
583
584
585
586
587
588
589
	 * Get a list of functions
	 * @param  int  session id
	 * @return mixed array of the available functions
	 * @author Julio Montoya <gugli100@gmail.com> BeezNest 2010
	 */


	public function get_function_list($session_id)
	{
		if(!$this->checkPerm($session_id, 'get_function_list')) {
590
			throw new SoapFault('permission_denied', 'You do not have the permissions to access this function.');
591
			return false;
592
593
594
595
		}
		return $this->_methods;
	}

latham's avatar
latham committed
596
}
597

598
?>