Christopher J. PeBenito wrote:
On Tue, 2008-08-05 at 11:03 +0100, Paul Howarth wrote:
Christopher J. PeBenito wrote:
On Mon, 2008-06-09 at 16:25 +0100, Paul Howarth wrote:
attached is a patch based on local policy I'm using on Fedora 9 to
support two "milter" mail filter daemons in conjunction with
sendmail,
namely spamass-milter and milter-regex (I maintain the packages for
both
of these in Fedora).
I've taken the view that most milter applications will have similar
requirements and so I've created a milter_template interface that
contains most of what's needed, and then added the specifics that are
needed on top of the generic stuff for each application.
+#============= milter-regex policy ==============
+milter_template(regex)
As I mentioned before, it doesn't look like a template is needed, unless
you think there will be many more milter domains. Then put all the
declarations in a section.
There are plenty of milters out there - see http://www.milter.org/milters
Not sure what you mean by "put all the declarations in a section". The
current version has very few declarations anyway now.
The style (including the commenting style) needs to match the rest of
refpolicy. If you're invoking a template like this, it means there are
some declarations. Other refpolicy modules have calls like this in the
declarations section.
OK, template invocations moved and commenting style revised.
+interface(`milter_spamass_stream_connect',`
+ gen_require(`
+ type milter_spamass_var_run_t, milter_spamass_t;
+ ')
+ stream_connect_pattern($1,milter_spamass_var_run_t,milter_spamass_var_run_t,milter_spamass_t)
+')
+
Missing a files_search_spool(). Interface name needs to be fixed [1].
I have two interfaces now, common to all milters:
milter_stream_connect
milter_getattr_socket_dir
I'll try claiming that "milter" is an abbreviation of "milters"; any
suggestions for better predicate names?
The target domain/object name, eg. milter_stream_connect_regex()
I'm now using milter_$1_data_dir_t in the interface, where this
directory might live under /var/spool for some milters, /var/run for
others etc. So I added files_search_spool() in the te file for the
milter(s) that needed it (only).
It seems that milter_$1_data_dir_t and milter_$1_socket_t can be merged
into milter_$1_data_t. They're all objects in the data dir, with
different classes. The object class differentiation should be
sufficient IMO.
OK, I've done this now. I originally split this up so that if a milter
wanted to create some other socket other than the one it used to
communicate with the MTA, then it would get a different context type. Of
course, if that happens, it's just as easy for the milter-specific
policy to arrange for a different context type to be used.
Heavily revised patch attached. The individual milter policies are quite
brief now (and there are plenty more that could be added), which I think
justifies the template approach. No further changes should need to be
made to the sendmail and postfix policies to support additional milters
either.
The main thing that worries me about template usage is too many rules
going into them just for convenience. We don't want rules that aren't
common to all milters.
I've removed more of the stuff from policygentool and kept the stuff I
really think is necessary now.
plain text document attachment (milters.patch)
[...]
--- policy/modules/services/milters.te (revision 0)
+++ policy/modules/services/milters.te (revision 0)
@@ -0,0 +1,42 @@
+policy_module(milters,0.1.4)
+
+require {
+ attribute port_type;
+}
This should be removed.
Done.
+#============= declarations ================
The commenting style needs to be fixed.
Done.
[...]
+interface(`milter_stream_connect',`
+ gen_require(`
+ attribute milter_socket_directories, milter_socket_type, milter_domains;
+ ')
+ getattr_dirs_pattern($1,milter_socket_directories,milter_socket_directories)
+ stream_connect_pattern($1,milter_socket_directories,milter_socket_type,milter_domains)
+')
Needs to be named so that it shows that you can connect to all milters:
milter_stream_connect_all()
Done.
Revised patch attached.
Paul.
Index: refpolicy/policy/modules/kernel/corenetwork.te.in
===================================================================
--- refpolicy/policy/modules/kernel/corenetwork.te.in (revision 2800)
+++ refpolicy/policy/modules/kernel/corenetwork.te.in (working copy)
@@ -121,6 +121,7 @@
type lrrd_port_t, port_type; dnl network_port(lrrd_port_t) # no defined portcon
network_port(lmtp, tcp,24,s0, udp,24,s0)
network_port(mail, tcp,2000,s0)
+type milter_port_t, port_type; dnl network_port(milter) # no defined portcon
network_port(mmcc, tcp,5050,s0, udp,5050,s0)
network_port(monopd, tcp,1234,s0)
network_port(msnp, tcp,1863,s0, udp,1863,s0)
Index: refpolicy/policy/modules/services/milters.te
===================================================================
--- refpolicy/policy/modules/services/milters.te (revision 0)
+++ refpolicy/policy/modules/services/milters.te (revision 0)
@@ -0,0 +1,54 @@
+policy_module(milters,0.2.0)
+
+########################################
+#
+# Declarations
+#
+
+# attributes common to all milters
+attribute milter_domains;
+attribute milter_data_type;
+
+# currently-supported milters are milter-regex and spamass-milter
+milter_template(regex)
+milter_template(spamass)
+
+########################################
+#
+# milter-regex local policy
+# filter emails using regular expressions
+# http://www.benzedrine.cx/milter-regex.html
+#
+
+# Look up username for dropping privs
+auth_use_nsswitch(milter_regex_t)
+
+# Config is in /etc/mail/milter-regex.conf
+mta_read_config(milter_regex_t)
+
+# The milter's socket directory lives under /var/spool
+files_search_spool(milter_regex_t)
+
+# It removes any existing socket (not owned by root) whilst running as root
+# and then calls setgid() and setuid() to drop privileges
+allow milter_regex_t self:capability { setuid setgid dac_override };
+
+
+########################################
+#
+# spamass-milter local policy
+# pipe emails through SpamAssassin
+# http://savannah.nongnu.org/projects/spamass-milt/
+#
+
+# The main job of the milter is to pipe spam through spamc and act on the result
+spamassassin_domtrans_spamc(milter_spamass_t)
+
+# When used with -b or -B options, the milter invokes sendmail to send mail
+# to a spamtrap address, using popen()
+corecmd_exec_shell(milter_spamass_t)
+corecmd_read_bin_symlinks(milter_spamass_t)
+corecmd_search_bin(milter_spamass_t)
+kernel_read_system_state(milter_spamass_t)
+mta_send_mail(milter_spamass_t)
+
Index: refpolicy/policy/modules/services/sendmail.te
===================================================================
--- refpolicy/policy/modules/services/sendmail.te (revision 2800)
+++ refpolicy/policy/modules/services/sendmail.te (working copy)
@@ -112,6 +112,10 @@
')
optional_policy(`
+ milter_stream_connect_all(sendmail_t)
+')
+
+optional_policy(`
postfix_exec_master(sendmail_t)
postfix_read_config(sendmail_t)
postfix_search_spool(sendmail_t)
Index: refpolicy/policy/modules/services/milters.fc
===================================================================
--- refpolicy/policy/modules/services/milters.fc (revision 0)
+++ refpolicy/policy/modules/services/milters.fc (revision 0)
@@ -0,0 +1,7 @@
+/usr/sbin/milter-regex -- gen_context(system_u:object_r:milter_regex_exec_t,s0)
+/var/spool/milter-regex(/.*)? gen_context(system_u:object_r:milter_regex_data_t,s0)
+
+/usr/sbin/spamass-milter -- gen_context(system_u:object_r:milter_spamass_exec_t,s0)
+/var/run/spamass-milter(/.*)? gen_context(system_u:object_r:milter_spamass_data_t,s0)
+/var/run/spamass-milter\.pid -- gen_context(system_u:object_r:milter_spamass_data_t,s0)
+
Index: refpolicy/policy/modules/services/mta.te
===================================================================
--- refpolicy/policy/modules/services/mta.te (revision 2800)
+++ refpolicy/policy/modules/services/mta.te (working copy)
@@ -105,6 +105,9 @@
# postfix needs this for newaliases
files_getattr_tmp_dirs(system_mail_t)
+ # newaliases runs as system_mail_t when the sendmail initscript does a restart
+ milter_getattr_all_data_dirs(system_mail_t)
+
postfix_exec_master(system_mail_t)
postfix_read_config(system_mail_t)
postfix_search_spool(system_mail_t)
Index: refpolicy/policy/modules/services/milters.if
===================================================================
--- refpolicy/policy/modules/services/milters.if (revision 0)
+++ refpolicy/policy/modules/services/milters.if (revision 0)
@@ -0,0 +1,90 @@
+## <summary>Milter mail filters</summary>
+
+########################################
+## <summary>
+## Create a set of derived types for various
+## mail filter applications using the milter interface.
+## </summary>
+## <param name="milter_name">
+## <summary>
+## The name to be used for deriving type names.
+## </summary>
+## </param>
+#
+template(`milter_template',`
+
+ # attributes common to all milters, plus port type for milter TCP sockets
+ gen_require(`
+ attribute milter_data_type, milter_domains;
+ type milter_port_t;
+ ')
+
+ # Type that the milter application runs as
+ type milter_$1_t, milter_domains;
+ domain_type(milter_$1_t)
+ role system_r types milter_$1_t;
+
+ # Type for the executable file
+ type milter_$1_exec_t;
+ init_daemon_domain(milter_$1_t, milter_$1_exec_t)
+
+ # Type for the milter data (e.g. the socket used to communicate with the MTA)
+ type milter_$1_data_t, milter_data_type;
+ files_type(milter_$1_data_t);
+
+ # Allow communication with MTA over a TCP socket
+ allow milter_$1_t milter_port_t:tcp_socket name_bind;
+ corenet_tcp_bind_generic_node(milter_$1_t)
+ allow milter_$1_t self:tcp_socket { listen accept };
+
+ # Allow communication with MTA over a unix-domain socket
+ manage_sock_files_pattern(milter_$1_t,milter_$1_data_t,milter_$1_data_t)
+
+ # Create other data files and directories in the data directory
+ manage_files_pattern(milter_$1_t,milter_$1_data_t,milter_$1_data_t)
+
+ # Things that all(?) milters will need to do
+ libs_use_ld_so(milter_$1_t)
+ libs_use_shared_libs(milter_$1_t)
+ miscfiles_read_localization(milter_$1_t)
+ init_use_fds(milter_$1_t)
+ allow milter_$1_t self:fifo_file rw_fifo_file_perms;
+ logging_send_syslog_msg(milter_$1_t)
+
+')
+
+########################################
+## <summary>
+## MTA communication with milter sockets
+## </summary>
+## <param name="domain">
+## <summary>
+## Domain allowed access.
+## </summary>
+## </param>
+#
+interface(`milter_stream_connect_all',`
+ gen_require(`
+ attribute milter_data_type, milter_domains;
+ ')
+ getattr_dirs_pattern($1,milter_data_type,milter_data_type)
+ stream_connect_pattern($1,milter_data_type,milter_data_type,milter_domains)
+')
+
+########################################
+## <summary>
+## Allow search of milter data directory
+## </summary>
+## <param name="domain">
+## <summary>
+## Domain allowed access.
+## </summary>
+## </param>
+#
+interface(`milter_getattr_all_data_dirs',`
+ gen_require(`
+ attribute milter_data_type;
+ ')
+ getattr_dirs_pattern($1,milter_data_type,milter_data_type)
+')
+
Index: refpolicy/policy/modules/services/spamassassin.fc
===================================================================
--- refpolicy/policy/modules/services/spamassassin.fc (revision 2800)
+++ refpolicy/policy/modules/services/spamassassin.fc (working copy)
@@ -10,7 +10,6 @@
/var/lib/spamassassin(/.*)? gen_context(system_u:object_r:spamd_var_lib_t,s0)
/var/run/spamassassin(/.*)? gen_context(system_u:object_r:spamd_var_run_t,s0)
-/var/run/spamass-milter(/.*)? gen_context(system_u:object_r:spamd_var_run_t,s0)
/var/spool/spamassassin(/.*)? gen_context(system_u:object_r:spamd_spool_t,s0)
/var/spool/spamd(/.*)? gen_context(system_u:object_r:spamd_spool_t,s0)
Index: refpolicy/policy/modules/services/postfix.te
===================================================================
--- refpolicy/policy/modules/services/postfix.te (revision 2800)
+++ refpolicy/policy/modules/services/postfix.te (working copy)
@@ -530,6 +530,10 @@
cyrus_stream_connect(postfix_smtp_t)
')
+optional_policy(`
+ milter_stream_connect_all(postfix_smtp_t)
+')
+
########################################
#
# Postfix smtpd local policy