哪些命令会改变开放目录密码?

我理解Open Directory是OpenLDAP + SASL(密码服务器)+ Kerberos。 看来,OpenLDAP按照SASL进行authentication; 我不知道Kerberos。

我想从脚本更改用户密码,最好是远程更改密码,我希望密码能够正确更改。 (也就是说,在任何情况下,我都不希望用户拥有不同的密码,具体取决于进入Open Directory的三种服务中的哪一种进行身份validation)。

我可以在没有绑定到目录的机器上通过networking执行dsimport ,但是当您尝试导入密码时(将AuthType设置为dsAuthMethodStandard:dsAuthClearText),只有当密码没有已经设置好了。 (我相信可以设置Crypt密码,但是我担心这意味着只有OD的LDAP部分才会知道当前密码。)

有没有什么我可以做短缺的服务器启动SSH会话,并在那里更改密码? 如果我这样做,是否有任何命令可以让我指定一个用户和他们的新密码在一行?

哪些命令可以改变所有打开的目录密码,有没有人喜欢?

apropos password给了我这些有趣的结果:

  • kpasswd(1) – 更改用户的Kerberos密码
  • ldappasswd(1) – 更改LDAP条目的密码
  • lppasswd(1) – 添加,更改或删除摘要密码
  • passwd(1) – 修改用户的密码
  • pwpolicy(8) – 获取并设置密码策略
  • saslpasswd2(8) – 设置用户的sasl密码
  • slappasswd(8) – OpenLDAP密码实用程序

我会看看一些手册页,我的印象是, pwpolicy是最好的select,但我很想知道是否有任何微妙的使用这些(例如,不要改变Kerberos密码,而不改变LDAP和SASL密码),如果没有SSH会话远程工作。

我遇到的最简单的答案是将passwd命令与dscl一起使用。 以下是交互式会话的输出(密码由星号代替):

 $ 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 

这是一个python脚本来进行更改。 您将需要pexpect模块( sudo easy_install pexpect应为您获得;我不认为您需要安装开发工具)。

 #!/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 

你可以使用它如下:

 # 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'] 

请记住,每个用户的login钥匙串上的密码通常与其开放目录密码保持同步。 Mac OS X足够聪明,可以使用在login窗口input的密码,不仅可以validation用户的身份,还可以解锁钥匙链。 如果这两个密码不同步,那么对于大多数用户来说这将是不方便和混乱的。

AFAIK,在服务器端更改OD密码的方法都不能修改用户的密钥链密码。 但是,AFP548的人们为这个问题创build了一个解决scheme,叫做Keychain Minder ,帮助那些陷入这种情况的用户。

尝试使用

 dscl -u xxxxxx -P xxxxxxx /LDAPv3/127.0.0.1/ -authonly username 

接着

 dscl -u diradmin -P xxxxx /LDAPv3/127.0.0.1/ -passwd Users/username newpassword 

这些命令可以从本地机器或远程机器运行。 远程客户端必须连接到目录实用程序中的目录。 来自授权机器的远程authentication检查看起来像

 dscl -u diradmin -P 123456 /LDAPv3/ldap.remote.com/ -authonly username 

我也用过

 dscl -u diradmin -P 123456 -url //LDAPv3/ldap.remote.com/ -authonly username 

这是我学到的一些有用的东西:

从OS X 10.5的命令行pipe理文档,第261页,“pipe理打开目录密码”:

pipe理打开目录密码

当用户帐户的密码types为Open Directory时,可以通过Kerberos或Open Directory Password Server对用户进行身份validation。 Kerberos是使用受信任服务器颁发的凭证的networkingauthentication系统。

开放目录密码服务器支持某些networking服务或用户的客户端应用程序需要的传统密码validation方法。 服务可以configuration为不允许Kerberos。 在这种情况下,他们使用密码服务器用户帐户与开放目录密码。

Kerberos和Open Directory Password Server都不将密码存储在用户的帐户中。 Kerberos和Open Directory Password Server都将密码存储在除目录域以外的安全数据库中,并且它们永远不允许读取密码。 密码只能设置和validation。

开放目录密码服务器

密码服务器使用标准的简单authentication和安全层(SASL)技术来协商客户端和服务之间的authentication方法。 Password Server支持多种authentication方式,包括APOP,CRAM-MD5,DHX,Digest-MD5,MS-CHAPv2,NTLMv1和NTLMv2,LAN Manager和WebDAV-Digest。

开放式目录还提供使用影子密码的validation服务,这些密码支持与密码服务器相同的validation方法。

关于使用ldappasswd ,命令行pipe理员文档进一步说明:

苹果推荐使用passwd而不是ldappasswd。 有关更多信息,请参见passwd手册页。

man passwd是指计算密码哈希值的OpenSSL工具。 要获得你真正想要的passwd命令的手册页, man /usr/share/man/man1/passwd.1.gz更有用。