sss_obfuscate revision 37ea8e70fa13ff9ba563300fb15de0e5e6185d68
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#!/usr/bin/python
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterfrom __future__ import print_function
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport sys
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterfrom optparse import OptionParser
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport pysss
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport SSSDConfig
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport getpass
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterdef parse_options():
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster parser = OptionParser()
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster parser.set_description("sss_obfuscate converts a given password into \
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster human-unreadable format and places it into \
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster appropriate domain section of the SSSD config \
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster file. The password can be passed in by stdin, \
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster specified on the command-line or entered \
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster interactively")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster parser.add_option("-s", "--stdin", action="store_true",
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster dest="stdin", default=False,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster help="Read the password from stdin.")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster parser.add_option("-d", "--domain",
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster dest="domain", default=None,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster help="The domain to use the password in (mandatory)",
327aca89813b3f887da682aa3c20dd3279e1c726Jonathan metavar="DOMNAME")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster parser.add_option("-f", "--file",
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster dest="filename", default=None,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster help="Set input file to FILE (default: Use system "
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster "default, usually /etc/sssd/sssd.conf)",
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster metavar="FILE")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (options, args) = parser.parse_args()
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return options, args
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterdef main():
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster options, args = parse_options()
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if not options:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print("Cannot parse options", file=sys.stderr)
327aca89813b3f887da682aa3c20dd3279e1c726Jonathan return 1
327aca89813b3f887da682aa3c20dd3279e1c726Jonathan
327aca89813b3f887da682aa3c20dd3279e1c726Jonathan if not options.domain:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print("No domain specified", file=sys.stderr)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return 1
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if not options.stdin:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster try:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster pprompt = lambda: (getpass.getpass("Enter password: "),
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster getpass.getpass("Re-enter password: "))
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster p1, p2 = pprompt()
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # Work around bug in Python 2.6
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if '\x03' in p1 or '\x03' in p2:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster raise KeyboardInterrupt
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster while p1 != p2:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print('Passwords do not match. Try again')
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster p1, p2 = pprompt()
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # Work around bug in Python 2.6
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if '\x03' in p1 or '\x03' in p2:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster raise KeyboardInterrupt
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster password = p1
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster except EOFError:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print('\nUnexpected end-of-file. Password change aborted',
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster file=sys.stderr)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return 1
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster except KeyboardInterrupt:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return 1
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster else:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster try:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster password = sys.stdin.read()
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster except KeyboardInterrupt:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return 1
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # Obfuscate the password
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster obfobj = pysss.password()
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster obfpwd = obfobj.encrypt(password, obfobj.AES_256)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # Save the obfuscated password into the domain
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster try:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster sssdconfig = SSSDConfig.SSSDConfig()
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster except IOError:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print("Cannot read internal configuration files.")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return 1
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster try:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster sssdconfig.import_config(options.filename)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster except IOError:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print("Permissions error reading config file")
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return 1
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster try:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster domain = sssdconfig.get_domain(options.domain)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster except SSSDConfig.NoDomainError:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print("No such domain %s" % options.domain)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return 1
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster try:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster domain.set_option('ldap_default_authtok_type', 'obfuscated_password')
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster domain.set_option('ldap_default_authtok', obfpwd)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster except SSSDConfig.NoOptionError:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print("The domain %s does not seem to support the required options"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster % options.domain)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return 1
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster sssdconfig.save_domain(domain)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster try:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster sssdconfig.write()
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster except IOError:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster # File could not be written
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster print("Could not write to config file. Check that you have the "
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster "appropriate permissions to edit this file.", file=sys.stderr)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return 1
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return 0
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterif __name__ == "__main__":
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ret = main()
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster sys.exit(ret)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster