A resposta mais útil que encontrei é usar o comando passwd em conjunto com dscl. Aqui está a saída de uma sessão interativa (com as senhas substituídas por asteriscos):
$ dscl -u diradmin -p ces
Password:
> cd /LDAPv3/127.0.0.1/
/LDAPv3/127.0.0.1 > auth diradmin *****
/LDAPv3/127.0.0.1 > passwd Users/Atwo807 *****
/LDAPv3/127.0.0.1 > passwd Users/Atwo249 *****
/LDAPv3/127.0.0.1 > passwd Users/doesnotexist foobar
passwd: Invalid Path
<dscl_cmd> DS Error: -14009 (eDSUnknownNodeName)
/LDAPv3/127.0.0.1 > exit
Goodbye
Aqui está um script python para fazer as alterações. Você precisará do módulo pexpect ( sudo easy_install pexpect
deve obtê-lo para você; não creio que você precise das ferramentas dev instaladas).
#!/usr/bin/env python
import pexpect
def ChangePasswords(host, path, diradmin, diradmin_password, user_passwords, record_type='Users'):
"""Changes passwords in a Open Directory or similar directory service.
host = the dns name or IP of the computer hosting the directory
path = the pathname to the directory (ex. '/LDAPv3/127.0.0.1')
diradmin = the directory administrator's shortname (ex. 'diradmin')
diradmin_password = the directory administrator's password
user_passwords = a dictionary mapping record names (typically, user's short
names) onto their new password
record_type = the sort of records you are updating. Typically 'Users'
Returns a tuple. The first entry is a list of all records (users) who
failed to update. The second entry is a list of all records (users)
who successfully updated.
"""
failed_list = []
succeeded_list = []
prompt = " > "
child = pexpect.spawn("dscl -u %s -p %s" % (diradmin, host))
if not (ReplyOnGoodResult(child, "Password:", diradmin_password) and
ReplyOnGoodResult(child, prompt, "cd %s" % path) and
ReplyOnGoodResult(child, prompt,
"auth %s %s" % (diradmin, diradmin_password)) and
ReplyOnGoodResult(child, prompt, None)):
print "Failed to log in and authenticate"
failed_list = user_passwords.keys()
return (failed_list, succeeded_list)
# We are now logged in, and have a prompt waiting for us
expected_list = [ pexpect.EOF, pexpect.TIMEOUT,
'(?i)error', 'Invalid Path', prompt ]
desired_index = len(expected_list) - 1
for record_name in user_passwords:
#print "Updating password for %s" % record_name,
child.sendline("passwd %s/%s %s" % (record_type, record_name,
user_passwords[record_name]))
if child.expect(expected_list) == desired_index:
#print ": Succeeded"
succeeded_list.append(record_name)
else:
#print ": Failed"
failed_list.append(record_name)
child.expect(prompt)
child.sendline("exit")
child.expect(pexpect.EOF)
return (failed_list, succeeded_list)
def ReplyOnGoodResult(child, desired, reply):
"""Helps analyze the results as we try to set passwords.
child = a pexpect child process
desired = The value we hope to see
reply = text to send if we get the desired result (or None for no reply)
If we do get the desired result, we send the reply and return true.
If not, we return false."""
expectations = [ pexpect.EOF, pexpect.TIMEOUT, '(?i)error', desired ]
desired_index = len(expectations) - 1
index = child.expect(expectations)
if index == desired_index:
if reply:
child.sendline(reply)
return True
else:
return False
Você pode usá-lo da seguinte maneira:
# This example assumes that you have named the script given above 'pwchange.py'
# and that it is in the current working directory
import pwchange
(failed, succeeded) = pwchange.ChangePasswords("ces", "/LDAPv3/127.0.0.1",
"diradmin", "******",
{ 'Atwo807' : '*****', 'Atwo249' : '*****',
'Nonexist' : 'foobar', 'Bad' : 'bad' })
print failed, succeeded
['Bad', 'Nonexist'] ['Atwo249', 'Atwo807']