Commit 7fcea7a5 authored by jan.koester's avatar jan.koester
Browse files

test

parent 66c5facb
Loading
Loading
Loading
Loading
+74 −0
Changes for test/test.cpp: 74 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <map>
#include <memory>
#include <iostream>
#include <string>
@@ -52,6 +53,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../src/cache.h"
#include "../src/config.h"
#include "../src/directory.h"
#include "../src/discover.h"
#include "../src/join.h"
#include "../src/gssapi.h"
#include "../src/krb5.h"
#include "../src/krb5crypto.h"
@@ -692,6 +695,75 @@ void testGss() {
    CHECK(throws([&] { ctx.unwrap(w); }), "unwrap: our own token (not from the acceptor) refused");
}

void testDiscover() {
    /* a DNS answer: two SRV records, the second target compressed */
    std::string m;
    auto u16 = [&](unsigned v) { m += (char)(v >> 8); m += (char)v; };
    u16(0x1234); u16(0x8180); u16(1); u16(2); u16(0); u16(0);
    for (const char *l : { "_ldap", "_tcp", "dc", "_msdcs", "example", "com" }) {
        m += (char)strlen(l);
        m += l;
    }
    m += '\0';
    u16(33); u16(1);
    auto answer = [&](unsigned prio, unsigned weight, const std::string &target) {
        u16(0xc00c); u16(33); u16(1); u16(0); u16(600);
        u16((unsigned)(6 + target.size())); u16(prio); u16(weight); u16(389);
        m += target;
    };
    answer(0, 100, std::string("\x03" "dc2" "\x07" "example" "\x03" "com", 17) + '\0');
    answer(0, 200, std::string("\x03" "dc1", 4) + "\xc0\x21");
    std::vector<SrvRecord> r = parseSrv((const unsigned char *)m.data(), m.size());
    CHECK(r.size() == 2 && r[0].target == "dc2.example.com" && r[0].port == 389 && r[1].target == "dc1.example.com" &&
          r[1].weight == 200, "SRV answers, with a compressed target");
    CHECK(parseSrv((const unsigned char *)m.data(), 20).empty(), "SRV: a truncated answer gives nothing");
}

void testJoin(const std::string &dir) {
    CHECK_EQ(computerName("fenriros-server-01.lan"), std::string("FENRIROS-SERVER"), "computer name: short, upper, 15");
    CHECK_EQ(computerName("nas_1"), std::string("NAS1"), "computer name: only letters, digits, -");

    fake::Server srv(objects(), BindDn, BindPw);
    Config admin = testConfig(srv.port());
    std::string secret = dir + "/secrets/bind-example.com.secret";
    auto utf16 = [](const std::string &s) {
        std::string q = "\"" + s + "\"", o;
        for (char c : q) { o += c; o += '\0'; }
        return o;
    };
    try {
        JoinResult r = joinWith(admin, "fenrir1.lan", secret, false);
        CHECK(r.created && r.principal == "FENRIR1$" && r.realm == "EXAMPLE.COM" && r.secretFile == secret, "join: a new account");
        fake::Object o;
        CHECK(srv.object("CN=FENRIR1,CN=Computers,DC=example,DC=com", o), "join: CN=FENRIR1,CN=Computers");
        std::map<std::string, std::vector<std::string>> a(o.attrs.begin(), o.attrs.end());
        std::ifstream in(secret);
        std::string pw;
        std::getline(in, pw);
        CHECK(pw.size() == 32 && a["unicodePwd"].size() == 1 && a["unicodePwd"][0] == utf16(pw),
              "join: the password in unicodePwd (quoted, UTF-16LE) and in the secret file");
        CHECK(a["sAMAccountName"] == std::vector<std::string>{ "FENRIR1$" } && a["userAccountControl"][0] == "4096" &&
              a["msDS-SupportedEncryptionTypes"][0] == "24" && a["dNSHostName"][0] == "fenrir1.example.com" &&
              a["servicePrincipalName"].size() == 2, "join: the account's attributes");
        struct stat st;
        CHECK(stat(secret.c_str(), &st) == 0 && (st.st_mode & 077) == 0, "join: the secret file root only");

        JoinResult again = joinWith(admin, "fenrir1", secret, false);
        std::ifstream in2(secret);
        std::string pw2;
        std::getline(in2, pw2);
        fake::Object o2;
        srv.object("CN=FENRIR1,CN=Computers,DC=example,DC=com", o2);
        std::map<std::string, std::vector<std::string>> a2(o2.attrs.begin(), o2.attrs.end());
        CHECK(!again.created && pw2 != pw && a2["unicodePwd"][0] == utf16(pw2), "join again: the existing account, a new password");
    } catch (const std::exception &e) {
        CHECK(false, std::string("join: ") + e.what());
    }
    Config wrong = admin;
    wrong.bindPassword = "nope";
    CHECK(throws([&] { joinWith(wrong, "fenrir2", secret, false); }), "join: a wrong admin password fails");
}

time_t fakeNow = 1000;

void testCache(const std::string &dir) {
@@ -935,6 +1007,8 @@ int main() {
    testSid();
    testConfig(dir);
    testCache(dir);
    testDiscover();
    testJoin(dir);
    testKrb5Crypto();
    testKeytab(dir);
    testGss();