Add option -g group to have the milter create a group-writeable socket for communication with the MTA and set the GID of the socket to the specified group. This makes it possible to use the milter via a unix-domain socket with Postfix as the MTA (Postfix doesn't run as root and would otherwise be unable to use the socket). http://bugzilla.redhat.com/452248 --- spamass-milter.1.in +++ spamass-milter.1.in @@ -14,6 +14,7 @@ .Op Fl D Ar host .Op Fl e Ar defaultdomain .Op Fl f +.Op Fl g Ar group .Op Fl i Ar networks .Op Fl m .Op Fl M @@ -115,6 +116,12 @@ flag. Causes .Nm to fork into the background. +.It Fl g Ar group +Makes the socket for communication with the MTA group-writable (mode 0750) +and sets the socket's group to +.Ar group . +This option is intended for use with MTA's like Postfix that do not run as +root, and is incompatible with Sendmail usage. .It Fl i Ar networks Ignores messages if the originating IP is in the network(s) listed. The message will be passed through without calling SpamAssassin at all. --- spamass-milter.cpp +++ spamass-milter.cpp @@ -89,6 +89,7 @@ #endif #include #include +#include // C++ includes #include @@ -184,8 +185,9 @@ int main(int argc, char* argv[]) { int c, err = 0; - const char *args = "afd:mMp:P:r:u:D:i:b:B:e:xS:R:C:"; + const char *args = "afd:mMp:P:r:u:D:i:b:B:e:xS:R:C:g:"; char *sock = NULL; + char *group = NULL; bool dofork = false; char *pidfilename = NULL; FILE *pidfile = NULL; @@ -206,6 +208,9 @@ main(int argc, char* argv[]) case 'f': dofork = true; break; + case 'g': + group = strdup(optarg); + break; case 'd': parse_debuglevel(optarg); break; @@ -298,7 +303,7 @@ main(int argc, char* argv[]) cout << "Usage: spamass-milter -p socket [-b|-B bucket] [-d xx[,yy...]] [-D host]" << endl; cout << " [-e defaultdomain] [-f] [-i networks] [-m] [-M]" << endl; cout << " [-P pidfile] [-r nn] [-u defaultuser] [-x] [-a]" << endl; - cout << " [-C rejectcode] [ -R rejectmsg ]" << endl; + cout << " [-C rejectcode] [-R rejectmsg] [-g group]" << endl; cout << " [-- spamc args ]" << endl; cout << " -p socket: path to create socket" << endl; cout << " -b bucket: redirect spam to this mail address. The orignal" << endl; @@ -310,6 +315,7 @@ main(int argc, char* argv[]) cout << " -e defaultdomain: pass full email address to spamc instead of just\n" " username. Uses 'defaultdomain' if there was none" << endl; cout << " -f: fork into background" << endl; + cout << " -g group: socket group (perms to 660 as well)" << endl; cout << " -i: skip (ignore) checks from these IPs or netblocks" << endl; cout << " example: -i 192.168.12.5,10.0.0.0/8,172.16.0.0/255.255.0.0" << endl; cout << " -m: don't modify body, Content-type: or Subject:" << endl; @@ -378,6 +384,30 @@ main(int argc, char* argv[]) } else { debug(D_MISC, "smfi_register succeeded"); } + + if (group) + { + struct group *gr; + + (void) smfi_opensocket(0); + gr = getgrnam(group); + if (gr) + { + int rc; + rc = chown(sock, (uid_t)-1, gr->gr_gid); + if (!rc) + { + (void) chmod(sock, 0660); + } else { + perror("group option, chown"); + exit(EX_NOPERM); + } + } else { + perror("group option, getgrnam"); + exit(EX_NOUSER); + } + } + debug(D_ALWAYS, "spamass-milter %s starting", PACKAGE_VERSION); err = smfi_main(); debug(D_ALWAYS, "spamass-milter %s exiting", PACKAGE_VERSION);