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

📄 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 2 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, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//*  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"#define NDR_BASE_MARSHALL_SIZE 1024/* this guid indicates NDR encoding in a protocol tower */const struct dcerpc_syntax_id ndr_transfer_syntax = {  { 0x8a885d04, 0x1ceb, 0x11c9, {0x9f, 0xe8}, {0x08,0x00,0x2b,0x10,0x48,0x60} },  2};const struct dcerpc_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*/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*/struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx){	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;	return ndr;}/*  advance by 'size' bytes*/NTSTATUS 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 NT_STATUS_OK;}/*  set the parse offset to 'ofs'*/static NTSTATUS 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 NT_STATUS_OK;}/* save the offset/size of the current ndr state */void ndr_pull_save(struct ndr_pull *ndr, struct ndr_pull_save *save){	save->offset = ndr->offset;	save->data_size = ndr->data_size;}/* restore the size/offset of a ndr structure */void ndr_pull_restore(struct ndr_pull *ndr, struct ndr_pull_save *save){	ndr->offset = save->offset;	ndr->data_size = save->data_size;}/* create a ndr_push structure, ready for some marshalling */struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx){	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;	}	return ndr;}/* create a ndr_push structure, ready for some marshalling */struct ndr_push *ndr_push_init(void){	return ndr_push_init_ctx(NULL);}/* free a ndr_push structure */void ndr_push_free(struct ndr_push *ndr){	talloc_free(ndr);}/* return a DATA_BLOB structure for the current ndr_push marshalled data */DATA_BLOB ndr_push_blob(struct ndr_push *ndr){	DATA_BLOB blob;	blob.data = ndr->data;	blob.length = ndr->offset;	blob.free = NULL;	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*/NTSTATUS 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 NT_STATUS_OK;	}	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 NT_STATUS_OK;}void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3){	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++) {		DEBUG(0,("    "));	}	DEBUG(0,("%s\n", s));	free(s);}static void ndr_print_string_helper(struct ndr_print *ndr, const char *format, ...) _PRINTF_ATTRIBUTE(2,3){	va_list ap;	int i;	for (i=0;i<ndr->depth;i++) {		ndr->private_data = talloc_asprintf_append(			(char *)ndr->private_data, "    ");	}	va_start(ap, format);	ndr->private_data = talloc_vasprintf_append(		(char *)ndr->private_data, format, ap);	va_end(ap);	ndr->private_data = talloc_asprintf_append(		(char *)ndr->private_data, "\n");}/*  a useful helper function for printing idl structures via DEBUG()*/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()*/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()*/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 function calls to a string*/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;	if (!(ndr->private_data = talloc_strdup(mem_ctx, ""))) {		TALLOC_FREE(ndr);		return NULL;	}	ndr->print = ndr_print_string_helper;	ndr->depth = 1;	ndr->flags = 0;	fn(ndr, name, flags, ptr);	ret = (char *)ndr->private_data;	talloc_free(ndr);	return ret;}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;}static NTSTATUS ndr_map_error(enum ndr_err_code ndr_err){	switch (ndr_err) {	case NDR_ERR_BUFSIZE:		return NT_STATUS_BUFFER_TOO_SMALL;	case NDR_ERR_TOKEN:		return NT_STATUS_INTERNAL_ERROR;	case NDR_ERR_ALLOC:		return NT_STATUS_NO_MEMORY;	case NDR_ERR_ARRAY_SIZE:		return NT_STATUS_ARRAY_BOUNDS_EXCEEDED;	default:		break;	}	/* we should map all error codes to different status codes */	return NT_STATUS_INVALID_PARAMETER;}/*  return and possibly log an NDR error*/NTSTATUS ndr_pull_error(struct ndr_pull *ndr,				 enum ndr_err_code ndr_err,				 const char *format, ...) _PRINTF_ATTRIBUTE(3,4){	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_map_error(ndr_err);}/*  return and possibly log an NDR error*/NTSTATUS ndr_push_error(struct ndr_push *ndr,				 enum ndr_err_code ndr_err,				 const char *format, ...)  _PRINTF_ATTRIBUTE(3,4){	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_map_error(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*/NTSTATUS 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);	NT_STATUS_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 = subndr;	return NT_STATUS_OK;}NTSTATUS 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 NT_STATUS_OK;}NTSTATUS 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);	NT_STATUS_HAVE_NO_MEMORY(subndr);	subndr->flags	= ndr->flags;	*_subndr = subndr;	return NT_STATUS_OK;}/*  push a subcontext header */NTSTATUS 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) {

⌨️ 快捷键说明

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