PSI Group Server - Installing Mail Services

Note: a lot of this relates to fixing problems with the SEcure Linux implementation in Fedora Core 4. Scientific Linux 4 is mostly equivalent to Fedora Core 3, and its ''targeted' SELinux policy is more relaxed, so that these problems are not encountered. But I will leave it here because it might turn out useful again when Scientific Linux 5 will be released. sergio June 06, 2006, at 05:52 PM

1.  SMTP: Use Postfix instead of SendMail

 yum install postfix system-switch-mail
 system-switch-mail 

select postfix

 rm /etc/aliases.db
 service postfix restart
 echo "test" | mail root

2.  IMAP: use Dovecot instead of UW-imapd

 yum install dovecot
 chkconfig dovecot on
 service dovecot start
 system-config-securitylevel-tui 

customize, allow ports 143, 993

root login to imap fails:

Feb 17 12:34:50 pc31 dovecot: Logins with UID 0 not permitted (user root)
Feb 17 12:34:50 pc31 imap-login: Internal login failure: root [::ffff:146.141.72.25]
 adduser psigroup
 passwd psigroup groupPSI
 echo "test" | mail psigroup

(at this point Postfix does not yet deliver mail to Dovecot)


Now the configuration of Postfix + Dovecot + Procmail using Maildir mailboxes outside of the user's home directories, on a SELinux-enabled system. Actually more complicated than I expected.

dovecot.conf:

default_mail_env = maildir:/dsk1/_MAIL/%u/Maildir

/etc/postfix/main.cf:

# CHANGES from defaults here ONLY !
# send mail via
relayhost=schonlan.src.wits.ac.za
# 20MB
message_size_limit= 20480000
# 100MB
mailbox_size_limit=102400000

mydomain=psi.phys.wits.ac.za
inet_interfaces = all
mynetworks = 146.141.72.0/24

home_mailbox = Maildir/
mailbox_command = /usr/bin/procmail -a "$EXTENSION"

# for testing
soft_bounce=yes

/etc/procmailrc

MAILDIR=/dsk1/_MAIL/$LOGNAME/Maildir
DEFAULT=$MAILDIR/

The server runs with SELinux enabled. This means that we must make SELinux happy about letting the procmail process (started by postfix) write to the user directory. It also means that we cannot use a link /MAIL -> /dsk1/_MAIL because postfix_local_t does not have the right to read links in / . Ouch.

Attach:mkMaildirs.txt


3.  Adjust LogWatch filter for Postfix

LogWatch on SL4 is too verbose, especially for the virtual hosts, so I have adjusted the filter:

--- /etc/log.d/scripts/services/postfix.orig_sash       2006-07-27 14:55:11.000000000 +0200
+++ /etc/log.d/scripts/services/postfix 2006-10-28 22:08:57.000000000 +0200
@@ -137,7 +137,8 @@
       ( $ThisLine =~ m/^warning: numeric domain name in resource data of MX record for .*$/ ) or
       ( $ThisLine =~ m/^warning: premature end-of-input from cleanup socket while reading input attribute name$/ ) or
       ( $ThisLine =~ m/^warning: uid=\d: Broken pipe$/ ) or
