Loading plugin/ad/ad.cpp +42 −38 Changes for plugin/ad/ad.cpp: 42 added lines, 38 removed lines. Original line number Diff line number Diff line Loading @@ -2233,6 +2233,46 @@ static bool serverOwnedAttr(const std::string &canon) { return dsdb::iequals(canon, "objectSid") || dsdb::iequals(canon, "objectGUID"); } namespace { const dsdb::Values *attrVals(const dsdb::AttrMap &a, const char *name) { auto it = a.find(name); return it == a.end() ? nullptr : &it->second; } 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::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; Loading Loading @@ -2314,7 +2354,7 @@ 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")) if (auto *mem = attrVals(attrs, "member")) syncMemberOf(*d->dir, dn.str(), {}, *mem); } catch (std::exception &e) { return buildLdapMessage(msgId, appResp, buildLdapResult(LDAP_OTHER, "", e.what())); Loading @@ -2322,42 +2362,6 @@ std::vector<uint8_t> ActiveDirectory::handleAddRequest(const uint8_t *content, s 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; Loading Loading @@ -2472,7 +2476,7 @@ std::vector<uint8_t> ActiveDirectory::handleModifyRequest(const uint8_t *content 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"); const dsdb::Values *was = cur->get("member"), *now = attrVals(attrs, "member"); if (was || now) syncMemberOf(*d->dir, cur->dn.str(), was ? *was : none, now ? *now : none); } catch (std::exception &e) { Loading Loading
plugin/ad/ad.cpp +42 −38 Changes for plugin/ad/ad.cpp: 42 added lines, 38 removed lines. Original line number Diff line number Diff line Loading @@ -2233,6 +2233,46 @@ static bool serverOwnedAttr(const std::string &canon) { return dsdb::iequals(canon, "objectSid") || dsdb::iequals(canon, "objectGUID"); } namespace { const dsdb::Values *attrVals(const dsdb::AttrMap &a, const char *name) { auto it = a.find(name); return it == a.end() ? nullptr : &it->second; } 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::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; Loading Loading @@ -2314,7 +2354,7 @@ 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")) if (auto *mem = attrVals(attrs, "member")) syncMemberOf(*d->dir, dn.str(), {}, *mem); } catch (std::exception &e) { return buildLdapMessage(msgId, appResp, buildLdapResult(LDAP_OTHER, "", e.what())); Loading @@ -2322,42 +2362,6 @@ std::vector<uint8_t> ActiveDirectory::handleAddRequest(const uint8_t *content, s 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; Loading Loading @@ -2472,7 +2476,7 @@ std::vector<uint8_t> ActiveDirectory::handleModifyRequest(const uint8_t *content 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"); const dsdb::Values *was = cur->get("member"), *now = attrVals(attrs, "member"); if (was || now) syncMemberOf(*d->dir, cur->dn.str(), was ? *was : none, now ? *now : none); } catch (std::exception &e) { Loading