2010-07-16 01:45:29 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1998-03-12 00:11:04 +03:00
Samba memory buffer functions
1999-12-13 16:27:58 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1997
Copyright ( C ) Luke Kenneth Casson Leighton 1996 - 1997
2003-10-02 01:18:32 +04:00
Copyright ( C ) Jeremy Allison 1999
Copyright ( C ) Andrew Bartlett 2003.
2010-07-16 01:45:29 +04:00
1998-03-12 00:11:04 +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-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1998-03-12 00:11:04 +03:00
( at your option ) any later version .
2010-07-16 01:45:29 +04:00
1998-03-12 00:11:04 +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 .
2010-07-16 01:45:29 +04:00
1998-03-12 00:11:04 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1998-03-12 00:11:04 +03:00
*/
# include "includes.h"
2010-07-16 01:45:29 +04:00
# include "reg_parse_prs.h"
2010-08-18 20:26:17 +04:00
# include "rpc_dce.h"
1998-03-12 00:11:04 +03:00
2002-07-15 14:35:28 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_RPC_PARSE
2023-01-03 21:14:24 +03:00
static const char * tab_depth ( int level , int depth )
{
if ( CHECK_DEBUGLVL ( level ) ) {
dbgtext ( " %*s " , depth * 4 , " " ) ;
}
return " " ;
}
1998-03-12 00:11:04 +03:00
/*******************************************************************
2005-09-30 21:13:37 +04:00
Debug output for parsing info
1998-03-12 00:11:04 +03:00
2005-09-30 21:13:37 +04:00
XXXX side - effect of this function is to increase the debug depth XXXX .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-03-12 00:11:04 +03:00
2003-01-03 11:28:12 +03:00
void prs_debug ( prs_struct * ps , int depth , const char * desc , const char * fn_name )
1998-03-12 00:11:04 +03:00
{
2007-12-18 03:20:44 +03:00
DEBUG ( 5 + depth , ( " %s%06x %s %s \n " , tab_depth ( 5 + depth , depth ) , ps - > data_offset , fn_name , desc ) ) ;
1998-03-12 00:11:04 +03:00
}
2001-11-15 09:03:22 +03:00
/**
* Initialise an expandable parse structure .
*
* @ param size Initial buffer size . If > 0 , a new buffer will be
2010-06-18 02:35:07 +04:00
* created with talloc ( ) .
2001-11-15 09:03:22 +03:00
*
* @ return False if allocation fails , otherwise True .
* */
2005-09-30 21:13:37 +04:00
2015-04-14 17:50:28 +03:00
bool prs_init ( prs_struct * ps , uint32_t size , TALLOC_CTX * ctx , bool io )
1999-12-06 03:44:32 +03:00
{
1999-12-13 16:27:58 +03:00
ZERO_STRUCTP ( ps ) ;
ps - > io = io ;
2001-03-10 02:48:58 +03:00
ps - > bigendian_data = RPC_LITTLE_ENDIAN ;
ps - > align = RPC_PARSE_ALIGN ;
1999-12-13 16:27:58 +03:00
ps - > is_dynamic = False ;
ps - > data_offset = 0 ;
ps - > buffer_size = 0 ;
ps - > data_p = NULL ;
2000-07-27 04:47:19 +04:00
ps - > mem_ctx = ctx ;
1999-12-13 16:27:58 +03:00
if ( size ! = 0 ) {
ps - > buffer_size = size ;
2010-07-07 16:56:14 +04:00
ps - > data_p = ( char * ) talloc_zero_size ( ps - > mem_ctx , size ) ;
2010-06-18 02:35:07 +04:00
if ( ps - > data_p = = NULL ) {
DEBUG ( 0 , ( " prs_init: talloc fail for %u bytes. \n " , ( unsigned int ) size ) ) ;
1999-12-13 16:27:58 +03:00
return False ;
}
ps - > is_dynamic = True ; /* We own this memory. */
2005-09-30 21:13:37 +04:00
} else if ( MARSHALLING ( ps ) ) {
/* If size is zero and we're marshalling we should allocate memory on demand. */
ps - > is_dynamic = True ;
1999-12-13 16:27:58 +03:00
}
return True ;
1999-12-06 03:44:32 +03:00
}
1998-03-12 00:11:04 +03:00
/*******************************************************************
1999-12-13 16:27:58 +03:00
Delete the memory in a parse structure - if we own it .
2007-08-14 18:27:42 +04:00
NOTE : Contrary to the somewhat confusing naming , this function is not
2010-06-18 02:35:07 +04:00
intended for freeing memory allocated by prs_alloc_mem ( ) .
That memory is also attached to the talloc context given by
ps - > mem_ctx , but is only freed when that talloc context is
freed . prs_mem_free ( ) is used to delete " dynamic " memory
allocated in marshalling / unmarshalling .
1998-03-12 00:11:04 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
void prs_mem_free ( prs_struct * ps )
1998-03-12 00:11:04 +03:00
{
2010-06-18 02:35:07 +04:00
if ( ps - > is_dynamic ) {
TALLOC_FREE ( ps - > data_p ) ;
}
1999-12-13 16:27:58 +03:00
ps - > is_dynamic = False ;
ps - > buffer_size = 0 ;
ps - > data_offset = 0 ;
}
1998-03-12 00:11:04 +03:00
2000-07-27 04:47:19 +04:00
/*******************************************************************
2001-02-27 05:09:50 +03:00
Allocate memory when unmarshalling . . . Always zero clears .
2000-07-27 04:47:19 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-12-07 21:25:53 +03:00
# if defined(PARANOID_MALLOC_CHECKER)
char * prs_alloc_mem_ ( prs_struct * ps , size_t size , unsigned int count )
# else
char * prs_alloc_mem ( prs_struct * ps , size_t size , unsigned int count )
# endif
2000-07-27 04:47:19 +04:00
{
2003-02-15 01:55:46 +03:00
char * ret = NULL ;
2001-02-27 05:09:50 +03:00
2007-04-28 03:18:41 +04:00
if ( size & & count ) {
2004-12-07 21:25:53 +03:00
/* We can't call the type-safe version here. */
2007-08-29 05:23:31 +04:00
ret = ( char * ) _talloc_zero_array ( ps - > mem_ctx , size , count ,
2006-07-30 20:36:56 +04:00
" parse_prs " ) ;
2003-02-15 01:55:46 +03:00
}
2001-02-27 05:09:50 +03:00
return ret ;
2000-07-27 04:47:19 +04:00
}
/*******************************************************************
Return the current talloc context we ' re using .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
TALLOC_CTX * prs_get_mem_context ( prs_struct * ps )
{
return ps - > mem_ctx ;
}
1999-12-13 16:27:58 +03:00
/*******************************************************************
Attempt , if needed , to grow a data buffer .
Also depends on the data stream mode ( io ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-04-14 17:50:28 +03:00
bool prs_grow ( prs_struct * ps , uint32_t extra_space )
1999-12-13 16:27:58 +03:00
{
2015-04-14 17:50:28 +03:00
uint32_t new_size ;
1999-12-13 16:27:58 +03:00
2000-05-15 13:58:58 +04:00
ps - > grow_size = MAX ( ps - > grow_size , ps - > data_offset + extra_space ) ;
1999-12-13 16:27:58 +03:00
if ( ps - > data_offset + extra_space < = ps - > buffer_size )
return True ;
/*
* We cannot grow the buffer if we ' re not reading
* into the prs_struct , or if we don ' t own the memory .
*/
if ( UNMARSHALLING ( ps ) | | ! ps - > is_dynamic ) {
DEBUG ( 0 , ( " prs_grow: Buffer overflow - unable to expand buffer by %u bytes. \n " ,
( unsigned int ) extra_space ) ) ;
delineation between smb and msrpc more marked. smbd now constructs
pdus, and then feeds them over either a "local" function call or a "remote"
function call to an msrpc service. the "remote" msrpc daemon, on the
other side of a unix socket, then calls the same "local" function that
smbd would, if the msrpc service were being run from inside smbd.
this allows a transition from local msrpc services (inside the same smbd
process) to remote (over a unix socket).
removed reference to pipes_struct in msrpc services. all msrpc processing
functions take rpcsrv_struct which is a structure containing state info
for the msrpc functions to decode and create pdus.
created become_vuser() which does everything not related to connection_struct
that become_user() does.
removed, as best i could, connection_struct dependencies from the nt spoolss
printing code.
todo: remove dcinfo from rpcsrv_struct because this stores NETLOGON-specific
info on a per-connection basis, and if the connection dies then so does
the info, and that's a fairly serious problem.
had to put pretty much everything that is in user_struct into parse_creds.c
to feed unix user info over to the msrpc daemons. why? because it's
expensive to do unix password/group database lookups, and it's definitely
expensive to do nt user profile lookups, not to mention pretty difficult
and if you did either of these it would introduce a complication /
unnecessary interdependency. so, send uid/gid/num_groups/gid_t* +
SID+num_rids+domain_group_rids* + unix username + nt username + nt domain
+ user session key etc. this is the MINIMUM info identified so far that's
actually implemented. missing bits include the called and calling
netbios names etc. (basically, anything that can be loaded into
standard_sub() and standard_sub_basic()...)
(This used to be commit aa3c659a8dba0437c17c60055a6ed30fdfecdb6d)
1999-12-12 04:25:49 +03:00
return False ;
}
2010-07-16 01:45:29 +04:00
1999-12-13 16:27:58 +03:00
/*
* Decide how much extra space we really need .
*/
extra_space - = ( ps - > buffer_size - ps - > data_offset ) ;
if ( ps - > buffer_size = = 0 ) {
2009-02-08 01:36:23 +03:00
1999-12-13 16:27:58 +03:00
/*
2009-02-08 01:36:23 +03:00
* Start with 128 bytes ( arbitrary value ) , enough for small rpc
* requests
1999-12-13 16:27:58 +03:00
*/
2009-02-08 01:36:23 +03:00
new_size = MAX ( 128 , extra_space ) ;
1999-12-13 16:27:58 +03:00
2010-06-18 02:35:07 +04:00
ps - > data_p = ( char * ) talloc_zero_size ( ps - > mem_ctx , new_size ) ;
if ( ps - > data_p = = NULL ) {
DEBUG ( 0 , ( " prs_grow: talloc failure for size %u. \n " , ( unsigned int ) new_size ) ) ;
1999-12-13 16:27:58 +03:00
return False ;
}
} else {
/*
2009-02-08 01:36:23 +03:00
* If the current buffer size is bigger than the space needed ,
* just double it , else add extra_space . Always keep 64 bytes
* more , so that after we added a large blob we don ' t have to
* realloc immediately again .
1999-12-13 16:27:58 +03:00
*/
2009-02-08 01:36:23 +03:00
new_size = MAX ( ps - > buffer_size * 2 ,
ps - > buffer_size + extra_space + 64 ) ;
1999-12-13 16:27:58 +03:00
2010-06-18 02:35:07 +04:00
ps - > data_p = talloc_realloc ( ps - > mem_ctx ,
ps - > data_p ,
char ,
new_size ) ;
if ( ps - > data_p = = NULL ) {
1999-12-13 16:27:58 +03:00
DEBUG ( 0 , ( " prs_grow: Realloc failure for size %u. \n " ,
( unsigned int ) new_size ) ) ;
return False ;
}
2000-05-17 07:12:56 +04:00
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
memset ( & ps - > data_p [ ps - > buffer_size ] , ' \0 ' , ( size_t ) ( new_size - ps - > buffer_size ) ) ;
1999-12-13 16:27:58 +03:00
}
ps - > buffer_size = new_size ;
delineation between smb and msrpc more marked. smbd now constructs
pdus, and then feeds them over either a "local" function call or a "remote"
function call to an msrpc service. the "remote" msrpc daemon, on the
other side of a unix socket, then calls the same "local" function that
smbd would, if the msrpc service were being run from inside smbd.
this allows a transition from local msrpc services (inside the same smbd
process) to remote (over a unix socket).
removed reference to pipes_struct in msrpc services. all msrpc processing
functions take rpcsrv_struct which is a structure containing state info
for the msrpc functions to decode and create pdus.
created become_vuser() which does everything not related to connection_struct
that become_user() does.
removed, as best i could, connection_struct dependencies from the nt spoolss
printing code.
todo: remove dcinfo from rpcsrv_struct because this stores NETLOGON-specific
info on a per-connection basis, and if the connection dies then so does
the info, and that's a fairly serious problem.
had to put pretty much everything that is in user_struct into parse_creds.c
to feed unix user info over to the msrpc daemons. why? because it's
expensive to do unix password/group database lookups, and it's definitely
expensive to do nt user profile lookups, not to mention pretty difficult
and if you did either of these it would introduce a complication /
unnecessary interdependency. so, send uid/gid/num_groups/gid_t* +
SID+num_rids+domain_group_rids* + unix username + nt username + nt domain
+ user session key etc. this is the MINIMUM info identified so far that's
actually implemented. missing bits include the called and calling
netbios names etc. (basically, anything that can be loaded into
standard_sub() and standard_sub_basic()...)
(This used to be commit aa3c659a8dba0437c17c60055a6ed30fdfecdb6d)
1999-12-12 04:25:49 +03:00
return True ;
}
1998-10-07 19:22:49 +04:00
/*******************************************************************
1999-12-13 16:27:58 +03:00
Get the data pointer ( external interface ) .
2003-02-15 01:55:46 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
delineation between smb and msrpc more marked. smbd now constructs
pdus, and then feeds them over either a "local" function call or a "remote"
function call to an msrpc service. the "remote" msrpc daemon, on the
other side of a unix socket, then calls the same "local" function that
smbd would, if the msrpc service were being run from inside smbd.
this allows a transition from local msrpc services (inside the same smbd
process) to remote (over a unix socket).
removed reference to pipes_struct in msrpc services. all msrpc processing
functions take rpcsrv_struct which is a structure containing state info
for the msrpc functions to decode and create pdus.
created become_vuser() which does everything not related to connection_struct
that become_user() does.
removed, as best i could, connection_struct dependencies from the nt spoolss
printing code.
todo: remove dcinfo from rpcsrv_struct because this stores NETLOGON-specific
info on a per-connection basis, and if the connection dies then so does
the info, and that's a fairly serious problem.
had to put pretty much everything that is in user_struct into parse_creds.c
to feed unix user info over to the msrpc daemons. why? because it's
expensive to do unix password/group database lookups, and it's definitely
expensive to do nt user profile lookups, not to mention pretty difficult
and if you did either of these it would introduce a complication /
unnecessary interdependency. so, send uid/gid/num_groups/gid_t* +
SID+num_rids+domain_group_rids* + unix username + nt username + nt domain
+ user session key etc. this is the MINIMUM info identified so far that's
actually implemented. missing bits include the called and calling
netbios names etc. (basically, anything that can be loaded into
standard_sub() and standard_sub_basic()...)
(This used to be commit aa3c659a8dba0437c17c60055a6ed30fdfecdb6d)
1999-12-12 04:25:49 +03:00
1999-12-13 16:27:58 +03:00
char * prs_data_p ( prs_struct * ps )
{
return ps - > data_p ;
1998-10-07 19:22:49 +04:00
}
1998-03-12 00:11:04 +03:00
/*******************************************************************
1999-12-13 16:27:58 +03:00
Get the current data size ( external interface ) .
1998-03-12 00:11:04 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2015-04-14 17:50:28 +03:00
uint32_t prs_data_size ( prs_struct * ps )
1998-03-12 00:11:04 +03:00
{
1999-12-13 16:27:58 +03:00
return ps - > buffer_size ;
1998-03-12 00:11:04 +03:00
}
/*******************************************************************
1999-12-13 16:27:58 +03:00
Fetch the current offset ( external interface ) .
1998-03-12 00:11:04 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2015-04-14 17:50:28 +03:00
uint32_t prs_offset ( prs_struct * ps )
1998-03-12 00:11:04 +03:00
{
1999-12-13 16:27:58 +03:00
return ps - > data_offset ;
1998-03-12 00:11:04 +03:00
}
delineation between smb and msrpc more marked. smbd now constructs
pdus, and then feeds them over either a "local" function call or a "remote"
function call to an msrpc service. the "remote" msrpc daemon, on the
other side of a unix socket, then calls the same "local" function that
smbd would, if the msrpc service were being run from inside smbd.
this allows a transition from local msrpc services (inside the same smbd
process) to remote (over a unix socket).
removed reference to pipes_struct in msrpc services. all msrpc processing
functions take rpcsrv_struct which is a structure containing state info
for the msrpc functions to decode and create pdus.
created become_vuser() which does everything not related to connection_struct
that become_user() does.
removed, as best i could, connection_struct dependencies from the nt spoolss
printing code.
todo: remove dcinfo from rpcsrv_struct because this stores NETLOGON-specific
info on a per-connection basis, and if the connection dies then so does
the info, and that's a fairly serious problem.
had to put pretty much everything that is in user_struct into parse_creds.c
to feed unix user info over to the msrpc daemons. why? because it's
expensive to do unix password/group database lookups, and it's definitely
expensive to do nt user profile lookups, not to mention pretty difficult
and if you did either of these it would introduce a complication /
unnecessary interdependency. so, send uid/gid/num_groups/gid_t* +
SID+num_rids+domain_group_rids* + unix username + nt username + nt domain
+ user session key etc. this is the MINIMUM info identified so far that's
actually implemented. missing bits include the called and calling
netbios names etc. (basically, anything that can be loaded into
standard_sub() and standard_sub_basic()...)
(This used to be commit aa3c659a8dba0437c17c60055a6ed30fdfecdb6d)
1999-12-12 04:25:49 +03:00
/*******************************************************************
1999-12-13 16:27:58 +03:00
Set the current offset ( external interface ) .
delineation between smb and msrpc more marked. smbd now constructs
pdus, and then feeds them over either a "local" function call or a "remote"
function call to an msrpc service. the "remote" msrpc daemon, on the
other side of a unix socket, then calls the same "local" function that
smbd would, if the msrpc service were being run from inside smbd.
this allows a transition from local msrpc services (inside the same smbd
process) to remote (over a unix socket).
removed reference to pipes_struct in msrpc services. all msrpc processing
functions take rpcsrv_struct which is a structure containing state info
for the msrpc functions to decode and create pdus.
created become_vuser() which does everything not related to connection_struct
that become_user() does.
removed, as best i could, connection_struct dependencies from the nt spoolss
printing code.
todo: remove dcinfo from rpcsrv_struct because this stores NETLOGON-specific
info on a per-connection basis, and if the connection dies then so does
the info, and that's a fairly serious problem.
had to put pretty much everything that is in user_struct into parse_creds.c
to feed unix user info over to the msrpc daemons. why? because it's
expensive to do unix password/group database lookups, and it's definitely
expensive to do nt user profile lookups, not to mention pretty difficult
and if you did either of these it would introduce a complication /
unnecessary interdependency. so, send uid/gid/num_groups/gid_t* +
SID+num_rids+domain_group_rids* + unix username + nt username + nt domain
+ user session key etc. this is the MINIMUM info identified so far that's
actually implemented. missing bits include the called and calling
netbios names etc. (basically, anything that can be loaded into
standard_sub() and standard_sub_basic()...)
(This used to be commit aa3c659a8dba0437c17c60055a6ed30fdfecdb6d)
1999-12-12 04:25:49 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2015-04-14 17:50:28 +03:00
bool prs_set_offset ( prs_struct * ps , uint32_t offset )
delineation between smb and msrpc more marked. smbd now constructs
pdus, and then feeds them over either a "local" function call or a "remote"
function call to an msrpc service. the "remote" msrpc daemon, on the
other side of a unix socket, then calls the same "local" function that
smbd would, if the msrpc service were being run from inside smbd.
this allows a transition from local msrpc services (inside the same smbd
process) to remote (over a unix socket).
removed reference to pipes_struct in msrpc services. all msrpc processing
functions take rpcsrv_struct which is a structure containing state info
for the msrpc functions to decode and create pdus.
created become_vuser() which does everything not related to connection_struct
that become_user() does.
removed, as best i could, connection_struct dependencies from the nt spoolss
printing code.
todo: remove dcinfo from rpcsrv_struct because this stores NETLOGON-specific
info on a per-connection basis, and if the connection dies then so does
the info, and that's a fairly serious problem.
had to put pretty much everything that is in user_struct into parse_creds.c
to feed unix user info over to the msrpc daemons. why? because it's
expensive to do unix password/group database lookups, and it's definitely
expensive to do nt user profile lookups, not to mention pretty difficult
and if you did either of these it would introduce a complication /
unnecessary interdependency. so, send uid/gid/num_groups/gid_t* +
SID+num_rids+domain_group_rids* + unix username + nt username + nt domain
+ user session key etc. this is the MINIMUM info identified so far that's
actually implemented. missing bits include the called and calling
netbios names etc. (basically, anything that can be loaded into
standard_sub() and standard_sub_basic()...)
(This used to be commit aa3c659a8dba0437c17c60055a6ed30fdfecdb6d)
1999-12-12 04:25:49 +03:00
{
2009-01-17 19:52:22 +03:00
if ( ( offset > ps - > data_offset )
& & ! prs_grow ( ps , offset - ps - > data_offset ) ) {
delineation between smb and msrpc more marked. smbd now constructs
pdus, and then feeds them over either a "local" function call or a "remote"
function call to an msrpc service. the "remote" msrpc daemon, on the
other side of a unix socket, then calls the same "local" function that
smbd would, if the msrpc service were being run from inside smbd.
this allows a transition from local msrpc services (inside the same smbd
process) to remote (over a unix socket).
removed reference to pipes_struct in msrpc services. all msrpc processing
functions take rpcsrv_struct which is a structure containing state info
for the msrpc functions to decode and create pdus.
created become_vuser() which does everything not related to connection_struct
that become_user() does.
removed, as best i could, connection_struct dependencies from the nt spoolss
printing code.
todo: remove dcinfo from rpcsrv_struct because this stores NETLOGON-specific
info on a per-connection basis, and if the connection dies then so does
the info, and that's a fairly serious problem.
had to put pretty much everything that is in user_struct into parse_creds.c
to feed unix user info over to the msrpc daemons. why? because it's
expensive to do unix password/group database lookups, and it's definitely
expensive to do nt user profile lookups, not to mention pretty difficult
and if you did either of these it would introduce a complication /
unnecessary interdependency. so, send uid/gid/num_groups/gid_t* +
SID+num_rids+domain_group_rids* + unix username + nt username + nt domain
+ user session key etc. this is the MINIMUM info identified so far that's
actually implemented. missing bits include the called and calling
netbios names etc. (basically, anything that can be loaded into
standard_sub() and standard_sub_basic()...)
(This used to be commit aa3c659a8dba0437c17c60055a6ed30fdfecdb6d)
1999-12-12 04:25:49 +03:00
return False ;
2009-01-17 19:52:22 +03:00
}
delineation between smb and msrpc more marked. smbd now constructs
pdus, and then feeds them over either a "local" function call or a "remote"
function call to an msrpc service. the "remote" msrpc daemon, on the
other side of a unix socket, then calls the same "local" function that
smbd would, if the msrpc service were being run from inside smbd.
this allows a transition from local msrpc services (inside the same smbd
process) to remote (over a unix socket).
removed reference to pipes_struct in msrpc services. all msrpc processing
functions take rpcsrv_struct which is a structure containing state info
for the msrpc functions to decode and create pdus.
created become_vuser() which does everything not related to connection_struct
that become_user() does.
removed, as best i could, connection_struct dependencies from the nt spoolss
printing code.
todo: remove dcinfo from rpcsrv_struct because this stores NETLOGON-specific
info on a per-connection basis, and if the connection dies then so does
the info, and that's a fairly serious problem.
had to put pretty much everything that is in user_struct into parse_creds.c
to feed unix user info over to the msrpc daemons. why? because it's
expensive to do unix password/group database lookups, and it's definitely
expensive to do nt user profile lookups, not to mention pretty difficult
and if you did either of these it would introduce a complication /
unnecessary interdependency. so, send uid/gid/num_groups/gid_t* +
SID+num_rids+domain_group_rids* + unix username + nt username + nt domain
+ user session key etc. this is the MINIMUM info identified so far that's
actually implemented. missing bits include the called and calling
netbios names etc. (basically, anything that can be loaded into
standard_sub() and standard_sub_basic()...)
(This used to be commit aa3c659a8dba0437c17c60055a6ed30fdfecdb6d)
1999-12-12 04:25:49 +03:00
1999-12-13 16:27:58 +03:00
ps - > data_offset = offset ;
delineation between smb and msrpc more marked. smbd now constructs
pdus, and then feeds them over either a "local" function call or a "remote"
function call to an msrpc service. the "remote" msrpc daemon, on the
other side of a unix socket, then calls the same "local" function that
smbd would, if the msrpc service were being run from inside smbd.
this allows a transition from local msrpc services (inside the same smbd
process) to remote (over a unix socket).
removed reference to pipes_struct in msrpc services. all msrpc processing
functions take rpcsrv_struct which is a structure containing state info
for the msrpc functions to decode and create pdus.
created become_vuser() which does everything not related to connection_struct
that become_user() does.
removed, as best i could, connection_struct dependencies from the nt spoolss
printing code.
todo: remove dcinfo from rpcsrv_struct because this stores NETLOGON-specific
info on a per-connection basis, and if the connection dies then so does
the info, and that's a fairly serious problem.
had to put pretty much everything that is in user_struct into parse_creds.c
to feed unix user info over to the msrpc daemons. why? because it's
expensive to do unix password/group database lookups, and it's definitely
expensive to do nt user profile lookups, not to mention pretty difficult
and if you did either of these it would introduce a complication /
unnecessary interdependency. so, send uid/gid/num_groups/gid_t* +
SID+num_rids+domain_group_rids* + unix username + nt username + nt domain
+ user session key etc. this is the MINIMUM info identified so far that's
actually implemented. missing bits include the called and calling
netbios names etc. (basically, anything that can be loaded into
standard_sub() and standard_sub_basic()...)
(This used to be commit aa3c659a8dba0437c17c60055a6ed30fdfecdb6d)
1999-12-12 04:25:49 +03:00
return True ;
}
1998-03-12 00:11:04 +03:00
/*******************************************************************
1999-12-13 16:27:58 +03:00
Append the data from a buffer into a parse_struct .
1998-03-12 00:11:04 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2015-04-14 17:50:28 +03:00
bool prs_copy_data_in ( prs_struct * dst , const char * src , uint32_t len )
1998-03-12 00:11:04 +03:00
{
2003-02-15 01:55:46 +03:00
if ( len = = 0 )
return True ;
2000-05-17 23:17:16 +04:00
if ( ! prs_grow ( dst , len ) )
1999-10-16 00:00:30 +04:00
return False ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
memcpy ( & dst - > data_p [ dst - > data_offset ] , src , ( size_t ) len ) ;
dst - > data_offset + = len ;
1998-03-12 00:11:04 +03:00
return True ;
}
1999-12-13 16:27:58 +03:00
/*******************************************************************
2023-09-07 07:08:34 +03:00
Align the data_len to a multiple of align bytes - filling with
1999-12-13 16:27:58 +03:00
zeros .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool prs_align ( prs_struct * ps )
1999-12-13 16:27:58 +03:00
{
2015-04-14 17:50:28 +03:00
uint32_t mod = ps - > data_offset & ( ps - > align - 1 ) ;
1999-12-13 16:27:58 +03:00
if ( ps - > align ! = 0 & & mod ! = 0 ) {
2015-04-14 17:50:28 +03:00
uint32_t extra_space = ( ps - > align - mod ) ;
1999-12-13 16:27:58 +03:00
if ( ! prs_grow ( ps , extra_space ) )
return False ;
memset ( & ps - > data_p [ ps - > data_offset ] , ' \0 ' , ( size_t ) extra_space ) ;
ps - > data_offset + = extra_space ;
}
return True ;
}
2002-07-15 14:35:28 +04:00
/******************************************************************
Align on a 8 byte boundary
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-07-16 01:45:29 +04:00
2007-10-19 04:40:25 +04:00
bool prs_align_uint64 ( prs_struct * ps )
2002-07-15 14:35:28 +04:00
{
2007-10-19 04:40:25 +04:00
bool ret ;
2015-05-09 22:19:46 +03:00
uint8_t old_align = ps - > align ;
2002-07-15 14:35:28 +04:00
ps - > align = 8 ;
ret = prs_align ( ps ) ;
ps - > align = old_align ;
2010-07-16 01:45:29 +04:00
2002-07-15 14:35:28 +04:00
return ret ;
}
1999-12-13 16:27:58 +03:00
/*******************************************************************
Ensure we can read / write to a given offset .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-04-14 17:50:28 +03:00
char * prs_mem_get ( prs_struct * ps , uint32_t extra_size )
1999-12-13 16:27:58 +03:00
{
if ( UNMARSHALLING ( ps ) ) {
/*
* If reading , ensure that we can read the requested size item .
*/
if ( ps - > data_offset + extra_size > ps - > buffer_size ) {
2005-09-02 04:24:28 +04:00
DEBUG ( 0 , ( " prs_mem_get: reading data of size %u would overrun "
" buffer by %u bytes. \n " ,
( unsigned int ) extra_size ,
( unsigned int ) ( ps - > data_offset + extra_size - ps - > buffer_size ) ) ) ;
1999-12-13 16:27:58 +03:00
return NULL ;
}
} else {
/*
* Writing - grow the buffer if needed .
*/
if ( ! prs_grow ( ps , extra_size ) )
2000-12-11 09:34:12 +03:00
return NULL ;
1999-12-13 16:27:58 +03:00
}
return & ps - > data_p [ ps - > data_offset ] ;
}
2000-02-07 19:25:15 +03:00
/*******************************************************************
Change the struct type .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
void prs_switch_type ( prs_struct * ps , bool io )
2000-02-07 19:25:15 +03:00
{
if ( ( ps - > io ^ io ) = = True )
ps - > io = io ;
}
1998-03-12 00:11:04 +03:00
/*******************************************************************
1999-12-13 16:27:58 +03:00
Stream a uint16 .
1998-03-12 00:11:04 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2015-05-14 03:26:01 +03:00
bool prs_uint16 ( const char * name , prs_struct * ps , int depth , uint16_t * data16 )
1998-03-12 00:11:04 +03:00
{
2015-05-09 22:19:46 +03:00
char * q = prs_mem_get ( ps , sizeof ( uint16_t ) ) ;
1999-10-16 00:00:30 +04:00
if ( q = = NULL )
return False ;
1998-03-12 00:11:04 +03:00
2005-03-24 02:26:33 +03:00
if ( UNMARSHALLING ( ps ) ) {
2001-03-31 23:06:45 +04:00
if ( ps - > bigendian_data )
* data16 = RSVAL ( q , 0 ) ;
else
* data16 = SVAL ( q , 0 ) ;
2005-03-24 02:26:33 +03:00
} else {
2001-03-31 23:06:45 +04:00
if ( ps - > bigendian_data )
RSSVAL ( q , 0 , * data16 ) ;
else
SSVAL ( q , 0 , * data16 ) ;
}
2008-12-16 04:12:49 +03:00
DEBUGADD ( 5 , ( " %s%04x %s: %04x \n " , tab_depth ( 5 , depth ) , ps - > data_offset , name , * data16 ) ) ;
2001-03-31 23:06:45 +04:00
2015-05-09 22:19:46 +03:00
ps - > data_offset + = sizeof ( uint16_t ) ;
1998-03-12 00:11:04 +03:00
return True ;
}
1999-12-13 16:27:58 +03:00
/*******************************************************************
Stream a uint32 .
1998-03-12 00:11:04 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2015-04-14 17:50:28 +03:00
bool prs_uint32 ( const char * name , prs_struct * ps , int depth , uint32_t * data32 )
1998-03-12 00:11:04 +03:00
{
2015-04-14 17:50:28 +03:00
char * q = prs_mem_get ( ps , sizeof ( uint32_t ) ) ;
1999-12-13 16:27:58 +03:00
if ( q = = NULL )
1999-10-16 00:00:30 +04:00
return False ;
1998-03-12 00:11:04 +03:00
2001-03-31 23:06:45 +04:00
if ( UNMARSHALLING ( ps ) ) {
if ( ps - > bigendian_data )
* data32 = RIVAL ( q , 0 ) ;
else
* data32 = IVAL ( q , 0 ) ;
} else {
if ( ps - > bigendian_data )
RSIVAL ( q , 0 , * data32 ) ;
else
SIVAL ( q , 0 , * data32 ) ;
}
2008-12-16 04:12:49 +03:00
DEBUGADD ( 5 , ( " %s%04x %s: %08x \n " , tab_depth ( 5 , depth ) , ps - > data_offset , name , * data32 ) ) ;
2001-03-31 23:06:45 +04:00
2015-04-14 17:50:28 +03:00
ps - > data_offset + = sizeof ( uint32_t ) ;
1998-03-12 00:11:04 +03:00
return True ;
}
2009-03-18 17:05:44 +03:00
/*******************************************************************
Stream a uint64_struct
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-05-15 17:38:04 +03:00
bool prs_uint64 ( const char * name , prs_struct * ps , int depth , uint64_t * data64 )
2009-03-18 17:05:44 +03:00
{
if ( UNMARSHALLING ( ps ) ) {
2015-04-14 17:50:28 +03:00
uint32_t high , low ;
2009-03-18 17:05:44 +03:00
if ( ! prs_uint32 ( name , ps , depth + 1 , & low ) )
return False ;
if ( ! prs_uint32 ( name , ps , depth + 1 , & high ) )
return False ;
* data64 = ( ( uint64_t ) high < < 32 ) + low ;
return True ;
} else {
2015-04-14 17:50:28 +03:00
uint32_t high = ( * data64 ) > > 32 , low = ( * data64 ) & 0xFFFFFFFF ;
2009-03-18 17:05:44 +03:00
return prs_uint32 ( name , ps , depth + 1 , & low ) & &
prs_uint32 ( name , ps , depth + 1 , & high ) ;
}
}
1999-04-27 14:43:32 +04:00
/******************************************************************
1999-12-13 16:27:58 +03:00
Stream an array of uint8s . Length is number of uint8s .
1999-04-27 14:43:32 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2015-05-09 22:19:46 +03:00
bool prs_uint8s ( bool charmode , const char * name , prs_struct * ps , int depth , uint8_t * data8s , int len )
1999-04-27 14:43:32 +04:00
{
2001-03-31 23:06:45 +04:00
int i ;
char * q = prs_mem_get ( ps , len ) ;
1999-12-13 16:27:58 +03:00
if ( q = = NULL )
1999-10-16 00:00:30 +04:00
return False ;
1999-04-27 14:43:32 +04:00
2001-03-31 23:06:45 +04:00
if ( UNMARSHALLING ( ps ) ) {
for ( i = 0 ; i < len ; i + + )
data8s [ i ] = CVAL ( q , i ) ;
} else {
for ( i = 0 ; i < len ; i + + )
SCVAL ( q , i , data8s [ i ] ) ;
}
2008-12-16 04:12:49 +03:00
DEBUGADD ( 5 , ( " %s%04x %s: " , tab_depth ( 5 , depth ) , ps - > data_offset , name ) ) ;
2005-01-08 03:51:12 +03:00
if ( charmode )
2001-03-31 23:06:45 +04:00
print_asc ( 5 , ( unsigned char * ) data8s , len ) ;
else {
2005-01-08 03:51:12 +03:00
for ( i = 0 ; i < len ; i + + )
2008-12-16 04:12:49 +03:00
DEBUGADD ( 5 , ( " %02x " , data8s [ i ] ) ) ;
2001-03-31 23:06:45 +04:00
}
2008-12-16 04:12:49 +03:00
DEBUGADD ( 5 , ( " \n " ) ) ;
2001-03-31 23:06:45 +04:00
ps - > data_offset + = len ;
1999-04-27 14:43:32 +04:00
return True ;
}