gentoo.lib.php 58.6 KB
Newer Older
1 2 3 4 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
<?php

/*
Copyright (c) 2007, Till Brehm, projektfarm Gmbh
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.
*/

31
class installer extends installer_base
32 33
{
	public function configure_jailkit()
34 35 36
	{
		global $conf;

37 38
		if (is_dir($conf['jailkit']['config_dir']))
		{
wyrie's avatar
wyrie committed
39
			$jkinit_content = $this->get_template_file($conf['jailkit']['jk_init'], true); //* get contents
40
			$this->write_config_file($conf['jailkit']['config_dir'] . '/' . $conf['jailkit']['jk_init'], $jkinit_content);
41

wyrie's avatar
wyrie committed
42
			$jkchroot_content = $this->get_template_file($conf['jailkit']['jk_chrootsh'], true); //* get contents
43 44
			$this->write_config_file($conf['jailkit']['config_dir'] . '/' . $conf['jailkit']['jk_chrootsh'], $jkchroot_content);
		}
45

wyrie's avatar
wyrie committed
46 47
		$command = 'chown root:root /var/www';
		caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
48 49
	}

50
	public function configure_postfix($options = '')
51
	{
52
		global $conf,$autoinstall;
53 54

		$cf = $conf['postfix'];
55
		$config_dir = $cf['config_dir'];
56

57
		if(!is_dir($config_dir)){
58 59 60 61 62 63 64 65
			$this->error("The postfix configuration directory '$config_dir' does not exist.");
		}

		//* Install virtual mappings
		foreach (glob('tpl/mysql-virtual_*.master') as $filename) {
			$this->process_postfix_config( basename($filename, '.master') );
		}

66 67 68
		//* mysql-verify_recipients.cf
		$this->process_postfix_config('mysql-verify_recipients.cf');

wyrie's avatar
wyrie committed
69
		//* Changing mode and group of the new created config files.
70
		caselog('chmod o= '.$config_dir.'/mysql-virtual_*.cf* &> /dev/null',
71 72 73 74
			__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');

wyrie's avatar
wyrie committed
75
		//* Creating virtual mail user and group
76 77 78 79
		$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");
		}
80

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

86
		//* These postconf commands will be executed on installation and update
Dominik's avatar
Dominik committed
87
		$server_ini_rec = $this->db->queryOneRecord("SELECT config FROM ?? WHERE server_id = ?", $conf["mysql"]["database"].'.server', $conf['server_id']);
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
		$server_ini_array = ini_to_array(stripslashes($server_ini_rec['config']));
		unset($server_ini_rec);

		//* If there are RBL's defined, format the list and add them to smtp_recipient_restrictions to prevent removeal after an update
		$rbl_list = '';
		if (@isset($server_ini_array['mail']['realtime_blackhole_list']) && $server_ini_array['mail']['realtime_blackhole_list'] != '') {
			$rbl_hosts = explode(",", str_replace(" ", "", $server_ini_array['mail']['realtime_blackhole_list']));
			foreach ($rbl_hosts as $key => $value) {
				$rbl_list .= ", reject_rbl_client ". $value;
			}
		}
		unset($rbl_hosts);

		//* If Postgrey is installed, configure it
		$greylisting = '';
		if($conf['postgrey']['installed'] == true) {
			$greylisting = ', check_recipient_access mysql:/etc/postfix/mysql-virtual_policy_greylist.cf';
		}
106

107
		$reject_sender_login_mismatch = '';
108
		$reject_authenticated_sender_login_mismatch = '';
109
		if(isset($server_ini_array['mail']['reject_sender_login_mismatch']) && ($server_ini_array['mail']['reject_sender_login_mismatch'] == 'y')) {
110
			$reject_sender_login_mismatch = ', reject_sender_login_mismatch';
111
			$reject_authenticated_sender_login_mismatch = 'reject_authenticated_sender_login_mismatch, ';
112
		}
113 114 115 116 117

		# placeholder includes comment char
		$stress_adaptive_placeholder = '#{stress_adaptive} ';
		$stress_adaptive = (isset($server_ini_array['mail']['stress_adaptive']) && ($server_ini_array['mail']['stress_adaptive'] == 'y')) ? '' : $stress_adaptive_placeholder;

118 119 120 121 122 123 124 125 126
		$reject_unknown_client_hostname='';
		if (isset($server_ini_array['mail']['reject_unknown']) && ($server_ini_array['mail']['reject_unknown'] == 'client' || $server_ini_array['mail']['reject_unknown'] == 'client_helo')) {
			$reject_unknown_client_hostname=',reject_unknown_client_hostname';
		}
		$reject_unknown_helo_hostname='';
		if ((!isset($server_ini_array['mail']['reject_unknown'])) || $server_ini_array['mail']['reject_unknown'] == 'helo' || $server_ini_array['mail']['reject_unknown'] == 'client_helo') {
			$reject_unknown_helo_hostname=',reject_unknown_helo_hostname';
		}

127
		unset($server_ini_array);
128

129 130
		$myhostname = str_replace('.','\.',$conf['hostname']);

131 132 133 134
		$postconf_placeholders = array('{config_dir}' => $config_dir,
			'{vmail_mailbox_base}' => $cf['vmail_mailbox_base'],
			'{vmail_userid}' => $cf['vmail_userid'],
			'{vmail_groupid}' => $cf['vmail_groupid'],
135 136 137
			'{rbl_list}' => $rbl_list,
			'{greylisting}' => $greylisting,
			'{reject_slm}' => $reject_sender_login_mismatch,
138
			'{reject_aslm}' => $reject_authenticated_sender_login_mismatch,
139
			'{myhostname}' => $myhostname,
140
			$stress_adaptive_placeholder => $stress_adaptive,
141 142
			'{reject_unknown_client_hostname}' => $reject_unknown_client_hostname,
			'{reject_unknown_helo_hostname}' => $reject_unknown_helo_hostname,
143
		);
144 145 146 147 148

		$postconf_tpl = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/gentoo_postfix.conf.master', 'tpl/gentoo_postfix.conf.master');
		$postconf_tpl = strtr($postconf_tpl, $postconf_placeholders);
		$postconf_commands = array_filter(explode("\n", $postconf_tpl)); // read and remove empty lines

149 150
		//* These postconf commands will be executed on installation only
		if($this->is_update == false) {
151 152 153 154 155
			$postconf_commands = array_merge($postconf_commands, array(
					'myhostname = '.$conf['hostname'],
					'mydestination = '.$conf['hostname'].', localhost, localhost.localdomain',
					'mynetworks = 127.0.0.0/8 [::1]/128'
				));
156
		}
157

wyrie's avatar
wyrie committed
158
		//* Create the header and body check files
159 160 161 162
		touch($config_dir.'/header_checks');
		touch($config_dir.'/mime_header_checks');
		touch($config_dir.'/nested_header_checks');
		touch($config_dir.'/body_checks');
163
		touch($config_dir.'/sasl_passwd');
164

165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
		//* Create auxillary postfix conf files
		$configfile = 'helo_access';
		if(is_file($config_dir.'/'.$configfile)) {
			copy($config_dir.'/'.$configfile, $config_dir.'/'.$configfile.'~');
			chmod($config_dir.'/'.$configfile.'~', 0400);
		}
		$content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/'.$configfile.'.master', 'tpl/'.$configfile.'.master');
		$content = strtr($content, $postconf_placeholders);
		# todo: look up this server's ip addrs and loop through each
		# todo: look up domains hosted on this server and loop through each
		wf($config_dir.'/'.$configfile, $content);

		$configfile = 'blacklist_helo';
		if(is_file($config_dir.'/'.$configfile)) {
			copy($config_dir.'/'.$configfile, $config_dir.'/'.$configfile.'~');
			chmod($config_dir.'/'.$configfile.'~', 0400);
		}
		$content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/'.$configfile.'.master', 'tpl/'.$configfile.'.master');
		$content = strtr($content, $postconf_placeholders);
		wf($config_dir.'/'.$configfile, $content);
185

wyrie's avatar
wyrie committed
186
		//* Make a backup copy of the main.cf file
187
		copy($config_dir.'/main.cf', $config_dir.'/main.cf~');
188

wyrie's avatar
wyrie committed
189
		//* Executing the postconf commands
190 191
		foreach($postconf_commands as $cmd) {
			$command = "postconf -e '$cmd'";
wyrie's avatar
wyrie committed
192
			caselog($command.' &> /dev/null', __FILE__, __LINE__, 'EXECUTED: '.$command, 'Failed to execute the command '.$command);
193
		}
194

wyrie's avatar
wyrie committed
195
		//* Create the SSL certificate
196
		if (!stristr($options, 'dont-create-certs'))
197
		{
Till Brehm's avatar
Till Brehm committed
198 199
			if(AUTOINSTALL){
				$command = 'cd '.$config_dir.'; '
200
					."openssl req -new -subj '/C=".escapeshellcmd($autoinstall['ssl_cert_country'])."/ST=".escapeshellcmd($autoinstall['ssl_cert_state'])."/L=".escapeshellcmd($autoinstall['ssl_cert_locality'])."/O=".escapeshellcmd($autoinstall['ssl_cert_organisation'])."/OU=".escapeshellcmd($autoinstall['ssl_cert_organisation_unit'])."/CN=".escapeshellcmd($autoinstall['ssl_cert_common_name'])."' -outform PEM -out smtpd.cert -newkey rsa:4096 -nodes -keyout smtpd.key -keyform PEM -days 3650 -x509";
Till Brehm's avatar
Till Brehm committed
201 202
			} else {
				$command = 'cd '.$config_dir.'; '
203
					.'openssl req -new -outform PEM -out smtpd.cert -newkey rsa:4096 -nodes -keyout smtpd.key -keyform PEM -days 3650 -x509';
Till Brehm's avatar
Till Brehm committed
204
			}
205
			exec($command);
206

207 208 209
			$command = 'chmod o= '.$config_dir.'/smtpd.key';
			caselog($command.' &> /dev/null', __FILE__, __LINE__, 'EXECUTED: '.$command, 'Failed to execute the command '.$command);
		}
210

wyrie's avatar
wyrie committed
211 212 213 214 215
		//* We have to change the permissions of the courier authdaemon directory to make it accessible for maildrop.
		$command = 'chmod 755  /var/lib/courier/authdaemon/';
		if (is_dir('/var/lib/courier/authdaemon')) {
			caselog($command.' &> /dev/null', __FILE__, __LINE__, 'EXECUTED: '.$command, 'Failed to execute the command '.$command);
		}
216

wyrie's avatar
wyrie committed
217
		//* Changing maildrop lines in posfix master.cf
218 219 220
		$configfile = $config_dir.'/master.cf';
		$content = rf($configfile);

221 222 223 224 225
		$content = preg_replace('/^#?maildrop/m', 'maildrop', $content);
		$content = preg_replace('/^#?(\s+)flags=DRhu user=vmail argv=\/usr\/bin\/maildrop -d/m',
			'$1flags=DRhu user=vmail argv=/usr/bin/maildrop -d vmail \${extension} \${recipient} \${user} \${nexthop} \${sender}',
			$content);

226
		$this->write_config_file($configfile, $content);
227

wyrie's avatar
wyrie committed
228
		//* Writing the Maildrop mailfilter file
229
		$content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/mailfilter.master', 'tpl/mailfilter.master');
230
		$content = str_replace('{dist_postfix_vmail_mailbox_base}', $cf['vmail_mailbox_base'], $content);
231

232
		$this->write_config_file($cf['vmail_mailbox_base'].'/.mailfilter', $content);
233

wyrie's avatar
wyrie committed
234
		//* Create the directory for the custom mailfilters
235
		if (!is_dir($cf['vmail_mailbox_base'].'/mailfilters'))
236 237
		{
			$command = 'mkdir '.$cf['vmail_mailbox_base'].'/mailfilters';
wyrie's avatar
wyrie committed
238
			caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
239
		}
240 241

		//* postfix-dkim
242 243 244 245 246 247 248 249 250 251 252
		$filename='tag_as_originating.re';
		$full_file_name=$config_dir.'/'.$filename;
		if(is_file($full_file_name)) copy($full_file_name, $full_file_name.'~');
		$content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/postfix-'.$filename.'.master', 'tpl/postfix-'.$filename.'.master');
		wf($full_file_name, $content);

		$filename='tag_as_foreign.re';
		$full_file_name=$config_dir.'/'.$filename;
		if(is_file($full_file_name)) copy($full_file_name, $full_file_name.'~');
		$content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/postfix-'.$filename.'.master', 'tpl/postfix-'.$filename.'.master');
		wf($full_file_name, $content);
253

wyrie's avatar
wyrie committed
254
		//* Chmod and chown the .mailfilter file
255 256
		$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");
257

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

261
	}
262 263

	public function configure_saslauthd()
264 265
	{
		global $conf;
266

wyrie's avatar
wyrie committed
267
		$content = $this->get_template_file('sasl_smtpd.conf', true, true); //* get contents & insert db cred
268
		$this->write_config_file($conf['saslauthd']['config_dir'].'/smtpd.conf', $content);
269

wyrie's avatar
wyrie committed
270 271
		//* Edit the file saslauthd config file
		$content = rf($conf['saslauthd']['config_file']);
272
		$content = preg_replace('/(?<=\n)SASLAUTHD_OPTS="\$\{SASLAUTHD_OPTS\}[^"]+"/', 'SASLAUTHD_OPTS="${SASLAUTHD_OPTS} -a pam -r -c -s 128 -t 30 -n 5"', $content);
273

wyrie's avatar
wyrie committed
274
		$this->write_config_file($conf['saslauthd']['config_file'], $content);
275
	}
276

277
	public function configure_courier()
278 279 280
	{
		global $conf;

wyrie's avatar
wyrie committed
281 282
		//* authmysqlrc
		$content = $this->get_template_file('authmysqlrc', true, true); //* get contents & insert db cred
283
		$this->write_config_file($conf['courier']['config_dir'].'/authmysqlrc', $content);
284

wyrie's avatar
wyrie committed
285
		//* authdaemonrc
286 287 288 289 290
		$configfile = $conf['courier']['config_dir'].'/authdaemonrc';

		$content = rf($configfile);
		$content = preg_replace('/(?<=\n)authmodulelist="[^"]+"/', "authmodulelist=\"authmysql\"", $content);
		$this->write_config_file($configfile, $content);
291

wyrie's avatar
wyrie committed
292 293 294
		//* create certificates
		$command = 'mkimapdcert';
		caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
295

wyrie's avatar
wyrie committed
296
		$command = 'mkpop3dcert';
297
		caselog($command." &> /dev/null", __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
298 299 300 301 302 303
	}

	public function configure_dovecot()
	{
		global $conf;

Dominik Müller's avatar
Dominik Müller committed
304
		$virtual_transport = 'dovecot';
305 306

		$configure_lmtp = false;
307

Dominik Müller's avatar
Dominik Müller committed
308 309
		// check if virtual_transport must be changed
		if ($this->is_update) {
310
			$tmp = $this->db->queryOneRecord("SELECT * FROM ?? WHERE server_id = ?", $conf["mysql"]["database"].".server", $conf['server_id']);
Dominik Müller's avatar
Dominik Müller committed
311 312
			$ini_array = ini_to_array(stripslashes($tmp['config']));
			// ini_array needs not to be checked, because already done in update.php -> updateDbAndIni()
313

Dominik Müller's avatar
Dominik Müller committed
314 315
			if(isset($ini_array['mail']['mailbox_virtual_uidgid_maps']) && $ini_array['mail']['mailbox_virtual_uidgid_maps'] == 'y') {
				$virtual_transport = 'lmtp:unix:private/dovecot-lmtp';
316
				$configure_lmtp = true;
Dominik Müller's avatar
Dominik Müller committed
317 318 319
			}
		}

320
		$config_dir = $conf['postfix']['config_dir'];
321

322
		//* Configure master.cf and add a line for deliver
323
		if(!$this->get_postfix_service('dovecot', 'unix')) {
324 325 326 327 328 329 330 331 332
			//* backup
			if(is_file($config_dir.'/master.cf')){
				copy($config_dir.'/master.cf', $config_dir.'/master.cf~2');
			}
			if(is_file($config_dir.'/master.cf~')){
				chmod($config_dir.'/master.cf~2', 0400);
			}
			//* Configure master.cf and add a line for deliver
			$content = rf($conf["postfix"]["config_dir"].'/master.cf');
333
			$deliver_content = 'dovecot   unix  -       n       n       -       -       pipe'."\n".'  flags=DROhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${user}@${nexthop}'."\n";
334
			af($config_dir.'/master.cf', $deliver_content);
335 336
			unset($content);
			unset($deliver_content);
wyrie's avatar
wyrie committed
337
		}
338

wyrie's avatar
wyrie committed
339 340
		//* Reconfigure postfix to use dovecot authentication
		$postconf_commands = array (
341
			'dovecot_destination_recipient_limit = 1',
Dominik Müller's avatar
Dominik Müller committed
342
			'virtual_transport = '.$virtual_transport,
343 344
			'smtpd_sasl_type = dovecot',
			'smtpd_sasl_path = private/auth'
wyrie's avatar
wyrie committed
345
		);
346

wyrie's avatar
wyrie committed
347
		//* Make a backup copy of the main.cf file
348 349 350 351
		copy($conf['postfix']['config_dir'].'/main.cf', $conf['postfix']['config_dir'].'/main.cf~3');

		//* Executing the postconf commands
		foreach($postconf_commands as $cmd)
wyrie's avatar
wyrie committed
352 353 354 355
		{
			$command = "postconf -e '$cmd'";
			caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
		}
356

357
		$config_dir = $conf['dovecot']['config_dir'];
wyrie's avatar
wyrie committed
358 359 360 361
		//* copy dovecot.conf
		$configfile = $config_dir.'/dovecot.conf';
		$content = $this->get_template_file('dovecot.conf', true);
		$this->write_config_file($configfile, $content);
362

363 364 365 366 367
		//* dovecot-lmtpd
		if($configure_lmtp) {
			replaceLine($config_dir.'/'.$configfile, 'protocols = imap pop3', 'protocols = imap pop3 lmtp', 1, 0);
		}

368 369 370 371 372
		//* Get the dovecot version
		exec('dovecot --version', $tmp);
		$dovecot_version = $tmp[0];
		unset($tmp);

wyrie's avatar
wyrie committed
373 374 375
		//* dovecot-sql.conf
		$configfile = $config_dir.'/dovecot-sql.conf';
		$content = $this->get_template_file('debian_dovecot-sql.conf', true, true);
Till Brehm's avatar
Till Brehm committed
376
		# enable iterate_query for dovecot2
377 378 379
		if(version_compare($dovecot_version,2, '>=')) {
			$content = str_replace('# iterate_query', 'iterate_query', $content);
		}
380
		$content = str_replace('{server_id}', $conf['server_id'], $content);
wyrie's avatar
wyrie committed
381
		$this->write_config_file($configfile, $content);
382 383
	}

384
	public function configure_spamassassin()
385
	{
386
		return true;
387 388
	}

389
	public function configure_getmail()
390
	{
391
		global $conf;
392

393
		$config_dir = $conf['getmail']['config_dir'];
394

395
		if (!is_dir($config_dir)) {
wyrie's avatar
wyrie committed
396
			exec('mkdir -p '.escapeshellcmd($config_dir));
397 398 399 400 401 402
		}

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

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

407 408
		$command = "chmod -R 700 $config_dir";
		caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
409

wyrie's avatar
wyrie committed
410
		//* Getmail will be run from cron. In order to have access to cron the getmail user needs to be part of the cron group.
411 412 413
		$command = "gpasswd -a getmail " . $conf['cron']['group'];
		caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
	}
414 415 416

	public function configure_amavis()
	{
417
		global $conf;
418

wyrie's avatar
wyrie committed
419
		//* Amavisd-new user config file
420 421
		$conf_file = 'amavisd-ispconfig.conf';
		$conf_path = dirname($conf['amavis']['config_file']) . '/' . $conf_file;
422

wyrie's avatar
wyrie committed
423
		$content = $this->get_template_file($conf_file, true, true); //* get contents & insert db cred
424
		$this->write_config_file($conf_path, $content);
425

wyrie's avatar
wyrie committed
426
		//* Activate config directory in default file
427
		$amavis_conf = rf($conf['amavis']['config_file']);
428
		if (stripos($amavis_conf, $conf_path) === false)
429
		{
wyrie's avatar
wyrie committed
430
			$amavis_conf = preg_replace('/^(1;.*)$/m', "include_config_files('$conf_path');\n$1", $amavis_conf);
431 432
			$this->write_config_file($conf['amavis']['config_file'], $amavis_conf);
		}
433

wyrie's avatar
wyrie committed
434
		//* Adding the amavisd commands to the postfix configuration
435 436 437 438
		$postconf_commands = array (
			'content_filter = amavis:[127.0.0.1]:10024',
			'receive_override_options = no_address_mappings'
		);
439 440

		foreach($postconf_commands as $cmd) {
441
			$command = "postconf -e '$cmd'";
wyrie's avatar
wyrie committed
442
			caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
443
		}
444

445 446 447
		$config_dir = $conf['postfix']['config_dir'];

		// Adding amavis-services to the master.cf file if the service does not already exists
448 449 450
		$add_amavis = !$this->get_postfix_service('amavis','unix');
		$add_amavis_10025 = !$this->get_postfix_service('127.0.0.1:10025','inet');
		$add_amavis_10027 = !$this->get_postfix_service('127.0.0.1:10027','inet');
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470

		if ($add_amavis || $add_amavis_10025 || $add_amavis_10027) {
			//* backup master.cf
			if(is_file($config_dir.'/master.cf')) copy($config_dir.'/master.cf', $config_dir.'/master.cf~');
			// adjust amavis-config
			if($add_amavis) {
				$content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/master_cf_amavis.master', 'tpl/master_cf_amavis.master');
				af($config_dir.'/master.cf', $content);
				unset($content);
			}
			if ($add_amavis_10025) {
				$content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/master_cf_amavis10025.master', 'tpl/master_cf_amavis10025.master');
				af($config_dir.'/master.cf', $content);
				unset($content);
			}
			if ($add_amavis_10027) {
				$content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/master_cf_amavis10027.master', 'tpl/master_cf_amavis10027.master');
				af($config_dir.'/master.cf', $content);
				unset($content);
			}
471
		}
472

wyrie's avatar
wyrie committed
473
		//* Add the clamav user to the amavis group
474
		exec('usermod -a -G amavis clamav');
475 476 477 478
	}

	public function configure_pureftpd()
	{
479
		global $conf;
480

481
		//* configure pure-ftpd for MySQL authentication against the ispconfig database
wyrie's avatar
wyrie committed
482 483
		$content = $this->get_template_file('pureftpd_mysql.conf', true, true); //* get contents & insert db cred
		$content = str_replace('{server_id}', $conf['server_id'], $content);
484

485
		$this->write_config_file($conf['pureftpd']['mysql_config_file'], $content, 600, 'root', 'root');
486

wyrie's avatar
wyrie committed
487
		//* enable pure-ftpd and server settings
488
		$content = rf($conf["pureftpd"]["config_file"]);
489

490 491
		$content = preg_replace('/#?IS_CONFIGURED="(?:yes|no)"/', 'IS_CONFIGURED="yes"', $content);
		$content = str_replace('AUTH="-l unix"', 'AUTH="-l mysql:'.$conf['pureftpd']['mysql_config_file'].'"', $content);
492

wyrie's avatar
wyrie committed
493 494
		//* Logging defaults to syslog's ftp facility. Override this behaviour for better compatibility with debian/ubuntu
		//* and specify the format.
495 496 497 498
		$logdir = '/var/log/pure-ftpd';
		if (!is_dir($logdir)) {
			mkdir($logdir, 0755, true);
		}
499

wyrie's avatar
wyrie committed
500
		/**
501 502 503 504 505 506
		 * @link http://download.pureftpd.org/pub/pure-ftpd/doc/README
		 * -b brokenclientscompatibility
		 * -A chrooteveryone
		 * -E noanonymous
		 * -O altlog <format>:<log file>
		 * -Z customerproof (Add safe guards against common customer mistakes ie. like chmod 0 on their own files)
507
		 * -D displaydotfiles
wyrie's avatar
wyrie committed
508
		 * -H dontresolve
509
		 */
510 511


wyrie's avatar
wyrie committed
512
		$content = preg_replace('/MISC_OTHER="[^"]+"/', 'MISC_OTHER="-b -A -E -Z -D -H -O clf:'.$logdir.'/transfer.log"', $content);
513

wyrie's avatar
wyrie committed
514
		$this->write_config_file($conf['pureftpd']['config_file'], $content);
515 516 517
	}

	public function configure_powerdns()
518 519
	{
		global $conf;
520

521
		//* Create the database
522
		if(!$this->db->query('CREATE DATABASE IF NOT EXISTS ?? DEFAULT CHARACTER SET ?', $conf['powerdns']['database'], $conf['mysql']['charset'])) {
523 524
			$this->error('Unable to create MySQL database: '.$conf['powerdns']['database'].'.');
		}
525

526
		//* Create the ISPConfig database user in the local database
527 528
		$query = 'GRANT ALL ON ??.* TO ?@?';
		if(!$this->db->query($query, $conf['powerdns']['database'], $conf['mysql']['ispconfig_user'], 'localhost')) {
529 530
			$this->error('Unable to create user for powerdns database Error: '.$this->db->errorMessage);
		}
531

532 533
		//* load the powerdns databse dump
		if($conf['mysql']['admin_password'] == '') {
534 535
			caselog("mysql --default-character-set=".$conf['mysql']['charset']." -h '".$conf['mysql']['host']."' -u '".$conf['mysql']['admin_user']."' '".$conf['powerdns']['database']."' < '".ISPC_INSTALL_ROOT."/install/sql/powerdns.sql' &> /dev/null",
				__FILE__, __LINE__, 'read in ispconfig3.sql', 'could not read in powerdns.sql');
536
		} else {
537 538
			caselog("mysql --default-character-set=".$conf['mysql']['charset']." -h '".$conf['mysql']['host']."' -u '".$conf['mysql']['admin_user']."' -p'".$conf['mysql']['admin_password']."' '".$conf['powerdns']['database']."' < '".ISPC_INSTALL_ROOT."/install/sql/powerdns.sql' &> /dev/null",
				__FILE__, __LINE__, 'read in ispconfig3.sql', 'could not read in powerdns.sql');
539
		}
540

541
		//* Create the powerdns config file
wyrie's avatar
wyrie committed
542
		$content = $this->get_template_file('pdns.local', true, true); //* get contents & insert db cred
543
		$content = str_replace('{powerdns_database}', $conf['powerdns']['database'], $content);
544

545 546
		$this->write_config_file($conf["powerdns"]["config_dir"].'/'.$conf["powerdns"]["config_file"], $content, 600, 'root', 'root');

wyrie's avatar
wyrie committed
547
		//* Create symlink to init script to start the correct config file
548 549 550 551
		if( !is_link($conf['init_scripts'].'/'.$conf['powerdns']['init_script']) ) {
			symlink($conf['init_scripts'].'/pdns', $conf['init_scripts'].'/'.$conf['powerdns']['init_script']);
		}
	}
552

wyrie's avatar
wyrie committed
553 554 555
	public function configure_bind() {
		global $conf;

556 557 558 559
		//* Check if the zonefile directory has a slash at the end
		$content=$conf['bind']['bind_zonefiles_dir'];
		if(substr($content, -1, 1) != '/') {
			$content .= '/';
wyrie's avatar
wyrie committed
560
		}
561

wyrie's avatar
wyrie committed
562 563
		//* New default format of named.conf uses views. Check which version the system is using and include our zones file.
		$named_conf = rf($conf['bind']['named_conf_path']);
564
		if (stripos($named_conf, 'include "'.$conf['bind']['named_conf_local_path'].'";') === false)
wyrie's avatar
wyrie committed
565 566 567 568 569 570
		{
			preg_match_all("/(?<=\n)view \"(?:public|internal)\" in \{.*\n\};/Us", $named_conf, $views);
			if (count($views[0]) == 2) {
				foreach ($views[0] as $view) {
					$named_conf = str_replace($view, substr($view, 0, -2)."include \"{$conf['bind']['named_conf_local_path']}\";\n};", $named_conf);
				}
571

wyrie's avatar
wyrie committed
572 573 574 575 576 577 578
				wf($conf['bind']['named_conf_path'], $named_conf);
			}
			else {
				af($conf['bind']['named_conf_path'], 'include "'.$conf['bind']['named_conf_local_path'].'";');
			}
		}
	}
579

580
	public function configure_apache()
581
	{
582
		global $conf;
583

Falko Timme's avatar
Falko Timme committed
584
		if($conf['apache']['installed'] == false) return;
wyrie's avatar
wyrie committed
585 586 587
		//* Create the logging directory for the vhost logfiles
		if (!is_dir($conf['ispconfig_log_dir'].'/httpd')) {
			mkdir($conf['ispconfig_log_dir'].'/httpd', 0755, true);
588
		}
589 590

		if (is_file($conf['suphp']['config_file']))
591 592
		{
			$content = rf($conf['suphp']['config_file']);
593

wyrie's avatar
wyrie committed
594 595
			if (!preg_match('|^x-httpd-suphp=php:/usr/bin/php-cgi$|m', $content))
			{
596 597
				$content = preg_replace('/;Handler for php-scripts/', ";Handler for php-scripts\nx-httpd-suphp=php:/usr/bin/php-cgi", $content);
				$content = preg_replace('/;?umask=\d+/', 'umask=0022', $content);
wyrie's avatar
wyrie committed
598
			}
599

600 601
			$this->write_config_file($conf['suphp']['config_file'], $content);
		}
602

wyrie's avatar
wyrie committed
603
		//* Enable ISPConfig default vhost settings
604
		$default_vhost_path = $conf['apache']['vhost_conf_dir'].'/'.$conf['apache']['vhost_default'];
605
		if (is_file($default_vhost_path))
606 607
		{
			$content = rf($default_vhost_path);
608

609 610
			$content = preg_replace('/^#?\s*NameVirtualHost.*$/m', 'NameVirtualHost *:80', $content);
			$content = preg_replace('/<VirtualHost[^>]+>/', '<VirtualHost *:80>', $content);
611

612 613
			$this->write_config_file($default_vhost_path, $content);
		}
614

wyrie's avatar
wyrie committed
615
		//* Generate default ssl certificates
616 617 618
		if (!is_dir($conf['apache']['ssl_dir'])) {
			mkdir($conf['apache']['ssl_dir']);
		}
619 620

		if ($conf['services']['mail'] == true)
621 622 623 624 625 626 627 628 629 630
		{
			copy($conf['postfix']['config_dir']."/smtpd.key", $conf['apache']['ssl_dir']."/server.key");
			copy($conf['postfix']['config_dir']."/smtpd.cert", $conf['apache']['ssl_dir']."/server.crt");
		}
		else
		{
			if (!is_file($conf['apache']['ssl_dir'] . '/server.crt')) {
				exec("openssl req -new -outform PEM -out {$conf['apache']['ssl_dir']}/server.crt -newkey rsa:2048 -nodes -keyout {$conf['apache']['ssl_dir']}/server.key -keyform PEM -days 365 -x509");
			}
		}
631 632 633



wyrie's avatar
wyrie committed
634
		//* Copy the ISPConfig configuration include
635 636
		$tpl = new tpl('apache_ispconfig.conf.master');
		$tpl->setVar('apache_version',getapacheversion());
637

638 639 640 641 642
		if($this->is_update == true) {
			$tpl->setVar('logging',get_logging_state());
		} else {
			$tpl->setVar('logging','yes');
		}
643

644
		$records = $this->db->queryAllRecords("SELECT * FROM ?? WHERE server_id = ? AND virtualhost = 'y'", $conf['mysql']['master_database'] . '.server_ip', $conf['server_id']);
645
		$ip_addresses = array();
646

647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
		if(is_array($records) && count($records) > 0) {
			foreach($records as $rec) {
				if($rec['ip_type'] == 'IPv6') {
					$ip_address = '['.$rec['ip_address'].']';
				} else {
					$ip_address = $rec['ip_address'];
				}
				$ports = explode(',', $rec['virtualhost_port']);
				if(is_array($ports)) {
					foreach($ports as $port) {
						$port = intval($port);
						if($port > 0 && $port < 65536 && $ip_address != '') {
							$ip_addresses[] = array('ip_address' => $ip_address, 'port' => $port);
						}
					}
				}
			}
		}
665

Till Brehm's avatar
Till Brehm committed
666
		if(count($ip_addresses) > 0) $tpl->setLoop('ip_adresses',$ip_addresses);
667 668 669

		wf($conf['apache']['vhost_conf_dir'].'/000-ispconfig.conf', $tpl->grab());
		unset($tpl);
670

wyrie's avatar
wyrie committed
671
		//* Gentoo by default does not include .vhost files. Add include line to config file.
672 673
		$content = rf($conf['apache']['config_file']);
		if ( strpos($content, 'Include /etc/apache2/vhosts.d/*.vhost') === false ) {
674
			$content = preg_replace('|(Include /etc/apache2/vhosts.d/\*.conf)|', "$1\nInclude /etc/apache2/vhosts.d/*.vhost", $content);
675
		}
676

677
		$this->write_config_file($conf['apache']['config_file'], $content);
678

wyrie's avatar
wyrie committed
679
		//* make sure that webalizer finds its config file when it is directly in /etc
680
		if(is_file('/etc/webalizer.conf') && !is_dir('/etc/webalizer'))
681 682 683 684
		{
			mkdir('/etc/webalizer', 0755);
			symlink('/etc/webalizer.conf', '/etc/webalizer/webalizer.conf');
		}
685 686 687 688 689 690

		if(is_file('/etc/webalizer/webalizer.conf')) //* Change webalizer mode to incremental
			{
			replaceLine('/etc/webalizer/webalizer.conf', '#IncrementalName', 'IncrementalName webalizer.current', 0, 0);
			replaceLine('/etc/webalizer/webalizer.conf', '#Incremental', 'Incremental     yes', 0, 0);
			replaceLine('/etc/webalizer/webalizer.conf', '#HistoryName', 'HistoryName     webalizer.hist', 0, 0);
691
		}
692

wyrie's avatar
wyrie committed
693
		//* add a sshusers group
694
		if (!is_group('sshusers'))
695 696 697 698
		{
			$command = 'groupadd sshusers';
			caselog($command.' &> /dev/null 2> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
		}
699 700 701
	}

	public function configure_apps_vhost()
702 703
	{
		global $conf;
704

705
		//* Create the ispconfig apps vhost user and group
706
		if($conf['apache']['installed'] == true){
Falko Timme's avatar
Falko Timme committed
707 708 709
			$apps_vhost_user = escapeshellcmd($conf['web']['apps_vhost_user']);
			$apps_vhost_group = escapeshellcmd($conf['web']['apps_vhost_group']);
			$install_dir = escapeshellcmd($conf['web']['website_basedir'].'/apps');
710

Falko Timme's avatar
Falko Timme committed
711 712 713 714
			$command = 'groupadd '.$apps_vhost_user;
			if ( !is_group($apps_vhost_group) ) {
				caselog($command.' &> /dev/null 2> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
			}
715

Falko Timme's avatar
Falko Timme committed
716 717 718 719
			$command = "useradd -g '$apps_vhost_group' -d $install_dir $apps_vhost_group";
			if ( !is_user($apps_vhost_user) ) {
				caselog($command.' &> /dev/null 2> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
			}
720

Falko Timme's avatar
Falko Timme committed
721 722
			$command = 'adduser '.$conf['apache']['user'].' '.$apps_vhost_group;
			caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");
723

724
			if(!@is_dir($install_dir)){
Falko Timme's avatar
Falko Timme committed
725
				mkdir($install_dir, 0755, true);
726 727
			} else {
				chmod($install_dir, 0755);
Falko Timme's avatar
Falko Timme committed
728 729 730
			}
			chown($install_dir, $apps_vhost_user);
			chgrp($install_dir, $apps_vhost_group);
731

Falko Timme's avatar
Falko Timme committed
732 733 734 735
			//* Copy the apps vhost file
			$vhost_conf_dir = $conf['apache']['vhost_conf_dir'];
			$vhost_conf_enabled_dir = $conf['apache']['vhost_conf_enabled_dir'];
			$apps_vhost_servername = ($conf['web']['apps_vhost_servername'] == '') ? '' : 'ServerName '.$conf['web']['apps_vhost_servername'];
736

Falko Timme's avatar
Falko Timme committed
737 738
			//* Dont just copy over the virtualhost template but add some custom settings
			$content = $this->get_template_file('apache_apps.vhost', true);
739

Falko Timme's avatar
Falko Timme committed
740 741 742 743 744
			$content = str_replace('{apps_vhost_ip}', $conf['web']['apps_vhost_ip'], $content);
			$content = str_replace('{apps_vhost_port}', $conf['web']['apps_vhost_port'], $content);
			$content = str_replace('{apps_vhost_dir}', $conf['web']['website_basedir'].'/apps', $content);
			$content = str_replace('{website_basedir}', $conf['web']['website_basedir'], $content);
			$content = str_replace('{apps_vhost_servername}', $apps_vhost_servername, $content);
745

Falko Timme's avatar
Falko Timme committed
746 747 748 749 750 751
			//* comment out the listen directive if port is 80 or 443
			if($conf['web']['apps_vhost_ip'] == 80 or $conf['web']['apps_vhost_ip'] == 443) {
				$content = str_replace('{vhost_port_listen}', '#', $content);
			} else {
				$content = str_replace('{vhost_port_listen}', '', $content);
			}
752

Falko Timme's avatar
Falko Timme committed
753
			$this->write_config_file("$vhost_conf_dir/apps.vhost", $content);
754 755

			//if ( !is_file($conf['web']['website_basedir'].'/php-fcgi-scripts/apps/.php-fcgi-starter') )
756
			//{
757 758 759 760 761
			$content = rfsel($conf['ispconfig_install_dir'].'/server/conf-custom/install/apache_apps_fcgi_starter.master', 'tpl/apache_apps_fcgi_starter.master');
			$content = str_replace('{fastcgi_bin}', $conf['fastcgi']['fastcgi_bin'], $content);
			$content = str_replace('{fastcgi_phpini_path}', $conf['fastcgi']['fastcgi_phpini_path'], $content);
			mkdir($conf['web']['website_basedir'].'/php-fcgi-scripts/apps', 0755, true);
			//copy('tpl/apache_apps_fcgi_starter.master',$conf['web']['website_basedir'].'/php-fcgi-scripts/apps/.php-fcgi-starter');
762
			$this->set_immutable($conf['web']['website_basedir'].'/php-fcgi-scripts/apps/.php-fcgi-starter', false);
763 764 765
			wf($conf['web']['website_basedir'].'/php-fcgi-scripts/apps/.php-fcgi-starter', $content);
			exec('chmod +x '.$conf['web']['website_basedir'].'/php-fcgi-scripts/apps/.php-fcgi-starter');
			exec('chown -R ispapps:ispapps '.$conf['web']['website_basedir'].'/php-fcgi-scripts/apps');
766
			$this->set_immutable($conf['web']['website_basedir'].'/php-fcgi-scripts/apps/.php-fcgi-starter', true);
767
			//}
Falko Timme's avatar
Falko Timme committed
768
		}
769
		if($conf['nginx']['installed'] == true){
Falko Timme's avatar
Falko Timme committed
770 771 772 773 774 775 776 777 778 779 780 781 782 783
			$apps_vhost_user = escapeshellcmd($conf['web']['apps_vhost_user']);
			$apps_vhost_group = escapeshellcmd($conf['web']['apps_vhost_group']);
			$install_dir = escapeshellcmd($conf['web']['website_basedir'].'/apps');

			$command = 'groupadd '.$apps_vhost_user;
			if(!is_group($apps_vhost_group)) caselog($command.' &> /dev/null 2> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");

			$command = 'useradd -g '.$apps_vhost_group.' -d '.$install_dir.' '.$apps_vhost_group;
			if(!is_user($apps_vhost_user)) caselog($command.' &> /dev/null 2> /dev/null', __FILE__, __LINE__, "EXECUTED: $command", "Failed to execute the command $command");


			$command = 'adduser '.$conf['nginx']['user'].' '.$apps_vhost_group;
			caselog($command.' &> /dev/null', __FILE__, __LINE__, "EXECUTED: $command",