2008-09-23 11:34:03 +04:00
/*
2005-01-21 09:54:10 +03:00
Unix SMB / CIFS implementation .
manipulate nbt name structures
Copyright ( C ) Andrew Tridgell 2005
2008-09-23 11:34:03 +04:00
2005-01-21 09:54:10 +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
2005-01-21 09:54:10 +03:00
( at your option ) any later version .
2008-09-23 11:34:03 +04:00
2005-01-21 09:54:10 +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 .
2008-09-23 11:34:03 +04:00
2005-01-21 09:54:10 +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/>.
2005-01-21 09:54:10 +03:00
*/
/*
see rfc1002 for the detailed format of compressed names
*/
# include "includes.h"
# include "librpc/gen_ndr/ndr_nbt.h"
2005-07-28 04:27:28 +04:00
# include "librpc/gen_ndr/ndr_misc.h"
2006-05-13 23:14:12 +04:00
# include "system/locale.h"
2005-01-21 09:54:10 +03:00
/* don't allow an unlimited number of name components */
# define MAX_COMPONENTS 10
2006-03-05 20:15:19 +03:00
/**
2005-04-14 06:36:30 +04:00
print a nbt string
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_print_nbt_string ( struct ndr_print * ndr , const char * name , const char * s )
2005-04-14 06:36:30 +04:00
{
2005-06-09 17:13:15 +04:00
ndr_print_string ( ndr , name , s ) ;
2005-04-14 06:36:30 +04:00
}
/*
pull one component of a nbt_string
2005-01-21 09:54:10 +03:00
*/
2007-11-09 21:24:51 +03:00
static enum ndr_err_code ndr_pull_component ( struct ndr_pull * ndr ,
uint8_t * * component ,
uint32_t * offset ,
uint32_t * max_offset )
2005-01-21 09:54:10 +03:00
{
uint8_t len ;
uint_t loops = 0 ;
while ( loops < 5 ) {
if ( * offset > = ndr - > data_size ) {
2007-11-03 12:20:45 +03:00
return ndr_pull_error ( ndr , NDR_ERR_STRING ,
" BAD NBT NAME component " ) ;
2005-01-21 09:54:10 +03:00
}
len = ndr - > data [ * offset ] ;
if ( len = = 0 ) {
* offset + = 1 ;
* max_offset = MAX ( * max_offset , * offset ) ;
* component = NULL ;
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-01-21 09:54:10 +03:00
}
if ( ( len & 0xC0 ) = = 0xC0 ) {
/* its a label pointer */
if ( 1 + * offset > = ndr - > data_size ) {
2007-11-03 12:20:45 +03:00
return ndr_pull_error ( ndr , NDR_ERR_STRING ,
" BAD NBT NAME component " ) ;
2005-01-21 09:54:10 +03:00
}
2005-02-14 14:31:48 +03:00
* max_offset = MAX ( * max_offset , * offset + 2 ) ;
2005-01-21 09:54:10 +03:00
* offset = ( ( len & 0x3F ) < < 8 ) | ndr - > data [ 1 + * offset ] ;
2005-02-14 14:31:48 +03:00
* max_offset = MAX ( * max_offset , * offset ) ;
2005-01-21 09:54:10 +03:00
loops + + ;
continue ;
}
if ( ( len & 0xC0 ) ! = 0 ) {
/* its a reserved length field */
2007-11-03 12:20:45 +03:00
return ndr_pull_error ( ndr , NDR_ERR_STRING ,
" BAD NBT NAME component " ) ;
2005-01-21 09:54:10 +03:00
}
2005-01-22 08:36:32 +03:00
if ( * offset + len + 2 > ndr - > data_size ) {
2007-11-03 12:20:45 +03:00
return ndr_pull_error ( ndr , NDR_ERR_STRING ,
" BAD NBT NAME component " ) ;
2005-01-21 09:54:10 +03:00
}
2006-01-18 18:46:00 +03:00
* component = ( uint8_t * ) talloc_strndup ( ndr , ( const char * ) & ndr - > data [ 1 + * offset ] , len ) ;
2007-11-09 21:24:51 +03:00
NDR_ERR_HAVE_NO_MEMORY ( * component ) ;
2005-01-21 09:54:10 +03:00
* offset + = len + 1 ;
* max_offset = MAX ( * max_offset , * offset ) ;
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-01-21 09:54:10 +03:00
}
/* too many pointers */
2007-11-03 12:20:45 +03:00
return ndr_pull_error ( ndr , NDR_ERR_STRING , " BAD NBT NAME component " ) ;
2005-01-21 09:54:10 +03:00
}
2006-03-05 20:15:19 +03:00
/**
2005-04-14 06:36:30 +04:00
pull a nbt_string from the wire
*/
2007-11-09 21:24:51 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_nbt_string ( struct ndr_pull * ndr , int ndr_flags , const char * * s )
2005-04-14 06:36:30 +04:00
{
uint32_t offset = ndr - > offset ;
uint32_t max_offset = offset ;
unsigned num_components ;
char * name ;
if ( ! ( ndr_flags & NDR_SCALARS ) ) {
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-04-14 06:36:30 +04:00
}
name = NULL ;
/* break up name into a list of components */
for ( num_components = 0 ; num_components < MAX_COMPONENTS ; num_components + + ) {
2008-09-23 11:34:03 +04:00
uint8_t * component = NULL ;
2007-11-03 12:45:59 +03:00
NDR_CHECK ( ndr_pull_component ( ndr , & component , & offset , & max_offset ) ) ;
2005-04-14 06:36:30 +04:00
if ( component = = NULL ) break ;
if ( name ) {
2007-09-15 03:21:00 +04:00
name = talloc_asprintf_append_buffer ( name , " .%s " , component ) ;
2007-11-09 21:24:51 +03:00
NDR_ERR_HAVE_NO_MEMORY ( name ) ;
2005-04-14 06:36:30 +04:00
} else {
2006-01-18 18:46:00 +03:00
name = ( char * ) component ;
2005-04-14 06:36:30 +04:00
}
}
if ( num_components = = MAX_COMPONENTS ) {
2007-11-03 12:20:45 +03:00
return ndr_pull_error ( ndr , NDR_ERR_STRING ,
" BAD NBT NAME too many components " ) ;
2005-04-14 06:36:30 +04:00
}
if ( num_components = = 0 ) {
name = talloc_strdup ( ndr , " " ) ;
2007-11-09 21:24:51 +03:00
NDR_ERR_HAVE_NO_MEMORY ( name ) ;
2005-04-14 06:36:30 +04:00
}
( * s ) = name ;
ndr - > offset = max_offset ;
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-04-14 06:36:30 +04:00
}
2006-03-05 20:15:19 +03:00
/**
2005-04-14 06:36:30 +04:00
push a nbt string to the wire
*/
2007-11-09 21:24:51 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_nbt_string ( struct ndr_push * ndr , int ndr_flags , const char * s )
2005-04-14 06:36:30 +04:00
{
if ( ! ( ndr_flags & NDR_SCALARS ) ) {
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-04-14 06:36:30 +04:00
}
2005-07-07 23:49:35 +04:00
while ( s & & * s ) {
2007-11-09 21:24:51 +03:00
enum ndr_err_code ndr_err ;
2005-07-07 23:49:35 +04:00
char * compname ;
size_t complen ;
uint32_t offset ;
/* see if we have pushed the remaing string allready,
* if so we use a label pointer to this string
*/
2007-11-09 21:24:51 +03:00
ndr_err = ndr_token_retrieve_cmp_fn ( & ndr - > nbt_string_list , s , & offset , ( comparison_fn_t ) strcmp , false ) ;
if ( NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2005-07-07 23:49:35 +04:00
uint8_t b [ 2 ] ;
2008-09-23 11:34:03 +04:00
2005-07-07 23:49:35 +04:00
if ( offset > 0x3FFF ) {
return ndr_push_error ( ndr , NDR_ERR_STRING ,
" offset for nbt string label pointer %u[%08X] > 0x00003FFF " ,
offset , offset ) ;
}
2005-04-14 11:40:23 +04:00
2005-07-07 23:49:35 +04:00
b [ 0 ] = 0xC0 | ( offset > > 8 ) ;
b [ 1 ] = ( offset & 0xFF ) ;
2005-04-14 11:40:23 +04:00
2005-07-07 23:49:35 +04:00
return ndr_push_bytes ( ndr , b , 2 ) ;
}
2005-04-14 06:36:30 +04:00
2005-07-07 23:49:35 +04:00
complen = strcspn ( s , " . " ) ;
2005-04-14 06:36:30 +04:00
2005-07-07 23:49:35 +04:00
/* we need to make sure the length fits into 6 bytes */
if ( complen > = 0x3F ) {
return ndr_push_error ( ndr , NDR_ERR_STRING ,
" component length %u[%08X] > 0x00003F " ,
2005-07-17 13:20:52 +04:00
( unsigned ) complen , ( unsigned ) complen ) ;
2005-04-14 06:36:30 +04:00
}
2005-07-07 23:49:35 +04:00
compname = talloc_asprintf ( ndr , " %c%*.*s " ,
( unsigned char ) complen ,
( unsigned char ) complen ,
( unsigned char ) complen , s ) ;
2007-11-09 21:24:51 +03:00
NDR_ERR_HAVE_NO_MEMORY ( compname ) ;
2005-04-14 06:36:30 +04:00
2005-07-07 23:49:35 +04:00
/* remember the current componemt + the rest of the string
* so it can be reused later
*/
NDR_CHECK ( ndr_token_store ( ndr , & ndr - > nbt_string_list , s , ndr - > offset ) ) ;
2005-04-14 06:36:30 +04:00
2005-07-07 23:49:35 +04:00
/* push just this component into the blob */
NDR_CHECK ( ndr_push_bytes ( ndr , ( const uint8_t * ) compname , complen + 1 ) ) ;
talloc_free ( compname ) ;
s + = complen ;
if ( * s = = ' . ' ) s + + ;
}
/* if we reach the end of the string and have pushed the last component
* without using a label pointer , we need to terminate the string
*/
return ndr_push_bytes ( ndr , ( const uint8_t * ) " " , 1 ) ;
2005-04-14 06:36:30 +04:00
}
2005-01-21 09:54:10 +03:00
/*
decompress a ' compressed ' name component
*/
2007-11-03 12:20:45 +03:00
static bool decompress_name ( char * name , enum nbt_name_type * type )
2005-01-21 09:54:10 +03:00
{
int i ;
for ( i = 0 ; name [ 2 * i ] ; i + + ) {
uint8_t c1 = name [ 2 * i ] ;
uint8_t c2 = name [ 1 + ( 2 * i ) ] ;
if ( c1 < ' A ' | | c1 > ' P ' | |
c2 < ' A ' | | c2 > ' P ' ) {
2007-11-03 12:20:45 +03:00
return false ;
2005-01-21 09:54:10 +03:00
}
2008-09-23 11:34:03 +04:00
name [ i ] = ( ( c1 - ' A ' ) < < 4 ) | ( c2 - ' A ' ) ;
2005-01-21 09:54:10 +03:00
}
name [ i ] = 0 ;
if ( i = = 16 ) {
* type = ( enum nbt_name_type ) ( name [ 15 ] ) ;
name [ 15 ] = 0 ;
i - - ;
} else {
* type = NBT_NAME_CLIENT ;
}
/* trim trailing spaces */
for ( ; i > 0 & & name [ i - 1 ] = = ' ' ; i - - ) {
name [ i - 1 ] = 0 ;
}
2008-09-23 11:34:03 +04:00
2007-11-03 12:20:45 +03:00
return true ;
2005-01-21 09:54:10 +03:00
}
/*
compress a name component
*/
2008-09-23 11:34:03 +04:00
static uint8_t * compress_name ( TALLOC_CTX * mem_ctx ,
2005-02-11 10:54:20 +03:00
const uint8_t * name , enum nbt_name_type type )
2005-01-21 09:54:10 +03:00
{
uint8_t * cname ;
int i ;
uint8_t pad_char ;
2006-01-18 18:46:00 +03:00
if ( strlen ( ( const char * ) name ) > 15 ) {
2005-01-21 09:54:10 +03:00
return NULL ;
}
cname = talloc_array ( mem_ctx , uint8_t , 33 ) ;
if ( cname = = NULL ) return NULL ;
for ( i = 0 ; name [ i ] ; i + + ) {
cname [ 2 * i ] = ' A ' + ( name [ i ] > > 4 ) ;
cname [ 1 + 2 * i ] = ' A ' + ( name [ i ] & 0xF ) ;
}
2006-01-18 18:46:00 +03:00
if ( strcmp ( ( const char * ) name , " * " ) = = 0 ) {
2005-01-21 09:54:10 +03:00
pad_char = 0 ;
} else {
pad_char = ' ' ;
}
for ( ; i < 15 ; i + + ) {
cname [ 2 * i ] = ' A ' + ( pad_char > > 4 ) ;
cname [ 1 + 2 * i ] = ' A ' + ( pad_char & 0xF ) ;
}
pad_char = type ;
cname [ 2 * i ] = ' A ' + ( pad_char > > 4 ) ;
cname [ 1 + 2 * i ] = ' A ' + ( pad_char & 0xF ) ;
cname [ 32 ] = 0 ;
return cname ;
}
2005-04-14 06:36:30 +04:00
2006-03-05 20:15:19 +03:00
/**
2005-01-21 09:54:10 +03:00
pull a nbt name from the wire
*/
2007-11-09 21:24:51 +03:00
_PUBLIC_ enum ndr_err_code ndr_pull_nbt_name ( struct ndr_pull * ndr , int ndr_flags , struct nbt_name * r )
2005-01-21 09:54:10 +03:00
{
uint8_t * scope ;
2005-04-14 06:36:30 +04:00
char * cname ;
const char * s ;
2007-11-03 12:20:45 +03:00
bool ok ;
2005-01-21 09:54:10 +03:00
if ( ! ( ndr_flags & NDR_SCALARS ) ) {
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-01-21 09:54:10 +03:00
}
2007-11-03 12:45:59 +03:00
NDR_CHECK ( ndr_pull_nbt_string ( ndr , ndr_flags , & s ) ) ;
2005-04-14 06:36:30 +04:00
2006-01-18 18:46:00 +03:00
scope = ( uint8_t * ) strchr ( s , ' . ' ) ;
2005-04-14 06:36:30 +04:00
if ( scope ) {
* scope = 0 ;
2006-01-18 18:46:00 +03:00
r - > scope = talloc_strdup ( ndr - > current_mem_ctx , ( const char * ) & scope [ 1 ] ) ;
2007-11-09 21:24:51 +03:00
NDR_ERR_HAVE_NO_MEMORY ( r - > scope ) ;
2005-04-14 06:36:30 +04:00
} else {
r - > scope = NULL ;
2005-01-21 09:54:10 +03:00
}
2005-04-14 06:36:30 +04:00
cname = discard_const_p ( char , s ) ;
2005-01-21 09:54:10 +03:00
/* the first component is limited to 16 bytes in the DOS charset,
which is 32 in the ' compressed ' form */
2005-04-14 06:36:30 +04:00
if ( strlen ( cname ) > 32 ) {
2007-11-03 12:20:45 +03:00
return ndr_pull_error ( ndr , NDR_ERR_STRING ,
" NBT NAME cname > 32 " ) ;
2005-01-21 09:54:10 +03:00
}
/* decompress the first component */
2007-11-03 12:20:45 +03:00
ok = decompress_name ( cname , & r - > type ) ;
if ( ! ok ) {
return ndr_pull_error ( ndr , NDR_ERR_STRING ,
" NBT NAME failed to decompress " ) ;
}
2005-01-21 09:54:10 +03:00
2005-09-29 18:00:07 +04:00
r - > name = talloc_strdup ( ndr - > current_mem_ctx , cname ) ;
2007-11-09 21:24:51 +03:00
NDR_ERR_HAVE_NO_MEMORY ( r - > name ) ;
2005-01-21 09:54:10 +03:00
2005-04-14 06:36:30 +04:00
talloc_free ( cname ) ;
2005-01-21 09:54:10 +03:00
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-01-21 09:54:10 +03:00
}
2006-03-05 20:15:19 +03:00
/**
2005-01-21 09:54:10 +03:00
push a nbt name to the wire
*/
2007-11-09 21:24:51 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_nbt_name ( struct ndr_push * ndr , int ndr_flags , const struct nbt_name * r )
2005-01-21 09:54:10 +03:00
{
2005-02-15 08:39:12 +03:00
uint8_t * cname , * fullname ;
2007-11-09 21:24:51 +03:00
enum ndr_err_code ndr_err ;
2005-01-21 09:54:10 +03:00
if ( ! ( ndr_flags & NDR_SCALARS ) ) {
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-01-21 09:54:10 +03:00
}
2007-02-28 20:23:35 +03:00
if ( strlen ( r - > name ) > 15 ) {
return ndr_push_error ( ndr , NDR_ERR_STRING ,
" nbt_name longer as 15 chars: %s " ,
r - > name ) ;
}
2006-01-18 18:46:00 +03:00
cname = compress_name ( ndr , ( const uint8_t * ) r - > name , r - > type ) ;
2007-11-09 21:24:51 +03:00
NDR_ERR_HAVE_NO_MEMORY ( cname ) ;
2005-01-21 09:54:10 +03:00
2005-04-14 06:36:30 +04:00
if ( r - > scope ) {
2006-01-18 18:46:00 +03:00
fullname = ( uint8_t * ) talloc_asprintf ( ndr , " %s.%s " , cname , r - > scope ) ;
2007-11-09 21:24:51 +03:00
NDR_ERR_HAVE_NO_MEMORY ( fullname ) ;
2005-04-14 06:36:30 +04:00
talloc_free ( cname ) ;
} else {
fullname = cname ;
2005-01-21 09:54:10 +03:00
}
2008-09-23 11:34:03 +04:00
2007-11-09 21:24:51 +03:00
ndr_err = ndr_push_nbt_string ( ndr , ndr_flags , ( const char * ) fullname ) ;
2005-09-29 18:00:07 +04:00
2007-11-09 21:24:51 +03:00
return ndr_err ;
2005-01-21 09:54:10 +03:00
}
2005-01-21 14:18:56 +03:00
2006-03-05 20:15:19 +03:00
/**
2005-01-21 14:18:56 +03:00
copy a nbt name structure
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS nbt_name_dup ( TALLOC_CTX * mem_ctx , struct nbt_name * name , struct nbt_name * newname )
2005-01-21 14:18:56 +03:00
{
* newname = * name ;
newname - > name = talloc_strdup ( mem_ctx , newname - > name ) ;
NT_STATUS_HAVE_NO_MEMORY ( newname - > name ) ;
newname - > scope = talloc_strdup ( mem_ctx , newname - > scope ) ;
if ( name - > scope ) {
NT_STATUS_HAVE_NO_MEMORY ( newname - > scope ) ;
}
return NT_STATUS_OK ;
}
2006-03-05 20:15:19 +03:00
/**
2005-01-21 14:18:56 +03:00
push a nbt name into a blob
*/
2008-02-21 16:50:57 +03:00
_PUBLIC_ NTSTATUS nbt_name_to_blob ( TALLOC_CTX * mem_ctx , struct smb_iconv_convenience * iconv_convenience , DATA_BLOB * blob , struct nbt_name * name )
2005-01-21 14:18:56 +03:00
{
2007-11-09 21:24:51 +03:00
enum ndr_err_code ndr_err ;
2005-01-21 14:18:56 +03:00
2008-02-21 16:50:57 +03:00
ndr_err = ndr_push_struct_blob ( blob , mem_ctx , iconv_convenience , name , ( ndr_push_flags_fn_t ) ndr_push_nbt_name ) ;
2007-11-09 21:24:51 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return ndr_map_error2ntstatus ( ndr_err ) ;
}
return NT_STATUS_OK ;
}
2005-01-22 08:36:32 +03:00
2006-03-05 20:15:19 +03:00
/**
2005-01-22 08:36:32 +03:00
pull a nbt name from a blob
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ NTSTATUS nbt_name_from_blob ( TALLOC_CTX * mem_ctx , const DATA_BLOB * blob , struct nbt_name * name )
2005-01-22 08:36:32 +03:00
{
2007-11-09 21:24:51 +03:00
enum ndr_err_code ndr_err ;
2008-01-02 07:05:13 +03:00
ndr_err = ndr_pull_struct_blob ( blob , mem_ctx , NULL , name ,
2007-11-09 21:24:51 +03:00
( ndr_pull_flags_fn_t ) ndr_pull_nbt_name ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return ndr_map_error2ntstatus ( ndr_err ) ;
}
return NT_STATUS_OK ;
2005-01-22 08:36:32 +03:00
}
2006-03-05 20:15:19 +03:00
/**
2005-01-21 14:18:56 +03:00
choose a name to use when calling a server in a NBT session request .
we use heuristics to see if the name we have been given is a IP
address , or a too - long name . If it is then use * SMBSERVER , or a
truncated name
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ void nbt_choose_called_name ( TALLOC_CTX * mem_ctx ,
2005-01-21 14:18:56 +03:00
struct nbt_name * n , const char * name , int type )
{
n - > scope = NULL ;
n - > type = type ;
2008-09-23 11:34:03 +04:00
if ( ( name = = NULL ) | | is_ipaddress ( name ) ) {
2005-01-21 14:18:56 +03:00
n - > name = " *SMBSERVER " ;
return ;
}
if ( strlen ( name ) > 15 ) {
const char * p = strchr ( name , ' . ' ) ;
2005-02-14 04:02:47 +03:00
char * s ;
2005-01-21 14:18:56 +03:00
if ( p - name > 15 ) {
n - > name = " *SMBSERVER " ;
return ;
}
2005-02-14 04:02:47 +03:00
s = talloc_strndup ( mem_ctx , name , PTR_DIFF ( p , name ) ) ;
2008-09-23 11:34:03 +04:00
n - > name = talloc_strdup_upper ( mem_ctx , s ) ;
2005-01-21 14:18:56 +03:00
return ;
}
2008-09-23 11:34:03 +04:00
n - > name = talloc_strdup_upper ( mem_ctx , name ) ;
2005-01-21 14:18:56 +03:00
}
2005-02-12 04:00:15 +03:00
/*
escape a string into a form containing only a small set of characters ,
the rest is hex encoded . This is similar to URL encoding
*/
static const char * nbt_hex_encode ( TALLOC_CTX * mem_ctx , const char * s )
{
int i , len ;
char * ret ;
2005-02-15 08:14:09 +03:00
const char * valid_chars = " _-.$@ " ;
2005-07-13 02:22:59 +04:00
# define NBT_CHAR_ALLOW(c) (isalnum((unsigned char)c) || strchr(valid_chars, c))
2005-02-12 04:00:15 +03:00
for ( len = i = 0 ; s [ i ] ; i + + , len + + ) {
2005-02-15 08:14:09 +03:00
if ( ! NBT_CHAR_ALLOW ( s [ i ] ) ) {
2005-02-12 04:00:15 +03:00
len + = 2 ;
}
}
ret = talloc_array ( mem_ctx , char , len + 1 ) ;
if ( ret = = NULL ) return NULL ;
for ( len = i = 0 ; s [ i ] ; i + + ) {
2005-02-15 08:14:09 +03:00
if ( NBT_CHAR_ALLOW ( s [ i ] ) ) {
2005-02-12 04:00:15 +03:00
ret [ len + + ] = s [ i ] ;
} else {
2005-02-12 06:10:50 +03:00
snprintf ( & ret [ len ] , 4 , " %%%02x " , ( unsigned char ) s [ i ] ) ;
2005-02-12 04:00:15 +03:00
len + = 3 ;
}
}
ret [ len ] = 0 ;
return ret ;
}
2006-03-05 20:15:19 +03:00
/**
2005-02-12 04:00:15 +03:00
form a string for a NBT name
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ char * nbt_name_string ( TALLOC_CTX * mem_ctx , const struct nbt_name * name )
2005-02-12 04:00:15 +03:00
{
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
2005-02-12 14:33:42 +03:00
char * ret ;
2008-09-23 11:34:03 +04:00
if ( name - > scope ) {
2005-02-12 04:00:15 +03:00
ret = talloc_asprintf ( mem_ctx , " %s<%02x>-%s " ,
nbt_hex_encode ( tmp_ctx , name - > name ) ,
2008-09-23 11:34:03 +04:00
name - > type ,
2005-02-12 04:00:15 +03:00
nbt_hex_encode ( tmp_ctx , name - > scope ) ) ;
} else {
2008-09-23 11:34:03 +04:00
ret = talloc_asprintf ( mem_ctx , " %s<%02x> " ,
nbt_hex_encode ( tmp_ctx , name - > name ) ,
2005-02-12 04:00:15 +03:00
name - > type ) ;
}
talloc_free ( tmp_ctx ) ;
return ret ;
}
2006-03-05 20:15:19 +03:00
/**
2005-09-29 18:00:07 +04:00
pull a nbt name , WINS Replication uses another on wire format for nbt name
*/
2008-04-02 06:53:27 +04:00
_PUBLIC_ enum ndr_err_code ndr_pull_wrepl_nbt_name ( struct ndr_pull * ndr , int ndr_flags , const struct nbt_name * * _r )
2005-09-29 18:00:07 +04:00
{
2005-10-06 11:26:05 +04:00
struct nbt_name * r ;
2005-09-29 18:00:07 +04:00
uint8_t * namebuf ;
uint32_t namebuf_len ;
if ( ! ( ndr_flags & NDR_SCALARS ) ) {
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-09-29 18:00:07 +04:00
}
NDR_CHECK ( ndr_pull_align ( ndr , 4 ) ) ;
NDR_CHECK ( ndr_pull_uint32 ( ndr , NDR_SCALARS , & namebuf_len ) ) ;
if ( namebuf_len < 1 | | namebuf_len > 255 ) {
return ndr_pull_error ( ndr , NDR_ERR_ALLOC , " value out of range " ) ;
}
NDR_PULL_ALLOC_N ( ndr , namebuf , namebuf_len ) ;
NDR_CHECK ( ndr_pull_array_uint8 ( ndr , NDR_SCALARS , namebuf , namebuf_len ) ) ;
2010-01-28 20:52:46 +03:00
if ( ( namebuf_len % 4 ) = = 0 ) {
/*
* [ MS - WINSRA ] — v20091104 was wrong
* regarding section " 2.2.10.1 Name Record "
*
* If the name buffer is already 4 byte aligned
* Windows ( at least 2003 SP1 and 2008 ) add 4 extra
* bytes . This can happen when the name has a scope .
*/
uint32_t pad ;
NDR_CHECK ( ndr_pull_uint32 ( ndr , NDR_SCALARS , & pad ) ) ;
}
2008-09-23 11:34:03 +04:00
NDR_PULL_ALLOC ( ndr , r ) ;
2005-10-06 11:26:05 +04:00
2005-09-29 18:00:07 +04:00
/* oh wow, what a nasty bug in windows ... */
if ( namebuf [ 0 ] = = 0x1b & & namebuf_len > = 16 ) {
namebuf [ 0 ] = namebuf [ 15 ] ;
namebuf [ 15 ] = 0x1b ;
}
if ( namebuf_len < 17 ) {
r - > type = 0x00 ;
2005-10-06 11:26:05 +04:00
r - > name = talloc_strndup ( r , ( char * ) namebuf , namebuf_len ) ;
2005-09-29 18:00:07 +04:00
if ( ! r - > name ) return ndr_pull_error ( ndr , NDR_ERR_ALLOC , " out of memory " ) ;
r - > scope = NULL ;
talloc_free ( namebuf ) ;
2005-10-06 11:26:05 +04:00
* _r = r ;
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-09-29 18:00:07 +04:00
}
r - > type = namebuf [ 15 ] ;
namebuf [ 15 ] = ' \0 ' ;
trim_string ( ( char * ) namebuf , NULL , " " ) ;
2005-10-06 11:26:05 +04:00
r - > name = talloc_strdup ( r , ( char * ) namebuf ) ;
2005-09-29 18:00:07 +04:00
if ( ! r - > name ) return ndr_pull_error ( ndr , NDR_ERR_ALLOC , " out of memory " ) ;
if ( namebuf_len > 18 ) {
2005-10-06 11:26:05 +04:00
r - > scope = talloc_strndup ( r , ( char * ) ( namebuf + 17 ) , namebuf_len - 17 ) ;
2005-09-29 18:00:07 +04:00
if ( ! r - > scope ) return ndr_pull_error ( ndr , NDR_ERR_ALLOC , " out of memory " ) ;
} else {
r - > scope = NULL ;
}
talloc_free ( namebuf ) ;
2005-10-06 11:26:05 +04:00
* _r = r ;
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-09-29 18:00:07 +04:00
}
2006-03-05 20:15:19 +03:00
/**
2005-09-29 18:00:07 +04:00
push a nbt name , WINS Replication uses another on wire format for nbt name
*/
2007-11-09 21:24:51 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_wrepl_nbt_name ( struct ndr_push * ndr , int ndr_flags , const struct nbt_name * r )
2005-09-29 18:00:07 +04:00
{
uint8_t * namebuf ;
uint32_t namebuf_len ;
2008-09-23 11:34:03 +04:00
uint32_t _name_len ;
2005-09-29 18:00:07 +04:00
uint32_t scope_len = 0 ;
2007-11-03 12:20:45 +03:00
if ( r = = NULL ) {
return ndr_push_error ( ndr , NDR_ERR_INVALID_POINTER ,
" wrepl_nbt_name NULL pointer " ) ;
}
2005-10-06 11:26:05 +04:00
2005-09-29 18:00:07 +04:00
if ( ! ( ndr_flags & NDR_SCALARS ) ) {
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-09-29 18:00:07 +04:00
}
2008-09-23 11:34:03 +04:00
_name_len = strlen ( r - > name ) ;
if ( _name_len > 15 ) {
2007-11-03 12:20:45 +03:00
return ndr_push_error ( ndr , NDR_ERR_STRING ,
" wrepl_nbt_name longer as 15 chars: %s " ,
r - > name ) ;
2005-09-29 18:00:07 +04:00
}
2005-10-06 11:26:05 +04:00
if ( r - > scope ) {
scope_len = strlen ( r - > scope ) ;
2005-09-29 18:00:07 +04:00
}
if ( scope_len > 238 ) {
2007-11-03 12:20:45 +03:00
return ndr_push_error ( ndr , NDR_ERR_STRING ,
" wrepl_nbt_name scope longer as 238 chars: %s " ,
r - > scope ) ;
2005-09-29 18:00:07 +04:00
}
namebuf = ( uint8_t * ) talloc_asprintf ( ndr , " %-15s%c%s " ,
2005-10-06 11:26:05 +04:00
r - > name , ' X ' ,
( r - > scope ? r - > scope : " " ) ) ;
2005-09-29 18:00:07 +04:00
if ( ! namebuf ) return ndr_push_error ( ndr , NDR_ERR_ALLOC , " out of memory " ) ;
namebuf_len = strlen ( ( char * ) namebuf ) + 1 ;
/*
* we need to set the type here , and use a place - holder in the talloc_asprintf ( )
* as the type can be 0x00 , and then the namebuf_len = strlen ( namebuf ) ; would give wrong results
*/
2005-10-06 11:26:05 +04:00
namebuf [ 15 ] = r - > type ;
2005-09-29 18:00:07 +04:00
/* oh wow, what a nasty bug in windows ... */
2005-10-06 11:26:05 +04:00
if ( r - > type = = 0x1b ) {
2005-09-29 18:00:07 +04:00
namebuf [ 15 ] = namebuf [ 0 ] ;
namebuf [ 0 ] = 0x1b ;
}
NDR_CHECK ( ndr_push_align ( ndr , 4 ) ) ;
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , namebuf_len ) ) ;
NDR_CHECK ( ndr_push_array_uint8 ( ndr , NDR_SCALARS , namebuf , namebuf_len ) ) ;
2010-01-28 20:52:46 +03:00
if ( ( namebuf_len % 4 ) = = 0 ) {
/*
* [ MS - WINSRA ] — v20091104 was wrong
* regarding section " 2.2.10.1 Name Record "
*
* If the name buffer is already 4 byte aligned
* Windows ( at least 2003 SP1 and 2008 ) add 4 extra
* bytes . This can happen when the name has a scope .
*/
NDR_CHECK ( ndr_push_zero ( ndr , 4 ) ) ;
}
2005-09-29 18:00:07 +04:00
talloc_free ( namebuf ) ;
2007-11-09 21:24:51 +03:00
return NDR_ERR_SUCCESS ;
2005-09-29 18:00:07 +04:00
}
2006-03-05 20:15:19 +03:00
_PUBLIC_ void ndr_print_wrepl_nbt_name ( struct ndr_print * ndr , const char * name , const struct nbt_name * r )
2005-09-29 18:00:07 +04:00
{
2005-10-06 11:26:05 +04:00
char * s = nbt_name_string ( ndr , r ) ;
2005-09-29 18:00:07 +04:00
ndr_print_string ( ndr , name , s ) ;
talloc_free ( s ) ;
}
2008-05-26 15:31:57 +04:00
_PUBLIC_ enum ndr_err_code ndr_push_nbt_res_rec ( struct ndr_push * ndr , int ndr_flags , const struct nbt_res_rec * r )
{
{
uint32_t _flags_save_STRUCT = ndr - > flags ;
ndr_set_flags ( & ndr - > flags , LIBNDR_PRINT_ARRAY_HEX ) ;
if ( ndr_flags & NDR_SCALARS ) {
NDR_CHECK ( ndr_push_align ( ndr , 4 ) ) ;
NDR_CHECK ( ndr_push_nbt_name ( ndr , NDR_SCALARS , & r - > name ) ) ;
NDR_CHECK ( ndr_push_nbt_qtype ( ndr , NDR_SCALARS , r - > rr_type ) ) ;
NDR_CHECK ( ndr_push_nbt_qclass ( ndr , NDR_SCALARS , r - > rr_class ) ) ;
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , r - > ttl ) ) ;
NDR_CHECK ( ndr_push_set_switch_value ( ndr , & r - > rdata , ( ( ( ( r - > rr_type ) = = NBT_QTYPE_NETBIOS ) & & ( ( r - > rdata ) . data . length = = 2 ) ) ? 0 : r - > rr_type ) ) ) ;
NDR_CHECK ( ndr_push_nbt_rdata ( ndr , NDR_SCALARS , & r - > rdata ) ) ;
}
if ( ndr_flags & NDR_BUFFERS ) {
}
ndr - > flags = _flags_save_STRUCT ;
}
return NDR_ERR_SUCCESS ;
}