#!/usr/bin/perl -w use strict; use IPC::Open2; use FileHandle; use MIME::Base64; use POSIX; $| = 1; if (!defined($ENV{GREETING}) || !defined($ENV{EHLORESP})) { die "You must set the environment variables GREETING and EHLORESP.\n"; } #$GREETING="220 mailweb.flinthomes.net ESMTP\r #"; #$HELORESP="250-mailweb.flinthomes.net\r #250-PIPELINING\r #250-8BITMIME\r #"; $ENV{GREETING} =~ s/\n/\r\n/g; $ENV{EHLORESP} =~ s/\n/\r\n/g; print $ENV{GREETING}; $ENV{SENTGREETING}=1; while (my $l = ) { if ($l =~ /^EHLO/i) { print $ENV{EHLORESP}; print "250 AUTH PLAIN\r\n"; $ENV{EHLO}=$l; } elsif ($l =~ /^AUTH(.*)$/i) { if ($1 =~ /^\s+PLAIN\s+(\S*)\s*$/i) { my($authorize,$authenticate,$pwd)=split(/\0/,decode_base64($1)); if (!defined($authorize) || !defined($authenticate) || !defined($pwd)) { print "501 Unable to decode password.\r\n"; next; } &authproxy($authenticate,$pwd); } print "504 Unrecognized authentication type.\r\n"; } else { $ENV{CMD}=$l; last; } } &runproxy; sub runproxy { shift @ARGV; exec(@ARGV); exit(0); } sub authproxy { my($user,$pass)=@_; $ENV{RELAYCLIENT}=""; $ENV{AUTHENTICATED}=$user; my($fdR,$fdW) = POSIX::pipe() or die "Couldn't create pipe: $!\n"; warn "Starting authproxy\n"; my $pid = fork; defined $pid or die "fork failed\n"; if (!$pid) { # Child POSIX::dup2(3,$fdR) unless ($fdR == 3); POSIX::close($fdW) unless ($fdW == 3); warn "exec('".join("', '",@ARGV)."')\n"; exec(@ARGV); die "exec error: $!\n"; } # Parent POSIX::close($fdR); open(AUTHOUT,">&=$fdW") or die "Couldn't open fd #$fdW as AUTHOUT: $!\n"; print AUTHOUT "$user\0$pass\0"; close(AUTHOUT); wait == $pid or die "Bad pid returned by wait (?!?)\n"; if ($? == 0) { ; } elsif ($? == 1) { print "535 Authentication credentials rejected\r\n"; } elsif ( ($? == 2) || ($? == 111) ) { print "454 Temporary authentication error\r\n"; } else { warn "Child process exited with $?\n"; } exit(0); }