#!/usr/bin/python # check password quality using cracklib given a new password, optionally the # old password, and a list of ldap/gecos words via stdin, each on a line by # itself (send an empty line if you want to skip the old password check) # Copyright (c) 2008 Peter Palfrader import sys, tempfile, os import cracklib def cleanup(dir): if not dir.startswith('/tmp/pwcheck-'): raise ValueError, 'cleanup got a weird dir to remove: '+dir for f in 'dict.hwm dict.pwd dict.pwi wordlist wordlist-cleaned'.split(' '): p = dir+'/'+f if os.path.exists(p): os.remove(p) if os.path.exists(dir): os.rmdir(dir) crack_mkdict = None crack_packer = None for b in "/usr/sbin/crack_mkdict /usr/sbin/cracklib-format".split(' '): if os.path.exists(b): crack_mkdict = b break for b in "/usr/sbin/crack_packer /usr/sbin/cracklib-packer".split(' '): if os.path.exists(b): crack_packer = b break if crack_mkdict is None or crack_packer is None: print "Could not find crack formater or packer" sys.exit(1) newpass = sys.stdin.readline().strip() oldpass = sys.stdin.readline().strip() ldapwords = map( lambda x: x.strip(), sys.stdin.readlines()) if oldpass == "": oldpass = None cracklib.min_length = 11 # check against the default dictionary try: cracklib.VeryFascistCheck(newpass, oldpass, '/var/cache/cracklib/cracklib_dict') except ValueError, e: print e sys.exit(1) # and against a dictionary created from the ldap info on this user if len(ldapwords) > 0: # squeeze's cracklib-packer complains about '*' on input - it # says 'skipping line: 1' while '-' in ldapwords: ldapwords.remove('-') while '*' in ldapwords: ldapwords.remove('*') tmpdir = tempfile.mkdtemp('', 'pwcheck-') F = open(tmpdir+'/wordlist', "w") for w in ldapwords: F.write(w+"\n"); for w1 in ldapwords: for w2 in ldapwords: F.write(w1+w2+"\n"); F.write(w1[0]+w2+"\n"); F.close() r = os.system(crack_mkdict+" "+tmpdir+"/wordlist > "+tmpdir+"/wordlist-cleaned") if r != 0: print "crack_mkdict returned non-zero exit status %d."%(r) cleanup(tmpdir) sys.exit(1) r = os.system(crack_packer+" "+tmpdir+"/dict < "+tmpdir+"/wordlist-cleaned > /dev/null") if r != 0: print "crack_packer returned non-zero exit status %d."%(r) cleanup(tmpdir) sys.exit(1) try: cracklib.VeryFascistCheck(newpass, None, tmpdir+"/dict") except ValueError, e: print "ldap data based check: "+str(e) cleanup(tmpdir) sys.exit(1) cleanup(tmpdir) sys.exit(0)