Пример #1
0
BOOL prs_string(const char *name, prs_struct *ps, int depth, char *str, int len, int max_buf_size)
{
	char *q;
	int i;

	len = MIN(len, (max_buf_size-1));

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

	for(i = 0; i < len; i++) {
		if (UNMARSHALLING(ps))
			str[i] = q[i];
		else
			q[i] = str[i];
	}

	/* The terminating null. */
	str[i] = '\0';

	if (MARSHALLING(ps)) {
		q[i] = '\0';
	}

	ps->data_offset += len+1;

	dump_data(5+depth, q, len);

	return True;
}
Пример #2
0
bool prs_init(prs_struct *ps, uint32_t size, TALLOC_CTX *ctx, bool io)
{
	ZERO_STRUCTP(ps);
	ps->io = io;
	ps->bigendian_data = RPC_LITTLE_ENDIAN;
	ps->align = RPC_PARSE_ALIGN;
	ps->is_dynamic = False;
	ps->data_offset = 0;
	ps->buffer_size = 0;
	ps->data_p = NULL;
	ps->mem_ctx = ctx;

	if (size != 0) {
		ps->buffer_size = size;
		ps->data_p = (char *)talloc_zero_size(ps->mem_ctx, size);
		if(ps->data_p == NULL) {
			DEBUG(0,("prs_init: talloc fail for %u bytes.\n", (unsigned int)size));
			return False;
		}
		ps->is_dynamic = True; /* We own this memory. */
	} else if (MARSHALLING(ps)) {
		/* If size is zero and we're marshalling we should allocate memory on demand. */
		ps->is_dynamic = True;
	}

	return True;
}
Пример #3
0
/******************************************************************
 do IO on a byte array
 ********************************************************************/
BOOL io_uint8s(char *name, io_struct *ps, int depth, uint8 **data8s, int len, unsigned flags)
{
	char *q;
	size_t num_bytes = len * sizeof(uint8);

	if (MARSHALLING(ps) && num_bytes == 0)
	{
		*data8s = NULL;
		return True;
	}

	if (!(flags & PARSE_SCALARS)) return True;

	q = io_mem_get(ps, num_bytes);
	if (q == NULL) return False;

	if (MARSHALLING(ps))
	{
		if (*data8s != NULL)
			DBG_RW_PCVAL(True, name, depth, ps->data_offset, ps->io, q, *data8s, len)
		else
			memset(q, 0, num_bytes);
	}
	else
	{
Пример #4
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;
}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
0
bool smb_io_rpc_hdr(const char *desc,  RPC_HDR *rpc, prs_struct *ps, int depth)
{
	if (rpc == NULL)
		return False;

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

	if(!prs_uint8 ("major     ", ps, depth, &rpc->major))
		return False;

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

	/* We always marshall in little endian format. */
	if (MARSHALLING(ps))
		rpc->pack_type[0] = 0x10;

	if(!prs_uint8("pack_type0", ps, depth, &rpc->pack_type[0]))
		return False;
	if(!prs_uint8("pack_type1", ps, depth, &rpc->pack_type[1]))
		return False;
	if(!prs_uint8("pack_type2", ps, depth, &rpc->pack_type[2]))
		return False;
	if(!prs_uint8("pack_type3", ps, depth, &rpc->pack_type[3]))
		return False;

	/*
	 * If reading and pack_type[0] == 0 then the data is in big-endian
	 * format. Set the flag in the prs_struct to specify reverse-endainness.
	 */

	if (UNMARSHALLING(ps) && rpc->pack_type[0] == 0) {
		DEBUG(10,("smb_io_rpc_hdr: PDU data format is big-endian. Setting flag.\n"));
		prs_set_endian_data(ps, RPC_BIG_ENDIAN);
	}

	if(!prs_uint16("frag_len  ", ps, depth, &rpc->frag_len))
		return False;
	if(!prs_uint16("auth_len  ", ps, depth, &rpc->auth_len))
		return False;
	if(!prs_uint32("call_id   ", ps, depth, &rpc->call_id))
		return False;
	return True;
}
Пример #8
0
BOOL prs_uint32_post(const char *name, prs_struct *ps, int depth, uint32 *data32,
				uint32 ptr_uint32, uint32 data_size)
{
	if (MARSHALLING(ps)) {
		/* 
		 * Writing - temporarily move the offset pointer.
		 */
		uint32 old_offset = ps->data_offset;
		ps->data_offset = ptr_uint32;
		if(!prs_uint32(name, ps, depth, &data_size)) {
			ps->data_offset = old_offset;
			return False;
		}
		ps->data_offset = old_offset;
	}
	return True;
}
Пример #9
0
BOOL prs_uint16_post(const char *name, prs_struct *ps, int depth, uint16 *data16,
				uint32 ptr_uint16, uint32 start_offset)
{
	if (MARSHALLING(ps)) {
		/* 
		 * Writing - temporarily move the offset pointer.
		 */
		uint16 data_size = ps->data_offset - start_offset;
		uint32 old_offset = ps->data_offset;

		ps->data_offset = ptr_uint16;
		if(!prs_uint16(name, ps, depth, &data_size)) {
			ps->data_offset = old_offset;
			return False;
		}
		ps->data_offset = old_offset;
	} else {
		ps->data_offset = start_offset + (uint32)(*data16);
	}
	return True;
}
Пример #10
0
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;
}
Пример #11
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;
}
Пример #12
0
/*******************************************************************
 do IO on a uint8.
 ********************************************************************/
BOOL io_format(char *name, io_struct *ps, int depth, void *data, uint32 struct_offset, unsigned flags)
{
	char *q;
	size_t item_size = 0;
	int nitems = 0;
	BOOL is_string = False;

	if (!io_format_interp(ps, &item_size, &nitems, &is_string))
		return False;

	if (is_string)
	{
		uint32 old_offset;
		uint32 str_offset;
		SMBCHR *str = (SMBCHR*)(((char*)data) + struct_offset);

		if (item_size != 1)
			return False;

		if (MARSHALLING(ps) && (flags & PARSE_SCALARS))
		{
			/* skip offset */
			q = io_mem_get_end(ps, sizeof(uint32));
			if (q == NULL)
				return False;
			DEBUG(5+depth, ("%s:    %04x z\n",
						name, ps->data_offset));
			ps->data_offset += sizeof(uint32);
			return True;
		}
		else if (MARSHALLING(ps) && (flags & PARSE_OFFSETS))
		{
			BOOL ret;
			if (str != NULL)
			{
				q = io_mem_get(ps, strlen(*str));
				q = io_mem_get_end(ps, strlen(*str));
				if (q == NULL) return False;
				str_offset = PTR_DIFF(q, ps->data_p);
			}
			else
			{
				str_offset = 0;
			}
			DEBUG(5+depth, ("%s:", name));
			if (!io_uint32("offset", ps, depth,
					&str_offset,
					PARSE_SCALARS))
				return False;
			if (str_offset == 0)
				return True;
			DEBUG(5+depth, ("%s:", name));
			old_offset = ps->data_offset;
			ps->data_offset = str_offset;
			ret = io_SMBCHR("z", ps, depth, str, PARSE_SCALARS);
			ps->data_offset = old_offset;
			return ret;
		}
		if (!(flags & PARSE_SCALARS)) return True;

		DEBUG(5+depth, ("%s:", name));
		if (!io_uint32("offset", ps, depth, &str_offset, PARSE_SCALARS))
			return False;
		str_offset &= 0xffff; /* spec says ignore above 16 bits */

		old_offset = ps->data_offset;
		ps->data_offset = str_offset;

		DEBUG(5+depth, ("%s:", name));
		if (!io_SMBCHR("z", ps, depth, str, PARSE_SCALARS))
			return False;
		ps->data_offset = old_offset;

		return True;
	}

	if ((flags & PARSE_OFFSETS))
	{
		ps->data_offset += nitems * item_size;
		return True;
	}

	if (!(flags & PARSE_SCALARS)) return True;

	DEBUG(5+depth, ("%s:", name));
	if (item_size == 1)
	{
		uint8 *u8 = (uint8*)(((char*)data) + struct_offset);
		if (nitems == 1)
		{
			return io_uint8("B", ps, depth, u8, PARSE_SCALARS);
		}
		return io_uint8s("B", ps, depth, &u8, nitems, PARSE_SCALARS);
	}
	else if (item_size == 2)
	{
		uint16 *u16 = (uint16*)(((char*)data) + struct_offset);
		if (nitems == 1)
		{
			return io_uint16("W", ps, depth, u16, PARSE_SCALARS);
		}
		return io_uint16s("W", ps, depth, u16, nitems, PARSE_SCALARS);
	}
	else if (item_size == 4)
	{
		uint32 *u32 = (uint32*)(((char*)data) + struct_offset);
		if (nitems == 1)
		{
			return io_uint32("D", ps, depth, u32, PARSE_SCALARS);
		}
		return io_uint32s("D", ps, depth, u32, nitems, PARSE_SCALARS);
	}

	return True;
}