2010-03-12 00:10:38 +03:00
/*
ldb database library
Copyright ( C ) Nadezhda Ivanova 2010
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/>.
*/
/*
* Name : dsdb_access
*
* Description : utility functions for access checking on objects
*
* Authors : Nadezhda Ivanova
*/
# include "includes.h"
# include "ldb.h"
2010-07-06 07:21:54 +04:00
# include "ldb_module.h"
2010-03-12 00:10:38 +03:00
# include "ldb_errors.h"
# include "libcli/security/security.h"
# include "librpc/gen_ndr/ndr_security.h"
# include "libcli/ldap/ldap_ndr.h"
# include "param/param.h"
# include "auth/auth.h"
2010-04-16 15:28:09 +04:00
# include "dsdb/samdb/samdb.h"
2010-09-27 08:12:48 +04:00
# include "dsdb/common/util.h"
2010-03-12 00:10:38 +03:00
void dsdb_acl_debug ( struct security_descriptor * sd ,
struct security_token * token ,
struct ldb_dn * dn ,
bool denied ,
int level )
{
if ( denied ) {
DEBUG ( level , ( " Access on %s denied " , ldb_dn_get_linearized ( dn ) ) ) ;
} else {
DEBUG ( level , ( " Access on %s granted " , ldb_dn_get_linearized ( dn ) ) ) ;
}
DEBUG ( level , ( " Security context: %s \n " ,
ndr_print_struct_string ( 0 , ( ndr_print_fn_t ) ndr_print_security_token , " " , token ) ) ) ;
DEBUG ( level , ( " Security descriptor: %s \n " ,
ndr_print_struct_string ( 0 , ( ndr_print_fn_t ) ndr_print_security_descriptor , " " , sd ) ) ) ;
}
2010-07-06 07:21:54 +04:00
int dsdb_get_sd_from_ldb_message ( struct ldb_context * ldb ,
TALLOC_CTX * mem_ctx ,
2010-03-12 00:10:38 +03:00
struct ldb_message * acl_res ,
struct security_descriptor * * sd )
{
struct ldb_message_element * sd_element ;
enum ndr_err_code ndr_err ;
sd_element = ldb_msg_find_element ( acl_res , " nTSecurityDescriptor " ) ;
if ( ! sd_element ) {
* sd = NULL ;
return LDB_SUCCESS ;
}
* sd = talloc ( mem_ctx , struct security_descriptor ) ;
if ( ! * sd ) {
2010-07-06 07:21:54 +04:00
return ldb_oom ( ldb ) ;
2010-03-12 00:10:38 +03:00
}
2010-05-09 19:20:01 +04:00
ndr_err = ndr_pull_struct_blob ( & sd_element - > values [ 0 ] , * sd , * sd ,
2010-03-12 00:10:38 +03:00
( ndr_pull_flags_fn_t ) ndr_pull_security_descriptor ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2010-07-06 07:21:54 +04:00
return ldb_operr ( ldb ) ;
2010-03-12 00:10:38 +03:00
}
return LDB_SUCCESS ;
}
2010-07-06 07:21:54 +04:00
int dsdb_check_access_on_dn_internal ( struct ldb_context * ldb ,
struct ldb_result * acl_res ,
2010-03-12 04:13:51 +03:00
TALLOC_CTX * mem_ctx ,
struct security_token * token ,
struct ldb_dn * dn ,
uint32_t access ,
const struct GUID * guid )
2010-03-12 00:10:38 +03:00
{
struct security_descriptor * sd = NULL ;
struct dom_sid * sid = NULL ;
struct object_tree * root = NULL ;
struct object_tree * new_node = NULL ;
NTSTATUS status ;
uint32_t access_granted ;
2010-03-12 04:13:51 +03:00
int ret ;
2010-03-12 00:10:38 +03:00
2010-07-06 07:21:54 +04:00
ret = dsdb_get_sd_from_ldb_message ( ldb , mem_ctx , acl_res - > msgs [ 0 ] , & sd ) ;
2010-03-12 00:10:38 +03:00
if ( ret ! = LDB_SUCCESS ) {
2010-07-06 07:21:54 +04:00
return ldb_operr ( ldb ) ;
2010-03-12 00:10:38 +03:00
}
/* Theoretically we pass the check if the object has no sd */
if ( ! sd ) {
return LDB_SUCCESS ;
}
2010-04-16 15:28:09 +04:00
sid = samdb_result_dom_sid ( mem_ctx , acl_res - > msgs [ 0 ] , " objectSid " ) ;
2010-03-12 00:10:38 +03:00
if ( guid ) {
if ( ! insert_in_object_tree ( mem_ctx , guid , access , & root , & new_node ) ) {
2010-07-06 07:21:54 +04:00
return ldb_operr ( ldb ) ;
2010-03-12 00:10:38 +03:00
}
}
2010-03-12 04:13:51 +03:00
status = sec_access_check_ds ( sd , token ,
2010-03-12 00:10:38 +03:00
access ,
& access_granted ,
root ,
sid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
dsdb_acl_debug ( sd ,
2010-03-12 04:13:51 +03:00
token ,
2010-03-12 00:10:38 +03:00
dn ,
true ,
10 ) ;
return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ;
}
return LDB_SUCCESS ;
}
2010-03-12 04:13:51 +03:00
/* performs an access check from outside the module stack
* given the dn of the object to be checked , the required access
* guid is either the guid of the extended right , or NULL
*/
int dsdb_check_access_on_dn ( struct ldb_context * ldb ,
TALLOC_CTX * mem_ctx ,
struct ldb_dn * dn ,
2010-09-27 08:12:48 +04:00
struct security_token * token ,
2010-03-12 04:13:51 +03:00
uint32_t access ,
2010-09-27 08:12:48 +04:00
const char * ext_right )
2010-03-12 04:13:51 +03:00
{
int ret ;
2010-09-27 08:12:48 +04:00
struct GUID guid ;
2010-03-12 04:13:51 +03:00
struct ldb_result * acl_res ;
static const char * acl_attrs [ ] = {
" nTSecurityDescriptor " ,
" objectSid " ,
NULL
} ;
2010-09-27 08:12:48 +04:00
NTSTATUS status = GUID_from_string ( ext_right , & guid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return LDB_ERR_OPERATIONS_ERROR ;
2010-03-12 04:13:51 +03:00
}
2010-09-27 08:12:48 +04:00
ret = dsdb_search_dn ( ldb , mem_ctx , & acl_res , dn , acl_attrs , DSDB_SEARCH_SHOW_DELETED ) ;
2010-03-12 04:13:51 +03:00
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " access_check: failed to find object %s \n " , ldb_dn_get_linearized ( dn ) ) ) ;
return ret ;
}
2010-07-06 07:21:54 +04:00
return dsdb_check_access_on_dn_internal ( ldb , acl_res ,
2010-03-12 04:13:51 +03:00
mem_ctx ,
2010-09-27 08:12:48 +04:00
token ,
2010-03-12 04:13:51 +03:00
dn ,
access ,
2010-09-27 08:12:48 +04:00
& guid ) ;
2010-03-12 04:13:51 +03:00
}