#!/usr/local/bin/perl #Written by Nick #This script is meant to be called from Zachary Bedell's # qmail-smtpd chkusr patch located at # https://mail.adirondack.net/phpwebsite/index.php?module=pagemaster&PAGE_user_op=view_page&PAGE_id=20 # #For more information about my programming, or this script #Please visit my web site at http://illx.org #Currently, this script supports checking local system users #and users in Qmail's users/assign (which are 'virtual' users #but Qmail just turns them back into local users anyhow) #email address is our argument (lower-case it to be safe) my $email = lc($ARGV[0]); #PLEASE NOTE: The following files must be readable by this script: # /etc/passwd # /var/qmail/control/locals # /var/qmail/control/virtualdomains # /var/qmail/users/assign #exit 0 returns a failure (non-existant user in to qmail-smtpd) #exit 1 returns a success (the user exists, # and lets qmail-smtpd know its good) #exit 2 For an error generated by this program. # An error like this will generate a # 421 unable to verify recipient (#4.3.0) from qmail-smtpd #exit 0 if no email address given unless($email) { exit(0); } #split out the username and domain name my ($user,$domain) = split('@', $email); #exit 0 if the user or domain is not present unless($user or $domain) { exit(0); } #If /var/qmail/control/locals and #/var/qmail/control/virtualdomains don't exist, we #exit 2, because we check the locals file for /etc/passwd users #and we check the users/assign file for virtualdomain users unless(-e '/var/qmail/control/locals' && -e '/var/qmail/control/virtualdomains') { exit(2); } #First, check local users # open up the /var/qmail/control/locals file # and grab all of the domains # NOTE: I lower-case all data retrieved from the qmail files # just to be safe. my @locals = (); open(LOCALS, '/var/qmail/control/locals') or exit(2); while() { chomp; next unless $_; push(@locals, lc($_)); } close(LOCALS); # get our system users from /etc/passwd my @sysusers = (); open(PASSWD, '/etc/passwd') or exit(2); while() { chomp; next unless $_; my @fields = split(':', $_); push(@sysusers, lc($fields[0])); } close(PASSWD); # get our qmail alias users from /var/qmail/alias my @aliasusers = (); opendir(ALIASES, "/var/qmail/alias") or die "Unable to open the directory '/var/qmail/alias': $!\n"; while(my $file = readdir(ALIASES)) { next if $file eq '.'; next if $file eq '..'; next unless $file =~ /\.qmail-/; my @s = split('-', $file); push(@aliasusers, $s[1]); } closedir(ALIASES); # go through our system users for local domains foreach my $u (@sysusers) { if($u eq $user) { #our user exists, continue on to check local domain foreach my $d (@locals) { if($d eq $domain) { #our domain exists, they exist! exit(1); } } } } # go through our alias users for local domains foreach my $u (@aliasusers) { if($u eq $user) { #our user exists, continue on to check local domain foreach my $d (@locals) { if($d eq $domain) { #our domain exists, they exist! exit(1); } } } } # so they didn't exist in /etc/passwd, go on to check our virtualdomains #Second, check users against qmail's virtualdomains # grab our virtual domains my %virtdoms = (); open(VDS, '/var/qmail/control/virtualdomains') or exit(2); while() { chomp; next unless $_; my ($dom,$id) = split(':', $_); $dom = lc($dom); $id = lc($id); $virtdoms{$dom} = $id; } close(VDS); # then, grab all of our local qmail users my @qmailusers = (); open(ASSIGN, '/var/qmail/users/assign') or exit(2); while() { chomp; #strip off all spacesa $_ =~ s/\s//g; next unless $_; my @fields = split(':', $_); my @chars = split(//, $fields[0]); next if $chars[0] eq '+'; #we skip all wildcards (for now, maybe I'll get around to it) next if $chars[0] eq '.'; #skip the dot at the end #remove the first char shift(@chars); push(@qmailusers, lc(join('', @chars))); } close(ASSIGN); # go through all of the users, and see if they exist foreach my $qmu (@qmailusers) { #then, go through all the virtdomains per user, prepending the #extension on to the username to make it local, and check it against users/assign foreach my $dom (keys %virtdoms) { #get the prefix of the username my $userprefix = substr($qmu, 0, length($virtdoms{$dom})); #if we see our domain as part of the qmail user prepended domain if($virtdoms{$dom} eq $userprefix) { #get just the username from the qmail username my $uname = substr($qmu, length($virtdoms{$dom})+1, length($qmu)); #make a valid email address out of it my $em = "$uname\@$dom";; #if it matches, it exists in the users/assign if($em eq $email) { exit(1); } } } } #HERE, you could call vpopmail or vmailmgr if you wanted. #I've just covered the basics. #If we're here at the end, they didn't exist exit(0);