예제 #1
0
static NTSTATUS create_rpc_bind_resp(struct cli_state *cli,
				 uint32 rpc_call_id,
				 prs_struct *rpc_out)
{
	NTSTATUS nt_status;
	RPC_HDR hdr;
	RPC_HDR_AUTHA hdr_autha;
	DATA_BLOB ntlmssp_null_response = data_blob(NULL, 0);
	DATA_BLOB ntlmssp_reply;
	int auth_type, auth_level;

	/* The response is picked up from the internal cache,
	   where it was placed by the rpc_auth_pipe() code */
	nt_status = ntlmssp_update(cli->ntlmssp_pipe_state,
				   ntlmssp_null_response,
				   &ntlmssp_reply);
	
	if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		return nt_status;
	}

	/* Create the request RPC_HDR */
	init_rpc_hdr(&hdr, RPC_BINDRESP, 0x0, rpc_call_id,
		     RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN + ntlmssp_reply.length,
		     ntlmssp_reply.length );
	
	/* Marshall it. */
	if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
		DEBUG(0,("create_rpc_bind_resp: failed to marshall RPC_HDR.\n"));
		data_blob_free(&ntlmssp_reply);
		return NT_STATUS_NO_MEMORY;
	}

	get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level);
	
	/* Create the request RPC_HDR_AUTHA */
	init_rpc_hdr_autha(&hdr_autha, MAX_PDU_FRAG_LEN, MAX_PDU_FRAG_LEN,
			   auth_type, auth_level, 0x00);

	if(!smb_io_rpc_hdr_autha("hdr_autha", &hdr_autha, rpc_out, 0)) {
		DEBUG(0,("create_rpc_bind_resp: failed to marshall RPC_HDR_AUTHA.\n"));
		data_blob_free(&ntlmssp_reply);
		return NT_STATUS_NO_MEMORY;
	}

	/*
	 * Append the auth data to the outgoing buffer.
	 */

	if(!prs_copy_data_in(rpc_out, (char *)ntlmssp_reply.data, ntlmssp_reply.length)) {
		DEBUG(0,("create_rpc_bind_req: failed to grow parse struct to add auth.\n"));
		data_blob_free(&ntlmssp_reply);
		return NT_STATUS_NO_MEMORY;
	}

	data_blob_free(&ntlmssp_reply);
	return NT_STATUS_OK;
}
예제 #2
0
static uint32 create_rpc_request(prs_struct *rpc_out, uint8 op_num, int data_len, int auth_len, uint8 flags, uint32 oldid, uint32 data_left)
{
	uint32 alloc_hint;
	RPC_HDR     hdr;
	RPC_HDR_REQ hdr_req;
	uint32 callid = oldid ? oldid : get_rpc_call_id();

	DEBUG(5,("create_rpc_request: opnum: 0x%x data_len: 0x%x\n", op_num, data_len));

	/* create the rpc header RPC_HDR */
	init_rpc_hdr(&hdr, RPC_REQUEST, flags,
	             callid, data_len, auth_len);

	/*
	 * The alloc hint should be the amount of data, not including 
	 * RPC headers & footers.
	 */

	if (auth_len != 0)
		alloc_hint = data_len - RPC_HEADER_LEN - RPC_HDR_AUTH_LEN - auth_len;
	else
		alloc_hint = data_len - RPC_HEADER_LEN;

	DEBUG(10,("create_rpc_request: data_len: %x auth_len: %x alloc_hint: %x\n",
	           data_len, auth_len, alloc_hint));

	/* Create the rpc request RPC_HDR_REQ */
	init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);

	/* stream-time... */
	if(!smb_io_rpc_hdr("hdr    ", &hdr, rpc_out, 0))
		return 0;

	if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, rpc_out, 0))
		return 0;

	if (prs_offset(rpc_out) != RPC_HEADER_LEN + RPC_HDR_REQ_LEN)
		return 0;

	return callid;
}
예제 #3
0
static BOOL rpc_check_hdr(prs_struct *rdata, RPC_HDR *rhdr, 
                          BOOL *first, BOOL *last, uint32 *len)
{
	DEBUG(5,("rpc_check_hdr: rdata->data_size = %u\n", (uint32)prs_data_size(rdata) ));

	/* Next call sets endian bit. */

	if(!smb_io_rpc_hdr("rpc_hdr   ", rhdr, rdata, 0)) {
		DEBUG(0,("rpc_check_hdr: Failed to unmarshall RPC_HDR.\n"));
		return False;
	}

	if (prs_offset(rdata) != RPC_HEADER_LEN) {
		DEBUG(0,("rpc_check_hdr: offset was %x, should be %x.\n", prs_offset(rdata), RPC_HEADER_LEN));
		return False;
	}

	(*first) = ((rhdr->flags & RPC_FLG_FIRST) != 0);
	(*last) = ((rhdr->flags & RPC_FLG_LAST ) != 0);
	(*len) = (uint32)rhdr->frag_len - prs_data_size(rdata);

	return (rhdr->pkt_type != RPC_FAULT);
}
예제 #4
0
파일: srv_pipe_hnd.c 프로젝트: gojdic/samba
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. */
}
예제 #5
0
파일: srv_pipe.c 프로젝트: hajuuk/R7000
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;
}
예제 #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 NTSTATUS create_rpc_bind_req(struct cli_state *cli, prs_struct *rpc_out, 
				    uint32 rpc_call_id,
				    RPC_IFACE *abstract, RPC_IFACE *transfer,
				    const char *my_name, const char *domain)
{
	RPC_HDR hdr;
	RPC_HDR_RB hdr_rb;
	RPC_HDR_AUTH hdr_auth;
	int auth_len = 0;
	int auth_type, auth_level;
	size_t saved_hdr_offset = 0;

	prs_struct auth_info;
	prs_init(&auth_info, RPC_HDR_AUTH_LEN, /* we will need at least this much */
		prs_get_mem_context(rpc_out), MARSHALL);

	if (cli->pipe_auth_flags) {
		get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level);
		
		/*
		 * Create the auth structs we will marshall.
		 */
		
		init_rpc_hdr_auth(&hdr_auth, auth_type, auth_level, 0x00, 1);
		
		/*
		 * Now marshall the data into the temporary parse_struct.
		 */
		
		if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &auth_info, 0)) {
			DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR_AUTH.\n"));
			prs_mem_free(&auth_info);
			return NT_STATUS_NO_MEMORY;
		}
		saved_hdr_offset = prs_offset(&auth_info);
	}
	
	if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {

		NTSTATUS nt_status;
		DATA_BLOB null_blob = data_blob(NULL, 0);
		DATA_BLOB request;

		DEBUG(5, ("Processing NTLMSSP Negotiate\n"));
		nt_status = ntlmssp_update(cli->ntlmssp_pipe_state,
					   null_blob,
					   &request);

		if (!NT_STATUS_EQUAL(nt_status, 
				     NT_STATUS_MORE_PROCESSING_REQUIRED)) {
			prs_mem_free(&auth_info);
			return nt_status;
		}

		/* Auth len in the rpc header doesn't include auth_header. */
		auth_len = request.length;
		prs_copy_data_in(&auth_info, (char *)request.data, request.length);

		DEBUG(5, ("NTLMSSP Negotiate:\n"));
		dump_data(5, (const char *)request.data, request.length);

		data_blob_free(&request);

	} else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
		RPC_AUTH_NETSEC_NEG netsec_neg;

		/* Use lp_workgroup() if domain not specified */

		if (!domain || !domain[0]) {
			DEBUG(10,("create_rpc_bind_req: no domain; assuming my own\n"));
			domain = lp_workgroup();
		}

		init_rpc_auth_netsec_neg(&netsec_neg, domain, my_name);

		/*
		 * Now marshall the data into the temporary parse_struct.
		 */

		if(!smb_io_rpc_auth_netsec_neg("netsec_neg",
					       &netsec_neg, &auth_info, 0)) {
			DEBUG(0,("Failed to marshall RPC_AUTH_NETSEC_NEG.\n"));
			prs_mem_free(&auth_info);
			return NT_STATUS_NO_MEMORY;
		}

		/* Auth len in the rpc header doesn't include auth_header. */
		auth_len = prs_offset(&auth_info) - saved_hdr_offset;
	}

	/* Create the request RPC_HDR */
	init_rpc_hdr(&hdr, RPC_BIND, 0x3, rpc_call_id, 
		RPC_HEADER_LEN + RPC_HDR_RB_LEN + prs_offset(&auth_info),
		auth_len);

	if(!smb_io_rpc_hdr("hdr"   , &hdr, rpc_out, 0)) {
		DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR.\n"));
		prs_mem_free(&auth_info);
		return NT_STATUS_NO_MEMORY;
	}

	/* create the bind request RPC_HDR_RB */
	init_rpc_hdr_rb(&hdr_rb, MAX_PDU_FRAG_LEN, MAX_PDU_FRAG_LEN, 0x0,
			0x1, 0x0, 0x1, abstract, transfer);

	/* Marshall the bind request data */
	if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
		DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR_RB.\n"));
		prs_mem_free(&auth_info);
		return NT_STATUS_NO_MEMORY;
	}

	/*
	 * Grow the outgoing buffer to store any auth info.
	 */

	if(auth_len != 0) {
		if(!prs_append_prs_data( rpc_out, &auth_info)) {
			DEBUG(0,("create_rpc_bind_req: failed to grow parse struct to add auth.\n"));
			prs_mem_free(&auth_info);
			return NT_STATUS_NO_MEMORY;
		}
	}
	prs_mem_free(&auth_info);
	return NT_STATUS_OK;
}