2019-10-29 11:04:43 +01:00
/*
2003-12-13 02:20:40 +00:00
Unix SMB / CIFS implementation .
server side dcerpc handle code
Copyright ( C ) Andrew Tridgell 2003
2019-10-29 11:04:43 +01:00
2003-12-13 02:20:40 +00: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 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2003-12-13 02:20:40 +00:00
( at your option ) any later version .
2019-10-29 11:04:43 +01:00
2003-12-13 02:20:40 +00: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 .
2019-10-29 11:04:43 +01:00
2003-12-13 02:20:40 +00:00
You should have received a copy of the GNU General Public License
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-12-13 02:20:40 +00:00
*/
# include "includes.h"
2019-09-30 23:35:55 +02:00
# include "lib/util/dlinklist.h"
2004-11-02 07:42:47 +00:00
# include "rpc_server/dcerpc_server.h"
2010-08-14 13:30:51 +10:00
# include "libcli/security/security.h"
2019-09-30 23:35:55 +02:00
# include "librpc/gen_ndr/auth.h"
2003-12-13 02:20:40 +00:00
2005-01-10 12:15:26 +00:00
/*
destroy a rpc handle
*/
2006-05-24 07:35:06 +00:00
static int dcesrv_handle_destructor ( struct dcesrv_handle * h )
2005-01-10 12:15:26 +00:00
{
2009-09-22 00:18:03 -07:00
DLIST_REMOVE ( h - > assoc_group - > handles , h ) ;
2005-01-10 12:15:26 +00:00
return 0 ;
}
2003-12-13 02:20:40 +00:00
/*
allocate a new rpc handle
*/
2018-11-08 12:20:44 +01:00
_PUBLIC_
struct dcesrv_handle * dcesrv_handle_create ( struct dcesrv_call_state * call ,
uint8_t handle_type )
2003-12-13 02:20:40 +00:00
{
2018-11-08 12:20:44 +01:00
struct dcesrv_connection_context * context = call - > context ;
2018-11-03 01:19:51 +01:00
struct auth_session_info * session_info =
dcesrv_call_session_info ( call ) ;
2003-12-13 02:20:40 +00:00
struct dcesrv_handle * h ;
2009-09-22 00:18:03 -07:00
struct dom_sid * sid ;
2003-12-13 02:20:40 +00:00
2016-11-14 11:24:03 +13:00
/*
2021-01-27 14:53:15 +01:00
* For simplicity , ensure we abort here for an interface that
* has no handles ( programmer error )
2016-11-14 11:24:03 +13:00
*/
SMB_ASSERT ( ( context - > iface - > flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED ) = = 0 ) ;
2018-11-03 01:19:51 +01:00
sid = & session_info - > security_token - > sids [ PRIMARY_USER_SID_INDEX ] ;
2009-09-22 00:18:03 -07:00
2015-07-15 10:18:13 +02:00
h = talloc_zero ( context - > conn - > assoc_group , struct dcesrv_handle ) ;
2003-12-13 02:20:40 +00:00
if ( ! h ) {
return NULL ;
}
h - > data = NULL ;
2021-01-27 14:59:16 +01:00
sid_copy ( & h - > sid , sid ) ;
2018-11-21 23:27:50 +01:00
h - > min_auth_level = call - > auth_state - > auth_level ;
2015-07-15 10:18:13 +02:00
h - > assoc_group = context - > conn - > assoc_group ;
2009-09-22 00:18:03 -07:00
h - > iface = context - > iface ;
2003-12-16 09:50:49 +00:00
h - > wire_handle . handle_type = handle_type ;
2004-11-25 20:03:46 +00:00
h - > wire_handle . uuid = GUID_random ( ) ;
2019-10-29 11:04:43 +01:00
2015-07-15 10:18:13 +02:00
DLIST_ADD ( context - > conn - > assoc_group - > handles , h ) ;
2003-12-13 02:20:40 +00:00
2005-01-10 12:15:26 +00:00
talloc_set_destructor ( h , dcesrv_handle_destructor ) ;
2003-12-13 02:20:40 +00:00
2005-01-10 12:15:26 +00:00
return h ;
2003-12-13 02:20:40 +00:00
}
2007-08-26 15:16:40 +00:00
/**
2003-12-13 02:20:40 +00:00
find an internal handle given a wire handle . If the wire handle is NULL then
allocate a new handle
*/
2018-11-08 12:20:44 +01:00
_PUBLIC_
struct dcesrv_handle * dcesrv_handle_lookup ( struct dcesrv_call_state * call ,
const struct policy_handle * p ,
uint8_t handle_type )
2003-12-13 02:20:40 +00:00
{
2018-11-08 12:20:44 +01:00
struct dcesrv_connection_context * context = call - > context ;
2018-11-03 01:19:51 +01:00
struct auth_session_info * session_info =
dcesrv_call_session_info ( call ) ;
2003-12-13 02:20:40 +00:00
struct dcesrv_handle * h ;
2009-09-22 00:18:03 -07:00
struct dom_sid * sid ;
2016-11-14 11:24:03 +13:00
/*
2021-01-29 10:13:13 +01:00
* For simplicity , ensure we abort here for an interface that
* has no handles ( programmer error )
2016-11-14 11:24:03 +13:00
*/
SMB_ASSERT ( ( context - > iface - > flags & DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED ) = = 0 ) ;
2018-11-03 01:19:51 +01:00
sid = & session_info - > security_token - > sids [ PRIMARY_USER_SID_INDEX ] ;
2003-12-13 02:20:40 +00:00
2012-03-18 17:44:24 +01:00
if ( ndr_policy_handle_empty ( p ) ) {
2009-09-21 21:36:54 -07:00
/* TODO: we should probably return a NULL handle here */
2018-11-08 12:20:44 +01:00
return dcesrv_handle_create ( call , handle_type ) ;
2003-12-13 02:20:40 +00:00
}
2021-09-20 16:36:15 +02:00
if ( handle_type ! = DCESRV_HANDLE_ANY & &
p - > handle_type ! = handle_type ) {
DBG_WARNING ( " client gave us the wrong handle type "
" (% " PRIu32 " should be % " PRIu8 " ) \n " ,
p - > handle_type ,
handle_type ) ;
return NULL ;
}
2015-07-15 10:18:13 +02:00
for ( h = context - > conn - > assoc_group - > handles ; h ; h = h - > next ) {
2003-12-16 09:50:49 +00:00
if ( h - > wire_handle . handle_type = = p - > handle_type & &
2004-11-25 20:03:46 +00:00
GUID_equal ( & p - > uuid , & h - > wire_handle . uuid ) ) {
2021-09-20 16:42:08 +02:00
break ;
2003-12-13 02:20:40 +00:00
}
}
2021-09-20 16:42:08 +02:00
if ( h = = NULL ) {
/* not found */
return NULL ;
}
if ( ! dom_sid_equal ( & h - > sid , sid ) ) {
struct dom_sid_buf buf1 , buf2 ;
DBG_ERR ( " Attempt to use invalid sid %s - %s \n " ,
dom_sid_str_buf ( & h - > sid , & buf1 ) ,
dom_sid_str_buf ( sid , & buf2 ) ) ;
return NULL ;
}
if ( call - > auth_state - > auth_level < h - > min_auth_level ) {
DBG_ERR ( " Attempt to use invalid auth_level %u < %u \n " ,
call - > auth_state - > auth_level ,
h - > min_auth_level ) ;
return NULL ;
}
if ( h - > iface ! = context - > iface ) {
DBG_ERR ( " Attempt to use invalid iface \n " ) ;
return NULL ;
}
return h ;
2003-12-13 02:20:40 +00:00
}
2018-12-10 22:41:31 +01:00
struct dcesrv_iface_state {
struct dcesrv_iface_state * prev , * next ;
struct dcesrv_assoc_group * assoc ;
const struct dcesrv_interface * iface ;
struct dom_sid owner ;
const struct dcesrv_connection * conn ;
const struct dcesrv_auth * auth ;
const struct dcesrv_connection_context * pres ;
uint64_t magic ;
void * ptr ;
const char * location ;
} ;
static int dcesrv_iface_state_destructor ( struct dcesrv_iface_state * istate )
{
DLIST_REMOVE ( istate - > assoc - > iface_states , istate ) ;
return 0 ;
}
static void * dcesrv_iface_state_find ( struct dcesrv_assoc_group * assoc ,
const struct dcesrv_interface * iface ,
const struct dom_sid * owner ,
const struct dcesrv_connection * conn ,
const struct dcesrv_auth * auth ,
const struct dcesrv_connection_context * pres ,
uint64_t magic ,
const void * ptr )
{
struct dcesrv_iface_state * cur = NULL ;
for ( cur = assoc - > iface_states ; cur ! = NULL ; cur = cur - > next ) {
bool match ;
SMB_ASSERT ( cur - > assoc = = assoc ) ;
if ( cur - > ptr = = ptr ) {
return cur - > ptr ;
}
if ( cur - > iface ! = iface ) {
continue ;
}
match = dom_sid_equal ( & cur - > owner , owner ) ;
if ( ! match ) {
continue ;
}
if ( cur - > conn ! = conn ) {
continue ;
}
if ( cur - > auth ! = auth ) {
continue ;
}
if ( cur - > pres ! = pres ) {
continue ;
}
if ( cur - > magic ! = magic ) {
continue ;
}
return cur - > ptr ;
}
return NULL ;
}
static NTSTATUS dcesrv_iface_state_store ( struct dcesrv_assoc_group * assoc ,
const struct dcesrv_interface * iface ,
const struct dom_sid * owner ,
const struct dcesrv_connection * conn ,
const struct dcesrv_auth * auth ,
const struct dcesrv_connection_context * pres ,
uint64_t magic ,
TALLOC_CTX * mem_ctx ,
void * ptr ,
const char * location )
{
struct dcesrv_iface_state * istate = NULL ;
void * optr = NULL ;
optr = dcesrv_iface_state_find ( assoc ,
iface ,
owner ,
conn ,
auth ,
pres ,
magic ,
ptr ) ;
if ( optr ! = NULL ) {
return NT_STATUS_OBJECTID_EXISTS ;
}
istate = talloc_zero ( ptr , struct dcesrv_iface_state ) ;
if ( istate = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
* istate = ( struct dcesrv_iface_state ) {
. assoc = assoc ,
. iface = iface ,
. owner = * owner ,
. conn = conn ,
. auth = auth ,
. pres = pres ,
. magic = magic ,
. location = location ,
} ;
istate - > ptr = talloc_steal ( mem_ctx , ptr ) ;
talloc_set_destructor ( istate , dcesrv_iface_state_destructor ) ;
DLIST_ADD_END ( assoc - > iface_states , istate ) ;
return NT_STATUS_OK ;
}
NTSTATUS _dcesrv_iface_state_store_assoc ( struct dcesrv_call_state * call ,
uint64_t magic ,
void * ptr ,
const char * location )
{
struct auth_session_info * session_info =
dcesrv_call_session_info ( call ) ;
const struct dom_sid * owner =
2022-12-16 12:08:41 +13:00
& session_info - > security_token - > sids [ PRIMARY_USER_SID_INDEX ] ;
2018-12-10 22:41:31 +01:00
NTSTATUS status ;
status = dcesrv_iface_state_store ( call - > conn - > assoc_group ,
call - > context - > iface ,
owner ,
NULL , /* conn */
NULL , /* auth */
NULL , /* pres */
magic ,
call - > conn - > assoc_group , /* mem_ctx */
ptr ,
location ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return NT_STATUS_OK ;
}
void * _dcesrv_iface_state_find_assoc ( struct dcesrv_call_state * call , uint64_t magic )
{
struct auth_session_info * session_info =
dcesrv_call_session_info ( call ) ;
const struct dom_sid * owner =
2022-12-16 12:08:41 +13:00
& session_info - > security_token - > sids [ PRIMARY_USER_SID_INDEX ] ;
2018-12-10 22:41:31 +01:00
void * ptr = NULL ;
ptr = dcesrv_iface_state_find ( call - > conn - > assoc_group ,
call - > context - > iface ,
owner ,
NULL , /* conn */
NULL , /* auth */
NULL , /* pres */
magic ,
NULL ) ; /* ptr */
if ( ptr = = NULL ) {
return NULL ;
}
return ptr ;
}
NTSTATUS _dcesrv_iface_state_store_conn ( struct dcesrv_call_state * call ,
uint64_t magic ,
void * ptr ,
const char * location )
{
struct auth_session_info * session_info =
dcesrv_call_session_info ( call ) ;
const struct dom_sid * owner =
2022-12-16 12:08:41 +13:00
& session_info - > security_token - > sids [ PRIMARY_USER_SID_INDEX ] ;
2018-12-10 22:41:31 +01:00
NTSTATUS status ;
status = dcesrv_iface_state_store ( call - > conn - > assoc_group ,
call - > context - > iface ,
owner ,
call - > conn ,
call - > auth_state ,
call - > context ,
magic ,
call - > conn , /* mem_ctx */
ptr ,
location ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return NT_STATUS_OK ;
}
void * _dcesrv_iface_state_find_conn ( struct dcesrv_call_state * call , uint64_t magic )
{
struct auth_session_info * session_info =
dcesrv_call_session_info ( call ) ;
const struct dom_sid * owner =
2022-12-16 12:08:41 +13:00
& session_info - > security_token - > sids [ PRIMARY_USER_SID_INDEX ] ;
2018-12-10 22:41:31 +01:00
void * ptr = NULL ;
ptr = dcesrv_iface_state_find ( call - > conn - > assoc_group ,
call - > context - > iface ,
owner ,
call - > conn ,
call - > auth_state ,
call - > context ,
magic ,
NULL ) ; /* ptr */
if ( ptr = = NULL ) {
return NULL ;
}
return ptr ;
}