Commit 941093c6 authored by jan.koester's avatar jan.koester
Browse files

test

parent 03f79295
Loading
Loading
Loading
Loading
Loading
+48 −0
Changes for plugin/ad/ad.cpp: 48 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -2314,12 +2314,50 @@ std::vector<uint8_t> ActiveDirectory::handleAddRequest(const uint8_t *content, s
            attrs["objectSid"] = {d->meta.sid.withRid(rid).binary()};
        }
        d->dir->create(dn, attrs, sec.get());
        if (auto *mem = dsdb::get(attrs, "member"))
            syncMemberOf(*d->dir, dn.str(), {}, *mem);
    } catch (std::exception &e) {
        return buildLdapMessage(msgId, appResp, buildLdapResult(LDAP_OTHER, "", e.what()));
    }
    return buildLdapMessage(msgId, appResp, buildLdapResult(LDAP_SUCCESS, "", ""));
}

namespace {
    std::string dnKey(const std::string &s) {
        dsdb::Dn d;
        return dsdb::Dn::parse(s, d) ? d.key() : dsdb::lower(s);
    }
    /* add/remove `dnStr` in attribute `attr` of the object at `target` */
    void editLink(dsdb::Directory &dir, const std::string &target, const char *attr,
                  const std::string &dnStr, bool add) {
        dsdb::Dn tdn;
        if (!dsdb::Dn::parse(target, tdn)) return;
        auto e = dir.byDn(tdn);
        if (!e) return;
        dsdb::Values v = e->get(attr) ? *e->get(attr) : dsdb::Values{};
        std::string k = dnKey(dnStr);
        auto it = std::find_if(v.begin(), v.end(), [&](const std::string &x) { return dnKey(x) == k; });
        if (add == (it != v.end())) return;
        if (add) v.push_back(dnStr); else v.erase(it);
        dsdb::AttrMap a;
        a[attr] = v;
        try { dir.modify(e->objectGuid, a, nullptr, true); } catch (...) {}
    }
    /* keep member.memberOf in step with a group's member list, as AD's
     * linked attributes do (Kerberos PACs are built from memberOf) */
    void syncMemberOf(dsdb::Directory &dir, const std::string &groupDn,
                      const dsdb::Values &oldMembers, const dsdb::Values &newMembers) {
        auto has = [](const dsdb::Values &v, const std::string &x) {
            std::string k = dnKey(x);
            return std::any_of(v.begin(), v.end(), [&](const std::string &y) { return dnKey(y) == k; });
        };
        for (auto &m : newMembers)
            if (!has(oldMembers, m)) editLink(dir, m, "memberOf", groupDn, true);
        for (auto &m : oldMembers)
            if (!has(newMembers, m)) editLink(dir, m, "memberOf", groupDn, false);
    }
}

std::vector<uint8_t> ActiveDirectory::handleModifyRequest(const uint8_t *content, size_t len,
                                                          int32_t msgId, LdapSession &session) {
    const uint8_t appResp = LdapBer::CLASS_APPLICATION | LdapBer::CONSTRUCTED | LDAP_MODIFY_RESPONSE;
@@ -2433,6 +2471,10 @@ std::vector<uint8_t> ActiveDirectory::handleModifyRequest(const uint8_t *content
        if (newSec)
            dsdb::setInt(attrs, "msDS-KeyVersionNumber", newSec->kvno);
        d->dir->modify(cur->objectGuid, attrs, newSec.get());
        const dsdb::Values none;
        const dsdb::Values *was = cur->get("member"), *now = dsdb::get(attrs, "member");
        if (was || now)
            syncMemberOf(*d->dir, cur->dn.str(), was ? *was : none, now ? *now : none);
    } catch (std::exception &e) {
        return buildLdapMessage(msgId, appResp, buildLdapResult(LDAP_OTHER, "", e.what()));
    }
@@ -2459,6 +2501,12 @@ std::vector<uint8_t> ActiveDirectory::handleDelRequest(const uint8_t *content, s
        return buildLdapMessage(msgId, appResp, buildLdapResult(LDAP_NO_SUCH_OBJECT, "", ""));
    try {
        d->dir->remove(cur->objectGuid);
        /* drop the links to and from the removed object */
        if (auto *mem = cur->get("member"))
            syncMemberOf(*d->dir, cur->dn.str(), *mem, {});
        if (auto *mo = cur->get("memberOf"))
            for (auto &g : *mo)
                editLink(*d->dir, g, "member", cur->dn.str(), false);
    } catch (std::exception &e) {
        return buildLdapMessage(msgId, appResp, buildLdapResult(LDAP_OTHER, "", e.what()));
    }