Loading src/netlogon.cpp +77 −2 Changes for src/netlogon.cpp: 77 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading
src/netlogon.cpp +77 −2 Changes for src/netlogon.cpp: 77 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading