Some additional patches: o lib/Qpsmtpd/SMTP.pm - Assumes a MAIL FROM value of "<[EMAIL PROTECTED]>" (utilized by qmail to indicate a null sender when generating a doublebounce message) is equivalent to "<>". Previously qpsmtpd complained that the value could not be parsed.
- Adds LOGIN to the default list of supported auth mechanisms. The documentation in Auth.pm indicated that auth-login was not currently supported due to lack of functionality, however I can confirm that LOGIN appears to work fine as tested by using msmtp (http://msmtp.sourceforge.net/). Are there any indications that LOGIN support is actually broken in the current implementation? - Removes the "X-Qpsmtpd-Auth: True" header appended when a message has been sent by an authenticated user. One problem with such a header is that it's impossible to say which SMTP hop added it, and it provides no information which could be used to backtrack the transaction. I grepped through my mail archives a bit looking for how other MTAs handled the problem, and decided it would be best to place this information in the Received: header: Received: from remotehost (HELO remotehost) (192.168.42.42) (smtp-auth username foo, mechanism cram-md5) by mail.netisland.net (qpsmtpd/0.28) with ESMTP; <date> o lib/Qpsmtpd/Auth.pm: - Documentation update for the arguments passed to an auth handler; previously the $mechanism argument was not mentioned, which threw off the argument offsets. - Documentation update for auth-login removing the warning that auth-login is not currently supported due to lack of functionality. - Fix to execute a generic auth hook when a more specific auth-$mechanism hook does not exist. (Previously posted to the list last week.) - Upon authentication, sets $session->{_auth_user} and $session->{_auth_mechanism} so that SMTP.pm can include them in the Received: header. o plugins/queue/qmail-queue - Added a timestamp and the qmail-queue qp identifier to the "Queued!" 250 message, for compatibility with qmail-smtpd, which can be very useful for tracking message delivery from machine to machine. For example, the new 250 message might be: 250 Queued! 1105927468 qp 3210 <[EMAIL PROTECTED]> qmail-smtpd returns: 250 ok 1106546213 qp 7129 Additionally, for consistency angle brackets are placed around the Message-ID displayed in the 250 if they were missing in the message header. o plugins/check_badmailfrom: - Changed the error message from "Mail from $bad not accepted here" to "sorry, your envelope sender is in my badmailfrom list", for compatibility with qmail-smtpd. I didn't see any reason to share with the sender the value of $bad, especially for situations where the sender was rejected resulting from a wildcard. o plugins/check_earlytalker: o plugins/require_resolvable_fromhost: - No longer checks for earlytalkers or resolvable senders if the connection note "whitelistclient" is set, which is nice for helping backup MX hosts empty their queue faster. o plugins/count_unrecognized_commands: - Return code changed from DENY_DISCONNECT, which isn't valid in an unrecognized_command hook, to DENY, which in this context drops the connection anyway. (Previously posted to the list last week.) Thanks, -mct -- perl -e'$u="\4\5\6";sub H{8*($_[1]%79)+($_[0]%8)}sub G{vec$u,H(@_),1}sub S{vec ($n,H(@_),1)=$_[2]}$_=q^{P`clear`;for$iX){PG($iY)?"O":" "forX8);P"\n"}for$iX){ forX8){$c=scalar [EMAIL PROTECTED];S$iY,G( $iY)?$c=~/[23]/?1:0:$c==3?1:0}}$u=$n;select$M,$C,$T,.2;redo}^;s/Z/],[\$i/g;s/Y /,\$_/xg;s/X/(0..7/g;s/P/print+/g;eval' # Michael C. Toren <[EMAIL PROTECTED]>
Index: lib/Qpsmtpd/Auth.pm =================================================================== RCS file: /cvs/public/qpsmtpd/lib/Qpsmtpd/Auth.pm,v retrieving revision 1.5 diff -u -u -r1.5 Auth.pm --- lib/Qpsmtpd/Auth.pm 23 Sep 2004 16:14:56 -0000 1.5 +++ lib/Qpsmtpd/Auth.pm 24 Jan 2005 05:16:27 -0000 @@ -64,6 +64,11 @@ A Qpsmtpd::Transaction object which can be used to examine information about the current SMTP session like the remote IP address. +=item $mechanism + +The lower-case name of the authentication mechanism requested by the +client; either "plain", "login", or "cram-md5". + =item $user Whatever the remote SMTP client sent to identify the user (may be bare @@ -157,7 +162,6 @@ encoded before sending. This is still an insecure method, since it is trivial to decode the Base-64 data. Again, it will not normally be chosen by SMTP clients unless a more secure method is not available (or if it fails). -CURRENTLY NOT SUPPORTED DUE TO LACK OF DOCUMENTATION ON FUNCTIONALITY =item * auth-cram-md5 @@ -309,7 +313,7 @@ $passHash, $ticket ); # try running the polymorphous hooks next - if ( $rc == DECLINED ) { + if ( !$rc || $rc == DECLINED ) { ( $rc, $msg ) = $session->run_hooks( "auth", $mechanism, $user, $passClear, $passHash, $ticket ); @@ -321,6 +325,11 @@ $session->respond( 235, $msg ); $session->connection->relay_client(1); $session->log( LOGINFO, $msg ); + + $session->{_auth_user} = $user; + $session->{_auth_mechanism} = $mechanism; + s/[\r\n].*//s for ($session->{_auth_user}, $session->{_auth_mechanism}); + return OK; } else { Index: lib/Qpsmtpd/SMTP.pm =================================================================== RCS file: /cvs/public/qpsmtpd/lib/Qpsmtpd/SMTP.pm,v retrieving revision 1.47 diff -u -u -r1.47 SMTP.pm --- lib/Qpsmtpd/SMTP.pm 27 Nov 2004 06:38:32 -0000 1.47 +++ lib/Qpsmtpd/SMTP.pm 24 Jan 2005 05:16:28 -0000 @@ -176,7 +176,7 @@ $auth_mechanisms{uc($1)} = 1; } else { # at least one polymorphous auth provider - %auth_mechanisms = map {$_,1} qw(PLAIN CRAM-MD5); + %auth_mechanisms = map {$_,1} qw(PLAIN CRAM-MD5 LOGIN); last HOOK; } } @@ -236,7 +236,7 @@ $self->log(LOGWARN, "from email address : [$from]"); - if ($from eq "<>" or $from =~ m/\[undefined\]/) { + if ($from eq "<>" or $from =~ m/\[undefined\]/ or $from eq "<[EMAIL PROTECTED]>") { $from = Qpsmtpd::Address->new("<>"); } else { @@ -488,15 +488,12 @@ $self->transaction->header($header); my $smtp = $self->connection->hello eq "ehlo" ? "ESMTP" : "SMTP"; - - # only true if client authenticated - if ( defined $self->{_auth} and $self->{_auth} == OK ) { - $header->add("X-Qpsmtpd-Auth","True"); - } + my $authheader = (defined $self->{_auth} and $self->{_auth} == OK) ? + "(smtp-auth username $self->{_auth_user}, mechanism $self->{_auth_mechanism})\n" : ""; $header->add("Received", "from ".$self->connection->remote_info ." (HELO ".$self->connection->hello_host . ") (".$self->connection->remote_ip - . ")\n by ".$self->config('me')." (qpsmtpd/".$self->version + . ")\n $authheader by ".$self->config('me')." (qpsmtpd/".$self->version .") with $smtp; ". (strftime('%a, %d %b %Y %H:%M:%S %z', localtime)), 0); Index: plugins/check_badmailfrom =================================================================== RCS file: /cvs/public/qpsmtpd/plugins/check_badmailfrom,v retrieving revision 1.6 diff -u -u -r1.6 check_badmailfrom --- plugins/check_badmailfrom 27 Nov 2004 18:40:54 -0000 1.6 +++ plugins/check_badmailfrom 24 Jan 2005 05:16:28 -0000 @@ -43,7 +43,7 @@ next unless $bad; $bad = lc $bad; warn "Bad badmailfrom config: No \@ sign in $bad\n" and next unless $bad =~ m/\@/; - $transaction->notes('badmailfrom', "Mail from $bad not accepted here") + $transaction->notes('badmailfrom', "sorry, your envelope sender is in my badmailfrom list") if ($bad eq $from) || (substr($bad,0,1) eq '@' && $bad eq "[EMAIL PROTECTED]"); } return (DECLINED); Index: plugins/check_earlytalker =================================================================== RCS file: /cvs/public/qpsmtpd/plugins/check_earlytalker,v retrieving revision 1.3 diff -u -u -r1.3 check_earlytalker --- plugins/check_earlytalker 1 Aug 2004 07:08:07 -0000 1.3 +++ plugins/check_earlytalker 24 Jan 2005 05:16:28 -0000 @@ -71,14 +71,19 @@ sub connect_handler { my ($self, $transaction) = @_; my $in = new IO::Select; + my $ip = $self->qp->connection->remote_ip; + + return DECLINED + if ($self->qp->connection->notes('whitelistclient')); $in->add(\*STDIN) || return DECLINED; if ($in->can_read($self->{_args}->{'wait'})) { - $self->log(LOGNOTICE, 'remote host started talking before we said hello'); + $self->log(LOGNOTICE, "remote host started talking before we said hello [$ip]"); if ($self->{_args}->{'defer-reject'}) { $self->qp->connection->notes('earlytalker', 1); } else { my $msg = 'Connecting host started transmitting before SMTP greeting'; return (DENY,$msg) if $self->{_args}->{'action'} eq 'deny'; return (DENYSOFT,$msg) if $self->{_args}->{'action'} eq 'denysoft'; } @@ -90,7 +95,8 @@ sub mail_handler { my ($self, $txn) = @_; my $msg = 'Connecting host started transmitting before SMTP greeting'; return DECLINED unless $self->qp->connection->notes('earlytalker'); return (DENY,$msg) if $self->{_args}->{'action'} eq 'deny'; Index: plugins/count_unrecognized_commands =================================================================== RCS file: /cvs/public/qpsmtpd/plugins/count_unrecognized_commands,v retrieving revision 1.6 diff -u -u -r1.6 count_unrecognized_commands --- plugins/count_unrecognized_commands 28 Nov 2004 05:58:58 -0000 1.6 +++ plugins/count_unrecognized_commands 24 Jan 2005 05:16:28 -0000 @@ -42,7 +42,7 @@ if ($badcmdcount >= $self->{_unrec_cmd_max}) { $self->log(LOGINFO, "Closing connection. Too many unrecognized commands."); - return (DENY_DISCONNECT, "Closing connection. $badcmdcount unrecognized commands. Perhaps you should read RFC 2821?"); + return (DENY, "Closing connection. $badcmdcount unrecognized commands. Perhaps you should read RFC 2821?"); } return DECLINED; Index: plugins/require_resolvable_fromhost =================================================================== RCS file: /cvs/public/qpsmtpd/plugins/require_resolvable_fromhost,v retrieving revision 1.3 diff -u -u -r1.3 require_resolvable_fromhost --- plugins/require_resolvable_fromhost 27 Nov 2004 07:08:45 -0000 1.3 +++ plugins/require_resolvable_fromhost 24 Jan 2005 05:16:28 -0000 @@ -8,6 +8,9 @@ sub mail_handler { my ($self, $transaction, $sender) = @_; + return DECLINED + if ($self->qp->connection->notes('whitelistclient')); + $sender->format ne "<>" and $self->qp->config("require_resolvable_fromhost") and !check_dns($sender->host) Index: plugins/queue/qmail-queue =================================================================== RCS file: /cvs/public/qpsmtpd/plugins/queue/qmail-queue,v retrieving revision 1.8 diff -u -u -r1.8 qmail-queue --- plugins/queue/qmail-queue 27 Nov 2004 17:54:46 -0000 1.8 +++ plugins/queue/qmail-queue 24 Jan 2005 05:16:28 -0000 @@ -75,7 +75,8 @@ my $msg_id = $transaction->header->get('Message-Id') || ''; $msg_id =~ s/[\r\n].*//s; # don't allow newlines in the Message-Id here - return (OK, "Queued! $msg_id"); + $msg_id = "<$msg_id>" unless $msg_id =~ /^<.*>$/; # surround in <>'s + return (OK, "Queued! " . time . " qp $child $msg_id"); } elsif (defined $child) { # Child @@ -100,7 +101,7 @@ POSIX::dup2(fileno(ENVELOPE_READER), 1) or die "Unable to dup ENVELOPE_READER: $!"; my $ppid = getppid(); - $self->log(LOGNOTICE, "(for $ppid ) Queuing to $queue_exec"); + $self->log(LOGNOTICE, "(for $ppid ) Queuing qp $$ to $queue_exec"); my $rc = exec $queue_exec;