installer_base.lib.php 73.2 KB
Newer Older
1 2 3
<?php

/*
vogelor's avatar
vogelor committed
4
Copyright (c) 2007-2010, Till Brehm, projektfarm Gmbh
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
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.
*/

class installer_base {
32

33 34 35 36 37 38 39 40
	var $wb = array();
	var $language = 'en';
	var $db;
	public $conf;
	public $install_ispconfig_interface = true;
	public $is_update = false; // true if it is an update, falsi if it is a new install


41 42 43 44 45 46 47
	public function __construct() {
		global $conf; //TODO: maybe $conf  should be passed to constructor
		//$this->conf = $conf;
	}

	//: TODO  Implement the translation function and language files for the installer.
	public function lng($text) {
48 49
		return $text;
	}
50 51

	public function error($msg) {
52 53
		die("ERROR: ".$msg."\n");
	}
54 55

	public function simple_query($query, $answers, $default) {
56 57 58 59 60
		$finished = false;
		do {
			$answers_str = implode(',', $answers);
			swrite($this->lng($query).' ('.$answers_str.') ['.$default.']: ');
			$input = sread();
61

62 63 64 65 66
			//* Stop the installation
			if($input == 'quit') {
				swriteln($this->lng("Installation terminated by user.\n"));
				die();
			}
67

68 69 70 71 72
			//* Select the default
			if($input == '') {
				$answer = $default;
				$finished = true;
			}
73 74

			//* Set answer id valid
75 76 77 78
			if(in_array($input, $answers)) {
				$answer = $input;
				$finished = true;
			}
79

80 81 82 83
		} while ($finished == false);
		swriteln();
		return $answer;
	}
84 85

	public function free_query($query,$default) {
86 87
		swrite($this->lng($query).' ['.$default.']: ');
		$input = sread();
88

89 90
		//* Stop the installation
		if($input == 'quit') {
91 92
			swriteln($this->lng("Installation terminated by user.\n"));
			die();
93
		}
94 95

		$answer =  ($input == '') ? $default : $input;
96 97 98
		swriteln();
		return $answer;
	}
99

100 101 102 103 104 105 106 107 108
	/*
	// TODO: this function is not used atmo I think - pedro
	function request_language(){
		
		swriteln(lng('Enter your language'));
		swriteln(lng('de, en'));
		
	}
	*/
109

110 111 112
	//** Detect installed applications
	public function find_installed_apps() {
		global $conf;
113

114 115 116 117 118
		if(is_installed('mysql') || is_installed('mysqld')) $conf['mysql']['installed'] = true;
		if(is_installed('postfix')) $conf['postfix']['installed'] = true;
		if(is_installed('apache') || is_installed('apache2') || is_installed('httpd')) $conf['apache']['installed'] = true;
		if(is_installed('getmail')) $conf['getmail']['installed'] = true;
		if(is_installed('couriertcpd')) $conf['courier']['installed'] = true;
119
		if(is_installed('dovecot')) $conf['dovecot']['installed'] = true;
120 121 122 123 124 125
		if(is_installed('saslsauthd')) $conf['saslauthd']['installed'] = true;
		if(is_installed('amavisd-new')) $conf['amavis']['installed'] = true;
		if(is_installed('clamdscan')) $conf['clamav']['installed'] = true;
		if(is_installed('pure-ftpd') || is_installed('pure-ftpd-wrapper')) $conf['pureftpd']['installed'] = true;
		if(is_installed('mydns') || is_installed('mydns-ng')) $conf['mydns']['installed'] = true;
		if(is_installed('jk_chrootsh')) $conf['jailkit']['installed'] = true;
126
		if(is_installed('pdns_server') || is_installed('pdns_control')) $conf['powerdns']['installed'] = true;
127
		if(is_installed('named') || is_installed('bind') || is_installed('bind9')) $conf['bind']['installed'] = true;
128

129
	}
130 131

