Draft sanity checker for smbpasswd

David Collier-Brown davecb at canada.sun.com
Tue Jul 24 16:27:33 GMT 2001


Kevin, can you check this out and sugegst additions?  You may have
to manually unfold lines folded in mail...

--dave

#!/bin/sh
#
# checksmbpasswd -- check the smb password file against /etc/passwd
#       and /etc/shadow. Reading smbpasswd requires running as root.
#       Developed on Solaris, may require fettling --dave c-b
#
#set -x
SMBPASSWD=/usr/local/samba/private/smbpasswd

#Shadow=0
Yp=0

main() {
        trap 'rm /tmp/$$.passwd' 0 1 2 3 4 5 6 7 8 9

        if [ $# -lt 1 ]; then
                say "checksmbpasswd: you must provide a file."
                say "Usage: checksmbpasswd [-y] file"
                exit 1
        fi

        while [ "$1" != "" ]; do
                case "$1" in
#               -s) # Include /etc/shadow
#                       Shadow=1
#                       ;;
                -y|-n) # Use YP/NIS
                        Yp=1
                        ;;
                -*) # oops
                        say "Unrecognized option \"$1\" ignored."
                        ;;
                *) # End of options
                        break
                        ;;
                esac
                shift
        done
        file="$1"

        compare $file
        check $file
}

#
# compare -- see if the file contains mismatches with /etc/passwd
#
compare() {
        file=$1

        # Get a safe copy of /etc/passwd and/or /etc/shadow
        getpass |\
        nawk -F: '{ 
                printf("%s:x:%s:%s:%s:%s:%s\n",$1,$3,$4,$5,$6,$7);
        }' |\
        sort |\
        sed -e '/^#/d' >/tmp/$$.passwd
        #cat /tmp/$$.passwd

        # Check lines
        linesInSmbpasswd=`cat $SMBPASSWD |sed -e '/^#/d' | wc -l`
        linesInPasswd=`cat /tmp/$$.passwd |sed -e '/^#/d' | wc -l`
        if [ "$linesInSmbpasswd" -gt "$linesInPasswd" ]; then
                say "Danger: more lines in smbpassword file than
passwd file."
        elif [ "$linesInSmbpasswd" -lt "$linesInPasswd" ]; then
                say "Note: more lines in passwd file than smbpassword
file (comm
on)."
        else
                say "Note: exactly $linesInSmbpasswd lines in smb and
passwwd fi
le."
                return
        fi

        # Show the mismatch(es).
        say "Lines in smbpasswd file missing from passwd file are:"
        comm -23 $SMBPASSWD /tmp/$$.passwd 1>&2
        say ""
        say "Lines in passwd file missing from smbpasswd file are:"
        comm -13 $SMBPASSWD /tmp/$$.passwd 1>&2
        say ""
}

#
# check -- see if the smbpasswd file is well-formed
#
check() {
        file=$1

        cat $file |\
        tr ' :' '_ ' |\
        while read name uid lanman nt flags lastchanged junk; do
                # say "$name $uid $lanman $nt $flags $lastchanged"

                # Name and uid must match unix.
                unixUid=`nawk -F: '$1 ~ /'$name'/ { print $3; exit}'
/tmp/$$.pas
swd`
                if [ "$uid" -ne "$unixUid" ]; then
                        say "Error: could not match ${name}'s uid in
the passwd 
file."
                fi

                echo $lanman |\
                 nawk '
                /.*/ {
                        len = length($1);
                        if (len != 32) {
                                print "Error: length of LanMAN hash
for " name \
                                        " was " len ", not 32."
                        }
                        if ($1 == "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
{
                                print "Warning: LanMAN hash for " name
\
                                        " was 32 Xs, a disabled
account."
                        }
                        if ($1 ~ /NO PASSWORD/) {
                                print "Warning: LanMAN hash for " name
\
                                        " was NO PASSWORD."
                        }
                }' name=$name


                # NT hash must be 32 hex digits
                echo $nt |\
                 nawk '
                /.*/ {
                        len = length($1);
                        if (len != 32) {
                                print "Error: length of NT hash for "
name \
                                        " was " len ", not 32."
                        }
                }' name=$name


                # flags are "[" 11 characters "]", limited to UNDW
                echo $flags |\
                nawk '
                /.*/ {
                        len = length($1);
                        if (len != 13) {
                                print "Error: length of flags for "
name \
                                        " was " len ", not 13."
                        }
                        user=index($1, "U");
                        no=index($1, "N");
                        disabled=index($1, "D");
                        wstrust=index($1, "W");

                        if (user != 0 && wstrust != 0) {
                                print "Error: flags for " name \
                                        "inlude both User and
Workstation-trust.
"
                        }
                        if (no != 0) {
                                print "Warning:  flags for " name \
                                        " include No-password"
                        }
                        if (disabled != 0) {
                                print "Warning:  flags for " name \
                                        " include Disabled"
                        }

                }' name=$name


                # Last-changed time; no checks yet.
        done
        say "$0: checking done"
        say

}

getpass() {
        if [ "$Yp" -eq 1 ]; then
                ypcat passwd
        else
                cat /etc/passwd 
        fi 
}

say() {
        echo "$*" 1>&2
}

main "$@"




More information about the samba-technical mailing list