uint16_t opnum;
DATA_BLOB request_data;
bool ignore_timeout;
+ bool wait_for_sync;
/* use by the ndr level async recv call */
struct {
ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
}
+ if (CVAL(blob->data, DCERPC_PFC_OFFSET) & DCERPC_PFC_FLAG_OBJECT_UUID) {
+ ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
+ }
+
ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return ndr_map_error2ntstatus(ndr_err);
}
+ if (pkt->frag_length != blob->length) {
+ return NT_STATUS_RPC_PROTOCOL_ERROR;
+ }
+
return NT_STATUS_OK;
}
size_t hdr_size = DCERPC_REQUEST_LENGTH;
/* non-signed packets are simpler */
- if (sig_size == 0) {
+ if (c->security_state.auth_info == NULL) {
return ncacn_push_auth(blob, mem_ctx, pkt, NULL);
}
switch (c->security_state.auth_info->auth_level) {
case DCERPC_AUTH_LEVEL_PRIVACY:
case DCERPC_AUTH_LEVEL_INTEGRITY:
+ if (sig_size == 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
break;
case DCERPC_AUTH_LEVEL_CONNECT:
if (req->recv_handler != NULL) {
dcerpc_req_dequeue(req);
req->state = RPC_REQUEST_DONE;
+
+ /*
+ * We have to look at shipping further requests before calling
+ * the async function, that one might close the pipe
+ */
+ dcerpc_schedule_io_trigger(c);
+
req->recv_handler(req, raw_packet, pkt);
return;
}
req_done:
/* we've got the full payload */
+ dcerpc_req_dequeue(req);
req->state = RPC_REQUEST_DONE;
- DLIST_REMOVE(c->pending, req);
/*
* We have to look at shipping further requests before calling
p->conn->transport.recv_data = dcerpc_recv_data;
- req = talloc(mem_ctx, struct rpc_request);
+ req = talloc_zero(mem_ctx, struct rpc_request);
if (req == NULL) {
return NULL;
}
req->p = p;
req->call_id = next_call_id(p->conn);
- req->status = NT_STATUS_OK;
req->state = RPC_REQUEST_QUEUED;
- req->payload = data_blob(NULL, 0);
- req->flags = 0;
- req->fault_code = 0;
- req->ignore_timeout = false;
- req->async.callback = NULL;
- req->async.private_data = NULL;
- req->recv_handler = NULL;
if (object != NULL) {
req->object = (struct GUID *)talloc_memdup(req, (const void *)object, sizeof(*object));
talloc_free(req);
return NULL;
}
- } else {
- req->object = NULL;
}
req->opnum = opnum;
bool first_packet = true;
size_t sig_size = 0;
bool need_async = false;
+ bool can_async = true;
req = c->request_queue;
if (req == NULL) {
need_async = true;
}
+ if (c->security_state.auth_info &&
+ c->security_state.generic_state)
+ {
+ struct gensec_security *gensec = c->security_state.generic_state;
+
+ switch (c->security_state.auth_info->auth_level) {
+ case DCERPC_AUTH_LEVEL_PRIVACY:
+ case DCERPC_AUTH_LEVEL_INTEGRITY:
+ can_async = gensec_have_feature(gensec,
+ GENSEC_FEATURE_ASYNC_REPLIES);
+ break;
+ case DCERPC_AUTH_LEVEL_CONNECT:
+ case DCERPC_AUTH_LEVEL_NONE:
+ can_async = true;
+ break;
+ default:
+ can_async = false;
+ break;
+ }
+ }
+
+ if (need_async && !can_async) {
+ req->wait_for_sync = true;
+ return;
+ }
+
DLIST_REMOVE(c->request_queue, req);
DLIST_ADD(c->pending, req);
req->state = RPC_REQUEST_PENDING;
chunk_size -= DCERPC_REQUEST_LENGTH;
if (c->security_state.auth_info &&
c->security_state.generic_state) {
+ 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(c->security_state.generic_state,
- p->conn->srv_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);
pkt.ptype = DCERPC_PKT_REQUEST;
pkt.call_id = req->call_id;
return;
}
+ if (c->request_queue->wait_for_sync && c->pending) {
+ return;
+ }
+
if (c->io_trigger_pending) {
return;
}
if (pkt->ptype == DCERPC_PKT_FAULT) {
DEBUG(5,("dcerpc: alter_resp - rpc fault: %s\n",
dcerpc_errstr(state, pkt->u.fault.status)));
- state->p->last_fault_code = pkt->u.fault.status;
- tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
+ if (pkt->u.fault.status == DCERPC_FAULT_ACCESS_DENIED) {
+ state->p->last_fault_code = pkt->u.fault.status;
+ tevent_req_nterror(req, NT_STATUS_LOGON_FAILURE);
+ } else {
+ state->p->last_fault_code = pkt->u.fault.status;
+ tevent_req_nterror(req, NT_STATUS_NET_WRITE_FAULT);
+ }
return;
}