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_iface(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_iface(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 cli_state *cli = NULL; if (!presult) { return WERR_INVALID_PARAM; } werr = libnetapi_open_ipc_connection(ctx, server_name, &cli); if (!W_ERROR_IS_OK(werr)) { return werr; } status = pipe_cm_open(ctx, cli, interface, &result); if (!NT_STATUS_IS_OK(status)) { libnetapi_set_error_string(ctx, "failed to open PIPE %s: %s", get_pipe_name_from_iface(interface), get_friendly_nt_error_msg(status)); return WERR_DEST_NOT_FOUND; } *presult = result; return WERR_OK; }
static void set_incoming_fault(pipes_struct *p) { prs_mem_free(&p->in_data.data); p->in_data.pdu_needed_len = 0; p->in_data.pdu_received_len = 0; p->fault_state = True; DEBUG(10, ("set_incoming_fault: Setting fault state on pipe %s\n", get_pipe_name_from_iface(&p->syntax))); }
static void free_pipe_context(pipes_struct *p) { if (p->mem_ctx) { DEBUG(3,("free_pipe_context: destroying talloc pool of size " "%lu\n", (unsigned long)talloc_total_size(p->mem_ctx) )); talloc_free_children(p->mem_ctx); } else { p->mem_ctx = talloc_init( "pipe %s %p", get_pipe_name_from_iface(&p->syntax), p); if (p->mem_ctx == NULL) { p->fault_state = True; } } }
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_iface(&p->syntax))); } }
static struct pipes_struct *make_internal_rpc_pipe_p(TALLOC_CTX *mem_ctx, const struct ndr_syntax_id *syntax, const char *client_address, struct auth_serversupplied_info *server_info) { pipes_struct *p; DEBUG(4,("Create pipe requested %s\n", get_pipe_name_from_iface(syntax))); p = TALLOC_ZERO_P(mem_ctx, struct pipes_struct); if (!p) { DEBUG(0,("ERROR! no memory for pipes_struct!\n")); return NULL; } if ((p->mem_ctx = talloc_init("pipe %s %p", get_pipe_name_from_iface(syntax), p)) == NULL) { DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n")); TALLOC_FREE(p); return NULL; } if (!init_pipe_handle_list(p, syntax)) { DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n")); talloc_destroy(p->mem_ctx); TALLOC_FREE(p); return NULL; } /* * Initialize the incoming RPC data buffer with one PDU worth of memory. * We cheat here and say we're marshalling, as we intend to add incoming * data directly into the prs_struct and we want it to auto grow. We will * change the type to UNMARSALLING before processing the stream. */ if(!prs_init(&p->in_data.data, 128, p->mem_ctx, MARSHALL)) { DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n")); talloc_destroy(p->mem_ctx); close_policy_by_pipe(p); TALLOC_FREE(p); return NULL; } p->server_info = copy_serverinfo(p, server_info); if (p->server_info == NULL) { DEBUG(0, ("open_rpc_pipe_p: copy_serverinfo failed\n")); talloc_destroy(p->mem_ctx); close_policy_by_pipe(p); TALLOC_FREE(p); return NULL; } DLIST_ADD(InternalPipes, p); memcpy(p->client_address, client_address, sizeof(p->client_address)); p->endian = RPC_LITTLE_ENDIAN; /* * Initialize the outgoing RPC data buffer with no memory. */ prs_init_empty(&p->out_data.rdata, p->mem_ctx, MARSHALL); p->syntax = *syntax; DEBUG(4,("Created internal pipe %s (pipes_open=%d)\n", get_pipe_name_from_iface(syntax), pipes_open)); talloc_set_destructor(p, close_internal_rpc_pipe_hnd); return p; }
static void process_complete_pdu(pipes_struct *p) { prs_struct rpc_in; size_t data_len = p->in_data.pdu_received_len - RPC_HEADER_LEN; char *data_p = (char *)&p->in_data.current_in_pdu[RPC_HEADER_LEN]; bool reply = False; if(p->fault_state) { DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n", get_pipe_name_from_iface(&p->syntax))); set_incoming_fault(p); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); return; } prs_init_empty( &rpc_in, p->mem_ctx, UNMARSHALL); /* * Ensure we're using the corrent endianness for both the * RPC header flags and the raw data we will be reading from. */ prs_set_endian_data( &rpc_in, p->endian); prs_set_endian_data( &p->in_data.data, p->endian); prs_give_memory( &rpc_in, data_p, (uint32)data_len, False); DEBUG(10,("process_complete_pdu: processing packet type %u\n", (unsigned int)p->hdr.pkt_type )); switch (p->hdr.pkt_type) { case RPC_REQUEST: reply = process_request_pdu(p, &rpc_in); break; case RPC_PING: /* CL request - ignore... */ DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n", (unsigned int)p->hdr.pkt_type, get_pipe_name_from_iface(&p->syntax))); break; case RPC_RESPONSE: /* No responses here. */ DEBUG(0,("process_complete_pdu: Error. RPC_RESPONSE received from client on pipe %s.\n", get_pipe_name_from_iface(&p->syntax))); break; case RPC_FAULT: case RPC_WORKING: /* CL request - reply to a ping when a call in process. */ case RPC_NOCALL: /* CL - server reply to a ping call. */ case RPC_REJECT: case RPC_ACK: case RPC_CL_CANCEL: case RPC_FACK: case RPC_CANCEL_ACK: DEBUG(0,("process_complete_pdu: Error. Connectionless packet type %u received on pipe %s.\n", (unsigned int)p->hdr.pkt_type, get_pipe_name_from_iface(&p->syntax))); break; case RPC_BIND: /* * We assume that a pipe bind is only in one pdu. */ if(pipe_init_outgoing_data(p)) { reply = api_pipe_bind_req(p, &rpc_in); } break; case RPC_BINDACK: case RPC_BINDNACK: DEBUG(0,("process_complete_pdu: Error. RPC_BINDACK/RPC_BINDNACK packet type %u received on pipe %s.\n", (unsigned int)p->hdr.pkt_type, get_pipe_name_from_iface(&p->syntax))); break; case RPC_ALTCONT: /* * We assume that a pipe bind is only in one pdu. */ if(pipe_init_outgoing_data(p)) { reply = api_pipe_alter_context(p, &rpc_in); } break; case RPC_ALTCONTRESP: DEBUG(0,("process_complete_pdu: Error. RPC_ALTCONTRESP on pipe %s: Should only be server -> client.\n", get_pipe_name_from_iface(&p->syntax))); break; case RPC_AUTH3: /* * The third packet in an NTLMSSP auth exchange. */ if(pipe_init_outgoing_data(p)) { reply = api_pipe_bind_auth3(p, &rpc_in); } break; case RPC_SHUTDOWN: DEBUG(0,("process_complete_pdu: Error. RPC_SHUTDOWN on pipe %s: Should only be server -> client.\n", get_pipe_name_from_iface(&p->syntax))); break; case RPC_CO_CANCEL: /* For now just free all client data and continue processing. */ DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n")); /* As we never do asynchronous RPC serving, we can never cancel a call (as far as I know). If we ever did we'd have to send a cancel_ack reply. For now, just free all client data and continue processing. */ reply = True; break; #if 0 /* Enable this if we're doing async rpc. */ /* We must check the call-id matches the outstanding callid. */ if(pipe_init_outgoing_data(p)) { /* Send a cancel_ack PDU reply. */ /* We should probably check the auth-verifier here. */ reply = setup_cancel_ack_reply(p, &rpc_in); } break; #endif case RPC_ORPHANED: /* We should probably check the auth-verifier here. For now just free all client data and continue processing. */ DEBUG(3,("process_complete_pdu: RPC_ORPHANED. Abandoning rpc call.\n")); reply = True; break; default: DEBUG(0,("process_complete_pdu: Unknown rpc type = %u received.\n", (unsigned int)p->hdr.pkt_type )); break; } /* Reset to little endian. Probably don't need this but it won't hurt. */ prs_set_endian_data( &p->in_data.data, RPC_LITTLE_ENDIAN); if (!reply) { DEBUG(3,("process_complete_pdu: DCE/RPC fault sent on " "pipe %s\n", get_pipe_name_from_iface(&p->syntax))); set_incoming_fault(p); setup_fault_pdu(p, NT_STATUS(DCERPC_FAULT_OP_RNG_ERROR)); prs_mem_free(&rpc_in); } else { /* * Reset the lengths. We're ready for a new pdu. */ TALLOC_FREE(p->in_data.current_in_pdu); p->in_data.pdu_needed_len = 0; p->in_data.pdu_received_len = 0; } prs_mem_free(&rpc_in); }