如何在Linux下编码密码适配MS LWS的ldapadd ldiff文件?
针对Microsoft LWS(非AD)在Linux下创建用户及密码编码的问题
问题背景
- 操作环境:Linux下对接Windows服务器上的Microsoft LWS(标准LDAP实现,非AD域)
- 权限情况:绑定账户为LDAP管理员,可正常执行绑定、读取、单属性修改操作
- 核心问题:添加用户/person对象或修改密码时,openldap工具(
ldapmodify/ldapadd)及商用LDAP工具均报错
报错详情
- 当ldiff文件中
unicodePwd值带外层引号时:
ldapadd: invalid format (line 4) entry: "CN=test,CN=AppUsers,CN=NewCN,DC=CORP,DC=LOC"
对应ldiff内容:
dn: CN=test,CN=AppUsers,CN=NewCN,DC=CORP,DC=LOC changetype: modify replace: unicodePwd unicodePwd:: "IgBkAHMAZwBmAGsAagBoAGUAcgA0ADMAdABlADgAeQA4AFkAVABnAEkAOQA3ADgAMwA2ADQAJAAlACYAKgA1ADkAOAA3AGUAcgB5AHQAIgA="
- 当
unicodePwd值不带外层引号时:
ldap_add: Operations error (1) additional info: 00002077: SvcErr: DSID-033808AF, problem 5012 (DIR_ERROR), data 8237
核心疑问
- Microsoft LWS是否确实使用
unicodePwd而非userPassword属性? - 密码的引号应加在密码字符外还是ldiff的属性值外?
- 密码的准确编码格式是什么?尝试过UTF-16LE+Base64编码(含引号)、
{CRYPT}/{SSHA}格式均报错
已尝试的方法
- Python编码脚本(尝试UTF-16LE+Base64):
import argparse import base64 def utf16le_encode(password): """Convert the password to UTF-16LE encoding.""" quoted_password = f'"{password}"' return quoted_password.encode('utf-16le') def main(): parser = argparse.ArgumentParser(description='Convert a cleartext password to UTF-16LE and encode it in Base64 for Microsoft LDS.') parser.add_argument('password', type=str, help='The cleartext password to be encoded') args = parser.parse_args() utf16le_password = utf16le_encode(args.password) base64_encoded_password = base64.b64encode(utf16le_password).decode('utf-8') print("Base64 encoded password:", base64_encoded_password) if __name__ == "__main__": main()
- 尝试
{CRYPT}、{SSHA}格式编码,均触发相同DIR错误 - PowerShell可正常执行(但无法使用PowerShell):
$Userpwd = ConvertTo-SecureString "Pword_String123" -AsPlainText -Force New-ADUser -Server $server -Path $path -Name "$_.UPN" -AccountPassword $userpwd -UserPrincipalName $_.UPN -Enabled $True -DisplayName $_.displayName -EmailAddress $_.mail -country $_.country
解决方案
针对核心疑问的明确答案
- 属性选择:Microsoft LWS(包括AD LDS)确实使用
unicodePwd作为密码属性,而非OpenLDAP常用的userPassword,这是微软LDAP实现的标准要求。 - 引号位置:引号必须包含在密码的编码内容中,而非ldiff属性值的外层。即先把
"密码明文"(带双引号)进行编码,不能在Base64结果外再加引号。 - 编码格式:正确的编码流程为:
- 给明文密码前后加上双引号(例如:
"P@ssw0rd123") - 将带引号的字符串编码为UTF-16LE(小端序UTF-16)
- 对UTF-16LE字节流进行Base64编码
- 在ldiff中使用
unicodePwd::(两个冒号表示Base64编码值),后面直接跟编码结果,不要加额外引号
- 给明文密码前后加上双引号(例如:
修正后的Python编码脚本
import argparse import base64 def encode_unicode_pwd(password): # 给密码前后加双引号 quoted_pwd = f'"{password}"' # 编码为UTF-16LE utf16le_bytes = quoted_pwd.encode('utf-16le') # Base64编码并返回字符串 return base64.b64encode(utf16le_bytes).decode('utf-8') def main(): parser = argparse.ArgumentParser(description='生成Microsoft LWS/LDS可用的unicodePwd值') parser.add_argument('password', help='需编码的明文密码') args = parser.parse_args() print(encode_unicode_pwd(args.password)) if __name__ == "__main__": main()
正确的ldiff示例
修改密码场景
dn: CN=test,CN=AppUsers,CN=NewCN,DC=CORP,DC=LOC changetype: modify replace: unicodePwd unicodePwd:: IjBQAHAAcwBzAHcAMAAyADMANQAiAA==
创建新用户场景
dn: CN=test,CN=AppUsers,CN=NewCN,DC=CORP,DC=LOC objectClass: top objectClass: person objectClass: organizationalPerson objectClass: user cn: test sn: test givenName: Test userPrincipalName: test@corp.loc unicodePwd:: IjBQAHAAcwBzAHcAMAAyADMANQAiAA== enabled: TRUE
关键注意事项
- 操作密码相关属性时,LDAP连接必须使用LDAPS(LDAP over SSL)或STARTTLS,微软LDAP实现不允许在明文连接中修改
unicodePwd - 确保密码符合LWS的复杂度要求(虽已排除,仍需再次确认)
内容的提问来源于stack exchange,提问作者BrandonH
相关产品推荐
相关产品推荐

