You need to enable JavaScript to run this app. C++中如何借助Winldap.h获取域级属性maxPwdAge
优惠活动
大模型
产品
解决方案
定价
更多

C++中如何借助Winldap.h获取域级属性maxPwdAge

C++ 基于Winldap读取域级maxPwdAge属性的实现方案

核心问题定位

maxPwdAge属于域根对象的系统属性,不会作为属性挂载在单个用户条目下,因此之前遍历用户条目属性的操作永远无法获取到该值,必须定位到域对象本身执行读取。

具体实现步骤

1. 复用现有LDAP连接,获取域对象的可分辨名称(DN)

你已经可以正常读取用户条目,说明当前LDAP连接已经完成服务器绑定、权限校验流程,无需重新建立连接。
从已读取的用户条目上提取rootDomainNamingContext系统属性,该属性值即为域根对象的DN(例如DC=contoso,DC=com),这是最可靠的域DN获取方式,不需要手工拼接字符串:

// 从已获取的用户条目pUserEntry中读取域DN
PCHAR *pDomainDN = ldap_get_values(ldapConn, pUserEntry, "rootDomainNamingContext");
if (!pDomainDN || pDomainDN[0] == NULL) {
    // 处理域DN读取失败的逻辑
    return;
}

2. 对域根对象发起基础搜索

maxPwdAge存储在域根对象本身,因此搜索范围必须设置为LDAP_SCOPE_BASE(仅匹配目标DN对应的单个对象,不遍历子节点),搜索基地址传入上一步拿到的域DN,指定仅返回需要的maxPwdAge属性以提升效率:

LDAPMessage *pDomainSearchRes = NULL;
// 指定要返回的属性列表,以NULL结尾
PCHAR targetAttrs[] = {"maxPwdAge", NULL};
ULONG opRet = ldap_search_s(
    ldapConn,
    pDomainDN[0],       // 搜索基:域根DN
    LDAP_SCOPE_BASE,    // 搜索范围:仅目标对象本身
    "(objectClass=*)",  // 匹配规则(BASE范围下任意规则都可匹配到域根对象)
    targetAttrs,
    0,
    &pDomainSearchRes
);

3. 解析maxPwdAge的返回值

maxPwdAge是64位类型的系统属性,存储格式为AD标准的FILETIME100纳秒间隔值,需要通过ldap_get_values_len获取二进制返回值,再解析为对应数值,不能按普通字符串或32位整数处理:

if (opRet == LDAP_SUCCESS) {
    LDAPMessage *pDomainEntry = ldap_first_entry(ldapConn, pDomainSearchRes);
    if (pDomainEntry) {
        // 读取64位属性值,必须用len版本的接口获取berval二进制结构
        struct berval **pAgeVal = ldap_get_values_len(ldapConn, pDomainEntry, "maxPwdAge");
        if (pAgeVal && pAgeVal[0] != NULL) {
            LARGE_INTEGER liAge;
            // 将二进制内容拷贝到64位整数结构
            memcpy(&liAge, pAgeVal[0]->bv_val, sizeof(LARGE_INTEGER));
            // 特殊值判断:值为0或-9223372036854775808时代表域策略配置为密码永不过期
            if (liAge.QuadPart == 0 || liAge.QuadPart == LLONG_MIN) {
                // 处理密码永不过期的场景
            } else {
                // AD存储的maxPwdAge为负值,取绝对值换算为实际有效期
                ULONGLONG ullInterval100ns = (ULONGLONG)(-liAge.QuadPart);
                ULONGLONG ullTotalSeconds = ullInterval100ns / 10000000; // 1秒对应10^7个100纳秒间隔
                ULONGLONG ullValidDays = ullTotalSeconds / 86400; // 1天对应86400秒
                // 此处ullValidDays即为域配置的密码最大有效期
            }
        }
        // 释放属性值内存
        ldap_value_free_len(pAgeVal);
    }
    // 释放搜索结果内存
    ldap_msgfree(pDomainSearchRes);
}
// 释放域DN值内存
ldap_value_free(pDomainDN);

常见踩坑点

  • 不要尝试在用户条目的属性列表中查找maxPwdAge,该属性从设计上就不属于用户类的属性定义,遍历所有用户属性也无法获取
  • 搜索域根时必须使用LDAP_SCOPE_BASE范围,若使用全树或一级范围搜索,会产生大量冗余网络请求,严重降低性能
  • 该属性为64位长整型,禁止使用32位变量接收返回值,否则会出现数值截断、解析错误
  • AD存储的maxPwdAge默认是负值,这是协议设计约定而非数据错误,换算实际有效期时需要先取绝对值
  • 普通域用户默认拥有读取该域属性的权限,一般不需要额外申请特殊权限

内容的提问来源于stack exchange,提问作者PDTech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.01 10:36:09