#include "lib/socket/socket.h"
#include "smbd/process_model.h"
#include "lib/messaging/irpc.h"
+#include "librpc/rpc/rpc_common.h"
/*
case DCESRV_LIST_NONE:
break;
case DCESRV_LIST_CALL_LIST:
- DLIST_ADD_END(call->conn->call_list, call, struct dcesrv_call_state *);
+ DLIST_ADD_END(call->conn->call_list, call);
break;
case DCESRV_LIST_FRAGMENTED_CALL_LIST:
- DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call, struct dcesrv_call_state *);
+ DLIST_ADD_END(call->conn->incoming_fragmented_call_list, call);
break;
case DCESRV_LIST_PENDING_CALL_LIST:
- DLIST_ADD_END(call->conn->pending_call_list, call, struct dcesrv_call_state *);
+ DLIST_ADD_END(call->conn->pending_call_list, call);
break;
}
}
/*
return a dcerpc fault
*/
-NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code)
+NTSTATUS dcesrv_fault_with_flags(struct dcesrv_call_state *call,
+ uint32_t fault_code,
+ uint8_t extra_flags)
{
struct ncacn_packet pkt;
struct data_blob_list_item *rep;
- uint8_t zeros[4];
NTSTATUS status;
- /* setup a bind_ack */
+ /* setup a fault */
dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
pkt.auth_length = 0;
pkt.call_id = call->pkt.call_id;
pkt.ptype = DCERPC_PKT_FAULT;
- pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
- pkt.u.fault.alloc_hint = 0;
- pkt.u.fault.context_id = 0;
+ pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST | extra_flags;
+ pkt.u.fault.alloc_hint = 24;
+ if (call->context != NULL) {
+ pkt.u.fault.context_id = call->context->context_id;
+ } else {
+ pkt.u.fault.context_id = 0;
+ }
pkt.u.fault.cancel_count = 0;
+ pkt.u.fault.flags = 0;
pkt.u.fault.status = fault_code;
+ pkt.u.fault.reserved = 0;
+ pkt.u.fault.error_and_verifier = data_blob_null;
- ZERO_STRUCT(zeros);
- pkt.u.fault._pad = data_blob_const(zeros, sizeof(zeros));
-
- rep = talloc(call, struct data_blob_list_item);
+ rep = talloc_zero(call, struct data_blob_list_item);
if (!rep) {
return NT_STATUS_NO_MEMORY;
}
dcerpc_set_frag_length(&rep->blob, rep->blob.length);
- DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
+ DLIST_ADD_END(call->replies, rep);
dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST);
if (call->conn->call_list && call->conn->call_list->replies) {
return NT_STATUS_OK;
}
-
+NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32_t fault_code)
+{
+ return dcesrv_fault_with_flags(call, fault_code, 0);
+}
_PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call)
{
/* we can write a full max_recv_frag size, minus the dcerpc
request header size */
- chunk_size = call->conn->cli_max_recv_frag;
+ chunk_size = call->conn->max_xmit_frag;
chunk_size -= DCERPC_REQUEST_LENGTH;
- if (call->conn->auth_state.auth_info &&
+ if (call->conn->auth_state.auth_finished &&
call->conn->auth_state.gensec_security) {
+ size_t max_payload = chunk_size;
+
+ max_payload -= DCERPC_AUTH_TRAILER_LENGTH;
+ max_payload -= (max_payload % DCERPC_AUTH_PAD_ALIGNMENT);
+
sig_size = gensec_sig_size(call->conn->auth_state.gensec_security,
- call->conn->cli_max_recv_frag);
+ max_payload);
if (sig_size) {
chunk_size -= DCERPC_AUTH_TRAILER_LENGTH;
chunk_size -= sig_size;
}
}
- chunk_size -= (chunk_size % 16);
+ chunk_size -= (chunk_size % DCERPC_AUTH_PAD_ALIGNMENT);
do {
uint32_t length;
struct data_blob_list_item *rep;
struct ncacn_packet pkt;
+ bool ok;
- rep = talloc(call, struct data_blob_list_item);
+ rep = talloc_zero(call, struct data_blob_list_item);
NT_STATUS_HAVE_NO_MEMORY(rep);
length = MIN(chunk_size, stub.length);
/* form the dcerpc response packet */
- dcesrv_init_hdr(&pkt, lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
+ dcesrv_init_hdr(&pkt,
+ lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx));
pkt.auth_length = 0;
pkt.call_id = call->pkt.call_id;
pkt.ptype = DCERPC_PKT_RESPONSE;
pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
}
pkt.u.response.alloc_hint = stub.length;
- pkt.u.response.context_id = call->pkt.u.request.context_id;
+ /*
+ * bug for bug, feature for feature...
+ *
+ * Windows truncates the context_id with & 0xFF,
+ * so we do.
+ */
+ pkt.u.response.context_id = context->context_id & 0xFF;
pkt.u.response.cancel_count = 0;
pkt.u.response.stub_and_verifier.data = stub.data;
pkt.u.response.stub_and_verifier.length = length;
- if (!dcesrv_auth_response(call, &rep->blob, sig_size, &pkt)) {
+ ok = dcesrv_auth_pkt_push(call, &rep->blob, sig_size,
+ DCERPC_RESPONSE_LENGTH,
+ &pkt.u.response.stub_and_verifier,
+ &pkt);
+ if (!ok) {
return dcesrv_fault(call, DCERPC_FAULT_OTHER);
}
dcerpc_set_frag_length(&rep->blob, rep->blob.length);
- DLIST_ADD_END(call->replies, rep, struct data_blob_list_item *);
+ DLIST_ADD_END(call->replies, rep);
stub.data += length;
stub.length -= length;
NTSTATUS dcesrv_generic_session_key(struct dcesrv_connection *c,
DATA_BLOB *session_key)
{
+ enum dcerpc_transport_t transport =
+ dcerpc_binding_get_transport(c->endpoint->ep_description);
+
+ if (transport != NCALRPC && transport != NCACN_UNIX_STREAM) {
+ return NT_STATUS_NO_USER_SESSION_KEY;
+ }
+
return dcerpc_generic_session_key(NULL, session_key);
}