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