Talk:Qmail, Mail toaster
m (Protected "Talk:Qmail, Mail toaster" [edit=autoconfirmed:move=autoconfirmed]) |
|||
(95 intermediate revisions by 34 users not shown) | |||
Line 1: | Line 1: | ||
+ | ==no, really== | ||
no, really, the comma shouldn't be there. (or the title should be "what it is, and what we are doing here" without the question mark). I used to be a spelling and grammar nazi in a past life. | no, really, the comma shouldn't be there. (or the title should be "what it is, and what we are doing here" without the question mark). I used to be a spelling and grammar nazi in a past life. | ||
-d. | -d. | ||
− | + | ==bad comma== | |
− | + | ||
− | + | ||
You're going to have to back that up with an external link to a well-accepted style guide that clearly states that using a comma there is wrong, and even then I don't promise to care. =) --[[User:Jimbo|Jimbo]] 20:36, 15 Dec 2004 (EST) | You're going to have to back that up with an external link to a well-accepted style guide that clearly states that using a comma there is wrong, and even then I don't promise to care. =) --[[User:Jimbo|Jimbo]] 20:36, 15 Dec 2004 (EST) | ||
− | + | ==grammar nazi bs== | |
− | + | ||
http://cctc2.commnet.edu/grammar/commas.htm | http://cctc2.commnet.edu/grammar/commas.htm | ||
Line 14: | Line 12: | ||
-d. | -d. | ||
− | + | ==full path== | |
− | + | ||
I'm not well up on wiki etiquette so I just thought I'd add a comment here on a small change I made. | I'm not well up on wiki etiquette so I just thought I'd add a comment here on a small change I made. | ||
Line 28: | Line 25: | ||
P.S. Great guide, it was very helpful, [[User:Eoin|Eoin]] | P.S. Great guide, it was very helpful, [[User:Eoin|Eoin]] | ||
− | + | ==that's odd== | |
− | + | ||
− | + | ||
− | + | ||
Huh - that's odd (that make qmail-enable ran into problems). Never seen that before. And your change was good, thanks. =) --[[User:Jimbo|Jimbo]] 10:59, 7 Jun 2005 (EDT) | Huh - that's odd (that make qmail-enable ran into problems). Never seen that before. And your change was good, thanks. =) --[[User:Jimbo|Jimbo]] 10:59, 7 Jun 2005 (EDT) | ||
− | |||
− | |||
== oddly enough == | == oddly enough == | ||
Line 115: | Line 107: | ||
-J | -J | ||
+ | |||
+ | ---- | ||
+ | ---- | ||
+ | |||
+ | maybe something else is holding the socket open? I'm guessing you've got sqwebmail tied into apache -- is your apache config ok? I don't run webmail myself so I probably won't be much help. | ||
+ | |||
+ | --[[User:Dave|Dave]] 09:47, 15 Sep 2005 (EDT) | ||
+ | |||
+ | == have you tried to ps waux | grep authdaemon? == | ||
+ | |||
+ | Try to start the authdaemon - '''/usr/local/etc/rc.d/(whatever)daemond.sh start''' - and then '''ps waux | grep authdaemon'''. Is it running? | ||
+ | |||
+ | If it isn't, you're going to need to figure out why. Usually the easiest way to deal with that PREFIX crap is just to snip it out and sub in the /usr/local/ hard-coded. --[[User:Jimbo|Jimbo]] 02:07, 16 Sep 2005 (EDT) | ||
+ | |||
+ | == lsof to find open sockets maybe == | ||
+ | |||
+ | might want to use [[lsof]] to see what's holding the socket open too... | ||
+ | |||
+ | --[[User:Dave|Dave]] 11:56, 17 Sep 2005 (EDT) | ||
+ | |||
+ | == this article should be updated... == | ||
+ | |||
+ | ...unfortunately, until i reinstall freebsd on a sparc at work, i have no bsd to do it with; the make qmail-enable thing doesn't work (i do the qmailrocks.org install myself....although i've been playing with postfix recently, and i'm going to install zimbra on my new listserver (why i moved my x86-64 box to CentOS instead of FreeBSD).... | ||
+ | |||
+ | --[[User:Dave|Dave]] 23:56, 3 Jan 2006 (EST) | ||
+ | |||
+ | == Checking Environment Variables == | ||
+ | |||
+ | Note to self: checking the environment variable TCPREMOTEINFO is a better way to check for authenticated SMTP, but qsheff doesn't pass that along - you'd need to wrap BEFORE qsheff, not after, in order to pick up on that. Which is beginning to beg the point of using qsheff at all... here is a complete list of environment variables present when qmail-queue is run: | ||
+ | |||
+ | TCPLOCALPORT=2525 | ||
+ | USER=yourmom | ||
+ | SSH_CLIENT='24.168.100.50 3295 22' | ||
+ | MACHTYPE=i386 | ||
+ | MAIL=/var/mail/mom | ||
+ | TCPREMOTEIP=70.150.138.10 | ||
+ | VENDOR=intel | ||
+ | SHLVL=2 | ||
+ | HOME=/root | ||
+ | PROTO=TCP | ||
+ | SSH_TTY=/dev/ttyp0 | ||
+ | PAGER=more | ||
+ | PS1='$ ' | ||
+ | OPTIND=1 | ||
+ | PS2='> ' | ||
+ | GROUP=wheel | ||
+ | LOGNAME=mom | ||
+ | TERM=xterm | ||
+ | BLOCKSIZE=K | ||
+ | TCPREMOTEPORT=1935 | ||
+ | PPID=92605 | ||
+ | PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin:/root/bin | ||
+ | REMOTEHOST=24.168.100.50 | ||
+ | TCPLOCALIP=66.154.114.98 | ||
+ | SHELL=/bin/csh | ||
+ | HOST=blackbox.tehinterweb.net | ||
+ | IFS=' | ||
+ | ' | ||
+ | OSTYPE=FreeBSD | ||
+ | TCPLOCALHOST=mail.jrssystems.net | ||
+ | PWD=/home/mom | ||
+ | TCPREMOTEINFO=jim@jrssystems.net | ||
+ | SSH_CONNECTION='24.168.100.50 3295 66.154.114.98 22' | ||
+ | FTP_PASSIVE_MODE=YES | ||
+ | HOSTTYPE=FreeBSD | ||
+ | EDITOR=vi | ||
+ | |||
+ | No black magic. So - ditch qsheff entirely and simply wrap qmail-queue itself? | ||
+ | |||
+ | ENVs to particularly note: TCPREMOTEINFO, TCPREMOTEIP | ||
+ | |||
+ | Final note for the night: don't see why not do my own standalone wrapper; mail got delivered fine while I was piping environment variables to a text file and piping STDIN to qmail-queue just now. No black magic a'tall, I don't know why wrapping qmail-queue wasn't seeming to work for me the last time I tried it; maybe I just didn't have the permissions set so that my wrapper would execute then? | ||
+ | |||
+ | AHA there is one bit of magic: qmail-queue actually READS its STDOUT to get addressing information normally; that's how bcc works. Example: | ||
+ | |||
+ | open (FH, "<&=1"); | ||
+ | @so = <FH>; | ||
+ | close (FH); | ||
+ | |||
+ | in a wrapper will get you the following in @so, from a message bcc'ed to yourmom@momscrib.com: | ||
+ | |||
+ | Fdad@pimpshack.netTyourmom@momscrib.com | ||
+ | |||
+ | Harrrr.... | ||
+ | |||
+ | --[[User:Jimbo|Jimbo]] 02:58, 21 Feb 2006 (EST) | ||
+ | |||
+ | Okay FOR REAL final line for the night: turns out that trying to get Perl to write to a child's STDOUT is beyond fucking painful. However it looks like /usr/ports/mail/qmail-qfilter will do the job nicely, it can be compiled as a plain (brown) wrapper with a minor alteration to the source code and takes a "get out of here you jackass" exit code (31) or a silent drop exit code (99) so there's good range of functionality. | ||
+ | |||
+ | it runs like this: put a shell script in place of qmail-queue like so: | ||
+ | #!/bin/sh | ||
+ | exec /path/to/qmail-qfilter \ | ||
+ | /path/to/spamc -- \ | ||
+ | /path/to/reject-message-with-spamrating-over-5 -- \ | ||
+ | /path/to/reject-message-with-unwantedkeyword -- \ | ||
+ | /path/to/reject-message-with-sobig | ||
+ | |||
+ | Sheesh. It's 5AM again. =( --[[User:Jimbo|Jimbo]] 05:00, 21 Feb 2006 (EST) | ||
+ | |||
+ | Confirmed. qmail-qfilter works fine. Just need to rework maildump.pl to dump the message to STDOUT instead of trying to feed it to qmail-queue directly by itself. --[[User:Jimbo|Jimbo]] 05:15, 21 Feb 2006 (EST) | ||
+ | |||
+ | == SETUID perl? == | ||
+ | |||
+ | probably will need to compile a new version of Perl from ports with MAKE -DENABLESUIDPERL=yes so's we can run the scanner as vpopmail / vchkpw, if you want to run the script setuid (as vpopmail, so it can deliver mail to normal MTA-accessible maildirs). It's better and easier to use sudo, IF you have the option - but if sudo craps out on you and starts acting buggy (it has happened to me on some servers but not others), running setuid IS a workable fallback option. | ||
+ | |||
+ | == qqxrc.patch == | ||
+ | |||
+ | save this (gotten from http://www.wijata.com/software/#QMAIL) as /home/[yourname]/qqxrc.patch | ||
+ | |||
+ | cd /usr/ports/mail/qmail-tls | ||
+ | make config : make sure to select the SMTP_AUTH knob and the RCDLINK knob; optionally you may choose to select the local-time knob also - DON'T select the double-bounce knob unless you want to patch by hand, the automated patch will FAIL if you do. | ||
+ | make fetch | ||
+ | make patch | ||
+ | cd work/qmail-1.0.3 | ||
+ | patch < /home/[yourname]/qqxrc.patch | ||
+ | cd ../.. | ||
+ | make install | ||
+ | |||
+ | [[Media:Qqxrc.patch.txt]] | ||
+ | |||
+ | now you can make install as normal | ||
+ | |||
+ | to use it, create /var/qmail/control/qqxrcode and populate it like so: | ||
+ | 32 Message permanently rejected (Virus detected) | ||
+ | 33 Message permanently rejected (Spam detected) | ||
+ | |||
+ | Net result: exiting from a filter program with a 32 or 33 gets you the above messages. | ||
+ | |||
+ | Normal SMTP 554 is from an exit 31, so I'd recommend sticking stuff in between 32 and 40. | ||
+ | |||
+ | == smartscan.pl == | ||
+ | |||
+ | <pre>#!/usr/bin/perl | ||
+ | |||
+ | ### | ||
+ | ### Smartscanner.pl | ||
+ | ### | ||
+ | ### VERSION 2.1 | ||
+ | ### 2006 Feb 28 | ||
+ | ### | ||
+ | ### (c) 2004,2006 JRS System Solutions | ||
+ | ### all rights reserved under BSD license - | ||
+ | ### you may use this code as long as this header remains | ||
+ | ### intact. | ||
+ | ### | ||
+ | |||
+ | # $postmaster is the address which will receive warnings. | ||
+ | # THIS SHOULD NOT BE AN ADDRESS AT A DOMAIN | ||
+ | # HANDLED BY THIS MAILSERVER! ENDLESS LOOPS | ||
+ | # COULD LOCK UP YOUR SERVER! | ||
+ | # | ||
+ | $postmaster = 'postmaster@ph34r.tehinterweb.net'; | ||
+ | |||
+ | # Don't forget to use visudo to allow qmaild to run maildir | ||
+ | # as vpopmail! | ||
+ | # | ||
+ | $delivery_agent = "/usr/local/bin/sudo -u vpopmail /usr/local/bin/maildir"; | ||
+ | |||
+ | # run antivirus / antispam scanners on mail delivered | ||
+ | # via SMTP AUTH connection? | ||
+ | # | ||
+ | $virus_scan_auth = 1; | ||
+ | $spam_scan_auth = 0; | ||
+ | |||
+ | # note: $quarantine_* does not determine whether mail is delivered | ||
+ | # to its original destination or not; only whether a copy of | ||
+ | # it is delivered to $quarantine_dir. The $reject_* | ||
+ | # variables below determine delivery or non-delivery to | ||
+ | # the original recipient and outcome of the SMTP conversation. | ||
+ | # | ||
+ | $quarantine_spam = 1; | ||
+ | $quarantine_virus = 1; | ||
+ | $spam_quarantine_dir = '/usr/local/vpopmail/domains/jrssystems.net/jim/Maildir/.INBOX.spam_quarantine'; | ||
+ | $virus_quarantine_dir = '/usr/local/vpopmail/domains/jrssystems.net/jim/Maildir/.INBOX.virus_quarantine'; | ||
+ | |||
+ | # note: if $archive_mail is set then copies of ACCEPTED mail - mail | ||
+ | # which has either not flagged as spam or virus OR mail which | ||
+ | # has flagged but for which the rejection setting is 0 - will | ||
+ | # be delivered to $archive_dir. If you want a single message | ||
+ | # store with accepted and rejected mail, set $archive_dir and | ||
+ | # $quarantine_dir to the same destination. | ||
+ | # | ||
+ | $archive_mail = 0; | ||
+ | $archive_dir = '/usr/local/vpopmail/domains/jrssystems.net/jim/Maildir/.INBOX.quarantine'; | ||
+ | |||
+ | # Reject detected spams and/or viruses, or deliver them? | ||
+ | # (in case of double-flag, virus rejection setting takes priority.) | ||
+ | # 0 = no rejection - accept and deliver (mangled) mail to | ||
+ | # original destination | ||
+ | # 1 = quiet reject, aka drop without alerting qmail-queue | ||
+ | # 2 = "noisy" reject, aka drop and pass error message along | ||
+ | # to qmail-queue for an SMTP 554 reject before SMTP | ||
+ | # conversation completes | ||
+ | # | ||
+ | $reject_spam = 2; | ||
+ | $reject_virus = 2; | ||
+ | |||
+ | # set the other basic configuration variables - | ||
+ | # logging, path of the working directory, name | ||
+ | # of the working file. | ||
+ | $logging = "/var/qmail/bin/splogger smartscan.pl"; | ||
+ | $antispam_agent = "/usr/local/bin/spamc -E"; | ||
+ | |||
+ | # $temppath is where working directories will be created. | ||
+ | $temppath = "/usr/local/vpopmail/smartscan"; | ||
+ | |||
+ | ################################################################################################ | ||
+ | ################################################################################################ | ||
+ | ## END USER CONFIGURATION VARIABLE SECTION -- PROGRAMMATIC SECTION BEGINS BELOW ## | ||
+ | ################################################################################################ | ||
+ | ################################################################################################ | ||
+ | |||
+ | # read envelope | ||
+ | # @envelope=(<STDERR>); | ||
+ | |||
+ | # read user and group id stuff | ||
+ | my $real_user_id = $<; # Grab all the original values | ||
+ | my $effective_user_id = $>; # so we can reset everything | ||
+ | my $real_group_id = $(; # when we are done with setuid access | ||
+ | my $effective_group_id = $); # | ||
+ | |||
+ | $<=$>=89; | ||
+ | $(=$)=89; | ||
+ | |||
+ | # Figure out where the SMTP connection came from and whether SMTP_AUTH was used. | ||
+ | $tcpremoteinfo = $ENV{'TCPREMOTEINFO'}; | ||
+ | $tcpremoteinfo =~ /(.*)/; | ||
+ | $tcpremoteinfo = $1; | ||
+ | # $tcpremoteip = $ENV{'TCPREMOTEIP'}; | ||
+ | |||
+ | $qmail_rcpts_raw = $ENV{'QMAILRCPTS'}; | ||
+ | @rcpts_raw = split ("\n", $qmail_rcpts_raw); | ||
+ | foreach $line (@rcpts_raw) { | ||
+ | $line =~ /(.*)/; | ||
+ | $line = $1; | ||
+ | $qmail_rcpts .= $line . " "; | ||
+ | } | ||
+ | |||
+ | # Clear Path so that Taint mode won't go nuts on us. | ||
+ | $ENV{'PATH'}='/bin:/usr/bin:/usr/local/bin:'; | ||
+ | delete @ENV{'IFS','CDPATH','ENV','BASH_ENV','PATH'}; | ||
+ | |||
+ | # working filename is a 15-digit random name to avoid overstep issues. | ||
+ | $tempdir = "smartscan_" . &randgen; | ||
+ | |||
+ | # fetch standard input, and rewrite it into a plain | ||
+ | # text file in a unique working directory. | ||
+ | |||
+ | mkdir ("$temppath/$tempdir",0777); | ||
+ | |||
+ | $email = ""; | ||
+ | @in=(<STDIN>); | ||
+ | $email = join("",@in); | ||
+ | $email =~ /(.*)/gs; | ||
+ | $email = $1; | ||
+ | open (FH, "> $temppath/$tempdir/email.txt"); | ||
+ | print FH "$email"; | ||
+ | close (FH); | ||
+ | |||
+ | # get (max 20 chars) the Subject: line | ||
+ | @subject_ = split ("Subject: ", $email); | ||
+ | @subject_ = split ("\n", $subject_[1]); | ||
+ | $subject = substr($subject_[0],0 ,20); | ||
+ | |||
+ | # peel off any MIME attachments and make them | ||
+ | # world-readable for benefit of scan daemons | ||
+ | # running under separate UIDs. | ||
+ | # | ||
+ | # note: ripmime is available at /usr/ports/mail/ripmime. | ||
+ | # note2: used to use munpack, but munpack couldn't handle TNEF (MS Outlook) garbage | ||
+ | # correctly. so ripmime is (significantly) better. | ||
+ | |||
+ | mkdir ("$temppath/$tempdir/WORKING",0777); | ||
+ | print `/usr/local/bin/ripmime -i $temppath/$tempdir/email.txt -e -d $temppath/$tempdir/WORKING`; | ||
+ | print `chmod -R 777 $temppath/$tempdir`; | ||
+ | |||
+ | # rework reject_spam and reject_virus to match desired exit codes: | ||
+ | # code 31 = SMTP 554, code 99 = silent drop | ||
+ | # | ||
+ | # in this case, we have a patched qmail with custom error codes for | ||
+ | # 32 and 33 so we are using those. | ||
+ | # | ||
+ | if ($reject_spam == 1) { $reject_spam = 99; } elsif ($reject_spam == 2) { $reject_spam = 33; } | ||
+ | if ($reject_virus == 1) { $reject_virus = 99; } elsif ($reject_virus == 2) { $reject_virus = 32; } | ||
+ | |||
+ | # only run virus scanning if not using SMTP AUTH or if $virus_scan_auth is set. | ||
+ | if ($tcpremoteinfo eq "" || $virus_scan_auth == 1) { | ||
+ | &scan_clamd; | ||
+ | } | ||
+ | |||
+ | # no point in wasting resources on spamassassin if we already found a virus; | ||
+ | # then only run spamassassin if not using SMTP AUTH or if $spam_scan_auth is set. | ||
+ | |||
+ | if ( $virus_found != 1 | ||
+ | && | ||
+ | ( $tcpremoteinfo eq '' | ||
+ | || $spam_scan_auth == 1 | ||
+ | ) | ||
+ | ) | ||
+ | { | ||
+ | &scan_spamc; | ||
+ | } | ||
+ | |||
+ | # deliver quarantine copy of spam email if called for | ||
+ | if ($quarantine_spam == 1 && $spam_found) { | ||
+ | open (FH, "| $delivery_agent $spam_quarantine_dir"); | ||
+ | print FH $email; | ||
+ | close (FH); | ||
+ | system "echo \"Quarantined spam message: RECIPIENT=$qmail_rcpts SUBJECT=$subject\" | $logging"; | ||
+ | } | ||
+ | |||
+ | # deliver quarantine copy of virus email if called for | ||
+ | if ($quarantine_virus == 1 && $virus_found) { | ||
+ | open (FH, "| $delivery_agent $virus_quarantine_dir"); | ||
+ | print FH $email; | ||
+ | close (FH); | ||
+ | system "echo \"Quarantined virus message: RECIPIENT=$qmail_rcpts SUBJECT=$subject\" | $logging"; | ||
+ | } | ||
+ | |||
+ | # deliver archive copy of email if called for | ||
+ | if ($archive_mail == 1 | ||
+ | && ($spam_found != 1 || $reject_spam == 0) | ||
+ | && ($virus_found != 1 || $reject_virus == 0) | ||
+ | ) | ||
+ | { | ||
+ | open (FH, "| $delivery_agent $archive_dir"); | ||
+ | print FH $email; | ||
+ | close (FH); | ||
+ | print `echo "Archived message for: RECIPIENT=$qmail_rcpts" | $logging`; | ||
+ | } | ||
+ | |||
+ | # lose the contents of our unique working directory. | ||
+ | # | ||
+ | print `/bin/rm -rf $temppath/$tempdir`; | ||
+ | |||
+ | # Decide how and if to deliver the message - controlled by exit code | ||
+ | $exit_code = 0; | ||
+ | if ($spam_found == 1) { $exit_code = $reject_spam; } | ||
+ | if ($virus_found == 1) { $exit_code = $reject_virus; } | ||
+ | |||
+ | # Pass STDOUT and exit status through and back out to qmail-queue | ||
+ | # No point in passing mail back to STDOUT if it's getting bounced. | ||
+ | if ($exit_code == 0) { print $email; } else { print ""; } | ||
+ | |||
+ | exit $exit_code; | ||
+ | |||
+ | |||
+ | ################################################################ | ||
+ | ################################################################ | ||
+ | |||
+ | sub randgen { | ||
+ | $result=""; | ||
+ | $rndkey="ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz"; | ||
+ | $randlength="15"; | ||
+ | while ($randlength) { | ||
+ | $result.=substr($rndkey,rand(length($rndkey)),1); | ||
+ | $randlength--; | ||
+ | } | ||
+ | return $result; | ||
+ | } | ||
+ | |||
+ | sub scan_fprot { | ||
+ | $strSCAN = `/usr/local/f-prot/f-prot -packed -ai -archive $temppath/$tempdir/WORKING`; | ||
+ | $virus_found = ($? == 0); | ||
+ | if ($virus_found) { | ||
+ | $virus_logstring = "no_malware_found"; | ||
+ | } else { | ||
+ | @scan_result = split(/\ /, $strSCAN); | ||
+ | $virus_logstring = "MALWARE_FOUND=$scan_result[1]"; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | sub scan_clamd { | ||
+ | $virus_found = 0; | ||
+ | $strSCAN = `/usr/local/bin/clamdscan --disable-summary --stdout $temppath/$tempdir/WORKING`; | ||
+ | $virus_found = ($? >> 8); # shift value of $? 8 places to get actual exit code | ||
+ | if ($virus_found == 0) { | ||
+ | $virus_logstring = "no_malware_found"; | ||
+ | } elsif ($virus_found == 1) { | ||
+ | @scan_result = split(/\ /, $strSCAN); | ||
+ | $virus_name = $scan_result[@scan_result - 2]; | ||
+ | $email =~ s/Subject:/Subject: \*\*\*VIRUS: \[$virus_name\]\*\*\*/s; | ||
+ | $virus_logstring = "MALWARE_FOUND: TYPE=$virus_name RECIPIENT=$qmail_rcpts SUBJECT=$subject"; | ||
+ | } else { | ||
+ | $virus_logstring = "WARNING: clamdscan returned error code $virus_found"; | ||
+ | $virus_logstring .= '! Delivering message anyway, and emailing postmaster...'; | ||
+ | $postmaster_mail = "WARNING: clamdscan returning error code $virus_found on your mailserver. (Is clamd running?)"; | ||
+ | # system "echo \"$postmaster_mail\" | mail -s \"CLAMD ERRORS!\" $postmaster"; | ||
+ | } | ||
+ | # now log the results of the scan | ||
+ | $virus_logstring =~ /(.*)/; | ||
+ | $virus_logstring = $1; | ||
+ | system "echo \"$virus_logstring\" | $logging"; | ||
+ | } | ||
+ | |||
+ | sub scan_spamc { | ||
+ | $spam_found = 0; | ||
+ | $email = `$antispam_agent < $temppath/$tempdir/email.txt`; | ||
+ | $spam_found = ($? >> 8); # shift value of $? 8 places to get actual exit code | ||
+ | if ($spam_found == 0) { | ||
+ | $spam_logstring = "no_spam_found"; | ||
+ | } elsif ($spam_found == 1) { | ||
+ | @spam_body = split(/score=/, $email); | ||
+ | @spam_body = split(/ /, $spam_body[1]); | ||
+ | $spam_logstring = "SPAM_FOUND: SCORE=$spam_body[0] RECIPIENT=$qmail_rcpts SUBJECT=$subject"; | ||
+ | } else { | ||
+ | $spam_logstring = "WARNING: spamc returned error code $spam_found"; | ||
+ | $spam_logstring .= '! Delivering message anyway, and emailing postmaster...'; | ||
+ | $postmaster_mail = "WARNING: spamc returning error code $spam_found on your mailserver. (Is clamd running?)"; | ||
+ | $spam_logstring =~ /(.*)/; | ||
+ | $spam_logstring = $1; | ||
+ | # system "echo \"$postmaster_mail\" | mail -s \"spamd errors\" $postmaster"; | ||
+ | } | ||
+ | # now log the results of the scan | ||
+ | $spam_logstring =~ /(.*)/; | ||
+ | $spam_logstring = $1; | ||
+ | system "echo \"$spam_logstring\" | $logging"; | ||
+ | |||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | == qmail-queue replacement == | ||
+ | |||
+ | mv qmail-queue qmail-queue.orig | ||
+ | |||
+ | this is the new qmail-queue: | ||
+ | |||
+ | #!/bin/sh | ||
+ | exec /usr/local/bin/qmail-qfilter \ | ||
+ | /usr/local/bin/sudo -u vpopmail /usr/local/bin/smartscan.pl | ||
+ | |||
+ | note be sure to set up sudoers properly and to make sure clamd and spamd are running as vpopmail (or you may want clamd to run as root), and '''chown vpopmail /usr/local/vpopmail/smartscan/tmp && chmod 700 /usr/local/vpopmail/smartscan/tmp''' to finish up. (Trying to be paranoid about permissions in the working directory to avoid possible race conditions potentially allowing unpriv users to do nasty things to email on its way in.) | ||
+ | |||
+ | == run setuid, or use sudo? == | ||
+ | |||
+ | You can do either one, but if you're forced to run in a setuid environment - INCLUDING if smartscan is called by a setuid script - you may have issues with sudo randomly acting like it isn't set up right, and "Password:" "Password:" "Password:" littering any root console you open and nasty messages all through your log files... in spite of things actually getting DELIVERED properly. Not sure why; my guess is that there's a race condition and occasionally Perl uses a real instead of an effective uid when it runs sudo, if it's running setuid itself? Regardless, if you don't HAVE to run the script setuid, it's a lot easier simply to specify sudo in your $delivery_agent variable... but if you DO have to, the script will run fine under taint checks. | ||
+ | |||
+ | '''BETTER OPTION:''' run smartscan itself sudo to vpopmail from the qmail-qfilter invocation. In sudoers, make sure you set | ||
+ | ALL ALL=(vpopmail) NOPASSWD: /usr/local/vpopmail/smartscan/smartscan.pl | ||
+ | because the UID qfilter is running under will change depending on whether it's called from a local injection process or an incoming mail from a remote host. Make sure clamd runs either as vpopmail or as root, and make sure spamd runs as vpopmail, and from there you're fine. | ||
+ | |||
+ | == qmail-ldap == | ||
+ | |||
+ | well, it's awkward because i didn't think it would work to have the mail toaster article do the qmail-ldap thing -- a lot of folks aren't going to have AD or LDAP, and a mail-toaster article that doesn't have ldap stuff in it is going to be lots more useful than one that does, but i have yet to find a single article that talks about installing qmail-ldap and getting it to talk to MS's AD and slapping a gui on it for management. which I'm going to do for my particular setup. except I haven't done that before so the article I'm ''going'' to make but haven't yet is basically going to be my scratch-pad until I get it right :) | ||
+ | |||
+ | in looking over the discussion page, i'm thinking a lot of these notes deserve their own articles, not to be buried in some other article's talk page...maybe a generalized "qmail notes and tips" page? | ||
+ | |||
+ | --[[User:Dave|Dave]] 22:00, 19 April 2006 (EDT) | ||
+ | |||
+ | == the notes on this page == | ||
+ | |||
+ | Are actually towards redoing the "real article" in a very big way; all of this stuff was my scratch paper while I built the 2.0 version of the toaster for a client. They need organization and rewriting "as a real article" and migration to "the real article." I never intended that they just live here forever, I just didn't want to bung up the actual article while I hacked together the new system. =) | ||
+ | |||
+ | As far as the qmail-ldap goes - why don't you just make a stub, and work from there? --[[User:Jimbo|Jimbo]] 22:09, 19 April 2006 (EDT) | ||
+ | |||
+ | == yeah, that's why the link's there.... == | ||
+ | |||
+ | so i can find the article i'm going to write when i get around to it :) | ||
+ | |||
+ | == CRAM-MD5 isn't really supported... *patch* == | ||
+ | |||
+ | Qmail will report that it supports CRAM-MD5 authentication when EHLO'ed by an incoming SMTP connection, but it's a lie - Qmail's native auth module might support it, but authvchkpw doesn't. At best, this means that incoming clients will pause for about 3 seconds while they fail out on CRAM-MD5 authentication before they fall back on LOGIN or PLAIN (either of which work fine). At worst (so far, I've only seen this with the Pegasus mail client), they'll just bomb out completely and refuse to send mail. | ||
+ | |||
+ | After issuing a '''make patch''', cd'ing to work/qmail-1.03, and patching with [[media:Qqxrc.patch.txt]], patch with [[media:Qmail-noCRAM-MD5.patch.txt]] to fix the issue and make authentication smooth, fast, and reliable. | ||
+ | |||
+ | ph34r# '''cd /usr/ports/mail/qmail''' | ||
+ | ph34r# '''make patch''' | ||
+ | ph34r# '''cd work/qmail-1.03''' | ||
+ | ph34r# '''patch < /home/username/qqxrc.patch''' | ||
+ | ph34r# '''patch < /home/username/qmail-noCRAM-MD5.patch''' | ||
+ | |||
+ | Now you can proceed with the actual building and installation of the port. |
Latest revision as of 02:29, 23 February 2009
[edit] no, really
no, really, the comma shouldn't be there. (or the title should be "what it is, and what we are doing here" without the question mark). I used to be a spelling and grammar nazi in a past life.
-d.
[edit] bad comma
You're going to have to back that up with an external link to a well-accepted style guide that clearly states that using a comma there is wrong, and even then I don't promise to care. =) --Jimbo 20:36, 15 Dec 2004 (EST)
[edit] grammar nazi bs
http://cctc2.commnet.edu/grammar/commas.htm
while not incorrect to use the comma there, it makes for bad scanning.
-d.
[edit] full path
I'm not well up on wiki etiquette so I just thought I'd add a comment here on a small change I made.
I added two /etc/ to the following section to ensure the command will work correctly when executed outside of the /etc directory
ph34r# rehash ph34r# cat /etc/tcp.smtp | tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp
Also for some reason I couldn't get make enable-qmail to execute. It was probably something I was doing wrong but should anyone run into similar difficulty just check out the file work/qmail-enable inside the qmail+smtp_auth+tls ports directory.
Its easy enough to read what it does and then execute the commands for disabling sendmail and enabling qmail manually.
P.S. Great guide, it was very helpful, Eoin
[edit] that's odd
Huh - that's odd (that make qmail-enable ran into problems). Never seen that before. And your change was good, thanks. =) --Jimbo 10:59, 7 Jun 2005 (EDT)
[edit] oddly enough
so for giggles, i'm installing a listserv (using mailman...i'll let you know how ti works out) and I'm using FreeBSD for the hell of it. and I am also having problems doing a make enable-qmail. going into the work dir doesn't shed any light on the matter as the only thing in there is:
# ls -la total 28 drwxr-xr-x 3 root wheel 512 Jul 13 16:18 . drwxr-xr-x 3 root wheel 512 Jul 13 16:18 .. -rw-r--r-- 1 root wheel 0 Jul 13 16:18 .build_done.qmail-smtp_auth+tls-1.03.20020519_1._var_qmail -rw-r--r-- 1 root wheel 0 Jul 13 16:18 .configure_done.qmail-smtp_auth+tls-1.03.20020519_1._var_qmail -rw-r--r-- 1 root wheel 0 Jul 13 16:18 .extract_done.qmail-smtp_auth+tls-1.03.20020519_1._var_qmail -rw-r--r-- 1 root wheel 0 Jul 13 16:18 .patch_done.qmail-smtp_auth+tls-1.03.20020519_1._var_qmail -rw-r--r-- 1 root wheel 311 Jul 13 16:18 SMTP_AUTH+TLS.readme -rw-r--r-- 1 root wheel 2639 Jul 13 16:18 pkg-install drwxr-xr-x 2 root wheel 16896 Jul 13 16:18 qmail-1.03
so what does enable-qmail do (as a target to make) that just a make install doesn't?
See the directory that I bolded in your ls output there? That's where the goodies are. That's how the work directory from a built port always looks. But in this case, what you actually want to look at is files/enable-qmail.in. What it does is, so far as I can tell, is just make sure that the mail command gets realiased to qmail from whatever it was aliased to before, by the means of copying a conf file. From looking at the Makefile, though, it looks as though the qmail-enable target may not even exist anymore; it looks like an installation of qmail since 1.03_3 will probably make a /var/qmail/scripts directory instead, from which you can run the script /var/qmail/scripts/enable-qmail. Lemme know what you find out, okay? --Jimbo 00:00, 14 Jul 2005 (EDT)
It might be worth mentioning that if vpopmail is ever upgraded then you need to manually reset the file attributes of /usr/local/vpopmail/bin/vchkpw or users will have login troubles.
-Eoin
Great Guide but I am having problems with SqWebmail Portion, it seems now that the in the ports tree when you install sqwebmail you get courier-authdaemond installed instead of sqwebmail-authdaemond, and I can not find anywhere the PREFIX script I need to replace in the .sh files, and I notice that courier-authdaemond has PREFIX already set to /usr/local already.......so I thought I was good to go.
but after I start the daemons and point my browser to Sqwebmail I get a 500 error with: The webmail system is temporarily unavailable. An error occured in function write: Socket is not connected?
I notice that in the courier-authdaemond.sh there is a setting for socket with the base directory being $authbase/run/socket however there is not a socket file or folder in /var/run
Any Thoughts?
- J
are you sure that $authbase == /var/run? I'd do a "find / | grep socket" to see where it might be..
--Dave 23:42, 14 Sep 2005 (EDT)
Here is the output:
nusparky# find / | grep socket /usr/include/netgraph/bluetooth/include/ng_btsocket.h /usr/include/netgraph/bluetooth/include/ng_btsocket_hci_raw.h /usr/include/netgraph/bluetooth/include/ng_btsocket_l2cap.h /usr/include/netgraph/bluetooth/include/ng_btsocket_rfcomm.h /usr/include/netgraph/ng_ksocket.h /usr/include/netgraph/ng_socket.h /usr/include/netgraph/ng_socketvar.h /usr/include/sys/socket.h /usr/include/sys/socketvar.h /usr/local/man/man1/socket.1.gz /usr/local/bin/socket /usr/local/lib/perl5/site_perl/5.8.7/mach/sys/socket.ph /usr/local/lib/perl5/site_perl/5.8.7/mach/sys/socketvar.ph /usr/local/share/doc/socket /usr/local/share/doc/socket/README / ......the rest are documents or in the ports tree ^C nusparky# nusparky# nusparky#
Any ideas?
-J
maybe something else is holding the socket open? I'm guessing you've got sqwebmail tied into apache -- is your apache config ok? I don't run webmail myself so I probably won't be much help.
--Dave 09:47, 15 Sep 2005 (EDT)
[edit] have you tried to ps waux | grep authdaemon?
Try to start the authdaemon - /usr/local/etc/rc.d/(whatever)daemond.sh start - and then ps waux | grep authdaemon. Is it running?
If it isn't, you're going to need to figure out why. Usually the easiest way to deal with that PREFIX crap is just to snip it out and sub in the /usr/local/ hard-coded. --Jimbo 02:07, 16 Sep 2005 (EDT)
[edit] lsof to find open sockets maybe
might want to use lsof to see what's holding the socket open too...
--Dave 11:56, 17 Sep 2005 (EDT)
[edit] this article should be updated...
...unfortunately, until i reinstall freebsd on a sparc at work, i have no bsd to do it with; the make qmail-enable thing doesn't work (i do the qmailrocks.org install myself....although i've been playing with postfix recently, and i'm going to install zimbra on my new listserver (why i moved my x86-64 box to CentOS instead of FreeBSD)....
--Dave 23:56, 3 Jan 2006 (EST)
[edit] Checking Environment Variables
Note to self: checking the environment variable TCPREMOTEINFO is a better way to check for authenticated SMTP, but qsheff doesn't pass that along - you'd need to wrap BEFORE qsheff, not after, in order to pick up on that. Which is beginning to beg the point of using qsheff at all... here is a complete list of environment variables present when qmail-queue is run:
TCPLOCALPORT=2525 USER=yourmom SSH_CLIENT='24.168.100.50 3295 22' MACHTYPE=i386 MAIL=/var/mail/mom TCPREMOTEIP=70.150.138.10 VENDOR=intel SHLVL=2 HOME=/root PROTO=TCP SSH_TTY=/dev/ttyp0 PAGER=more PS1='$ ' OPTIND=1 PS2='> ' GROUP=wheel LOGNAME=mom TERM=xterm BLOCKSIZE=K TCPREMOTEPORT=1935 PPID=92605 PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin:/root/bin REMOTEHOST=24.168.100.50 TCPLOCALIP=66.154.114.98 SHELL=/bin/csh HOST=blackbox.tehinterweb.net IFS=' ' OSTYPE=FreeBSD TCPLOCALHOST=mail.jrssystems.net PWD=/home/mom TCPREMOTEINFO=jim@jrssystems.net SSH_CONNECTION='24.168.100.50 3295 66.154.114.98 22' FTP_PASSIVE_MODE=YES HOSTTYPE=FreeBSD EDITOR=vi
No black magic. So - ditch qsheff entirely and simply wrap qmail-queue itself?
ENVs to particularly note: TCPREMOTEINFO, TCPREMOTEIP
Final note for the night: don't see why not do my own standalone wrapper; mail got delivered fine while I was piping environment variables to a text file and piping STDIN to qmail-queue just now. No black magic a'tall, I don't know why wrapping qmail-queue wasn't seeming to work for me the last time I tried it; maybe I just didn't have the permissions set so that my wrapper would execute then?
AHA there is one bit of magic: qmail-queue actually READS its STDOUT to get addressing information normally; that's how bcc works. Example:
open (FH, "<&=1"); @so = <FH>; close (FH);
in a wrapper will get you the following in @so, from a message bcc'ed to yourmom@momscrib.com:
Fdad@pimpshack.netTyourmom@momscrib.com
Harrrr....
--Jimbo 02:58, 21 Feb 2006 (EST)
Okay FOR REAL final line for the night: turns out that trying to get Perl to write to a child's STDOUT is beyond fucking painful. However it looks like /usr/ports/mail/qmail-qfilter will do the job nicely, it can be compiled as a plain (brown) wrapper with a minor alteration to the source code and takes a "get out of here you jackass" exit code (31) or a silent drop exit code (99) so there's good range of functionality.
it runs like this: put a shell script in place of qmail-queue like so:
#!/bin/sh exec /path/to/qmail-qfilter \ /path/to/spamc -- \ /path/to/reject-message-with-spamrating-over-5 -- \ /path/to/reject-message-with-unwantedkeyword -- \ /path/to/reject-message-with-sobig
Sheesh. It's 5AM again. =( --Jimbo 05:00, 21 Feb 2006 (EST)
Confirmed. qmail-qfilter works fine. Just need to rework maildump.pl to dump the message to STDOUT instead of trying to feed it to qmail-queue directly by itself. --Jimbo 05:15, 21 Feb 2006 (EST)
[edit] SETUID perl?
probably will need to compile a new version of Perl from ports with MAKE -DENABLESUIDPERL=yes so's we can run the scanner as vpopmail / vchkpw, if you want to run the script setuid (as vpopmail, so it can deliver mail to normal MTA-accessible maildirs). It's better and easier to use sudo, IF you have the option - but if sudo craps out on you and starts acting buggy (it has happened to me on some servers but not others), running setuid IS a workable fallback option.
[edit] qqxrc.patch
save this (gotten from http://www.wijata.com/software/#QMAIL) as /home/[yourname]/qqxrc.patch
cd /usr/ports/mail/qmail-tls make config : make sure to select the SMTP_AUTH knob and the RCDLINK knob; optionally you may choose to select the local-time knob also - DON'T select the double-bounce knob unless you want to patch by hand, the automated patch will FAIL if you do. make fetch make patch cd work/qmail-1.0.3 patch < /home/[yourname]/qqxrc.patch cd ../.. make install
now you can make install as normal
to use it, create /var/qmail/control/qqxrcode and populate it like so:
32 Message permanently rejected (Virus detected) 33 Message permanently rejected (Spam detected)
Net result: exiting from a filter program with a 32 or 33 gets you the above messages.
Normal SMTP 554 is from an exit 31, so I'd recommend sticking stuff in between 32 and 40.
[edit] smartscan.pl
#!/usr/bin/perl ### ### Smartscanner.pl ### ### VERSION 2.1 ### 2006 Feb 28 ### ### (c) 2004,2006 JRS System Solutions ### all rights reserved under BSD license - ### you may use this code as long as this header remains ### intact. ### # $postmaster is the address which will receive warnings. # THIS SHOULD NOT BE AN ADDRESS AT A DOMAIN # HANDLED BY THIS MAILSERVER! ENDLESS LOOPS # COULD LOCK UP YOUR SERVER! # $postmaster = 'postmaster@ph34r.tehinterweb.net'; # Don't forget to use visudo to allow qmaild to run maildir # as vpopmail! # $delivery_agent = "/usr/local/bin/sudo -u vpopmail /usr/local/bin/maildir"; # run antivirus / antispam scanners on mail delivered # via SMTP AUTH connection? # $virus_scan_auth = 1; $spam_scan_auth = 0; # note: $quarantine_* does not determine whether mail is delivered # to its original destination or not; only whether a copy of # it is delivered to $quarantine_dir. The $reject_* # variables below determine delivery or non-delivery to # the original recipient and outcome of the SMTP conversation. # $quarantine_spam = 1; $quarantine_virus = 1; $spam_quarantine_dir = '/usr/local/vpopmail/domains/jrssystems.net/jim/Maildir/.INBOX.spam_quarantine'; $virus_quarantine_dir = '/usr/local/vpopmail/domains/jrssystems.net/jim/Maildir/.INBOX.virus_quarantine'; # note: if $archive_mail is set then copies of ACCEPTED mail - mail # which has either not flagged as spam or virus OR mail which # has flagged but for which the rejection setting is 0 - will # be delivered to $archive_dir. If you want a single message # store with accepted and rejected mail, set $archive_dir and # $quarantine_dir to the same destination. # $archive_mail = 0; $archive_dir = '/usr/local/vpopmail/domains/jrssystems.net/jim/Maildir/.INBOX.quarantine'; # Reject detected spams and/or viruses, or deliver them? # (in case of double-flag, virus rejection setting takes priority.) # 0 = no rejection - accept and deliver (mangled) mail to # original destination # 1 = quiet reject, aka drop without alerting qmail-queue # 2 = "noisy" reject, aka drop and pass error message along # to qmail-queue for an SMTP 554 reject before SMTP # conversation completes # $reject_spam = 2; $reject_virus = 2; # set the other basic configuration variables - # logging, path of the working directory, name # of the working file. $logging = "/var/qmail/bin/splogger smartscan.pl"; $antispam_agent = "/usr/local/bin/spamc -E"; # $temppath is where working directories will be created. $temppath = "/usr/local/vpopmail/smartscan"; ################################################################################################ ################################################################################################ ## END USER CONFIGURATION VARIABLE SECTION -- PROGRAMMATIC SECTION BEGINS BELOW ## ################################################################################################ ################################################################################################ # read envelope # @envelope=(<STDERR>); # read user and group id stuff my $real_user_id = $<; # Grab all the original values my $effective_user_id = $>; # so we can reset everything my $real_group_id = $(; # when we are done with setuid access my $effective_group_id = $); # $<=$>=89; $(=$)=89; # Figure out where the SMTP connection came from and whether SMTP_AUTH was used. $tcpremoteinfo = $ENV{'TCPREMOTEINFO'}; $tcpremoteinfo =~ /(.*)/; $tcpremoteinfo = $1; # $tcpremoteip = $ENV{'TCPREMOTEIP'}; $qmail_rcpts_raw = $ENV{'QMAILRCPTS'}; @rcpts_raw = split ("\n", $qmail_rcpts_raw); foreach $line (@rcpts_raw) { $line =~ /(.*)/; $line = $1; $qmail_rcpts .= $line . " "; } # Clear Path so that Taint mode won't go nuts on us. $ENV{'PATH'}='/bin:/usr/bin:/usr/local/bin:'; delete @ENV{'IFS','CDPATH','ENV','BASH_ENV','PATH'}; # working filename is a 15-digit random name to avoid overstep issues. $tempdir = "smartscan_" . &randgen; # fetch standard input, and rewrite it into a plain # text file in a unique working directory. mkdir ("$temppath/$tempdir",0777); $email = ""; @in=(<STDIN>); $email = join("",@in); $email =~ /(.*)/gs; $email = $1; open (FH, "> $temppath/$tempdir/email.txt"); print FH "$email"; close (FH); # get (max 20 chars) the Subject: line @subject_ = split ("Subject: ", $email); @subject_ = split ("\n", $subject_[1]); $subject = substr($subject_[0],0 ,20); # peel off any MIME attachments and make them # world-readable for benefit of scan daemons # running under separate UIDs. # # note: ripmime is available at /usr/ports/mail/ripmime. # note2: used to use munpack, but munpack couldn't handle TNEF (MS Outlook) garbage # correctly. so ripmime is (significantly) better. mkdir ("$temppath/$tempdir/WORKING",0777); print `/usr/local/bin/ripmime -i $temppath/$tempdir/email.txt -e -d $temppath/$tempdir/WORKING`; print `chmod -R 777 $temppath/$tempdir`; # rework reject_spam and reject_virus to match desired exit codes: # code 31 = SMTP 554, code 99 = silent drop # # in this case, we have a patched qmail with custom error codes for # 32 and 33 so we are using those. # if ($reject_spam == 1) { $reject_spam = 99; } elsif ($reject_spam == 2) { $reject_spam = 33; } if ($reject_virus == 1) { $reject_virus = 99; } elsif ($reject_virus == 2) { $reject_virus = 32; } # only run virus scanning if not using SMTP AUTH or if $virus_scan_auth is set. if ($tcpremoteinfo eq "" || $virus_scan_auth == 1) { &scan_clamd; } # no point in wasting resources on spamassassin if we already found a virus; # then only run spamassassin if not using SMTP AUTH or if $spam_scan_auth is set. if ( $virus_found != 1 && ( $tcpremoteinfo eq '' || $spam_scan_auth == 1 ) ) { &scan_spamc; } # deliver quarantine copy of spam email if called for if ($quarantine_spam == 1 && $spam_found) { open (FH, "| $delivery_agent $spam_quarantine_dir"); print FH $email; close (FH); system "echo \"Quarantined spam message: RECIPIENT=$qmail_rcpts SUBJECT=$subject\" | $logging"; } # deliver quarantine copy of virus email if called for if ($quarantine_virus == 1 && $virus_found) { open (FH, "| $delivery_agent $virus_quarantine_dir"); print FH $email; close (FH); system "echo \"Quarantined virus message: RECIPIENT=$qmail_rcpts SUBJECT=$subject\" | $logging"; } # deliver archive copy of email if called for if ($archive_mail == 1 && ($spam_found != 1 || $reject_spam == 0) && ($virus_found != 1 || $reject_virus == 0) ) { open (FH, "| $delivery_agent $archive_dir"); print FH $email; close (FH); print `echo "Archived message for: RECIPIENT=$qmail_rcpts" | $logging`; } # lose the contents of our unique working directory. # print `/bin/rm -rf $temppath/$tempdir`; # Decide how and if to deliver the message - controlled by exit code $exit_code = 0; if ($spam_found == 1) { $exit_code = $reject_spam; } if ($virus_found == 1) { $exit_code = $reject_virus; } # Pass STDOUT and exit status through and back out to qmail-queue # No point in passing mail back to STDOUT if it's getting bounced. if ($exit_code == 0) { print $email; } else { print ""; } exit $exit_code; ################################################################ ################################################################ sub randgen { $result=""; $rndkey="ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz"; $randlength="15"; while ($randlength) { $result.=substr($rndkey,rand(length($rndkey)),1); $randlength--; } return $result; } sub scan_fprot { $strSCAN = `/usr/local/f-prot/f-prot -packed -ai -archive $temppath/$tempdir/WORKING`; $virus_found = ($? == 0); if ($virus_found) { $virus_logstring = "no_malware_found"; } else { @scan_result = split(/\ /, $strSCAN); $virus_logstring = "MALWARE_FOUND=$scan_result[1]"; } } sub scan_clamd { $virus_found = 0; $strSCAN = `/usr/local/bin/clamdscan --disable-summary --stdout $temppath/$tempdir/WORKING`; $virus_found = ($? >> 8); # shift value of $? 8 places to get actual exit code if ($virus_found == 0) { $virus_logstring = "no_malware_found"; } elsif ($virus_found == 1) { @scan_result = split(/\ /, $strSCAN); $virus_name = $scan_result[@scan_result - 2]; $email =~ s/Subject:/Subject: \*\*\*VIRUS: \[$virus_name\]\*\*\*/s; $virus_logstring = "MALWARE_FOUND: TYPE=$virus_name RECIPIENT=$qmail_rcpts SUBJECT=$subject"; } else { $virus_logstring = "WARNING: clamdscan returned error code $virus_found"; $virus_logstring .= '! Delivering message anyway, and emailing postmaster...'; $postmaster_mail = "WARNING: clamdscan returning error code $virus_found on your mailserver. (Is clamd running?)"; # system "echo \"$postmaster_mail\" | mail -s \"CLAMD ERRORS!\" $postmaster"; } # now log the results of the scan $virus_logstring =~ /(.*)/; $virus_logstring = $1; system "echo \"$virus_logstring\" | $logging"; } sub scan_spamc { $spam_found = 0; $email = `$antispam_agent < $temppath/$tempdir/email.txt`; $spam_found = ($? >> 8); # shift value of $? 8 places to get actual exit code if ($spam_found == 0) { $spam_logstring = "no_spam_found"; } elsif ($spam_found == 1) { @spam_body = split(/score=/, $email); @spam_body = split(/ /, $spam_body[1]); $spam_logstring = "SPAM_FOUND: SCORE=$spam_body[0] RECIPIENT=$qmail_rcpts SUBJECT=$subject"; } else { $spam_logstring = "WARNING: spamc returned error code $spam_found"; $spam_logstring .= '! Delivering message anyway, and emailing postmaster...'; $postmaster_mail = "WARNING: spamc returning error code $spam_found on your mailserver. (Is clamd running?)"; $spam_logstring =~ /(.*)/; $spam_logstring = $1; # system "echo \"$postmaster_mail\" | mail -s \"spamd errors\" $postmaster"; } # now log the results of the scan $spam_logstring =~ /(.*)/; $spam_logstring = $1; system "echo \"$spam_logstring\" | $logging"; }
[edit] qmail-queue replacement
mv qmail-queue qmail-queue.orig
this is the new qmail-queue:
#!/bin/sh exec /usr/local/bin/qmail-qfilter \ /usr/local/bin/sudo -u vpopmail /usr/local/bin/smartscan.pl
note be sure to set up sudoers properly and to make sure clamd and spamd are running as vpopmail (or you may want clamd to run as root), and chown vpopmail /usr/local/vpopmail/smartscan/tmp && chmod 700 /usr/local/vpopmail/smartscan/tmp to finish up. (Trying to be paranoid about permissions in the working directory to avoid possible race conditions potentially allowing unpriv users to do nasty things to email on its way in.)
[edit] run setuid, or use sudo?
You can do either one, but if you're forced to run in a setuid environment - INCLUDING if smartscan is called by a setuid script - you may have issues with sudo randomly acting like it isn't set up right, and "Password:" "Password:" "Password:" littering any root console you open and nasty messages all through your log files... in spite of things actually getting DELIVERED properly. Not sure why; my guess is that there's a race condition and occasionally Perl uses a real instead of an effective uid when it runs sudo, if it's running setuid itself? Regardless, if you don't HAVE to run the script setuid, it's a lot easier simply to specify sudo in your $delivery_agent variable... but if you DO have to, the script will run fine under taint checks.
BETTER OPTION: run smartscan itself sudo to vpopmail from the qmail-qfilter invocation. In sudoers, make sure you set
ALL ALL=(vpopmail) NOPASSWD: /usr/local/vpopmail/smartscan/smartscan.pl
because the UID qfilter is running under will change depending on whether it's called from a local injection process or an incoming mail from a remote host. Make sure clamd runs either as vpopmail or as root, and make sure spamd runs as vpopmail, and from there you're fine.
[edit] qmail-ldap
well, it's awkward because i didn't think it would work to have the mail toaster article do the qmail-ldap thing -- a lot of folks aren't going to have AD or LDAP, and a mail-toaster article that doesn't have ldap stuff in it is going to be lots more useful than one that does, but i have yet to find a single article that talks about installing qmail-ldap and getting it to talk to MS's AD and slapping a gui on it for management. which I'm going to do for my particular setup. except I haven't done that before so the article I'm going to make but haven't yet is basically going to be my scratch-pad until I get it right :)
in looking over the discussion page, i'm thinking a lot of these notes deserve their own articles, not to be buried in some other article's talk page...maybe a generalized "qmail notes and tips" page?
--Dave 22:00, 19 April 2006 (EDT)
[edit] the notes on this page
Are actually towards redoing the "real article" in a very big way; all of this stuff was my scratch paper while I built the 2.0 version of the toaster for a client. They need organization and rewriting "as a real article" and migration to "the real article." I never intended that they just live here forever, I just didn't want to bung up the actual article while I hacked together the new system. =)
As far as the qmail-ldap goes - why don't you just make a stub, and work from there? --Jimbo 22:09, 19 April 2006 (EDT)
[edit] yeah, that's why the link's there....
so i can find the article i'm going to write when i get around to it :)
[edit] CRAM-MD5 isn't really supported... *patch*
Qmail will report that it supports CRAM-MD5 authentication when EHLO'ed by an incoming SMTP connection, but it's a lie - Qmail's native auth module might support it, but authvchkpw doesn't. At best, this means that incoming clients will pause for about 3 seconds while they fail out on CRAM-MD5 authentication before they fall back on LOGIN or PLAIN (either of which work fine). At worst (so far, I've only seen this with the Pegasus mail client), they'll just bomb out completely and refuse to send mail.
After issuing a make patch, cd'ing to work/qmail-1.03, and patching with media:Qqxrc.patch.txt, patch with media:Qmail-noCRAM-MD5.patch.txt to fix the issue and make authentication smooth, fast, and reliable.
ph34r# cd /usr/ports/mail/qmail ph34r# make patch ph34r# cd work/qmail-1.03 ph34r# patch < /home/username/qqxrc.patch ph34r# patch < /home/username/qmail-noCRAM-MD5.patch
Now you can proceed with the actual building and installation of the port.