	/** Create the database for ISPConfig */
132 133
	public function configure_database() {
		global $conf;
134

135 136 137 138
		//** Create the database
		if(!$this->db->query('CREATE DATABASE IF NOT EXISTS '.$conf['mysql']['database'].' DEFAULT CHARACTER SET '.$conf['mysql']['charset'])) {
			$this->error('Unable to create MySQL database: '.$conf['mysql']['database'].'.');
		}
139

140 141
		//* Set the database name in the DB library
		$this->db->dbName = $conf['mysql']['database'];
142

143 144 145 146 147 148
		//* Load the database dump into the database, if database contains no tables
		$db_tables = $this->db->getTables();
		if(count($db_tables) > 0) {
			$this->error('Stopped: Database already contains some tables.');
		} else {
			if($conf['mysql']['admin_password'] == '') {
149 150
				caselog("mysql --default-character-set=".$conf['mysql']['charset']." -h '".$conf['mysql']['host']."' -u '".$conf['mysql']['admin_user']."' '".$conf['mysql']['database']."' < '".ISPC_INSTALL_ROOT."/install/sql/ispconfig3.sql' &> /dev/null",
						__FILE__, __LINE__, 'read in ispconfig3.sql', 'could not read in ispconfig3.sql');
151
			} else {
vogelor's avatar
vogelor committed
152
				caselog("mysql --default-character-set=".$conf['mysql']['charset']." -h '".$conf['mysql']['host']."' -u '".$conf['mysql']['admin_user']."' -p'".$conf['mysql']['admin_password']."' '".$conf['mysql']['database']."' < '".ISPC_INSTALL_ROOT."/install/sql/ispconfig3.sql' &> /dev/null",
153
						__FILE__, __LINE__, 'read in ispconfig3.sql', 'could not read in ispconfig3.sql');
154 155 156 157 158
			}
			$db_tables = $this->db->getTables();
			if(count($db_tables) == 0) {
				$this->error('Unable to load SQL-Dump into database table.');
			}
159

160 161 162
			//* Load system.ini into the sys_ini table
			$system_ini = $this->db->quote(rf('tpl/system.ini.master'));
			$this->db->query("UPDATE sys_ini SET config = '$system_ini' WHERE sysini_id = 1");
163

164 165
		}
	}
166

167 168
	//** Create the server record in the database
	public function add_database_server_record() {
169

170
		global $conf;
171

172 173 174 175 176
		if($conf['mysql']['host'] == 'localhost') {
			$from_host = 'localhost';
		} else {
			$from_host = $conf['hostname'];
		}
177

178 179 180 181
		// Delete ISPConfig user in the local database, in case that it exists
		$this->db->query("DELETE FROM mysql.user WHERE User = '".$conf['mysql']['ispconfig_user']."' AND Host = '".$from_host."';");
		$this->db->query("DELETE FROM mysql.db WHERE Db = '".$conf['mysql']['database']."' AND Host = '".$from_host."';");
		$this->db->query('FLUSH PRIVILEGES;');
182

183
		//* Create the ISPConfig database user in the local database
184 185 186
		$query = 'GRANT SELECT, INSERT, UPDATE, DELETE ON '.$conf['mysql']['database'].".* "
				."TO '".$conf['mysql']['ispconfig_user']."'@'".$from_host."' "
				."IDENTIFIED BY '".$conf['mysql']['ispconfig_password']."';";
187 188 189
		if(!$this->db->query($query)) {
			$this->error('Unable to create database user: '.$conf['mysql']['ispconfig_user'].' Error: '.$this->db->errorMessage);
		}
190

191 192
		//* Reload database privelages
		$this->db->query('FLUSH PRIVILEGES;');
193

194 195
		//* Set the database name in the DB library
		$this->db->dbName = $conf['mysql']['database'];
196

197
		$tpl_ini_array = ini_to_array(rf('tpl/server.ini.master'));
198

199 200 201 202 203 204 205 206 207 208 209
		// TODO: Update further distribution specific parameters for server config here
		$tpl_ini_array['web']['vhost_conf_dir'] = $conf['apache']['vhost_conf_dir'];
		$tpl_ini_array['web']['vhost_conf_enabled_dir'] = $conf['apache']['vhost_conf_enabled_dir'];
		$tpl_ini_array['jailkit']['jailkit_chroot_app_programs'] = $conf['jailkit']['jailkit_chroot_app_programs'];
		$tpl_ini_array['fastcgi']['fastcgi_phpini_path'] = $conf['fastcgi']['fastcgi_phpini_path'];
		$tpl_ini_array['fastcgi']['fastcgi_starter_path'] = $conf['fastcgi']['fastcgi_starter_path'];
		$tpl_ini_array['server']['hostname'] = $conf['hostname'];
		$tpl_ini_array['server']['ip_address'] = @gethostbyname($conf['hostname']);
		$tpl_ini_array['web']['website_basedir'] = $conf['web']['website_basedir'];
		$tpl_ini_array['web']['website_path'] = $conf['web']['website_path'];
		$tpl_ini_array['web']['website_symlinks'] = $conf['web']['website_symlinks'];
210
		$tpl_ini_array['cron']['crontab_dir'] = $conf['cron']['crontab_dir'];
tbrehm's avatar
tbrehm committed
211
		$tpl_ini_array['web']['security_level'] = 20;
212 213
		$tpl_ini_array['web']['user'] = $conf['apache']['user'];
		$tpl_ini_array['web']['group'] = $conf['apache']['group'];
214 215
		$tpl_ini_array['mail']['pop3_imap_daemon'] = ($conf['dovecot']['installed'] == true)?'dovecot':'courier';
		$tpl_ini_array['mail']['mail_filter_syntax'] = ($conf['dovecot']['installed'] == true)?'sieve':'maildrop';
tbrehm's avatar
tbrehm committed
216 217 218 219 220
		$tpl_ini_array['dns']['bind_user'] = $conf['bind']['bind_user'];
		$tpl_ini_array['dns']['bind_group'] = $conf['bind']['bind_group'];
		$tpl_ini_array['dns']['bind_zonefiles_dir'] = $conf['bind']['bind_zonefiles_dir'];
		$tpl_ini_array['dns']['named_conf_path'] = $conf['bind']['named_conf_path'];
		$tpl_ini_array['dns']['named_conf_local_path'] = $conf['bind']['named_conf_local_path'];
221

222 223
		$server_ini_content = array_to_ini($tpl_ini_array);
		$server_ini_content = mysql_real_escape_string($server_ini_content);
224

225 226 227 228 229 230
		$mail_server_enabled = ($conf['services']['mail'])?1:0;
		$web_server_enabled = ($conf['services']['web'])?1:0;
		$dns_server_enabled = ($conf['services']['dns'])?1:0;
		$file_server_enabled = ($conf['services']['file'])?1:0;
		$db_server_enabled = ($conf['services']['db'])?1:0;
		$vserver_server_enabled = ($conf['services']['vserver'])?1:0;
231 232 233



234
		if($conf['mysql']['master_slave_setup'] == 'y') {
235

236 237 238 239 240
			//* Insert the server record in master DB
			$sql = "INSERT INTO `server` (`sys_userid`, `sys_groupid`, `sys_perm_user`, `sys_perm_group`, `sys_perm_other`, `server_name`, `mail_server`, `web_server`, `dns_server`, `file_server`, `db_server`, `vserver_server`, `config`, `updated`, `active`) VALUES (1, 1, 'riud', 'riud', 'r', '".$conf['hostname']."', '$mail_server_enabled', '$web_server_enabled', '$dns_server_enabled', '$file_server_enabled', '$db_server_enabled', '$vserver_server_enabled', '$server_ini_content', 0, 1);";
			$this->dbmaster->query($sql);
			$conf['server_id'] = $this->dbmaster->insertID();
			$conf['server_id'] = $conf['server_id'];
241

242 243 244
			//* Insert the same record in the local DB
			$sql = "INSERT INTO `server` (`server_id`, `sys_userid`, `sys_groupid`, `sys_perm_user`, `sys_perm_group`, `sys_perm_other`, `server_name`, `mail_server`, `web_server`, `dns_server`, `file_server`, `db_server`, `vserver_server`, `config`, `updated`, `active`) VALUES ('".$conf['server_id']."',1, 1, 'riud', 'riud', 'r', '".$conf['hostname']."', '$mail_server_enabled', '$web_server_enabled', '$dns_server_enabled', '$file_server_enabled', '$db_server_enabled', '$vserver_server_enabled', '$server_ini_content', 0, 1);";
			$this->db->query($sql);
245

246 247
			//* username for the ispconfig user
			$conf['mysql']['master_ispconfig_user'] = 'ispcsrv'.$conf['server_id'];
248 249 250

			$this->grant_master_database_rights();

251 252 253 254 255 256 257
		} else {
			//* Insert the server, if its not a mster / slave setup
			$sql = "INSERT INTO `server` (`sys_userid`, `sys_groupid`, `sys_perm_user`, `sys_perm_group`, `sys_perm_other`, `server_name`, `mail_server`, `web_server`, `dns_server`, `file_server`, `db_server`, `vserver_server`, `config`, `updated`, `active`) VALUES (1, 1, 'riud', 'riud', 'r', '".$conf['hostname']."', '$mail_server_enabled', '$web_server_enabled', '$dns_server_enabled', '$file_server_enabled', '$db_server_enabled', '$vserver_server_enabled', '$server_ini_content', 0, 1);";
			$this->db->query($sql);
			$conf['server_id'] = $this->db->insertID();
			$conf['server_id'] = $conf['server_id'];
		}
258 259


260
	}
261 262 263 264

	public function grant_master_database_rights() {
		global $conf;

265 266 267 268 269 270 271 272 273 274 275 276 277
		/*
		 * The following code is a little bit tricky:
		 * * If we HAVE a master-slave - Setup then the client has to grant the rights for himself
		 *   at the master.
		 * * If we DO NOT have a master-slave - Setup then we have two possibilities
		 *   1) it is a single server
		 *   2) it is the MASTER of n clients
		*/
		if($conf['mysql']['master_slave_setup'] == 'y') {
			/*
			 * it is a master-slave - Setup so the slave has to grant its rights in the master
			 * database
			 */
278

279 280 281 282 283 284
			//* insert the ispconfig user in the remote server
			$from_host = $conf['hostname'];
			$from_ip = gethostbyname($conf['hostname']);
			
			$hosts[$from_host]['user'] = $conf['mysql']['master_ispconfig_user'];
			$hosts[$from_host]['db'] = $conf['mysql']['master_database'];
285
			$hosts[$from_host]['pwd'] = $conf['mysql']['master_ispconfig_password'];
286 287 288

			$hosts[$from_ip]['user'] = $conf['mysql']['master_ispconfig_user'];
			$hosts[$from_ip]['db'] = $conf['mysql']['master_database'];
289
			$hosts[$from_ip]['pwd'] = $conf['mysql']['master_ispconfig_password'];
290 291 292 293 294 295 296 297 298 299 300 301 302
		} else{
			/*
			 * it is NOT a master-slave - Setup so we have to find out all clients and their
			 * host
			 */
			$query = "SELECT Host, User FROM mysql.user WHERE User like 'ispcsrv%' ORDER BY User, Host";
			$data = $this->dbmaster->queryAllRecords($query);
			if($data === false) {
				$this->error('Unable to get the user rights: '.$value['db'].' Error: '.$this->dbmaster->errorMessage);
			}
			foreach ($data as $item){
				$hosts[$item['Host']]['user'] = $item['User'];
				$hosts[$item['Host']]['db'] = $conf['mysql']['master_database'];
303
				$hosts[$item['Host']]['pwd'] = ''; // the user already exists, so we need no pwd!
304 305
			}
		}
306 307
		
		if(is_array($hosts)) {
308 309
		foreach($hosts as $host => $value) {
			/*
310 311
			 * If a pwd exists, this means, we have to add the new user (and his pwd).
			 * if not, the user already exists and we do not need the pwd
312
			 */
313 314 315
			if ($value['pwd'] != ''){
				$query = "CREATE USER '".$value['user']."'@'".$host."' IDENTIFIED BY '" . $value['pwd'] . "'";
				$this->dbmaster->query($query); // ignore the error
316
			}
317

318 319 320 321 322 323 324
			/*
			 *  Try to delete all rights of the user in case that it exists.
			 *  In Case that it will not exist, do nothing (ignore the error!)
			 */
			$query = "REVOKE ALL PRIVILEGES, GRANT OPTION FROM '".$value['user']."'@'".$host."' ";
			$this->dbmaster->query($query); // ignore the error

325
			//* Create the ISPConfig database user in the remote database
326
			$query = "GRANT SELECT ON ".$value['db'].".`server` TO '".$value['user']."'@'".$host."' ";
327
			if(!$this->dbmaster->query($query)) {
328
				$this->error('Unable to set rights of user in master database: '.$value['db'].' Error: '.$this->dbmaster->errorMessage);
329 330
			}

331
			$query = "GRANT SELECT, INSERT ON ".$value['db'].".`sys_log` TO '".$value['user']."'@'".$host."' ";
332
			if(!$this->dbmaster->query($query)) {
333
				$this->error('Unable to set rights of user in master database: '.$value['db'].' Error: '.$this->dbmaster->errorMessage);
334 335
			}

336
			$query = "GRANT SELECT, UPDATE(`status`) ON ".$value['db'].".`sys_datalog` TO '".$value['user']."'@'".$host."' ";
337
			if(!$this->dbmaster->query($query)) {
338
				$this->error('Unable to set rights of user in master database: '.$value['db'].' Error: '.$this->dbmaster->errorMessage);
339 340
			}

341
			$query = "GRANT SELECT, UPDATE(`status`) ON ".$value['db'].".`software_update_inst` TO '".$value['user']."'@'".$host."' ";
342
			if(!$this->dbmaster->query($query)) {
343
				$this->error('Unable to set rights of user in master database: '.$value['db'].' Error: '.$this->dbmaster->errorMessage);
344 345
			}

346
			$query = "GRANT SELECT, UPDATE(`updated`) ON ".$value['db'].".`server` TO '".$value['user']."'@'".$host."' ";
347
			if(!$this->dbmaster->query($query)) {
348
				$this->error('Unable to set rights of user in master database: '.$value['db'].' Error: '.$this->dbmaster->errorMessage);
349 350
			}

351
			$query = "GRANT SELECT, UPDATE (`ssl_request`, `ssl_cert`, `ssl_action`) ON ".$value['db'].".`web_domain` TO '".$value['user']."'@'".$host."' ";
352
			if(!$this->dbmaster->query($query)) {
353
				$this->error('Unable to set rights of user in master database: '.$value['db'].' Error: '.$this->dbmaster->errorMessage);
354 355
			}

356
			$query = "GRANT SELECT ON ".$value['db'].".`sys_group` TO '".$value['user']."'@'".$host."' ";
357
			if(!$this->dbmaster->query($query)) {
358
				$this->error('Unable to set rights of user in master database: '.$value['db'].' Error: '.$this->dbmaster->errorMessage);
359 360
			}

361
			$query = "GRANT SELECT, UPDATE (`action_state`, `response`) ON ".$value['db'].".`sys_remoteaction` TO '".$value['user']."'@'".$host."' ";
362
			if(!$this->dbmaster->query($query)) {
363
				$this->error('Unable to set rights of user in master database: '.$value['db'].' Error: '.$this->dbmaster->errorMessage);
364 365
			}

366
			$query = "GRANT SELECT, INSERT , DELETE ON ".$value['db'].".`monitor_data` TO '".$value['user']."'@'".$host."' ";
367
			if(!$this->dbmaster->query($query)) {
368
				$this->error('Unable to set rights of user in master database: '.$value['db'].' Error: '.$this->dbmaster->errorMessage);
369 370
			}

371
			$query = "GRANT SELECT, INSERT, UPDATE ON ".$value['db'].".`mail_traffic` TO '".$value['user']."'@'".$host."' ";
372
			if(!$this->dbmaster->query($query)) {
373
				$this->error('Unable to set rights of user in master database: '.$value['db'].' Error: '.$this->dbmaster->errorMessage);
374 375
			}

376
			$query = "GRANT SELECT, INSERT, UPDATE ON ".$value['db'].".`web_traffic` TO '".$value['user']."'@'".$host."' ";
377
			if(!$this->dbmaster->query($query)) {
378
				$this->error('Unable to set rights of user in master database: '.$value['db'].' Error: '.$this->dbmaster->errorMessage);
379 380 381
			}
		}

382 383 384 385
		/*
		 * It is all done. Relod the rights...
		 */
		$this->dbmaster->query('FLUSH PRIVILEGES;');
386
		}
387

388 389 390 391
	}

