Пример #1
0
/* useful function to fetch a structure into rpc wire format */
int tdb_prs_fetch(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps, TALLOC_CTX *mem_ctx)
{
    TDB_DATA kbuf, dbuf;
    kbuf.dptr = keystr;
    kbuf.dsize = strlen(keystr)+1;

    dbuf = tdb_fetch(tdb, kbuf);
    if (!dbuf.dptr) return -1;

    ZERO_STRUCTP(ps);
    prs_init(ps, 0, mem_ctx, UNMARSHALL);
    prs_give_memory(ps, dbuf.dptr, dbuf.dsize, True);

    return 0;
} 
Пример #2
0
/****************************************************************************
  set the security descriptor for a open file
 ****************************************************************************/
BOOL cli_set_secdesc(struct cli_state *cli, int fnum, SEC_DESC *sd)
{
	char param[8];
	char *rparam=NULL, *rdata=NULL;
	unsigned int rparam_count=0, rdata_count=0;
	uint32 sec_info = 0;
	TALLOC_CTX *mem_ctx;
	prs_struct pd;
	BOOL ret = False;

	if ((mem_ctx = talloc_init("cli_set_secdesc")) == NULL) {
		DEBUG(0,("talloc_init failed.\n"));
		goto cleanup;
	}

	prs_init(&pd, 0, mem_ctx, MARSHALL);
	prs_give_memory(&pd, NULL, 0, True);

	if (!sec_io_desc("sd data", &sd, &pd, 1)) {
		DEBUG(1,("Failed to marshall secdesc\n"));
		goto cleanup;
	}

	SIVAL(param, 0, fnum);

	if (sd->off_dacl)
		sec_info |= DACL_SECURITY_INFORMATION;
	if (sd->off_owner_sid)
		sec_info |= OWNER_SECURITY_INFORMATION;
	if (sd->off_grp_sid)
		sec_info |= GROUP_SECURITY_INFORMATION;
	SSVAL(param, 4, sec_info);

	if (!cli_send_nt_trans(cli, 
			       NT_TRANSACT_SET_SECURITY_DESC, 
			       0, 
			       NULL, 0, 0,
			       param, 8, 0,
			       prs_data_p(&pd), prs_offset(&pd), 0)) {
		DEBUG(1,("Failed to send NT_TRANSACT_SET_SECURITY_DESC\n"));
		goto cleanup;
	}


	if (!cli_receive_nt_trans(cli, 
				  &rparam, &rparam_count,
				  &rdata, &rdata_count)) {
		DEBUG(1,("NT_TRANSACT_SET_SECURITY_DESC failed\n"));
		goto cleanup;
	}

	ret = True;

  cleanup:

	SAFE_FREE(rparam);
	SAFE_FREE(rdata);

	talloc_destroy(mem_ctx);

	prs_mem_free(&pd);
	return ret;
}
Пример #3
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);
}
Пример #4
0
BOOL create_next_pdu(pipes_struct *p)
{
	RPC_HDR_RESP hdr_resp;
	BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0);
	BOOL auth_seal   = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL) != 0);
	uint32 ss_padding_len = 0;
	uint32 data_len;
	uint32 data_space_available;
	uint32 data_len_left;
	prs_struct outgoing_pdu;
	uint32 data_pos;

	/*
	 * If we're in the fault state, keep returning fault PDU's until
	 * the pipe gets closed. JRA.
	 */

	if(p->fault_state) {
		setup_fault_pdu(p, NT_STATUS(0x1c010002));
		return True;
	}

	memset((char *)&hdr_resp, '\0', sizeof(hdr_resp));

	/* Change the incoming request header to a response. */
	p->hdr.pkt_type = RPC_RESPONSE;

	/* Set up rpc header flags. */
	if (p->out_data.data_sent_length == 0) {
		p->hdr.flags = RPC_FLG_FIRST;
	} else {
		p->hdr.flags = 0;
	}

	/*
	 * Work out how much we can fit in a single PDU.
	 */

	data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
	if(p->ntlmssp_auth_validated) {
		data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN);
	} else if(p->netsec_auth_validated) {
		data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN);
	}

	/*
	 * The amount we send is the minimum of the available
	 * space and the amount left to send.
	 */

	data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length;

	/*
	 * Ensure there really is data left to send.
	 */

	if(!data_len_left) {
		DEBUG(0,("create_next_pdu: no data left to send !\n"));
		return False;
	}

	data_len = MIN(data_len_left, data_space_available);

	/*
	 * Set up the alloc hint. This should be the data left to
	 * send.
	 */

	hdr_resp.alloc_hint = data_len_left;

	/*
	 * Work out if this PDU will be the last.
	 */

	if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) {
		p->hdr.flags |= RPC_FLG_LAST;
		if ((auth_seal || auth_verify) && (data_len_left % 8)) {
			ss_padding_len = 8 - (data_len_left % 8);
			DEBUG(10,("create_next_pdu: adding sign/seal padding of %u\n",
				ss_padding_len ));
		}
	}

	/*
	 * Set up the header lengths.
	 */

	if (p->ntlmssp_auth_validated) {
		p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
			data_len + ss_padding_len +
			RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN;
		p->hdr.auth_len = RPC_AUTH_NTLMSSP_CHK_LEN;
	} else if (p->netsec_auth_validated) {
		p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
			data_len + ss_padding_len +
			RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN;
		p->hdr.auth_len = RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN;
	} else {
		p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len;
		p->hdr.auth_len = 0;
	}

	/*
	 * Init the parse struct to point at the outgoing
	 * data.
	 */

	prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL);
	prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);

	/* Store the header in the data stream. */
	if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) {
		DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR.\n"));
		prs_mem_free(&outgoing_pdu);
		return False;
	}

	if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) {
		DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_RESP.\n"));
		prs_mem_free(&outgoing_pdu);
		return False;
	}

	/* Store the current offset. */
	data_pos = prs_offset(&outgoing_pdu);

	/* Copy the data into the PDU. */

	if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) {
		DEBUG(0,("create_next_pdu: failed to copy %u bytes of data.\n", (unsigned int)data_len));
		prs_mem_free(&outgoing_pdu);
		return False;
	}

	/* Copy the sign/seal padding data. */
	if (ss_padding_len) {
		char pad[8];
		memset(pad, '\0', 8);
		if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) {
			DEBUG(0,("create_next_pdu: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len));
			prs_mem_free(&outgoing_pdu);
			return False;
		}
	}

	if (p->ntlmssp_auth_validated) {
		/*
		 * NTLMSSP processing. Mutually exclusive with Schannel.
		 */
		uint32 crc32 = 0;
		char *data;

		DEBUG(5,("create_next_pdu: sign: %s seal: %s data %d auth %d\n",
			 BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len + ss_padding_len, p->hdr.auth_len));

		/*
		 * Set data to point to where we copied the data into.
		 */

		data = prs_data_p(&outgoing_pdu) + data_pos;

		if (auth_seal) {
			crc32 = crc32_calc_buffer(data, data_len + ss_padding_len);
			NTLMSSPcalc_p(p, (uchar*)data, data_len + ss_padding_len);
		}

		if (auth_seal || auth_verify) {
			RPC_HDR_AUTH auth_info;

			init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE,
					auth_seal ? RPC_PIPE_AUTH_SEAL_LEVEL : RPC_PIPE_AUTH_SIGN_LEVEL,
					(auth_verify ? ss_padding_len : 0), (auth_verify ? 1 : 0));
			if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
				DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n"));
				prs_mem_free(&outgoing_pdu);
				return False;
			}
		}

		if (auth_verify) {
			RPC_AUTH_NTLMSSP_CHK ntlmssp_chk;
			char *auth_data = prs_data_p(&outgoing_pdu);

			p->ntlmssp_seq_num++;
			init_rpc_auth_ntlmssp_chk(&ntlmssp_chk, NTLMSSP_SIGN_VERSION,
					crc32, p->ntlmssp_seq_num++);
			auth_data = prs_data_p(&outgoing_pdu) + prs_offset(&outgoing_pdu) + 4;
			if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &ntlmssp_chk, &outgoing_pdu, 0)) {
				DEBUG(0,("create_next_pdu: failed to marshall RPC_AUTH_NTLMSSP_CHK.\n"));
				prs_mem_free(&outgoing_pdu);
				return False;
			}
			NTLMSSPcalc_p(p, (uchar*)auth_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4);
		}
	} else if (p->netsec_auth_validated) {
		/*
		 * Schannel processing. Mutually exclusive with NTLMSSP.
		 */
		int auth_type, auth_level;
		char *data;
		RPC_HDR_AUTH auth_info;

		RPC_AUTH_NETSEC_CHK verf;
		prs_struct rverf;
		prs_struct rauth;

		data = prs_data_p(&outgoing_pdu) + data_pos;
		/* Check it's the type of reply we were expecting to decode */

		get_auth_type_level(p->netsec_auth.auth_flags, &auth_type, &auth_level);
		init_rpc_hdr_auth(&auth_info, auth_type, auth_level, 
				  ss_padding_len, 1);

		if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
			DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n"));
			prs_mem_free(&outgoing_pdu);
			return False;
		}

		prs_init(&rverf, 0, p->mem_ctx, MARSHALL);
		prs_init(&rauth, 0, p->mem_ctx, MARSHALL);

		netsec_encode(&p->netsec_auth, 
			      p->netsec_auth.auth_flags,
			      SENDER_IS_ACCEPTOR,
			      &verf, data, data_len + ss_padding_len);

		smb_io_rpc_auth_netsec_chk("", RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN, 
			&verf, &outgoing_pdu, 0);

		p->netsec_auth.seq_num++;
	}

	/*
	 * Setup the counts for this PDU.
	 */

	p->out_data.data_sent_length += data_len;
	p->out_data.current_pdu_len = p->hdr.frag_len;
	p->out_data.current_pdu_sent = 0;

	prs_mem_free(&outgoing_pdu);
	return True;
}
Пример #5
0
static ssize_t unmarshall_rpc_header(pipes_struct *p)
{
    /*
     * Unmarshall the header to determine the needed length.
     */

    prs_struct rpc_in;

    if(p->in_data.pdu_received_len != RPC_HEADER_LEN) {
        DEBUG(0,("unmarshall_rpc_header: assert on rpc header length failed.\n"));
        set_incoming_fault(p);
        return -1;
    }

    prs_init_empty( &rpc_in, p->mem_ctx, UNMARSHALL);
    prs_set_endian_data( &rpc_in, p->endian);

    prs_give_memory( &rpc_in, (char *)&p->in_data.current_in_pdu[0],
                     p->in_data.pdu_received_len, False);

    /*
     * Unmarshall the header as this will tell us how much
     * data we need to read to get the complete pdu.
     * This also sets the endian flag in rpc_in.
     */

    if(!smb_io_rpc_hdr("", &p->hdr, &rpc_in, 0)) {
        DEBUG(0,("unmarshall_rpc_header: failed to unmarshall RPC_HDR.\n"));
        set_incoming_fault(p);
        prs_mem_free(&rpc_in);
        return -1;
    }

    /*
     * Validate the RPC header.
     */

    if(p->hdr.major != 5 && p->hdr.minor != 0) {
        DEBUG(0,("unmarshall_rpc_header: invalid major/minor numbers in RPC_HDR.\n"));
        set_incoming_fault(p);
        prs_mem_free(&rpc_in);
        return -1;
    }

    /*
     * If there's not data in the incoming buffer this should be the start of a new RPC.
     */

    if(prs_offset(&p->in_data.data) == 0) {

        /*
         * AS/U doesn't set FIRST flag in a BIND packet it seems.
         */

        if ((p->hdr.pkt_type == RPC_REQUEST) && !(p->hdr.flags & RPC_FLG_FIRST)) {
            /*
             * Ensure that the FIRST flag is set. If not then we have
             * a stream missmatch.
             */

            DEBUG(0,("unmarshall_rpc_header: FIRST flag not set in first PDU !\n"));
            set_incoming_fault(p);
            prs_mem_free(&rpc_in);
            return -1;
        }

        /*
         * If this is the first PDU then set the endianness
         * flag in the pipe. We will need this when parsing all
         * data in this RPC.
         */

        p->endian = rpc_in.bigendian_data;

        DEBUG(5,("unmarshall_rpc_header: using %sendian RPC\n",
                 p->endian == RPC_LITTLE_ENDIAN ? "little-" : "big-" ));

    } else {

        /*
         * If this is *NOT* the first PDU then check the endianness
         * flag in the pipe is the same as that in the PDU.
         */

        if (p->endian != rpc_in.bigendian_data) {
            DEBUG(0,("unmarshall_rpc_header: FIRST endianness flag (%d) different in next PDU !\n", (int)p->endian));
            set_incoming_fault(p);
            prs_mem_free(&rpc_in);
            return -1;
        }
    }

    /*
     * Ensure that the pdu length is sane.
     */

    if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > RPC_MAX_PDU_FRAG_LEN)) {
        DEBUG(0,("unmarshall_rpc_header: assert on frag length failed.\n"));
        set_incoming_fault(p);
        prs_mem_free(&rpc_in);
        return -1;
    }

    DEBUG(10,("unmarshall_rpc_header: type = %u, flags = %u\n", (unsigned int)p->hdr.pkt_type,
              (unsigned int)p->hdr.flags ));

    p->in_data.pdu_needed_len = (uint32)p->hdr.frag_len - RPC_HEADER_LEN;

    prs_mem_free(&rpc_in);

    p->in_data.current_in_pdu = TALLOC_REALLOC_ARRAY(
                                    p, p->in_data.current_in_pdu, uint8_t, p->hdr.frag_len);
    if (p->in_data.current_in_pdu == NULL) {
        DEBUG(0, ("talloc failed\n"));
        set_incoming_fault(p);
        return -1;
    }

    return 0; /* No extra data processed. */
}
Пример #6
0
static ssize_t unmarshall_rpc_header(pipes_struct *p)
{
	/*
	 * Unmarshall the header to determine the needed length.
	 */

	prs_struct rpc_in;

	if(p->in_data.pdu_received_len != RPC_HEADER_LEN) {
		DEBUG(0,("unmarshall_rpc_header: assert on rpc header length failed.\n"));
		set_incoming_fault(p);
		return -1;
	}

	prs_init( &rpc_in, 0, 4, UNMARSHALL);
	prs_give_memory( &rpc_in, (char *)&p->in_data.current_in_pdu[0],
					p->in_data.pdu_received_len, False);

	/*
	 * Unmarshall the header as this will tell us how much
	 * data we need to read to get the complete pdu.
	 */

	if(!smb_io_rpc_hdr("", &p->hdr, &rpc_in, 0)) {
		DEBUG(0,("unmarshall_rpc_header: failed to unmarshall RPC_HDR.\n"));
		set_incoming_fault(p);
		return -1;
	}

	/*
	 * Validate the RPC header.
	 */

	if(p->hdr.major != 5 && p->hdr.minor != 0) {
		DEBUG(0,("unmarshall_rpc_header: invalid major/minor numbers in RPC_HDR.\n"));
		set_incoming_fault(p);
		return -1;
	}

	/*
	 * If there is no data in the incoming buffer and it's a requst pdu then
	 * ensure that the FIRST flag is set. If not then we have
	 * a stream missmatch.
	 */

	if((p->hdr.pkt_type == RPC_REQUEST) && (prs_offset(&p->in_data.data) == 0) && !(p->hdr.flags & RPC_FLG_FIRST)) {
		DEBUG(0,("unmarshall_rpc_header: FIRST flag not set in first PDU !\n"));
		set_incoming_fault(p);
		return -1;
	}

	/*
	 * Ensure that the pdu length is sane.
	 */

	if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > MAX_PDU_FRAG_LEN)) {
		DEBUG(0,("unmarshall_rpc_header: assert on frag length failed.\n"));
		set_incoming_fault(p);
		return -1;
	}

	DEBUG(10,("unmarshall_rpc_header: type = %u, flags = %u\n", (unsigned int)p->hdr.pkt_type,
			(unsigned int)p->hdr.flags ));

	/*
	 * Adjust for the header we just ate.
	 */
	p->in_data.pdu_received_len = 0;
	p->in_data.pdu_needed_len = (uint32)p->hdr.frag_len - RPC_HEADER_LEN;

	/*
	 * Null the data we just ate.
	 */

	memset((char *)&p->in_data.current_in_pdu[0], '\0', RPC_HEADER_LEN);

	return 0; /* No extra data processed. */
}
Пример #7
0
static BOOL rpc_api_pipe(struct cli_state *cli, prs_struct *data, prs_struct *rdata,
			 uint8 expected_pkt_type)
{
	uint32 len;
	char *rparam = NULL;
	uint32 rparam_len = 0;
	uint16 setup[2];
	BOOL first = True;
	BOOL last  = True;
	RPC_HDR rhdr;
	char *pdata = data ? prs_data_p(data) : NULL;
	uint32 data_len = data ? prs_offset(data) : 0;
	char *prdata = NULL;
	uint32 rdata_len = 0;
	uint32 current_offset = 0;
	uint32 fragment_start = 0;
	uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : 1024;
	int auth_padding_len = 0;

	/* Create setup parameters - must be in native byte order. */

	setup[0] = TRANSACT_DCERPCCMD; 
	setup[1] = cli->nt_pipe_fnum; /* Pipe file handle. */

	DEBUG(5,("rpc_api_pipe: fnum:%x\n", (int)cli->nt_pipe_fnum));

	/* Send the RPC request and receive a response.  For short RPC
	   calls (about 1024 bytes or so) the RPC request and response
	   appears in a SMBtrans request and response.  Larger RPC
	   responses are received further on. */

	if (!cli_api_pipe(cli, "\\PIPE\\",
	          setup, 2, 0,                     /* Setup, length, max */
	          NULL, 0, 0,                      /* Params, length, max */
	          pdata, data_len, max_data,   	   /* data, length, max */
	          &rparam, &rparam_len,            /* return params, len */
	          &prdata, &rdata_len))            /* return data, len */
	{
		DEBUG(0, ("cli_pipe: return critical error. Error was %s\n", cli_errstr(cli)));
		return False;
	}

	/* Throw away returned params - we know we won't use them. */

	SAFE_FREE(rparam);

	if (prdata == NULL) {
		DEBUG(0,("rpc_api_pipe: pipe %x failed to return data.\n",
			(int)cli->nt_pipe_fnum));
		return False;
	}

	/*
	 * Give this memory as dynamically allocated to the return parse
	 * struct.  
	 */

	prs_give_memory(rdata, prdata, rdata_len, True);
	current_offset = rdata_len;

	/* This next call sets the endian bit correctly in rdata. */

	if (!rpc_check_hdr(rdata, &rhdr, &first, &last, &len)) {
		prs_mem_free(rdata);
		return False;
	}

	if (rhdr.pkt_type == RPC_BINDACK) {
		if (!last && !first) {
			DEBUG(5,("rpc_api_pipe: bug in server (AS/U?), setting fragment first/last ON.\n"));
			first = True;
			last = True;
		}
	}

	if (rhdr.pkt_type == RPC_BINDNACK) {
		DEBUG(3, ("Bind NACK received on pipe %x!\n", (int)cli->nt_pipe_fnum));
		prs_mem_free(rdata);
		return False;
	}

	if (rhdr.pkt_type == RPC_RESPONSE) {
		RPC_HDR_RESP rhdr_resp;
		if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, rdata, 0)) {
			DEBUG(5,("rpc_api_pipe: failed to unmarshal RPC_HDR_RESP.\n"));
			prs_mem_free(rdata);
			return False;
		}
	}

	if (rhdr.pkt_type != expected_pkt_type) {
		DEBUG(3, ("Connection to pipe %x got an unexpected RPC packet type - %d, not %d\n", (int)cli->nt_pipe_fnum, rhdr.pkt_type, expected_pkt_type));
		prs_mem_free(rdata);
		return False;
	}

	DEBUG(5,("rpc_api_pipe: len left: %u smbtrans read: %u\n",
	          (unsigned int)len, (unsigned int)rdata_len ));

	/* check if data to be sent back was too large for one SMBtrans */
	/* err status is only informational: the _real_ check is on the
           length */

	if (len > 0) { 
		/* || err == (0x80000000 | STATUS_BUFFER_OVERFLOW)) */

		/* Read the remaining part of the first response fragment */

		if (!rpc_read(cli, rdata, len, &current_offset)) {
			prs_mem_free(rdata);
			return False;
		}
	}

	/*
	 * Now we have a complete PDU, check the auth struct if any was sent.
	 */

	if(!rpc_auth_pipe(cli, rdata, fragment_start, rhdr.frag_len,
			  rhdr.auth_len, rhdr.pkt_type, &auth_padding_len)) {
		prs_mem_free(rdata);
		return False;
	}

	if (rhdr.auth_len != 0) {
		/*
		 * Drop the auth footers from the current offset.
		 * We need this if there are more fragments.
		 * The auth footers consist of the auth_data and the
		 * preceeding 8 byte auth_header.
		 */
		current_offset -= (auth_padding_len + RPC_HDR_AUTH_LEN + rhdr.auth_len);
	}
	
	/* 
	 * Only one rpc fragment, and it has been read.
	 */

	if (first && last) {
		DEBUG(6,("rpc_api_pipe: fragment first and last both set\n"));
		return True;
	}

	/*
	 * Read more fragments using SMBreadX until we get one with the
	 * last bit set.
	 */

	while (!last) {
		RPC_HDR_RESP rhdr_resp;
		int num_read;
		char hdr_data[RPC_HEADER_LEN+RPC_HDR_RESP_LEN];
		prs_struct hps;
		uint8 eclass;
		uint32 ecode;
		
		/*
		 * First read the header of the next PDU.
		 */

		prs_init(&hps, 0, cli->mem_ctx, UNMARSHALL);
		prs_give_memory(&hps, hdr_data, sizeof(hdr_data), False);

		num_read = cli_read(cli, cli->nt_pipe_fnum, hdr_data, 0, RPC_HEADER_LEN+RPC_HDR_RESP_LEN);
		if (cli_is_dos_error(cli)) {
                        cli_dos_error(cli, &eclass, &ecode);
                        if (eclass != ERRDOS && ecode != ERRmoredata) {
                                DEBUG(0,("rpc_api_pipe: cli_read error : %d/%d\n", eclass, ecode));
                                return False;
                        }
		}

		DEBUG(5,("rpc_api_pipe: read header (size:%d)\n", num_read));

		if (num_read != RPC_HEADER_LEN+RPC_HDR_RESP_LEN) {
			DEBUG(0,("rpc_api_pipe: Error : requested %d bytes, got %d.\n",
				RPC_HEADER_LEN+RPC_HDR_RESP_LEN, num_read ));
			return False;
		}

		/* This call sets the endianness in hps. */

		if (!rpc_check_hdr(&hps, &rhdr, &first, &last, &len))
			return False;

		/* Ensure the endianness in rdata is set correctly - must be same as hps. */

		if (hps.bigendian_data != rdata->bigendian_data) {
			DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n",
				rdata->bigendian_data ? "big" : "little",
				hps.bigendian_data ? "big" : "little" ));
			return False;
		}

		if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, &hps, 0)) {
			DEBUG(0,("rpc_api_pipe: Error in unmarshalling RPC_HDR_RESP.\n"));
			return False;
		}

		if (first) {
			DEBUG(0,("rpc_api_pipe: secondary PDU rpc header has 'first' set !\n"));
			return False;
		}

		/*
		 * Now read the rest of the PDU.
		 */

		if (!rpc_read(cli, rdata, len, &current_offset)) {
			prs_mem_free(rdata);
			return False;
		}

		fragment_start = current_offset - len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;

		/*
		 * Verify any authentication footer.
		 */

		
		if(!rpc_auth_pipe(cli, rdata, fragment_start, rhdr.frag_len,
				  rhdr.auth_len, rhdr.pkt_type, &auth_padding_len)) {
			prs_mem_free(rdata);
			return False;
		}
		
		if (rhdr.auth_len != 0 ) {
			
			/*
			 * Drop the auth footers from the current offset.
			 * The auth footers consist of the auth_data and the
			 * preceeding 8 byte auth_header.
			 * We need this if there are more fragments.
			 */
			current_offset -= (auth_padding_len + RPC_HDR_AUTH_LEN + rhdr.auth_len);
		}
	}

	return True;
}
Пример #8
0
static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata,
			  uint32 fragment_start, int len, int auth_len, uint8 pkt_type,
			  int *pauth_padding_len)
{
	
	/*
	 * The following is that length of the data we must sign or seal.
	 * This doesn't include the RPC headers or the auth_len or the RPC_HDR_AUTH_LEN
	 * preceeding the auth_data.
	 */

	int data_len = len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;

	/*
	 * The start of the data to sign/seal is just after the RPC headers.
	 */
	char *reply_data = prs_data_p(rdata) + fragment_start + RPC_HEADER_LEN + RPC_HDR_REQ_LEN;

	RPC_HDR_AUTH rhdr_auth; 

	char *dp = prs_data_p(rdata) + fragment_start + len -
		RPC_HDR_AUTH_LEN - auth_len;
	prs_struct auth_verf;

	*pauth_padding_len = 0;

	if (auth_len == 0) {
		if (cli->pipe_auth_flags == 0) {
			/* move along, nothing to see here */
			return True;
		}

		DEBUG(2, ("No authenticaton header recienved on reply, but this pipe is authenticated\n"));
		return False;
	}

	DEBUG(5,("rpc_auth_pipe: pkt_type: %d len: %d auth_len: %d NTLMSSP %s schannel %s sign %s seal %s \n",
		 pkt_type, len, auth_len, 
		 BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP), 
		 BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_NETSEC), 
		 BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SIGN), 
		 BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SEAL)));

	if (dp - prs_data_p(rdata) > prs_data_size(rdata)) {
		DEBUG(0,("rpc_auth_pipe: schannel auth data > data size !\n"));
		return False;
	}

	DEBUG(10,("rpc_auth_pipe: packet:\n"));
	dump_data(100, dp, auth_len);

	prs_init(&auth_verf, 0, cli->mem_ctx, UNMARSHALL);
	
	/* The endinness must be preserved. JRA. */
	prs_set_endian_data( &auth_verf, rdata->bigendian_data);
	
	/* Point this new parse struct at the auth section of the main 
	   parse struct - rather than copying it.  Avoids needing to
	   free it on every error
	*/
	prs_give_memory(&auth_verf, dp, RPC_HDR_AUTH_LEN + auth_len, False /* not dynamic */);
	prs_set_offset(&auth_verf, 0);

	{
		int auth_type;
		int auth_level;
		if (!smb_io_rpc_hdr_auth("auth_hdr", &rhdr_auth, &auth_verf, 0)) {
			DEBUG(0, ("rpc_auth_pipe: Could not parse auth header\n"));
			return False;
		}

		/* Let the caller know how much padding at the end of the data */
		*pauth_padding_len = rhdr_auth.padding;
		
		/* Check it's the type of reply we were expecting to decode */

		get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level);
		if (rhdr_auth.auth_type != auth_type) {
			DEBUG(0, ("BAD auth type %d (should be %d)\n",
				  rhdr_auth.auth_type, auth_type));
			return False;
		}
		
		if (rhdr_auth.auth_level != auth_level) {
			DEBUG(0, ("BAD auth level %d (should be %d)\n", 
				  rhdr_auth.auth_level, auth_level));
			return False;
		}
	}

	if (pkt_type == RPC_BINDACK) {
		if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
			/* copy the next auth_len bytes into a buffer for 
			   later use */

			DATA_BLOB ntlmssp_verf = data_blob(NULL, auth_len);
			BOOL store_ok;

			/* save the reply away, for use a little later */
			prs_copy_data_out((char *)ntlmssp_verf.data, &auth_verf, auth_len);

			store_ok = (NT_STATUS_IS_OK(ntlmssp_store_response(cli->ntlmssp_pipe_state, 
									   ntlmssp_verf)));

			data_blob_free(&ntlmssp_verf);
			return store_ok;
		} 
		else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
			/* nothing to do here - we don't seem to be able to 
			   validate the bindack based on VL's comments */
			return True;
		}
	}
	
	if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
		NTSTATUS nt_status;
		DATA_BLOB sig;
		if ((cli->pipe_auth_flags & AUTH_PIPE_SIGN) ||
		    (cli->pipe_auth_flags & AUTH_PIPE_SEAL)) {
			if (auth_len != RPC_AUTH_NTLMSSP_CHK_LEN) {
				DEBUG(0,("rpc_auth_pipe: wrong ntlmssp auth len %d\n", auth_len));
				return False;
			}
			sig = data_blob(NULL, auth_len);
			prs_copy_data_out((char *)sig.data, &auth_verf, auth_len);
		}
	
		/*
		 * Unseal any sealed data in the PDU, not including the
		 * 8 byte auth_header or the auth_data.
		 */

		/*
		 * Now unseal and check the auth verifier in the auth_data at
		 * the end of the packet. 
		 */

		if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
			if (data_len < 0) {
				DEBUG(1, ("Can't unseal - data_len < 0!!\n"));
				return False;
			}
			nt_status = ntlmssp_unseal_packet(cli->ntlmssp_pipe_state, 
								 (unsigned char *)reply_data, data_len,
								 &sig);
		} 
		else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
			nt_status = ntlmssp_check_packet(cli->ntlmssp_pipe_state, 
								(const unsigned char *)reply_data, data_len,
								&sig);
		}

		data_blob_free(&sig);

		if (!NT_STATUS_IS_OK(nt_status)) {
			DEBUG(0, ("rpc_auth_pipe: could not validate "
				  "incoming NTLMSSP packet!\n"));
			return False;
		}
	}

	if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
		RPC_AUTH_NETSEC_CHK chk;

		if (auth_len != RPC_AUTH_NETSEC_CHK_LEN) {
			DEBUG(0,("rpc_auth_pipe: wrong schannel auth len %d\n", auth_len));
			return False;
		}

		if (!smb_io_rpc_auth_netsec_chk("schannel_auth_sign", 
						&chk, &auth_verf, 0)) {
			DEBUG(0, ("rpc_auth_pipe: schannel unmarshalling "
				  "RPC_AUTH_NETSECK_CHK failed\n"));
			return False;
		}

		if (!netsec_decode(&cli->auth_info,
				   cli->pipe_auth_flags,
				   SENDER_IS_ACCEPTOR,
				   &chk, reply_data, data_len)) {
			DEBUG(0, ("rpc_auth_pipe: Could not decode schannel\n"));
			return False;
		}

		cli->auth_info.seq_num++;

	}
	return True;
}
Пример #9
0
static BOOL rpc_pipe_bind(struct cli_state *cli, int pipe_idx, const char *my_name)
{
	RPC_IFACE abstract;
	RPC_IFACE transfer;
	prs_struct rpc_out;
	prs_struct rdata;
	uint32 rpc_call_id;
	char buffer[MAX_PDU_FRAG_LEN];

	if ( (pipe_idx < 0) || (pipe_idx >= PI_MAX_PIPES) )
		return False;

	DEBUG(5,("Bind RPC Pipe[%x]: %s\n", cli->nt_pipe_fnum, pipe_names[pipe_idx].client_pipe));

	if (!valid_pipe_name(pipe_idx, &abstract, &transfer))
		return False;

	prs_init(&rpc_out, 0, cli->mem_ctx, MARSHALL);

	/*
	 * Use the MAX_PDU_FRAG_LEN buffer to store the bind request.
	 */

	prs_give_memory( &rpc_out, buffer, sizeof(buffer), False);

	rpc_call_id = get_rpc_call_id();

	if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
		NTSTATUS nt_status;
		fstring password;

		DEBUG(5, ("NTLMSSP authenticated pipe selected\n"));

		nt_status = ntlmssp_client_start(&cli->ntlmssp_pipe_state);
		
		if (!NT_STATUS_IS_OK(nt_status))
			return False;

		/* Currently the NTLMSSP code does not implement NTLM2 correctly for signing or sealing */

		cli->ntlmssp_pipe_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;

		nt_status = ntlmssp_set_username(cli->ntlmssp_pipe_state, 
						 cli->user_name);
		if (!NT_STATUS_IS_OK(nt_status))
			return False;

		nt_status = ntlmssp_set_domain(cli->ntlmssp_pipe_state, 
					       cli->domain);	
		if (!NT_STATUS_IS_OK(nt_status))
			return False;

		if (cli->pwd.null_pwd) {
			nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, 
							 NULL);
			if (!NT_STATUS_IS_OK(nt_status))
				return False;
		} else {
			pwd_get_cleartext(&cli->pwd, password);
			nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, 
							 password);
			if (!NT_STATUS_IS_OK(nt_status))
				return False;
		}

		if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
			cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
		}

		if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
			cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
		}
	} else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
		cli->auth_info.seq_num = 0;
	}

	/* Marshall the outgoing data. */
	create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
	                    &abstract, &transfer,
	                    global_myname(), cli->domain);

	/* Initialize the incoming data struct. */
	prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL);

	/* send data on \PIPE\.  receive a response */
	if (rpc_api_pipe(cli, &rpc_out, &rdata, RPC_BINDACK)) {
		RPC_HDR_BA   hdr_ba;

		DEBUG(5, ("rpc_pipe_bind: rpc_api_pipe returned OK.\n"));

		if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0)) {
			DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
			prs_mem_free(&rdata);
			return False;
		}

		if(!check_bind_response(&hdr_ba, pipe_idx, &transfer)) {
			DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
			prs_mem_free(&rdata);
			return False;
		}

		cli->max_xmit_frag = hdr_ba.bba.max_tsize;
		cli->max_recv_frag = hdr_ba.bba.max_rsize;

		/*
		 * If we're doing NTLMSSP auth we need to send a reply to
		 * the bind-ack to complete the 3-way challenge response
		 * handshake.
		 */

		if ((cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) 
		    && !rpc_send_auth_reply(cli, &rdata, rpc_call_id)) {
			DEBUG(0,("rpc_pipe_bind: rpc_send_auth_reply failed.\n"));
			prs_mem_free(&rdata);
			return False;
		}
		prs_mem_free(&rdata);
		return True;
	}

	return False;
}
Пример #10
0
static ssize_t process_complete_pdu(pipes_struct *p)
{
	prs_struct rpc_in;
	size_t data_len = p->in_data.pdu_received_len;
	char *data_p = (char *)&p->in_data.current_in_pdu[0];
	BOOL reply = False;

	if(p->fault_state) {
		DEBUG(10,("process_complete_pdu: pipe %s in fault state.\n",
			p->name ));
		set_incoming_fault(p);
		setup_fault_pdu(p, NT_STATUS(0x1c010002));
		return (ssize_t)data_len;
	}

	prs_init( &rpc_in, 0, 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_BIND:
		case RPC_ALTCONT:
			/*
			 * 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_BINDRESP:
			/*
			 * We assume that a pipe bind_resp is only in one pdu.
			 */
			if(pipe_init_outgoing_data(p))
				reply = api_pipe_bind_auth_resp(p, &rpc_in);
			break;
		case RPC_REQUEST:
			reply = process_request_pdu(p, &rpc_in);
			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", p->pipe_srv_name));
		set_incoming_fault(p);
		setup_fault_pdu(p, NT_STATUS(0x1c010002));
		prs_mem_free(&rpc_in);
	} else {
		/*
		 * Reset the lengths. We're ready for a new pdu.
		 */
		p->in_data.pdu_needed_len = 0;
		p->in_data.pdu_received_len = 0;
	}

	prs_mem_free(&rpc_in);
	return (ssize_t)data_len;
}