Commit f7c26b31 authored by jan.koester's avatar jan.koester
Browse files

test

parent 39b63ff5
Loading
Loading
Loading
Loading
Loading
+2 −4
Changes for plugin/ad/ad.cpp: 2 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -1544,10 +1544,8 @@ std::vector<uint8_t> ActiveDirectory::handleBindRequest(const uint8_t *content,
            std::vector<uint8_t> creds;
            if (spnego) {
                std::vector<uint8_t> krb5oid = gss::firstMechOid(session.gssMechTypes);
                std::vector<uint8_t> mic = gss::getMic(session.gssKey, session.gssEtype,
                                                       true, session.sendSeq++, session.gssMechTypes,
                                                       session.gssAccSubkey);
                creds = gss::buildSpnegoResp(gss::ACCEPT_COMPLETED, &krb5oid, krb5reply, mic);
                /* the client's preferred mech: no mechListMIC (see smb.cpp) */
                creds = gss::buildSpnegoResp(gss::ACCEPT_COMPLETED, &krb5oid, krb5reply, {});
                /* GSS-SPNEGO has no RFC 4752 layer negotiation: the bind is
                 * done, and the client signs or seals the following PDUs as
                 * it asked for in its authenticator (MS-ADTS 5.1.1.1.2) */
+28 −5
Changes for plugin/smb/smb.cpp: 28 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -166,7 +166,9 @@ void RpcPipe::handlePdu(const std::vector<uint8_t> &pdu) {
                      << " iface=" << _name << std::endl;
            _boundAbstract = b.contexts[0].abstractSyntax;
            _bound = true;
            resp = rpc::buildBindAck(b, "\\PIPE\\" + _name);
            resp = rpc::buildBindAck(b, "\\PIPE\\" + _name, {}, 0, 0, [](const rpc::SyntaxId &a) {
                return rpc::isLsarpc(a.uuid) || rpc::isSamr(a.uuid) || rpc::isNetlogon(a.uuid);
            });
        } else {
            resp = rpc::buildBindNak(h.callId);
        }
@@ -752,16 +754,30 @@ SmbServer::Reply SmbServer::sessionSetup(Conn &c, const smb::Smb2Header &req,
    }
    std::vector<uint8_t> outTok;
    if (spnego) {
        /* we take the client's preferred mech (its optimistic token), so no
         * mechListMIC (RFC 4178 5): with one, Windows wants to send its own
         * MIC in another leg and fails the context (LsaSrv event 40962) */
        std::vector<uint8_t> oid = gss::firstMechOid(mechTypes);
        auto m = gss::getMic(res.sessionKey, res.sessionEtype, true, res.acceptorSeq, mechTypes,
                             res.acceptorSubkey);
        outTok = gss::buildSpnegoResp(gss::ACCEPT_COMPLETED, &oid, krb5reply, m);
        outTok = gss::buildSpnegoResp(gss::ACCEPT_COMPLETED, &oid, krb5reply, {});
    } else {
        outTok = krb5reply;
    }
    s.keys = smb::deriveKeys(c.dialect, res.sessionKey, c.dialect >= smb::SMB_3_1_1 ? s.preauth : std::vector<uint8_t>());
    s.haveKeys = true;
    reply.pdu = respond(ST_SUCCESS, 0, outTok);
    {   /* TEMPORARY interop diagnosis: the full token exchange */
        static const char *hx = "0123456789abcdef";
        auto hex = [](const std::vector<uint8_t> &b) {
            std::string o;
            for (uint8_t x : b) { o += hx[x >> 4]; o += hx[x & 15]; }
            return o;
        };
        std::vector<uint8_t> sk(res.sessionKey.begin(), res.sessionKey.end());
        std::cerr << "[SMB] KRB in  (" << tok.size() << "B): " << hex(tok) << "\n"
                  << "[SMB] KRB out (" << outTok.size() << "B): " << hex(outTok) << "\n"
                  << "[SMB] KRB dialect=0x" << std::hex << c.dialect << std::dec
                  << " sesskey=" << hex(sk) << " preauth=" << hex(s.preauth) << std::endl;
    }
    reply.signKey = s.keys.signing;
    return reply;
}
@@ -910,6 +926,9 @@ std::vector<uint8_t> SmbServer::create(Conn &c, Session &s, const smb::Smb2Heade
    if (nameLen && nameOff >= 64 && size_t(nameOff-64)+nameLen <= blen)
        name = rpc::fromUtf16(body + (nameOff-64), nameLen);
    const Tree &tree = s.trees[req.treeId];
    std::cerr << "[SMB] CREATE req share=" << int(tree.kind) << " name='" << name << "' access=0x"
              << std::hex << access << " disp=" << disposition << " opts=0x" << options << std::dec
              << " hdrflags=0x" << std::hex << req.flags << std::dec << std::endl;   /* TEMPORARY */

    Open o;
    o.sessionId = s.id;
@@ -941,8 +960,11 @@ std::vector<uint8_t> SmbServer::create(Conn &c, Session &s, const smb::Smb2Heade
    if (tree.kind == SHARE_IPC) {
        std::string pname = lowerAscii(name);
        if (!pname.empty() && pname[0] == '\\') pname.erase(0, 1);
        /* protected_storage (DPAPI backup keys) and ntsvcs (PnP) exist on a
         * DC; we bind-reject their interfaces, so clients fail fast */
        if (pname != "lsarpc" && pname != "samr" && pname != "netlogon" &&
            pname != "lsass" && pname != "srvsvc" && pname != "wkssvc")
            pname != "lsass" && pname != "srvsvc" && pname != "wkssvc" &&
            pname != "protected_storage" && pname != "ntsvcs")
            return errorResponse(req, ST_NAME_NOT_FOUND);
        uint64_t fid = c.nextFid++;
        o.pipe = new RpcPipe(pname);
@@ -1186,6 +1208,7 @@ std::vector<uint8_t> SmbServer::dfsReferral(const uint8_t *in, size_t inLen, boo
        reqName = rpc::fromUtf16(in + 10, nlen);
    }
    while (!reqName.empty() && reqName.back() == '\0') reqName.pop_back();
    std::cerr << "[SMB] DFS referral request '" << reqName << "' ex=" << ex << std::endl;   /* TEMPORARY */
    std::vector<std::string> parts;
    {
        std::string cur;
+14 −3
Changes for src/rpc/dcerpc.cpp: 14 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -153,7 +153,8 @@ static void appendAuthTrailer(std::vector<uint8_t> &pdu, const std::vector<uint8
}

std::vector<uint8_t> buildBindAck(const BindPdu &bind, const std::string &sec,
                                  const std::vector<uint8_t> &authToken, uint8_t authType, uint8_t authLevel) {
                                  const std::vector<uint8_t> &authToken, uint8_t authType, uint8_t authLevel,
                                  const std::function<bool(const SyntaxId &)> &knownInterface) {
    std::vector<uint8_t> body;
    wr16(body, bind.maxXmitFrag ? bind.maxXmitFrag : 4280);
    wr16(body, bind.maxRecvFrag ? bind.maxRecvFrag : 4280);
@@ -172,11 +173,21 @@ std::vector<uint8_t> buildBindAck(const BindPdu &bind, const std::string &sec,
        bool ok = false;
        for (auto &ts : c.transferSyntaxes)
            if (sameSyntax(ts, ndr)) { ok = true; break; }
        wr16(body, ok ? 0 : 2);        /* 0 = acceptance, 2 = provider_rejection */
        wr16(body, 0);                 /* reason */
        /* an interface this endpoint doesn't serve: provider_rejection with
         * reason abstract_syntax_not_supported, so the client fails fast
         * with RPC_S_UNKNOWN_IF instead of retrying */
        bool known = !knownInterface || knownInterface(c.abstractSyntax);
        if (ok && known) {
            wr16(body, 0);             /* acceptance */
            wr16(body, 0);
            body.insert(body.end(), ndr.uuid, ndr.uuid + 16);
            wr16(body, ndr.versionMajor);
            wr16(body, ndr.versionMinor);
        } else {
            wr16(body, 2);             /* provider_rejection */
            wr16(body, known ? 2 : 1); /* transfer syntaxes / abstract syntax not supported */
            for (int i = 0; i < 20; ++i) body.push_back(0);   /* null syntax */
        }
    }
    uint16_t authLen = uint16_t(authToken.size());
    std::vector<uint8_t> pdu = header(PDU_BIND_ACK, PFC_FIRST_FRAG | PFC_LAST_FRAG, bind.callId, 0, authLen);
+3 −1
Changes for src/rpc/dcerpc.h: 3 added lines, 1 removed line.
Original line number Diff line number Diff line
#pragma once

#include <cstdint>
#include <functional>
#include <map>
#include <string>
#include <vector>
@@ -88,7 +89,8 @@ namespace fenrirds {
         * transfer syntaxes include NDR), echoing the secondary address. */
        std::vector<uint8_t> buildBindAck(const BindPdu &bind, const std::string &secondaryAddr,
                                          const std::vector<uint8_t> &authToken = {},
                                          uint8_t authType = 0, uint8_t authLevel = 0);
                                          uint8_t authType = 0, uint8_t authLevel = 0,
                                          const std::function<bool(const SyntaxId &)> &knownInterface = nullptr);
        std::vector<uint8_t> buildBindNak(uint32_t callId);

        /* build a RESPONSE carrying the NDR stub (single fragment) */
+3 −2
Changes for src/rpc/lsarpc.cpp: 3 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -431,7 +431,8 @@ DispatchResult lsarpcDispatch(uint16_t opnum, const std::vector<uint8_t> &stub,
        NdrPush p;
        p.ref(true);              /* [out,ref] **info -> the union pointer */
        p.u16(level);             /* union discriminant */
        if (level == 5) {         /* PolicyAccountDomainInformation */
        if (level == 3 || level == 5) {  /* PolicyPrimaryDomain- / AccountDomainInformation:
                                          * both lsa_DomainInfo (name + domain SID) */
            p.align(4);
            pushLsaString(p, di.netbios, false);
            p.ref(true);          /* sid pointer */
@@ -452,7 +453,7 @@ DispatchResult lsarpcDispatch(uint16_t opnum, const std::vector<uint8_t> &stub,
            /* unsupported level: return a null pointer + invalid info class */
            p.buf.clear();
            p.ref(false);
            p.u32(0xC00000DD);    /* STATUS_INVALID_INFO_CLASS */
            p.u32(0xC0000003);    /* STATUS_INVALID_INFO_CLASS */
            r.stub = p.buf;
            return r;
        }
Loading