-      ( $ThisLine =~ m/^verify error:num=/ )
+      ( $ThisLine =~ m/^verify error:num=/ ) or
+      ( $ThisLine =~ m/^statistcs: / )
    ) {
       # We don't care about these
    } elsif ( ($Bytes) = ($ThisLine =~ /^[a-zA-Z0-9]+: from=.*size=([0-9]+).*$/) ) {
@@ -152,12 +153,15 @@
    } elsif ((undef,$User) = ($ThisLine =~ /^[a-zA-Z0-9]+: reject: RCPT from ([^ ]*): [0-9]+ <([^ ]*)>: User unknown in virtual mailbox table;/)) {
       # unknown virtual user
       $UnknownUsers{$User}++;
-   } elsif (($User) = ($ThisLine =~ /^[a-zA-Z0-9]+: to\=\<([^ ]*)>, .*, status\=bounced .*: User unknown in virtual mailbox table/)) {
+   } elsif (($User) = ($ThisLine =~ /^[a-zA-Z0-9]+: to\=\<([^ ]*)>, .*, status\=bounced .*: User unknown in virtual alias table/)) {
       # another unknown user probably could combine with local unknown but again my perl is weak
       $UnknownUsers{$User}++;
    } elsif ((undef,$User) = ($ThisLine =~ /^[a-zA-Z0-9]+: reject: RCPT from ([^ ]*): [0-9]+ <([^ ]*)>.*: User unknown in local recipient table/)) {
       # and yet another unknown user probably
       $UnknownUsers{$User}++;
+   } elsif ((undef,$User) = ($ThisLine =~ /^[a-zA-Z0-9]+: reject: RCPT from ([^ ]*): [0-9]+ <([^ ]*)>.*: User unknown in virtual alias table/)) {
+      # and yet another unknown user probably
+      $UnknownUsers{$User}++;
    } elsif (($Dest, $Relay, $Msg) = ($ThisLine =~ /^[a-zA-Z0-9]+: to\=\<([^ ]*)>, relay=([^ ]*).*, delay\=-?[0-9]+, status\=bounced \(([^)]*)/ )) {
       # unknown user
       # $Msg = " hello "

4.  install Squirrelmail

See http://www.squirrelmail.org/wiki/SquirrelMailAndDovecotIMAP

 yum install squirrelmail system-config-securitylevel

Try http://psi.phys.wits.ac.za/webmail/src/configtest.php (note that this may require to temporarily add $allow_remote_configtest = true; to @@config_local.php)

The config file is /etc/squirrelmail/config_local.php:

$domain                 = 'psi.phys.wits.ac.za';
$imap_server_type       = 'dovecot';
$imapServerAddress      = 'localhost';
$imapPort               = 143;
$useSendmail            = false;
$smtpServerAddress      = 'localhost';
$smtpPort               = 25;
$default_folder_prefix          = '';
$trash_folder                   = 'Trash';
$sent_folder                    = 'Sent';
$draft_folder                   = 'Drafts';
$show_prefix_option		= false;
$default_sub_of_inbox		= false;
$show_contain_subfolders_option = false;
$optional_delimiter		= 'detect';
$delete_folder			= false;
$force_username_lowercase 	= true;

From http://slacy.com/blog/index.php/2005/11/19/php-warnings-from-squirrelmail/

[client xxx.xxx.xxx.xxx] PHP Warning: fsockopen() [function.fsockopen]: unable to connect to xxx.xxx.xxx.xxx:25 (Permission denied) in […]/configtest.php on line 266
The issue was the selinux permissions on the web server — what I was trying to do violated the selinux permissions scheme that was currently in place. I ran “system-config-securitylevel” and under the SElinux tab, selected the HTTPD permissions, and checked the box that says “Allow HTTPD scripts to connect to the network”.

Actually, that option is only available in the graphical mode of system-config-securitylevel, so make sure you ssh -X.

A command line alternative is

setsebool -P httpd_can_network_connect=1


5.  Install Mailman

See http://www.gnu.org/software/mailman/mailman-install/index.html
# yum install mailman

Go to http://psi.phys.wits.ac.za/mailman/listinfo

Add in /etc/mailman/mm_cfg.py

MTA = 'Postfix'
DEFAULT_URL_PATTERN = 'https://%s/mailman/'

Run

 /usr/lib/mailman/bin/withlist -l -r fix_url psigroup -v -u psi.phys.wits.ac.za

is you ever again change a _URL_

[root@psi:~]# /usr/lib/mailman/bin/newlist mailman
Enter the email of the person running the list: someone@psi.phys.wits.ac.za
Initial mailman password: (same as root)
...

Configure postfix for mailman: /etc/postfix/main.cf

# for Mailman:
alias_maps = hash:/etc/aliases,hash:/etc/mailman/aliases
recipient_delimiter = +
unknown_local_recipient_reject_code = 550

Now I had to fix SELinux policy for Postfix+Mailman. This time I cannot avoid actually modifying the source policy, so I need the relevant package:

 yum -y install selinux-policy-targeted-sources

Testing:

make -C /etc/selinux/targeted/src/policy load;\
  /usr/lib/mailman/bin/genaliases; \
  audit2allow -l -i /var/log/audit/audit.log
make -C /etc/selinux/targeted/src/policy load; \
  postfix reload;\
  audit2allow -l -i /var/log/audit/audit.log
make -C /etc/selinux/targeted/src/policy load;\
  echo "test" | mail mailman-admin ; sleep 5;\
  audit2allow -l -i /var/log/audit/audit.log

The resulting local policy file /etc/selinux/targeted/src/policy/domains/misc/local.te

# allow postalias to update mailman's  aliases
allow postfix_master_t mailman_data_t:dir { search write add_name remove_name };
allow postfix_master_t mailman_data_t:file { getattr read create write rename lock };

# allow reading mailman's  aliases
allow postfix_local_t mailman_data_t:file { read getattr lock };
allow postfix_smtpd_t mailman_data_t:dir search;
allow postfix_smtpd_t mailman_data_t:file { read getattr lock };

# allow postfix to execute mailman
allow postfix_local_t lib_t:file execute_no_trans;
allow postfix_postqueue_t unconfined_t:fifo_file write;

# allow logging
allow postfix_local_t var_log_t:dir search;
allow postfix_local_t mailman_log_t:dir search;
allow postfix_local_t mailman_log_t:file { append read getattr };

# operations on spool
allow postfix_local_t mailman_data_t:dir { write add_name remove_name create };
allow postfix_local_t mailman_data_t:file { create write rename };

# now allow the CGI to create a new mailing list
allow mailman_cgi_t postfix_etc_t:dir search;
allow mailman_cgi_t postfix_etc_t:file { read getattr };
allow mailman_cgi_t urandom_device_t:chr_file read;
allow mailman_cgi_t var_run_t:dir search;
allow mailman_cgi_t nscd_var_run_t:dir search;

Change the password:

 /usr/lib/mailman/bin/change_pw -l mailman
 /usr/lib/mailman/bin/mmsitepass

To create the list from the web you need

 chown apache /etc/mailman/aliases.db 

but this conflicts with other stuff...

Contrary to the instructions, do NOT add the /usr/lib/mailman/cron/crontab.in to the mailman user's crontab. The init.d startup script takes care of cron using /etc/cron.d/, so having that in the personal crontab would be redundant, and moreover the format of the file is not right for a personal crontab.

 chkconfig mailman on
 service mailman start