【问题标题】:LDAP in C/Go : Error code 53 "Server is unwilling to perfom" when trying to set unicodePwdC/Go 中的 LDAP:尝试设置 unicodePwd 时出现错误代码 53“服务器不愿执行”
【发布时间】:2016-01-10 22:49:06
【问题描述】:

所以我正在用 Go 编写一个程序,多亏了 CGo,我使用 C 绑定,并且我正在使用 ldap 来执行搜索、添加和修改操作。我可以做到这一切,但现在我试图在 unicodePwd mod_type 中设置密码,我似乎无法绕过错误 53:服务器不愿意执行。

我知道很多东西都会导致这个错误,所以: 我与ldaps有关。 为了测试目的,我硬编码了一个由 10 个字符组成的密码,开头和结尾都有双引号,并在 UTF-16LE、Base64 中得到了它。 密码有小写字母、大写字母和标点符号。

这是我的一些代码示例,我现在只是在测试一些东西,所以编码真的很糟糕:

设置选项:C.ldap_set_option(l, LDAP_OPT_PROTOCOL_VERSION, unsafe.Pointer(&version)) C.ldap_set_option(l, LDAP_OPT_REFERRALS, unsafe.Pointer(&v))

初始化:C.ldap_initialize(&l, C.CString("ldaps://**.**.**.**:636"))

绑定:rc := C.ldap_simple_bind_s(l, C.CString("CN=Administrator,CN=Users,DC=intra,DC=localdomain,DC=com"), C.CString("**********"))

现在是重要的部分,添加一个带密码的用户:

add_user(l, "ldaps://**.**.**.**", "636", "CN=Administrator,CN=Users,DC=intra,DC=localdomain,DC=com", "OU=*******,DC=intra,DC=localdomain,DC=com")

func add_user(l *C.LDAP, host string, port string, login string, container string) {

var mods [5]*C.LDAPModStr
var modClass, modCN, modSN, modPass C.LDAPModStr
var vclass [5]*C.char
var vcn [4]*C.char
var vsn [2]*C.char
var vpass [2]*C.char
modClass.mod_op = 0
modClass.mod_type = C.CString("objectclass")
vclass[0] = C.CString("top")
vclass[1] = C.CString("person")
vclass[2] = C.CString("organizationalPerson")
vclass[3] = C.CString("User")
vclass[4] = nil
modClass.mod_vals = &vclass[0]

modCN.mod_op = 0
modCN.mod_type = C.CString("cn")
vcn[0] = C.CString("john")
vcn[1] = nil
modCN.mod_vals = &vcn[0]

modSN.mod_op = 0
modSN.mod_type = C.CString("sn")
vsn[0] = C.CString("mclane")
vsn[1] = nil
modSN.mod_vals = &vsn[0]

modPass.mod_op = 0
modPass.mod_type = C.CString("unicodePwd")
vpass[0] = C.CString("IgBTAHcAZQBlAHQATgBlAHcAUAB3AGQAMQAyADMAIQAiAA==")
vpass[1] = nil
modPass.mod_vals = &vpass[0]

mods[0] = &modClass
mods[1] = &modCN
mods[2] = &modSN
mods[3] = &modPass
mods[4] = nil

dn := "cn=john,OU=*********,DC=intra,DC=localdomain,DC=com"

rc := C._ldap_add(l, C.CString(dn), &mods[0])

if rc != LDAP_SUCCESS {
    er := C.ldap_err2string(rc)
    fmt.Println("ADD ERROR")
    fmt.Println(rc)
    fmt.Println(C.GoString(er))
}

哦,这是 LDAPModStr 类型的定义:

typedef struct ldapmod_str {
    int  mod_op;
    char      *mod_type;
    char    **mod_vals;} LDAPModStr;

还有 _ldap_add :

int _ldap_add(LDAP *ld, char* dn, LDAPModStr **attrs){

            return ldap_add_ext_s(ld, dn, (LDAPMod **)attrs, NULL, NULL);
        }

我可能在这里遗漏了一些明显的东西,因为我对 GO 和 LDAP 有点陌生,但如果你能帮我解决这个问题,我将不胜感激。我不知道这是否相关,但程序连接到 Windows Server 2012 R2 的 Active Directory,它在虚拟机的同一台计算机上运行。另外我在这里有点新,我可以在这里发布我的所有代码,如果它对你来说更容易的话,但我认为只发布重要的步骤可能会更好。

【问题讨论】:

  • 您可能应该传递明文密码,如果您使用带有密码策略扩展的 OpenLDAP,您应该使用 modify-password 扩展操作,而不仅仅是属性更改。
  • 在我的代码中使用非编码密码也不起作用。至于您的其他建议,您的意思是在 shell 命令中使用 ldappasswd 吗?
  • @madraven,不,这是一些 LDAP 服务器支持的特殊类型的操作(例如“搜索”和“更新”)——请参阅 RFC 3062
  • @madraven,进一步谷歌搜索告诉我,我的建议可能完全没有抓住重点:AD 似乎不支持密码修改操作。 This post 处理关于特定属性的简单修改操作的特定于 AD 的缺陷。
  • @madraven,你不妨尝试另一条路线,而不是尝试使用 LDAP 与 AD 对话——MS 本身从未正式认可的技术——你可以尝试使用 WinAPI 来制作 MS 自己的东西以它喜欢的方式与 AD 交谈。比如说,NetUserChangePassword 来自 netapi32.dll 似乎很合适。当然,这只有在您的代码在 Windows 上运行时才有效。作为回报,要调用 WInAPI 函数,您不需要使用 cgo 这是 IMO 的胜利。

标签: c go ldap openldap


【解决方案1】:

我不知道是否有人会感兴趣,但我在 @kostix 的帮助下找到了一个解决方案,我想我会分享:C 中的扩展修改操作(使用 CGO)不起作用,但是一个简单的使用正确编码的 go-ldap 修改操作允许我在 Windows AD 上更改用户密码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多