Make Selinux Postfix Postgrey and Dovecot work together

I am using Centos 5.2 which is a clone of Redhat Enterprise Linux. The following could work for Redhat and Fedora as well.
Please keep in mind that I am a beginner. Be aware of the fact that Selinux has changed a lot since Redhat 4 / Centos 4. I noted some resources in my blog as well to get uptodate information.

My Centos came with the default policy targeted.

Before you start find out how Selinux is configured.

sestatus

You should set it to permissive which logs denied messages but still let the application proceed. This can be done with

setenforce Permissive

Read the man page of both commands to get more information.

After having installed Postfix, Postgrey and Dovecot, I cleaned my log and restarted the auditd domain which is writing to the logs.


echo "" > /var/log/audit/audit.log
service auditd restart

Then I restarted the server to see all denied messages when these services are starting. Alternatively just restart the services.

In the audit.log you will find a lot of messages containing postfix now.
Sample:


type=SYSCALL msg=audit(1221346094.708:142515): arch=c000003e syscall=59 success=yes exit=0 a0=87abfc0 a1=87ac030 a2=87ab0f0 a3=3 items=0 ppid=13879 pid=13924
auid=500 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=699
comm=“sendmail” exe=“/usr/sbin/sendmail.postfix” subj=user_u:system_r:system_mail_t:s0 key=(null)
type=AVC msg=audit(1221346094.722:142516): avc: denied { getattr } for pid=13925 comm=“postdrop” path=“/var/log/httpd/error_log”
dev=dm-1 ino=2284942 scontext=user_u:system_r:postfix_postdrop_t:s0 tcontext=user_u:object_r:httpd_log_t:s0 tclass=file

Reading them is not easy at all. I just give a short summary, as I don’t know more details ;-)
scontext describes the source context doing something with a target context (tcontext). What is normally described in curly brackets. { getattr }
If you want to find out about the meaning have a look in the documentation of a tool. I don’t use it because it provides its own policy but it has a useful documentation.
http://seedit.sourceforge.net/doc/access_vectors/

postfix_postdrop_t indicates that there are already contexts defined for postfix. At least since Centos 5, you don’t have to define those context but just have to write the permissive rules to allow
things for this context. In case you have another application you need to create them first. See the article of Dan Walsh on http://www.redhatmagazine.com/2007/08/21/a-step-by-step-guide-to-building-a-new-selinux-policy-module/

From here we can do two things just create a Selinux module to allow all the denied things or analyse the messages first. I will go for the latter.

In my opinion, the most helpful tool is sealert. The following package contains it.

yum install setroubleshoot-server

sealert has a visual fronted or we can generate a report on a console as well.

As we don’t want to analyse all messages in audit.log we just filter for postfix first.
Either use a
grep postfix /var/log/audit/audit.log > postfix.log
or use the more flexible selinux search tool

ausearch --comm postfix > postfix.log

Read the manpage for more tips on ausearch.

To get the messages of today just use

ausearch --comm postfix --start today > postfix.log

Now run

sealert -a postfix.log > myreport

This report will give us a much easier to understand description on what is happening. It might interprete things not always correct but provides us with a general direction.

The next thing is to generate a policy module. There is a nice tool which can help us doing this: audit2allow

There are two options to use it:
create, install and ignore a policy module

grep postfix audit.log | audit2allow -M mymodule

semodule -i mymodule.pp

This will create a policy module which allows everything grepped for postfix in the log.

The second command installs it permanently.

But you should not simply trust what is added to the policy module. See my blog entry on Tomcat, Apache and mod_jk
create, analyse and compile a policy module

Therefore create a readable policy module first.

grep postfix audit.log | audit2allow -M mymodule

or
grep postfix audit.log | audit2allow -m > mymodule.te

The first one creates a compiled module as well, which we will overwrite later.

Below you can see my commented policy module for postfix. First the module name and version is defined. The require section declares all contexts and classes we are using later.
After this you can find the section which actually allows things.
Sample

dontaudit postfix_postdrop_t httpd_log_t:file getattr;

This dissallows the call to getattr for a file from the source context postfix_postdrop_t to the target context httpd_log_t.
I added this manually as I have no idea why postfix tries to get informations from the httpd log. This happens when a php script
is sending emails.
I found the following to be useful sources when adapting the entries
http://www.engardelinux.org/modules/index/selinux/overview.cgi#chapter-policy
and
http://seedit.sourceforge.net/doc/access_vectors/

module mypostfix 1.0;

require {
        type tmp_t;
        type postfix_spool_t;
        type default_context_t;
        type krb5_conf_t;
        type postfix_smtpd_t;
        type postfix_cleanup_t;
        type postfix_master_t;
        type postfix_postdrop_t;
        type httpd_log_t;
        type dovecot_cert_t;
        type file_context_t;
        type initrc_t;
        type security_t;
        class process setfscreate;
        class unix_stream_socket connectto;
        class file { read write getattr };
        class sock_file write;
        class security check_context;
        class dir { read getattr search };
}

#============= postfix_postdrop_t ==============
# don't know why it tries
dontaudit postfix_postdrop_t httpd_log_t:file getattr;

#========= postfix_smtpd_t ===========
# read security
allow postfix_smtpd_t krb5_conf_t:file { read getattr };
# search tmp
allow postfix_smtpd_t tmp_t:dir search;

# connect and write to postgrey socket
allow postfix_smtpd_t initrc_t:unix_stream_socket connectto;
allow postfix_smtpd_t postfix_spool_t:sock_file write;

allow postfix_smtpd_t self:process setfscreate;

allow postfix_smtpd_t default_context_t:dir search;
allow postfix_smtpd_t file_context_t:dir search;
allow postfix_smtpd_t file_context_t:file { read getattr };

allow postfix_smtpd_t security_t:file { read write };
allow postfix_smtpd_t security_t:security check_context;

#============= postfix_cleanup_t ==============
allow postfix_cleanup_t krb5_conf_t:file { read getattr };
allow postfix_cleanup_t tmp_t:dir search;
allow postfix_cleanup_t self:process setfscreate;
allow postfix_cleanup_t default_context_t:dir search;
allow postfix_cleanup_t file_context_t:dir search;
allow postfix_cleanup_t file_context_t:file { read getattr };
allow postfix_cleanup_t security_t:file write;
allow postfix_cleanup_t security_t:security check_context;

#============= postfix_master_t ==============
allow postfix_master_t krb5_conf_t:file { read getattr };
allow postfix_master_t tmp_t:dir search;

allow postfix_master_t dovecot_cert_t:dir { read getattr search };
allow postfix_master_t dovecot_cert_t:file getattr;


allow postfix_master_t self:process setfscreate;
allow postfix_master_t default_context_t:dir search;
allow postfix_master_t file_context_t:dir search;
allow postfix_master_t file_context_t:file { read getattr };
allow postfix_master_t security_t:file write;
allow postfix_master_t security_t:security check_context;

Now we need to compile the module

checkmodule -M -m -o mymodule.mod mymodule.te

semodule_package -o mymodule.pp -m mymodule.mod

and install it


semanage -i mymodule.pp

To get dovecot running do the same thing as we did with postfix. Clean your audit log, restart the auditd service and do everything with your mail service you could do (including restarting it).

To check the current rules you can use


sesearch —allow -s postfix_t

Check its manpage as well, it is very useful.
I hope, I could provide you with some tips. This article just stated some general things, we have not touched the option to use booleans for example. They help to configure existing domains.

Best Regards

Sebastian Hennebrueder

Comment from Dave on April 8, 2009 1:58:11 AM CEST #

Just what I’ve been looking for — great!