/*
  parse a uint16_t
*/
_PUBLIC_ enum ndr_err_code ndr_pull_uint16(struct ndr_pull *ndr, int ndr_flags, uint16_t *v)
{
	NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
	NDR_PULL_ALIGN(ndr, 2);
	NDR_PULL_NEED_BYTES(ndr, 2);
	*v = NDR_SVAL(ndr, ndr->offset);
	ndr->offset += 2;
	return NDR_ERR_SUCCESS;
}
/*
  parse a double
*/
_PUBLIC_ enum ndr_err_code ndr_pull_double(struct ndr_pull *ndr, int ndr_flags, double *v)
{
	NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
	NDR_PULL_ALIGN(ndr, 8);
	NDR_PULL_NEED_BYTES(ndr, 8);
	memcpy(v, ndr->data+ndr->offset, 8);
	ndr->offset += 8;
	return NDR_ERR_SUCCESS;
}
/*
  parse a int32_t
*/
_PUBLIC_ enum ndr_err_code ndr_pull_int32(struct ndr_pull *ndr, int ndr_flags, int32_t *v)
{
	NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
	NDR_PULL_ALIGN(ndr, 4);
	NDR_PULL_NEED_BYTES(ndr, 4);
	*v = NDR_IVALS(ndr, ndr->offset);
	ndr->offset += 4;
	return NDR_ERR_SUCCESS;
}
Esempio n. 4
0
/*
  parse a pointer
*/
_PUBLIC_ enum ndr_err_code ndr_pull_pointer(struct ndr_pull *ndr, int ndr_flags, void* *v)
{
	uintptr_t h;
	NDR_PULL_ALIGN(ndr, sizeof(h));
	NDR_PULL_NEED_BYTES(ndr, sizeof(h));
	memcpy(&h, ndr->data+ndr->offset, sizeof(h));
	ndr->offset += sizeof(h);
	*v = (void *)h;
	return NDR_ERR_SUCCESS;
}
Esempio n. 5
0
/*
  parse a udlongr
*/
_PUBLIC_ enum ndr_err_code ndr_pull_udlongr(struct ndr_pull *ndr, int ndr_flags, uint64_t *v)
{
	NDR_PULL_CHECK_FLAGS(ndr, ndr_flags);
	NDR_PULL_ALIGN(ndr, 4);
	NDR_PULL_NEED_BYTES(ndr, 8);
	*v = ((uint64_t)NDR_IVAL(ndr, ndr->offset)) << 32;
	*v |= NDR_IVAL(ndr, ndr->offset+4);
	ndr->offset += 8;
	return NDR_ERR_SUCCESS;
}
Esempio n. 6
0
_PUBLIC_ enum ndr_err_code ndr_pull_AV_PAIR_LIST(struct ndr_pull *ndr, int ndr_flags, struct AV_PAIR_LIST *r)
{
	uint32_t cntr_pair_0;
	TALLOC_CTX *_mem_save_pair_0;
	if (ndr_flags & NDR_SCALARS) {
		uint32_t offset = 0;
		NDR_CHECK(ndr_pull_align(ndr, 4));
		r->count = 0;
		if (ndr->data_size > 0) {
			NDR_PULL_NEED_BYTES(ndr, 4);
		}
		while (offset + 4 <= ndr->data_size) {
			uint16_t length;
			uint16_t type;
			type = SVAL(ndr->data + offset, 0);
			if (type == MsvAvEOL) {
				r->count++;
				break;
			}
			length = SVAL(ndr->data + offset, 2);
			offset += length + 4;
			r->count++;
		}
		NDR_PULL_ALLOC_N(ndr, r->pair, r->count);
		_mem_save_pair_0 = NDR_PULL_GET_MEM_CTX(ndr);
		NDR_PULL_SET_MEM_CTX(ndr, r->pair, 0);
		for (cntr_pair_0 = 0; cntr_pair_0 < r->count; cntr_pair_0++) {
			NDR_CHECK(ndr_pull_AV_PAIR(ndr, NDR_SCALARS, &r->pair[cntr_pair_0]));
		}
		NDR_PULL_SET_MEM_CTX(ndr, _mem_save_pair_0, 0);
	}
	if (ndr_flags & NDR_BUFFERS) {
		_mem_save_pair_0 = NDR_PULL_GET_MEM_CTX(ndr);
		NDR_PULL_SET_MEM_CTX(ndr, r->pair, 0);
		for (cntr_pair_0 = 0; cntr_pair_0 < r->count; cntr_pair_0++) {
			NDR_CHECK(ndr_pull_AV_PAIR(ndr, NDR_BUFFERS, &r->pair[cntr_pair_0]));
		}
		NDR_PULL_SET_MEM_CTX(ndr, _mem_save_pair_0, 0);
	}
	return NDR_ERR_SUCCESS;
}
Esempio n. 7
0
NTSTATUS ndr_check_string_terminator(struct ndr_pull *ndr, uint32_t count, uint32_t element_size)
{
	uint32_t i;
	struct ndr_pull_save save_offset;

	ndr_pull_save(ndr, &save_offset);
	ndr_pull_advance(ndr, (count - 1) * element_size);
	NDR_PULL_NEED_BYTES(ndr, element_size);

	for (i = 0; i < element_size; i++) {
		 if (ndr->data[ndr->offset+i] != 0) {
			ndr_pull_restore(ndr, &save_offset);

			return ndr_pull_error(ndr, NDR_ERR_ARRAY_SIZE, "String terminator not present or outside string boundaries");
		 }
	}

	ndr_pull_restore(ndr, &save_offset);

	return NT_STATUS_OK;
}
Esempio n. 8
0
/*
  handle subcontext buffers, which in midl land are user-marshalled, but
  we use magic in pidl to make them easier to cope with
*/
_PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start(struct ndr_pull *ndr,
				   struct ndr_pull **_subndr,
				   size_t header_size,
				   ssize_t size_is)
{
	struct ndr_pull *subndr;
	uint32_t r_content_size;
	bool force_le = false;
	bool force_be = false;

	switch (header_size) {
	case 0: {
		uint32_t content_size = ndr->data_size - ndr->offset;
		if (size_is >= 0) {
			content_size = size_is;
		}
		r_content_size = content_size;
		break;
	}

	case 2: {
		uint16_t content_size;
		NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &content_size));
		if (size_is >= 0 && size_is != content_size) {
			return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d", 
						(int)size_is, (int)content_size);
		}
		r_content_size = content_size;
		break;
	}

	case 4: {
		uint32_t content_size;
		NDR_CHECK(ndr_pull_uint3264(ndr, NDR_SCALARS, &content_size));
		if (size_is >= 0 && size_is != content_size) {
			return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d", 
						(int)size_is, (int)content_size);
		}
		r_content_size = content_size;
		break;
	}
	case 0xFFFFFC01: {
		/*
		 * Common Type Header for the Serialization Stream
		 * See [MS-RPCE] 2.2.6 Type Serialization Version 1
		 */
		uint8_t version;
		uint8_t drep;
		uint16_t hdrlen;
		uint32_t filler;
		uint32_t content_size;
		uint32_t reserved;

		/* version */
		NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &version));

		if (version != 1) {
			return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
					      "Bad subcontext (PULL) Common Type Header version %d != 1",
					      (int)version);
		}

		/*
		 * 0x10 little endian
		 * 0x00 big endian
		 */
		NDR_CHECK(ndr_pull_uint8(ndr, NDR_SCALARS, &drep));
		if (drep == 0x10) {
			force_le = true;
		} else if (drep == 0x00) {
			force_be = true;
		} else {
			return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
					      "Bad subcontext (PULL) Common Type Header invalid drep 0x%02X",
					      (unsigned int)drep);
		}

		/* length of the "Private Header for Constructed Type" */
		NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &hdrlen));
		if (hdrlen != 8) {
			return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
					      "Bad subcontext (PULL) Common Type Header length %d != 8",
					      (int)hdrlen);
		}

		/* filler should be ignored */
		NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &filler));

		/*
		 * Private Header for Constructed Type
		 */
		/* length - will be updated latter */
		NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &content_size));
		if (size_is >= 0 && size_is != content_size) {
			return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) size_is(%d) mismatch content_size %d",
					      (int)size_is, (int)content_size);
		}
		/* the content size must be a multiple of 8 */
		if ((content_size % 8) != 0) {
			return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT,
					      "Bad subcontext (PULL) size_is(%d) not padded to 8 content_size %d",
					      (int)size_is, (int)content_size);
		}
		r_content_size = content_size;

		/* reserved */
		NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &reserved));
		break;
	}
	default:
		return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PULL) header_size %d", 
				      (int)header_size);
	}

	NDR_PULL_NEED_BYTES(ndr, r_content_size);

	subndr = talloc_zero(ndr, struct ndr_pull);
	NDR_ERR_HAVE_NO_MEMORY(subndr);
	subndr->flags		= ndr->flags & ~LIBNDR_FLAG_NDR64;
	subndr->current_mem_ctx	= ndr->current_mem_ctx;

	subndr->data = ndr->data + ndr->offset;
	subndr->offset = 0;
	subndr->data_size = r_content_size;
	subndr->iconv_convenience = talloc_reference(subndr, ndr->iconv_convenience);

	if (force_le) {
		ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN);
	} else if (force_be) {
		ndr_set_flags(&ndr->flags, LIBNDR_FLAG_BIGENDIAN);
	}

	*_subndr = subndr;
	return NDR_ERR_SUCCESS;
}
Esempio n. 9
0
/**
  pull a general string from the wire
*/
NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s)
{
	char *as=NULL;
	uint32_t len1, ofs, len2;
	uint16_t len3;
	int ret;
	charset_t chset = CH_UTF16LE;
	unsigned byte_mul = 2;
	unsigned flags = ndr->flags;
	unsigned c_len_term = 0;

	if (!(ndr_flags & NDR_SCALARS)) {
		return NT_STATUS_OK;
	}

	if (NDR_BE(ndr)) {
		chset = CH_UTF16BE;
	}

	if (flags & LIBNDR_FLAG_STR_ASCII) {
		chset = CH_DOS;
		byte_mul = 1;
		flags &= ~LIBNDR_FLAG_STR_ASCII;
	}

	if (flags & LIBNDR_FLAG_STR_UTF8) {
		chset = CH_UTF8;
		byte_mul = 1;
		flags &= ~LIBNDR_FLAG_STR_UTF8;
	}

	flags &= ~LIBNDR_FLAG_STR_CONFORMANT;
	if (flags & LIBNDR_FLAG_STR_CHARLEN) {
		c_len_term = 1;
		flags &= ~LIBNDR_FLAG_STR_CHARLEN;
	}

	switch (flags & LIBNDR_STRING_FLAGS) {
	case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
	case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
		NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
		NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
		if (ofs != 0) {
			return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
					      ndr->flags & LIBNDR_STRING_FLAGS);
		}
		NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len2));
		if (len2 > len1) {
			return ndr_pull_error(ndr, NDR_ERR_STRING, 
					      "Bad string lengths len1=%u ofs=%u len2=%u\n", 
					      len1, ofs, len2);
		}
		NDR_PULL_NEED_BYTES(ndr, (len2 + c_len_term)*byte_mul);
		if (len2 == 0) {
			as = talloc_strdup(ndr->current_mem_ctx, "");
		} else {
			ret = convert_string_talloc(ndr->current_mem_ctx,
						    chset, CH_UNIX, 
						    ndr->data+ndr->offset, 
						    (len2 + c_len_term)*byte_mul,
						    &as, True);
			if (ret == -1) {
				return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
						      "Bad character conversion");
			}
		}
		NDR_CHECK(ndr_pull_advance(ndr, (len2 + c_len_term)*byte_mul));

		if (len1 != len2) {
			DEBUG(6,("len1[%u] != len2[%u] '%s'\n", len1, len2, as));
		}

		/* this is a way of detecting if a string is sent with the wrong
		   termination */
		if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
			if (strlen(as) < (len2 + c_len_term)) {
				DEBUG(6,("short string '%s'\n", as));
			}
		} else {
			if (strlen(as) == (len2 + c_len_term)) {
				DEBUG(6,("long string '%s'\n", as));
			}
		}
		*s = as;
		break;

	case LIBNDR_FLAG_STR_SIZE4:
	case LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
		NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
		NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
		if (len1 == 0) {
			as = talloc_strdup(ndr->current_mem_ctx, "");
		} else {
			ret = convert_string_talloc(ndr->current_mem_ctx,
						    chset, CH_UNIX, 
						    ndr->data+ndr->offset, 
						    (len1 + c_len_term)*byte_mul,
						    &as, False);
			if (ret == -1) {
				return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
						      "Bad character conversion");
			}
		}
		NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));

		/* this is a way of detecting if a string is sent with the wrong
		   termination */
		if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
			if (strlen(as) < (len1 + c_len_term)) {
				DEBUG(6,("short string '%s'\n", as));
			}
		} else {
			if (strlen(as) == (len1 + c_len_term)) {
				DEBUG(6,("long string '%s'\n", as));
			}
		}
		*s = as;
		break;

	case LIBNDR_FLAG_STR_LEN4:
	case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_NOTERM:
		NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &ofs));
		if (ofs != 0) {
			return ndr_pull_error(ndr, NDR_ERR_STRING, "non-zero array offset with string flags 0x%x\n",
					      ndr->flags & LIBNDR_STRING_FLAGS);
		}
		NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &len1));
		NDR_PULL_NEED_BYTES(ndr, (len1 + c_len_term)*byte_mul);
		if (len1 == 0) {
			as = talloc_strdup(ndr->current_mem_ctx, "");
		} else {
			ret = convert_string_talloc(ndr->current_mem_ctx,
						    chset, CH_UNIX, 
						    ndr->data+ndr->offset, 
						    (len1 + c_len_term)*byte_mul,
						    &as, False);
			if (ret == -1) {
				return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
						      "Bad character conversion");
			}
		}
		NDR_CHECK(ndr_pull_advance(ndr, (len1 + c_len_term)*byte_mul));

		/* this is a way of detecting if a string is sent with the wrong
		   termination */
		if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
			if (strlen(as) < (len1 + c_len_term)) {
				DEBUG(6,("short string '%s'\n", as));
			}
		} else {
			if (strlen(as) == (len1 + c_len_term)) {
				DEBUG(6,("long string '%s'\n", as));
			}
		}
		*s = as;
		break;


	case LIBNDR_FLAG_STR_SIZE2:
	case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM:
		NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
		NDR_PULL_NEED_BYTES(ndr, (len3 + c_len_term)*byte_mul);
		if (len3 == 0) {
			as = talloc_strdup(ndr->current_mem_ctx, "");
		} else {
			ret = convert_string_talloc(ndr->current_mem_ctx,
						    chset, CH_UNIX, 
						    ndr->data+ndr->offset, 
						    (len3 + c_len_term)*byte_mul,
						    &as, False);
			if (ret == -1) {
				return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
						      "Bad character conversion");
			}
		}
		NDR_CHECK(ndr_pull_advance(ndr, (len3 + c_len_term)*byte_mul));

		/* this is a way of detecting if a string is sent with the wrong
		   termination */
		if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
			if (strlen(as) < (len3 + c_len_term)) {
				DEBUG(6,("short string '%s'\n", as));
			}
		} else {
			if (strlen(as) == (len3 + c_len_term)) {
				DEBUG(6,("long string '%s'\n", as));
			}
		}
		*s = as;
		break;

	case LIBNDR_FLAG_STR_SIZE2|LIBNDR_FLAG_STR_NOTERM|LIBNDR_FLAG_STR_BYTESIZE:
		NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &len3));
		NDR_PULL_NEED_BYTES(ndr, len3);
		if (len3 == 0) {
			as = talloc_strdup(ndr->current_mem_ctx, "");
		} else {
			ret = convert_string_talloc(ndr->current_mem_ctx,
						    chset, CH_UNIX, 
						    ndr->data+ndr->offset, 
						    len3, &as, False);
			if (ret == -1) {
				return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
						      "Bad character conversion");
			}
		}
		NDR_CHECK(ndr_pull_advance(ndr, len3));
		*s = as;
		break;

	case LIBNDR_FLAG_STR_NULLTERM:
		if (byte_mul == 1) {
			len1 = ascii_len_n((const char *)(ndr->data+ndr->offset), ndr->data_size - ndr->offset);
		} else {
			len1 = utf16_len_n(ndr->data+ndr->offset, ndr->data_size - ndr->offset);
		}
		ret = convert_string_talloc(ndr->current_mem_ctx,
					    chset, CH_UNIX, 
					    ndr->data+ndr->offset, 
					    len1, &as, False);
		if (ret == -1) {
			return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
					      "Bad character conversion");
		}
		NDR_CHECK(ndr_pull_advance(ndr, len1));
		*s = as;
		break;

	case LIBNDR_FLAG_STR_FIXLEN15:
	case LIBNDR_FLAG_STR_FIXLEN32:
		len1 = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15;
		NDR_PULL_NEED_BYTES(ndr, len1*byte_mul);
		ret = convert_string_talloc(ndr->current_mem_ctx,
					    chset, CH_UNIX, 
					    ndr->data+ndr->offset, 
					    len1*byte_mul, &as, False);
		if (ret == -1) {
			return ndr_pull_error(ndr, NDR_ERR_CHARCNV, 
					      "Bad character conversion");
		}
		NDR_CHECK(ndr_pull_advance(ndr, len1*byte_mul));
		*s = as;
		break;

	default:
		return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
				      ndr->flags & LIBNDR_STRING_FLAGS);
	}

	return NT_STATUS_OK;
}