2012-03-18 19:46:57 +04:00
/*
2003-10-30 11:32:26 +03:00
Unix SMB / CIFS implementation .
2003-11-03 09:22:45 +03:00
2003-10-30 11:32:26 +03:00
libndr interface
2003-11-03 09:22:45 +03:00
2003-10-30 11:32:26 +03:00
Copyright ( C ) Andrew Tridgell 2003
2012-03-18 19:46:57 +04:00
Copyright ( C ) Jelmer Vernooij 2005 - 2008
2003-10-30 11:32:26 +03:00
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-10-30 11:32:26 +03:00
( at your option ) any later version .
2012-03-18 19:46:57 +04:00
2003-10-30 11:32:26 +03:00
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 .
2012-03-18 19:46:57 +04:00
2003-10-30 11:32:26 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-10-30 11:32:26 +03:00
*/
/*
2003-11-03 09:22:45 +03:00
this provides the core routines for NDR parsing functions
see http : //www.opengroup.org/onlinepubs/9629399/chap14.htm for details
of NDR encoding rules
2003-10-30 11:32:26 +03:00
*/
# include "includes.h"
2006-03-18 18:42:57 +03:00
# include "librpc/ndr/libndr.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2003-10-30 11:32:26 +03:00
2003-11-05 02:12:44 +03:00
# define NDR_BASE_MARSHALL_SIZE 1024
2005-12-27 19:47:09 +03:00
/* this guid indicates NDR encoding in a protocol tower */
2012-03-18 19:46:57 +04:00
const struct ndr_syntax_id ndr_transfer_syntax_ndr = {
2005-12-27 19:47:09 +03:00
{ 0x8a885d04 , 0x1ceb , 0x11c9 , { 0x9f , 0xe8 } , { 0x08 , 0x00 , 0x2b , 0x10 , 0x48 , 0x60 } } ,
2
} ;
2012-03-18 19:46:57 +04:00
const struct ndr_syntax_id ndr_transfer_syntax_ndr64 = {
2005-12-27 19:47:09 +03:00
{ 0x71710533 , 0xbeba , 0x4937 , { 0x83 , 0x19 } , { 0xb5 , 0xdb , 0xef , 0x9c , 0xcc , 0x36 } } ,
1
} ;
2012-03-18 19:46:57 +04:00
const struct ndr_syntax_id ndr_syntax_id_null = {
2011-02-08 01:21:41 +03:00
{ 0 , 0 , 0 , { 0 , 0 } , { 0 , 0 , 0 , 0 , 0 , 0 } } ,
0
} ;
2003-11-23 09:28:12 +03:00
/*
work out the number of bytes needed to align on a n byte boundary
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ size_t ndr_align_size ( uint32_t offset , size_t n )
2003-11-23 09:28:12 +03:00
{
if ( ( offset & ( n - 1 ) ) = = 0 ) return 0 ;
return n - ( offset & ( n - 1 ) ) ;
}
2003-10-30 11:32:26 +03:00
/*
initialise a ndr parse structure from a data blob
*/
2010-05-09 19:20:01 +04:00
_PUBLIC_ struct ndr_pull * ndr_pull_init_blob ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx )
2003-10-30 11:32:26 +03:00
{
2003-11-03 09:22:45 +03:00
struct ndr_pull * ndr ;
2003-10-30 11:32:26 +03:00
2005-01-27 10:08:20 +03:00
ndr = talloc_zero ( mem_ctx , struct ndr_pull ) ;
2003-10-30 11:32:26 +03:00
if ( ! ndr ) return NULL ;
2005-08-18 05:24:08 +04:00
ndr - > current_mem_ctx = mem_ctx ;
2003-10-30 11:32:26 +03:00
ndr - > data = blob - > data ;
ndr - > data_size = blob - > length ;
return ndr ;
}
2013-09-21 04:28:33 +04:00
_PUBLIC_ enum ndr_err_code ndr_pull_append ( struct ndr_pull * ndr , DATA_BLOB * blob )
{
enum ndr_err_code ndr_err ;
DATA_BLOB b ;
uint32_t append = 0 ;
bool ok ;
if ( blob - > length = = 0 ) {
return NDR_ERR_SUCCESS ;
}
ndr_err = ndr_token_retrieve ( & ndr - > array_size_list , ndr , & append ) ;
if ( ndr_err = = NDR_ERR_TOKEN ) {
append = 0 ;
ndr_err = NDR_ERR_SUCCESS ;
}
NDR_CHECK ( ndr_err ) ;
if ( ndr - > data_size = = 0 ) {
ndr - > data = NULL ;
append = UINT32_MAX ;
}
if ( append = = UINT32_MAX ) {
/*
* append = = UINT32_MAX means that
* ndr - > data is either NULL or a valid
* talloc child of ndr , which means
* we can use data_blob_append ( ) without
* data_blob_talloc ( ) of the existing callers data
*/
b = data_blob_const ( ndr - > data , ndr - > data_size ) ;
} else {
b = data_blob_talloc ( ndr , ndr - > data , ndr - > data_size ) ;
if ( b . data = = NULL ) {
return ndr_pull_error ( ndr , NDR_ERR_ALLOC , " %s " , __location__ ) ;
}
}
ok = data_blob_append ( ndr , & b , blob - > data , blob - > length ) ;
if ( ! ok ) {
return ndr_pull_error ( ndr , NDR_ERR_ALLOC , " %s " , __location__ ) ;
}
ndr - > data = b . data ;
ndr - > data_size = b . length ;
return ndr_token_store ( ndr , & ndr - > array_size_list , ndr , UINT32_MAX ) ;
}
_PUBLIC_ enum ndr_err_code ndr_pull_pop ( struct ndr_pull * ndr )
{
uint32_t skip = 0 ;
uint32_t append = 0 ;
if ( ndr - > relative_base_offset ! = 0 ) {
return ndr_pull_error ( ndr , NDR_ERR_RELATIVE ,
" %s " , __location__ ) ;
}
if ( ndr - > relative_highest_offset ! = 0 ) {
return ndr_pull_error ( ndr , NDR_ERR_RELATIVE ,
" %s " , __location__ ) ;
}
2017-02-24 01:58:33 +03:00
if ( ndr - > relative_list . count ! = 0 ) {
2013-09-21 04:28:33 +04:00
return ndr_pull_error ( ndr , NDR_ERR_RELATIVE ,
" %s " , __location__ ) ;
}
2017-02-24 01:58:33 +03:00
if ( ndr - > relative_base_list . count ! = 0 ) {
2013-09-21 04:28:33 +04:00
return ndr_pull_error ( ndr , NDR_ERR_RELATIVE ,
" %s " , __location__ ) ;
}
/*
* we need to keep up to 7 bytes
* in order to get the aligment right .
*/
skip = ndr - > offset & 0xFFFFFFF8 ;
if ( skip = = 0 ) {
return NDR_ERR_SUCCESS ;
}
ndr - > offset - = skip ;
ndr - > data_size - = skip ;
append = ndr_token_peek ( & ndr - > array_size_list , ndr ) ;
if ( append ! = UINT32_MAX ) {
/*
* here we assume , that ndr - > data is not a
* talloc child of ndr .
*/
ndr - > data + = skip ;
return NDR_ERR_SUCCESS ;
}
memmove ( ndr - > data , ndr - > data + skip , ndr - > data_size ) ;
ndr - > data = talloc_realloc ( ndr , ndr - > data , uint8_t , ndr - > data_size ) ;
if ( ndr - > data_size ! = 0 & & ndr - > data = = NULL ) {
return ndr_pull_error ( ndr , NDR_ERR_ALLOC , " %s " , __location__ ) ;
}
return NDR_ERR_SUCCESS ;
}
2003-10-30 11:32:26 +03:00
/*
advance by ' size ' bytes
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_advance ( struct ndr_pull * ndr , uint32_t size )
2003-10-30 11:32:26 +03:00
{
ndr - > offset + = size ;
if ( ndr - > offset > ndr - > data_size ) {
2017-02-24 01:59:24 +03:00
return ndr_pull_error ( ndr , NDR_ERR_BUFSIZE ,
2003-11-22 11:11:32 +03:00
" ndr_pull_advance by %u failed " ,
size ) ;
2003-10-30 11:32:26 +03:00
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-10-30 11:32:26 +03:00
}
/*
set the parse offset to ' ofs '
*/
2007-11-09 21:23:40 +03:00
static enum ndr_err_code ndr_pull_set_offset ( struct ndr_pull * ndr , uint32_t ofs )
2003-10-30 11:32:26 +03:00
{
ndr - > offset = ofs ;
if ( ndr - > offset > ndr - > data_size ) {
2017-02-24 01:59:24 +03:00
return ndr_pull_error ( ndr , NDR_ERR_BUFSIZE ,
2003-11-22 11:11:32 +03:00
" ndr_pull_set_offset %u failed " ,
ofs ) ;
2003-10-30 11:32:26 +03:00
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-10-30 11:32:26 +03:00
}
2003-11-03 09:22:45 +03:00
/* create a ndr_push structure, ready for some marshalling */
2010-05-09 19:20:01 +04:00
_PUBLIC_ struct ndr_push * ndr_push_init_ctx ( TALLOC_CTX * mem_ctx )
2003-11-03 09:22:45 +03:00
{
struct ndr_push * ndr ;
2005-01-27 10:08:20 +03:00
ndr = talloc_zero ( mem_ctx , struct ndr_push ) ;
2003-11-03 09:22:45 +03:00
if ( ! ndr ) {
return NULL ;
}
ndr - > flags = 0 ;
ndr - > alloc_size = NDR_BASE_MARSHALL_SIZE ;
2005-01-27 10:08:20 +03:00
ndr - > data = talloc_array ( ndr , uint8_t , ndr - > alloc_size ) ;
2003-11-03 09:22:45 +03:00
if ( ! ndr - > data ) {
2013-09-04 15:15:34 +04:00
talloc_free ( ndr ) ;
2003-11-03 09:22:45 +03:00
return NULL ;
}
2004-08-12 09:15:41 +04:00
2003-11-03 09:22:45 +03:00
return ndr ;
}
/* return a DATA_BLOB structure for the current ndr_push marshalled data */
2006-03-05 20:15:19 +03:00
_PUBLIC_ DATA_BLOB ndr_push_blob ( struct ndr_push * ndr )
2003-11-03 09:22:45 +03:00
{
DATA_BLOB blob ;
2007-11-08 11:07:51 +03:00
blob = data_blob_const ( ndr - > data , ndr - > offset ) ;
2005-07-17 13:13:05 +04:00
if ( ndr - > alloc_size > ndr - > offset ) {
ndr - > data [ ndr - > offset ] = 0 ;
}
2003-11-03 09:22:45 +03:00
return blob ;
}
/*
2007-03-13 07:18:07 +03:00
expand the available space in the buffer to ndr - > offset + extra_size
2003-11-03 09:22:45 +03:00
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_expand ( struct ndr_push * ndr , uint32_t extra_size )
2003-11-03 09:22:45 +03:00
{
2007-03-13 07:18:07 +03:00
uint32_t size = extra_size + ndr - > offset ;
if ( size < ndr - > offset ) {
/* extra_size overflowed the offset */
2007-03-13 07:42:49 +03:00
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE , " Overflow in push_expand to %u " ,
size ) ;
2007-03-13 07:18:07 +03:00
}
2016-06-17 04:29:51 +03:00
if ( ndr - > fixed_buf_size ) {
if ( ndr - > alloc_size > = size ) {
return NDR_ERR_SUCCESS ;
}
return ndr_push_error ( ndr ,
NDR_ERR_BUFSIZE ,
" Overflow of fixed buffer in "
" push_expand to %u " ,
size ) ;
}
2017-02-24 01:59:24 +03:00
2005-07-17 13:08:19 +04:00
if ( ndr - > alloc_size > size ) {
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-11-03 09:22:45 +03:00
}
2003-11-12 08:34:21 +03:00
ndr - > alloc_size + = NDR_BASE_MARSHALL_SIZE ;
2005-07-17 13:08:19 +04:00
if ( size + 1 > ndr - > alloc_size ) {
ndr - > alloc_size = size + 1 ;
2003-11-12 08:34:21 +03:00
}
2005-01-07 07:39:16 +03:00
ndr - > data = talloc_realloc ( ndr , ndr - > data , uint8_t , ndr - > alloc_size ) ;
2003-11-03 09:22:45 +03:00
if ( ! ndr - > data ) {
2003-11-22 11:11:32 +03:00
return ndr_push_error ( ndr , NDR_ERR_ALLOC , " Failed to push_expand to %u " ,
ndr - > alloc_size ) ;
2003-11-03 09:22:45 +03:00
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-11-03 09:22:45 +03:00
}
2013-01-18 21:35:15 +04:00
_PUBLIC_ void ndr_print_debugc_helper ( struct ndr_print * ndr , const char * format , . . . )
{
va_list ap ;
char * s = NULL ;
uint32_t i ;
int ret ;
int dbgc_class ;
va_start ( ap , format ) ;
ret = vasprintf ( & s , format , ap ) ;
va_end ( ap ) ;
if ( ret = = - 1 ) {
return ;
}
dbgc_class = * ( int * ) ndr - > private_data ;
if ( ndr - > no_newline ) {
DEBUGADDC ( dbgc_class , 1 , ( " %s " , s ) ) ;
free ( s ) ;
return ;
}
for ( i = 0 ; i < ndr - > depth ; i + + ) {
DEBUGADDC ( dbgc_class , 1 , ( " " ) ) ;
}
DEBUGADDC ( dbgc_class , 1 , ( " %s \n " , s ) ) ;
free ( s ) ;
}
2017-02-24 01:59:24 +03:00
_PUBLIC_ void ndr_print_debug_helper ( struct ndr_print * ndr , const char * format , . . . )
2003-11-11 07:04:36 +03:00
{
va_list ap ;
char * s = NULL ;
2010-10-27 10:54:46 +04:00
uint32_t i ;
int ret ;
2003-11-11 07:04:36 +03:00
va_start ( ap , format ) ;
2008-10-13 17:17:41 +04:00
ret = vasprintf ( & s , format , ap ) ;
2003-11-11 07:04:36 +03:00
va_end ( ap ) ;
2008-10-13 17:17:41 +04:00
if ( ret = = - 1 ) {
return ;
}
2010-08-09 10:37:52 +04:00
if ( ndr - > no_newline ) {
DEBUGADD ( 1 , ( " %s " , s ) ) ;
free ( s ) ;
return ;
}
2003-11-11 07:04:36 +03:00
for ( i = 0 ; i < ndr - > depth ; i + + ) {
2009-02-14 15:18:28 +03:00
DEBUGADD ( 1 , ( " " ) ) ;
2003-11-11 07:04:36 +03:00
}
2009-02-14 15:18:28 +03:00
DEBUGADD ( 1 , ( " %s \n " , s ) ) ;
2003-11-11 07:04:36 +03:00
free ( s ) ;
}
2017-02-24 01:59:24 +03:00
_PUBLIC_ void ndr_print_printf_helper ( struct ndr_print * ndr , const char * format , . . . )
2010-10-27 08:19:05 +04:00
{
va_list ap ;
2010-10-27 10:54:46 +04:00
uint32_t i ;
2010-10-27 08:19:05 +04:00
if ( ! ndr - > no_newline ) {
for ( i = 0 ; i < ndr - > depth ; i + + ) {
printf ( " " ) ;
}
}
va_start ( ap , format ) ;
vprintf ( format , ap ) ;
va_end ( ap ) ;
if ( ! ndr - > no_newline ) {
printf ( " \n " ) ;
}
}
2008-04-02 06:53:27 +04:00
_PUBLIC_ void ndr_print_string_helper ( struct ndr_print * ndr , const char * format , . . . )
2005-12-31 07:29:34 +03:00
{
va_list ap ;
2010-10-27 10:54:46 +04:00
uint32_t i ;
2005-12-31 07:29:34 +03:00
2010-08-09 10:37:52 +04:00
if ( ! ndr - > no_newline ) {
for ( i = 0 ; i < ndr - > depth ; i + + ) {
ndr - > private_data = talloc_asprintf_append_buffer (
( char * ) ndr - > private_data , " " ) ;
}
2005-12-31 07:29:34 +03:00
}
va_start ( ap , format ) ;
2017-02-24 01:59:24 +03:00
ndr - > private_data = talloc_vasprintf_append_buffer ( ( char * ) ndr - > private_data ,
2007-09-07 19:08:14 +04:00
format , ap ) ;
2005-12-31 07:29:34 +03:00
va_end ( ap ) ;
2010-08-09 10:37:52 +04:00
if ( ! ndr - > no_newline ) {
ndr - > private_data = talloc_asprintf_append_buffer ( ( char * ) ndr - > private_data ,
" \n " ) ;
}
2005-12-31 07:29:34 +03:00
}
2013-01-18 21:35:15 +04:00
/*
a useful helper function for printing idl structures via DEBUGC ( )
*/
_PUBLIC_ void ndr_print_debugc ( int dbgc_class , ndr_print_fn_t fn , const char * name , void * ptr )
{
struct ndr_print * ndr ;
DEBUGC ( dbgc_class , 1 , ( " " ) ) ;
ndr = talloc_zero ( NULL , struct ndr_print ) ;
if ( ! ndr ) return ;
ndr - > private_data = & dbgc_class ;
ndr - > print = ndr_print_debugc_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
2017-06-12 18:58:20 +03:00
# ifdef DEBUG_PASSWORD
if ( CHECK_DEBUGLVL ( 100 ) ) {
ndr - > print_secrets = true ;
}
# endif
2013-01-18 21:35:15 +04:00
fn ( ndr , name , ptr ) ;
talloc_free ( ndr ) ;
}
2003-11-11 07:04:36 +03:00
/*
a useful helper function for printing idl structures via DEBUG ( )
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_print_debug ( ndr_print_fn_t fn , const char * name , void * ptr )
2003-11-11 07:04:36 +03:00
{
2004-08-21 11:43:29 +04:00
struct ndr_print * ndr ;
2003-11-11 07:04:36 +03:00
2009-02-14 15:18:28 +03:00
DEBUG ( 1 , ( " " ) ) ;
2009-01-17 20:13:31 +03:00
2005-04-04 09:52:53 +04:00
ndr = talloc_zero ( NULL , struct ndr_print ) ;
2004-08-21 11:43:29 +04:00
if ( ! ndr ) return ;
ndr - > print = ndr_print_debug_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
2017-06-12 18:58:20 +03:00
# ifdef DEBUG_PASSWORD
if ( CHECK_DEBUGLVL ( 100 ) ) {
ndr - > print_secrets = true ;
}
# endif
2004-08-21 11:43:29 +04:00
fn ( ndr , name , ptr ) ;
talloc_free ( ndr ) ;
2003-11-11 07:04:36 +03:00
}
2003-11-11 07:38:51 +03:00
2005-05-11 03:33:56 +04:00
/*
a useful helper function for printing idl unions via DEBUG ( )
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_print_union_debug ( ndr_print_fn_t fn , const char * name , uint32_t level , void * ptr )
2005-05-11 03:33:56 +04:00
{
struct ndr_print * ndr ;
2009-02-14 15:18:28 +03:00
DEBUG ( 1 , ( " " ) ) ;
2009-01-17 20:13:31 +03:00
2005-05-11 03:33:56 +04:00
ndr = talloc_zero ( NULL , struct ndr_print ) ;
if ( ! ndr ) return ;
ndr - > print = ndr_print_debug_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
2017-06-12 18:58:20 +03:00
# ifdef DEBUG_PASSWORD
if ( CHECK_DEBUGLVL ( 100 ) ) {
ndr - > print_secrets = true ;
}
# endif
2005-05-11 03:33:56 +04:00
ndr_print_set_switch_value ( ndr , ptr , level ) ;
fn ( ndr , name , ptr ) ;
talloc_free ( ndr ) ;
}
2003-11-17 14:55:56 +03:00
/*
a useful helper function for printing idl function calls via DEBUG ( )
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_print_function_debug ( ndr_print_function_t fn , const char * name , int flags , void * ptr )
2003-11-17 14:55:56 +03:00
{
2004-08-21 11:43:29 +04:00
struct ndr_print * ndr ;
2003-11-17 14:55:56 +03:00
2009-02-14 15:18:28 +03:00
DEBUG ( 1 , ( " " ) ) ;
2009-01-17 20:13:31 +03:00
2005-04-04 09:52:53 +04:00
ndr = talloc_zero ( NULL , struct ndr_print ) ;
2004-08-21 11:43:29 +04:00
if ( ! ndr ) return ;
ndr - > print = ndr_print_debug_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
2017-06-12 18:58:20 +03:00
# ifdef DEBUG_PASSWORD
if ( CHECK_DEBUGLVL ( 100 ) ) {
ndr - > print_secrets = true ;
}
# endif
2009-09-03 06:50:19 +04:00
2004-08-21 11:43:29 +04:00
fn ( ndr , name , flags , ptr ) ;
talloc_free ( ndr ) ;
2003-11-17 14:55:56 +03:00
}
2006-05-15 18:38:04 +04:00
/*
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 ;
2009-09-03 06:50:19 +04:00
2006-05-15 18:38:04 +04:00
fn ( ndr , name , ptr ) ;
2007-09-07 19:08:14 +04:00
ret = talloc_steal ( mem_ctx , ( char * ) ndr - > private_data ) ;
2006-05-15 18:38:04 +04:00
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 ) ;
2007-09-07 19:08:14 +04:00
ret = talloc_steal ( mem_ctx , ( char * ) ndr - > private_data ) ;
2006-05-15 18:38:04 +04:00
failed :
talloc_free ( ndr ) ;
return ret ;
}
2005-12-31 07:29:34 +03:00
/*
a useful helper function for printing idl function calls to a string
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ char * ndr_print_function_string ( TALLOC_CTX * mem_ctx ,
2017-02-24 01:59:24 +03:00
ndr_print_function_t fn , const char * name ,
2005-12-31 07:29:34 +03:00
int flags , void * ptr )
{
struct ndr_print * ndr ;
2006-01-11 23:38:10 +03:00
char * ret = NULL ;
2005-12-31 07:29:34 +03:00
ndr = talloc_zero ( mem_ctx , struct ndr_print ) ;
if ( ! ndr ) return NULL ;
2006-05-04 15:01:10 +04:00
ndr - > private_data = talloc_strdup ( ndr , " " ) ;
if ( ! ndr - > private_data ) {
2006-01-11 23:38:10 +03:00
goto failed ;
}
2005-12-31 07:29:34 +03:00
ndr - > print = ndr_print_string_helper ;
ndr - > depth = 1 ;
ndr - > flags = 0 ;
fn ( ndr , name , flags , ptr ) ;
2007-09-07 19:08:14 +04:00
ret = talloc_steal ( mem_ctx , ( char * ) ndr - > private_data ) ;
2006-01-11 23:38:10 +03:00
failed :
2005-12-31 07:29:34 +03:00
talloc_free ( ndr ) ;
2006-01-10 00:59:42 +03:00
return ret ;
2005-12-31 07:29:34 +03:00
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_set_flags ( uint32_t * pflags , uint32_t new_flags )
2004-10-14 13:07:41 +04:00
{
/* the big/little endian flags are inter-dependent */
if ( new_flags & LIBNDR_FLAG_LITTLE_ENDIAN ) {
( * pflags ) & = ~ LIBNDR_FLAG_BIGENDIAN ;
2009-09-17 20:08:47 +04:00
( * pflags ) & = ~ LIBNDR_FLAG_NDR64 ;
2004-10-14 13:07:41 +04:00
}
if ( new_flags & LIBNDR_FLAG_BIGENDIAN ) {
( * pflags ) & = ~ LIBNDR_FLAG_LITTLE_ENDIAN ;
2009-09-17 20:08:47 +04:00
( * pflags ) & = ~ LIBNDR_FLAG_NDR64 ;
2004-10-14 13:07:41 +04:00
}
2005-09-10 12:46:28 +04:00
if ( new_flags & LIBNDR_ALIGN_FLAGS ) {
2012-05-25 20:16:50 +04:00
/* Ensure we only have the passed-in
align flag set in the new_flags ,
remove any old align flag . */
( * pflags ) & = ~ LIBNDR_ALIGN_FLAGS ;
2005-09-10 12:46:28 +04:00
}
2010-02-09 20:27:37 +03:00
if ( new_flags & LIBNDR_FLAG_NO_RELATIVE_REVERSE ) {
( * pflags ) & = ~ LIBNDR_FLAG_RELATIVE_REVERSE ;
}
2004-10-14 13:07:41 +04:00
( * pflags ) | = new_flags ;
}
2003-11-22 11:11:32 +03:00
2003-11-13 12:26:53 +03:00
/*
return and possibly log an NDR error
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_error ( struct ndr_pull * ndr ,
2006-03-22 17:33:06 +03:00
enum ndr_err_code ndr_err ,
2008-04-02 06:53:27 +04:00
const char * format , . . . )
2003-11-13 12:26:53 +03:00
{
char * s = NULL ;
va_list ap ;
2008-10-13 17:17:41 +04:00
int ret ;
2003-11-13 12:26:53 +03:00
2011-03-08 12:14:51 +03:00
if ( ndr - > flags & LIBNDR_FLAG_INCOMPLETE_BUFFER ) {
switch ( ndr_err ) {
case NDR_ERR_BUFSIZE :
return NDR_ERR_INCOMPLETE_BUFFER ;
default :
break ;
}
}
2003-11-13 12:26:53 +03:00
va_start ( ap , format ) ;
2008-10-13 17:17:41 +04:00
ret = vasprintf ( & s , format , ap ) ;
2003-11-13 12:26:53 +03:00
va_end ( ap ) ;
2008-10-13 17:17:41 +04:00
if ( ret = = - 1 ) {
return NDR_ERR_ALLOC ;
}
DEBUG ( 1 , ( " ndr_pull_error(%u): %s \n " , ndr_err , s ) ) ;
2003-11-13 12:26:53 +03:00
free ( s ) ;
2003-11-22 11:11:32 +03:00
2007-11-09 21:23:40 +03:00
return ndr_err ;
2003-11-13 12:26:53 +03:00
}
2003-11-14 10:20:46 +03:00
/*
return and possibly log an NDR error
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_error ( struct ndr_push * ndr ,
2006-03-22 17:33:06 +03:00
enum ndr_err_code ndr_err ,
2017-02-24 01:59:24 +03:00
const char * format , . . . )
2003-11-14 10:20:46 +03:00
{
char * s = NULL ;
va_list ap ;
2008-10-13 17:17:41 +04:00
int ret ;
2003-11-14 10:20:46 +03:00
va_start ( ap , format ) ;
2008-10-13 17:17:41 +04:00
ret = vasprintf ( & s , format , ap ) ;
2003-11-14 10:20:46 +03:00
va_end ( ap ) ;
2008-10-13 17:17:41 +04:00
if ( ret = = - 1 ) {
return NDR_ERR_ALLOC ;
}
DEBUG ( 1 , ( " ndr_push_error(%u): %s \n " , ndr_err , s ) ) ;
2003-11-14 10:20:46 +03:00
free ( s ) ;
2003-11-22 11:11:32 +03:00
2007-11-09 21:23:40 +03:00
return ndr_err ;
2003-11-14 10:20:46 +03:00
}
2003-11-16 09:00:15 +03:00
2003-11-21 16:14:17 +03:00
/*
handle subcontext buffers , which in midl land are user - marshalled , but
we use magic in pidl to make them easier to cope with
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_subcontext_start ( struct ndr_pull * ndr ,
2005-08-18 04:45:19 +04:00
struct ndr_pull * * _subndr ,
size_t header_size ,
ssize_t size_is )
2003-11-21 16:14:17 +03:00
{
2005-08-18 04:45:19 +04:00
struct ndr_pull * subndr ;
uint32_t r_content_size ;
2008-08-18 19:10:59 +04:00
bool force_le = false ;
bool force_be = false ;
2005-01-29 06:17:14 +03:00
2005-03-15 17:33:38 +03:00
switch ( header_size ) {
2003-11-21 16:14:17 +03:00
case 0 : {
2005-03-15 17:33:38 +03:00
uint32_t content_size = ndr - > data_size - ndr - > offset ;
if ( size_is > = 0 ) {
content_size = size_is ;
}
2005-08-18 04:45:19 +04:00
r_content_size = content_size ;
2003-11-21 16:14:17 +03:00
break ;
}
case 2 : {
2005-03-15 17:33:38 +03:00
uint16_t content_size ;
NDR_CHECK ( ndr_pull_uint16 ( ndr , NDR_SCALARS , & content_size ) ) ;
if ( size_is > = 0 & & size_is ! = content_size ) {
2015-06-25 21:50:30 +03:00
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PULL) size_is(%d) (0x%04x) mismatch content_size %d (0x%04x) " ,
( int ) size_is , ( int ) size_is ,
( int ) content_size ,
( int ) content_size ) ;
2005-03-15 17:33:38 +03:00
}
2005-08-18 04:45:19 +04:00
r_content_size = content_size ;
2003-11-21 16:14:17 +03:00
break ;
}
case 4 : {
2005-03-15 17:33:38 +03:00
uint32_t content_size ;
2009-09-18 02:14:31 +04:00
NDR_CHECK ( ndr_pull_uint3264 ( ndr , NDR_SCALARS , & content_size ) ) ;
2005-03-15 17:33:38 +03:00
if ( size_is > = 0 & & size_is ! = content_size ) {
2015-06-25 21:50:30 +03:00
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PULL) size_is(%d) (0x%08x) mismatch content_size %d (0x%08x) " ,
( int ) size_is , ( int ) size_is ,
( int ) content_size ,
( int ) content_size ) ;
2005-03-15 17:33:38 +03:00
}
2005-08-18 04:45:19 +04:00
r_content_size = content_size ;
2003-11-21 16:14:17 +03:00
break ;
}
2008-08-18 19:10:59 +04:00
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 ;
}
2013-09-21 23:58:05 +04:00
case 0xFFFFFFFF :
/*
* a shallow copy like subcontext
* useful for DCERPC pipe chunks .
*/
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 ;
subndr - > offset = ndr - > offset ;
subndr - > data_size = ndr - > data_size ;
* _subndr = subndr ;
return NDR_ERR_SUCCESS ;
2003-11-21 16:14:17 +03:00
default :
2017-02-24 01:59:24 +03:00
return ndr_pull_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PULL) header_size %d " ,
2005-07-17 13:08:19 +04:00
( int ) header_size ) ;
2003-11-21 16:14:17 +03:00
}
2005-08-18 04:45:19 +04:00
NDR_PULL_NEED_BYTES ( ndr , r_content_size ) ;
subndr = talloc_zero ( ndr , struct ndr_pull ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( subndr ) ;
2009-09-18 02:14:31 +04:00
subndr - > flags = ndr - > flags & ~ LIBNDR_FLAG_NDR64 ;
2005-08-18 05:24:08 +04:00
subndr - > current_mem_ctx = ndr - > current_mem_ctx ;
2005-08-18 04:45:19 +04:00
subndr - > data = ndr - > data + ndr - > offset ;
subndr - > offset = 0 ;
subndr - > data_size = r_content_size ;
2008-08-18 19:10:59 +04:00
if ( force_le ) {
ndr_set_flags ( & ndr - > flags , LIBNDR_FLAG_LITTLE_ENDIAN ) ;
} else if ( force_be ) {
ndr_set_flags ( & ndr - > flags , LIBNDR_FLAG_BIGENDIAN ) ;
}
2005-08-18 04:45:19 +04:00
* _subndr = subndr ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-08-18 04:45:19 +04:00
}
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_subcontext_end ( struct ndr_pull * ndr ,
2005-08-18 04:45:19 +04:00
struct ndr_pull * subndr ,
size_t header_size ,
ssize_t size_is )
{
uint32_t advance ;
2014-01-03 12:25:23 +04:00
uint32_t highest_ofs ;
2013-09-21 23:58:05 +04:00
if ( header_size = = 0xFFFFFFFF ) {
advance = subndr - > offset - ndr - > offset ;
} else if ( size_is > = 0 ) {
2005-08-18 04:45:19 +04:00
advance = size_is ;
} else if ( header_size > 0 ) {
advance = subndr - > data_size ;
} else {
advance = subndr - > offset ;
}
2014-01-03 12:25:23 +04:00
if ( subndr - > offset > ndr - > relative_highest_offset ) {
highest_ofs = subndr - > offset ;
} else {
highest_ofs = subndr - > relative_highest_offset ;
}
if ( ! ( subndr - > flags & LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES ) ) {
/*
* avoid an error unless SUBCONTEXT_NO_UNREAD_BYTES is specified
*/
highest_ofs = advance ;
}
if ( highest_ofs < advance ) {
return ndr_pull_error ( subndr , NDR_ERR_UNREAD_BYTES ,
" not all bytes consumed ofs[%u] advance[%u] " ,
highest_ofs , advance ) ;
}
2005-08-18 04:45:19 +04:00
NDR_CHECK ( ndr_pull_advance ( ndr , advance ) ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-08-18 04:45:19 +04:00
}
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_subcontext_start ( struct ndr_push * ndr ,
2005-08-18 04:45:19 +04:00
struct ndr_push * * _subndr ,
size_t header_size ,
ssize_t size_is )
{
struct ndr_push * subndr ;
2010-05-09 19:20:01 +04:00
subndr = ndr_push_init_ctx ( ndr ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( subndr ) ;
2009-09-18 02:14:31 +04:00
subndr - > flags = ndr - > flags & ~ LIBNDR_FLAG_NDR64 ;
2005-08-18 04:45:19 +04:00
2009-12-17 00:54:02 +03:00
if ( size_is > 0 ) {
NDR_CHECK ( ndr_push_zero ( subndr , size_is ) ) ;
subndr - > offset = 0 ;
2009-12-14 17:33:32 +03:00
subndr - > relative_end_offset = size_is ;
2009-12-17 00:54:02 +03:00
}
2005-08-18 04:45:19 +04:00
* _subndr = subndr ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-11-21 16:14:17 +03:00
}
2003-11-22 11:11:32 +03:00
/*
2017-02-24 01:59:24 +03:00
push a subcontext header
2003-11-22 11:11:32 +03:00
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_subcontext_end ( struct ndr_push * ndr ,
2005-08-18 04:45:19 +04:00
struct ndr_push * subndr ,
size_t header_size ,
ssize_t size_is )
2003-11-22 11:11:32 +03:00
{
2008-08-18 19:10:59 +04:00
ssize_t padding_len ;
2005-03-15 17:33:38 +03:00
if ( size_is > = 0 ) {
2008-08-18 19:10:59 +04:00
padding_len = size_is - subndr - > offset ;
2009-12-17 00:54:02 +03:00
if ( padding_len < 0 ) {
2005-03-15 17:33:38 +03:00
return ndr_push_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext (PUSH) content_size %d is larger than size_is(%d) " ,
2005-08-18 04:45:19 +04:00
( int ) subndr - > offset , ( int ) size_is ) ;
2005-03-15 17:33:38 +03:00
}
2009-12-17 00:54:02 +03:00
subndr - > offset = size_is ;
2005-03-15 17:33:38 +03:00
}
switch ( header_size ) {
2017-02-24 01:59:24 +03:00
case 0 :
2003-11-22 11:11:32 +03:00
break ;
2017-02-24 01:59:24 +03:00
case 2 :
2005-08-18 04:45:19 +04:00
NDR_CHECK ( ndr_push_uint16 ( ndr , NDR_SCALARS , subndr - > offset ) ) ;
2003-11-22 11:11:32 +03:00
break ;
2017-02-24 01:59:24 +03:00
case 4 :
2009-09-18 02:14:31 +04:00
NDR_CHECK ( ndr_push_uint3264 ( ndr , NDR_SCALARS , subndr - > offset ) ) ;
2003-11-22 11:11:32 +03:00
break ;
2008-08-18 19:10:59 +04:00
case 0xFFFFFC01 :
/*
* Common Type Header for the Serialization Stream
* See [ MS - RPCE ] 2.2 .6 Type Serialization Version 1
*/
padding_len = NDR_ROUND ( subndr - > offset , 8 ) - subndr - > offset ;
if ( padding_len > 0 ) {
NDR_CHECK ( ndr_push_zero ( subndr , padding_len ) ) ;
}
/* version */
NDR_CHECK ( ndr_push_uint8 ( ndr , NDR_SCALARS , 1 ) ) ;
/*
* 0x10 little endian
* 0x00 big endian
*/
NDR_CHECK ( ndr_push_uint8 ( ndr , NDR_SCALARS , NDR_BE ( ndr ) ? 0x00 : 0x10 ) ) ;
/* length of the "Private Header for Constructed Type" */
NDR_CHECK ( ndr_push_uint16 ( ndr , NDR_SCALARS , 8 ) ) ;
/* filler */
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , 0xCCCCCCCC ) ) ;
/*
* Private Header for Constructed Type
*/
/* length - will be updated latter */
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , subndr - > offset ) ) ;
/* reserved */
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , 0 ) ) ;
break ;
2003-11-22 11:11:32 +03:00
default :
2017-02-24 01:59:24 +03:00
return ndr_push_error ( ndr , NDR_ERR_SUBCONTEXT , " Bad subcontext header size %d " ,
2005-07-17 13:08:19 +04:00
( int ) header_size ) ;
2003-11-22 11:11:32 +03:00
}
2005-08-18 04:45:19 +04:00
NDR_CHECK ( ndr_push_bytes ( ndr , subndr - > data , subndr - > offset ) ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-11-22 11:11:32 +03:00
}
2017-02-24 01:58:33 +03:00
struct ndr_token {
const void * key ;
uint32_t value ;
} ;
2004-08-12 09:15:41 +04:00
/*
store a token in the ndr context , for later retrieval
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_token_store ( TALLOC_CTX * mem_ctx ,
2017-02-24 01:58:33 +03:00
struct ndr_token_list * list ,
const void * key ,
2005-07-07 23:13:32 +04:00
uint32_t value )
2004-08-12 09:15:41 +04:00
{
2017-02-24 01:58:33 +03:00
if ( list - > tokens = = NULL ) {
list - > tokens = talloc_array ( mem_ctx , struct ndr_token , 10 ) ;
if ( list - > tokens = = NULL ) {
NDR_ERR_HAVE_NO_MEMORY ( list - > tokens ) ;
}
} else {
uint32_t alloc_count = talloc_array_length ( list - > tokens ) ;
if ( list - > count = = alloc_count ) {
unsigned new_alloc ;
unsigned increment = MIN ( list - > count , 1000 ) ;
new_alloc = alloc_count + increment ;
if ( new_alloc < alloc_count ) {
return NDR_ERR_RANGE ;
}
list - > tokens = talloc_realloc ( mem_ctx , list - > tokens ,
struct ndr_token , new_alloc ) ;
if ( list - > tokens = = NULL ) {
NDR_ERR_HAVE_NO_MEMORY ( list - > tokens ) ;
}
}
}
list - > tokens [ list - > count ] . key = key ;
list - > tokens [ list - > count ] . value = value ;
list - > count + + ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2004-08-12 09:15:41 +04:00
}
2003-11-16 16:49:14 +03:00
/*
2005-07-07 23:13:32 +04:00
retrieve a token from a ndr context , using cmp_fn to match the tokens
2003-11-16 16:49:14 +03:00
*/
2017-02-24 01:58:33 +03:00
_PUBLIC_ enum ndr_err_code ndr_token_retrieve_cmp_fn ( struct ndr_token_list * list ,
const void * key , uint32_t * v ,
comparison_fn_t _cmp_fn ,
bool erase )
2003-11-16 16:49:14 +03:00
{
2017-02-24 01:58:33 +03:00
struct ndr_token * tokens = list - > tokens ;
unsigned i ;
if ( _cmp_fn ) {
for ( i = list - > count - 1 ; i < list - > count ; i - - ) {
if ( _cmp_fn ( tokens [ i ] . key , key ) = = 0 ) {
goto found ;
}
}
} else {
for ( i = list - > count - 1 ; i < list - > count ; i - - ) {
if ( tokens [ i ] . key = = key ) {
goto found ;
}
}
2004-12-09 10:05:00 +03:00
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_TOKEN ;
2005-07-07 23:13:32 +04:00
found :
2017-02-24 01:58:33 +03:00
* v = tokens [ i ] . value ;
if ( erase ) {
if ( i ! = list - > count - 1 ) {
tokens [ i ] = tokens [ list - > count - 1 ] ;
}
list - > count - - ;
2005-07-07 23:13:32 +04:00
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-07-07 23:13:32 +04:00
}
/*
retrieve a token from a ndr context
*/
2017-02-24 01:58:33 +03:00
_PUBLIC_ enum ndr_err_code ndr_token_retrieve ( struct ndr_token_list * list ,
const void * key , uint32_t * v )
2005-07-07 23:13:32 +04:00
{
2007-09-25 20:05:08 +04:00
return ndr_token_retrieve_cmp_fn ( list , key , v , NULL , true ) ;
2004-12-09 10:05:00 +03:00
}
/*
peek at but don ' t removed a token from a ndr context
*/
2017-02-24 01:58:33 +03:00
_PUBLIC_ uint32_t ndr_token_peek ( struct ndr_token_list * list , const void * key )
2004-12-09 10:05:00 +03:00
{
2017-02-24 01:58:33 +03:00
unsigned i ;
struct ndr_token * tokens = list - > tokens ;
for ( i = list - > count - 1 ; i < list - > count ; i - - ) {
if ( tokens [ i ] . key = = key ) {
return tokens [ i ] . value ;
2016-02-26 06:58:09 +03:00
}
2007-11-02 12:59:43 +03:00
}
2017-02-24 01:58:33 +03:00
2016-02-26 06:58:09 +03:00
return 0 ;
2004-08-12 09:15:41 +04:00
}
2004-12-09 10:05:00 +03:00
/*
pull an array size field and add it to the array_size_list token list
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_array_size ( struct ndr_pull * ndr , const void * p )
2004-12-09 10:05:00 +03:00
{
uint32_t size ;
2009-09-17 10:57:32 +04:00
NDR_CHECK ( ndr_pull_uint3264 ( ndr , NDR_SCALARS , & size ) ) ;
2004-12-09 10:05:00 +03:00
return ndr_token_store ( ndr , & ndr - > array_size_list , p , size ) ;
}
/*
get the stored array size field
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_get_array_size ( struct ndr_pull * ndr , const void * p )
2004-12-09 10:05:00 +03:00
{
return ndr_token_peek ( & ndr - > array_size_list , p ) ;
}
/*
check the stored array size field
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_check_array_size ( struct ndr_pull * ndr , void * p , uint32_t size )
2004-12-09 10:05:00 +03:00
{
2004-12-11 01:36:46 +03:00
uint32_t stored ;
r6973: Merge new version of pidl into the main SAMBA_4_0 branch.
The main difference in this new version is the extra data structure generated
between the IDL data structure and the NDR parser:
IDL -> NDR -> { ndr_parser, ndr_header, eparser, etc }
This makes the ndr_parser.pm internals much more sane.
Other changes include:
- Remove unnecessary calls with NDR_BUFFERS (for example, GUID doesn't have any buffers, just scalars) as well as some (unnecessary) nested setting of flags.
- Parse array loops in the C code rather then calling ndr_pull_array(). This allows us to have, for example, arrays of pointers or arrays of pointers to arrays, etc..
- Use if() {} rather then if () goto foo; everywhere
- NDR_IN no longer implies LIBNDR_FLAG_REF_ALLOC
- By default, top level pointers are now "ref" (as is the default in
most other IDL compilers). This can be overridden using the
default_pointer_top() property.
- initial work on new ethereal parser generators by Alan DeKok and me
- pidl now writes errors in the standard format used by compilers, which
is parsable by most editors
- ability to warn about the fact that pidl extension(s) have been used,
useful for making sure IDL files work with other IDL compilers.
oh, and there's probably some other things I can't think of right now..
(This used to be commit 13cf227615f6b9e0e5fa62e59197024410254f01)
2005-05-25 17:50:27 +04:00
stored = ndr_token_peek ( & ndr - > array_size_list , p ) ;
2004-12-09 10:05:00 +03:00
if ( stored ! = size ) {
2017-02-24 01:59:24 +03:00
return ndr_pull_error ( ndr , NDR_ERR_ARRAY_SIZE ,
2004-12-09 10:05:00 +03:00
" Bad array size - got %u expected %u \n " ,
stored , size ) ;
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2004-12-09 10:05:00 +03:00
}
/*
pull an array length field and add it to the array_length_list token list
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_array_length ( struct ndr_pull * ndr , const void * p )
2004-12-09 10:05:00 +03:00
{
uint32_t length , offset ;
2009-09-17 10:57:32 +04:00
NDR_CHECK ( ndr_pull_uint3264 ( ndr , NDR_SCALARS , & offset ) ) ;
2004-12-09 10:05:00 +03:00
if ( offset ! = 0 ) {
2017-02-24 01:59:24 +03:00
return ndr_pull_error ( ndr , NDR_ERR_ARRAY_SIZE ,
2004-12-09 10:05:00 +03:00
" non-zero array offset %u \n " , offset ) ;
}
2009-09-17 10:57:32 +04:00
NDR_CHECK ( ndr_pull_uint3264 ( ndr , NDR_SCALARS , & length ) ) ;
2004-12-09 10:05:00 +03:00
return ndr_token_store ( ndr , & ndr - > array_length_list , p , length ) ;
}
/*
get the stored array length field
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_get_array_length ( struct ndr_pull * ndr , const void * p )
2004-12-09 10:05:00 +03:00
{
return ndr_token_peek ( & ndr - > array_length_list , p ) ;
}
/*
check the stored array length field
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_check_array_length ( struct ndr_pull * ndr , void * p , uint32_t length )
2004-12-09 10:05:00 +03:00
{
uint32_t stored ;
r6973: Merge new version of pidl into the main SAMBA_4_0 branch.
The main difference in this new version is the extra data structure generated
between the IDL data structure and the NDR parser:
IDL -> NDR -> { ndr_parser, ndr_header, eparser, etc }
This makes the ndr_parser.pm internals much more sane.
Other changes include:
- Remove unnecessary calls with NDR_BUFFERS (for example, GUID doesn't have any buffers, just scalars) as well as some (unnecessary) nested setting of flags.
- Parse array loops in the C code rather then calling ndr_pull_array(). This allows us to have, for example, arrays of pointers or arrays of pointers to arrays, etc..
- Use if() {} rather then if () goto foo; everywhere
- NDR_IN no longer implies LIBNDR_FLAG_REF_ALLOC
- By default, top level pointers are now "ref" (as is the default in
most other IDL compilers). This can be overridden using the
default_pointer_top() property.
- initial work on new ethereal parser generators by Alan DeKok and me
- pidl now writes errors in the standard format used by compilers, which
is parsable by most editors
- ability to warn about the fact that pidl extension(s) have been used,
useful for making sure IDL files work with other IDL compilers.
oh, and there's probably some other things I can't think of right now..
(This used to be commit 13cf227615f6b9e0e5fa62e59197024410254f01)
2005-05-25 17:50:27 +04:00
stored = ndr_token_peek ( & ndr - > array_length_list , p ) ;
2004-12-09 10:05:00 +03:00
if ( stored ! = length ) {
2017-02-24 01:59:24 +03:00
return ndr_pull_error ( ndr , NDR_ERR_ARRAY_SIZE ,
2004-12-09 10:05:00 +03:00
" Bad array length - got %u expected %u \n " ,
stored , length ) ;
}
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2004-12-09 10:05:00 +03:00
}
2004-08-12 09:15:41 +04:00
2010-09-21 07:18:02 +04:00
_PUBLIC_ enum ndr_err_code ndr_push_pipe_chunk_trailer ( struct ndr_push * ndr , int ndr_flags , uint32_t count )
{
if ( ndr - > flags & LIBNDR_FLAG_NDR64 ) {
int64_t tmp = 0 - ( int64_t ) count ;
uint64_t ncount = tmp ;
NDR_CHECK ( ndr_push_hyper ( ndr , ndr_flags , ncount ) ) ;
}
return NDR_ERR_SUCCESS ;
}
_PUBLIC_ enum ndr_err_code ndr_check_pipe_chunk_trailer ( struct ndr_pull * ndr , int ndr_flags , uint32_t count )
{
if ( ndr - > flags & LIBNDR_FLAG_NDR64 ) {
int64_t tmp = 0 - ( int64_t ) count ;
uint64_t ncount1 = tmp ;
uint64_t ncount2 ;
NDR_CHECK ( ndr_pull_hyper ( ndr , ndr_flags , & ncount2 ) ) ;
if ( ncount1 = = ncount2 ) {
return NDR_ERR_SUCCESS ;
}
return ndr_pull_error ( ndr , NDR_ERR_ARRAY_SIZE ,
" Bad pipe trailer[%lld should be %lld] size was %lu \" " ,
( unsigned long long ) ncount2 ,
( unsigned long long ) ncount1 ,
( unsigned long ) count ) ;
}
return NDR_ERR_SUCCESS ;
}
2005-03-06 20:02:14 +03:00
/*
store a switch value
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_set_switch_value ( struct ndr_push * ndr , const void * p , uint32_t val )
2005-03-06 20:02:14 +03:00
{
return ndr_token_store ( ndr , & ndr - > switch_list , p , val ) ;
}
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_set_switch_value ( struct ndr_pull * ndr , const void * p , uint32_t val )
2005-03-06 20:02:14 +03:00
{
return ndr_token_store ( ndr , & ndr - > switch_list , p , val ) ;
}
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_print_set_switch_value ( struct ndr_print * ndr , const void * p , uint32_t val )
2005-04-04 18:22:28 +04:00
{
return ndr_token_store ( ndr , & ndr - > switch_list , p , val ) ;
}
2005-03-06 20:02:14 +03:00
/*
retrieve a switch value
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_push_get_switch_value ( struct ndr_push * ndr , const void * p )
2005-03-06 20:02:14 +03:00
{
return ndr_token_peek ( & ndr - > switch_list , p ) ;
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_pull_get_switch_value ( struct ndr_pull * ndr , const void * p )
2005-03-06 20:02:14 +03:00
{
return ndr_token_peek ( & ndr - > switch_list , p ) ;
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_print_get_switch_value ( struct ndr_print * ndr , const void * p )
2005-04-03 00:57:27 +04:00
{
return ndr_token_peek ( & ndr - > switch_list , p ) ;
}
2016-03-01 02:26:33 +03:00
/* retrieve a switch value and remove it from the list */
_PUBLIC_ uint32_t ndr_pull_steal_switch_value ( struct ndr_pull * ndr , const void * p )
{
enum ndr_err_code status ;
uint32_t v ;
status = ndr_token_retrieve ( & ndr - > switch_list , p , & v ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( status ) ) {
return 0 ;
}
return v ;
}
2003-11-17 07:56:59 +03:00
/*
pull a struct from a blob using NDR
*/
2010-05-09 19:20:01 +04:00
_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx , void * p ,
2004-11-05 10:29:02 +03:00
ndr_pull_flags_fn_t fn )
2003-11-17 07:56:59 +03:00
{
struct ndr_pull * ndr ;
2010-05-09 19:20:01 +04:00
ndr = ndr_pull_init_blob ( blob , mem_ctx ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndr ) ;
2009-09-12 09:21:33 +04:00
NDR_CHECK_FREE ( fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
talloc_free ( ndr ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-11-17 07:56:59 +03:00
}
2003-11-24 04:24:29 +03:00
2005-05-10 05:58:34 +04:00
/*
pull a struct from a blob using NDR - failing if all bytes are not consumed
*/
2017-02-24 01:59:24 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx ,
2008-01-02 07:05:13 +03:00
void * p , ndr_pull_flags_fn_t fn )
2005-05-10 05:58:34 +04:00
{
struct ndr_pull * ndr ;
2009-11-20 13:34:53 +03:00
uint32_t highest_ofs ;
2010-05-09 19:20:01 +04:00
ndr = ndr_pull_init_blob ( blob , mem_ctx ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndr ) ;
2009-09-12 09:21:33 +04:00
NDR_CHECK_FREE ( fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
2009-11-20 13:34:53 +03:00
if ( ndr - > offset > ndr - > relative_highest_offset ) {
highest_ofs = ndr - > offset ;
} else {
highest_ofs = ndr - > relative_highest_offset ;
}
if ( highest_ofs < ndr - > data_size ) {
enum ndr_err_code ret ;
ret = ndr_pull_error ( ndr , NDR_ERR_UNREAD_BYTES ,
" not all bytes consumed ofs[%u] size[%u] " ,
highest_ofs , ndr - > data_size ) ;
talloc_free ( ndr ) ;
return ret ;
2005-05-10 05:58:34 +04:00
}
2009-09-12 09:21:33 +04:00
talloc_free ( ndr ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-05-10 05:58:34 +04:00
}
2016-04-22 03:02:57 +03:00
/*
pull a struct from a blob using NDR - failing if all bytes are not consumed
This only works for structures with NO allocated memory , like
objectSID and GUID . This helps because we parse these a lot .
*/
_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all_noalloc ( const DATA_BLOB * blob ,
void * p , ndr_pull_flags_fn_t fn )
{
/*
* We init this structure on the stack here , to avoid a
* talloc ( ) as otherwise this call to the fn ( ) is assured not
* to be doing any allocation , eg SIDs and GUIDs .
*
* This allows us to keep the safety of the PIDL - generated
* code without the talloc ( ) overhead .
*/
struct ndr_pull ndr = {
. data = blob - > data ,
. data_size = blob - > length ,
. current_mem_ctx = ( void * ) - 1
} ;
uint32_t highest_ofs ;
NDR_CHECK ( fn ( & ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
if ( ndr . offset > ndr . relative_highest_offset ) {
highest_ofs = ndr . offset ;
} else {
highest_ofs = ndr . relative_highest_offset ;
}
if ( highest_ofs < ndr . data_size ) {
enum ndr_err_code ret ;
ret = ndr_pull_error ( & ndr , NDR_ERR_UNREAD_BYTES ,
" not all bytes consumed ofs[%u] size[%u] " ,
highest_ofs , ndr . data_size ) ;
return ret ;
}
return NDR_ERR_SUCCESS ;
}
2005-05-11 03:33:56 +04:00
/*
pull a union from a blob using NDR , given the union discriminator
*/
2017-02-24 01:59:24 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_union_blob ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx ,
2010-05-09 19:20:01 +04:00
void * p ,
2005-05-11 03:33:56 +04:00
uint32_t level , ndr_pull_flags_fn_t fn )
2007-11-01 10:10:54 +03:00
{
struct ndr_pull * ndr ;
2010-05-09 19:20:01 +04:00
ndr = ndr_pull_init_blob ( blob , mem_ctx ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndr ) ;
2009-09-12 09:21:33 +04:00
NDR_CHECK_FREE ( ndr_pull_set_switch_value ( ndr , p , level ) ) ;
NDR_CHECK_FREE ( fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
talloc_free ( ndr ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2007-11-01 10:10:54 +03:00
}
/*
pull a union from a blob using NDR , given the union discriminator ,
failing if all bytes are not consumed
*/
2017-02-24 01:59:24 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all ( const DATA_BLOB * blob , TALLOC_CTX * mem_ctx ,
2010-05-09 19:20:01 +04:00
void * p ,
2007-11-01 10:10:54 +03:00
uint32_t level , ndr_pull_flags_fn_t fn )
2005-05-11 03:33:56 +04:00
{
struct ndr_pull * ndr ;
2009-11-20 13:34:53 +03:00
uint32_t highest_ofs ;
2010-05-09 19:20:01 +04:00
ndr = ndr_pull_init_blob ( blob , mem_ctx ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndr ) ;
2009-09-12 09:21:33 +04:00
NDR_CHECK_FREE ( ndr_pull_set_switch_value ( ndr , p , level ) ) ;
NDR_CHECK_FREE ( fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
2009-11-20 13:34:53 +03:00
if ( ndr - > offset > ndr - > relative_highest_offset ) {
highest_ofs = ndr - > offset ;
} else {
highest_ofs = ndr - > relative_highest_offset ;
}
if ( highest_ofs < ndr - > data_size ) {
2009-09-12 09:21:33 +04:00
enum ndr_err_code ret ;
ret = ndr_pull_error ( ndr , NDR_ERR_UNREAD_BYTES ,
" not all bytes consumed ofs[%u] size[%u] " ,
2009-11-20 13:34:53 +03:00
highest_ofs , ndr - > data_size ) ;
2009-09-12 09:21:33 +04:00
talloc_free ( ndr ) ;
return ret ;
2005-05-11 03:33:56 +04:00
}
2009-09-12 09:21:33 +04:00
talloc_free ( ndr ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-05-11 03:33:56 +04:00
}
2003-11-26 04:16:41 +03:00
/*
push a struct to a blob using NDR
*/
2010-05-09 19:20:01 +04:00
_PUBLIC_ enum ndr_err_code ndr_push_struct_blob ( DATA_BLOB * blob , TALLOC_CTX * mem_ctx , const void * p , ndr_push_flags_fn_t fn )
2003-11-26 04:16:41 +03:00
{
struct ndr_push * ndr ;
2010-05-09 19:20:01 +04:00
ndr = ndr_push_init_ctx ( mem_ctx ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndr ) ;
2007-11-02 12:26:49 +03:00
NDR_CHECK ( fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
2003-11-24 04:24:29 +03:00
2003-11-26 04:16:41 +03:00
* blob = ndr_push_blob ( ndr ) ;
2006-10-16 15:03:12 +04:00
talloc_steal ( mem_ctx , blob - > data ) ;
talloc_free ( ndr ) ;
2003-11-26 04:16:41 +03:00
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2003-11-26 04:16:41 +03:00
}
2005-01-05 05:01:19 +03:00
2017-02-24 01:59:24 +03:00
/*
push a struct into a provided blob using NDR .
2016-06-17 04:29:51 +03:00
We error because we want to have the performance issue ( extra
talloc ( ) calls ) show up as an error , not just slower code . This is
used for things like GUIDs , which we expect to be a fixed size , and
SIDs that we can pre - calculate the size for .
*/
_PUBLIC_ enum ndr_err_code ndr_push_struct_into_fixed_blob (
DATA_BLOB * blob , const void * p , ndr_push_flags_fn_t fn )
{
struct ndr_push ndr = {
. data = blob - > data ,
. alloc_size = blob - > length ,
. fixed_buf_size = true
} ;
NDR_CHECK ( fn ( & ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
if ( ndr . offset ! = blob - > length ) {
return ndr_push_error ( & ndr , NDR_ERR_BUFSIZE ,
" buffer was either to large or small "
" ofs[%u] size[%zu] " ,
ndr . offset , blob - > length ) ;
}
return NDR_ERR_SUCCESS ;
}
2005-05-12 12:27:04 +04:00
/*
push a union to a blob using NDR
*/
2010-05-09 19:20:01 +04:00
_PUBLIC_ enum ndr_err_code ndr_push_union_blob ( DATA_BLOB * blob , TALLOC_CTX * mem_ctx , void * p ,
2005-05-12 12:27:04 +04:00
uint32_t level , ndr_push_flags_fn_t fn )
{
struct ndr_push * ndr ;
2010-05-09 19:20:01 +04:00
ndr = ndr_push_init_ctx ( mem_ctx ) ;
2007-11-09 21:23:40 +03:00
NDR_ERR_HAVE_NO_MEMORY ( ndr ) ;
2007-11-02 12:26:49 +03:00
2007-11-02 12:29:19 +03:00
NDR_CHECK ( ndr_push_set_switch_value ( ndr , p , level ) ) ;
2007-11-02 12:26:49 +03:00
NDR_CHECK ( fn ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ) ;
2005-05-12 12:27:04 +04:00
* blob = ndr_push_blob ( ndr ) ;
2006-10-16 18:32:07 +04:00
talloc_steal ( mem_ctx , blob - > data ) ;
talloc_free ( ndr ) ;
2005-05-12 12:27:04 +04:00
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-05-12 12:27:04 +04:00
}
2005-01-05 05:01:19 +03:00
/*
generic ndr_size_ * ( ) handler for structures
*/
2010-05-09 19:20:01 +04:00
_PUBLIC_ size_t ndr_size_struct ( const void * p , int flags , ndr_push_flags_fn_t push )
2005-01-05 05:01:19 +03:00
{
struct ndr_push * ndr ;
2007-11-09 21:23:40 +03:00
enum ndr_err_code status ;
2005-01-05 05:01:19 +03:00
size_t ret ;
2005-03-11 13:09:16 +03:00
/* avoid recursion */
if ( flags & LIBNDR_FLAG_NO_NDR_SIZE ) return 0 ;
2010-05-09 19:20:01 +04:00
ndr = ndr_push_init_ctx ( NULL ) ;
2005-01-05 05:01:19 +03:00
if ( ! ndr ) return 0 ;
2005-03-11 13:09:16 +03:00
ndr - > flags | = flags | LIBNDR_FLAG_NO_NDR_SIZE ;
2005-01-05 05:01:19 +03:00
status = push ( ndr , NDR_SCALARS | NDR_BUFFERS , discard_const ( p ) ) ;
2007-11-09 21:23:40 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( status ) ) {
2007-11-02 13:01:18 +03:00
talloc_free ( ndr ) ;
2005-01-05 05:01:19 +03:00
return 0 ;
}
ret = ndr - > offset ;
talloc_free ( ndr ) ;
return ret ;
}
2005-01-21 09:54:10 +03:00
/*
generic ndr_size_ * ( ) handler for unions
*/
2010-05-09 19:20:01 +04:00
_PUBLIC_ size_t ndr_size_union ( const void * p , int flags , uint32_t level , ndr_push_flags_fn_t push )
2005-01-21 09:54:10 +03:00
{
struct ndr_push * ndr ;
2007-11-09 21:23:40 +03:00
enum ndr_err_code status ;
2005-01-21 09:54:10 +03:00
size_t ret ;
2005-03-11 13:09:16 +03:00
/* avoid recursion */
if ( flags & LIBNDR_FLAG_NO_NDR_SIZE ) return 0 ;
2010-05-09 19:20:01 +04:00
ndr = ndr_push_init_ctx ( NULL ) ;
2005-01-21 09:54:10 +03:00
if ( ! ndr ) return 0 ;
2005-03-11 13:09:16 +03:00
ndr - > flags | = flags | LIBNDR_FLAG_NO_NDR_SIZE ;
2007-11-02 13:01:18 +03:00
status = ndr_push_set_switch_value ( ndr , p , level ) ;
2007-11-09 21:23:40 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( status ) ) {
2007-11-02 13:01:18 +03:00
talloc_free ( ndr ) ;
return 0 ;
}
2005-07-04 06:25:33 +04:00
status = push ( ndr , NDR_SCALARS | NDR_BUFFERS , p ) ;
2007-11-09 21:23:40 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( status ) ) {
2007-11-02 13:01:18 +03:00
talloc_free ( ndr ) ;
2005-01-21 09:54:10 +03:00
return 0 ;
}
ret = ndr - > offset ;
talloc_free ( ndr ) ;
return ret ;
}
2005-06-02 07:41:12 +04:00
/*
get the current base for relative pointers for the push
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_push_get_relative_base_offset ( struct ndr_push * ndr )
2005-06-02 07:41:12 +04:00
{
return ndr - > relative_base_offset ;
}
/*
restore the old base for relative pointers for the push
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_push_restore_relative_base_offset ( struct ndr_push * ndr , uint32_t offset )
2005-06-02 07:41:12 +04:00
{
ndr - > relative_base_offset = offset ;
}
/*
setup the current base for relative pointers for the push
called in the NDR_SCALAR stage
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset1 ( struct ndr_push * ndr , const void * p , uint32_t offset )
2005-06-02 07:41:12 +04:00
{
ndr - > relative_base_offset = offset ;
return ndr_token_store ( ndr , & ndr - > relative_base_list , p , offset ) ;
}
/*
setup the current base for relative pointers for the push
called in the NDR_BUFFERS stage
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_setup_relative_base_offset2 ( struct ndr_push * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
return ndr_token_retrieve ( & ndr - > relative_base_list , p , & ndr - > relative_base_offset ) ;
}
/*
push a relative object - stage1
this is called during SCALARS processing
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_relative_ptr1 ( struct ndr_push * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
if ( p = = NULL ) {
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , 0 ) ) ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-06-02 07:41:12 +04:00
}
NDR_CHECK ( ndr_push_align ( ndr , 4 ) ) ;
NDR_CHECK ( ndr_token_store ( ndr , & ndr - > relative_list , p , ndr - > offset ) ) ;
return ndr_push_uint32 ( ndr , NDR_SCALARS , 0xFFFFFFFF ) ;
}
2009-12-10 10:04:48 +03:00
/*
push a short relative object - stage1
this is called during SCALARS processing
*/
_PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr1 ( struct ndr_push * ndr , const void * p )
{
if ( p = = NULL ) {
NDR_CHECK ( ndr_push_uint16 ( ndr , NDR_SCALARS , 0 ) ) ;
return NDR_ERR_SUCCESS ;
}
NDR_CHECK ( ndr_push_align ( ndr , 2 ) ) ;
NDR_CHECK ( ndr_token_store ( ndr , & ndr - > relative_list , p , ndr - > offset ) ) ;
return ndr_push_uint16 ( ndr , NDR_SCALARS , 0xFFFF ) ;
}
2005-06-02 07:41:12 +04:00
/*
push a relative object - stage2
this is called during buffers processing
*/
2010-02-17 22:00:36 +03:00
static enum ndr_err_code ndr_push_relative_ptr2 ( struct ndr_push * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
2007-11-20 13:07:57 +03:00
uint32_t save_offset ;
2005-06-02 10:25:48 +04:00
uint32_t ptr_offset = 0xFFFFFFFF ;
2005-06-02 07:41:12 +04:00
if ( p = = NULL ) {
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-06-02 07:41:12 +04:00
}
2007-11-20 13:07:57 +03:00
save_offset = ndr - > offset ;
2005-06-02 10:25:48 +04:00
NDR_CHECK ( ndr_token_retrieve ( & ndr - > relative_list , p , & ptr_offset ) ) ;
if ( ptr_offset > ndr - > offset ) {
2017-02-24 01:59:24 +03:00
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE ,
2005-06-02 10:25:48 +04:00
" ndr_push_relative_ptr2 ptr_offset(%u) > ndr->offset(%u) " ,
ptr_offset , ndr - > offset ) ;
}
ndr - > offset = ptr_offset ;
2007-11-20 13:07:57 +03:00
if ( save_offset < ndr - > relative_base_offset ) {
2017-02-24 01:59:24 +03:00
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE ,
2007-11-20 13:07:57 +03:00
" ndr_push_relative_ptr2 save_offset(%u) < ndr->relative_base_offset(%u) " ,
save_offset , ndr - > relative_base_offset ) ;
2017-02-24 01:59:24 +03:00
}
2007-11-20 13:07:57 +03:00
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , save_offset - ndr - > relative_base_offset ) ) ;
2009-12-10 10:04:48 +03:00
ndr - > offset = save_offset ;
return NDR_ERR_SUCCESS ;
}
/*
push a short relative object - stage2
this is called during buffers processing
*/
_PUBLIC_ enum ndr_err_code ndr_push_short_relative_ptr2 ( struct ndr_push * ndr , const void * p )
{
uint32_t save_offset ;
uint32_t ptr_offset = 0xFFFF ;
2016-01-06 15:25:45 +03:00
uint32_t relative_offset ;
size_t pad ;
size_t align = 1 ;
2009-12-10 10:04:48 +03:00
if ( p = = NULL ) {
return NDR_ERR_SUCCESS ;
}
2016-01-06 15:25:45 +03:00
if ( ndr - > offset < ndr - > relative_base_offset ) {
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_push_relative_ptr2 ndr->offset(%u) < ndr->relative_base_offset(%u) " ,
ndr - > offset , ndr - > relative_base_offset ) ;
}
relative_offset = ndr - > offset - ndr - > relative_base_offset ;
if ( ndr - > flags & LIBNDR_FLAG_NOALIGN ) {
align = 1 ;
} else if ( ndr - > flags & LIBNDR_FLAG_ALIGN2 ) {
align = 2 ;
} else if ( ndr - > flags & LIBNDR_FLAG_ALIGN4 ) {
align = 4 ;
} else if ( ndr - > flags & LIBNDR_FLAG_ALIGN8 ) {
align = 8 ;
}
pad = ndr_align_size ( relative_offset , align ) ;
if ( pad ! = 0 ) {
NDR_CHECK ( ndr_push_zero ( ndr , pad ) ) ;
}
relative_offset = ndr - > offset - ndr - > relative_base_offset ;
if ( relative_offset > UINT16_MAX ) {
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_push_relative_ptr2 relative_offset(%u) > UINT16_MAX " ,
relative_offset ) ;
}
2009-12-10 10:04:48 +03:00
save_offset = ndr - > offset ;
NDR_CHECK ( ndr_token_retrieve ( & ndr - > relative_list , p , & ptr_offset ) ) ;
if ( ptr_offset > ndr - > offset ) {
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_push_short_relative_ptr2 ptr_offset(%u) > ndr->offset(%u) " ,
ptr_offset , ndr - > offset ) ;
}
ndr - > offset = ptr_offset ;
2016-01-06 15:25:45 +03:00
NDR_CHECK ( ndr_push_uint16 ( ndr , NDR_SCALARS , relative_offset ) ) ;
2007-11-20 13:07:57 +03:00
ndr - > offset = save_offset ;
2007-11-09 21:23:40 +03:00
return NDR_ERR_SUCCESS ;
2005-06-02 07:41:12 +04:00
}
2009-12-14 16:08:34 +03:00
/*
push a relative object - stage2 start
this is called during buffers processing
*/
_PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_start ( struct ndr_push * ndr , const void * p )
{
if ( p = = NULL ) {
return NDR_ERR_SUCCESS ;
}
2010-02-17 22:27:08 +03:00
if ( ! ( ndr - > flags & LIBNDR_FLAG_RELATIVE_REVERSE ) ) {
2011-02-22 17:45:44 +03:00
uint32_t relative_offset ;
size_t pad ;
2011-02-22 17:58:45 +03:00
size_t align = 1 ;
2011-02-22 17:45:44 +03:00
if ( ndr - > offset < ndr - > relative_base_offset ) {
return ndr_push_error ( ndr , NDR_ERR_BUFSIZE ,
" ndr_push_relative_ptr2_start ndr->offset(%u) < ndr->relative_base_offset(%u) " ,
ndr - > offset , ndr - > relative_base_offset ) ;
}
relative_offset = ndr - > offset - ndr - > relative_base_offset ;
2011-03-01 16:20:32 +03:00
if ( ndr - > flags & LIBNDR_FLAG_NOALIGN ) {
align = 1 ;
} else if ( ndr - > flags & LIBNDR_FLAG_ALIGN2 ) {
2011-02-22 17:45:44 +03:00
align = 2 ;
} else if ( ndr - > flags & LIBNDR_FLAG_ALIGN4 ) {
align = 4 ;
} else if ( ndr - > flags & LIBNDR_FLAG_ALIGN8 ) {
align = 8 ;
}
pad = ndr_align_size ( relative_offset , align ) ;
if ( pad ) {
NDR_CHECK ( ndr_push_zero ( ndr , pad ) ) ;
}
2010-02-17 22:27:08 +03:00
return ndr_push_relative_ptr2 ( ndr , p ) ;
}
2010-02-17 23:24:40 +03:00
if ( ndr - > relative_end_offset = = - 1 ) {
return ndr_push_error ( ndr , NDR_ERR_RELATIVE ,
" ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d " ,
ndr - > relative_end_offset ) ;
}
NDR_CHECK ( ndr_token_store ( ndr , & ndr - > relative_begin_list , p , ndr - > offset ) ) ;
return NDR_ERR_SUCCESS ;
2009-12-14 16:08:34 +03:00
}
/*
push a relative object - stage2 end
this is called during buffers processing
*/
_PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_end ( struct ndr_push * ndr , const void * p )
{
2010-02-17 23:24:40 +03:00
uint32_t begin_offset = 0xFFFFFFFF ;
ssize_t len ;
uint32_t correct_offset = 0 ;
uint32_t align = 1 ;
uint32_t pad = 0 ;
2009-12-14 16:08:34 +03:00
if ( p = = NULL ) {
return NDR_ERR_SUCCESS ;
}
2010-02-17 23:24:40 +03:00
if ( ! ( ndr - > flags & LIBNDR_FLAG_RELATIVE_REVERSE ) ) {
return NDR_ERR_SUCCESS ;
}
2010-02-18 17:13:20 +03:00
if ( ndr - > flags & LIBNDR_FLAG_NO_NDR_SIZE ) {
/* better say more than calculation a too small buffer */
NDR_PUSH_ALIGN ( ndr , 8 ) ;
return NDR_ERR_SUCCESS ;
}
2010-02-17 23:24:40 +03:00
if ( ndr - > relative_end_offset < ndr - > offset ) {
return ndr_push_error ( ndr , NDR_ERR_RELATIVE ,
" ndr_push_relative_ptr2_end: "
" relative_end_offset %u < offset %u " ,
ndr - > relative_end_offset , ndr - > offset ) ;
}
NDR_CHECK ( ndr_token_retrieve ( & ndr - > relative_begin_list , p , & begin_offset ) ) ;
/* we have marshalled a buffer, see how long it was */
len = ndr - > offset - begin_offset ;
if ( len < 0 ) {
return ndr_push_error ( ndr , NDR_ERR_RELATIVE ,
" ndr_push_relative_ptr2_end: "
" offset %u - begin_offset %u < 0 " ,
ndr - > offset , begin_offset ) ;
}
if ( ndr - > relative_end_offset < len ) {
return ndr_push_error ( ndr , NDR_ERR_RELATIVE ,
" ndr_push_relative_ptr2_end: "
" relative_end_offset %u < len %lld " ,
ndr - > offset , ( long long ) len ) ;
}
/* the reversed offset is at the end of the main buffer */
correct_offset = ndr - > relative_end_offset - len ;
2011-03-01 16:20:32 +03:00
if ( ndr - > flags & LIBNDR_FLAG_NOALIGN ) {
align = 1 ;
} else if ( ndr - > flags & LIBNDR_FLAG_ALIGN2 ) {
2010-02-17 23:24:40 +03:00
align = 2 ;
} else if ( ndr - > flags & LIBNDR_FLAG_ALIGN4 ) {
align = 4 ;
} else if ( ndr - > flags & LIBNDR_FLAG_ALIGN8 ) {
align = 8 ;
}
pad = ndr_align_size ( correct_offset , align ) ;
if ( pad ) {
correct_offset + = pad ;
correct_offset - = align ;
}
if ( correct_offset < begin_offset ) {
return ndr_push_error ( ndr , NDR_ERR_RELATIVE ,
" ndr_push_relative_ptr2_end: "
" correct_offset %u < begin_offset %u " ,
correct_offset , begin_offset ) ;
}
if ( len > 0 ) {
2010-02-19 10:11:24 +03:00
uint32_t clear_size = correct_offset - begin_offset ;
clear_size = MIN ( clear_size , len ) ;
2010-02-17 23:24:40 +03:00
/* now move the marshalled buffer to the end of the main buffer */
memmove ( ndr - > data + correct_offset , ndr - > data + begin_offset , len ) ;
2010-02-19 10:11:24 +03:00
if ( clear_size ) {
/* and wipe out old buffer within the main buffer */
memset ( ndr - > data + begin_offset , ' \0 ' , clear_size ) ;
}
2010-02-17 23:24:40 +03:00
}
/* and set the end offset for the next buffer */
ndr - > relative_end_offset = correct_offset ;
/* finally write the offset to the main buffer */
ndr - > offset = correct_offset ;
NDR_CHECK ( ndr_push_relative_ptr2 ( ndr , p ) ) ;
/* restore to where we were in the main buffer */
ndr - > offset = begin_offset ;
2009-12-14 16:08:34 +03:00
return NDR_ERR_SUCCESS ;
}
2005-06-02 07:41:12 +04:00
/*
get the current base for relative pointers for the pull
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ uint32_t ndr_pull_get_relative_base_offset ( struct ndr_pull * ndr )
2005-06-02 07:41:12 +04:00
{
return ndr - > relative_base_offset ;
}
/*
restore the old base for relative pointers for the pull
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_pull_restore_relative_base_offset ( struct ndr_pull * ndr , uint32_t offset )
2005-06-02 07:41:12 +04:00
{
ndr - > relative_base_offset = offset ;
}
/*
setup the current base for relative pointers for the pull
called in the NDR_SCALAR stage
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset1 ( struct ndr_pull * ndr , const void * p , uint32_t offset )
2005-06-02 07:41:12 +04:00
{
ndr - > relative_base_offset = offset ;
return ndr_token_store ( ndr , & ndr - > relative_base_list , p , offset ) ;
}
/*
setup the current base for relative pointers for the pull
called in the NDR_BUFFERS stage
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_setup_relative_base_offset2 ( struct ndr_pull * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
return ndr_token_retrieve ( & ndr - > relative_base_list , p , & ndr - > relative_base_offset ) ;
}
/*
pull a relative object - stage1
called during SCALARS processing
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr1 ( struct ndr_pull * ndr , const void * p , uint32_t rel_offset )
2005-06-02 07:41:12 +04:00
{
rel_offset + = ndr - > relative_base_offset ;
2005-06-02 10:25:48 +04:00
if ( rel_offset > ndr - > data_size ) {
2017-02-24 01:59:24 +03:00
return ndr_pull_error ( ndr , NDR_ERR_BUFSIZE ,
2005-06-02 10:25:48 +04:00
" ndr_pull_relative_ptr1 rel_offset(%u) > ndr->data_size(%u) " ,
rel_offset , ndr - > data_size ) ;
}
2005-06-02 07:41:12 +04:00
return ndr_token_store ( ndr , & ndr - > relative_list , p , rel_offset ) ;
}
/*
pull a relative object - stage2
called during BUFFERS processing
*/
2007-11-09 21:23:40 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr2 ( struct ndr_pull * ndr , const void * p )
2005-06-02 07:41:12 +04:00
{
uint32_t rel_offset ;
NDR_CHECK ( ndr_token_retrieve ( & ndr - > relative_list , p , & rel_offset ) ) ;
return ndr_pull_set_offset ( ndr , rel_offset ) ;
}
2009-01-26 19:31:22 +03:00
const static struct {
enum ndr_err_code err ;
const char * string ;
} ndr_err_code_strings [ ] = {
{ NDR_ERR_SUCCESS , " Success " } ,
{ NDR_ERR_ARRAY_SIZE , " Bad Array Size " } ,
{ NDR_ERR_BAD_SWITCH , " Bad Switch " } ,
{ NDR_ERR_OFFSET , " Offset Error " } ,
{ NDR_ERR_RELATIVE , " Relative Pointer Error " } ,
{ NDR_ERR_CHARCNV , " Character Conversion Error " } ,
{ NDR_ERR_LENGTH , " Length Error " } ,
{ NDR_ERR_SUBCONTEXT , " Subcontext Error " } ,
{ NDR_ERR_COMPRESSION , " Compression Error " } ,
{ NDR_ERR_STRING , " String Error " } ,
{ NDR_ERR_VALIDATE , " Validate Error " } ,
{ NDR_ERR_BUFSIZE , " Buffer Size Error " } ,
{ NDR_ERR_ALLOC , " Allocation Error " } ,
{ NDR_ERR_RANGE , " Range Error " } ,
{ NDR_ERR_TOKEN , " Token Error " } ,
{ NDR_ERR_IPV4ADDRESS , " IPv4 Address Error " } ,
{ NDR_ERR_INVALID_POINTER , " Invalid Pointer " } ,
{ NDR_ERR_UNREAD_BYTES , " Unread Bytes " } ,
2009-09-17 20:08:47 +04:00
{ NDR_ERR_NDR64 , " NDR64 assertion error " } ,
2011-03-08 12:14:51 +03:00
{ NDR_ERR_INCOMPLETE_BUFFER , " Incomplete Buffer " } ,
2009-01-26 19:31:22 +03:00
{ 0 , NULL }
} ;
_PUBLIC_ const char * ndr_map_error2string ( enum ndr_err_code ndr_err )
{
int i ;
for ( i = 0 ; ndr_err_code_strings [ i ] . string ! = NULL ; i + + ) {
if ( ndr_err_code_strings [ i ] . err = = ndr_err )
return ndr_err_code_strings [ i ] . string ;
}
return " Unknown error " ;
}