	//** writes postfix configuration files
	public function process_postfix_config($configfile) {
392
		global $conf;
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411

		$config_dir = $conf['postfix']['config_dir'].'/';
		$full_file_name = $config_dir.$configfile;
		//* Backup exiting file
		if(is_file($full_file_name)) {
			copy($full_file_name, $config_dir.$configfile.'~');
		}
		$content = rf('tpl/'.$configfile.'.master');
		$content = str_replace('{mysql_server_ispconfig_user}', $conf['mysql']['ispconfig_user'], $content);
		$content = str_replace('{mysql_server_ispconfig_password}', $conf['mysql']['ispconfig_password'], $content);
		$content = str_replace('{mysql_server_database}', $conf['mysql']['database'], $content);
		$content = str_replace('{mysql_server_ip}', $conf['mysql']['ip'], $content);
		$content = str_replace('{server_id}', $conf['server_id'], $content);
		wf($full_file_name, $content);
	}

	public function configure_jailkit() {
		global $conf;

412 413 414 415
		$cf = $conf['jailkit'];
		$config_dir = $cf['config_dir'];
		$jk_init = $cf['jk_init'];
		$jk_chrootsh = $cf['jk_chrootsh'];
416 417

		if (is_dir($config_dir)) {
418 419
			if(is_file($config_dir.'/'.$jk_init)) copy($config_dir.'/'.$jk_init, $config_dir.'/'.$jk_init.'~');
			if(is_file($config_dir.'/'.$jk_chrootsh.".master")) copy($config_dir.'/'.$jk_chrootsh.".master", $config_dir.'/'.$jk_chrootsh.'~');
420

421 422 423
			copy('tpl/'.$jk_init.".master", $config_dir.'/'.$jk_init);
			copy('tpl/'.$jk_chrootsh.".master", $config_dir.'/'.$jk_chrootsh);
		}
424 425 426 427 428

	}

