Commit 70bf5060 authored by jan.koester's avatar jan.koester
Browse files

test

parent 3c68a8c7
Loading
Loading
Loading
Loading
Loading
+46 −20
Changes for plugin/ad/ad.cpp: 46 added lines, 20 removed lines.
Original line number Diff line number Diff line
@@ -885,8 +885,11 @@ bool ActiveDirectory::dirImportNative(const std::string &domain, int &migrated,
            try { std::string v = udat.getLastname();  if (!v.empty()) a["sn"] = {v}; } catch (...) {}
            try { std::string v = udat.getMail();      if (!v.empty()) a["mail"] = {v}; } catch (...) {}
            try { std::string v = udat.getPwHash();    if (!v.empty()) a["@webHash"] = {v}; } catch (...) {}
            try { d->dir->create(dn, a, nullptr); ++migrated; } catch (...) {}
            try { std::vector<char> av; udat.getAvatar(av); if (!av.empty()) a["thumbnailPhoto"] = {std::string(av.begin(), av.end())}; } catch (...) {}
            try { d->dir->create(dn, a, nullptr); ++migrated; }
            catch (std::exception &e) { std::cerr << "[AD] dirImportNative: user '" << sam << "' skipped: " << e.what() << std::endl; }
        }
        std::cerr << "[AD] dirImportNative: native users=" << uids.size() << std::endl;
    }

    /* native GroupData -> SID-less directory group + members (by username) */
@@ -899,39 +902,62 @@ bool ActiveDirectory::dirImportNative(const std::string &domain, int &migrated,
            try { size_t p = sizeof(AuthHeader); group.info(*bck, gdat, p); } catch (...) { continue; }
            std::string gname = gdat.getName();
            if (gname.empty()) continue;
            if (d->dir->bySamAccountName(gname)) continue;

            /* find-or-create the directory group: MERGE into an existing one
             * (e.g. a provisioned "Domain Admins") instead of dropping its
             * imported members */
            dsdb::Dn dn = users.child("CN", gname);
            if (d->dir->byDn(dn)) continue;
            uuid::uuid groupGuid;
            std::string groupDn;
            auto existing = d->dir->bySamAccountName(gname);
            if (!existing) existing = d->dir->byDn(dn);   /* same CN, maybe no sAMAccountName indexed */
            if (existing) {
                groupGuid = existing->objectGuid;
                groupDn   = existing->dn.str();
            } else {
                dsdb::AttrMap a;
                a["objectClass"]    = {"top", "group"};
                a["objectCategory"] = {"CN=Group,CN=Schema,CN=Configuration," + d->meta.baseDn.str()};
                a["sAMAccountName"] = {gname};
                a["cn"] = {gname}; a["name"] = {gname};
                a["distinguishedName"] = {dn.str()};
                try { groupGuid = d->dir->create(dn, a, nullptr); groupDn = dn.str(); ++migrated; }
                catch (std::exception &e) {
                    std::cerr << "[AD] dirImportNative: group '" << gname << "' skipped: " << e.what() << std::endl;
                    continue;
                }
            }

            /* add each native member (resolved by username) to the directory
             * group — member + memberOf, duplicate-safe so a re-import is a no-op */
            std::vector<uuid::uuid> mems; gdat.getMembers(mems);
            dsdb::Values memberDns;
            for (const auto &muid : mems) {
                class UserData mu(muid); User u;
                try { size_t p = sizeof(AuthHeader); u.info(*bck, mu, p);
                    std::string msam = mu.getUsername();
                    if (!msam.empty()) memberDns.push_back(users.child("CN", msam).str());
                } catch (...) {}
                std::string msam;
                try { size_t p = sizeof(AuthHeader); u.info(*bck, mu, p); msam = mu.getUsername(); } catch (...) { continue; }
                if (msam.empty()) continue;
                auto me = d->dir->bySamAccountName(msam);
                if (!me) continue;
                std::string mdn = me->dn.str();

                auto grpEnt = d->dir->byGuid(groupGuid);
                if (grpEnt) {
                    dsdb::Values members = grpEnt->get("member") ? *grpEnt->get("member") : dsdb::Values{};
                    if (std::find(members.begin(), members.end(), mdn) == members.end()) {
                        members.push_back(mdn);
                        dsdb::AttrMap ga; ga["member"] = members;
                        try { d->dir->modify(groupGuid, ga, nullptr); } catch (...) {}
                    }
                }
            if (!memberDns.empty()) a["member"] = memberDns;
            try {
                d->dir->create(dn, a, nullptr);
                for (auto &mdn : memberDns) {
                    dsdb::Dn md; if (!dsdb::Dn::parse(mdn, md)) continue;
                    auto me = d->dir->byDn(md); if (!me) continue;
                    dsdb::AttrMap up;
                dsdb::Values mo = me->get("memberOf") ? *me->get("memberOf") : dsdb::Values{};
                    mo.push_back(dn.str());
                    up["memberOf"] = mo;
                    try { d->dir->modify(me->objectGuid, up, nullptr); } catch (...) {}
                if (std::find(mo.begin(), mo.end(), groupDn) == mo.end()) {
                    mo.push_back(groupDn);
                    dsdb::AttrMap ua; ua["memberOf"] = mo;
                    try { d->dir->modify(me->objectGuid, ua, nullptr); } catch (...) {}
                }
            }
                ++migrated;
            } catch (...) {}
        }
        std::cerr << "[AD] dirImportNative: native groups=" << gids.size() << std::endl;
    }
    std::cerr << "[AD] dirImportNative domain=" << domain << " migrated=" << migrated << std::endl;
    return true;
+31 −0
Changes for src/admin.cpp: 31 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -2079,6 +2079,37 @@ namespace fenrirds {
                std::string err;
                if (!domain.empty() && !g_AdPlugin->dirImportNative(domain, migrated, err))
                    std::cerr << "import: dirImportNative failed: " << err << std::endl;

                /* ensure the domain has the default policies (so the Policies
                 * view is populated), with allowed pointing at the directory
                 * "Domain Admins" group — matching session memberships */
                if (!domain.empty()) {
                    uuid::uuid adminsGuid;
                    bool haveAdmins = false;
                    dsdb::Entry da;
                    std::string e2;
                    if (g_AdPlugin->dirGetBySam(domain, "Domain Admins", da, e2)) {
                        adminsGuid = da.objectGuid;
                        haveAdmins = true;
                    }
                    std::vector<uuid::uuid> allowed;
                    if (haveAdmins) allowed.push_back(adminsGuid);
                    AuthBackend::Guard g(*backend);
                    Gpo gpo;
                    for (size_t i = 0; gpo_default[i][0] != nullptr; ++i) {
                        uuid::uuid gpoid(gpo_default[i][0]);
                        int ret = 0;
                        if (gpo.exists(*backend, gpoid, nullptr, ret))
                            continue;
                        class GpoData gd(gpoid);
                        gd.setName(gpo_default[i][1]);
                        gd.setDesc(gpo_default[i][2]);
                        bool defval = (strcmp(gpo_default[i][3], "true") == 0);
                        gd.setGpoValue(defval);
                        if (!defval && haveAdmins) gd.setAllowed(allowed);
                        try { gpo.create(*backend, &gd); } catch (...) {}
                    }
                }
            }

            json_object *jobj = json_object_new_object();