Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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)));
}
Beispiel #4
0
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;
        }
    }
}
Beispiel #5
0
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)));
	}
}
Beispiel #6
0
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;
}
Beispiel #7
0
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);
}