Commit 80da86ad authored by jan.koester's avatar jan.koester
Browse files

test

parent 021a3f98
Loading
Loading
Loading
Loading
+26 −0
Changes for src/daemon.cpp: 26 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -431,6 +431,32 @@ int main(int argc, char **argv) {
    sigaddset(&signals, SIGINT);
    pthread_sigmask(SIG_BLOCK, &signals, nullptr);
    std::thread(saver, std::ref(s), signals).detach();
    /* joined domains: SPNs older joins lack (cifs/ -- without it Windows
     * gets no ticket for SMB and falls back to NTLM), until a DC answers */
    for (auto &dp : s.domains) {
        Domain *d = dp.get();
        const std::string &acct = d->cfg.krbPrincipal;
        if (d->cfg.auth != Auth::Kerberos || acct.empty() || acct.back() != '$') continue;
        std::thread([d, acct]() {
            for (int attempt = 0; attempt < 48; attempt++) {
                try {
                    std::vector<std::string> added;
                    {
                        std::lock_guard<std::mutex> l(d->lock);
                        added = addMissingSpns(d->src, d->cfg, acct);
                    }
                    for (const std::string &spn : added)
                        std::cerr << "adconnectd: " << d->cfg.domain << ": SPN " << spn << " added to " << acct << std::endl;
                    return;
                } catch (const std::exception &e) {
                    if (attempt == 0)
                        std::cerr << "adconnectd: " << d->cfg.domain << ": checking the SPNs of " << acct << ": " << e.what()
                                  << std::endl;
                }
                std::this_thread::sleep_for(std::chrono::minutes(5));
            }
        }).detach();
    }
    std::unique_ptr<netplus::tcp> srv;
    try {
        unlink(cfg.socket.c_str());
+30 −1
Changes for src/join.cpp: 30 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -127,6 +127,12 @@ void writeSecret(const std::string &path, const std::string &secret) {

} // namespace

/* the SPNs of a computer account of ours: HOST/ for logins, cifs/ for SMB
 * (Windows asks for cifs/<server>; Samba's KDC doesn't map that to HOST/) */
static std::vector<std::string> computerSpns(const std::string &name, const std::string &dnsName) {
    return { "HOST/" + name, "HOST/" + dnsName, "cifs/" + name, "cifs/" + dnsName };
}

std::string computerName(const std::string &hostname) {
    std::string out;
    for (char c : hostname.substr(0, hostname.find('.'))) {
@@ -163,7 +169,7 @@ JoinResult joinWith(const Config &admin, const std::string &hostname, const std:
                { "sAMAccountName", { sam } },
                { "userAccountControl", { WorkstationTrust } },
                { "dNSHostName", { dnsName } },
                { "servicePrincipalName", { "HOST/" + name, "HOST/" + dnsName } },
                { "servicePrincipalName", computerSpns(name, dnsName) },
                { "msDS-SupportedEncryptionTypes", { AesOnly } },
                { "unicodePwd", { unicodePwd(password) } },
            });
@@ -174,6 +180,7 @@ JoinResult joinWith(const Config &admin, const std::string &hostname, const std:
                { ldap::Connection::ModReplace, { "userAccountControl", { WorkstationTrust } } },
                { ldap::Connection::ModReplace, { "msDS-SupportedEncryptionTypes", { AesOnly } } },
                { ldap::Connection::ModReplace, { "dNSHostName", { dnsName } } },
                { ldap::Connection::ModReplace, { "servicePrincipalName", computerSpns(name, dnsName) } },
            });
        }
    } catch (const ldap::Error &e) {
@@ -211,6 +218,28 @@ JoinResult joinWith(const Config &admin, const std::string &hostname, const std:
    return r;
}

std::vector<std::string> addMissingSpns(LdapSource &src, const Config &c, const std::string &account) {
    std::string dn, dnsName;
    std::vector<std::string> have;
    src.search(c.base, ldap::Subtree, "(&(objectClass=computer)(sAMAccountName=" + ldap::escape(account) + "))",
               { "servicePrincipalName", "dNSHostName" }, [&](const ldap::Entry &e) {
                   dn = e.dn;
                   if (const std::string *d = e.first("dnshostname")) dnsName = *d;
                   if (const auto *v = e.all("serviceprincipalname")) have = *v;
               }, 0);
    if (dn.empty()) throw std::runtime_error("no computer account " + account);
    std::string name = account.substr(0, account.size() - (!account.empty() && account.back() == '$'));
    if (dnsName.empty()) dnsName = lower(name) + "." + c.domain;
    std::vector<std::string> missing;
    for (const std::string &spn : computerSpns(name, dnsName)) {
        bool found = false;
        for (const std::string &h : have) found = found || lower(h) == lower(spn);
        if (!found) missing.push_back(spn);
    }
    if (!missing.empty()) src.modify(dn, { { ldap::Connection::ModAdd, { "servicePrincipalName", missing } } });
    return missing;
}

bool leaveWith(const Config &admin, const std::string &account) {
    LdapSource src(admin);
    src.check();
+6 −0
Changes for src/join.h: 6 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -64,6 +64,12 @@ bool leaveDomain(const Config &domain, const std::string &account, const std::st
/* the deletion on a connection admin describes (tests) */
bool leaveWith(const Config &admin, const std::string &account);

class LdapSource;
/* adds the SPNs a computer account of ours (account: HOST$) lacks -- cifs/
 * for SMB, which older joins didn't register; the account may do that
 * itself. The ones added; throws std::runtime_error */
std::vector<std::string> addMissingSpns(LdapSource &src, const Config &c, const std::string &account);

/* this system's name as a computer account: short, upper case, at most 15 */
std::string computerName(const std::string &hostname);