static bool api_HrRBackupTruncateLogs(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct HrRBackupTruncateLogs *r; call = &ndr_table_ad_backup.calls[NDR_HRRBACKUPTRUNCATELOGS]; r = talloc(talloc_tos(), struct HrRBackupTruncateLogs); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(HrRBackupTruncateLogs, NDR_IN, r); } _HrRBackupTruncateLogs(p, r); if (p->fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(HrRBackupTruncateLogs, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
static bool api_frstrans_RequestUpdates(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct frstrans_RequestUpdates *r; call = &ndr_table_frstrans.calls[NDR_FRSTRANS_REQUESTUPDATES]; r = talloc(talloc_tos(), struct frstrans_RequestUpdates); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(frstrans_RequestUpdates, NDR_IN, r); } ZERO_STRUCT(r->out); r->out.frs_update = talloc_zero_array(r, struct frstrans_Update, r->in.credits_available); if (r->out.frs_update == NULL) { talloc_free(r); return false; } r->out.update_count = talloc_zero(r, uint32_t); if (r->out.update_count == NULL) { talloc_free(r); return false; } r->out.update_status = talloc_zero(r, enum frstrans_UpdateStatus); if (r->out.update_status == NULL) { talloc_free(r); return false; } r->out.gvsn_db_guid = talloc_zero(r, struct GUID); if (r->out.gvsn_db_guid == NULL) { talloc_free(r); return false; } r->out.gvsn_version = talloc_zero(r, uint64_t); if (r->out.gvsn_version == NULL) { talloc_free(r); return false; } r->out.result = _frstrans_RequestUpdates(p, r); if (p->fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(frstrans_RequestUpdates, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
static bool api_frstrans_CheckConnectivity(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct frstrans_CheckConnectivity *r; call = &ndr_table_frstrans.calls[NDR_FRSTRANS_CHECKCONNECTIVITY]; r = talloc(talloc_tos(), struct frstrans_CheckConnectivity); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(frstrans_CheckConnectivity, NDR_IN, r); } r->out.result = _frstrans_CheckConnectivity(p, r); if (p->fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(frstrans_CheckConnectivity, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
static bool api_frsrpc_FrsStartPromotionParent(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct frsrpc_FrsStartPromotionParent *r; call = &ndr_table_frsrpc.calls[NDR_FRSRPC_FRSSTARTPROMOTIONPARENT]; r = talloc(talloc_tos(), struct frsrpc_FrsStartPromotionParent); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(frsrpc_FrsStartPromotionParent, NDR_IN, r); } ZERO_STRUCT(r->out); r->out.parent_guid = r->in.parent_guid; r->out.result = _frsrpc_FrsStartPromotionParent(p, r); if (p->fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(frsrpc_FrsStartPromotionParent, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
static bool api_frstrans_InitializeFileTransferAsync(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct frstrans_InitializeFileTransferAsync *r; call = &ndr_table_frstrans.calls[NDR_FRSTRANS_INITIALIZEFILETRANSFERASYNC]; r = talloc(talloc_tos(), struct frstrans_InitializeFileTransferAsync); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(frstrans_InitializeFileTransferAsync, NDR_IN, r); } ZERO_STRUCT(r->out); r->out.frs_update = r->in.frs_update; r->out.staging_policy = r->in.staging_policy; r->out.server_context = talloc_zero(r, struct policy_handle); if (r->out.server_context == NULL) { talloc_free(r); return false; } r->out.rdc_file_info = talloc_zero(r, struct frstrans_RdcFileInfo *); if (r->out.rdc_file_info == NULL) { talloc_free(r); return false; } r->out.data_buffer = talloc_zero_array(r, uint8_t, r->in.buffer_size); if (r->out.data_buffer == NULL) { talloc_free(r); return false; } r->out.size_read = talloc_zero(r, uint32_t); if (r->out.size_read == NULL) { talloc_free(r); return false; } r->out.is_end_of_file = talloc_zero(r, uint32_t); if (r->out.is_end_of_file == NULL) { talloc_free(r); return false; } r->out.result = _frstrans_InitializeFileTransferAsync(p, r); if (p->fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(frstrans_InitializeFileTransferAsync, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
static bool api_fss_RecoveryCompleteShadowCopySet(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct fss_RecoveryCompleteShadowCopySet *r; call = &ndr_table_FileServerVssAgent.calls[NDR_FSS_RECOVERYCOMPLETESHADOWCOPYSET]; r = talloc(talloc_tos(), struct fss_RecoveryCompleteShadowCopySet); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(fss_RecoveryCompleteShadowCopySet, NDR_IN, r); } r->out.result = _fss_RecoveryCompleteShadowCopySet(p, r); if (p->fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(fss_RecoveryCompleteShadowCopySet, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
static bool api_fss_GetSupportedVersion(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct fss_GetSupportedVersion *r; call = &ndr_table_FileServerVssAgent.calls[NDR_FSS_GETSUPPORTEDVERSION]; r = talloc(talloc_tos(), struct fss_GetSupportedVersion); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(fss_GetSupportedVersion, NDR_IN, r); } ZERO_STRUCT(r->out); r->out.MinVersion = talloc_zero(r, uint32_t); if (r->out.MinVersion == NULL) { talloc_free(r); return false; } r->out.MaxVersion = talloc_zero(r, uint32_t); if (r->out.MaxVersion == NULL) { talloc_free(r); return false; } r->out.result = _fss_GetSupportedVersion(p, r); if (p->fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(fss_GetSupportedVersion, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
static bool api_eventlog_GetLogInformation(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct eventlog_GetLogInformation *r; call = &ndr_table_eventlog.calls[NDR_EVENTLOG_GETLOGINFORMATION]; r = talloc(talloc_tos(), struct eventlog_GetLogInformation); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(eventlog_GetLogInformation, NDR_IN, r); } ZERO_STRUCT(r->out); r->out.buffer = talloc_zero_array(r, uint8_t, r->in.buf_size); if (r->out.buffer == NULL) { talloc_free(r); return false; } r->out.bytes_needed = talloc_zero(r, uint32_t); if (r->out.bytes_needed == NULL) { talloc_free(r); return false; } r->out.result = _eventlog_GetLogInformation(p, r); if (p->rng_fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(eventlog_GetLogInformation, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
static bool api_eventlog_ReportEventW(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct eventlog_ReportEventW *r; call = &ndr_table_eventlog.calls[NDR_EVENTLOG_REPORTEVENTW]; r = talloc(talloc_tos(), struct eventlog_ReportEventW); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(eventlog_ReportEventW, NDR_IN, r); } ZERO_STRUCT(r->out); r->out.record_number = r->in.record_number; r->out.time_written = r->in.time_written; r->out.result = _eventlog_ReportEventW(p, r); if (p->rng_fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(eventlog_ReportEventW, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
static bool api_RemoteActivation(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct RemoteActivation *r; call = &ndr_table_IRemoteActivation.calls[NDR_REMOTEACTIVATION]; r = talloc(talloc_tos(), struct RemoteActivation); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(RemoteActivation, NDR_IN, r); } ZERO_STRUCT(r->out); r->out.that = talloc_zero(r, struct ORPCTHAT); if (r->out.that == NULL) { talloc_free(r); return false; } r->out.pOxid = talloc_zero(r, uint64_t); if (r->out.pOxid == NULL) { talloc_free(r); return false; } r->out.pdsaOxidBindings = talloc_zero(r, struct DUALSTRINGARRAY); if (r->out.pdsaOxidBindings == NULL) { talloc_free(r); return false; } r->out.ipidRemUnknown = talloc_zero(r, struct GUID); if (r->out.ipidRemUnknown == NULL) { talloc_free(r); return false; } r->out.AuthnHint = talloc_zero(r, uint32_t); if (r->out.AuthnHint == NULL) { talloc_free(r); return false; } r->out.ServerVersion = talloc_zero(r, struct COMVERSION); if (r->out.ServerVersion == NULL) { talloc_free(r); return false; } r->out.hr = talloc_zero(r, WERROR); if (r->out.hr == NULL) { talloc_free(r); return false; } r->out.ifaces = talloc_zero_array(r, struct MInterfacePointer *, r->in.Interfaces); if (r->out.ifaces == NULL) { talloc_free(r); return false; } r->out.results = talloc_zero_array(r, WERROR, r->in.Interfaces); if (r->out.results == NULL) { talloc_free(r); return false; } r->out.result = _RemoteActivation(p, r); if (p->fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(RemoteActivation, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
_PUBLIC_ NTSTATUS dcesrv_reply(struct dcesrv_call_state *call) { struct ndr_push *push; NTSTATUS status; DATA_BLOB stub; uint32_t total_length, chunk_size; struct dcesrv_connection_context *context = call->context; size_t sig_size = 0; /* call the reply function */ status = context->iface->reply(call, call, call->r); if (!NT_STATUS_IS_OK(status)) { return dcesrv_fault(call, call->fault_code); } /* form the reply NDR */ push = ndr_push_init_ctx(call); NT_STATUS_HAVE_NO_MEMORY(push); /* carry over the pointer count to the reply in case we are using full pointer. See NDR specification for full pointers */ push->ptr_count = call->ndr_pull->ptr_count; if (lpcfg_rpc_big_endian(call->conn->dce_ctx->lp_ctx)) { push->flags |= LIBNDR_FLAG_BIGENDIAN; } status = context->iface->ndr_push(call, call, push, call->r); if (!NT_STATUS_IS_OK(status)) { return dcesrv_fault(call, call->fault_code); } stub = ndr_push_blob(push); total_length = stub.length; /* 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 -= DCERPC_REQUEST_LENGTH; if (call->conn->auth_state.auth_info && 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, max_payload); if (sig_size) { chunk_size -= DCERPC_AUTH_TRAILER_LENGTH; chunk_size -= sig_size; } } chunk_size -= (chunk_size % DCERPC_AUTH_PAD_ALIGNMENT); do { uint32_t length; struct data_blob_list_item *rep; struct ncacn_packet pkt; rep = talloc(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)); pkt.auth_length = 0; pkt.call_id = call->pkt.call_id; pkt.ptype = DCERPC_PKT_RESPONSE; pkt.pfc_flags = 0; if (stub.length == total_length) { pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST; } if (length == stub.length) { 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; pkt.u.response.cancel_count = 0; pkt.u.response._pad.data = call->pkt.u.request._pad.data; pkt.u.response._pad.length = call->pkt.u.request._pad.length; 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)) { return dcesrv_fault(call, DCERPC_FAULT_OTHER); } dcerpc_set_frag_length(&rep->blob, rep->blob.length); DLIST_ADD_END(call->replies, rep); stub.data += length; stub.length -= length; } while (stub.length != 0); /* move the call from the pending to the finished calls list */ dcesrv_call_set_list(call, DCESRV_LIST_CALL_LIST); if (call->conn->call_list && call->conn->call_list->replies) { if (call->conn->transport.report_output_data) { call->conn->transport.report_output_data(call->conn); } } return NT_STATUS_OK; }
static bool api_EfsRpcDuplicateEncryptionInfoFile(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct EfsRpcDuplicateEncryptionInfoFile *r; call = &ndr_table_efs.calls[NDR_EFSRPCDUPLICATEENCRYPTIONINFOFILE]; r = talloc(talloc_tos(), struct EfsRpcDuplicateEncryptionInfoFile); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(EfsRpcDuplicateEncryptionInfoFile, NDR_IN, r); } r->out.result = _EfsRpcDuplicateEncryptionInfoFile(p, r); if (p->fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(EfsRpcDuplicateEncryptionInfoFile, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
static bool api_BrowserrQueryOtherDomains(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct BrowserrQueryOtherDomains *r; call = &ndr_table_browser.calls[NDR_BROWSERRQUERYOTHERDOMAINS]; r = talloc(talloc_tos(), struct BrowserrQueryOtherDomains); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(BrowserrQueryOtherDomains, NDR_IN, r); } ZERO_STRUCT(r->out); r->out.info = r->in.info; r->out.total_entries = talloc_zero(r, uint32_t); if (r->out.total_entries == NULL) { talloc_free(r); return false; } r->out.result = _BrowserrQueryOtherDomains(p, r); if (p->fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(BrowserrQueryOtherDomains, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const struct ndr_interface_table *table, uint32 opnum, void *r) { #ifdef AVM_SMALL return NT_STATUS_NO_MEMORY; #else prs_struct q_ps, r_ps; const struct ndr_interface_call *call; struct ndr_pull *pull; DATA_BLOB blob; struct ndr_push *push; NTSTATUS status; enum ndr_err_code ndr_err; SMB_ASSERT(ndr_syntax_id_equal(&table->syntax_id, &cli->abstract_syntax)); SMB_ASSERT(table->num_calls > opnum); call = &table->calls[opnum]; push = ndr_push_init_ctx(mem_ctx); if (!push) { return NT_STATUS_NO_MEMORY; } ndr_err = call->ndr_push(push, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return ndr_map_error2ntstatus(ndr_err); } blob = ndr_push_blob(push); if (!prs_init_data_blob(&q_ps, &blob, mem_ctx)) { return NT_STATUS_NO_MEMORY; } talloc_free(push); prs_init_empty( &r_ps, mem_ctx, UNMARSHALL ); status = rpc_api_pipe_req(cli, opnum, &q_ps, &r_ps); prs_mem_free( &q_ps ); if (!NT_STATUS_IS_OK(status)) { prs_mem_free( &r_ps ); return status; } if (!prs_data_blob(&r_ps, &blob, mem_ctx)) { prs_mem_free( &r_ps ); return NT_STATUS_NO_MEMORY; } prs_mem_free( &r_ps ); pull = ndr_pull_init_blob(&blob, mem_ctx); if (pull == NULL) { return NT_STATUS_NO_MEMORY; } /* have the ndr parser alloc memory for us */ pull->flags |= LIBNDR_FLAG_REF_ALLOC; ndr_err = call->ndr_pull(pull, NDR_OUT, r); talloc_free(pull); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return ndr_map_error2ntstatus(ndr_err); } return NT_STATUS_OK; #endif }
/* push a signed or sealed dcerpc request packet into a blob */ bool dcesrv_auth_response(struct dcesrv_call_state *call, DATA_BLOB *blob, size_t sig_size, struct ncacn_packet *pkt) { struct dcesrv_connection *dce_conn = call->conn; NTSTATUS status; enum ndr_err_code ndr_err; struct ndr_push *ndr; uint32_t payload_length; DATA_BLOB creds2; /* non-signed packets are simple */ if (sig_size == 0) { status = ncacn_push_auth(blob, call, pkt, NULL); return NT_STATUS_IS_OK(status); } switch (dce_conn->auth_state.auth_info->auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: case DCERPC_AUTH_LEVEL_INTEGRITY: break; case DCERPC_AUTH_LEVEL_CONNECT: /* * TODO: let the gensec mech decide if it wants to generate a * signature that might be needed for schannel... */ status = ncacn_push_auth(blob, call, pkt, NULL); return NT_STATUS_IS_OK(status); case DCERPC_AUTH_LEVEL_NONE: status = ncacn_push_auth(blob, call, pkt, NULL); return NT_STATUS_IS_OK(status); default: return false; } ndr = ndr_push_init_ctx(call); if (!ndr) { return false; } if (!(pkt->drep[0] & DCERPC_DREP_LE)) { ndr->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return false; } /* pad to 16 byte multiple in the payload portion of the packet. This matches what w2k3 does. Note that we can't use ndr_push_align() as that is relative to the start of the whole packet, whereas w2k8 wants it relative to the start of the stub */ dce_conn->auth_state.auth_info->auth_pad_length = (16 - (pkt->u.response.stub_and_verifier.length & 15)) & 15; ndr_err = ndr_push_zero(ndr, dce_conn->auth_state.auth_info->auth_pad_length); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return false; } payload_length = pkt->u.response.stub_and_verifier.length + dce_conn->auth_state.auth_info->auth_pad_length; /* we start without signature, it will appended later */ dce_conn->auth_state.auth_info->credentials = data_blob(NULL, 0); /* add the auth verifier */ ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, dce_conn->auth_state.auth_info); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return false; } /* extract the whole packet as a blob */ *blob = ndr_push_blob(ndr); /* * Setup the frag and auth length in the packet buffer. * This is needed if the GENSEC mech does AEAD signing * of the packet headers. The signature itself will be * appended later. */ dcerpc_set_frag_length(blob, blob->length + sig_size); dcerpc_set_auth_length(blob, sig_size); /* sign or seal the packet */ switch (dce_conn->auth_state.auth_info->auth_level) { case DCERPC_AUTH_LEVEL_PRIVACY: status = gensec_seal_packet(dce_conn->auth_state.gensec_security, call, ndr->data + DCERPC_REQUEST_LENGTH, payload_length, blob->data, blob->length, &creds2); break; case DCERPC_AUTH_LEVEL_INTEGRITY: status = gensec_sign_packet(dce_conn->auth_state.gensec_security, call, ndr->data + DCERPC_REQUEST_LENGTH, payload_length, blob->data, blob->length, &creds2); break; default: status = NT_STATUS_INVALID_LEVEL; break; } if (!NT_STATUS_IS_OK(status)) { return false; } if (creds2.length != sig_size) { DEBUG(3,("dcesrv_auth_response: creds2.length[%u] != sig_size[%u] pad[%u] stub[%u]\n", (unsigned)creds2.length, (uint32_t)sig_size, (unsigned)dce_conn->auth_state.auth_info->auth_pad_length, (unsigned)pkt->u.response.stub_and_verifier.length)); dcerpc_set_frag_length(blob, blob->length + creds2.length); dcerpc_set_auth_length(blob, creds2.length); } if (!data_blob_append(call, blob, creds2.data, creds2.length)) { status = NT_STATUS_NO_MEMORY; return false; } data_blob_free(&creds2); return true; }
NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int p_idx, int opnum, void *data, ndr_pull_flags_fn_t pull_fn, ndr_push_flags_fn_t push_fn) { prs_struct q_ps, r_ps; struct ndr_pull *pull; DATA_BLOB blob; struct ndr_push *push; NTSTATUS status; SMB_ASSERT(cli->pipe_idx == p_idx); push = ndr_push_init_ctx(mem_ctx); if (!push) { return NT_STATUS_NO_MEMORY; } status = push_fn(push, NDR_IN, data); if (!NT_STATUS_IS_OK(status)) { return status; } blob = ndr_push_blob(push); if (!prs_init_data_blob(&q_ps, &blob, mem_ctx)) { return NT_STATUS_NO_MEMORY; } talloc_free(push); if (!prs_init( &r_ps, 0, mem_ctx, UNMARSHALL )) { prs_mem_free( &q_ps ); return NT_STATUS_NO_MEMORY; } status = rpc_api_pipe_req(cli, opnum, &q_ps, &r_ps); prs_mem_free( &q_ps ); if (!NT_STATUS_IS_OK(status)) { prs_mem_free( &r_ps ); return status; } if (!prs_data_blob(&r_ps, &blob, mem_ctx)) { prs_mem_free( &r_ps ); return NT_STATUS_NO_MEMORY; } prs_mem_free( &r_ps ); pull = ndr_pull_init_blob(&blob, mem_ctx); if (pull == NULL) { return NT_STATUS_NO_MEMORY; } /* have the ndr parser alloc memory for us */ pull->flags |= LIBNDR_FLAG_REF_ALLOC; status = pull_fn(pull, NDR_OUT, data); talloc_free(pull); if (!NT_STATUS_IS_OK(status)) { return status; } return NT_STATUS_OK; }