The handiest answer I've come across is to use the passwd command in conjunction with dscl. Here is the output from an interactive session (with the passwords replaced by asterices):
$ 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
Here is a python script to make the changes. You will need the pexpect module (sudo easy_install pexpect
should get it for you; I don't think you need the dev tools installed).
#!/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
You can use it as follows:
# 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']
You can export security settings with:
secedit /export /cfg X:\new.cfg
Then you edit new.cfg (it is ini format) and change line "PasswordComplexity = 1" to "PasswordComplexity = 0". Apply it on Hyper-V server with:
secedit /configure /db C:\Windows\security\new.sdb /cfg X:\new.cfg /areas SECURITYPOLICY
You can find more details in this blog post.
Best Answer
You can indeed script out passwords from sql server 2000 and import them into sql server 2008 so that they are recognised as upper case passwords. Here's some background reading that will be useful in understanding sql server password hashes, so you can following along with the example.
SQL Server 2000 passwords were actually case insensitive as described in this rant. Even so, the sql server hashes store a case sensitive and case insensitive copy of the password, so that when you migrate password hashes to sql server 2005/2008 your passwords are then case sensitive.
To test this out, you can run the following on your SQL Server 2000 Server:
logging into SQL Server 2000 as usera works with 'PASSWORD' , even though it shouldn't. To migrate usera to SQL Server 2005/2008 we can use the following to copy the login keeping the sid & password hash:
You will get the following output (with different sid & hash of course):
What you can do is perform some 'processing' on the password hash before importing it into 2008 so that the second upper case hash overwrites the case sensitive hash. This will mean all your passwords are in upper case. Using the password has above, you can perform the following operation, which I've done here in t-sql:
using this @new_password as the @passwd parameter for sp_addlogin will mean the password is recognised as upper case!