Loading plugin/ad/ad.cpp +17 −2 Changes for plugin/ad/ad.cpp: 17 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -1747,7 +1747,7 @@ std::vector<uint8_t> ActiveDirectory::handleSearchRequest(const uint8_t *content rc = LDAP_SIZE_LIMIT_EXCEEDED; return false; } LdapEntry le = renderEntry(ent, requested, typesOnly); LdapEntry le = renderEntry(ent, requested, typesOnly, d.dir.get()); { std::string dump; for (auto &at : le.attributes) { Loading Loading @@ -1780,7 +1780,7 @@ std::vector<uint8_t> ActiveDirectory::handleSearchRequest(const uint8_t *content *****************************************************************************/ LdapEntry ActiveDirectory::renderEntry(const dsdb::Entry &ent, const std::vector<std::string> &requested, bool typesOnly) { bool typesOnly, dsdb::Directory *dir) { using namespace dsdb; LdapEntry le; le.dn = ent.dn.str(); Loading Loading @@ -1823,6 +1823,21 @@ LdapEntry ActiveDirectory::renderEntry(const dsdb::Entry &ent, le.attributes.push_back(std::move(a)); } /* tokenGroups: constructed, only when asked for by name (as in AD) */ if (dir && !ent.objectSid.empty()) { for (auto &n : named) { if (!iequals(n, "tokenGroups") && !iequals(n, "tokenGroupsGlobalAndUniversal")) continue; LdapAttribute a; a.type = "tokenGroups"; if (!typesOnly) for (auto &sid : dir->tokenGroupsInSearch(ent)) a.values.push_back(sid.binary()); le.attributes.push_back(std::move(a)); break; } } /* objectGUID is the record UUID (a separate Entry field, not in attrs): * synthesize it as the 16-byte binary GUID AD clients expect -- the * UUID's bytes as they are (network order), see buildRootDSE(). Windows Loading plugin/ad/ad.h +1 −1 Changes for plugin/ad/ad.h: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -372,7 +372,7 @@ namespace fenrirds { * attribute list (empty / "*" = all user attrs; "+" = operational; * "1.1" = none; secret attributes are never returned) */ LdapEntry renderEntry(const dsdb::Entry &e, const std::vector<std::string> &requested, bool typesOnly); bool typesOnly, dsdb::Directory *dir = nullptr); LdapEntry buildRootDSE(); /* parse a BER-encoded LDAP filter into a dsdb::Filter */ bool parseFilter(const uint8_t *data, size_t len, dsdb::Filter &out); Loading src/dsdb/directory.cpp +36 −0 Changes for src/dsdb/directory.cpp: 36 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -13,6 +13,42 @@ namespace dsdb { Directory::Directory(AuthBackend &backend, const DomainMeta &meta) : _Backend(backend), _Meta(meta) {} std::vector<Sid> Directory::tokenGroupsInSearch(const Entry &e) { std::vector<Sid> out; std::map<std::string, bool, CaseLess> seen; std::vector<std::string> work; auto addGroup = [&](const Entry *g) { if (!g || seen.count(g->dn.str())) return; seen[g->dn.str()] = true; if (!g->objectSid.empty()) out.push_back(g->objectSid); if (auto it = g->attrs.find("memberOf"); it != g->attrs.end()) work.insert(work.end(), it->second.begin(), it->second.end()); }; /* the primary group (domain SID + primaryGroupID) */ int64_t pg = intValue(e.attrs, "primaryGroupID", 0); if (pg > 0 && !e.objectSid.empty()) { Sid psid = e.objectSid.domain().withRid(uint32_t(pg)); auto it = _BySid.find(psid.binary()); if (it != _BySid.end() && it->second < _Entries.size()) addGroup(&_Entries[it->second]); else out.push_back(psid); } if (auto it = e.attrs.find("memberOf"); it != e.attrs.end()) work.insert(work.end(), it->second.begin(), it->second.end()); while (!work.empty()) { std::string cur = work.back(); work.pop_back(); Dn dn; if (seen.count(cur) || !Dn::parse(cur, dn)) continue; addGroup(findByDnLocked(dn)); } return out; } MatchContext Directory::matchContext() { MatchContext ctx; DomainMeta m = _Meta; Loading src/dsdb/directory.h +4 −0 Changes for src/dsdb/directory.h: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -132,6 +132,10 @@ namespace fenrirds { /* with _Mtx held: its callbacks look entries up unlocked */ MatchContext matchContext(); /* the constructed tokenGroups of a principal: the SIDs of its * primary group and of all groups it is in, transitively. Only * call from inside a search() callback (the lock is held). */ std::vector<Sid> tokenGroupsInSearch(const Entry &e); private: void ensureFresh(); Loading Loading
plugin/ad/ad.cpp +17 −2 Changes for plugin/ad/ad.cpp: 17 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -1747,7 +1747,7 @@ std::vector<uint8_t> ActiveDirectory::handleSearchRequest(const uint8_t *content rc = LDAP_SIZE_LIMIT_EXCEEDED; return false; } LdapEntry le = renderEntry(ent, requested, typesOnly); LdapEntry le = renderEntry(ent, requested, typesOnly, d.dir.get()); { std::string dump; for (auto &at : le.attributes) { Loading Loading @@ -1780,7 +1780,7 @@ std::vector<uint8_t> ActiveDirectory::handleSearchRequest(const uint8_t *content *****************************************************************************/ LdapEntry ActiveDirectory::renderEntry(const dsdb::Entry &ent, const std::vector<std::string> &requested, bool typesOnly) { bool typesOnly, dsdb::Directory *dir) { using namespace dsdb; LdapEntry le; le.dn = ent.dn.str(); Loading Loading @@ -1823,6 +1823,21 @@ LdapEntry ActiveDirectory::renderEntry(const dsdb::Entry &ent, le.attributes.push_back(std::move(a)); } /* tokenGroups: constructed, only when asked for by name (as in AD) */ if (dir && !ent.objectSid.empty()) { for (auto &n : named) { if (!iequals(n, "tokenGroups") && !iequals(n, "tokenGroupsGlobalAndUniversal")) continue; LdapAttribute a; a.type = "tokenGroups"; if (!typesOnly) for (auto &sid : dir->tokenGroupsInSearch(ent)) a.values.push_back(sid.binary()); le.attributes.push_back(std::move(a)); break; } } /* objectGUID is the record UUID (a separate Entry field, not in attrs): * synthesize it as the 16-byte binary GUID AD clients expect -- the * UUID's bytes as they are (network order), see buildRootDSE(). Windows Loading
plugin/ad/ad.h +1 −1 Changes for plugin/ad/ad.h: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -372,7 +372,7 @@ namespace fenrirds { * attribute list (empty / "*" = all user attrs; "+" = operational; * "1.1" = none; secret attributes are never returned) */ LdapEntry renderEntry(const dsdb::Entry &e, const std::vector<std::string> &requested, bool typesOnly); bool typesOnly, dsdb::Directory *dir = nullptr); LdapEntry buildRootDSE(); /* parse a BER-encoded LDAP filter into a dsdb::Filter */ bool parseFilter(const uint8_t *data, size_t len, dsdb::Filter &out); Loading
src/dsdb/directory.cpp +36 −0 Changes for src/dsdb/directory.cpp: 36 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -13,6 +13,42 @@ namespace dsdb { Directory::Directory(AuthBackend &backend, const DomainMeta &meta) : _Backend(backend), _Meta(meta) {} std::vector<Sid> Directory::tokenGroupsInSearch(const Entry &e) { std::vector<Sid> out; std::map<std::string, bool, CaseLess> seen; std::vector<std::string> work; auto addGroup = [&](const Entry *g) { if (!g || seen.count(g->dn.str())) return; seen[g->dn.str()] = true; if (!g->objectSid.empty()) out.push_back(g->objectSid); if (auto it = g->attrs.find("memberOf"); it != g->attrs.end()) work.insert(work.end(), it->second.begin(), it->second.end()); }; /* the primary group (domain SID + primaryGroupID) */ int64_t pg = intValue(e.attrs, "primaryGroupID", 0); if (pg > 0 && !e.objectSid.empty()) { Sid psid = e.objectSid.domain().withRid(uint32_t(pg)); auto it = _BySid.find(psid.binary()); if (it != _BySid.end() && it->second < _Entries.size()) addGroup(&_Entries[it->second]); else out.push_back(psid); } if (auto it = e.attrs.find("memberOf"); it != e.attrs.end()) work.insert(work.end(), it->second.begin(), it->second.end()); while (!work.empty()) { std::string cur = work.back(); work.pop_back(); Dn dn; if (seen.count(cur) || !Dn::parse(cur, dn)) continue; addGroup(findByDnLocked(dn)); } return out; } MatchContext Directory::matchContext() { MatchContext ctx; DomainMeta m = _Meta; Loading
src/dsdb/directory.h +4 −0 Changes for src/dsdb/directory.h: 4 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -132,6 +132,10 @@ namespace fenrirds { /* with _Mtx held: its callbacks look entries up unlocked */ MatchContext matchContext(); /* the constructed tokenGroups of a principal: the SIDs of its * primary group and of all groups it is in, transitively. Only * call from inside a search() callback (the lock is held). */ std::vector<Sid> tokenGroupsInSearch(const Entry &e); private: void ensureFresh(); Loading