Commit de7f1a0c authored by jan.koester's avatar jan.koester
Browse files

test

parent c7081d1f
Loading
Loading
Loading
Loading
Loading
+25 −3
Changes for plugin/ad/ad.cpp: 25 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -1766,7 +1766,8 @@ LdapEntry ActiveDirectory::renderEntry(const dsdb::Entry &ent,
    }

    /* objectGUID is the record UUID (a separate Entry field, not in attrs):
     * synthesize it as the 16-byte binary GUID AD clients expect. Windows
     * synthesize it as the 16-byte binary GUID AD clients expect -- the
     * UUID's bytes as they are (network order), see buildRootDSE(). Windows
     * reads the domain/computer objectGUID during a join and rejects an entry
     * that lacks it (ERROR_INVALID_PARAMETER). */
    if (!ent.attrs.count("objectGUID") && wanted("objectGUID", findAttribute("objectGUID"))) {
@@ -1972,6 +1973,12 @@ LdapEntry ActiveDirectory::buildRootDSE() {
    e.addAttribute("supportedSASLMechanisms", std::vector<std::string>{"GSSAPI", "GSS-SPNEGO"});
    e.addAttribute("vendorName", "tuxist.de");
    e.addAttribute("vendorVersion", "FenrirDirectoryServer");
    /* Our objectGUIDs are the record UUIDs (RFC 9562 version 4) in network
     * byte order -- not a Windows GUID with Data1-3 little endian, though
     * Windows reads the same 16 bytes as one. FenrirOS members
     * (adconnect id_mapping: uuid) take them as the accounts' native UUID
     * ids only when this says so. */
    e.addAttribute("fenrirObjectGuidIsUuid", "TRUE");
    e.addAttribute("isSynchronized", "TRUE");
    e.addAttribute("supportedControl", std::vector<std::string>{
        "1.2.840.113556.1.4.319",   /* paged results */
@@ -2121,6 +2128,13 @@ bool ActiveDirectory::parseFilter(const uint8_t *data, size_t len, dsdb::Filter
/******************************************************************************
 * Add / Modify / Delete / ModifyDN
 *****************************************************************************/
/* objectSid and objectGUID are the server's: FenrirOS members map file
 * owners between them and the accounts' ids (adconnect SIDOF/IDOF), so a
 * client that could set them could take over another account's files. */
static bool serverOwnedAttr(const std::string &canon) {
    return dsdb::iequals(canon, "objectSid") || dsdb::iequals(canon, "objectGUID");
}

std::vector<uint8_t> ActiveDirectory::handleAddRequest(const uint8_t *content, size_t len,
                                                       int32_t msgId, LdapSession &session) {
    const uint8_t appResp = LdapBer::CLASS_APPLICATION | LdapBer::CONSTRUCTED | LDAP_ADD_RESPONSE;
@@ -2163,8 +2177,13 @@ std::vector<uint8_t> ActiveDirectory::handleAddRequest(const uint8_t *content, s
                while (voff < pl && LdapBer::parseTLV(pc, pl, voff, vt, vc, vl))
                    vals.emplace_back(reinterpret_cast<const char*>(vc), vl);
            }
            if (!type.empty())
                attrs[dsdb::canonicalName(type)] = std::move(vals);
            if (!type.empty()) {
                std::string canon = dsdb::canonicalName(type);
                if (serverOwnedAttr(canon))
                    return buildLdapMessage(msgId, appResp,
                                            buildLdapResult(LDAP_UNWILLING_TO_PERFORM, "", canon + " is set by the server"));
                attrs[canon] = std::move(vals);
            }
        }
    }

@@ -2267,6 +2286,9 @@ std::vector<uint8_t> ActiveDirectory::handleModifyRequest(const uint8_t *content
            if (type.empty())
                continue;
            std::string canon = dsdb::canonicalName(type);
            if (serverOwnedAttr(canon))
                return buildLdapMessage(msgId, appResp,
                                        buildLdapResult(LDAP_UNWILLING_TO_PERFORM, "", canon + " is set by the server"));

            if (dsdb::iequals(canon, "unicodePwd")) {
                if (!vals.empty()) {
+20 −2
Changes for src/dsdb/directory.cpp: 20 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ MatchContext Directory::matchContext() {
            Dn d;
            if (!Dn::parse(cur, d))
                continue;
            std::lock_guard<std::mutex> lk(_Mtx);
            /* search() holds _Mtx already (matchContext()'s only user) */
            Entry *e = findByDnLocked(d);
            if (!e)
                continue;
@@ -99,11 +99,23 @@ Entry *Directory::findByDnLocked(const Dn &dn) {
    return &_Entries[it->second];
}

/* objectGUID is the record UUID, not in the attribute map: a filter on it
 * (adconnect finds an account by its id this way) needs it added */
static bool mentionsGuid(const Filter &f) {
    if (iequals(f.attr, "objectGUID"))
        return true;
    for (auto &c : f.children)
        if (mentionsGuid(c))
            return true;
    return false;
}

void Directory::search(const Dn &base, int scope, const Filter &filter,
                       const std::function<bool(const Entry &)> &sink) {
    std::lock_guard<std::mutex> lk(_Mtx);
    ensureFresh();
    MatchContext ctx = matchContext();
    bool withGuid = mentionsGuid(filter);
    for (auto &e : _Entries) {
        bool inScope = false;
        switch (scope) {
@@ -113,7 +125,13 @@ void Directory::search(const Dn &base, int scope, const Filter &filter,
        }
        if (!inScope)
            continue;
        if (!matches(filter, e.attrs, ctx))
        if (withGuid) {
            AttrMap a = e.attrs;
            if (!a.count("objectGUID"))
                a["objectGUID"] = {std::string(reinterpret_cast<const char*>(e.objectGuid.value), 16)};
            if (!matches(filter, a, ctx))
                continue;
        } else if (!matches(filter, e.attrs, ctx))
            continue;
        if (!sink(e))
            return;
+1 −0
Changes for src/dsdb/directory.h: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ namespace fenrirds {
            /* next RID from the domain head's pool */
            uint32_t allocateRid();

            /* with _Mtx held: its callbacks look entries up unlocked */
            MatchContext matchContext();

        private: