Path : /etc/ |
|
Current File : //etc/exim.pl.rpmsave |
BEGIN {
unshift @INC, '/etc/exim/perl';
}
my $hasmd5;
sub loadmd5 {
if ( defined $hasmd5 ) { return; }
eval {
#require Digest::Perl::MD5;
$hasmd5 = 1;
};
}
sub checkrelayhost {
my ($hostaddress) = @_;
if ( $hostaddress eq "127.0.0.1" ) { return 1; }
open( RELAYHOSTS, "/etc/relayhosts" );
while (<RELAYHOSTS>) {
s/\n//g;
next if ( $_ eq "" );
if ( $hostaddress eq $_ ) {
close(RELAYHOSTS);
return 1;
}
}
close(RELAYHOSTS);
return (0);
}
sub getfilterfile {
my ($user) = @_;
my ($domain) = getusersdomain($user);
return ("/etc/vfilters/${domain}");
}
sub hasfilterfile {
my ($user) = @_;
my ($domain) = getusersdomain($user);
if ( ${domain} eq "" ) { return (0); }
if ( !-d "/etc/vfilters/${domain}" && -e "/etc/vfilters/${domain}" ) { return (1); }
return (0);
}
sub checkvalias {
my ( $domain, $local_part ) = @_;
my ($hasval) = 0;
my ($autoresponder) = 0;
open( VAL, "/etc/valiases/$domain" );
while (<VAL>) {
if ( $autoresponder && beginmatch( $_, "*:" ) ) {
if (/:fail:/) {
#stop processing the message as we already have
#given an autoresponse and we do not want to send
#a failure message
$hasval = 1;
last();
}
}
elsif ( beginmatch( $_, "${local_part}\@${domain}:" ) ) {
my $defi;
( undef, $defi ) = split( /: /, $_ );
my (@DESTS) = split( /\,/, $defi );
foreach my $dest (@DESTS) {
if ( $dest =~ /\/autorespond/ ) {
$autoresponder = 1;
}
else {
$hasval = 1;
}
}
if ( !$autoresponder ) {
last;
}
}
}
close(VAL);
return ($hasval);
}
sub gensaheader_virtual {
my ($domain) = @_;
my ($owner) = getdomainowner($domain);
my ($spamkey) = getspamkey($owner);
return "X-Spam-Exim: $spamkey\n";
}
sub gensaheader {
my ($owner) = @_;
my ($spamkey) = getspamkey($owner);
return "X-Spam-Exim: $spamkey\n";
}
sub getspamkey {
my ($user) = @_;
my ($homedir) = gethomedir($user);
my ($spamkey);
if ( -e "${homedir}/.spamkey" ) {
open( SPAMKEY, "${homedir}/.spamkey" );
$spamkey = <SPAMKEY>;
close(SPAMKEY);
return ($spamkey);
}
else {
if ( $> == 0 ) {
my $pid;
if ( !( $pid = fork() ) ) {
&setuids($user);
open( RANDOM, "/dev/urandom" );
read RANDOM, $spamkey, 4096;
close(RANDOM);
$spamkey =~ s/\W//g;
$spamkey = substr( $spamkey, 0, 24 );
open( SPAMKEY, ">${homedir}/.spamkey" );
chmod( 0600, "${homedir}/.spamkey" );
print SPAMKEY $spamkey;
close(SPAMKEY);
exit();
}
waitpid( $pid, 0 );
open( SPAMKEY, "${homedir}/.spamkey" );
$spamkey = <SPAMKEY>;
close(SPAMKEY);
return ($spamkey);
}
else {
open( RANDOM, "/dev/urandom" );
read RANDOM, $spamkey, 4096;
close(RANDOM);
$spamkey =~ s/\W//g;
$spamkey = substr( $spamkey, 0, 24 );
open( SPAMKEY, ">${homedir}/.spamkey" );
chmod( 0600, "${homedir}/.spamkey" );
print SPAMKEY $spamkey;
close(SPAMKEY);
return ($spamkey);
}
}
}
sub checksa_deliver {
my ( $domain, $localpart, $received_protocol ) = @_;
my ($owner) = getdomainowner($domain);
my ($homedir) = gethomedir($owner);
my ($passwd) = "${homedir}/etc/${domain}/passwd";
my ($addressexists) = 0;
my ($spamkey) = getspamkey($owner);
my $headers = Exim::expand_string('$message_headers');
if ( $headers =~ /^X-Spam-Exim: ${spamkey}$/m ) {
return "no";
}
if ( $received_protocol eq "local-bsmtp" ) { return "no"; }
if ( -e $passwd ) {
open( PASSWD, ${passwd} );
while (<PASSWD>) {
if ( beginmatch( $_, "${localpart}:" ) ) { $addressexists = 1; }
}
close(PASSWD);
}
else {
return "no";
}
if ( $> == 0 ) {
my $waittime = 1;
while ( -e "${homedir}/.spamassassinquotatest" ) {
if ( $waittime == 60 ) { last; }
$waittime++;
sleep(1);
}
my $pid;
if ( !( $pid = fork() ) ) {
umask(0002);
&setuids($owner);
open( QUOTATEST, ">${homedir}/.spamassassinquotatest" );
print QUOTATEST " " x 4096;
close(QUOTATEST);
exit();
}
waitpid( $pid, 0 );
if ( !( ( stat("${homedir}/.spamassassinquotatest") )[7] == 4096 ) ) {
unlink("${homedir}/.spamassassinquotatest");
return "no";
}
unlink("${homedir}/.spamassassinquotatest");
}
if ( -e $homedir . "/.spamassassinenable" && $addressexists ) {
return "yes";
}
else {
return "no";
}
}
sub check_deliver {
my ( $domain, $localpart ) = @_;
my ($owner) = getdomainowner($domain);
my ($homedir) = gethomedir($owner);
my ($passwd) = "${homedir}/etc/${domain}/passwd";
my ($addressexists) = 0;
if ( -e $passwd ) {
open( PASSWD, ${passwd} );
while (<PASSWD>) {
if ( beginmatch( $_, "${localpart}:" ) ) { $addressexists = 1; }
}
close(PASSWD);
}
else {
return "no";
}
if ($addressexists) {
return "yes";
}
else {
return "no";
}
}
sub check_deliver_spam {
my ( $domain, $localpart ) = @_;
my ($owner) = getdomainowner($domain);
if ( $owner eq "root" ) { return "no"; }
my ($homedir) = gethomedir($owner);
my ($passwd) = "${homedir}/etc/${domain}/passwd";
my ($addressexists) = 0;
my ($isspam) = 0;
if ( !-e $homedir . "/.spamassassinboxenable" ) { return "no"; }
if ( -e $passwd ) {
open( PASSWD, ${passwd} );
while (<PASSWD>) {
if ( beginmatch( $_, "${localpart}:" ) ) { $addressexists = 1; }
}
close(PASSWD);
}
else {
return "no";
}
my $headers = Exim::expand_string('$message_headers');
if ( $headers =~ /^X-Spam-Status: Yes/m ) {
$isspam = 1;
}
if ( $addressexists && $isspam ) {
return "yes";
}
else {
return "no";
}
}
sub checkusersa {
my ( $owner, $received_protocol ) = @_;
if ( $owner eq "root" ) { return "no"; }
my ($homedir) = gethomedir($owner);
my ($spamkey) = getspamkey($owner);
my $headers = Exim::expand_string('$message_headers');
if ( $headers =~ /^X-Spam-Exim: ${spamkey}$/m ) {
return "no";
}
if ( $received_protocol eq "local-bsmtp" ) { return "no"; }
if ( $> == 0 ) {
my $waittime = 1;
while ( -e "${homedir}/.spamassassinquotatest" ) {
if ( $waittime == 60 ) { last; }
$waittime++;
sleep(1);
}
my $pid;
if ( !( $pid = fork() ) ) {
umask(0002);
&setuids($owner);
open( QUOTATEST, ">${homedir}/.spamassassinquotatest" );
print QUOTATEST " " x 4096;
close(QUOTATEST);
exit();
}
waitpid( $pid, 0 );
if ( !( ( stat("${homedir}/.spamassassinquotatest") )[7] == 4096 ) ) {
unlink("${homedir}/.spamassassinquotatest");
return "no";
}
unlink("${homedir}/.spamassassinquotatest");
}
if ( -e $homedir . "/.spamassassinenable" ) {
return "yes";
}
else {
return "no";
}
}
sub checkuserspambox {
my ($owner) = @_;
if ( $owner eq "root" ) { return "no"; }
my ($homedir) = gethomedir($owner);
my ($isspam) = 0;
my $headers = Exim::expand_string('$message_headers');
if ( $headers =~ /^X-Spam-Status: Yes/m ) {
$isspam = 1;
}
if ( -e $homedir . "/.spamassassinboxenable" && $isspam ) {
return "yes";
}
else {
return "no";
}
}
sub checkspam {
my $uid = Exim::expand_string('$originator_uid');
my $gid = Exim::expand_string('$originator_gid');
my $primary_hostname = Exim::expand_string('$primary_hostname');
my $sender = Exim::expand_string('$sender_address');
my $domain;
my $islocald = 0;
my @LD;
open( LD, "/etc/localdomains" );
@LD = <LD>;
close(LD);
#MAILTRAP
my $safegid = ( getgrnam("mailtrap") )[2];
if ( $uid >= 99 && $gid >= 99 && $safegid ne $gid && -e "/etc/eximmailtrap" ) {
die "Gid $gid is not permitted to relay mail";
}
#MAILTRAP
if ( $sender =~ /\@${primary_hostname}/ ) {
my $tuid = Exim::expand_string('${extract{2}{:}{${lookup passwd{$sender_address}{$value}}}}');
if ( $uid eq "0" and $tuid ne "0" ) {
$uid = $tuid;
}
$domain = getusersdomain( ( getpwuid($uid) )[0] );
$islocald = 1;
}
else {
my $sender_domain;
( undef, $sender_domain ) = split( /\@/, $sender );
$domain = $sender_domain;
foreach my $ldomain (@LD) {
$ldomain =~ s/\n//g;
if ( $domain eq $ldomain ) { $islocald = 1; }
}
my $tuser = getdomainowner($sender_domain);
$tuser =~ s/\\//g;
my $tuid = Exim::expand_string( '${extract{2}{:}{${lookup passwd{\N' . $tuser . '\N}{$value}}}}' );
if ( $uid eq "0" and $tuid ne "0" ) {
$uid = $tuid;
}
}
if ( int($uid) == 99 && -e '/etc/webspam' ) {
die "Mail sent by user nobody, UID 99, being discarded due to sender restrictions in WHM->Tweak Settings";
}
if ( isdemo($uid) ) {
die "Demo Accounts are not permitted to relay mail.";
}
my $headers = Exim::expand_string('$message_headers');
my $original_domain = Exim::expand_string('$original_domain');
my $sender_address_domain = Exim::expand_string('$sender_address_domain');
if ( !$islocald ) { return "yes"; }
#logsmtpbw here
my $now = time();
$domain =~ s/[^\w\.\-]//g;
#we just can't trust user input
my $message_size = Exim::expand_string('$message_size');
if ( $domain ne "" ) {
my $maxmails = 0;
open( CF, "/var/cpanel/cpanel.config" );
while (<CF>) {
next if (/^#/);
s/\n//g;
my ( $var, $value ) = split( /=/, $_ );
if ( $var eq "maxemailsperhour" ) {
$maxmails = int($value);
}
}
close(CF);
open( CPM, "/var/cpanel/maxemails" );
while (<CPM>) {
s/\n//g;
my ( $mdomain, $mmax ) = split(/=/);
if ( $mdomain eq $domain ) {
$maxmails = int($mmax);
}
}
close(CPM);
if ( $maxmails > 0 ) {
my $nummailsinhour = readbacktodate("/usr/local/apache/domlogs/$domain-smtpbytes_log");
if ( $nummailsinhour > $maxmails ) {
die "Domain $domain has exceeded the max emails per hour. Message discarded.\n";
}
}
open( DLOG, ">>/usr/local/apache/domlogs/$domain-smtpbytes_log" );
print DLOG "$now $message_size .\n";
close(DLOG);
chmod( 0640, "/usr/local/apache/domlogs/$domain-smtpbytes_log" );
}
#end logsmtpbw
if ( !( $uid == 99 ) ) {
#If it isn't the nobody user its ok
return "yes";
}
my ($receivedfor);
my @RECPS;
my @HEADERS = split( /\n/, $headers );
my ( $header, $email );
foreach $header (@HEADERS) {
if ( $header =~ /^to:/i ) {
my $line = $header;
$line =~ s/^to: //ig;
my @TRECPS = split( /[\,\;]/, $line );
foreach (@TRECPS) { push( @RECPS, $_ ); }
}
if ( $header =~ /^bcc:/i ) {
my $line = $header;
$line =~ s/^to: //ig;
my @TRECPS = split( /[\,\;]/, $line );
foreach (@TRECPS) { push( @RECPS, $_ ); }
}
if ( $header =~ /^cc:/i ) {
my $line = $header;
$line =~ s/^to: //ig;
my @TRECPS = split( /[\,\;]/, $line );
foreach (@TRECPS) { push( @RECPS, $_ ); }
}
if ( $header =~ /\tfor\s([^\;]+)/i ) {
$receivedfor = $1;
}
}
for ( my $i = 0; $i <= $#RECPS; $i++ ) {
if ( $RECPS[$i] =~ /\<(\S+)\>/ ) {
$RECPS[$i] = $1;
}
elsif ( $RECPS[$i] =~ /\((\S+)\)/ ) {
$RECPS[$i] = $1;
}
}
my $matchdomain = 0;
my $matchrecv = 0;
foreach my $ldomain (@LD) {
$ldomain =~ s/\n//g;
next if ( $ldomain !~ /\./ );
foreach my $recp (@RECPS) {
if ( $recp =~ /\@${ldomain}$/ ) {
$matchdomain = 1;
}
}
if ( $receivedfor =~ /\@${ldomain}$/ ) {
$matchrecv = 1;
}
}
if ( $receivedfor ne "" && $matchrecv == 0 && -e "/etc/webspam" ) {
die "you are not permitted to relay mail";
}
if ($matchdomain) { return "yes"; }
if ( -e "/etc/webspam" ) { die "you are not permitted to relay mail"; }
return "yes";
}
sub checkuserpass {
my ( $user, $pass, $shift ) = @_;
my ($domain);
my ( $owner, $homedir, $uid, $gid );
if ( $user eq "" || ( $user eq $pass && length($shift) > 0 ) ) { #netscape sucks!
$user = $pass;
$pass = $shift;
}
$user =~ s/[\+\%\/\:]/\@/g;
my $trueowner;
if ( $user =~ /\@/ ) {
( $user, $domain ) = split( /\@/, $user );
if ( $domain eq "" ) {
return "no";
}
$owner = getdomainowner($domain);
if ( $owner eq "" ) {
return "no";
}
$homedir = gethomedir($owner);
if ( $homedir eq "" || $homedir eq "/" ) {
return "no";
}
$owner =~ s/\\//g;
( undef, $uid, $gid ) = split( /:/, Exim::expand_string( '${lookup passwd{\N' . $owner . '\N}{$value}}' ) );
$trueowner = $owner;
}
else {
$user =~ s/\\//g;
( undef, $uid, $gid ) = split( /:/, Exim::expand_string( '${lookup passwd{\N' . $user . '\N}{$value}}' ) );
$trueowner = $user;
}
$trueowner =~ s/\///g;
$trueowner =~ s/\.\.//g;
if ( isdemo( ${trueowner} ) ) {
return ('no');
}
if ( checkpass( $user, $pass, $homedir, $domain ) ) {
return "yes";
}
else {
return "no";
}
}
sub checkpass {
my ( $user, $pass, $homedir, $domain ) = @_;
my ($cpass);
my ($retval) = 0;
if ( $pass eq "" ) { return (0); }
if ( -e "$homedir/etc/exim/authtab" ) {
open( SHADOW, "$homedir/etc/exim/authtab" );
}
else {
open( SHADOW, "$homedir/etc/${domain}/shadow" );
}
while (<SHADOW>) {
if ( beginmatch( $_, "$user:" ) ) {
( $user, $cpass, undef ) = split( /:/, $_, 3 );
if ( crypt( $pass, $cpass ) eq $cpass ) {
close(SHADOW);
return (1);
}
else {
close(SHADOW);
return (0);
}
}
}
close(SHADOW);
return (0);
}
sub getdomainowner {
my ($domain) = @_;
my ($user) = '';
open( USERDOMS, "/etc/userdomains" );
seek( USERDOMS, 0, 0 );
while (<USERDOMS>) {
s/\n//g;
if ( beginmatch( $_, "$domain: " ) ) {
/\S+:\s(\S+)/;
$user = $1;
last;
}
}
close(USERDOMS);
return $user;
}
sub gethomedir {
my ($user) = @_;
$user =~ s/\\//g;
return ( Exim::expand_string( '${extract{5}{:}{${lookup passwd{\N' . $user . '\N}{$value}}}}' ) );
}
sub isdemo {
my ($user) = @_;
if ( $user =~ /^\d+$/ ) {
$user = getpwuid($uid);
}
open( DEMOUSERS, "<", "/etc/demousers" );
my @DEMOUSERS = <DEMOUSERS>;
close(DEMOUSERS);
if ( grep( /^\Q${user}\E$/, @DEMOUSERS ) ) {
return (1);
}
return (0);
}
sub readbacktodate {
my ($filename) = @_;
my ($buf);
my ($filepos) = 0;
my $now = time();
my $onehourago = ( $now - ( 60 * 60 ) );
my ($hitcount) = 0;
my ( $dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks ) = stat($filename);
$filepos = ( $size - 4096 );
open( RF, "$filename" );
seek( RF, $filepos, 0 );
my $reachedend = 0;
while ( $filepos >= -4096 ) {
if ( $filepos < 0 ) {
read( RF, $buf, ( $filepos + 4096 ) );
}
else {
read( RF, $buf, 4096 );
}
if ( $filepos > 0 ) {
$buf =~ /([^\n]+\n)/;
$filepos += length($1);
$buf = substr( $buf, length($1) );
}
my @BUF = split( /\n/, $buf );
foreach ( reverse @BUF ) {
my ( $ttime, $tbytes ) = split(/ /);
if ( $ttime > $onehourago ) {
$hitcount++;
}
else {
$reachedend = 1;
last();
}
}
last if ($reachedend);
$filepos -= 4096;
if ( $filepos < 0 ) {
seek( RF, 0, 0 );
}
else {
seek( RF, $filepos, 0 );
}
}
close(RF);
return ($hitcount);
}
sub beginmatch {
my ( $haystack, $needle ) = @_;
$haystack =~ tr/[A-Z]/[a-z]/;
$needle =~ tr/[A-Z]/[a-z]/;
if ( substr( $haystack, 0, length($needle) ) eq $needle ) {
return (1);
}
return (0);
}
sub setuids {
my ($user) = $_[0];
my ( $uid, $gid );
$user =~ s/\\//g;
( undef, $uid, $gid ) = split( /:/, Exim::expand_string( '${lookup passwd{\N' . $user . '\N}{$value}}' ) );
if ( !( $( = int($gid) ) ) {
print "error setting gid\n";
exit;
}
if ( !( $) = "$gid $gid" ) ) {
print "error setting gid\n";
exit;
}
if ( !( ( $< = $uid ) && ( $> = $uid ) ) ) {
die "error setting uid ($uid) [$user]\n";
}
return $uid;
}
sub popbeforesmtpwarn {
my ($hostaddress) = @_;
if ( !-e "/etc/eximpopbeforesmtpwarning" ) {
return ();
}
my (@SENDERS);
open( RELAYHOSTS, "/etc/relayhostsusers" );
while (<RELAYHOSTS>) {
chomp();
my ( $rhost, $user ) = split( / /, $_ );
next if ( $rhost eq "" );
if ( $hostaddress eq $rhost ) {
push( @SENDERS, $user );
}
}
close(RELAYHOSTS);
if ( $#SENDERS > -1 ) {
return ( "X-PopBeforeSMTPSenders: " . join( ",", @SENDERS ) );
}
return ("");
}
sub mailtrapheaders {
my $primary_hostname = Exim::expand_string('$primary_hostname');
my $original_domain = Exim::expand_string('$original_domain');
my $sender_address_domain = Exim::expand_string('$sender_address_domain');
my $originator_uid = Exim::expand_string('$originator_uid');
my $originator_gid = Exim::expand_string('$originator_gid');
my $caller_uid = Exim::expand_string('$caller_uid');
my $caller_gid = Exim::expand_string('$caller_gid');
my $xsource = $ENV{'X-SOURCE'};
my $xsourceargs = $ENV{'X-SOURCE-ARGS'};
my $xsourcedir = maskdir( $ENV{'X-SOURCE-DIR'} );
my $headers =
"X-AntiAbuse: This header was added to track abuse, please include it with any abuse report\n"
. "X-AntiAbuse: Primary Hostname - $primary_hostname\n"
. "X-AntiAbuse: Original Domain - $original_domain\n"
. "X-AntiAbuse: Originator/Caller UID/GID - [$originator_uid $originator_gid] / [$caller_uid $caller_gid]\n"
. "X-AntiAbuse: Sender Address Domain - $sender_address_domain\n"
. "X-Source: ${xsource}\n"
. "X-Source-Args: ${xsourceargs}\n"
. "X-Source-Dir: ${xsourcedir}";
return ($headers);
}
sub maskdir {
my ($dir) = @_;
open( PASSWD, "/etc/passwd" );
while (<PASSWD>) {
my ( $homedir, $uid, $user );
( $user, undef, $uid, undef, undef, $homedir, undef ) =
split( /:/, $_ );
next if ( $uid < 100 );
next if ( length($homedir) < 3 );
if ( substr( $homedir, -1, 1 ) ne "/" ) { $homedir .= "/"; }
if ( beginmatch( ${dir}, ${homedir} ) ) {
my $maskeddir = $dir;
$maskeddir =~ s/^${homedir}//g;
$maskeddir = getusersdomain($user) . ":" . "/" . $maskeddir;
close(PASSWD);
return ($maskeddir);
}
}
close(PASSWD);
return ($dir);
}
sub getusersdomain {
my ($user) = @_;
open( USERDOMS, "/etc/trueuserdomains" );
seek( USERDOMS, 0, 0 );
while (<USERDOMS>) {
s/\n//g;
if ( endmatch( $_, " ${user}" ) ) {
/(\S+):/;
$domain = $1;
last;
}
}
close(USERDOMS);
return $domain;
}
sub endmatch {
my ( $haystack, $needle ) = @_;
$haystack =~ tr/[A-Z]/[a-z]/;
$needle =~ tr/[A-Z]/[a-z]/;
if ( substr( $haystack, -1 * length($needle) ) eq $needle ) {
return (1);
}
return (0);
}
if ( -e "/usr/share/amavis/amavis-filter" && !-e "/etc/noamavis" ) {
do '/usr/share/amavis/amavis-filter';
}
if ( -e "/etc/exim.pl.local" ) {
do '/etc/exim.pl.local';
}
1;
# The following notice referes to code below this line:
#
# "THE BEER-WARE LICENSE" (Revision 42):
# <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
# can do whatever you want with this stuff. If we meet some day, and you think
# this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
#
# based on Crypt::PasswdMD5
#
# bdraco@darkorb.net http://cpanel.net
sub checkpassword {
my ( $password, $cryptedpassword ) = @_;
if ( $cryptedpassword eq "" || $cryptedpassword =~ /^\!/ || $cryptedpassword =~ /^\*/ ) { return (0); }
loadmd5();
if ( $cryptedpassword =~ /^\$1\$(.+)\$.*/ && $hasmd5 ) {
my $salt = getsalt($cryptedpassword);
if ( unix_md5_crypt( $password, $salt ) eq $cryptedpassword ) {
return (1);
}
}
else {
if ( crypt( $password, $cryptedpassword ) eq $cryptedpassword ) {
return (1);
}
}
return (0);
}
sub unix_md5_crypt {
my $Magic = '$1$'; # Magic string
my ( $pw, $salt ) = @_;
my $passwd;
$salt =~ s/^\Q$Magic//; # Take care of the magic string if
# if present.
$salt =~ s/^(.*)\$.*$/$1/; # Salt can have up to 8 chars...
$salt = substr( $salt, 0, 8 );
my $ctx = new Digest::Perl::MD5; # Here we start the calculation
$ctx->add($pw); # Original password...
$ctx->add($Magic); # ...our magic string...
$ctx->add($salt); # ...the salt...
my ($final) = new Digest::Perl::MD5;
$final->add($pw);
$final->add($salt);
$final->add($pw);
$final = $final->digest;
for ( my $pl = length($pw); $pl > 0; $pl -= 16 ) {
$ctx->add( substr( $final, 0, $pl > 16 ? 16 : $pl ) );
}
# Now the 'weird' xform
for ( my $i = length($pw); $i; $i >>= 1 ) {
if ( $i & 1 ) { $ctx->add( pack( "C", 0 ) ); }
# This comes from the original version,
# where a memset() is done to $final
# before this loop.
else { $ctx->add( substr( $pw, 0, 1 ) ); }
}
$final = $ctx->digest;
# The following is supposed to make
# things run slower. In perl, perhaps
# it'll be *really* slow!
for ( my $i = 0; $i < 1000; $i++ ) {
my $ctx1 = new Digest::Perl::MD5;
if ( $i & 1 ) { $ctx1->add($pw); }
else { $ctx1->add( substr( $final, 0, 16 ) ); }
if ( $i % 3 ) { $ctx1->add($salt); }
if ( $i % 7 ) { $ctx1->add($pw); }
if ( $i & 1 ) { $ctx1->add( substr( $final, 0, 16 ) ); }
else { $ctx1->add($pw); }
$final = $ctx1->digest;
}
# Final xform
$passwd = '';
$passwd .= to64( int( unpack( "C", ( substr( $final, 0, 1 ) ) ) << 16 ) | int( unpack( "C", ( substr( $final, 6, 1 ) ) ) << 8 ) | int( unpack( "C", ( substr( $final, 12, 1 ) ) ) ), 4 );
$passwd .= to64( int( unpack( "C", ( substr( $final, 1, 1 ) ) ) << 16 ) | int( unpack( "C", ( substr( $final, 7, 1 ) ) ) << 8 ) | int( unpack( "C", ( substr( $final, 13, 1 ) ) ) ), 4 );
$passwd .= to64( int( unpack( "C", ( substr( $inal, 2, 1 ) ) ) << 16 ) | int( unpack( "C", ( substr( $final, 8, 1 ) ) ) << 8 ) | int( unpack( "C", ( substr( $final, 14, 1 ) ) ) ), 4 );
$passwd .= to64( int( unpack( "C", ( substr( $final, 3, 1 ) ) ) << 16 ) | int( unpack( "C", ( substr( $final, 9, 1 ) ) ) << 8 ) | int( unpack( "C", ( substr( $final, 15, 1 ) ) ) ), 4 );
$passwd .= to64( int( unpack( "C", ( substr( $final, 4, 1 ) ) ) << 16 ) | int( unpack( "C", ( substr( $final, 10, 1 ) ) ) << 8 ) | int( unpack( "C", ( substr( $final, 5, 1 ) ) ) ), 4 );
$passwd .= to64( int( unpack( "C", substr( $final, 11, 1 ) ) ), 2 );
$final = '';
return ( $Magic . $salt . '$' . $passwd );
}
sub to64 {
my $itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
my ( $v, $n ) = @_;
my $ret = '';
while ( --$n >= 0 ) {
$ret .= substr( $itoa64, $v & 0x3f, 1 );
$v >>= 6;
}
$ret;
}
sub getsalt {
my ($cpass) = @_;
( $cpass =~ /^\$1\$(.+)\$.*/ ) and return $1;
( $cpass =~ /^(..)*/ ) and return $1;
}
sub democheck {
my $uid = Exim::expand_string('$originator_uid');
if ( isdemo($uid) ) { return 'yes'; }
return 'no';
}
1;
@KyuuKazami