	public function configure_postfix($options = '') {
		global $conf;
429 430
		$cf = $conf['postfix'];
		$config_dir = $cf['config_dir'];
431 432 433 434 435

		if(!is_dir($config_dir)) {
			$this->error("The postfix configuration directory '$config_dir' does not exist.");
		}

436
		//* mysql-virtual_domains.cf
437
		$this->process_postfix_config('mysql-virtual_domains.cf');
438 439

		//* mysql-virtual_forwardings.cf
440
		$this->process_postfix_config('mysql-virtual_forwardings.cf');
441 442

		//* mysql-virtual_mailboxes.cf
443
		$this->process_postfix_config('mysql-virtual_mailboxes.cf');
444 445

		//* mysql-virtual_email2email.cf
446
		$this->process_postfix_config('mysql-virtual_email2email.cf');
447 448

		//* mysql-virtual_transports.cf
449
		$this->process_postfix_config('mysql-virtual_transports.cf');
450 451

		//* mysql-virtual_recipient.cf
452
		$this->process_postfix_config('mysql-virtual_recipient.cf');
453 454

		//* mysql-virtual_sender.cf
455
		$this->process_postfix_config('mysql-virtual_sender.cf');
456 457

		//* mysql-virtual_client.cf
458 459
		$this->process_postfix_config('mysql-virtual_client.cf');

460
		//* mysql-virtual_relaydomains.cf
461 462
		$this->process_postfix_config('mysql-virtual_relaydomains.cf');

463
		//* mysql-virtual_relayrecipientmaps.cf
464
		$this->process_postfix_config('mysql-virtual_relayrecipientmaps.cf');
465 466 467

		//* Changing mode and group of the new created config files.
		caselog('chmod o= '.$config_dir.'/mysql-virtual_*.cf* &> /dev/null',
468 469 470 471
				__FILE__, __LINE__, 'chmod on mysql-virtual_*.cf*', 'chmod on mysql-virtual_*.cf* failed');
		caselog('chgrp '.$cf['group'].' '.$config_dir.'/mysql-virtual_*.cf* &> /dev/null',
				__FILE__, __LINE__, 'chgrp on mysql-virtual_*.cf*', 'chgrp on mysql-virtual_*.cf* failed');

472 473 474 475 476
		//* Creating virtual mail user and group
		$command = 'groupadd -g '.$cf['vmail_groupid'].' '.$cf['vmail_groupname'];
		if(!is_group($cf['vmail_groupname'])) caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");

		$command = 'useradd -g '.$cf['vmail_groupname'].' -u '.$cf['vmail_userid'].' '.$cf['vmail_username'].' -d '.$cf['vmail_mailbox_base'].' -m';
477
		if(!is_user($cf['vmail_username'])) caselog("$command &> /dev/null", __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
478 479

		$postconf_commands = array (
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
				'myhostname = '.$conf['hostname'],
				'mydestination = '.$conf['hostname'].', localhost, localhost.localdomain',
				'mynetworks = 127.0.0.0/8 [::1]/128',
				'virtual_alias_domains =',
				'virtual_alias_maps = proxy:mysql:'.$config_dir.'/mysql-virtual_forwardings.cf, mysql:'.$config_dir.'/mysql-virtual_email2email.cf',
				'virtual_mailbox_domains = proxy:mysql:'.$config_dir.'/mysql-virtual_domains.cf',
				'virtual_mailbox_maps = proxy:mysql:'.$config_dir.'/mysql-virtual_mailboxes.cf',
				'virtual_mailbox_base = '.$cf['vmail_mailbox_base'],
				'virtual_uid_maps = static:'.$cf['vmail_userid'],
				'virtual_gid_maps = static:'.$cf['vmail_groupid'],
				'smtpd_sasl_auth_enable = yes',
				'broken_sasl_auth_clients = yes',
				'smtpd_sasl_authenticated_header = yes',
				'smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, check_recipient_access mysql:'.$config_dir.'/mysql-virtual_recipient.cf, reject_unauth_destination',
				'smtpd_use_tls = yes',
				'smtpd_tls_security_level = may',
				'smtpd_tls_cert_file = '.$config_dir.'/smtpd.cert',
				'smtpd_tls_key_file = '.$config_dir.'/smtpd.key',
				'transport_maps = proxy:mysql:'.$config_dir.'/mysql-virtual_transports.cf',
				'relay_domains = mysql:'.$config_dir.'/mysql-virtual_relaydomains.cf',
				'relay_recipient_maps = mysql:'.$config_dir.'/mysql-virtual_relayrecipientmaps.cf',
				'virtual_create_maildirsize = yes',
				'virtual_maildir_extended = yes',
				'virtual_mailbox_limit_maps = proxy:mysql:'.$config_dir.'/mysql-virtual_mailbox_limit_maps.cf',
				'virtual_mailbox_limit_override = yes',
				'virtual_maildir_limit_message = "The user you are trying to reach is over quota."',
				'virtual_overquota_bounce = yes',
				'proxy_read_maps = $local_recipient_maps $mydestination $virtual_alias_maps $virtual_alias_domains $virtual_mailbox_maps $virtual_mailbox_domains $relay_recipient_maps $relay_domains $canonical_maps $sender_canonical_maps $recipient_canonical_maps $relocated_maps $transport_maps $mynetworks $virtual_mailbox_limit_maps',
				'smtpd_sender_restrictions = check_sender_access mysql:'.$config_dir.'/mysql-virtual_sender.cf',
				'smtpd_client_restrictions = check_client_access mysql:'.$config_dir.'/mysql-virtual_client.cf',
				'maildrop_destination_concurrency_limit = 1',
				'maildrop_destination_recipient_limit   = 1',
				'virtual_transport = maildrop',
				'header_checks = regexp:'.$config_dir.'/header_checks',
				'mime_header_checks = regexp:'.$config_dir.'/mime_header_checks',
				'nested_header_checks = regexp:'.$config_dir.'/nested_header_checks',
				'body_checks = regexp:'.$config_dir.'/body_checks'
517
		);
518

519 520 521 522 523
		//* Create the header and body check files
		touch($config_dir.'/header_checks');
		touch($config_dir.'/mime_header_checks');
		touch($config_dir.'/nested_header_checks');
		touch($config_dir.'/body_checks');
524 525


526 527
		//* Make a backup copy of the main.cf file
		copy($config_dir.'/main.cf', $config_dir.'/main.cf~');
528

529 530 531 532 533
		//* Executing the postconf commands
		foreach($postconf_commands as $cmd) {
			$command = "postconf -e '$cmd'";
			caselog($command." &> /dev/null", __FILE__, __LINE__, 'EXECUTED: '.$command, 'Failed to execute the command '.$command);
		}
534

535 536 537
		if(!stristr($options,'dont-create-certs')) {
			//* Create the SSL certificate
			$command = 'cd '.$config_dir.'; '
538
					.'openssl req -new -outform PEM -out smtpd.cert -newkey rsa:2048 -nodes -keyout smtpd.key -keyform PEM -days 365 -x509';
539
			exec($command);
540

541 542 543
			$command = 'chmod o= '.$config_dir.'/smtpd.key';
			caselog($command.' &> /dev/null', __FILE__, __LINE__, 'EXECUTED: '.$command, 'Failed to execute the command '.$command);
		}
544

545 546
		//** We have to change the permissions of the courier authdaemon directory to make it accessible for maildrop.
		$command = 'chmod 755  /var/run/courier/authdaemon/';
547
		if(is_file('/var/run/courier/authdaemon/')) caselog($command.' &> /dev/null', __FILE__, __LINE__, 'EXECUTED: '.$command, 'Failed to execute the command '.$command);
548

549
		//* Changing maildrop lines in posfix master.cf
550 551 552 553 554 555
		if(is_file($config_dir.'/master.cf')) {
			copy($config_dir.'/master.cf', $config_dir.'/master.cf~');
		}
		if(is_file($config_dir.'/master.cf~')) {
			exec('chmod 400 '.$config_dir.'/master.cf~');
		}
556 557
		$configfile = $config_dir.'/master.cf';
		$content = rf($configfile);
558 559 560
		$content = str_replace('flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}',
				'flags=DRhu user='.$cf['vmail_username'].' argv=/usr/bin/maildrop -d '.$cf['vmail_username'].' ${extension} ${recipient} ${user} ${nexthop} ${sender}',
				$content);
561
		wf($configfile, $content);
562

563 564
		//* Writing the Maildrop mailfilter file
		$configfile = 'mailfilter';
565 566 567
		if(is_file($cf['vmail_mailbox_base'].'/.'.$configfile)) {
			copy($cf['vmail_mailbox_base'].'/.'.$configfile, $cf['vmail_mailbox_base'].'/.'.$configfile.'~');
		}
568 569 570
		$content = rf("tpl/$configfile.master");
		$content = str_replace('{dist_postfix_vmail_mailbox_base}', $cf['vmail_mailbox_base'], $content);
		wf($cf['vmail_mailbox_base'].'/.'.$configfile, $content);
571

572 573 574 575 576
		//* Create the directory for the custom mailfilters
		if(!is_dir($cf['vmail_mailbox_base'].'/mailfilters')) {
			$command = 'mkdir '.$cf['vmail_mailbox_base'].'/mailfilters';
			caselog($command." &> /dev/null", __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
		}
577

578 579 580
		//* Chmod and chown the .mailfilter file
		$command = 'chown -R '.$cf['vmail_username'].':'.$cf['vmail_groupname'].' '.$cf['vmail_mailbox_base'].'/.mailfilter';
		caselog($command." &> /dev/null", __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
581

582 583
		$command = 'chmod -R 600 '.$cf['vmail_mailbox_base'].'/.mailfilter';
		caselog($command." &> /dev/null", __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
584

585
	}
586

587 588
	public function configure_saslauthd() {
		global $conf;
589 590


591 592 593 594 595 596 597 598 599
		$configfile = 'sasl_smtpd.conf';
		if(is_file($conf["postfix"]["config_dir"].'/sasl/smtpd.conf')) copy($conf["postfix"]["config_dir"].'/sasl/smtpd.conf',$conf["postfix"]["config_dir"].'/sasl/smtpd.conf~');
		if(is_file($conf["postfix"]["config_dir"].'/sasl/smtpd.conf~')) exec('chmod 400 '.$conf["postfix"]["config_dir"].'/sasl/smtpd.conf~');
		$content = rf("tpl/".$configfile.".master");
		$content = str_replace('{mysql_server_ispconfig_user}',$conf['mysql']['ispconfig_user'],$content);
		$content = str_replace('{mysql_server_ispconfig_password}',$conf['mysql']['ispconfig_password'], $content);
		$content = str_replace('{mysql_server_database}',$conf['mysql']['database'],$content);
		$content = str_replace('{mysql_server_ip}',$conf['mysql']['ip'],$content);
		wf($conf["postfix"]["config_dir"].'/sasl/smtpd.conf',$content);
600

601
		// TODO: Chmod and chown on the config file
602 603 604



605 606
		// Create the spool directory
		exec('mkdir -p /var/spool/postfix/var/run/saslauthd');
607

608 609 610 611 612 613 614 615 616 617 618
		// Edit the file /etc/default/saslauthd
		$configfile = $conf["saslauthd"]["config"];
		if(is_file($configfile)) copy($configfile,$configfile.'~');
		if(is_file($configfile.'~')) exec('chmod 400 '.$configfile.'~');
		$content = rf($configfile);
		$content = str_replace('START=no','START=yes',$content);
		// Debian
		$content = str_replace('OPTIONS="-c"','OPTIONS="-m /var/spool/postfix/var/run/saslauthd -r"',$content);
		// Ubuntu
		$content = str_replace('OPTIONS="-c -m /var/run/saslauthd"','OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd -r"',$content);
		wf($configfile,$content);
619

620 621 622 623 624
		// Edit the file /etc/init.d/saslauthd
		$configfile = $conf["init_scripts"].'/'.$conf["saslauthd"]["init_script"];
		$content = rf($configfile);
		$content = str_replace('PIDFILE=$RUN_DIR/saslauthd.pid','PIDFILE="/var/spool/postfix/var/run/${NAME}/saslauthd.pid"',$content);
		wf($configfile,$content);
625

626 627
		// add the postfix user to the sasl group (at least nescessary for ubuntu 8.04 and most likely debian lenny too.
		exec('adduser postfix sasl');
628 629


630
	}
631 632

	public function configure_pam() {
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
		global $conf;
		$pam = $conf['pam'];
		//* configure pam for SMTP authentication agains the ispconfig database
		$configfile = 'pamd_smtp';
		if(is_file("$pam/smtp"))    copy("$pam/smtp", "$pam/smtp~");
		if(is_file("$pam/smtp~"))   exec("chmod 400 $pam/smtp~");

		$content = rf("tpl/$configfile.master");
		$content = str_replace('{mysql_server_ispconfig_user}', $conf['mysql']['ispconfig_user'], $content);
		$content = str_replace('{mysql_server_ispconfig_password}', $conf['mysql']['ispconfig_password'], $content);
		$content = str_replace('{mysql_server_database}', $conf['mysql']['database'], $content);
		$content = str_replace('{mysql_server_ip}', $conf['mysql']['ip'], $content);
		wf("$pam/smtp", $content);
		exec("chmod 660 $pam/smtp");
		exec("chown daemon:daemon $pam/smtp");
648

649
	}
650 651

	public function configure_courier() {
652 653 654 655
		global $conf;
		$config_dir = $conf['courier']['config_dir'];
		//* authmysqlrc
		$configfile = 'authmysqlrc';
656 657 658
		if(is_file("$config_dir/$configfile")) {
			copy("$config_dir/$configfile", "$config_dir/$configfile~");
		}
659 660 661 662 663 664 665
		exec("chmod 400 $config_dir/$configfile~");
		$content = rf("tpl/$configfile.master");
		$content = str_replace('{mysql_server_ispconfig_user}',$conf['mysql']['ispconfig_user'],$content);
		$content = str_replace('{mysql_server_ispconfig_password}',$conf['mysql']['ispconfig_password'], $content);
		$content = str_replace('{mysql_server_database}',$conf['mysql']['database'],$content);
		$content = str_replace('{mysql_server_host}',$conf['mysql']['host'],$content);
		wf("$config_dir/$configfile", $content);
666

667 668
		exec("chmod 660 $config_dir/$configfile");
		exec("chown daemon:daemon $config_dir/$configfile");
669

670 671
		//* authdaemonrc
		$configfile = $conf['courier']['config_dir'].'/authdaemonrc';
672 673 674 675 676 677
		if(is_file($configfile)) {
			copy($configfile, $configfile.'~');
		}
		if(is_file($configfile.'~')) {
			exec('chmod 400 '.$configfile.'~');
		}
678 679 680 681
		$content = rf($configfile);
		$content = str_replace('authmodulelist="authpam"', 'authmodulelist="authmysql"', $content);
		wf($configfile, $content);
	}
682 683

	public function configure_dovecot() {
684
		global $conf;
685

686
		$config_dir = $conf['dovecot']['config_dir'];
687

688
		//* Configure master.cf and add a line for deliver
689 690 691 692 693 694
		if(is_file($config_dir.'/master.cf')) {
			copy($config_dir.'/master.cf', $config_dir.'/master.cf~2');
		}
		if(is_file($config_dir.'/master.cf~')) {
			exec('chmod 400 '.$config_dir.'/master.cf~2');
		}
695 696 697
		$content = rf($conf["postfix"]["config_dir"].'/master.cf');
		// Only add the content if we had not addded it before
		if(!stristr($content,"dovecot/deliver")) {
698
			$deliver_content = 'dovecot   unix  -       n       n       -       -       pipe'."\n".'  flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${user}@${nexthop}';
699 700 701 702
			af($conf["postfix"]["config_dir"].'/master.cf',$deliver_content);
		}
		unset($content);
		unset($deliver_content);
703 704


705 706 707
		//* Reconfigure postfix to use dovecot authentication
		// Adding the amavisd commands to the postfix configuration
		$postconf_commands = array (
708 709 710 711
				'dovecot_destination_recipient_limit = 1',
				'virtual_transport = dovecot',
				'smtpd_sasl_type = dovecot',
				'smtpd_sasl_path = private/auth'
712
		);
713

714 715
		// Make a backup copy of the main.cf file
		copy($conf["postfix"]["config_dir"].'/main.cf',$conf["postfix"]["config_dir"].'/main.cf~3');
716

717 718 719 720 721
		// Executing the postconf commands
		foreach($postconf_commands as $cmd) {
			$command = "postconf -e '$cmd'";
			caselog($command." &> /dev/null", __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
		}
722

723 724
		//* copy dovecot.conf
		$configfile = 'dovecot.conf';
725 726 727
		if(is_file("$config_dir/$configfile")) {
			copy("$config_dir/$configfile", "$config_dir/$configfile~");
		}
728
		copy('tpl/debian_dovecot.conf.master',"$config_dir/$configfile");
729

730 731
		//* dovecot-sql.conf
		$configfile = 'dovecot-sql.conf';
732 733 734
		if(is_file("$config_dir/$configfile")) {
			copy("$config_dir/$configfile", "$config_dir/$configfile~");
		}
735 736 737 738 739 740 741
		exec("chmod 400 $config_dir/$configfile~");
		$content = rf("tpl/debian_dovecot-sql.conf.master");
		$content = str_replace('{mysql_server_ispconfig_user}',$conf['mysql']['ispconfig_user'],$content);
		$content = str_replace('{mysql_server_ispconfig_password}',$conf['mysql']['ispconfig_password'], $content);
		$content = str_replace('{mysql_server_database}',$conf['mysql']['database'],$content);
		$content = str_replace('{mysql_server_host}',$conf['mysql']['host'],$content);
		wf("$config_dir/$configfile", $content);
742

743 744 745 746
		exec("chmod 600 $config_dir/$configfile");
		exec("chown root:root $config_dir/$configfile");

	}
747

748 749
	public function configure_amavis() {
		global $conf;
750

751 752
		// amavisd user config file
		$configfile = 'amavisd_user_config';
tbrehm's avatar
tbrehm committed
753
		if(is_file($conf["amavis"]["config_dir"].'/conf.d/50-user')) copy($conf["amavis"]["config_dir"].'/conf.d/50-user',$conf["amavis"]["config_dir"].'/50-user~');
754 755 756 757 758 759 760 761
		if(is_file($conf["amavis"]["config_dir"].'/conf.d/50-user~')) exec('chmod 400 '.$conf["amavis"]["config_dir"].'/conf.d/50-user~');
		$content = rf("tpl/".$configfile.".master");
		$content = str_replace('{mysql_server_ispconfig_user}',$conf['mysql']['ispconfig_user'],$content);
		$content = str_replace('{mysql_server_ispconfig_password}',$conf['mysql']['ispconfig_password'], $content);
		$content = str_replace('{mysql_server_database}',$conf['mysql']['database'],$content);
		$content = str_replace('{mysql_server_port}',$conf["mysql"]["port"],$content);
		$content = str_replace('{mysql_server_ip}',$conf['mysql']['ip'],$content);
		wf($conf["amavis"]["config_dir"].'/conf.d/50-user',$content);
762

763
		// TODO: chmod and chown on the config file
764 765


766 767
		// Adding the amavisd commands to the postfix configuration
		$postconf_commands = array (
768 769
				'content_filter = amavis:[127.0.0.1]:10024',
				'receive_override_options = no_address_mappings'
770
		);
771

772 773
		// Make a backup copy of the main.cf file
		copy($conf["postfix"]["config_dir"].'/main.cf',$conf["postfix"]["config_dir"].'/main.cf~2');
774

775 776 777 778 779
		// Executing the postconf commands
		foreach($postconf_commands as $cmd) {
			$command = "postconf -e '$cmd'";
			caselog($command." &> /dev/null", __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
		}
780

781 782 783 784 785 786 787 788 789 790
		// Append the configuration for amavisd to the master.cf file
		if(is_file($conf["postfix"]["config_dir"].'/master.cf')) copy($conf["postfix"]["config_dir"].'/master.cf',$conf["postfix"]["config_dir"].'/master.cf~');
		$content = rf($conf["postfix"]["config_dir"].'/master.cf');
		// Only add the content if we had not addded it before
		if(!stristr($content,"127.0.0.1:10025")) {
			unset($content);
			$content = rf("tpl/master_cf_amavis.master");
			af($conf["postfix"]["config_dir"].'/master.cf',$content);
		}
		unset($content);
791

792 793
		// Add the clamav user to the amavis group
		exec('adduser clamav amavis');
794 795


796
	}
797 798

	public function configure_spamassassin() {
799
		global $conf;
800

801 802
		//* Enable spamasasssin on debian and ubuntu
		$configfile = '/etc/default/spamassassin';
803 804 805
		if(is_file($configfile)) {
			copy($configfile, $configfile.'~');
		}
806 807 808 809
		$content = rf($configfile);
		$content = str_replace('ENABLED=0', 'ENABLED=1', $content);
		wf($configfile, $content);
	}
810 811

	public function configure_getmail() {
812
		global $conf;
813

814
		$config_dir = $conf['getmail']['config_dir'];
815

816 817 818 819
		if(!is_dir($config_dir)) exec("mkdir -p ".escapeshellcmd($config_dir));

		$command = "useradd -d $config_dir getmail";
		if(!is_user('getmail')) caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
820

821 822
		$command = "chown -R getmail $config_dir";
		caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
823

824 825 826
		$command = "chmod -R 700 $config_dir";
		caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
	}
827 828 829


	public function configure_pureftpd() {
830
		global $conf;
831

832 833
		$config_dir = $conf['pureftpd']['config_dir'];

834
		//* configure pure-ftpd for MySQL authentication against the ispconfig database
835
		$configfile = 'db/mysql.conf';
836 837 838 839 840 841
		if(is_file("$config_dir/$configfile")) {
			copy("$config_dir/$configfile", "$config_dir/$configfile~");
		}
		if(is_file("$config_dir/$configfile~")) {
			exec("chmod 400 $config_dir/$configfile~");
		}
842 843 844 845 846 847 848 849 850 851 852 853 854
		$content = rf('tpl/pureftpd_mysql.conf.master');
		$content = str_replace('{mysql_server_ispconfig_user}', $conf["mysql"]["ispconfig_user"], $content);
		$content = str_replace('{mysql_server_ispconfig_password}', $conf["mysql"]["ispconfig_password"], $content);
		$content = str_replace('{mysql_server_database}', $conf["mysql"]["database"], $content);
		$content = str_replace('{mysql_server_ip}', $conf["mysql"]["ip"], $content);
		$content = str_replace('{server_id}', $conf["server_id"], $content);
		wf("$config_dir/$configfile", $content);
		exec("chmod 600 $config_dir/$configfile");
		exec("chown root:root $config_dir/$configfile");
		// **enable chrooting
		//exec('mkdir -p '.$config_dir.'/conf/ChrootEveryone');
		exec('echo "yes" > '.$config_dir.'/conf/ChrootEveryone');
		exec('echo "yes" > '.$config_dir.'/conf/BrokenClientsCompatibility');
855
		exec('echo "yes" > '.$config_dir.'/conf/DisplayDotFiles');
856

857 858 859 860
		if(is_file('/etc/default/pure-ftpd-common')) {
			replaceLine('/etc/default/pure-ftpd-common','STANDALONE_OR_INETD=inetd','STANDALONE_OR_INETD=standalone',1,0);
			replaceLine('/etc/default/pure-ftpd-common','VIRTUALCHROOT=false','VIRTUALCHROOT=true',1,0);
		}
861

862
		if(is_file('/etc/inetd.conf')) {
tbrehm's avatar
tbrehm committed
863
			replaceLine('/etc/inetd.conf','/usr/sbin/pure-ftpd-wrapper','#ftp     stream  tcp     nowait  root    /usr/sbin/tcpd /usr/sbin/pure-ftpd-wrapper',0,0);