check-root-password.py (1471B)
1 #!/usr/bin/env python 2 3 from __future__ import ( 4 generators, division, absolute_import, with_statement, print_function 5 ) 6 import sys 7 import os 8 import os.path 9 import pwd 10 import spwd 11 import crypt 12 import getpass 13 14 15 def execve(argv, env=None): 16 if env is None: 17 env = os.environ 18 if '/' in argv[0]: 19 os.execve(argv[0], argv, env) 20 else: 21 for p in os.environ['PATH'].split(os.path.pathsep): 22 try: 23 os.execve(os.path.join(p, argv[0]), argv, env) 24 except OSError: 25 continue 26 raise SystemExit(1) 27 28 29 def constant_time_compare(val1, val2): 30 """ 31 Returns True if the two strings are equal, False otherwise. 32 33 The time taken is independent of the number of characters that match. 34 35 For the sake of simplicity, this function executes in constant time only 36 when the two strings have the same length. It short-circuits when they 37 have different lengths. 38 """ 39 if len(val1) != len(val2): 40 return False 41 result = 0 42 for x, y in zip(val1, val2): 43 result |= ord(x) ^ ord(y) 44 return result == 0 45 46 47 def main(): 48 root_hash = spwd.getspnam('root').sp_pwd 49 root_pwent = pwd.getpwnam('root') 50 p = getpass.getpass() 51 if constant_time_compare(root_hash, crypt.crypt(p, root_hash)): 52 # OK 53 execve(sys.argv[1:]) 54 else: 55 sys.stderr.write("Incorrect password\n") 56 sys.exit(2) 57 58 59 if __name__ == '__main__': 60 sys.exit(main()) 61