DATA_BLOB pdu;
struct dcerpc_call *call;
bool valid_type = false;
+ bool allow_fragments = false;
conn->loop.subreq = NULL;
case DCERPC_PKT_REQUEST:
/* Ordinary request. */
valid_type = true;
+ allow_fragments = true;
break;
case DCERPC_PKT_PING:
case DCERPC_PKT_RESPONSE:
/* Ordinary reply. */
valid_type = true;
+ allow_fragments = true;
break;
case DCERPC_PKT_FAULT:
return;
}
+ if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
+ if (!allow_fragments) {
+ TALLOC_FREE(subreq);
+ // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
+ return;
+ }
+ }
+
if (conn->calls.active != NULL) {
+
if (pkt->call_id != conn->calls.active->call_id) {
TALLOC_FREE(subreq);
// disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
return;
}
+
+ if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
+ TALLOC_FREE(subreq);
+ // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
+ return;
+ }
+
call = conn->calls.active;
+
+ if (pkt->pfc_flags & DCERPC_PFC_FLAG_LAST) {
+ conn->calls.active = NULL;
+ }
} else {
+ if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
+ TALLOC_FREE(subreq);
+ // disconnect and notify pending calls NT_STATUS_RPC_PROTOCOL_ERROR;
+ return;
+ }
+
call = conn->calls.list;
}
return;
}
+ if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_LAST)) {
+ conn->calls.active = call;
+
+ // TODO
+ //
+ // reassemble and return
+ }
+
error = call->incoming.handler(call->incoming.private_data, pkt, pdu);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(error)) {
if (!state->got_first) {
state->got_first = true;
- if (!(pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST)) {
- return NT_STATUS_RPC_PROTOCOL_ERROR;
- }
-
- state->conn->calls.active = state->call;
-
if (pkt->drep[0] & DCERPC_DREP_LE) {
state->response.bigendian = false;
} else {
if (state->verify_pcontext) {
state->call->pres->verified_pcontext = true;
}
- } else {
- if (pkt->pfc_flags & DCERPC_PFC_FLAG_FIRST) {
- return NT_STATUS_RPC_PROTOCOL_ERROR;
- }
}
if (state->response.bigendian) {