예제 #1
0
BOOL smb_io_relstr(const char *desc, RPC_BUFFER *buffer, int depth, UNISTR *string)
{
	prs_struct *ps=&buffer->prs;
	
	if (MARSHALLING(ps)) {
		uint32 struct_offset = prs_offset(ps);
		uint32 relative_offset;
		
		buffer->string_at_end -= (size_of_relative_string(string) - 4);
		if(!prs_set_offset(ps, buffer->string_at_end))
			return False;
#if 0	/* JERRY */
		/*
		 * Win2k does not align strings in a buffer
		 * Tested against WinNT 4.0 SP 6a & 2k SP2  --jerry
		 */
		if (!prs_align(ps))
			return False;
#endif
		buffer->string_at_end = prs_offset(ps);
		
		/* write the string */
		if (!smb_io_unistr(desc, string, ps, depth))
			return False;

		if(!prs_set_offset(ps, struct_offset))
			return False;
		
		relative_offset=buffer->string_at_end - buffer->struct_start;
		/* write its offset */
		if (!prs_uint32("offset", ps, depth, &relative_offset))
			return False;
	}
	else {
		uint32 old_offset;
		
		/* read the offset */
		if (!prs_uint32("offset", ps, depth, &(buffer->string_at_end)))
			return False;

		if (buffer->string_at_end == 0)
			return True;

		old_offset = prs_offset(ps);
		if(!prs_set_offset(ps, buffer->string_at_end+buffer->struct_start))
			return False;

		/* read the string */
		if (!smb_io_unistr(desc, string, ps, depth))
			return False;

		if(!prs_set_offset(ps, old_offset))
			return False;
	}
	return True;
}
예제 #2
0
BOOL smb_io_relsecdesc(const char *desc, RPC_BUFFER *buffer, int depth, SEC_DESC **secdesc)
{
	prs_struct *ps= &buffer->prs;

	prs_debug(ps, depth, desc, "smb_io_relsecdesc");
	depth++;

	if (MARSHALLING(ps)) {
		uint32 struct_offset = prs_offset(ps);
		uint32 relative_offset;

		if (! *secdesc) {
			relative_offset = 0;
			if (!prs_uint32("offset", ps, depth, &relative_offset))
				return False;
			return True;
		}
		
		if (*secdesc != NULL) {
			buffer->string_at_end -= sec_desc_size(*secdesc);

			if(!prs_set_offset(ps, buffer->string_at_end))
				return False;
			/* write the secdesc */
			if (!sec_io_desc(desc, secdesc, ps, depth))
				return False;

			if(!prs_set_offset(ps, struct_offset))
				return False;
		}

		relative_offset=buffer->string_at_end - buffer->struct_start;
		/* write its offset */

		if (!prs_uint32("offset", ps, depth, &relative_offset))
			return False;
	} else {
		uint32 old_offset;
		
		/* read the offset */
		if (!prs_uint32("offset", ps, depth, &buffer->string_at_end))
			return False;

		old_offset = prs_offset(ps);
		if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start))
			return False;

		/* read the sd */
		if (!sec_io_desc(desc, secdesc, ps, depth))
			return False;

		if(!prs_set_offset(ps, old_offset))
			return False;
	}
	return True;
}
예제 #3
0
파일: parse_prs.c 프로젝트: jophxy/samba
BOOL prs_append_prs_data(prs_struct *dst, prs_struct *src)
{
	if(!prs_grow(dst, prs_offset(src)))
		return False;

	memcpy(&dst->data_p[dst->data_offset], prs_data_p(src), (size_t)prs_offset(src));
	dst->data_offset += prs_offset(src);

	return True;
}
예제 #4
0
BOOL sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth)
{
	uint32 off_len;
	uint32 off_max_len;
	uint32 old_offset;
	uint32 size;
	SEC_DESC_BUF *psdb;

	if (ppsdb == NULL)
		return False;

	psdb = *ppsdb;

	if (UNMARSHALLING(ps) && psdb == NULL) {
		if((psdb = (SEC_DESC_BUF *)prs_alloc_mem(ps,sizeof(SEC_DESC_BUF))) == NULL)
			return False;
		*ppsdb = psdb;
	}

	prs_debug(ps, depth, desc, "sec_io_desc_buf");
	depth++;

	if(!prs_align(ps))
		return False;
	
	if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len))
		return False;

	if(!prs_uint32    ("ptr  ", ps, depth, &psdb->ptr))
		return False;

	if(!prs_uint32_pre("len    ", ps, depth, &psdb->len, &off_len))
		return False;

	old_offset = prs_offset(ps);

	/* reading, length is non-zero; writing, descriptor is non-NULL */
	if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) {
		if(!sec_io_desc("sec   ", &psdb->sec, ps, depth))
			return False;
	}

	if(!prs_align(ps))
		return False;
	
	size = prs_offset(ps) - old_offset;
	if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size))
		return False;

	if(!prs_uint32_post("len    ", ps, depth, &psdb->len, off_len, size))
		return False;

	return True;
}
예제 #5
0
BOOL prs_rpcbuffer(const char *desc, prs_struct *ps, int depth, RPC_BUFFER *buffer)
{
	prs_debug(ps, depth, desc, "prs_rpcbuffer");
	depth++;

	/* reading */
	if (UNMARSHALLING(ps)) {
		buffer->size=0;
		buffer->string_at_end=0;
		
		if (!prs_uint32("size", ps, depth, &buffer->size))
			return False;
					
		/*
		 * JRA. I'm not sure if the data in here is in big-endian format if
		 * the client is big-endian. Leave as default (little endian) for now.
		 */

		if (!prs_init(&buffer->prs, buffer->size, prs_get_mem_context(ps), UNMARSHALL))
			return False;

		if (!prs_append_some_prs_data(&buffer->prs, ps, prs_offset(ps), buffer->size))
			return False;

		if (!prs_set_offset(&buffer->prs, 0))
			return False;

		if (!prs_set_offset(ps, buffer->size+prs_offset(ps)))
			return False;

		buffer->string_at_end=buffer->size;
		
		return True;
	}
	else {
		BOOL ret = False;

		if (!prs_uint32("size", ps, depth, &buffer->size))
			goto out;

		if (!prs_append_some_prs_data(ps, &buffer->prs, 0, buffer->size))
			goto out;

		ret = True;
	out:

		/* We have finished with the data in buffer->prs - free it. */
		prs_mem_free(&buffer->prs);

		return ret;
	}
}
예제 #6
0
/**********************************************************************
 Initialize a new spoolss buff for use by a client rpc
**********************************************************************/
void rpcbuf_init(RPC_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx)
{
	buffer->size = size;
	buffer->string_at_end = size;
	prs_init(&buffer->prs, size, ctx, MARSHALL);
	buffer->struct_start = prs_offset(&buffer->prs);
}
예제 #7
0
파일: parse_prs.c 프로젝트: jophxy/samba
/* useful function to store a structure in rpc wire format */
int tdb_prs_store(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps)
{
    TDB_DATA kbuf, dbuf;
    kbuf.dptr = keystr;
    kbuf.dsize = strlen(keystr)+1;
    dbuf.dptr = prs_data_p(ps);
    dbuf.dsize = prs_offset(ps);
    return tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
}
예제 #8
0
BOOL prs_copy_all_data_out(char *dst, prs_struct *src)
{
	uint32 len = prs_offset(src);

	if (!len)
		return True;

	prs_set_offset(src, 0);
	return prs_copy_data_out(dst, src, len);
}
예제 #9
0
BOOL smb_io_hdrbuf_pre(const char *desc, BUFHDR *hdr, prs_struct *ps, int depth, uint32 *offset)
{
	(*offset) = prs_offset(ps);
	if (ps->io) {

		/* reading. */

		if(!smb_io_hdrbuf(desc, hdr, ps, depth))
			return False;

	} else {

		/* writing. */

		if(!prs_set_offset(ps, prs_offset(ps) + (sizeof(uint32) * 2)))
			return False;
	}

	return True;
}
예제 #10
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);
}
예제 #11
0
static BOOL rpc_send_auth_reply(struct cli_state *cli, prs_struct *rdata, uint32 rpc_call_id)
{
	prs_struct rpc_out;
	ssize_t ret;

	prs_init(&rpc_out, RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN, /* need at least this much */ 
		 cli->mem_ctx, MARSHALL);

	if (!NT_STATUS_IS_OK(create_rpc_bind_resp(cli, rpc_call_id,
						  &rpc_out))) {
		return False;
	}

	if ((ret = cli_write(cli, cli->nt_pipe_fnum, 0x8, prs_data_p(&rpc_out), 
			0, (size_t)prs_offset(&rpc_out))) != (ssize_t)prs_offset(&rpc_out)) {
		DEBUG(0,("rpc_send_auth_reply: cli_write failed. Return was %d\n", (int)ret));
		prs_mem_free(&rpc_out);
		return False;
	}

	prs_mem_free(&rpc_out);
	return True;
}
예제 #12
0
BOOL sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
{
	uint32 old_offset;
	uint32 offset_ace_size;

	if (psa == NULL)
		return False;

	prs_debug(ps, depth, desc, "sec_io_ace");
	depth++;
	
	old_offset = prs_offset(ps);

	if(!prs_uint8("type ", ps, depth, &psa->type))
		return False;

	if(!prs_uint8("flags", ps, depth, &psa->flags))
		return False;

	if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
		return False;

	if(!sec_io_access("info ", &psa->info, ps, depth))
		return False;

	/* check whether object access is present */
	if (!sec_ace_object(psa->type)) {
		if (!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
			return False;
	} else {
		if (!prs_uint32("obj_flags", ps, depth, &psa->obj_flags))
			return False;

		if (psa->obj_flags & SEC_ACE_OBJECT_PRESENT)
			if (!smb_io_uuid("obj_guid", &psa->obj_guid, ps,depth))
				return False;

		if (psa->obj_flags & SEC_ACE_OBJECT_INHERITED_PRESENT)
			if (!smb_io_uuid("inh_guid", &psa->inh_guid, ps,depth))
				return False;

		if(!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
			return False;
	}

	if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_ace_size, old_offset))
		return False;
	return True;
}
예제 #13
0
BOOL smb_io_hdrbuf_post(const char *desc, BUFHDR *hdr, prs_struct *ps, int depth, 
				uint32 ptr_hdrbuf, uint32 max_len, uint32 len)
{
	if (!ps->io) {
		/* writing: go back and do a retrospective job.  i hate this */

		uint32 old_offset = prs_offset(ps);

		init_buf_hdr(hdr, max_len, len);
		if(!prs_set_offset(ps, ptr_hdrbuf))
			return False;
		if(!smb_io_hdrbuf(desc, hdr, ps, depth))
			return False;

		if(!prs_set_offset(ps, old_offset))
			return False;
	}

	return True;
}
예제 #14
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;
}
예제 #15
0
BOOL rpcbuf_alloc_size(RPC_BUFFER *buffer, uint32 buffer_size)
{
	prs_struct *ps;
	uint32 extra_space;
	uint32 old_offset;
	
	/* if we don't need anything. don't do anything */
	
	if ( buffer_size == 0x0 )
		return True;

	if (!buffer) {
		return False;
	}

	ps= &buffer->prs;

	/* damn, I'm doing the reverse operation of prs_grow() :) */
	if (buffer_size < prs_data_size(ps))
		extra_space=0;
	else	
		extra_space = buffer_size - prs_data_size(ps);

	/*
	 * save the offset and move to the end of the buffer
	 * prs_grow() checks the extra_space against the offset
	 */
	old_offset=prs_offset(ps);	
	prs_set_offset(ps, prs_data_size(ps));
	
	if (!prs_grow(ps, extra_space))
		return False;

	prs_set_offset(ps, old_offset);

	buffer->string_at_end=prs_data_size(ps);

	return True;
}
예제 #16
0
BOOL sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
{
	uint32 old_offset;
	uint32 max_offset = 0; /* after we're done, move offset to end */
	uint32 tmp_offset = 0;
	
	SEC_DESC *psd;

	if (ppsd == NULL)
		return False;

	psd = *ppsd;

	if (psd == NULL) {
		if(UNMARSHALLING(ps)) {
			if((psd = (SEC_DESC *)prs_alloc_mem(ps,sizeof(SEC_DESC))) == NULL)
				return False;
			*ppsd = psd;
		} else {
			/* Marshalling - just ignore. */
			return True;
		}
	}

	prs_debug(ps, depth, desc, "sec_io_desc");
	depth++;

#if 0	
	/*
	 * if alignment is needed, should be done by the the 
	 * caller.  Not here.  This caused me problems when marshalling
	 * printer info into a buffer.   --jerry
	 */
	if(!prs_align(ps))
		return False;
#endif
	
	/* start of security descriptor stored for back-calc offset purposes */
	old_offset = prs_offset(ps);

	if(!prs_uint16("revision ", ps, depth, &psd->revision))
		return False;

	if(!prs_uint16("type     ", ps, depth, &psd->type))
		return False;

	if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
		return False;

	if(!prs_uint32("off_grp_sid  ", ps, depth, &psd->off_grp_sid))
		return False;

	if(!prs_uint32("off_sacl     ", ps, depth, &psd->off_sacl))
		return False;

	if(!prs_uint32("off_dacl     ", ps, depth, &psd->off_dacl))
		return False;

	max_offset = MAX(max_offset, prs_offset(ps));

	if (psd->off_owner_sid != 0) {

		tmp_offset = prs_offset(ps);
		if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
			return False;

		if (UNMARSHALLING(ps)) {
			/* reading */
			if((psd->owner_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->owner_sid))) == NULL)
				return False;
		}

		if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
			return False;

		max_offset = MAX(max_offset, prs_offset(ps));

		if (!prs_set_offset(ps,tmp_offset))
			return False;
	}

	if (psd->off_grp_sid != 0) {

		tmp_offset = prs_offset(ps);
		if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
			return False;

		if (UNMARSHALLING(ps)) {
			/* reading */
			if((psd->grp_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->grp_sid))) == NULL)
				return False;
		}

		if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
			return False;
			
		max_offset = MAX(max_offset, prs_offset(ps));

		if (!prs_set_offset(ps,tmp_offset))
			return False;
	}

	if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
		tmp_offset = prs_offset(ps);
		if(!prs_set_offset(ps, old_offset + psd->off_sacl))
			return False;
		if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
			return False;
		max_offset = MAX(max_offset, prs_offset(ps));
		if (!prs_set_offset(ps,tmp_offset))
			return False;
	}


	if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
		tmp_offset = prs_offset(ps);
		if(!prs_set_offset(ps, old_offset + psd->off_dacl))
			return False;
		if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
			return False;
		max_offset = MAX(max_offset, prs_offset(ps));
		if (!prs_set_offset(ps,tmp_offset))
			return False;
	}

	if(!prs_set_offset(ps, max_offset))
		return False;
	return True;
}
예제 #17
0
BOOL sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
{
	unsigned int i;
	uint32 old_offset;
	uint32 offset_acl_size;
	SEC_ACL *psa;

	/*
	 * Note that the size is always a multiple of 4 bytes due to the
	 * nature of the data structure.  Therefore the prs_align() calls
	 * have been removed as they through us off when doing two-layer
	 * marshalling such as in the printing code (NEW_BUFFER).  --jerry
	 */

	if (ppsa == NULL)
		return False;

	psa = *ppsa;

	if(UNMARSHALLING(ps) && psa == NULL) {
		/*
		 * This is a read and we must allocate the stuct to read into.
		 */
		if((psa = (SEC_ACL *)prs_alloc_mem(ps, sizeof(SEC_ACL))) == NULL)
			return False;
		*ppsa = psa;
	}

	prs_debug(ps, depth, desc, "sec_io_acl");
	depth++;
	
	old_offset = prs_offset(ps);

	if(!prs_uint16("revision", ps, depth, &psa->revision))
		return False;

	if(!prs_uint16_pre("size     ", ps, depth, &psa->size, &offset_acl_size))
		return False;

	if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces))
		return False;

	if (UNMARSHALLING(ps)) {
		/*
		 * Even if the num_aces is zero, allocate memory as there's a difference
		 * between a non-present DACL (allow all access) and a DACL with no ACE's
		 * (allow no access).
		 */
		if((psa->ace = (SEC_ACE *)prs_alloc_mem(ps,sizeof(psa->ace[0]) * (psa->num_aces+1))) == NULL)
			return False;
	}

	for (i = 0; i < psa->num_aces; i++) {
		fstring tmp;
		slprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
		if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
			return False;
	}

	if(!prs_uint16_post("size     ", ps, depth, &psa->size, offset_acl_size, old_offset))
		return False;

	return True;
}
예제 #18
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;
}
예제 #19
0
파일: parse_prs.c 프로젝트: jophxy/samba
BOOL prs_unistr(const char *name, prs_struct *ps, int depth, UNISTR *str)
{
	int len = 0;
	unsigned char *p = (unsigned char *)str->buffer;
	uint8 *start;
	char *q;
	uint32 max_len;
	uint16* ptr;

	if (MARSHALLING(ps)) {

		for(len = 0; str->buffer[len] != 0; len++)
			;

		q = prs_mem_get(ps, (len+1)*2);
		if (q == NULL)
			return False;

		start = (uint8*)q;

		for(len = 0; str->buffer[len] != 0; len++) 
		{
			if(ps->bigendian_data) 
			{
				/* swap bytes - p is little endian, q is big endian. */
				q[0] = (char)p[1];
				q[1] = (char)p[0];
				p += 2;
				q += 2;
			} 
			else 
			{
				q[0] = (char)p[0];
				q[1] = (char)p[1];
				p += 2;
				q += 2;
			}
		}

		/*
		 * even if the string is 'empty' (only an \0 char)
		 * at this point the leading \0 hasn't been parsed.
		 * so parse it now
		 */

		q[0] = 0;
		q[1] = 0;
		q += 2;

		len++;

		dump_data(5+depth, (char *)start, len * 2);
	}
	else { /* unmarshalling */
	
		uint32 alloc_len = 0;
		q = prs_data_p(ps) + prs_offset(ps);

		/*
		 * Work out how much space we need and talloc it.
		 */
		max_len = (ps->buffer_size - ps->data_offset)/sizeof(uint16);

		/* the test of the value of *ptr helps to catch the circumstance
		   where we have an emtpty (non-existent) string in the buffer */
		for ( ptr = (uint16 *)q; *ptr && (alloc_len <= max_len); alloc_len++)
			/* do nothing */ 
			;

		/* should we allocate anything at all? */
		str->buffer = (uint16 *)prs_alloc_mem(ps,alloc_len * sizeof(uint16));
		if ((str->buffer == NULL) && (alloc_len > 0))
			return False;

		p = (unsigned char *)str->buffer;

		len = 0;
		/* the (len < alloc_len) test is to prevent us from overwriting
		   memory that is not ours...if we get that far, we have a non-null
		   terminated string in the buffer and have messed up somewhere */
		while ((len < alloc_len) && (*(uint16 *)q != 0))
		{
			if(ps->bigendian_data) 
			{
				/* swap bytes - q is big endian, p is little endian. */
				p[0] = (unsigned char)q[1];
				p[1] = (unsigned char)q[0];
				p += 2;
				q += 2;
			} else {

				p[0] = (unsigned char)q[0];
				p[1] = (unsigned char)q[1];
				p += 2;
				q += 2;
			}

			len++;
		} 
		if (len < alloc_len)
		{
			/* NULL terminate the UNISTR */
			str->buffer[len++] = '\0';
		}
	}

	/* set the offset in the prs_struct; 'len' points to the
	   terminiating NULL in the UNISTR so we need to go one more
	   uint16 */
	ps->data_offset += (len)*2;
	
	return True;
}
예제 #20
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;
}
예제 #21
0
static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR *values )
{
	DEVICEMODE	*devmode;
	prs_struct	prs;
	uint32		offset;
	UNISTR2		data;
	char 		*p;
	uint32 printer_status = PRINTER_STATUS_OK;
	
	regval_ctr_addvalue( values, "Attributes",       REG_DWORD, (char*)&info2->attributes,       sizeof(info2->attributes) );
	regval_ctr_addvalue( values, "Priority",         REG_DWORD, (char*)&info2->priority,         sizeof(info2->attributes) );
	regval_ctr_addvalue( values, "ChangeID",         REG_DWORD, (char*)&info2->changeid,         sizeof(info2->changeid) );
	regval_ctr_addvalue( values, "Default Priority", REG_DWORD, (char*)&info2->default_priority, sizeof(info2->default_priority) );
	
	/* lie and say everything is ok since we don't want to call print_queue_length() to get the real status */
	regval_ctr_addvalue( values, "Status",           REG_DWORD, (char*)&printer_status,          sizeof(info2->status) );

	regval_ctr_addvalue( values, "StartTime",        REG_DWORD, (char*)&info2->starttime,        sizeof(info2->starttime) );
	regval_ctr_addvalue( values, "UntilTime",        REG_DWORD, (char*)&info2->untiltime,        sizeof(info2->untiltime) );

	/* strip the \\server\ from this string */
	if ( !(p = strrchr( info2->printername, '\\' ) ) )
		p = info2->printername;
	else
		p++;
	init_unistr2( &data, p, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->location, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Location", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->comment, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Description", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->parameters, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Parameters", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->portname, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Port", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->sharename, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Share Name", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->drivername, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Printer Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, info2->sepfile, UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Separator File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, "WinPrint", UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Print Processor",  REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

	init_unistr2( &data, "RAW", UNI_STR_TERMINATE);
	regval_ctr_addvalue( values, "Datatype", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );

		
	/* use a prs_struct for converting the devmode and security 
	   descriptor to REG_BINARY */
	
	prs_init( &prs, RPC_MAX_PDU_FRAG_LEN, values, MARSHALL);

	/* stream the device mode */
		
	if ( (devmode = construct_dev_mode( info2->sharename )) != NULL ) {
		if ( spoolss_io_devmode( "devmode", &prs, 0, devmode ) ) {
			offset = prs_offset( &prs );
			regval_ctr_addvalue( values, "Default Devmode", REG_BINARY, prs_data_p(&prs), offset );
		}
	}
		
	prs_mem_clear( &prs );
	prs_set_offset( &prs, 0 );
		
	/* stream the printer security descriptor */
	
	if ( info2->secdesc_buf && info2->secdesc_buf->len )  {
		if ( sec_io_desc("sec_desc", &info2->secdesc_buf->sec, &prs, 0 ) ) {
			offset = prs_offset( &prs );
			regval_ctr_addvalue( values, "Security", REG_BINARY, prs_data_p(&prs), offset );
		}
	}

	prs_mem_free( &prs );

	return;		
}
예제 #22
0
파일: srv_pipe_hnd.c 프로젝트: gojdic/samba
static bool process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
{
    uint32 ss_padding_len = 0;
    size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
                      (p->hdr.auth_len ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;

    if(!p->pipe_bound) {
        DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
        set_incoming_fault(p);
        return False;
    }

    /*
     * Check if we need to do authentication processing.
     * This is only done on requests, not binds.
     */

    /*
     * Read the RPC request header.
     */

    if(!smb_io_rpc_hdr_req("req", &p->hdr_req, rpc_in_p, 0)) {
        DEBUG(0,("process_request_pdu: failed to unmarshall RPC_HDR_REQ.\n"));
        set_incoming_fault(p);
        return False;
    }

    switch(p->auth.auth_type) {
    case PIPE_AUTH_TYPE_NONE:
        break;

    case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
    case PIPE_AUTH_TYPE_NTLMSSP:
    {
        NTSTATUS status;
        if(!api_pipe_ntlmssp_auth_process(p, rpc_in_p, &ss_padding_len, &status)) {
            DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));
            DEBUG(0,("process_request_pdu: error was %s.\n", nt_errstr(status) ));
            set_incoming_fault(p);
            return False;
        }
        break;
    }

    case PIPE_AUTH_TYPE_SCHANNEL:
        if (!api_pipe_schannel_process(p, rpc_in_p, &ss_padding_len)) {
            DEBUG(3,("process_request_pdu: failed to do schannel processing.\n"));
            set_incoming_fault(p);
            return False;
        }
        break;

    default:
        DEBUG(0,("process_request_pdu: unknown auth type %u set.\n", (unsigned int)p->auth.auth_type ));
        set_incoming_fault(p);
        return False;
    }

    /* Now we've done the sign/seal we can remove any padding data. */
    if (data_len > ss_padding_len) {
        data_len -= ss_padding_len;
    }

    /*
     * Check the data length doesn't go over the 15Mb limit.
     * increased after observing a bug in the Windows NT 4.0 SP6a
     * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC
     * will not fit in the initial buffer of size 0x1068   --jerry 22/01/2002
     */

    if(prs_offset(&p->in_data.data) + data_len > MAX_RPC_DATA_SIZE) {
        DEBUG(0,("process_request_pdu: rpc data buffer too large (%u) + (%u)\n",
                 (unsigned int)prs_data_size(&p->in_data.data), (unsigned int)data_len ));
        set_incoming_fault(p);
        return False;
    }

    /*
     * Append the data portion into the buffer and return.
     */

    if(!prs_append_some_prs_data(&p->in_data.data, rpc_in_p, prs_offset(rpc_in_p), data_len)) {
        DEBUG(0,("process_request_pdu: Unable to append data size %u to parse buffer of size %u.\n",
                 (unsigned int)data_len, (unsigned int)prs_data_size(&p->in_data.data) ));
        set_incoming_fault(p);
        return False;
    }

    if(p->hdr.flags & RPC_FLG_LAST) {
        bool ret = False;
        /*
         * Ok - we finally have a complete RPC stream.
         * Call the rpc command to process it.
         */

        /*
         * Ensure the internal prs buffer size is *exactly* the same
         * size as the current offset.
         */

        if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data))) {
            DEBUG(0,("process_request_pdu: Call to prs_set_buffer_size failed!\n"));
            set_incoming_fault(p);
            return False;
        }

        /*
         * Set the parse offset to the start of the data and set the
         * prs_struct to UNMARSHALL.
         */

        prs_set_offset(&p->in_data.data, 0);
        prs_switch_type(&p->in_data.data, UNMARSHALL);

        /*
         * Process the complete data stream here.
         */

        free_pipe_context(p);

        if(pipe_init_outgoing_data(p)) {
            ret = api_pipe_request(p);
        }

        free_pipe_context(p);

        /*
         * We have consumed the whole data stream. Set back to
         * marshalling and set the offset back to the start of
         * the buffer to re-use it (we could also do a prs_mem_free()
         * and then re_init on the next start of PDU. Not sure which
         * is best here.... JRA.
         */

        prs_switch_type(&p->in_data.data, MARSHALL);
        prs_set_offset(&p->in_data.data, 0);
        return ret;
    }

    return True;
}
예제 #23
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. */
}
예제 #24
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;
}
예제 #25
0
BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num,
                      prs_struct *data, prs_struct *rdata)
{
	uint32 auth_len, real_auth_len, auth_hdr_len, max_data, data_left, data_sent;
	NTSTATUS nt_status;
	BOOL ret = False;
	uint32 callid = 0;
	fstring dump_name;

	auth_len = 0;
	real_auth_len = 0;
	auth_hdr_len = 0;

	if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {	
		if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {	
			auth_len = RPC_AUTH_NTLMSSP_CHK_LEN;
		}
		if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {	
			auth_len = RPC_AUTH_NETSEC_CHK_LEN;
		}
		auth_hdr_len = RPC_HDR_AUTH_LEN;
	}

	/*
	 * calc how much actual data we can send in a PDU fragment
	 */
	max_data = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
		auth_hdr_len - auth_len - 8;
	
	for (data_left = prs_offset(data), data_sent = 0; data_left > 0;) {
		prs_struct outgoing_packet;
		prs_struct sec_blob;
		uint32 data_len, send_size;
		uint8 flags = 0;
		uint32 auth_padding = 0;
		DATA_BLOB sign_blob;

		/*
		 * how much will we send this time
		 */
		send_size = MIN(data_left, max_data);

		if (!prs_init(&sec_blob, send_size, /* will need at least this much */
			      cli->mem_ctx, MARSHALL)) {
			DEBUG(0,("Could not malloc %u bytes",
				 send_size+auth_padding));
			return False;
		}

		if(!prs_append_some_prs_data(&sec_blob, data, 
					     data_sent, send_size)) {
			DEBUG(0,("Failed to append data to netsec blob\n"));
			prs_mem_free(&sec_blob);
			return False;
		}

		/*
		 * NT expects the data that is sealed to be 8-byte
		 * aligned. The padding must be encrypted as well and
		 * taken into account when generating the
		 * authentication verifier. The amount of padding must
		 * be stored in the auth header.
		 */

		if (cli->pipe_auth_flags) {
			size_t data_and_padding_size;
			int auth_type;
			int auth_level;
			prs_align_uint64(&sec_blob);

			get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level);

			data_and_padding_size = prs_offset(&sec_blob);
			auth_padding = data_and_padding_size - send_size;

			/* insert the auth header */
			
			if(!create_auth_hdr(&sec_blob, auth_type, auth_level, auth_padding)) {
				prs_mem_free(&sec_blob);
				return False;
			}
			
			/* create an NTLMSSP signature */
			if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
				/*
				 * Seal the outgoing data if requested.
				 */
				if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
					
					nt_status = ntlmssp_seal_packet(cli->ntlmssp_pipe_state,
									       (unsigned char*)prs_data_p(&sec_blob),
									       data_and_padding_size,
									       &sign_blob);
					if (!NT_STATUS_IS_OK(nt_status)) {
						prs_mem_free(&sec_blob);
						return False;
					}
				} 
				else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
					
					nt_status = ntlmssp_sign_packet(cli->ntlmssp_pipe_state,
									       (unsigned char*)prs_data_p(&sec_blob),
									       data_and_padding_size, &sign_blob);
					if (!NT_STATUS_IS_OK(nt_status)) {
						prs_mem_free(&sec_blob);
						return False;
					}
				}
				

				/* write auth footer onto the packet */
				real_auth_len = sign_blob.length;
				
				prs_copy_data_in(&sec_blob, (char *)sign_blob.data, sign_blob.length);
				data_blob_free(&sign_blob);

			}
			else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {	
				size_t parse_offset_marker;
				RPC_AUTH_NETSEC_CHK verf;
				DEBUG(10,("SCHANNEL seq_num=%d\n", cli->auth_info.seq_num));
				
				netsec_encode(&cli->auth_info, 
					      cli->pipe_auth_flags,
					      SENDER_IS_INITIATOR,
					      &verf,
					      prs_data_p(&sec_blob),
					      data_and_padding_size);

				cli->auth_info.seq_num++;

				/* write auth footer onto the packet */
				
				parse_offset_marker = prs_offset(&sec_blob);
				if (!smb_io_rpc_auth_netsec_chk("", &verf,
								&sec_blob, 0)) {
					prs_mem_free(&sec_blob);
					return False;
				}
				real_auth_len = prs_offset(&sec_blob) - parse_offset_marker;
			}
		}

		data_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + prs_offset(&sec_blob);

		/*
		 * Malloc parse struct to hold it (and enough for alignments).
		 */
		if(!prs_init(&outgoing_packet, data_len + 8, 
			     cli->mem_ctx, MARSHALL)) {
			DEBUG(0,("rpc_api_pipe_req: Failed to malloc %u bytes.\n", (unsigned int)data_len ));
			return False;
		}

		if (data_left == prs_offset(data))
			flags |= RPC_FLG_FIRST;

		if (data_left <= max_data)
			flags |= RPC_FLG_LAST;
		/*
		 * Write out the RPC header and the request header.
		 */
		if(!(callid = create_rpc_request(&outgoing_packet, op_num, 
						 data_len, real_auth_len, flags, 
						 callid, data_left))) {
			DEBUG(0,("rpc_api_pipe_req: Failed to create RPC request.\n"));
			prs_mem_free(&outgoing_packet);
			prs_mem_free(&sec_blob);
			return False;
		}

		prs_append_prs_data(&outgoing_packet, &sec_blob);
		prs_mem_free(&sec_blob);

		DEBUG(100,("data_len: %x data_calc_len: %x\n", data_len, 
			   prs_offset(&outgoing_packet)));
		
		if (flags & RPC_FLG_LAST)
			ret = rpc_api_pipe(cli, &outgoing_packet, 
					   rdata, RPC_RESPONSE);
		else {
			cli_write(cli, cli->nt_pipe_fnum, 0x0008,
				   prs_data_p(&outgoing_packet),
				   data_sent, data_len);
		}
		prs_mem_free(&outgoing_packet);
		data_sent += send_size;
		data_left -= send_size;
	}
	/* Also capture received data */
	slprintf(dump_name, sizeof(dump_name) - 1, "reply_%s",
		 cli_pipe_get_name(cli));
	prs_dump(dump_name, op_num, rdata);

	return ret;
}
예제 #26
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. */
}
예제 #27
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;
}
예제 #28
0
BOOL smb_io_relarraystr(const char *desc, RPC_BUFFER *buffer, int depth, uint16 **string)
{
	UNISTR chaine;
	
	prs_struct *ps=&buffer->prs;
	
	if (MARSHALLING(ps)) {
		uint32 struct_offset = prs_offset(ps);
		uint32 relative_offset;
		uint16 *p;
		uint16 *q;
		uint16 zero=0;
		p=*string;
		q=*string;

		/* first write the last 0 */
		buffer->string_at_end -= 2;
		if(!prs_set_offset(ps, buffer->string_at_end))
			return False;

		if(!prs_uint16("leading zero", ps, depth, &zero))
			return False;

		while (p && (*p!=0)) {	
			while (*q!=0)
				q++;

			/* Yes this should be malloc not talloc. Don't change. */

			chaine.buffer = (uint16 *)
				SMB_MALLOC((q-p+1)*sizeof(uint16));
			if (chaine.buffer == NULL)
				return False;

			memcpy(chaine.buffer, p, (q-p+1)*sizeof(uint16));

			buffer->string_at_end -= (q-p+1)*sizeof(uint16);

			if(!prs_set_offset(ps, buffer->string_at_end)) {
				SAFE_FREE(chaine.buffer);
				return False;
			}

			/* write the string */
			if (!smb_io_unistr(desc, &chaine, ps, depth)) {
				SAFE_FREE(chaine.buffer);
				return False;
			}
			q++;
			p=q;

			SAFE_FREE(chaine.buffer);
		}
		
		if(!prs_set_offset(ps, struct_offset))
			return False;
		
		relative_offset=buffer->string_at_end - buffer->struct_start;
		/* write its offset */
		if (!prs_uint32("offset", ps, depth, &relative_offset))
			return False;

	} else {

		/* UNMARSHALLING */

		uint32 old_offset;
		uint16 *chaine2=NULL;
		int l_chaine=0;
		int l_chaine2=0;
		size_t realloc_size = 0;

		*string=NULL;
				
		/* read the offset */
		if (!prs_uint32("offset", ps, depth, &buffer->string_at_end))
			return False;

		old_offset = prs_offset(ps);
		if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start))
			return False;
	
		do {
			if (!smb_io_unistr(desc, &chaine, ps, depth))
				return False;
			
			l_chaine=str_len_uni(&chaine);
			
			/* we're going to add two more bytes here in case this
			   is the last string in the array and we need to add 
			   an extra NULL for termination */
			if (l_chaine > 0) {
				realloc_size = (l_chaine2+l_chaine+2)*sizeof(uint16);

				/* Yes this should be realloc - it's freed below. JRA */

				if((chaine2=(uint16 *)SMB_REALLOC(chaine2, realloc_size)) == NULL) {
					return False;
				}
				memcpy(chaine2+l_chaine2, chaine.buffer, (l_chaine+1)*sizeof(uint16));
				l_chaine2+=l_chaine+1;
			}
		
		} while(l_chaine!=0);
		
		/* the end should be bould NULL terminated so add 
		   the second one here */
		if (chaine2)
		{
			chaine2[l_chaine2] = '\0';
			*string=(uint16 *)TALLOC_MEMDUP(prs_get_mem_context(ps),chaine2,realloc_size);
			if (!*string) {
				return False;
			}
			SAFE_FREE(chaine2);
		}

		if(!prs_set_offset(ps, old_offset))
			return False;
	}
	return True;
}
예제 #29
0
static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
{
	BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0);
	size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
				(auth_verify ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;

	if(!p->pipe_bound) {
		DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
		set_incoming_fault(p);
		return False;
	}

	/*
	 * Check if we need to do authentication processing.
	 * This is only done on requests, not binds.
	 */

	/*
	 * Read the RPC request header.
	 */

	if(!smb_io_rpc_hdr_req("req", &p->hdr_req, rpc_in_p, 0)) {
		DEBUG(0,("process_request_pdu: failed to unmarshall RPC_HDR_REQ.\n"));
		set_incoming_fault(p);
		return False;
	}

	if(p->ntlmssp_auth_validated && !api_pipe_auth_process(p, rpc_in_p)) {
		DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));
		set_incoming_fault(p);
		return False;
	}

	if (p->ntlmssp_auth_requested && !p->ntlmssp_auth_validated) {

		/*
		 * Authentication _was_ requested and it already failed.
		 */

		DEBUG(0,("process_request_pdu: RPC request received on pipe %s "
			 "where authentication failed. Denying the request.\n",
			 p->name));
		set_incoming_fault(p);
		return False;
	}

	if (p->netsec_auth_validated && !api_pipe_netsec_process(p, rpc_in_p)) {
		DEBUG(3,("process_request_pdu: failed to do schannel processing.\n"));
		set_incoming_fault(p);
		return False;
	}

	/*
	 * Check the data length doesn't go over the 15Mb limit.
	 * increased after observing a bug in the Windows NT 4.0 SP6a
	 * spoolsv.exe when the response to a GETPRINTERDRIVER2 RPC
	 * will not fit in the initial buffer of size 0x1068   --jerry 22/01/2002
	 */
	
	if(prs_offset(&p->in_data.data) + data_len > 15*1024*1024) {
		DEBUG(0,("process_request_pdu: rpc data buffer too large (%u) + (%u)\n",
				(unsigned int)prs_data_size(&p->in_data.data), (unsigned int)data_len ));
		set_incoming_fault(p);
		return False;
	}

	/*
	 * Append the data portion into the buffer and return.
	 */

	if(!prs_append_some_prs_data(&p->in_data.data, rpc_in_p, prs_offset(rpc_in_p), data_len)) {
		DEBUG(0,("process_request_pdu: Unable to append data size %u to parse buffer of size %u.\n",
				(unsigned int)data_len, (unsigned int)prs_data_size(&p->in_data.data) ));
		set_incoming_fault(p);
		return False;
	}

	if(p->hdr.flags & RPC_FLG_LAST) {
		BOOL ret = False;
		/*
		 * Ok - we finally have a complete RPC stream.
		 * Call the rpc command to process it.
		 */

		/*
		 * Ensure the internal prs buffer size is *exactly* the same
		 * size as the current offset.
		 */

 		if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data)))
		{
			DEBUG(0,("process_request_pdu: Call to prs_set_buffer_size failed!\n"));
			set_incoming_fault(p);
			return False;
		}

		/*
		 * Set the parse offset to the start of the data and set the
		 * prs_struct to UNMARSHALL.
		 */

		prs_set_offset(&p->in_data.data, 0);
		prs_switch_type(&p->in_data.data, UNMARSHALL);

		/*
		 * Process the complete data stream here.
		 */

		free_pipe_context(p);

		if(pipe_init_outgoing_data(p))
			ret = api_pipe_request(p);

		free_pipe_context(p);

		/*
		 * We have consumed the whole data stream. Set back to
		 * marshalling and set the offset back to the start of
		 * the buffer to re-use it (we could also do a prs_mem_free()
		 * and then re_init on the next start of PDU. Not sure which
		 * is best here.... JRA.
		 */

		prs_switch_type(&p->in_data.data, MARSHALL);
		prs_set_offset(&p->in_data.data, 0);
		return ret;
	}

	return True;
}