⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ndr.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   libndr interface   Copyright (C) Andrew Tridgell 2003      This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 3 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program.  If not, see <http://www.gnu.org/licenses/>.*//*  this provides the core routines for NDR parsing functions  see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details  of NDR encoding rules*/#include "includes.h"#include "librpc/ndr/libndr.h"#include "lib/util/dlinklist.h"#include "librpc/gen_ndr/dcerpc.h"#include "param/param.h"#define NDR_BASE_MARSHALL_SIZE 1024/* this guid indicates NDR encoding in a protocol tower */const struct ndr_syntax_id ndr_transfer_syntax = {  { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },  2};const struct ndr_syntax_id ndr64_transfer_syntax = {  { 0x71710533, 0xbeba, 0x4937, {0x83, 0x19}, {0xb5,0xdb,0xef,0x9c,0xcc,0x36} },  1};/*  work out the number of bytes needed to align on a n byte boundary*/_PUBLIC_ size_t ndr_align_size(uint32_t offset, size_t n){	if ((offset & (n-1)) == 0) return 0;	return n - (offset & (n-1));}/*  initialise a ndr parse structure from a data blob*/_PUBLIC_ struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience){	struct ndr_pull *ndr;	ndr = talloc_zero(mem_ctx, struct ndr_pull);	if (!ndr) return NULL;	ndr->current_mem_ctx = mem_ctx;	ndr->data = blob->data;	ndr->data_size = blob->length;	ndr->iconv_convenience = talloc_reference(ndr, iconv_convenience);	return ndr;}/*  advance by 'size' bytes*/_PUBLIC_ enum ndr_err_code ndr_pull_advance(struct ndr_pull *ndr, uint32_t size){	ndr->offset += size;	if (ndr->offset > ndr->data_size) {		return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, 				      "ndr_pull_advance by %u failed",				      size);	}	return NDR_ERR_SUCCESS;}/*  set the parse offset to 'ofs'*/static enum ndr_err_code ndr_pull_set_offset(struct ndr_pull *ndr, uint32_t ofs){	ndr->offset = ofs;	if (ndr->offset > ndr->data_size) {		return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, 				      "ndr_pull_set_offset %u failed",				      ofs);	}	return NDR_ERR_SUCCESS;}/* create a ndr_push structure, ready for some marshalling */_PUBLIC_ struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience){	struct ndr_push *ndr;	ndr = talloc_zero(mem_ctx, struct ndr_push);	if (!ndr) {		return NULL;	}	ndr->flags = 0;	ndr->alloc_size = NDR_BASE_MARSHALL_SIZE;	ndr->data = talloc_array(ndr, uint8_t, ndr->alloc_size);	if (!ndr->data) {		return NULL;	}	ndr->iconv_convenience = talloc_reference(ndr, iconv_convenience);	return ndr;}/* return a DATA_BLOB structure for the current ndr_push marshalled data */_PUBLIC_ DATA_BLOB ndr_push_blob(struct ndr_push *ndr){	DATA_BLOB blob;	blob = data_blob_const(ndr->data, ndr->offset);	if (ndr->alloc_size > ndr->offset) {		ndr->data[ndr->offset] = 0;	}	return blob;}/*  expand the available space in the buffer to ndr->offset + extra_size*/_PUBLIC_ enum ndr_err_code ndr_push_expand(struct ndr_push *ndr, uint32_t extra_size){	uint32_t size = extra_size + ndr->offset;	if (size < ndr->offset) {		/* extra_size overflowed the offset */		return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "Overflow in push_expand to %u",				      size);	}	if (ndr->alloc_size > size) {		return NDR_ERR_SUCCESS;	}	ndr->alloc_size += NDR_BASE_MARSHALL_SIZE;	if (size+1 > ndr->alloc_size) {		ndr->alloc_size = size+1;	}	ndr->data = talloc_realloc(ndr, ndr->data, uint8_t, ndr->alloc_size);	if (!ndr->data) {		return ndr_push_error(ndr, NDR_ERR_ALLOC, "Failed to push_expand to %u",				      ndr->alloc_size);	}	return NDR_ERR_SUCCESS;}_PUBLIC_ void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...){	va_list ap;	char *s = NULL;	int i;	va_start(ap, format);	vasprintf(&s, format, ap);	va_end(ap);	for (i=0;i<ndr->depth;i++) {		DEBUGADD(0,("    "));	}	DEBUGADD(0,("%s\n", s));	free(s);}_PUBLIC_ void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...){	va_list ap;	int i;	for (i=0;i<ndr->depth;i++) {		ndr->private_data = talloc_asprintf_append_buffer(					(char *)ndr->private_data, "    ");	}	va_start(ap, format);	ndr->private_data = talloc_vasprintf_append_buffer((char *)ndr->private_data, 						    format, ap);	va_end(ap);	ndr->private_data = talloc_asprintf_append_buffer((char *)ndr->private_data, 						   "\n");}/*  a useful helper function for printing idl structures via DEBUG()*/_PUBLIC_ void ndr_print_debug(ndr_print_fn_t fn, const char *name, void *ptr){	struct ndr_print *ndr;	ndr = talloc_zero(NULL, struct ndr_print);	if (!ndr) return;	ndr->print = ndr_print_debug_helper;	ndr->depth = 1;	ndr->flags = 0;	fn(ndr, name, ptr);	talloc_free(ndr);}/*  a useful helper function for printing idl unions via DEBUG()*/_PUBLIC_ void ndr_print_union_debug(ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr){	struct ndr_print *ndr;	ndr = talloc_zero(NULL, struct ndr_print);	if (!ndr) return;	ndr->print = ndr_print_debug_helper;	ndr->depth = 1;	ndr->flags = 0;	ndr_print_set_switch_value(ndr, ptr, level);	fn(ndr, name, ptr);	talloc_free(ndr);}/*  a useful helper function for printing idl function calls via DEBUG()*/_PUBLIC_ void ndr_print_function_debug(ndr_print_function_t fn, const char *name, int flags, void *ptr){	struct ndr_print *ndr;	ndr = talloc_zero(NULL, struct ndr_print);	if (!ndr) return;	ndr->print = ndr_print_debug_helper;	ndr->depth = 1;	ndr->flags = 0;	fn(ndr, name, flags, ptr);	talloc_free(ndr);}/*  a useful helper function for printing idl structures to a string*/_PUBLIC_ char *ndr_print_struct_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, void *ptr){	struct ndr_print *ndr;	char *ret = NULL;	ndr = talloc_zero(mem_ctx, struct ndr_print);	if (!ndr) return NULL;	ndr->private_data = talloc_strdup(ndr, "");	if (!ndr->private_data) {		goto failed;	}	ndr->print = ndr_print_string_helper;	ndr->depth = 1;	ndr->flags = 0;	fn(ndr, name, ptr);	ret = talloc_steal(mem_ctx, (char *)ndr->private_data);failed:	talloc_free(ndr);	return ret;}/*  a useful helper function for printing idl unions to a string*/_PUBLIC_ char *ndr_print_union_string(TALLOC_CTX *mem_ctx, ndr_print_fn_t fn, const char *name, uint32_t level, void *ptr){	struct ndr_print *ndr;	char *ret = NULL;	ndr = talloc_zero(mem_ctx, struct ndr_print);	if (!ndr) return NULL;	ndr->private_data = talloc_strdup(ndr, "");	if (!ndr->private_data) {		goto failed;	}	ndr->print = ndr_print_string_helper;	ndr->depth = 1;	ndr->flags = 0;	ndr_print_set_switch_value(ndr, ptr, level);	fn(ndr, name, ptr);	ret = talloc_steal(mem_ctx, (char *)ndr->private_data);failed:	talloc_free(ndr);	return ret;}/*  a useful helper function for printing idl function calls to a string*/_PUBLIC_ char *ndr_print_function_string(TALLOC_CTX *mem_ctx,				ndr_print_function_t fn, const char *name, 				int flags, void *ptr){	struct ndr_print *ndr;	char *ret = NULL;	ndr = talloc_zero(mem_ctx, struct ndr_print);	if (!ndr) return NULL;	ndr->private_data = talloc_strdup(ndr, "");	if (!ndr->private_data) {		goto failed;	}	ndr->print = ndr_print_string_helper;	ndr->depth = 1;	ndr->flags = 0;	fn(ndr, name, flags, ptr);	ret = talloc_steal(mem_ctx, (char *)ndr->private_data);failed:	talloc_free(ndr);	return ret;}_PUBLIC_ void ndr_set_flags(uint32_t *pflags, uint32_t new_flags){	/* the big/little endian flags are inter-dependent */	if (new_flags & LIBNDR_FLAG_LITTLE_ENDIAN) {		(*pflags) &= ~LIBNDR_FLAG_BIGENDIAN;	}	if (new_flags & LIBNDR_FLAG_BIGENDIAN) {		(*pflags) &= ~LIBNDR_FLAG_LITTLE_ENDIAN;	}	if (new_flags & LIBNDR_FLAG_REMAINING) {		(*pflags) &= ~LIBNDR_ALIGN_FLAGS;	}	if (new_flags & LIBNDR_ALIGN_FLAGS) {		(*pflags) &= ~LIBNDR_FLAG_REMAINING;	}	(*pflags) |= new_flags;}/*  return and possibly log an NDR error*/_PUBLIC_ enum ndr_err_code ndr_pull_error(struct ndr_pull *ndr,				 enum ndr_err_code ndr_err,				 const char *format, ...){	char *s=NULL;	va_list ap;	va_start(ap, format);	vasprintf(&s, format, ap);	va_end(ap);	DEBUG(3,("ndr_pull_error(%u): %s\n", ndr_err, s));	free(s);	return ndr_err;}/*  return and possibly log an NDR error*/_PUBLIC_ enum ndr_err_code ndr_push_error(struct ndr_push *ndr,				 enum ndr_err_code ndr_err,				 const char *format, ...){	char *s=NULL;	va_list ap;	va_start(ap, format);	vasprintf(&s, format, ap);	va_end(ap);	DEBUG(3,("ndr_push_error(%u): %s\n", ndr_err, s));	free(s);	return ndr_err;}/*  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;	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_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);		}		r_content_size = content_size;		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;	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);	*_subndr = subndr;	return NDR_ERR_SUCCESS;}_PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end(struct ndr_pull *ndr,				 struct ndr_pull *subndr,				 size_t header_size,				 ssize_t size_is){	uint32_t advance;	if (size_is >= 0) {		advance = size_is;	} else if (header_size > 0) {		advance = subndr->data_size;	} else {		advance = subndr->offset;	}	NDR_CHECK(ndr_pull_advance(ndr, advance));	return NDR_ERR_SUCCESS;}_PUBLIC_ enum ndr_err_code ndr_push_subcontext_start(struct ndr_push *ndr,				   struct ndr_push **_subndr,				   size_t header_size,				   ssize_t size_is){	struct ndr_push *subndr;	subndr = ndr_push_init_ctx(ndr, ndr->iconv_convenience);	NDR_ERR_HAVE_NO_MEMORY(subndr);	subndr->flags	= ndr->flags;	*_subndr = subndr;	return NDR_ERR_SUCCESS;}/*  push a subcontext header */_PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr,				 struct ndr_push *subndr,				 size_t header_size,				 ssize_t size_is){	if (size_is >= 0) {		ssize_t padding_len = size_is - subndr->offset;		if (padding_len > 0) {			NDR_CHECK(ndr_push_zero(subndr, padding_len));		} else if (padding_len < 0) {			return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)",					      (int)subndr->offset, (int)size_is);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -