Commit 070b39f6 authored by jan.koester's avatar jan.koester
Browse files

test

parent 9a9b95c2
Loading
Loading
Loading
Loading
+77 −2
Changes for src/netlogon.cpp: 77 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -314,13 +314,15 @@ struct Rpc {
        p32(h, 0x00000010);                                         /* little-endian data rep */
        p16(h, fragLen); p16(h, authLen); p32(h, callid++);
    }
    /* abstract syntax to bind; defaults to NETLOGON v1.0, set before an EPM bind */
    const uint8_t *ifaceUuid = (const uint8_t *)"\x78\x56\x34\x12\x34\x12\xcd\xab\xef\x00\x01\x23\x45\x67\xcf\xfb";
    uint32_t ifaceVer = 1;
    void bindOrAlter(uint8_t ptype, const Bytes &authval, uint8_t authType, uint8_t authLevel) {
        Bytes body;
        p16(body, 5840); p16(body, 5840); p32(body, ptype == 11 ? 0 : assoc);
        body += (char)1; body += (char)0; p16(body, 0);
        p16(body, 0); body += (char)1; body += (char)0;
        static const uint8_t ns[16] = {0x78, 0x56, 0x34, 0x12, 0x34, 0x12, 0xcd, 0xab, 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0xcf, 0xfb};
        body.append((char *)ns, 16); p32(body, 1);
        body.append((char *)ifaceUuid, 16); p32(body, ifaceVer);
        static const uint8_t ts[16] = {0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60};
        body.append((char *)ts, 16); p32(body, 2);
        Bytes tail;
@@ -383,6 +385,79 @@ Bytes randBytes(size_t n) {
    return r;
}

/* the NETLOGON-over-ncacn_ip_tcp tower the endpoint mapper resolves to a port */
Bytes netlogonTower() {
    static const uint8_t nl[16] = {0x78, 0x56, 0x34, 0x12, 0x34, 0x12, 0xcd, 0xab, 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0xcf, 0xfb};
    static const uint8_t ndr[16] = {0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60};
    Bytes t;
    p16(t, 5); /* five floors */
    auto floor = [&](const Bytes &lhs, const Bytes &rhs) { p16(t, (uint16_t)lhs.size()); t += lhs; p16(t, (uint16_t)rhs.size()); t += rhs; };
    Bytes l1; l1 += (char)0x0d; l1.append((char *)nl, 16); p16(l1, 1); floor(l1, Bytes("\0\0", 2));   /* interface + ver major, rhs ver minor */
    Bytes l2; l2 += (char)0x0d; l2.append((char *)ndr, 16); p16(l2, 2); floor(l2, Bytes("\0\0", 2));  /* NDR transfer */
    floor(Bytes("\x0b", 1), Bytes("\0\0", 2));                                                        /* RPC CO */
    floor(Bytes("\x07", 1), Bytes("\0\0", 2));                                                        /* tcp port (placeholder) */
    floor(Bytes("\x09", 1), Bytes("\0\0\0\0", 4));                                                    /* IP host */
    return t;
}

/* parse an endpoint-mapper tower, return the tcp port from its floor 4 (0 if none) */
int portFromTower(const Bytes &t) {
    if (t.size() < 2) return 0;
    size_t o = 0;
    uint16_t floors = g16((const uint8_t *)t.data());
    o = 2;
    for (int i = 0; i < floors && o + 4 <= t.size(); i++) {
        uint16_t ll = g16((const uint8_t *)t.data() + o); o += 2;
        if (o + ll > t.size()) break;
        uint8_t proto = ll ? (uint8_t)t[o] : 0;
        o += ll;
        if (o + 2 > t.size()) break;
        uint16_t rl = g16((const uint8_t *)t.data() + o); o += 2;
        if (o + rl > t.size()) break;
        if (proto == 0x07 && rl == 2) return (int)(((uint8_t)t[o] << 8) | (uint8_t)t[o + 1]); /* big-endian port */
        o += rl;
    }
    return 0;
}

/* ask the endpoint mapper (ept_map, opnum 3) for the NETLOGON tcp port */
int epmMapNetlogon(const std::string &host, int epmPort, int timeoutMs) {
    Rpc r;
    r.conn(host, epmPort, timeoutMs);
    r.ifaceUuid = (const uint8_t *)"\x08\x83\xaf\xe1\x1f\x5d\xc9\x11\x91\xa4\x08\x00\x2b\x14\xa0\xfa"; /* EPM v3.0 */
    r.ifaceVer = 3;
    r.bindOrAlter(11, Bytes(), 0, 0);

    Bytes tower = netlogonTower();
    Bytes s;
    p32(s, 0x00020000);               /* obj referent */
    s.append(16, '\0');               /* null object uuid */
    p32(s, 0x00020004);               /* map_tower referent */
    p32(s, (uint32_t)tower.size());   /* conformant max_count */
    p32(s, (uint32_t)tower.size());   /* twr_t.tower_length */
    s += tower; align4(s);
    s.append(20, '\0');               /* entry_handle (null context handle) */
    p32(s, 1);                        /* max_towers */

    Bytes o = r.call(3, s);
    /* response: entry_handle(20), num_towers(4), vector{max,off,count}, referents, towers..., status */
    if (o.size() < 24 + 12) return 0;
    size_t p = 20;
    uint32_t num = g32((const uint8_t *)o.data() + p); p += 4;
    if (num == 0) return 0;
    uint32_t vmax = g32((const uint8_t *)o.data() + p); (void)vmax; p += 4;
    p += 4;                           /* offset */
    uint32_t count = g32((const uint8_t *)o.data() + p); p += 4;
    if (count == 0) return 0;
    p += 4 * count;                   /* skip referent ids */
    /* first tower: max_count(4), tower_length(4), bytes */
    if (p + 8 > o.size()) return 0;
    uint32_t tmax = g32((const uint8_t *)o.data() + p); (void)tmax; p += 4;
    uint32_t tlen = g32((const uint8_t *)o.data() + p); p += 4;
    if (p + tlen > o.size()) return 0;
    return portFromTower(o.substr(p, tlen));
}

} // namespace

NtlmResult samLogonNetwork(const NetlogonConfig &cfg, const NtlmPassthrough &in) {