1#! /bin/sh
2#
3# nasty:
4# Simple virtual-domains authentication with auth_other. Also, the World's
5# Worst Bourne Shell Script.
6#
7# Mailspools live under /var/spool/mail/SERVERS/domain/user; users are
8# authenticated against a password file in /etc/mail/SERVERS/domain/passwd,
9# which is in the format username:password hash; the password hash is the
10# cksum(1) of the password.
11#
12# Thanks to Rick Leeming and Richard Smith for perpetrating the first part of
13# this deranged monstrosity.
14#
15# This script should not be used for any purpose whatsoever, with the possible
16# exception of scaring people who are afraid of the shell.
17#
18# $Id$
19#
20
21VCONF=/etc/mail/SERVERS             # where password files live
22VSPOOL=/var/spool/mail/SERVERS      # where spools live
23VUSER=mail                          # user and group to use
24VGROUP=mail
25
26# Get the parameters. You are not expected to understand this.
27IFS=
28eval `
29while true ; do
30    a=@
31    while [ "$a" ] ; do
32        tmp=\`echo @ | dd ibs=1 obs=1 count=1 2>/dev/null; dd ibs=1 obs=1 count=1  2>/dev/null; echo @ | dd ibs=1 obs=1 count=1 2>/dev/null\`
33        if [ x"$tmp" = x"@" -o "$tmp" = x"@@" ] ; then
34            break
35        fi
36        a="$a$tmp"
37    done
38
39    if [ "$a" = @ ] ; then
40        break
41    fi
42
43    a=\`echo $a | sed 's/@\\(.\\)@/\\1/g;s/^@//;s/@$//;s/\\"/\\\\"/g'\`
44
45    b=@
46    while [ "$b" ] ; do
47        tmp=\`echo @ | dd ibs=1 obs=1 count=1 2>/dev/null; dd ibs=1 obs=1 count=1  2>/dev/null; echo @ | dd ibs=1 obs=1 count=1 2>/dev/null\`
48        if [ x"$tmp" = x"@" -o "$tmp" = x"@@" ] ; then
49            break
50        fi
51        b="$b$tmp"
52    done
53    b=\`echo $b | sed 's/@\\(.\\)@/\\1/g;s/^@//;s/@$//;s/\\"/\\\\"/g'\`
54
55    echo auth_other_$a=\\"$b\\"
56done
57`
58
59# Replacement for echo -n, for systems which don't have it
60function echo_n {
61    echo $1 | tr -d '\n'
62}
63
64# Send a \0
65function charzero {
66    dd if=/dev/zero ibs=1 obs=1 count=1 2> /dev/null
67}
68
69# Send back a failure message
70function refuse_authentication {
71    echo_n "result"
72    charzero
73    echo_n "NO"
74    charzero
75    echo_n logmsg
76    charzero
77    echo_n $1
78    charzero
79    charzero
80}
81
82# OK, at this stage, we should have some auth_other_... variables
83if [ x"$auth_other_method" = x"APOP" ] ; then
84    # no APOP support
85    refuse_authentication "APOP not supported"
86elif [ x"$auth_other_method" = x"PASS" ] ; then
87    # OK, we should be authenticating user@domain here
88    domain=`echo $auth_other_user | sed 's/^[^@!%]\+[@!%]//' | tr -d '/'`
89    local_part=`echo $auth_other_user | sed 's/^\([^@!%]\+\).*/\1/'`
90
91    if [ -e "$VCONF/$domain/passwords" ] ; then
92        # Look up the user's password
93        pwentry=`grep "^$local_part:" "$VCONF/$domain/passwords"`
94        if [ x"$pwentry" = x"" ] ; then
95            refuse_authentication "unknown user $local_part@$domain"
96        else
97            # Calculate hash of user's password
98            hash=`echo_n $auth_other_password | cksum | sed 's/ [0-9]+$//'`
99            if [ x"$pwentry" = x"$local_part:$hash" ] ; then
100                # OK, success; return a suitable packet of data to the server.
101                echo_n result
102                charzero
103                echo_n YES
104                charzero
105                echo_n uid
106                charzero
107                echo_n $VUSER
108                charzero
109                echo_n gid
110                charzero
111                echo_n $VGROUP
112                charzero
113                echo_n mboxtype
114                charzero
115                echo_n bsd
116                charzero
117                echo_n mailbox
118                charzero
119                echo_n $VSPOOL/$domain/$local_part
120                charzero
121                charzero
122            else
123                refuse_authentication "wrong password for $local_part@$domain"
124            fi
125        fi
126    else
127        # We don't know about this domain
128        refuse_authentication "unknown domain $domain"
129    fi
130fi
131
132# Re-exec script to handle another request.
133exec $0
134