2014-01-02 14:18:38 +04:00
/*
Unix SMB / CIFS implementation .
Manually parsed structures found in the DCERPC protocol
Copyright ( C ) Stefan Metzmacher 2014
Copyright ( C ) Gregor Beck 2014
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2014-01-17 15:13:50 +04:00
# include "librpc/gen_ndr/ndr_dcerpc.h"
2014-01-02 14:18:38 +04:00
# include "librpc/gen_ndr/ndr_misc.h"
2016-09-13 18:03:47 +03:00
_PUBLIC_ enum ndr_err_code ndr_push_ncacn_packet ( struct ndr_push * ndr , int ndr_flags , const struct ncacn_packet * r )
{
NDR_PUSH_CHECK_FLAGS ( ndr , ndr_flags ) ;
if ( ndr_flags & NDR_SCALARS ) {
NDR_CHECK ( ndr_push_align ( ndr , 4 ) ) ;
NDR_CHECK ( ndr_push_uint8 ( ndr , NDR_SCALARS , r - > rpc_vers ) ) ;
NDR_CHECK ( ndr_push_uint8 ( ndr , NDR_SCALARS , r - > rpc_vers_minor ) ) ;
NDR_CHECK ( ndr_push_dcerpc_pkt_type ( ndr , NDR_SCALARS , r - > ptype ) ) ;
NDR_CHECK ( ndr_push_dcerpc_pfc_flags ( ndr , NDR_SCALARS , r - > pfc_flags ) ) ;
NDR_CHECK ( ndr_push_array_uint8 ( ndr , NDR_SCALARS , r - > drep , 4 ) ) ;
if ( r - > pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID ) {
ndr - > flags | = LIBNDR_FLAG_OBJECT_PRESENT ;
}
if ( ! ( r - > drep [ 0 ] & DCERPC_DREP_LE ) ) {
ndr - > flags | = LIBNDR_FLAG_BIGENDIAN ;
}
NDR_CHECK ( ndr_push_uint16 ( ndr , NDR_SCALARS , r - > frag_length ) ) ;
NDR_CHECK ( ndr_push_uint16 ( ndr , NDR_SCALARS , r - > auth_length ) ) ;
NDR_CHECK ( ndr_push_uint32 ( ndr , NDR_SCALARS , r - > call_id ) ) ;
NDR_CHECK ( ndr_push_set_switch_value ( ndr , & r - > u , r - > ptype ) ) ;
NDR_CHECK ( ndr_push_dcerpc_payload ( ndr , NDR_SCALARS , & r - > u ) ) ;
NDR_CHECK ( ndr_push_trailer_align ( ndr , 4 ) ) ;
}
if ( ndr_flags & NDR_BUFFERS ) {
}
return NDR_ERR_SUCCESS ;
}
_PUBLIC_ enum ndr_err_code ndr_pull_ncacn_packet ( struct ndr_pull * ndr , int ndr_flags , struct ncacn_packet * r )
{
uint32_t size_drep_0 = 0 ;
NDR_PULL_CHECK_FLAGS ( ndr , ndr_flags ) ;
if ( ndr_flags & NDR_SCALARS ) {
NDR_CHECK ( ndr_pull_align ( ndr , 4 ) ) ;
NDR_CHECK ( ndr_pull_uint8 ( ndr , NDR_SCALARS , & r - > rpc_vers ) ) ;
NDR_CHECK ( ndr_pull_uint8 ( ndr , NDR_SCALARS , & r - > rpc_vers_minor ) ) ;
NDR_CHECK ( ndr_pull_dcerpc_pkt_type ( ndr , NDR_SCALARS , & r - > ptype ) ) ;
NDR_CHECK ( ndr_pull_dcerpc_pfc_flags ( ndr , NDR_SCALARS , & r - > pfc_flags ) ) ;
size_drep_0 = 4 ;
NDR_CHECK ( ndr_pull_array_uint8 ( ndr , NDR_SCALARS , r - > drep , size_drep_0 ) ) ;
if ( r - > pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID ) {
ndr - > flags | = LIBNDR_FLAG_OBJECT_PRESENT ;
}
if ( ! ( r - > drep [ 0 ] & DCERPC_DREP_LE ) ) {
ndr - > flags | = LIBNDR_FLAG_BIGENDIAN ;
}
NDR_CHECK ( ndr_pull_uint16 ( ndr , NDR_SCALARS , & r - > frag_length ) ) ;
NDR_CHECK ( ndr_pull_uint16 ( ndr , NDR_SCALARS , & r - > auth_length ) ) ;
NDR_CHECK ( ndr_pull_uint32 ( ndr , NDR_SCALARS , & r - > call_id ) ) ;
NDR_CHECK ( ndr_pull_set_switch_value ( ndr , & r - > u , r - > ptype ) ) ;
NDR_CHECK ( ndr_pull_dcerpc_payload ( ndr , NDR_SCALARS , & r - > u ) ) ;
NDR_CHECK ( ndr_pull_trailer_align ( ndr , 4 ) ) ;
}
if ( ndr_flags & NDR_BUFFERS ) {
}
return NDR_ERR_SUCCESS ;
}
_PUBLIC_ void ndr_print_ncacn_packet ( struct ndr_print * ndr , const char * name , const struct ncacn_packet * r )
{
ndr_print_struct ( ndr , name , " ncacn_packet " ) ;
if ( r = = NULL ) { ndr_print_null ( ndr ) ; return ; }
ndr - > depth + + ;
ndr_print_uint8 ( ndr , " rpc_vers " , r - > rpc_vers ) ;
ndr_print_uint8 ( ndr , " rpc_vers_minor " , r - > rpc_vers_minor ) ;
ndr_print_dcerpc_pkt_type ( ndr , " ptype " , r - > ptype ) ;
ndr_print_dcerpc_pfc_flags ( ndr , " pfc_flags " , r - > pfc_flags ) ;
ndr_print_array_uint8 ( ndr , " drep " , r - > drep , 4 ) ;
if ( r - > pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID ) {
ndr - > flags | = LIBNDR_FLAG_OBJECT_PRESENT ;
}
if ( ! ( r - > drep [ 0 ] & DCERPC_DREP_LE ) ) {
ndr - > flags | = LIBNDR_FLAG_BIGENDIAN ;
}
ndr_print_uint16 ( ndr , " frag_length " , r - > frag_length ) ;
ndr_print_uint16 ( ndr , " auth_length " , r - > auth_length ) ;
ndr_print_uint32 ( ndr , " call_id " , r - > call_id ) ;
ndr_print_set_switch_value ( ndr , & r - > u , r - > ptype ) ;
ndr_print_dcerpc_payload ( ndr , " u " , & r - > u ) ;
ndr - > depth - - ;
}
2015-10-21 13:01:26 +03:00
/*
* This function was generated by pidl and
* has been extended by the ( _available = = 0 ) check .
*
* That ' s why we ignore the 80 char per line limit .
*/
enum ndr_err_code ndr_pull_dcerpc_bind_nak ( struct ndr_pull * ndr , int ndr_flags , struct dcerpc_bind_nak * r )
{
uint32_t size_versions_0 = 0 ;
uint32_t cntr_versions_0 ;
TALLOC_CTX * _mem_save_versions_0 = NULL ;
NDR_PULL_CHECK_FLAGS ( ndr , ndr_flags ) ;
if ( ndr_flags & NDR_SCALARS ) {
uint32_t _available ;
NDR_CHECK ( ndr_pull_align ( ndr , 4 ) ) ;
NDR_CHECK ( ndr_pull_dcerpc_bind_nak_reason ( ndr , NDR_SCALARS , & r - > reject_reason ) ) ;
_available = ndr - > data_size - ndr - > offset ;
if ( _available = = 0 ) {
/*
* This works around a bug in older
* Samba ( < = 4.1 ) releases .
*
* See bug # 11327.
*/
r - > num_versions = 0 ;
} else {
NDR_CHECK ( ndr_pull_uint8 ( ndr , NDR_SCALARS , & r - > num_versions ) ) ;
}
size_versions_0 = r - > num_versions ;
NDR_PULL_ALLOC_N ( ndr , r - > versions , size_versions_0 ) ;
_mem_save_versions_0 = NDR_PULL_GET_MEM_CTX ( ndr ) ;
NDR_PULL_SET_MEM_CTX ( ndr , r - > versions , 0 ) ;
for ( cntr_versions_0 = 0 ; cntr_versions_0 < ( size_versions_0 ) ; cntr_versions_0 + + ) {
NDR_CHECK ( ndr_pull_dcerpc_bind_nak_version ( ndr , NDR_SCALARS , & r - > versions [ cntr_versions_0 ] ) ) ;
}
NDR_PULL_SET_MEM_CTX ( ndr , _mem_save_versions_0 , 0 ) ;
{
uint32_t _flags_save_DATA_BLOB = ndr - > flags ;
ndr_set_flags ( & ndr - > flags , LIBNDR_FLAG_REMAINING ) ;
NDR_CHECK ( ndr_pull_DATA_BLOB ( ndr , NDR_SCALARS , & r - > _pad ) ) ;
ndr - > flags = _flags_save_DATA_BLOB ;
}
NDR_CHECK ( ndr_pull_trailer_align ( ndr , 4 ) ) ;
}
if ( ndr_flags & NDR_BUFFERS ) {
}
return NDR_ERR_SUCCESS ;
}
2014-01-02 14:18:38 +04:00
const uint8_t DCERPC_SEC_VT_MAGIC [ ] = { 0x8a , 0xe3 , 0x13 , 0x71 , 0x02 , 0xf4 , 0x36 , 0x71 } ;
_PUBLIC_ enum ndr_err_code ndr_push_dcerpc_sec_vt_count ( struct ndr_push * ndr , int ndr_flags , const struct dcerpc_sec_vt_count * r )
{
NDR_PUSH_CHECK_FLAGS ( ndr , ndr_flags ) ;
/* nothing */
return NDR_ERR_SUCCESS ;
}
_PUBLIC_ enum ndr_err_code ndr_pull_dcerpc_sec_vt_count ( struct ndr_pull * ndr , int ndr_flags , struct dcerpc_sec_vt_count * r )
{
uint32_t _saved_ofs = ndr - > offset ;
NDR_PULL_CHECK_FLAGS ( ndr , ndr_flags ) ;
if ( ! ( ndr_flags & NDR_SCALARS ) ) {
return NDR_ERR_SUCCESS ;
}
r - > count = 0 ;
while ( true ) {
uint16_t command ;
uint16_t length ;
NDR_CHECK ( ndr_pull_uint16 ( ndr , NDR_SCALARS , & command ) ) ;
NDR_CHECK ( ndr_pull_uint16 ( ndr , NDR_SCALARS , & length ) ) ;
NDR_CHECK ( ndr_pull_advance ( ndr , length ) ) ;
r - > count + = 1 ;
if ( command & DCERPC_SEC_VT_COMMAND_END ) {
break ;
}
}
ndr - > offset = _saved_ofs ;
return NDR_ERR_SUCCESS ;
}
2014-01-02 18:30:52 +04:00
_PUBLIC_ enum ndr_err_code ndr_pop_dcerpc_sec_verification_trailer (
struct ndr_pull * ndr , TALLOC_CTX * mem_ctx ,
struct dcerpc_sec_verification_trailer * * _r )
{
enum ndr_err_code ndr_err ;
uint32_t ofs ;
uint32_t min_ofs = 0 ;
struct dcerpc_sec_verification_trailer * r ;
DATA_BLOB sub_blob = data_blob_null ;
struct ndr_pull * sub_ndr = NULL ;
uint32_t remaining ;
* _r = NULL ;
r = talloc_zero ( mem_ctx , struct dcerpc_sec_verification_trailer ) ;
if ( r = = NULL ) {
return NDR_ERR_ALLOC ;
}
if ( ndr - > data_size < sizeof ( DCERPC_SEC_VT_MAGIC ) ) {
/*
* we return with r - > count = 0
*/
* _r = r ;
return NDR_ERR_SUCCESS ;
}
ofs = ndr - > data_size - sizeof ( DCERPC_SEC_VT_MAGIC ) ;
/* the magic is 4 byte aligned */
ofs & = ~ 3 ;
if ( ofs > DCERPC_SEC_VT_MAX_SIZE ) {
/*
* We just scan the last 1024 bytes .
*/
min_ofs = ofs - DCERPC_SEC_VT_MAX_SIZE ;
} else {
min_ofs = 0 ;
}
while ( true ) {
int ret ;
ret = memcmp ( & ndr - > data [ ofs ] ,
DCERPC_SEC_VT_MAGIC ,
sizeof ( DCERPC_SEC_VT_MAGIC ) ) ;
if ( ret = = 0 ) {
sub_blob = data_blob_const ( & ndr - > data [ ofs ] ,
ndr - > data_size - ofs ) ;
break ;
}
if ( ofs < = min_ofs ) {
break ;
}
ofs - = 4 ;
}
if ( sub_blob . length = = 0 ) {
/*
* we return with r - > count = 0
*/
* _r = r ;
return NDR_ERR_SUCCESS ;
}
sub_ndr = ndr_pull_init_blob ( & sub_blob , r ) ;
if ( sub_ndr = = NULL ) {
TALLOC_FREE ( r ) ;
return NDR_ERR_ALLOC ;
}
ndr_err = ndr_pull_dcerpc_sec_verification_trailer ( sub_ndr ,
NDR_SCALARS | NDR_BUFFERS ,
r ) ;
if ( ndr_err = = NDR_ERR_ALLOC ) {
TALLOC_FREE ( r ) ;
return NDR_ERR_ALLOC ;
}
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
goto ignore_error ;
}
remaining = sub_ndr - > data_size - sub_ndr - > offset ;
if ( remaining > 16 ) {
/*
* we expect not more than 16 byte of additional
* padding after the verification trailer .
*/
goto ignore_error ;
}
/*
* We assume that we got a real verification trailer .
*
* We remove it from the available stub data .
*/
ndr - > data_size = ofs ;
TALLOC_FREE ( sub_ndr ) ;
* _r = r ;
return NDR_ERR_SUCCESS ;
ignore_error :
TALLOC_FREE ( sub_ndr ) ;
/*
* just ignore the error , it ' s likely
* that the magic we found belongs to
* the stub data .
*
* we return with r - > count = 0
*/
ZERO_STRUCTP ( r ) ;
* _r = r ;
return NDR_ERR_SUCCESS ;
}