Loading plugin/smb/smb.cpp +48 −6 Changes for plugin/smb/smb.cpp: 48 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -164,11 +164,30 @@ void RpcPipe::handlePdu(const std::vector<uint8_t> &pdu) { std::cerr << "[RPC] BIND auth=" << b.hasAuth << " type=" << int(b.authType) << " level=" << int(b.authLevel) << " token=" << b.authToken.size() << "B" << " iface=" << _name << std::endl; auto known = [](const rpc::SyntaxId &a) { return rpc::isLsarpc(a.uuid) || rpc::isSamr(a.uuid) || rpc::isNetlogon(a.uuid); }; _boundAbstract = b.contexts[0].abstractSyntax; _bound = true; 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); }); if (b.hasAuth && b.authType == rpc::AUTH_TYPE_SCHANNEL) { /* netlogon secure channel: the client names its computer, we * take the session key of its ServerAuthenticate3 */ rpc::NlAuthNegotiate neg; std::vector<uint8_t> sk; if (rpc::parseNlAuthNegotiate(b.authToken, neg) && rpc::netlogonChannelKey(neg.computer, sk)) { _netsec = rpc::NetsecContext(sk, neg.computer); resp = rpc::buildBindAck(b, "\\PIPE\\" + _name, rpc::buildNlAuthResponse(), b.authType, b.authLevel, known, b.authContextId); std::cerr << "[RPC] schannel bind for '" << neg.computer << "'" << std::endl; } else { std::cerr << "[RPC] schannel bind: no secure channel for '" << neg.computer << "'" << std::endl; resp = rpc::buildBindNak(h.callId); } } else { resp = rpc::buildBindAck(b, "\\PIPE\\" + _name, {}, 0, 0, known); } if (h.pduType == rpc::PDU_ALTER && resp.size() > 2 && resp[2] == rpc::PDU_BIND_ACK) resp[2] = rpc::PDU_ALTER_ACK; } else { resp = rpc::buildBindNak(h.callId); } Loading @@ -180,13 +199,25 @@ void RpcPipe::handlePdu(const std::vector<uint8_t> &pdu) { if (req.hasAuth) std::cerr << "[RPC] REQUEST opnum=" << req.opnum << " auth type=" << int(req.authType) << " level=" << int(req.authLevel) << " token=" << req.authToken.size() << "B" << std::endl; if (req.hasAuth && req.authType == rpc::AUTH_TYPE_SCHANNEL) { bool seal = req.authLevel == rpc::AUTH_LEVEL_PRIVACY; if (!_netsec.valid() || !_netsec.unwrapRequest(req.stub, req.authToken, seal)) { std::cerr << "[RPC] schannel request rejected (signature)" << std::endl; resp = rpc::buildFault(req.callId, req.contextId, 0x00000005); /* access denied */ } else { if (req.authPadLength <= req.stub.size()) req.stub.resize(req.stub.size() - req.authPadLength); resp = dispatch(req, true); } } else { resp = dispatch(req); } } } _out.insert(_out.end(), resp.begin(), resp.end()); } std::vector<uint8_t> RpcPipe::dispatch(const rpc::RequestPdu &req) { std::vector<uint8_t> RpcPipe::dispatch(const rpc::RequestPdu &req, bool schannel) { rpc::DispatchResult res; const char *iface = "?"; if (rpc::isLsarpc(_boundAbstract.uuid)) { Loading @@ -197,7 +228,8 @@ std::vector<uint8_t> RpcPipe::dispatch(const rpc::RequestPdu &req) { res = rpc::samrDispatch(req.opnum, req.stub, _sessionKey, _appKey); } else if (rpc::isNetlogon(_boundAbstract.uuid)) { iface = "netlogon"; res = rpc::netlogonDispatch(req.opnum, req.stub, _sessionKey); res = rpc::netlogonDispatch(req.opnum, req.stub, _sessionKey, schannel ? _netsec.computer() : std::string()); } else { res.fault = true; res.faultCode = 0x1C010003; /* nca_unk_if */ Loading @@ -214,6 +246,14 @@ std::vector<uint8_t> RpcPipe::dispatch(const rpc::RequestPdu &req) { } if (res.fault) return rpc::buildFault(req.callId, req.contextId, res.faultCode); if (schannel) { bool seal = req.authLevel == rpc::AUTH_LEVEL_PRIVACY; size_t sigLen = req.authToken.size(); return rpc::buildAuthResponse(req.callId, req.contextId, res.stub, req.authType, req.authLevel, req.authContextId, [&](std::vector<uint8_t> &data) { return _netsec.wrapResponse(data, seal, sigLen); }); } return rpc::buildResponse(req.callId, req.contextId, res.stub); } Loading Loading @@ -1817,7 +1857,7 @@ std::vector<uint8_t> SmbServer::setInfo(Conn &c, Session &s, const smb::Smb2Head extern "C" { fenrirds::Plugin *fenrirds_plugin_create(fenrirds::AuthBackend &backend, const char *configJson) { std::string bindAddr = "0.0.0.0", host; std::string bindAddr = "0.0.0.0", host, address; int port = 445; if (configJson) { json_object *j = json_tokener_parse(configJson); Loading @@ -1825,9 +1865,11 @@ fenrirds::Plugin *fenrirds_plugin_create(fenrirds::AuthBackend &backend, const c if (auto *x = json_object_object_get(j, "smb_bind")) bindAddr = json_object_get_string(x); if (auto *x = json_object_object_get(j, "smb_port")) port = json_object_get_int(x); if (auto *x = json_object_object_get(j, "dns_hostname")) host = json_object_get_string(x); if (auto *x = json_object_object_get(j, "dns_address")) address = json_object_get_string(x); json_object_put(j); } } fenrirds::rpc::setDcIdentity(host, address); return new fenrirds::SmbServer(backend, bindAddr, port, host); } Loading plugin/smb/smb.h +2 −1 Changes for plugin/smb/smb.h: 2 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -45,7 +45,7 @@ namespace fenrirds { private: void handlePdu(const std::vector<uint8_t> &pdu); std::vector<uint8_t> dispatch(const rpc::RequestPdu &req); std::vector<uint8_t> dispatch(const rpc::RequestPdu &req, bool schannel = false); std::string _name; std::vector<uint8_t> _in; /* request assembly */ Loading @@ -55,6 +55,7 @@ namespace fenrirds { bool _bound = false; std::vector<uint8_t> _sessionKey; std::vector<uint8_t> _appKey; rpc::NetsecContext _netsec; /* netlogon schannel bind (auth type 68) */ }; /*************************************************************************** Loading src/rpc/dcerpc.cpp +37 −7 Changes for src/rpc/dcerpc.cpp: 37 added lines, 7 removed lines. Original line number Diff line number Diff line Loading @@ -47,7 +47,8 @@ bool parseCommonHeader(const uint8_t *d, size_t n, CommonHeader &h) { } static void parseAuthTrailer(const uint8_t *d, size_t n, const CommonHeader &h, bool &hasAuth, std::vector<uint8_t> &tok, uint8_t &type, uint8_t &level) { bool &hasAuth, std::vector<uint8_t> &tok, uint8_t &type, uint8_t &level, uint8_t *padLen = nullptr, uint32_t *ctxId = nullptr) { if (h.authLength == 0 || h.fragLength > n) return; /* auth trailer = 8-byte sec_trailer header + authLength bytes, at the end */ Loading @@ -56,6 +57,8 @@ static void parseAuthTrailer(const uint8_t *d, size_t n, const CommonHeader &h, return; type = d[authStart]; level = d[authStart + 1]; if (padLen) *padLen = d[authStart + 2]; if (ctxId) *ctxId = rd32(d + authStart + 4); tok.assign(d + authStart + 8, d + authStart + 8 + h.authLength); hasAuth = true; } Loading Loading @@ -98,7 +101,8 @@ bool parseBind(const uint8_t *d, size_t n, BindPdu &out) { } out.contexts.push_back(std::move(ctx)); } parseAuthTrailer(d, n, h, out.hasAuth, out.authToken, out.authType, out.authLevel); parseAuthTrailer(d, n, h, out.hasAuth, out.authToken, out.authType, out.authLevel, nullptr, &out.authContextId); return true; } Loading @@ -120,7 +124,8 @@ bool parseRequest(const uint8_t *d, size_t n, RequestPdu &out) { stubEnd = size_t(h.fragLength) - h.authLength - 8; if (stubEnd > n || stubEnd < o) return false; out.stub.assign(d + o, d + stubEnd); parseAuthTrailer(d, n, h, out.hasAuth, out.authToken, out.authType, out.authLevel); parseAuthTrailer(d, n, h, out.hasAuth, out.authToken, out.authType, out.authLevel, &out.authPadLength, &out.authContextId); return true; } Loading @@ -138,7 +143,7 @@ static std::vector<uint8_t> header(uint8_t type, uint8_t flags, uint32_t callId, } static void appendAuthTrailer(std::vector<uint8_t> &pdu, const std::vector<uint8_t> &tok, uint8_t type, uint8_t level) { uint8_t type, uint8_t level, uint32_t ctxId = 0) { if (tok.empty()) return; /* pad the stub to a 4-byte boundary (auth_pad) */ Loading @@ -148,13 +153,14 @@ static void appendAuthTrailer(std::vector<uint8_t> &pdu, const std::vector<uint8 pdu.push_back(level); pdu.push_back(pad); pdu.push_back(0); /* reserved */ wr32(pdu, 0); /* auth context id */ wr32(pdu, ctxId); /* auth context id */ pdu.insert(pdu.end(), tok.begin(), tok.end()); } 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::function<bool(const SyntaxId &)> &knownInterface) { const std::function<bool(const SyntaxId &)> &knownInterface, uint32_t authContextId) { std::vector<uint8_t> body; wr16(body, bind.maxXmitFrag ? bind.maxXmitFrag : 4280); wr16(body, bind.maxRecvFrag ? bind.maxRecvFrag : 4280); Loading Loading @@ -193,7 +199,7 @@ std::vector<uint8_t> buildBindAck(const BindPdu &bind, const std::string &sec, std::vector<uint8_t> pdu = header(PDU_BIND_ACK, PFC_FIRST_FRAG | PFC_LAST_FRAG, bind.callId, 0, authLen); pdu.insert(pdu.end(), body.begin(), body.end()); if (!authToken.empty()) appendAuthTrailer(pdu, authToken, authType, authLevel); appendAuthTrailer(pdu, authToken, authType, authLevel, authContextId); uint16_t frag = uint16_t(pdu.size()); pdu[8] = frag & 0xff; pdu[9] = frag >> 8; return pdu; Loading Loading @@ -226,6 +232,30 @@ std::vector<uint8_t> buildResponse(uint32_t callId, uint16_t contextId, return pdu; } std::vector<uint8_t> buildAuthResponse(uint32_t callId, uint16_t contextId, const std::vector<uint8_t> &stub, uint8_t authType, uint8_t authLevel, uint32_t authContextId, const std::function<std::vector<uint8_t>(std::vector<uint8_t> &)> &wrap) { std::vector<uint8_t> data = stub; uint8_t pad = uint8_t((16 - data.size() % 16) % 16); data.resize(data.size() + pad, 0); std::vector<uint8_t> tok = wrap(data); std::vector<uint8_t> pdu = header(PDU_RESPONSE, PFC_FIRST_FRAG | PFC_LAST_FRAG, callId, 0, uint16_t(tok.size())); wr32(pdu, uint32_t(stub.size())); /* alloc_hint */ wr16(pdu, contextId); wr16(pdu, 0); pdu.insert(pdu.end(), data.begin(), data.end()); pdu.push_back(authType); pdu.push_back(authLevel); pdu.push_back(pad); pdu.push_back(0); wr32(pdu, authContextId); pdu.insert(pdu.end(), tok.begin(), tok.end()); uint16_t frag = uint16_t(pdu.size()); pdu[8] = frag & 0xff; pdu[9] = frag >> 8; return pdu; } std::vector<uint8_t> buildFault(uint32_t callId, uint16_t contextId, uint32_t status) { std::vector<uint8_t> pdu = header(PDU_FAULT, PFC_FIRST_FRAG | PFC_LAST_FRAG, callId, 0, 0); wr32(pdu, 0); /* alloc_hint */ Loading src/rpc/dcerpc.h +11 −1 Changes for src/rpc/dcerpc.h: 11 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ namespace fenrirds { std::vector<uint8_t> authToken; uint8_t authType = 0; uint8_t authLevel = 0; uint32_t authContextId = 0; }; /* a parsed REQUEST */ Loading @@ -75,6 +76,8 @@ namespace fenrirds { std::vector<uint8_t> authToken; uint8_t authType = 0; uint8_t authLevel = 0; uint8_t authPadLength = 0; /* stub ends with this many pad bytes */ uint32_t authContextId = 0; }; bool parseCommonHeader(const uint8_t *d, size_t n, CommonHeader &h); Loading @@ -90,7 +93,8 @@ namespace fenrirds { 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, const std::function<bool(const SyntaxId &)> &knownInterface = nullptr); const std::function<bool(const SyntaxId &)> &knownInterface = nullptr, uint32_t authContextId = 0); std::vector<uint8_t> buildBindNak(uint32_t callId); /* build a RESPONSE carrying the NDR stub (single fragment) */ Loading @@ -98,6 +102,12 @@ namespace fenrirds { const std::vector<uint8_t> &stub, const std::vector<uint8_t> &authToken = {}, uint8_t authType = 0, uint8_t authLevel = 0); /* a RESPONSE protected by a security provider: the stub is padded to * 16 bytes, wrap() signs/seals it in place and returns the auth_value */ std::vector<uint8_t> buildAuthResponse(uint32_t callId, uint16_t contextId, const std::vector<uint8_t> &stub, uint8_t authType, uint8_t authLevel, uint32_t authContextId, const std::function<std::vector<uint8_t>(std::vector<uint8_t> &)> &wrap); std::vector<uint8_t> buildFault(uint32_t callId, uint16_t contextId, uint32_t status); }; }; src/rpc/netlogon.cpp +378 −10 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
plugin/smb/smb.cpp +48 −6 Changes for plugin/smb/smb.cpp: 48 added lines, 6 removed lines. Original line number Diff line number Diff line Loading @@ -164,11 +164,30 @@ void RpcPipe::handlePdu(const std::vector<uint8_t> &pdu) { std::cerr << "[RPC] BIND auth=" << b.hasAuth << " type=" << int(b.authType) << " level=" << int(b.authLevel) << " token=" << b.authToken.size() << "B" << " iface=" << _name << std::endl; auto known = [](const rpc::SyntaxId &a) { return rpc::isLsarpc(a.uuid) || rpc::isSamr(a.uuid) || rpc::isNetlogon(a.uuid); }; _boundAbstract = b.contexts[0].abstractSyntax; _bound = true; 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); }); if (b.hasAuth && b.authType == rpc::AUTH_TYPE_SCHANNEL) { /* netlogon secure channel: the client names its computer, we * take the session key of its ServerAuthenticate3 */ rpc::NlAuthNegotiate neg; std::vector<uint8_t> sk; if (rpc::parseNlAuthNegotiate(b.authToken, neg) && rpc::netlogonChannelKey(neg.computer, sk)) { _netsec = rpc::NetsecContext(sk, neg.computer); resp = rpc::buildBindAck(b, "\\PIPE\\" + _name, rpc::buildNlAuthResponse(), b.authType, b.authLevel, known, b.authContextId); std::cerr << "[RPC] schannel bind for '" << neg.computer << "'" << std::endl; } else { std::cerr << "[RPC] schannel bind: no secure channel for '" << neg.computer << "'" << std::endl; resp = rpc::buildBindNak(h.callId); } } else { resp = rpc::buildBindAck(b, "\\PIPE\\" + _name, {}, 0, 0, known); } if (h.pduType == rpc::PDU_ALTER && resp.size() > 2 && resp[2] == rpc::PDU_BIND_ACK) resp[2] = rpc::PDU_ALTER_ACK; } else { resp = rpc::buildBindNak(h.callId); } Loading @@ -180,13 +199,25 @@ void RpcPipe::handlePdu(const std::vector<uint8_t> &pdu) { if (req.hasAuth) std::cerr << "[RPC] REQUEST opnum=" << req.opnum << " auth type=" << int(req.authType) << " level=" << int(req.authLevel) << " token=" << req.authToken.size() << "B" << std::endl; if (req.hasAuth && req.authType == rpc::AUTH_TYPE_SCHANNEL) { bool seal = req.authLevel == rpc::AUTH_LEVEL_PRIVACY; if (!_netsec.valid() || !_netsec.unwrapRequest(req.stub, req.authToken, seal)) { std::cerr << "[RPC] schannel request rejected (signature)" << std::endl; resp = rpc::buildFault(req.callId, req.contextId, 0x00000005); /* access denied */ } else { if (req.authPadLength <= req.stub.size()) req.stub.resize(req.stub.size() - req.authPadLength); resp = dispatch(req, true); } } else { resp = dispatch(req); } } } _out.insert(_out.end(), resp.begin(), resp.end()); } std::vector<uint8_t> RpcPipe::dispatch(const rpc::RequestPdu &req) { std::vector<uint8_t> RpcPipe::dispatch(const rpc::RequestPdu &req, bool schannel) { rpc::DispatchResult res; const char *iface = "?"; if (rpc::isLsarpc(_boundAbstract.uuid)) { Loading @@ -197,7 +228,8 @@ std::vector<uint8_t> RpcPipe::dispatch(const rpc::RequestPdu &req) { res = rpc::samrDispatch(req.opnum, req.stub, _sessionKey, _appKey); } else if (rpc::isNetlogon(_boundAbstract.uuid)) { iface = "netlogon"; res = rpc::netlogonDispatch(req.opnum, req.stub, _sessionKey); res = rpc::netlogonDispatch(req.opnum, req.stub, _sessionKey, schannel ? _netsec.computer() : std::string()); } else { res.fault = true; res.faultCode = 0x1C010003; /* nca_unk_if */ Loading @@ -214,6 +246,14 @@ std::vector<uint8_t> RpcPipe::dispatch(const rpc::RequestPdu &req) { } if (res.fault) return rpc::buildFault(req.callId, req.contextId, res.faultCode); if (schannel) { bool seal = req.authLevel == rpc::AUTH_LEVEL_PRIVACY; size_t sigLen = req.authToken.size(); return rpc::buildAuthResponse(req.callId, req.contextId, res.stub, req.authType, req.authLevel, req.authContextId, [&](std::vector<uint8_t> &data) { return _netsec.wrapResponse(data, seal, sigLen); }); } return rpc::buildResponse(req.callId, req.contextId, res.stub); } Loading Loading @@ -1817,7 +1857,7 @@ std::vector<uint8_t> SmbServer::setInfo(Conn &c, Session &s, const smb::Smb2Head extern "C" { fenrirds::Plugin *fenrirds_plugin_create(fenrirds::AuthBackend &backend, const char *configJson) { std::string bindAddr = "0.0.0.0", host; std::string bindAddr = "0.0.0.0", host, address; int port = 445; if (configJson) { json_object *j = json_tokener_parse(configJson); Loading @@ -1825,9 +1865,11 @@ fenrirds::Plugin *fenrirds_plugin_create(fenrirds::AuthBackend &backend, const c if (auto *x = json_object_object_get(j, "smb_bind")) bindAddr = json_object_get_string(x); if (auto *x = json_object_object_get(j, "smb_port")) port = json_object_get_int(x); if (auto *x = json_object_object_get(j, "dns_hostname")) host = json_object_get_string(x); if (auto *x = json_object_object_get(j, "dns_address")) address = json_object_get_string(x); json_object_put(j); } } fenrirds::rpc::setDcIdentity(host, address); return new fenrirds::SmbServer(backend, bindAddr, port, host); } Loading
plugin/smb/smb.h +2 −1 Changes for plugin/smb/smb.h: 2 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -45,7 +45,7 @@ namespace fenrirds { private: void handlePdu(const std::vector<uint8_t> &pdu); std::vector<uint8_t> dispatch(const rpc::RequestPdu &req); std::vector<uint8_t> dispatch(const rpc::RequestPdu &req, bool schannel = false); std::string _name; std::vector<uint8_t> _in; /* request assembly */ Loading @@ -55,6 +55,7 @@ namespace fenrirds { bool _bound = false; std::vector<uint8_t> _sessionKey; std::vector<uint8_t> _appKey; rpc::NetsecContext _netsec; /* netlogon schannel bind (auth type 68) */ }; /*************************************************************************** Loading
src/rpc/dcerpc.cpp +37 −7 Changes for src/rpc/dcerpc.cpp: 37 added lines, 7 removed lines. Original line number Diff line number Diff line Loading @@ -47,7 +47,8 @@ bool parseCommonHeader(const uint8_t *d, size_t n, CommonHeader &h) { } static void parseAuthTrailer(const uint8_t *d, size_t n, const CommonHeader &h, bool &hasAuth, std::vector<uint8_t> &tok, uint8_t &type, uint8_t &level) { bool &hasAuth, std::vector<uint8_t> &tok, uint8_t &type, uint8_t &level, uint8_t *padLen = nullptr, uint32_t *ctxId = nullptr) { if (h.authLength == 0 || h.fragLength > n) return; /* auth trailer = 8-byte sec_trailer header + authLength bytes, at the end */ Loading @@ -56,6 +57,8 @@ static void parseAuthTrailer(const uint8_t *d, size_t n, const CommonHeader &h, return; type = d[authStart]; level = d[authStart + 1]; if (padLen) *padLen = d[authStart + 2]; if (ctxId) *ctxId = rd32(d + authStart + 4); tok.assign(d + authStart + 8, d + authStart + 8 + h.authLength); hasAuth = true; } Loading Loading @@ -98,7 +101,8 @@ bool parseBind(const uint8_t *d, size_t n, BindPdu &out) { } out.contexts.push_back(std::move(ctx)); } parseAuthTrailer(d, n, h, out.hasAuth, out.authToken, out.authType, out.authLevel); parseAuthTrailer(d, n, h, out.hasAuth, out.authToken, out.authType, out.authLevel, nullptr, &out.authContextId); return true; } Loading @@ -120,7 +124,8 @@ bool parseRequest(const uint8_t *d, size_t n, RequestPdu &out) { stubEnd = size_t(h.fragLength) - h.authLength - 8; if (stubEnd > n || stubEnd < o) return false; out.stub.assign(d + o, d + stubEnd); parseAuthTrailer(d, n, h, out.hasAuth, out.authToken, out.authType, out.authLevel); parseAuthTrailer(d, n, h, out.hasAuth, out.authToken, out.authType, out.authLevel, &out.authPadLength, &out.authContextId); return true; } Loading @@ -138,7 +143,7 @@ static std::vector<uint8_t> header(uint8_t type, uint8_t flags, uint32_t callId, } static void appendAuthTrailer(std::vector<uint8_t> &pdu, const std::vector<uint8_t> &tok, uint8_t type, uint8_t level) { uint8_t type, uint8_t level, uint32_t ctxId = 0) { if (tok.empty()) return; /* pad the stub to a 4-byte boundary (auth_pad) */ Loading @@ -148,13 +153,14 @@ static void appendAuthTrailer(std::vector<uint8_t> &pdu, const std::vector<uint8 pdu.push_back(level); pdu.push_back(pad); pdu.push_back(0); /* reserved */ wr32(pdu, 0); /* auth context id */ wr32(pdu, ctxId); /* auth context id */ pdu.insert(pdu.end(), tok.begin(), tok.end()); } 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::function<bool(const SyntaxId &)> &knownInterface) { const std::function<bool(const SyntaxId &)> &knownInterface, uint32_t authContextId) { std::vector<uint8_t> body; wr16(body, bind.maxXmitFrag ? bind.maxXmitFrag : 4280); wr16(body, bind.maxRecvFrag ? bind.maxRecvFrag : 4280); Loading Loading @@ -193,7 +199,7 @@ std::vector<uint8_t> buildBindAck(const BindPdu &bind, const std::string &sec, std::vector<uint8_t> pdu = header(PDU_BIND_ACK, PFC_FIRST_FRAG | PFC_LAST_FRAG, bind.callId, 0, authLen); pdu.insert(pdu.end(), body.begin(), body.end()); if (!authToken.empty()) appendAuthTrailer(pdu, authToken, authType, authLevel); appendAuthTrailer(pdu, authToken, authType, authLevel, authContextId); uint16_t frag = uint16_t(pdu.size()); pdu[8] = frag & 0xff; pdu[9] = frag >> 8; return pdu; Loading Loading @@ -226,6 +232,30 @@ std::vector<uint8_t> buildResponse(uint32_t callId, uint16_t contextId, return pdu; } std::vector<uint8_t> buildAuthResponse(uint32_t callId, uint16_t contextId, const std::vector<uint8_t> &stub, uint8_t authType, uint8_t authLevel, uint32_t authContextId, const std::function<std::vector<uint8_t>(std::vector<uint8_t> &)> &wrap) { std::vector<uint8_t> data = stub; uint8_t pad = uint8_t((16 - data.size() % 16) % 16); data.resize(data.size() + pad, 0); std::vector<uint8_t> tok = wrap(data); std::vector<uint8_t> pdu = header(PDU_RESPONSE, PFC_FIRST_FRAG | PFC_LAST_FRAG, callId, 0, uint16_t(tok.size())); wr32(pdu, uint32_t(stub.size())); /* alloc_hint */ wr16(pdu, contextId); wr16(pdu, 0); pdu.insert(pdu.end(), data.begin(), data.end()); pdu.push_back(authType); pdu.push_back(authLevel); pdu.push_back(pad); pdu.push_back(0); wr32(pdu, authContextId); pdu.insert(pdu.end(), tok.begin(), tok.end()); uint16_t frag = uint16_t(pdu.size()); pdu[8] = frag & 0xff; pdu[9] = frag >> 8; return pdu; } std::vector<uint8_t> buildFault(uint32_t callId, uint16_t contextId, uint32_t status) { std::vector<uint8_t> pdu = header(PDU_FAULT, PFC_FIRST_FRAG | PFC_LAST_FRAG, callId, 0, 0); wr32(pdu, 0); /* alloc_hint */ Loading
src/rpc/dcerpc.h +11 −1 Changes for src/rpc/dcerpc.h: 11 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ namespace fenrirds { std::vector<uint8_t> authToken; uint8_t authType = 0; uint8_t authLevel = 0; uint32_t authContextId = 0; }; /* a parsed REQUEST */ Loading @@ -75,6 +76,8 @@ namespace fenrirds { std::vector<uint8_t> authToken; uint8_t authType = 0; uint8_t authLevel = 0; uint8_t authPadLength = 0; /* stub ends with this many pad bytes */ uint32_t authContextId = 0; }; bool parseCommonHeader(const uint8_t *d, size_t n, CommonHeader &h); Loading @@ -90,7 +93,8 @@ namespace fenrirds { 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, const std::function<bool(const SyntaxId &)> &knownInterface = nullptr); const std::function<bool(const SyntaxId &)> &knownInterface = nullptr, uint32_t authContextId = 0); std::vector<uint8_t> buildBindNak(uint32_t callId); /* build a RESPONSE carrying the NDR stub (single fragment) */ Loading @@ -98,6 +102,12 @@ namespace fenrirds { const std::vector<uint8_t> &stub, const std::vector<uint8_t> &authToken = {}, uint8_t authType = 0, uint8_t authLevel = 0); /* a RESPONSE protected by a security provider: the stub is padded to * 16 bytes, wrap() signs/seals it in place and returns the auth_value */ std::vector<uint8_t> buildAuthResponse(uint32_t callId, uint16_t contextId, const std::vector<uint8_t> &stub, uint8_t authType, uint8_t authLevel, uint32_t authContextId, const std::function<std::vector<uint8_t>(std::vector<uint8_t> &)> &wrap); std::vector<uint8_t> buildFault(uint32_t callId, uint16_t contextId, uint32_t status); }; };
src/rpc/netlogon.cpp +378 −10 File changed.Preview size limit exceeded, changes collapsed. Show changes