bool init_pipe_handle_list(pipes_struct *p, const struct ndr_syntax_id *syntax) { pipes_struct *plist; struct handle_list *hl; for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist)) { if (ndr_syntax_id_equal(syntax, &plist->syntax)) { break; } if (is_samr_lsa_pipe(&plist->syntax) && is_samr_lsa_pipe(syntax)) { /* * samr and lsa share a handle space (same process * under Windows?) */ break; } } if (plist != NULL) { hl = plist->pipe_handles; if (hl == NULL) { return false; } } else { /* * First open, we have to create the handle list */ hl = SMB_MALLOC_P(struct handle_list); if (hl == NULL) { return false; } ZERO_STRUCTP(hl); DEBUG(10,("init_pipe_handles: created handle list for " "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(), syntax))); } /* * One more pipe is using this list. */ hl->pipe_ref_count++; /* * Point this pipe at this list. */ p->pipe_handles = hl; DEBUG(10,("init_pipe_handles: pipe_handles ref count = %lu for pipe %s\n", (unsigned long)p->pipe_handles->pipe_ref_count, get_pipe_name_from_syntax(talloc_tos(), syntax))); return True; }
WERROR libnetapi_open_pipe(struct libnetapi_ctx *ctx, const char *server_name, const struct ndr_syntax_id *interface, struct rpc_pipe_client **presult) { struct rpc_pipe_client *result = NULL; NTSTATUS status; WERROR werr; struct client_ipc_connection *ipc = NULL; if (!presult) { return WERR_INVALID_PARAM; } werr = libnetapi_open_ipc_connection(ctx, server_name, &ipc); if (!W_ERROR_IS_OK(werr)) { return werr; } status = pipe_cm_open(ctx, ipc, interface, &result); if (!NT_STATUS_IS_OK(status)) { libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s", get_pipe_name_from_syntax(talloc_tos(), interface), get_friendly_nt_error_msg(status)); return WERR_DEST_NOT_FOUND; } *presult = result; return WERR_OK; }
void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, uint32_t access_granted, size_t data_size, const char *type, NTSTATUS *pstatus) { struct dcesrv_handle *rpc_hnd; void *data; if (p->pipe_handles->count > MAX_OPEN_POLS) { DEBUG(0, ("ERROR: Too many handles (%d) for RPC connection %s\n", (int) p->pipe_handles->count, get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax))); *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } data = talloc_size(talloc_tos(), data_size); if (data == NULL) { *pstatus = NT_STATUS_NO_MEMORY; return NULL; } talloc_set_name_const(data, type); rpc_hnd = create_rpc_handle_internal(p, hnd, data); if (rpc_hnd == NULL) { TALLOC_FREE(data); *pstatus = NT_STATUS_NO_MEMORY; return NULL; } rpc_hnd->access_granted = access_granted; *pstatus = NT_STATUS_OK; return data; }
void *_policy_handle_create(struct pipes_struct *p, struct policy_handle *hnd, uint32_t access_granted, size_t data_size, const char *type, NTSTATUS *pstatus) { struct policy *pol; void *data; if (p->pipe_handles->count > MAX_OPEN_POLS) { DEBUG(0, ("policy_handle_create: ERROR: too many handles (%d) " "on pipe %s.\n", (int)p->pipe_handles->count, get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES; return NULL; } data = talloc_size(talloc_tos(), data_size); if (data == NULL) { *pstatus = NT_STATUS_NO_MEMORY; return NULL; } talloc_set_name_const(data, type); pol = create_policy_hnd_internal(p, hnd, data); if (pol == NULL) { TALLOC_FREE(data); *pstatus = NT_STATUS_NO_MEMORY; return NULL; } pol->access_granted = access_granted; *pstatus = NT_STATUS_OK; return data; }
struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax, const struct tsocket_address *remote_address, const struct auth_session_info *session_info, struct messaging_context *msg_ctx) { struct pipes_struct *p; struct pipe_rpc_fns *context_fns; const char *pipe_name; int ret; pipe_name = get_pipe_name_from_syntax(talloc_tos(), syntax); DEBUG(4,("Create pipe requested %s\n", pipe_name)); ret = make_base_pipes_struct(mem_ctx, msg_ctx, pipe_name, NCALRPC, RPC_LITTLE_ENDIAN, false, remote_address, NULL, &p); if (ret) { DEBUG(0,("ERROR! no memory for pipes_struct!\n")); return NULL; } if (!init_pipe_handles(p, syntax)) { DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n")); TALLOC_FREE(p); return NULL; } p->session_info = copy_session_info(p, session_info); if (p->session_info == NULL) { DEBUG(0, ("open_rpc_pipe_p: copy_serverinfo failed\n")); close_policy_by_pipe(p); TALLOC_FREE(p); return NULL; } context_fns = talloc(p, struct pipe_rpc_fns); if (context_fns == NULL) { DEBUG(0,("talloc() failed!\n")); TALLOC_FREE(p); return NULL; } context_fns->next = context_fns->prev = NULL; context_fns->n_cmds = rpc_srv_get_pipe_num_cmds(syntax); context_fns->cmds = rpc_srv_get_pipe_cmds(syntax); context_fns->context_id = 0; context_fns->syntax = *syntax; /* add to the list of open contexts */ DLIST_ADD(p->contexts, context_fns); DEBUG(4,("Created internal pipe %s\n", pipe_name)); return p; }
void close_policy_by_pipe(struct pipes_struct *p) { if (p->pipe_handles == NULL) { return; } p->pipe_handles->pipe_ref_count--; if (p->pipe_handles->pipe_ref_count == 0) { /* * Last pipe open on this list - free the list. */ TALLOC_FREE(p->pipe_handles); DEBUG(10,("Deleted handle list for RPC connection %s\n", get_pipe_name_from_syntax(talloc_tos(), &p->contexts->syntax))); } }
void close_policy_by_pipe(pipes_struct *p) { p->pipe_handles->pipe_ref_count--; if (p->pipe_handles->pipe_ref_count == 0) { /* * Last pipe open on this list - free the list. */ while (p->pipe_handles->Policy) close_policy_hnd(p, &p->pipe_handles->Policy->pol_hnd); p->pipe_handles->Policy = NULL; p->pipe_handles->count = 0; SAFE_FREE(p->pipe_handles); DEBUG(10,("close_policy_by_pipe: deleted handle list for " "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); } }
struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax, const struct tsocket_address *remote_address, const struct auth_serversupplied_info *session_info, struct messaging_context *msg_ctx) { struct pipes_struct *p; struct pipe_rpc_fns *context_fns; DEBUG(4,("Create pipe requested %s\n", get_pipe_name_from_syntax(talloc_tos(), syntax))); p = talloc_zero(mem_ctx, struct pipes_struct); if (!p) { DEBUG(0,("ERROR! no memory for pipes_struct!\n")); return NULL; } p->mem_ctx = talloc_named(p, 0, "pipe %s %p", get_pipe_name_from_syntax(talloc_tos(), syntax), p); if (p->mem_ctx == NULL) { DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n")); TALLOC_FREE(p); return NULL; } if (!init_pipe_handles(p, syntax)) { DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n")); TALLOC_FREE(p); return NULL; } p->session_info = copy_serverinfo(p, session_info); if (p->session_info == NULL) { DEBUG(0, ("open_rpc_pipe_p: copy_serverinfo failed\n")); close_policy_by_pipe(p); TALLOC_FREE(p); return NULL; } p->msg_ctx = msg_ctx; DLIST_ADD(InternalPipes, p); p->remote_address = tsocket_address_copy(remote_address, p); if (p->remote_address == NULL) { return false; } p->endian = RPC_LITTLE_ENDIAN; p->transport = NCALRPC; context_fns = SMB_MALLOC_P(struct pipe_rpc_fns); if (context_fns == NULL) { DEBUG(0,("malloc() failed!\n")); return False; } context_fns->next = context_fns->prev = NULL; context_fns->n_cmds = rpc_srv_get_pipe_num_cmds(syntax); context_fns->cmds = rpc_srv_get_pipe_cmds(syntax); context_fns->context_id = 0; context_fns->syntax = *syntax; /* add to the list of open contexts */ DLIST_ADD(p->contexts, context_fns); DEBUG(4,("Created internal pipe %s\n", get_pipe_name_from_syntax(talloc_tos(), syntax))); talloc_set_destructor(p, close_internal_rpc_pipe_hnd); return p; }
static ssize_t read_from_internal_pipe(struct pipes_struct *p, char *data, size_t n, bool *is_data_outstanding) { uint32 pdu_remaining = 0; ssize_t data_returned = 0; if (!p) { DEBUG(0,("read_from_pipe: pipe not open\n")); return -1; } DEBUG(6,(" name: %s len: %u\n", get_pipe_name_from_syntax(talloc_tos(), &p->syntax), (unsigned int)n)); /* * We cannot return more than one PDU length per * read request. */ /* * This condition should result in the connection being closed. * Netapp filers seem to set it to 0xffff which results in domain * authentications failing. Just ignore it so things work. */ if(n > RPC_MAX_PDU_FRAG_LEN) { DEBUG(5,("read_from_pipe: too large read (%u) requested on " "pipe %s. We can only service %d sized reads.\n", (unsigned int)n, get_pipe_name_from_syntax(talloc_tos(), &p->syntax), RPC_MAX_PDU_FRAG_LEN )); n = RPC_MAX_PDU_FRAG_LEN; } /* * Determine if there is still data to send in the * pipe PDU buffer. Always send this first. Never * send more than is left in the current PDU. The * client should send a new read request for a new * PDU. */ pdu_remaining = p->out_data.frag.length - p->out_data.current_pdu_sent; if (pdu_remaining > 0) { data_returned = (ssize_t)MIN(n, pdu_remaining); DEBUG(10,("read_from_pipe: %s: current_pdu_len = %u, " "current_pdu_sent = %u returning %d bytes.\n", get_pipe_name_from_syntax(talloc_tos(), &p->syntax), (unsigned int)p->out_data.frag.length, (unsigned int)p->out_data.current_pdu_sent, (int)data_returned)); memcpy(data, p->out_data.frag.data + p->out_data.current_pdu_sent, data_returned); p->out_data.current_pdu_sent += (uint32)data_returned; goto out; } /* * At this point p->current_pdu_len == p->current_pdu_sent (which * may of course be zero if this is the first return fragment. */ DEBUG(10,("read_from_pipe: %s: fault_state = %d : data_sent_length " "= %u, p->out_data.rdata.length = %u.\n", get_pipe_name_from_syntax(talloc_tos(), &p->syntax), (int)p->fault_state, (unsigned int)p->out_data.data_sent_length, (unsigned int)p->out_data.rdata.length)); if (p->out_data.data_sent_length >= p->out_data.rdata.length) { /* * We have sent all possible data, return 0. */ data_returned = 0; goto out; } /* * We need to create a new PDU from the data left in p->rdata. * Create the header/data/footers. This also sets up the fields * p->current_pdu_len, p->current_pdu_sent, p->data_sent_length * and stores the outgoing PDU in p->current_pdu. */ if(!create_next_pdu(p)) { DEBUG(0,("read_from_pipe: %s: create_next_pdu failed.\n", get_pipe_name_from_syntax(talloc_tos(), &p->syntax))); return -1; } data_returned = MIN(n, p->out_data.frag.length); memcpy(data, p->out_data.frag.data, (size_t)data_returned); p->out_data.current_pdu_sent += (uint32)data_returned; out: (*is_data_outstanding) = p->out_data.frag.length > n; if (p->out_data.current_pdu_sent == p->out_data.frag.length) { /* We've returned everything in the out_data.frag * so we're done with this pdu. Free it and reset * current_pdu_sent. */ p->out_data.current_pdu_sent = 0; data_blob_free(&p->out_data.frag); if (p->out_data.data_sent_length >= p->out_data.rdata.length) { /* * We're completely finished with both outgoing and * incoming data streams. It's safe to free all * temporary data from this request. */ free_pipe_context(p); } } return data_returned; }
bool init_pipe_handles(struct pipes_struct *p, const struct ndr_syntax_id *syntax) { struct pipes_struct *plist; struct handle_list *hl; for (plist = InternalPipes; plist; plist = plist->next) { struct pipe_rpc_fns *p_ctx; bool stop = false; for (p_ctx = plist->contexts; p_ctx != NULL; p_ctx = p_ctx->next) { if (ndr_syntax_id_equal(syntax, &p_ctx->syntax)) { stop = true; break; } if (is_samr_lsa_pipe(&p_ctx->syntax) && is_samr_lsa_pipe(syntax)) { /* * samr and lsa share a handle space (same process * under Windows?) */ stop = true; break; } } if (stop) { break; } } if (plist != NULL) { hl = plist->pipe_handles; if (hl == NULL) { return false; } } else { /* * First open, we have to create the handle list */ hl = talloc_zero(NULL, struct handle_list); if (hl == NULL) { return false; } DEBUG(10,("init_pipe_handle_list: created handle list for " "pipe %s\n", get_pipe_name_from_syntax(talloc_tos(), syntax))); } /* * One more pipe is using this list. */ hl->pipe_ref_count++; /* * Point this pipe at this list. */ p->pipe_handles = hl; DEBUG(10,("init_pipe_handle_list: pipe_handles ref count = %lu for " "pipe %s\n", (unsigned long)p->pipe_handles->pipe_ref_count, get_pipe_name_from_syntax(talloc_tos(), syntax))); return True; }