Created
August 15, 2012 20:54
-
-
Save glarizza/3363581 to your computer and use it in GitHub Desktop.
Setting the password in 10.7 by editing the plist
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'puppet' | |
| require 'facter/util/plist' | |
| require 'stringio' | |
| require 'base64' | |
| def convert_xml_to_binary(plist_data) | |
| # This method will accept a hash that has been returned from Plist::parse_xml | |
| # and convert it to a binary plist (string value). | |
| Puppet.debug('Converting XML plist to binary') | |
| Puppet.debug('Executing: \'plutil -convert binary1 -o - -\'') | |
| IO.popen('plutil -convert binary1 -o - -', mode='r+') do |io| | |
| io.write Plist::Emit.dump(plist_data) | |
| io.close_write | |
| @converted_plist = io.read | |
| end | |
| @converted_plist | |
| end | |
| def convert_binary_to_xml(plist_data) | |
| # This method will accept a binary plist (as a string) and convert it to a | |
| # hash via Plist::parse_xml. | |
| Puppet.debug('Converting binary plist to XML') | |
| Puppet.debug('Executing: \'plutil -convert xml1 -o - -\'') | |
| IO.popen('plutil -convert xml1 -o - -', mode='r+') do |io| | |
| io.write plist_data | |
| io.close_write | |
| @converted_plist = io.read | |
| end | |
| Puppet.debug('Converting XML values to a hash.') | |
| @plist_hash = Plist::parse_xml(@converted_plist) | |
| @plist_hash | |
| end | |
| def write_password_to_users_plist(users_plist, value) | |
| shadow_hash_data = get_shadow_hash_data(users_plist) | |
| set_salted_sha512(users_plist, shadow_hash_data, value) | |
| end | |
| def get_shadow_hash_data(users_plist) | |
| if users_plist['ShadowHashData'] | |
| password_hash_plist = users_plist['ShadowHashData'][0].string | |
| convert_binary_to_xml(password_hash_plist) | |
| else | |
| false | |
| end | |
| end | |
| def set_salted_sha512(users_plist, shadow_hash_data, value) | |
| shadow_hash_data = Hash.new unless shadow_hash_data | |
| shadow_hash_data['SALTED-SHA512'].string = Base64.decode64([[value].pack("H*")].pack("m").strip) | |
| binary_plist = convert_xml_to_binary(shadow_hash_data) | |
| users_plist['ShadowHashData'][0].string = binary_plist | |
| write_users_plist_to_disk(users_plist) | |
| end | |
| def users_plist_dir | |
| '/var/db/dslocal/nodes/Default/users' | |
| end | |
| def write_users_plist_to_disk(users_plist) | |
| puts users_plist | |
| puts "#{users_plist_dir}/#{@resource}.plist" | |
| Plist::Emit.save_plist(users_plist, "#{users_plist_dir}/#{@resource}.plist") | |
| `/usr/bin/plutil -convert binary1 "#{users_plist_dir}/#{@resource}.plist` | |
| # Restart directoryservices or opendirectoryd | |
| # OR dscacheutil -cachedump | |
| # OR sleep 5 | |
| end | |
| def get_attribute_from_dscl(path, keyname) | |
| # Perform a dscl lookup at the path specified for the specific keyname | |
| # value. The value returned is the first item within the array returned | |
| # from dscl | |
| puts "/usr/bin/dscl -plist . read /#{path}/#{@resource} #{keyname}" | |
| Plist.parse_xml(`/usr/bin/dscl -plist . read /#{path}/#{@resource} #{keyname}`) | |
| end | |
| def get_embedded_binary_plist(shadow_hash_data) | |
| # The plist embedded in the ShadowHashData key is a binary plist. The | |
| # facter/util/plist library doesn't read binary plists, so we need to | |
| # extract the binary plist, convert it to XML, and return it. | |
| embedded_binary_plist = Array(shadow_hash_data['dsAttrTypeNative:ShadowHashData'][0].delete(' ')).pack('H*') | |
| convert_binary_to_xml(embedded_binary_plist) | |
| end | |
| def get_salted_sha512(embedded_binary_plist) | |
| # The salted-SHA512 password hash in 10.7 is stored in the 'SALTED-SHA512' | |
| # key as binary data. That data is extracted and converted to a hex string. | |
| embedded_binary_plist['SALTED-SHA512'].string.unpack("H*")[0] | |
| end | |
| @resource = 'jeff' | |
| value = "7ea7d592131f57b2c8f8bdbcec8d9df12128a386393a4f00c7619bac2622a44d451419d11da512d5915ab98e39718ac94083fe2efd6bf710a54d477f8ff735b12587192d" | |
| ## Get the password | |
| shadow_hash_data = get_attribute_from_dscl('Users', 'ShadowHashData') | |
| embedded_binary_plist = get_embedded_binary_plist(shadow_hash_data) | |
| the_password = get_salted_sha512(embedded_binary_plist) | |
| ## Set the password | |
| users_plist = Plist::parse_xml(`plutil -convert xml1 -o /dev/stdout /var/db/dslocal/nodes/Default/users/jeff.plist`) | |
| write_password_to_users_plist(users_plist, value) | |
| ## Get the password again | |
| shadow_hash_data = get_attribute_from_dscl('Users', 'ShadowHashData') | |
| embedded_binary_plist = get_embedded_binary_plist(shadow_hash_data) | |
| the_password = get_salted_sha512(embedded_binary_plist) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment