RootDSE 中的 SearchRequest

SearchRequest in RootDSE

我必须使用以下函数从 AD 服务器查询用户:

public List<LDAPUserDTO> getUsersWithPaging(String filter)
{
    List<LDAPUserDTO> userList = new ArrayList<>();

    try(LDAPConnection connection = new LDAPConnection(config.getHost(),config.getPort(),config.getUsername(),config.getPassword()))
    {
        SearchRequest searchRequest = new SearchRequest("", SearchScope.SUB,filter, null);          
        ASN1OctetString resumeCookie = null;
        while (true)
        {
            searchRequest.setControls(
                    new SimplePagedResultsControl(100, resumeCookie));
            SearchResult searchResult = connection.search(searchRequest);
            for (SearchResultEntry e : searchResult.getSearchEntries())
            {
                LDAPUserDTO tmp = new LDAPUserDTO();
                tmp.distinguishedName = e.getAttributeValue("distinguishedName");
                tmp.name = e.getAttributeValue("name");
                userList.add(tmp);
            }

            LDAPTestUtils.assertHasControl(searchResult,
                    SimplePagedResultsControl.PAGED_RESULTS_OID);
            SimplePagedResultsControl responseControl =
                    SimplePagedResultsControl.get(searchResult);
            if (responseControl.moreResultsToReturn())
            {
                resumeCookie = responseControl.getCookie();
            }
            else
            {
                break;
            }
        }       
        return userList;
    } catch (LDAPException e) {
        logger.error(e.getExceptionMessage());
        return null;
    }


}

但是,当我尝试在 RootDSE 上搜索时,这会中断。

到目前为止我尝试过的:

baseDN = null
baseDN = "";
baseDN = RootDSE.getRootDSE(connection).getDN()
baseDN = "RootDSE"

全部导致各种异常或空结果:

Caused by: LDAPSDKUsageException(message='A null object was provided where a non-null object is required (non-null index 0). 

2020-04-01 10:42:22,902 ERROR [de.dbz.service.LDAPService] (default task-1272) LDAPException(resultCode=32 (no such object), numEntries=0, numReferences=0, diagnosticMessage='0000208D: NameErr: DSID-03100213, problem 2001 (NO_OBJECT), data 0, best match of:
    ''
 ', ldapSDKVersion=4.0.12, revision=aaefc59e0e6d110bf3a8e8a029adb776f6d2ce28')

您不能从 RootDSE 查询用户。

使用域,或者如果您需要查询林中跨域的用户,请使用全局目录(运行 在不同的端口上,而不是 LDAP 的默认 389 / 636。

RootDSE 仅包含元数据。可能应该在其他地方询问这个问题以获取更多信息,但首先阅读 Microsoft 的文档,例如:

例如:可以读取 namingContexts 属性以查找您可能想要为实际用户查询哪些其他上下文。

也许可以从这篇不错的文章开始介绍:

http://cbtgeeks.com/2016/06/02/what-is-rootdse/

所以,我真的花了很多时间在这上面。可以查询 RootDSE,但并不像某些人想象的那么直接。

我主要使用 WireShark 来查看 Softerra 的人用他们的 LDAP 浏览器做什么。

原来我并没有那么远:

如您所见,baseObject 此处为空。 此外,还有一个带有 OID LDAP_SERVER_SEARCH_OPTIONS_OID 和 ASN.1 字符串 308400000003020102 的附加控件。

那么这个 308400000003020102 更具可读性的是什么:30 84 00 00 00 03 02 01 02 实际上做了什么?

首先,我们将它解码成我们可以读取的东西 - 在这种情况下,这将是 int 2

在二进制中,这给了我们:0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0

正如我们从文档中了解到的,我们有以下表示法:

| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30    | 31    |
|---|---|---|---|---|---|---|---|---|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|-------|-------|
| x | x | x | x | x | x | x | x | x | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | x  | SSFPR | SSFDS |

或者我们只是从文档中获取 int 值:

  • 1 = SSFDS -> SERVER_SEARCH_FLAG_DOMAIN_SCOPE
  • 2 = SSFPR -> SERVER_SEARCH_FLAG_PHANTOM_ROOT

因此,在我的示例中,我们有 SSFPR 定义如下:

For AD DS, instructs the server to search all NC replicas except application NC replicas that are subordinate to the search base, even if the search base is not instantiated on the server. For AD LDS, the behavior is the same except that it also includes application NC replicas in the search. For AD DS and AD LDS, this will cause the search to be executed over all NC replicas (except for application NCs on AD DS DCs) held on the DC that are subordinate to the search base. This enables search bases such as the empty string, which would cause the server to search all of the NC replicas (except for application NCs on AD DS DCs) that it holds.

NC 代表 Naming Context,它们在 RootDSE 中存储为 Operational Attribute,名称为 namingContexts

另一个值,SSFDS 执行以下操作:

Prevents continuation references from being generated when the search results are returned. This performs the same function as the LDAP_SERVER_DOMAIN_SCOPE_OID control.

所以,有人可能会问我为什么要这样做。事实证明,我有一个客户在一个 DC 下有几个子 DC。如果我让搜索处理推荐,执行时间会非常长而且太长 - 因此这对我来说不是一个真正的选择。但是当我关闭它时,当我将 BaseDN 定义为我想要检索其成员的组时,我并没有得到所有结果。

通过 Softerra 的 LDAP 浏览器中的 RootDSE 选项进行搜索速度更快,并且在不到一秒的时间内返回结果。

我个人不知道为什么这样更快 - 但 ActiveDirectory 没有任何来自 Microsoft 的工具界面对我来说无论如何都是一种黑魔法。但坦率地说,那不是我的专业领域。

最后,我得到了以下 Java 代码:

SearchRequest searchRequest = new SearchRequest("", SearchScope.SUB, filter, null); 
[...]
Control globalSearch = new Control("1.2.840.113556.1.4.1340", true, new ASN1OctetString(Hex.decode("308400000003020102")));

searchRequest.setControls(new SimplePagedResultsControl(100, resumeCookie, true),globalSearch);
[...]

使用的Hex.decode()如下:org.bouncycastle.util.encoders.Hex.

非常感谢 Softerra 的工作人员,他们或多或少地结束了我进入 AD 深渊的旅程。