如何通过LDAP架构判断AD对象属性是否可修改(LDAP C++)
判断Active Directory属性是否可修改的LDAP C++实现方法
以下是几种可行的方案,帮你提前识别不可修改的AD属性:
1. 解析属性架构的searchFlags和systemFlags标记
通过查询属性的架构对象,结合两个关键属性的标记来判断:
- 构造属性判定:如果
systemFlags包含0x40000000(对应ADS_SYSTEMFLAG_ATTR_IS_CONSTRUCTED),这类属性是AD动态生成的(比如memberOf),无法手动修改。 - 只读属性判定:如果
searchFlags包含0x00000004(对应ADS_FLAG_ATTR_READONLY),AD会直接标记该属性为只读,任何用户都无法修改。 - 系统维护属性:
systemFlags包含0x10000000(对应ADS_SYSTEMFLAG_ATTR_IS_SYSTEM)的属性多为AD核心维护的属性(比如objectGUID、objectSID),这类属性即使是管理员也无法修改,可结合前两个标记进一步确认。
C++查询架构对象示例
// 初始化LDAP连接并绑定 LDAP* ld = ldap_init("domain controller address", LDAP_PORT); ldap_simple_bind_s(ld, "admin DN", "password"); // 属性架构对象的DN格式:CN=属性名,CN=Schema,CN=Configuration,DC=domain,DC=com const char* attrSchemaDN = "CN=objectGUID,CN=Schema,CN=Configuration,DC=contoso,DC=com"; char* attrs[] = {"searchFlags", "systemFlags", NULL}; LDAPMessage* result; int rc = ldap_search_s(ld, attrSchemaDN, LDAP_SCOPE_BASE, "(objectClass=attributeSchema)", attrs, 0, &result); if (rc == LDAP_SUCCESS) { LDAPMessage* entry = ldap_first_entry(ld, result); if (entry) { // 获取searchFlags值 char** searchFlagsVals = ldap_get_values(ld, entry, "searchFlags"); if (searchFlagsVals && searchFlagsVals[0]) { unsigned long searchFlags = strtoul(searchFlagsVals[0], NULL, 10); if (searchFlags & 0x00000004) { printf("属性为只读,不可修改\n"); } ldap_value_free(searchFlagsVals); } // 获取systemFlags值 char** systemFlagsVals = ldap_get_values(ld, entry, "systemFlags"); if (systemFlagsVals && systemFlagsVals[0]) { unsigned long systemFlags = strtoul(systemFlagsVals[0], NULL, 10); if (systemFlags & 0x40000000) { printf("属性为构造属性,不可修改\n"); } if (systemFlags & 0x10000000) { printf("属性为系统维护属性,大概率不可修改\n"); } ldap_value_free(systemFlagsVals); } } ldap_msgfree(result); } ldap_unbind(ld);
2. 直接检查当前用户的属性写入权限
使用LDAP的ldap_check_access函数,提前验证当前绑定用户是否拥有目标属性的写入权限,这是最准确的方法之一,能覆盖架构标记之外的权限限制(比如组策略限制的属性)。
C++权限检查示例
LDAP* ld = ldap_init("domain controller address", LDAP_PORT); ldap_simple_bind_s(ld, "current user DN", "password"); const char* targetObjectDN = "CN=TestUser,OU=Users,DC=contoso,DC=com"; const char* targetAttr = "objectGUID"; // 检查写入权限(LDAP_CONTROL_ACCESS_REQUEST对应写入操作) int rc = ldap_check_access(ld, targetObjectDN, targetAttr, LDAP_CONTROL_ACCESS_REQUEST, NULL, NULL, NULL); if (rc == LDAP_INSUFFICIENT_ACCESS || rc == LDAP_UNWILLING_TO_PERFORM) { printf("无该属性的写入权限,不可修改\n"); } else if (rc == LDAP_SUCCESS) { printf("拥有写入权限,属性可修改\n"); } ldap_unbind(ld);
3. 模拟修改捕获错误
如果前两种方法无法覆盖所有场景,可以尝试对属性执行一次空修改或测试值修改,捕获LDAP错误码来判断:
- 返回
LDAP_INSUFFICIENT_ACCESS(错误码50):权限不足 - 返回
LDAP_UNWILLING_TO_PERFORM(错误码53):AD拒绝修改该属性 - 返回
LDAP_CONSTRAINT_VIOLATION(错误码19):属性值不符合约束(也可能表示不可修改)
这种方法虽然直接,但会产生AD操作日志,适合对准确性要求极高的场景。
内容的提问来源于stack exchange,提问作者Vivank Sharma
相关产品推荐
相关产品推荐

