#!/bin/bash # pmpass # poor man's pop authentication system for sendmail # version 20050402 # pmpass extracts IP addresses from todays's successful uw-imap POP3/IMAP logins # and adds them to access.db to allow relaying through sendmail # Installation: # Simply put pmpass in root's path (i.e. /usr/local/sbin) # Make sure pmpass is executable: # # chmod 700 /usr/local/sbin/pmpass # # Test it to make sure it works: # # pmpass --test # # Run it to verify that it is checking for new logins and updating access.db: # # pmpass # less /var/log/pmpass # # Install in root's crontab to continually check for new logins: # # */5 * * * * /usr/local/sbin/pmpass # Optionally, pmpass will search the log for strings in a restrictions file # (default=/etc/mail/pmpass_restrict), if that file exists. The file is used # by egrep, and may contain only one string per line, with no blank lines. # This can be used to restrict IP extraction to a short list of users or other # criteria (albeit in a fuzzy, sometimes unpredictable sort of way). In most # cases, this file is not necessary. # Set variables: # current maillog location MAILLOG="/var/log/maillog" # location of pmpass log PMPASS_LOG="/var/log/pmpass" # pmpass working directory: BASEDIR="/etc/mail" # access file ACCESS=$BASEDIR/access # IP addresses go into this file IPLIST=$BASEDIR/pmpass_ip # old IP list, used for diff IPLIST_OLD=$BASEDIR/pmpass_ip_old # list of authorized users RESTRICTIONLIST=$BASEDIR/pmpass_restrict # limit to today's successful logins # create today's date Apr 2 TODAY=$(date "+%b %e") # or use all successful logins in maillog regardless of date # TODAY="" # It is not normally necessary to edit below this line # create today's date as Tue Aug 28 15:30:07 EDT 2001 NOW=$(date) # Functions: usage () { USAGE="usage = `basename $0` [option]" printf "\n$USAGE\n\nOptions (use only one or none):\n" printf " (none) : extract IPs and rebuild access.db" printf " --force or -f: rebuild access.db with $IPLIST\n" printf " --test or -t: get & show IPs, without rebuilding access.db\n" printf " --version or -v: version info\n\n" printf " --help or -h: show help\n" } check_file () { # does the file exist if [ ! -e $1 ] then printf "\n$1 does not exist.\n\n" exit fi } extract_ips () { # Extract IP's from successful ipop3d or imapd logins (Login or Auth) # Don't use the Logout log line, because it is also created for failed logins # sort it, uniq it, unbracket IP's, egrep to make sure it's an IP, # remove loopback (127.0.0.1) from list to repress error message # tested with imap2000 ipop3d server, log line looks like this: # Sep 30 04:09:25 nexus ipop3d[247]: Login user=bob host=pool.foo.net [141.158.14.54] nmsgs=2/2 # logins from unresolvable hosts may look like this: # Sep 30 12:20:36 hq ipop3d[14187]: Login user=jenny host=[192.168.1.226] nmsgs=0/0 # NOTE: pmpass will not work for users with a space in their login awk '$5 ~ /ipop3d|imapd/ && $0 !~ /Logout/ && $6 ~ /Login|Auth/ && $9 ~ /\[[0-9]/ {print $9"\tRELAY"} \ $5 ~ /ipop3d|imapd/ && $0 !~ /Logout/ && $6 ~ /Login|Auth/ && $8 ~ /\[[0-9]/ {print substr($8, 6)"\tRELAY"}' \ | sort \ | uniq \ | sed -e 's/\[\|\]//g' \ | egrep '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' \ | grep -v '127\.0\.0\.1' } extract_lines () { # check for user list if [ -e ${RESTRICTIONLIST} ] then grep "$TODAY" ${MAILLOG} | egrep '(ipop3d|imapd)' | egrep -f ${RESTRICTIONLIST} else grep "$TODAY" ${MAILLOG} | egrep '(ipop3d|imapd)' fi } new_access_db () { # create new access.db # format your makemap command to suit your system # makemap will report duplicate IP's, but it still works echo "$NOW Generating new access.db..." >>$PMPASS_LOG cat $ACCESS $IPLIST | makemap hash $ACCESS 2>>$PMPASS_LOG } make_if_new () { # compare new list to the one last used, discard output diff $IPLIST $IPLIST_OLD >> /dev/null # if they differ (diff exit status not zero), create a new access.db if [ $? != 0 ] then new_access_db fi } # Begin: # create list of IP's if it doesn't exist if [ ! -e $IPLIST ] then touch $IPLIST echo "$NOW $IPLIST created." >> $PMPASS_LOG fi # check for arguments if [ $# -eq 0 ] then # if no arguments, check for new IPs # rotate IP list, we're making a new one mv $IPLIST $IPLIST_OLD extract_lines | extract_ips > $IPLIST make_if_new else # if arguments are present # if the first argument is... case $1 in --force | -f) # rebuild access.db echo "$NOW Using --force option..." >>$PMPASS_LOG new_access_db ;; --test | -t) # check installation, look at output to prove it's working check_file $ACCESS check_file $IPLIST check_file $MAILLOG grep "$TODAY" ${MAILLOG} | extract_lines | extract_ips ;; --version | -v) echo echo "pmpass 20050402" echo "April 2, 2005" echo "by Jorey Bump" echo "http://www.joreybump.com/" echo ;; *) # display usage for unknown arguments usage ;; esac fi # exit nicely exit 0