2009-09-21 17:27:50 -07:00
/*
2009-12-10 15:49:53 +02:00
ldb database library
2009-09-21 17:27:50 -07:00
2009-12-10 15:49:53 +02:00
Copyright ( C ) Simo Sorce 2006 - 2008
Copyright ( C ) Nadezhda Ivanova 2009
Copyright ( C ) Anatoliy Atanasov 2009
2009-09-21 17:27:50 -07:00
2009-12-10 15:49:53 +02: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
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
2009-09-21 17:27:50 -07:00
2009-12-10 15:49:53 +02: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 .
2009-09-21 17:27:50 -07:00
2009-12-10 15:49:53 +02:00
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2009-09-21 17:27:50 -07:00
*/
/*
* Name : ldb
*
* Component : ldb ACL module
*
* Description : Module that performs authorisation access checks based on the
* account ' s security context and the DACL of the object being polled .
* Only DACL checks implemented at this point
*
* Authors : Nadezhda Ivanova , Anatoliy Atanasov
*/
# include "includes.h"
# include "ldb_module.h"
# include "auth/auth.h"
# include "libcli/security/security.h"
# include "dsdb/samdb/samdb.h"
# include "librpc/gen_ndr/ndr_security.h"
# include "param/param.h"
2010-01-08 09:30:59 +11:00
# include "dsdb/samdb/ldb_modules/util.h"
2010-02-13 12:59:43 +11:00
# include "lib/util/tsort.h"
2009-09-21 17:27:50 -07:00
struct extended_access_check_attribute {
const char * oa_name ;
const uint32_t requires_rights ;
} ;
2009-12-10 15:49:53 +02:00
struct acl_private {
bool acl_perform ;
const char * * password_attrs ;
} ;
struct acl_context {
struct ldb_module * module ;
struct ldb_request * req ;
2010-01-08 09:30:31 +11:00
bool am_system ;
2009-12-10 15:49:53 +02:00
bool allowedAttributes ;
bool allowedAttributesEffective ;
bool allowedChildClasses ;
bool allowedChildClassesEffective ;
bool sDRightsEffective ;
const char * const * attrs ;
2010-03-16 14:43:33 +11:00
struct dsdb_schema * schema ;
2009-09-21 17:27:50 -07:00
} ;
2009-11-05 17:34:12 +02:00
static struct security_token * acl_user_token ( struct ldb_module * module )
2009-09-21 17:27:50 -07:00
{
2009-11-05 17:34:12 +02:00
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
struct auth_session_info * session_info
= ( struct auth_session_info * ) ldb_get_opaque ( ldb , " sessionInfo " ) ;
if ( ! session_info ) {
return NULL ;
2009-09-21 17:27:50 -07:00
}
2009-11-05 17:34:12 +02:00
return session_info - > security_token ;
2009-09-21 17:27:50 -07:00
}
2010-03-12 03:13:51 +02:00
/* performs an access check from inside 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_module_check_access_on_dn ( struct ldb_module * module ,
TALLOC_CTX * mem_ctx ,
struct ldb_dn * dn ,
uint32_t access ,
const struct GUID * guid )
{
int ret ;
struct ldb_result * acl_res ;
static const char * acl_attrs [ ] = {
" nTSecurityDescriptor " ,
" objectSid " ,
NULL
} ;
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
struct auth_session_info * session_info
= ( struct auth_session_info * ) ldb_get_opaque ( ldb , " sessionInfo " ) ;
if ( ! session_info ) {
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2010-03-12 03:13:51 +02:00
}
ret = dsdb_module_search_dn ( module , mem_ctx , & acl_res , dn ,
2010-07-06 03:26:03 +03:00
acl_attrs ,
DSDB_FLAG_NEXT_MODULE |
DSDB_SEARCH_SHOW_DELETED ) ;
2010-03-12 03:13:51 +02: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 13:21:54 +10:00
return dsdb_check_access_on_dn_internal ( ldb , acl_res ,
2010-03-12 03:13:51 +02:00
mem_ctx ,
session_info - > security_token ,
dn ,
access ,
guid ) ;
}
2009-11-05 17:34:12 +02:00
static int acl_module_init ( struct ldb_module * module )
2009-09-21 17:27:50 -07:00
{
2009-11-05 17:34:12 +02:00
struct ldb_context * ldb ;
struct acl_private * data ;
2009-12-10 15:49:53 +02:00
int ret , i ;
2010-07-07 18:01:34 +02:00
TALLOC_CTX * mem_ctx ;
2009-12-10 15:49:53 +02:00
static const char * attrs [ ] = { " passwordAttribute " , NULL } ;
struct ldb_result * res ;
struct ldb_message * msg ;
struct ldb_message_element * password_attributes ;
2009-09-21 17:27:50 -07:00
2009-11-05 17:34:12 +02:00
ldb = ldb_module_get_ctx ( module ) ;
2009-09-21 17:27:50 -07:00
2009-11-05 17:34:12 +02:00
ret = ldb_mod_register_control ( module , LDB_CONTROL_SD_FLAGS_OID ) ;
if ( ret ! = LDB_SUCCESS ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" acl_module_init: Unable to register control with rootdse! \n " ) ;
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2009-09-21 17:27:50 -07:00
}
2009-11-05 17:34:12 +02:00
data = talloc ( module , struct acl_private ) ;
2009-12-10 15:49:53 +02:00
if ( data = = NULL ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb ) ;
2009-12-10 15:49:53 +02:00
}
data - > password_attrs = NULL ;
2010-07-16 14:32:42 +10:00
data - > acl_perform = lpcfg_parm_bool ( ldb_get_opaque ( ldb , " loadparm " ) ,
2009-12-10 15:49:53 +02:00
NULL , " acl " , " perform " , false ) ;
2009-11-05 17:34:12 +02:00
ldb_module_set_private ( module , data ) ;
2009-09-21 17:27:50 -07:00
2010-07-07 18:01:34 +02:00
mem_ctx = talloc_new ( module ) ;
2009-12-10 15:49:53 +02:00
if ( ! mem_ctx ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb ) ;
2009-12-10 15:49:53 +02:00
}
2010-03-12 02:21:16 +02:00
ret = dsdb_module_search_dn ( module , mem_ctx , & res ,
ldb_dn_new ( mem_ctx , ldb , " @KLUDGEACL " ) ,
2010-07-06 03:26:03 +03:00
attrs ,
DSDB_FLAG_NEXT_MODULE ) ;
2009-12-10 15:49:53 +02:00
if ( ret ! = LDB_SUCCESS ) {
goto done ;
}
if ( res - > count = = 0 ) {
goto done ;
}
if ( res - > count > 1 ) {
talloc_free ( mem_ctx ) ;
return LDB_ERR_CONSTRAINT_VIOLATION ;
}
msg = res - > msgs [ 0 ] ;
password_attributes = ldb_msg_find_element ( msg , " passwordAttribute " ) ;
if ( ! password_attributes ) {
goto done ;
}
data - > password_attrs = talloc_array ( data , const char * , password_attributes - > num_values + 1 ) ;
if ( ! data - > password_attrs ) {
talloc_free ( mem_ctx ) ;
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb ) ;
2009-12-10 15:49:53 +02:00
}
for ( i = 0 ; i < password_attributes - > num_values ; i + + ) {
data - > password_attrs [ i ] = ( const char * ) password_attributes - > values [ i ] . data ;
talloc_steal ( data - > password_attrs , password_attributes - > values [ i ] . data ) ;
}
data - > password_attrs [ i ] = NULL ;
done :
talloc_free ( mem_ctx ) ;
2009-11-05 17:34:12 +02:00
return ldb_next_init ( module ) ;
2009-09-21 17:27:50 -07:00
}
2009-12-10 15:49:53 +02:00
static const struct GUID * get_oc_guid_from_message ( struct ldb_module * module ,
2010-03-16 14:43:33 +11:00
const struct dsdb_schema * schema ,
2009-12-10 15:49:53 +02:00
struct ldb_message * msg )
2009-09-21 17:27:50 -07:00
{
2009-11-05 17:34:12 +02:00
struct ldb_message_element * oc_el ;
2009-09-21 17:27:50 -07:00
2009-12-10 15:49:53 +02:00
oc_el = ldb_msg_find_element ( msg , " objectClass " ) ;
2009-11-05 17:34:12 +02:00
if ( ! oc_el ) {
return NULL ;
}
2009-09-21 17:27:50 -07:00
2010-03-16 14:43:33 +11:00
return class_schemaid_guid_by_lDAPDisplayName ( schema ,
2009-11-05 17:34:12 +02:00
( char * ) oc_el - > values [ oc_el - > num_values - 1 ] . data ) ;
2009-09-21 17:27:50 -07:00
}
2009-12-10 15:49:53 +02:00
static int acl_check_access_on_attribute ( struct ldb_module * module ,
TALLOC_CTX * mem_ctx ,
struct security_descriptor * sd ,
2009-12-17 17:25:11 +02:00
struct dom_sid * rp_sid ,
2009-12-10 15:49:53 +02:00
uint32_t access ,
2010-01-08 09:30:59 +11:00
const struct dsdb_attribute * attr )
2009-12-10 15:49:53 +02:00
{
int ret ;
NTSTATUS status ;
uint32_t access_granted ;
struct object_tree * root = NULL ;
struct object_tree * new_node = NULL ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
struct security_token * token = acl_user_token ( module ) ;
if ( attr ) {
if ( ! GUID_all_zero ( & attr - > attributeSecurityGUID ) ) {
if ( ! insert_in_object_tree ( tmp_ctx ,
& attr - > attributeSecurityGUID , access ,
& root , & new_node ) ) {
DEBUG ( 10 , ( " acl_search: cannot add to object tree securityGUID \n " ) ) ;
goto fail ;
}
if ( ! insert_in_object_tree ( tmp_ctx ,
& attr - > schemaIDGUID , access , & new_node , & new_node ) ) {
DEBUG ( 10 , ( " acl_search: cannot add to object tree attributeGUID \n " ) ) ;
goto fail ;
}
}
else {
if ( ! insert_in_object_tree ( tmp_ctx ,
& attr - > schemaIDGUID , access , & root , & new_node ) ) {
DEBUG ( 10 , ( " acl_search: cannot add to object tree attributeGUID \n " ) ) ;
goto fail ;
}
}
}
status = sec_access_check_ds ( sd , token ,
access ,
& access_granted ,
2009-12-17 17:25:11 +02:00
root ,
rp_sid ) ;
2009-12-10 15:49:53 +02:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ;
}
else {
ret = LDB_SUCCESS ;
}
2010-07-05 00:17:38 +03:00
talloc_free ( tmp_ctx ) ;
2009-12-10 15:49:53 +02:00
return ret ;
fail :
2010-07-05 00:17:38 +03:00
talloc_free ( tmp_ctx ) ;
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb_module_get_ctx ( module ) ) ;
2009-12-10 15:49:53 +02:00
}
static int acl_check_access_on_class ( struct ldb_module * module ,
2010-03-16 14:43:33 +11:00
const struct dsdb_schema * schema ,
2009-12-10 15:49:53 +02:00
TALLOC_CTX * mem_ctx ,
struct security_descriptor * sd ,
2009-12-17 17:25:11 +02:00
struct dom_sid * rp_sid ,
2009-12-10 15:49:53 +02:00
uint32_t access ,
const char * class_name )
{
int ret ;
NTSTATUS status ;
uint32_t access_granted ;
struct object_tree * root = NULL ;
struct object_tree * new_node = NULL ;
2010-01-08 09:30:59 +11:00
const struct GUID * guid ;
2009-12-10 15:49:53 +02:00
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
struct security_token * token = acl_user_token ( module ) ;
if ( class_name ) {
guid = class_schemaid_guid_by_lDAPDisplayName ( schema , class_name ) ;
if ( ! guid ) {
DEBUG ( 10 , ( " acl_search: cannot find class %s \n " ,
class_name ) ) ;
goto fail ;
}
if ( ! insert_in_object_tree ( tmp_ctx ,
guid , access ,
& root , & new_node ) ) {
DEBUG ( 10 , ( " acl_search: cannot add to object tree guid \n " ) ) ;
goto fail ;
}
}
status = sec_access_check_ds ( sd , token ,
access ,
& access_granted ,
2009-12-17 17:25:11 +02:00
root ,
rp_sid ) ;
2009-12-10 15:49:53 +02:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ;
}
else {
ret = LDB_SUCCESS ;
}
return ret ;
fail :
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb_module_get_ctx ( module ) ) ;
2009-12-10 15:49:53 +02:00
}
static int acl_allowedAttributes ( struct ldb_module * module ,
2010-03-16 14:43:33 +11:00
const struct dsdb_schema * schema ,
2009-12-10 15:49:53 +02:00
struct ldb_message * sd_msg ,
struct ldb_message * msg ,
struct acl_context * ac )
{
struct ldb_message_element * oc_el ;
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
TALLOC_CTX * mem_ctx ;
const char * * attr_list ;
int i , ret ;
/* If we don't have a schema yet, we can't do anything... */
if ( schema = = NULL ) {
2010-03-16 14:43:33 +11:00
ldb_asprintf_errstring ( ldb , " cannot add allowedAttributes to %s because no schema is loaded " , ldb_dn_get_linearized ( msg - > dn ) ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2009-12-10 15:49:53 +02:00
}
/* Must remove any existing attribute */
if ( ac - > allowedAttributes ) {
ldb_msg_remove_attr ( msg , " allowedAttributes " ) ;
}
mem_ctx = talloc_new ( msg ) ;
if ( ! mem_ctx ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb ) ;
2009-12-10 15:49:53 +02:00
}
oc_el = ldb_msg_find_element ( sd_msg , " objectClass " ) ;
attr_list = dsdb_full_attribute_list ( mem_ctx , schema , oc_el , DSDB_SCHEMA_ALL ) ;
if ( ! attr_list ) {
ldb_asprintf_errstring ( ldb , " acl: Failed to get list of attributes " ) ;
talloc_free ( mem_ctx ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
if ( ac - > allowedAttributes ) {
for ( i = 0 ; attr_list & & attr_list [ i ] ; i + + ) {
ldb_msg_add_string ( msg , " allowedAttributes " , attr_list [ i ] ) ;
}
}
if ( ac - > allowedAttributesEffective ) {
struct security_descriptor * sd ;
2009-12-17 17:25:11 +02:00
struct dom_sid * sid = NULL ;
2009-12-18 18:00:15 +02:00
struct ldb_control * as_system = ldb_request_get_control ( ac - > req ,
LDB_CONTROL_AS_SYSTEM_OID ) ;
2010-02-04 09:22:39 +01:00
if ( as_system ! = NULL ) {
as_system - > critical = 0 ;
}
2009-12-10 15:49:53 +02:00
ldb_msg_remove_attr ( msg , " allowedAttributesEffective " ) ;
2010-01-08 09:30:31 +11:00
if ( ac - > am_system | | as_system ) {
2009-12-10 15:49:53 +02:00
for ( i = 0 ; attr_list & & attr_list [ i ] ; i + + ) {
ldb_msg_add_string ( msg , " allowedAttributesEffective " , attr_list [ i ] ) ;
}
return LDB_SUCCESS ;
}
2010-07-06 13:21:54 +10:00
ret = dsdb_get_sd_from_ldb_message ( ldb_module_get_ctx ( module ) , mem_ctx , sd_msg , & sd ) ;
2009-12-10 15:49:53 +02:00
2009-12-17 17:25:11 +02:00
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2010-04-16 14:28:09 +03:00
sid = samdb_result_dom_sid ( mem_ctx , sd_msg , " objectSid " ) ;
2009-12-10 15:49:53 +02:00
for ( i = 0 ; attr_list & & attr_list [ i ] ; i + + ) {
2010-01-08 09:30:59 +11:00
const struct dsdb_attribute * attr = dsdb_attribute_by_lDAPDisplayName ( schema ,
2009-12-10 15:49:53 +02:00
attr_list [ i ] ) ;
if ( ! attr ) {
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2009-12-10 15:49:53 +02:00
}
/* remove constructed attributes */
2009-12-15 12:02:20 +02:00
if ( attr - > systemFlags & DS_FLAG_ATTR_IS_CONSTRUCTED
| | attr - > systemOnly
| | ( attr - > linkID ! = 0 & & attr - > linkID % 2 ! = 0 ) ) {
2009-12-10 15:49:53 +02:00
continue ;
}
ret = acl_check_access_on_attribute ( module ,
msg ,
sd ,
2009-12-17 17:25:11 +02:00
sid ,
2009-12-10 15:49:53 +02:00
SEC_ADS_WRITE_PROP ,
attr ) ;
if ( ret = = LDB_SUCCESS ) {
ldb_msg_add_string ( msg , " allowedAttributesEffective " , attr_list [ i ] ) ;
}
}
}
return LDB_SUCCESS ;
}
static int acl_childClasses ( struct ldb_module * module ,
2010-03-16 14:43:33 +11:00
const struct dsdb_schema * schema ,
2009-12-10 15:49:53 +02:00
struct ldb_message * sd_msg ,
struct ldb_message * msg ,
const char * attrName )
{
struct ldb_message_element * oc_el ;
struct ldb_message_element * allowedClasses ;
const struct dsdb_class * sclass ;
2010-06-05 20:08:45 +02:00
unsigned int i , j ;
int ret ;
2009-12-10 15:49:53 +02:00
/* If we don't have a schema yet, we can't do anything... */
if ( schema = = NULL ) {
2010-03-16 14:43:33 +11:00
ldb_asprintf_errstring ( ldb_module_get_ctx ( module ) , " cannot add childClassesEffective to %s because no schema is loaded " , ldb_dn_get_linearized ( msg - > dn ) ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2009-12-10 15:49:53 +02:00
}
/* Must remove any existing attribute, or else confusion reins */
ldb_msg_remove_attr ( msg , attrName ) ;
ret = ldb_msg_add_empty ( msg , attrName , 0 , & allowedClasses ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
oc_el = ldb_msg_find_element ( sd_msg , " objectClass " ) ;
for ( i = 0 ; oc_el & & i < oc_el - > num_values ; i + + ) {
sclass = dsdb_class_by_lDAPDisplayName_ldb_val ( schema , & oc_el - > values [ i ] ) ;
if ( ! sclass ) {
/* We don't know this class? what is going on? */
continue ;
}
for ( j = 0 ; sclass - > possibleInferiors & & sclass - > possibleInferiors [ j ] ; j + + ) {
ldb_msg_add_string ( msg , attrName , sclass - > possibleInferiors [ j ] ) ;
}
}
if ( allowedClasses - > num_values > 1 ) {
2010-02-13 12:59:43 +11:00
TYPESAFE_QSORT ( allowedClasses - > values , allowedClasses - > num_values , data_blob_cmp ) ;
2009-12-10 15:49:53 +02:00
for ( i = 1 ; i < allowedClasses - > num_values ; i + + ) {
struct ldb_val * val1 = & allowedClasses - > values [ i - 1 ] ;
struct ldb_val * val2 = & allowedClasses - > values [ i ] ;
if ( data_blob_cmp ( val1 , val2 ) = = 0 ) {
memmove ( val1 , val2 , ( allowedClasses - > num_values - i ) * sizeof ( struct ldb_val ) ) ;
allowedClasses - > num_values - - ;
i - - ;
}
}
}
return LDB_SUCCESS ;
}
static int acl_childClassesEffective ( struct ldb_module * module ,
2010-03-16 14:43:33 +11:00
const struct dsdb_schema * schema ,
2009-12-10 15:49:53 +02:00
struct ldb_message * sd_msg ,
struct ldb_message * msg ,
struct acl_context * ac )
{
struct ldb_message_element * oc_el ;
struct ldb_message_element * allowedClasses = NULL ;
const struct dsdb_class * sclass ;
struct security_descriptor * sd ;
2009-12-18 18:00:15 +02:00
struct ldb_control * as_system = ldb_request_get_control ( ac - > req ,
LDB_CONTROL_AS_SYSTEM_OID ) ;
2009-12-17 17:25:11 +02:00
struct dom_sid * sid = NULL ;
2010-06-05 20:08:45 +02:00
unsigned int i , j ;
int ret ;
2009-12-10 15:49:53 +02:00
2010-02-04 09:22:39 +01:00
if ( as_system ! = NULL ) {
as_system - > critical = 0 ;
}
2010-01-08 09:30:31 +11:00
if ( ac - > am_system | | as_system ) {
2010-03-16 14:43:33 +11:00
return acl_childClasses ( module , schema , sd_msg , msg , " allowedChildClassesEffective " ) ;
2009-12-10 15:49:53 +02:00
}
/* If we don't have a schema yet, we can't do anything... */
if ( schema = = NULL ) {
2010-03-16 14:43:33 +11:00
ldb_asprintf_errstring ( ldb_module_get_ctx ( module ) , " cannot add allowedChildClassesEffective to %s because no schema is loaded " , ldb_dn_get_linearized ( msg - > dn ) ) ;
return LDB_ERR_OPERATIONS_ERROR ;
2009-12-10 15:49:53 +02:00
}
/* Must remove any existing attribute, or else confusion reins */
ldb_msg_remove_attr ( msg , " allowedChildClassesEffective " ) ;
oc_el = ldb_msg_find_element ( sd_msg , " objectClass " ) ;
2010-07-06 13:21:54 +10:00
ret = dsdb_get_sd_from_ldb_message ( ldb_module_get_ctx ( module ) , msg , sd_msg , & sd ) ;
2009-12-10 15:49:53 +02:00
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2010-04-16 14:28:09 +03:00
sid = samdb_result_dom_sid ( msg , sd_msg , " objectSid " ) ;
2009-12-10 15:49:53 +02:00
for ( i = 0 ; oc_el & & i < oc_el - > num_values ; i + + ) {
sclass = dsdb_class_by_lDAPDisplayName_ldb_val ( schema , & oc_el - > values [ i ] ) ;
if ( ! sclass ) {
/* We don't know this class? what is going on? */
continue ;
}
for ( j = 0 ; sclass - > possibleInferiors & & sclass - > possibleInferiors [ j ] ; j + + ) {
ret = acl_check_access_on_class ( module ,
2010-03-16 14:43:33 +11:00
schema ,
2009-12-10 15:49:53 +02:00
msg ,
sd ,
2009-12-17 17:25:11 +02:00
sid ,
2009-12-10 15:49:53 +02:00
SEC_ADS_CREATE_CHILD ,
sclass - > possibleInferiors [ j ] ) ;
if ( ret = = LDB_SUCCESS ) {
ldb_msg_add_string ( msg , " allowedChildClassesEffective " ,
sclass - > possibleInferiors [ j ] ) ;
}
}
}
allowedClasses = ldb_msg_find_element ( msg , " allowedChildClassesEffective " ) ;
if ( ! allowedClasses ) {
return LDB_SUCCESS ;
}
if ( allowedClasses - > num_values > 1 ) {
2010-02-13 12:59:43 +11:00
TYPESAFE_QSORT ( allowedClasses - > values , allowedClasses - > num_values , data_blob_cmp ) ;
2009-12-10 15:49:53 +02:00
for ( i = 1 ; i < allowedClasses - > num_values ; i + + ) {
struct ldb_val * val1 = & allowedClasses - > values [ i - 1 ] ;
struct ldb_val * val2 = & allowedClasses - > values [ i ] ;
if ( data_blob_cmp ( val1 , val2 ) = = 0 ) {
memmove ( val1 , val2 , ( allowedClasses - > num_values - i ) * sizeof ( struct ldb_val ) ) ;
allowedClasses - > num_values - - ;
i - - ;
}
}
}
return LDB_SUCCESS ;
}
static int acl_sDRightsEffective ( struct ldb_module * module ,
struct ldb_message * sd_msg ,
struct ldb_message * msg ,
struct acl_context * ac )
{
struct ldb_message_element * rightsEffective ;
int ret ;
struct security_descriptor * sd ;
2009-12-18 18:00:15 +02:00
struct ldb_control * as_system = ldb_request_get_control ( ac - > req ,
LDB_CONTROL_AS_SYSTEM_OID ) ;
2009-12-17 17:25:11 +02:00
struct dom_sid * sid = NULL ;
2009-12-10 15:49:53 +02:00
uint32_t flags = 0 ;
2010-02-04 09:22:39 +01:00
if ( as_system ! = NULL ) {
as_system - > critical = 0 ;
}
2009-12-10 15:49:53 +02:00
/* Must remove any existing attribute, or else confusion reins */
ldb_msg_remove_attr ( msg , " sDRightsEffective " ) ;
ret = ldb_msg_add_empty ( msg , " sDRightsEffective " , 0 , & rightsEffective ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2010-01-08 09:30:31 +11:00
if ( ac - > am_system | | as_system ) {
2009-12-10 15:49:53 +02:00
flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_SACL | SECINFO_DACL ;
}
else {
/* Get the security descriptor from the message */
2010-07-06 13:21:54 +10:00
ret = dsdb_get_sd_from_ldb_message ( ldb_module_get_ctx ( module ) , msg , sd_msg , & sd ) ;
2009-12-10 15:49:53 +02:00
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2010-04-16 14:28:09 +03:00
sid = samdb_result_dom_sid ( msg , sd_msg , " objectSid " ) ;
2009-12-10 15:49:53 +02:00
ret = acl_check_access_on_attribute ( module ,
msg ,
sd ,
2009-12-17 17:25:11 +02:00
sid ,
2009-12-10 15:49:53 +02:00
SEC_STD_WRITE_OWNER ,
NULL ) ;
if ( ret = = LDB_SUCCESS ) {
flags | = SECINFO_OWNER | SECINFO_GROUP ;
}
ret = acl_check_access_on_attribute ( module ,
msg ,
sd ,
2009-12-17 17:25:11 +02:00
sid ,
2009-12-10 15:49:53 +02:00
SEC_STD_WRITE_DAC ,
NULL ) ;
if ( ret = = LDB_SUCCESS ) {
flags | = SECINFO_DACL ;
}
ret = acl_check_access_on_attribute ( module ,
msg ,
sd ,
2009-12-17 17:25:11 +02:00
sid ,
2009-12-10 15:49:53 +02:00
SEC_FLAG_SYSTEM_SECURITY ,
NULL ) ;
if ( ret = = LDB_SUCCESS ) {
flags | = SECINFO_SACL ;
}
}
ldb_msg_add_fmt ( msg , " sDRightsEffective " , " %u " , flags ) ;
return LDB_SUCCESS ;
}
2009-11-05 17:34:12 +02:00
static int acl_add ( struct ldb_module * module , struct ldb_request * req )
2009-09-21 17:27:50 -07:00
{
2009-11-05 17:34:12 +02:00
int ret ;
struct ldb_dn * parent = ldb_dn_get_parent ( req , req - > op . add . message - > dn ) ;
struct ldb_context * ldb ;
2010-03-16 14:43:33 +11:00
const struct dsdb_schema * schema ;
2009-11-05 17:34:12 +02:00
struct ldb_message_element * oc_el ;
const struct GUID * guid ;
2009-12-18 18:00:15 +02:00
struct ldb_control * as_system = ldb_request_get_control ( req , LDB_CONTROL_AS_SYSTEM_OID ) ;
2009-09-21 17:27:50 -07:00
2010-02-04 09:22:39 +01:00
if ( as_system ! = NULL ) {
as_system - > critical = 0 ;
}
2010-01-08 09:30:31 +11:00
if ( dsdb_module_am_system ( module ) | | as_system ) {
2009-11-05 17:34:12 +02:00
return ldb_next_request ( module , req ) ;
2009-09-21 17:27:50 -07:00
}
2009-11-05 17:34:12 +02:00
if ( ldb_dn_is_special ( req - > op . add . message - > dn ) ) {
return ldb_next_request ( module , req ) ;
2009-09-21 17:27:50 -07:00
}
2009-11-05 17:34:12 +02:00
ldb = ldb_module_get_ctx ( module ) ;
/* Creating an NC. There is probably something we should do here,
* but we will establish that later */
2010-04-13 09:18:33 +02:00
/* FIXME: this has to be made dynamic at some point */
2009-11-05 17:34:12 +02:00
if ( ( ldb_dn_compare ( req - > op . add . message - > dn , ( ldb_get_schema_basedn ( ldb ) ) ) = = 0 ) | |
( ldb_dn_compare ( req - > op . add . message - > dn , ( ldb_get_config_basedn ( ldb ) ) ) = = 0 ) | |
2010-08-01 17:02:45 +02:00
( ldb_dn_compare ( req - > op . add . message - > dn , ( ldb_get_default_basedn ( ldb ) ) ) = = 0 ) ) {
2009-11-05 17:34:12 +02:00
return ldb_next_request ( module , req ) ;
2009-09-21 17:27:50 -07:00
}
2010-03-16 14:43:33 +11:00
schema = dsdb_get_schema ( ldb , req ) ;
if ( ! schema ) {
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2010-03-16 14:43:33 +11:00
}
2009-11-05 17:34:12 +02:00
oc_el = ldb_msg_find_element ( req - > op . add . message , " objectClass " ) ;
if ( ! oc_el | | oc_el - > num_values = = 0 ) {
DEBUG ( 10 , ( " acl:operation error %s \n " , ldb_dn_get_linearized ( req - > op . add . message - > dn ) ) ) ;
return ldb_module_done ( req , NULL , NULL , LDB_ERR_OPERATIONS_ERROR ) ;
2009-09-21 17:27:50 -07:00
}
2010-03-16 14:43:33 +11:00
guid = class_schemaid_guid_by_lDAPDisplayName ( schema ,
2009-11-05 17:34:12 +02:00
( char * ) oc_el - > values [ oc_el - > num_values - 1 ] . data ) ;
2010-03-12 03:13:51 +02:00
ret = dsdb_module_check_access_on_dn ( module , req , parent , SEC_ADS_CREATE_CHILD , guid ) ;
2009-09-21 17:27:50 -07:00
if ( ret ! = LDB_SUCCESS ) {
2009-11-05 17:34:12 +02:00
return ret ;
2009-09-21 17:27:50 -07:00
}
2009-11-05 17:34:12 +02:00
return ldb_next_request ( module , req ) ;
2009-09-21 17:27:50 -07:00
}
2010-06-28 10:34:14 +03:00
/* checks for validated writes */
2010-07-05 00:17:38 +03:00
static int acl_check_extended_right ( TALLOC_CTX * mem_ctx ,
struct security_descriptor * sd ,
struct security_token * token ,
const char * ext_right ,
uint32_t right_type ,
struct dom_sid * sid )
2010-06-28 10:34:14 +03:00
{
struct GUID right ;
NTSTATUS status ;
uint32_t access_granted ;
struct object_tree * root = NULL ;
struct object_tree * new_node = NULL ;
2010-07-05 00:17:38 +03:00
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
2010-06-28 10:34:14 +03:00
2010-07-05 00:17:38 +03:00
GUID_from_string ( ext_right , & right ) ;
2010-06-28 10:34:14 +03:00
2010-07-05 00:17:38 +03:00
if ( ! insert_in_object_tree ( tmp_ctx , & right , right_type ,
2010-06-28 10:34:14 +03:00
& root , & new_node ) ) {
2010-07-05 00:17:38 +03:00
DEBUG ( 10 , ( " acl_ext_right: cannot add to object tree \n " ) ) ;
2010-06-28 10:34:14 +03:00
talloc_free ( tmp_ctx ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
status = sec_access_check_ds ( sd , token ,
2010-07-05 00:17:38 +03:00
right_type ,
2010-06-28 10:34:14 +03:00
& access_granted ,
root ,
sid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ;
}
2010-07-05 00:17:38 +03:00
talloc_free ( tmp_ctx ) ;
2010-06-28 10:34:14 +03:00
return LDB_SUCCESS ;
}
2010-07-05 00:17:38 +03:00
2010-06-28 10:34:14 +03:00
/* ckecks if modifications are allowed on "Member" attribute */
2010-07-05 00:17:38 +03:00
static int acl_check_self_membership ( TALLOC_CTX * mem_ctx ,
struct ldb_module * module ,
2010-06-28 10:34:14 +03:00
struct ldb_request * req ,
struct security_descriptor * sd ,
struct dom_sid * sid ,
const struct GUID * oc_guid ,
const struct dsdb_attribute * attr )
{
2010-06-28 11:25:43 +02:00
int ret ;
unsigned int i ;
2010-06-28 10:34:14 +03:00
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
struct ldb_dn * user_dn ;
struct ldb_message_element * member_el ;
/* if we have wp, we can do whatever we like */
if ( acl_check_access_on_attribute ( module ,
2010-07-05 00:17:38 +03:00
mem_ctx ,
2010-06-28 10:34:14 +03:00
sd ,
sid ,
SEC_ADS_WRITE_PROP ,
attr ) = = LDB_SUCCESS ) {
return LDB_SUCCESS ;
}
/* if we are adding/deleting ourselves, check for self membership */
2010-08-14 13:30:51 +10:00
ret = dsdb_find_dn_by_sid ( ldb , mem_ctx ,
acl_user_token ( module ) - > sids [ PRIMARY_USER_SID_INDEX ] ,
& user_dn ) ;
2010-06-28 10:34:14 +03:00
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2010-06-29 11:46:22 +03:00
member_el = ldb_msg_find_element ( req - > op . mod . message , " member " ) ;
2010-06-28 10:34:14 +03:00
if ( ! member_el ) {
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2010-06-28 10:34:14 +03:00
}
/* user can only remove oneself */
if ( member_el - > num_values = = 0 ) {
return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ;
}
for ( i = 0 ; i < member_el - > num_values ; i + + ) {
if ( strcasecmp ( ( const char * ) member_el - > values [ i ] . data ,
2010-07-05 00:17:38 +03:00
ldb_dn_get_extended_linearized ( mem_ctx , user_dn , 1 ) ) ! = 0 ) {
2010-06-28 10:34:14 +03:00
return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ;
}
}
2010-07-05 00:17:38 +03:00
ret = acl_check_extended_right ( mem_ctx , sd , acl_user_token ( module ) ,
GUID_DRS_SELF_MEMBERSHIP ,
SEC_ADS_SELF_WRITE ,
sid ) ;
if ( ret = = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ) {
dsdb_acl_debug ( sd , acl_user_token ( module ) ,
req - > op . mod . message - > dn ,
true ,
10 ) ;
}
return ret ;
}
static int acl_check_password_rights ( TALLOC_CTX * mem_ctx ,
struct ldb_module * module ,
struct ldb_request * req ,
struct security_descriptor * sd ,
struct dom_sid * sid ,
const struct GUID * oc_guid )
{
int ret = LDB_SUCCESS ;
unsigned int del_attr_cnt = 0 , add_attr_cnt = 0 , rep_attr_cnt = 0 ;
struct ldb_message_element * el ;
struct ldb_message * msg ;
2010-07-08 14:51:49 +02:00
const char * passwordAttrs [ ] = { " userPassword " , " clearTextPassword " ,
" unicodePwd " , " dBCSPwd " , NULL } , * * l ;
2010-07-05 00:17:38 +03:00
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
msg = ldb_msg_copy_shallow ( tmp_ctx , req - > op . mod . message ) ;
if ( msg = = NULL ) {
2010-07-06 13:21:54 +10:00
return ldb_module_oom ( module ) ;
2010-07-05 00:17:38 +03:00
}
for ( l = passwordAttrs ; * l ! = NULL ; l + + ) {
while ( ( el = ldb_msg_find_element ( msg , * l ) ) ! = NULL ) {
2010-08-17 11:21:11 +10:00
if ( LDB_FLAG_MOD_TYPE ( el - > flags ) = = LDB_FLAG_MOD_DELETE ) {
2010-07-05 00:17:38 +03:00
+ + del_attr_cnt ;
}
2010-08-17 11:21:11 +10:00
if ( LDB_FLAG_MOD_TYPE ( el - > flags ) = = LDB_FLAG_MOD_ADD ) {
2010-07-05 00:17:38 +03:00
+ + add_attr_cnt ;
}
2010-08-17 11:21:11 +10:00
if ( LDB_FLAG_MOD_TYPE ( el - > flags ) = = LDB_FLAG_MOD_REPLACE ) {
2010-07-05 00:17:38 +03:00
+ + rep_attr_cnt ;
}
ldb_msg_remove_element ( msg , el ) ;
}
}
/* a single delete will be handled by password hash
later in the stack , so we let it though here */
if ( del_attr_cnt > 0 & & add_attr_cnt = = 0 ) {
talloc_free ( tmp_ctx ) ;
return LDB_SUCCESS ;
}
2010-07-08 16:00:19 +02:00
if ( ldb_request_get_control ( req ,
DSDB_CONTROL_PASSWORD_CHANGE_OID ) ! = NULL ) {
/* The "DSDB_CONTROL_PASSWORD_CHANGE_OID" control means that we
* have a user password change and not a set as the message
* looks like . In it ' s value blob it contains the NT and / or LM
* hash of the old password specified by the user .
* This control is used by the SAMR and " kpasswd " password
* change mechanisms . */
ret = acl_check_extended_right ( tmp_ctx , sd , acl_user_token ( module ) ,
GUID_DRS_USER_CHANGE_PASSWORD ,
SEC_ADS_CONTROL_ACCESS ,
sid ) ;
}
else if ( rep_attr_cnt > 0 | | ( add_attr_cnt ! = del_attr_cnt ) ) {
2010-07-05 00:17:38 +03:00
ret = acl_check_extended_right ( tmp_ctx , sd , acl_user_token ( module ) ,
GUID_DRS_FORCE_CHANGE_PASSWORD ,
SEC_ADS_CONTROL_ACCESS ,
sid ) ;
}
else if ( add_attr_cnt = = 1 & & del_attr_cnt = = 1 ) {
ret = acl_check_extended_right ( tmp_ctx , sd , acl_user_token ( module ) ,
GUID_DRS_USER_CHANGE_PASSWORD ,
SEC_ADS_CONTROL_ACCESS ,
sid ) ;
/* Very strange, but we get constraint violation in this case */
if ( ret = = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ) {
ret = LDB_ERR_CONSTRAINT_VIOLATION ;
}
}
if ( ret ! = LDB_SUCCESS ) {
dsdb_acl_debug ( sd , acl_user_token ( module ) ,
req - > op . mod . message - > dn ,
true ,
10 ) ;
}
2010-06-28 10:34:14 +03:00
talloc_free ( tmp_ctx ) ;
2010-07-05 00:17:38 +03:00
return ret ;
2010-06-28 10:34:14 +03:00
}
2009-11-05 17:34:12 +02:00
static int acl_modify ( struct ldb_module * module , struct ldb_request * req )
2009-09-21 17:27:50 -07:00
{
int ret ;
2009-11-05 17:34:12 +02:00
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
2010-03-16 14:43:33 +11:00
const struct dsdb_schema * schema ;
2010-03-07 19:16:24 +01:00
unsigned int i ;
2009-11-05 17:34:12 +02:00
const struct GUID * guid ;
uint32_t access_granted ;
struct object_tree * root = NULL ;
struct object_tree * new_node = NULL ;
NTSTATUS status ;
struct ldb_result * acl_res ;
struct security_descriptor * sd ;
2009-12-17 17:25:11 +02:00
struct dom_sid * sid = NULL ;
2009-12-18 18:00:15 +02:00
struct ldb_control * as_system = ldb_request_get_control ( req , LDB_CONTROL_AS_SYSTEM_OID ) ;
2009-11-05 17:34:12 +02:00
TALLOC_CTX * tmp_ctx = talloc_new ( req ) ;
static const char * acl_attrs [ ] = {
" nTSecurityDescriptor " ,
" objectClass " ,
2009-12-17 17:25:11 +02:00
" objectSid " ,
2009-11-05 17:34:12 +02:00
NULL
} ;
2010-02-04 09:22:39 +01:00
if ( as_system ! = NULL ) {
as_system - > critical = 0 ;
}
2009-12-14 20:32:28 -05:00
/* Don't print this debug statement if elements[0].name is going to be NULL */
if ( req - > op . mod . message - > num_elements > 0 )
{
DEBUG ( 10 , ( " ldb:acl_modify: %s \n " , req - > op . mod . message - > elements [ 0 ] . name ) ) ;
}
2010-01-08 09:30:31 +11:00
if ( dsdb_module_am_system ( module ) | | as_system ) {
2009-09-21 17:27:50 -07:00
return ldb_next_request ( module , req ) ;
}
2009-11-05 17:34:12 +02:00
if ( ldb_dn_is_special ( req - > op . mod . message - > dn ) ) {
2009-09-21 17:27:50 -07:00
return ldb_next_request ( module , req ) ;
}
2010-07-05 00:17:38 +03:00
ret = dsdb_module_search_dn ( module , tmp_ctx , & acl_res , req - > op . mod . message - > dn ,
2010-07-06 03:26:03 +03:00
acl_attrs ,
DSDB_FLAG_NEXT_MODULE ) ;
2009-09-21 17:27:50 -07:00
2009-11-05 17:34:12 +02:00
if ( ret ! = LDB_SUCCESS ) {
2010-07-05 00:17:38 +03:00
goto fail ;
2009-11-05 17:34:12 +02:00
}
2009-09-21 17:27:50 -07:00
2010-07-05 00:17:38 +03:00
schema = dsdb_get_schema ( ldb , tmp_ctx ) ;
2010-03-16 14:43:33 +11:00
if ( ! schema ) {
2010-07-05 00:17:38 +03:00
ret = LDB_ERR_OPERATIONS_ERROR ;
goto fail ;
2010-03-16 14:43:33 +11:00
}
2010-07-06 13:21:54 +10:00
ret = dsdb_get_sd_from_ldb_message ( ldb , tmp_ctx , acl_res - > msgs [ 0 ] , & sd ) ;
2009-11-05 17:34:12 +02:00
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " acl_modify: cannot get descriptor \n " ) ) ;
2010-07-05 00:17:38 +03:00
goto fail ;
2009-11-05 17:34:12 +02:00
}
/* Theoretically we pass the check if the object has no sd */
if ( ! sd ) {
2010-07-05 00:17:38 +03:00
goto success ;
2009-11-05 17:34:12 +02:00
}
2009-09-21 17:27:50 -07:00
2010-03-16 14:43:33 +11:00
guid = get_oc_guid_from_message ( module , schema , acl_res - > msgs [ 0 ] ) ;
2009-11-05 17:34:12 +02:00
if ( ! guid ) {
DEBUG ( 10 , ( " acl_modify: cannot get guid \n " ) ) ;
goto fail ;
}
2010-04-16 14:28:09 +03:00
sid = samdb_result_dom_sid ( req , acl_res - > msgs [ 0 ] , " objectSid " ) ;
2009-11-05 17:34:12 +02:00
if ( ! insert_in_object_tree ( tmp_ctx , guid , SEC_ADS_WRITE_PROP ,
2009-12-10 15:49:53 +02:00
& root , & new_node ) ) {
2009-11-05 17:34:12 +02:00
DEBUG ( 10 , ( " acl_modify: cannot add to object tree \n " ) ) ;
goto fail ;
2009-09-21 17:27:50 -07:00
}
2009-11-05 17:34:12 +02:00
for ( i = 0 ; i < req - > op . mod . message - > num_elements ; i + + ) {
const struct dsdb_attribute * attr ;
2010-07-05 00:17:38 +03:00
attr = dsdb_attribute_by_lDAPDisplayName ( schema ,
2009-11-05 17:34:12 +02:00
req - > op . mod . message - > elements [ i ] . name ) ;
2010-06-05 20:19:31 +02:00
2010-06-06 19:06:58 +02:00
if ( ldb_attr_cmp ( " nTSecurityDescriptor " , req - > op . mod . message - > elements [ i ] . name ) = = 0 ) {
2010-07-05 00:17:38 +03:00
status = sec_access_check_ds ( sd , acl_user_token ( module ) ,
SEC_STD_WRITE_DAC ,
& access_granted ,
NULL ,
sid ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " Object %s has no write dacl access \n " ,
ldb_dn_get_linearized ( req - > op . mod . message - > dn ) ) ) ;
dsdb_acl_debug ( sd ,
acl_user_token ( module ) ,
req - > op . mod . message - > dn ,
true ,
10 ) ;
ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ;
goto fail ;
}
2010-06-28 10:34:14 +03:00
}
2010-06-29 11:46:22 +03:00
else if ( ldb_attr_cmp ( " member " , req - > op . mod . message - > elements [ i ] . name ) = = 0 ) {
2010-07-05 00:17:38 +03:00
ret = acl_check_self_membership ( tmp_ctx ,
module ,
2010-06-28 10:34:14 +03:00
req ,
sd ,
sid ,
guid ,
attr ) ;
if ( ret ! = LDB_SUCCESS ) {
2010-07-05 00:17:38 +03:00
goto fail ;
}
}
else if ( ldb_attr_cmp ( " dBCSPwd " , req - > op . mod . message - > elements [ i ] . name ) = = 0 ) {
/* this one is not affected by any rights, we should let it through
so that passwords_hash returns the correct error */
continue ;
}
else if ( ldb_attr_cmp ( " unicodePwd " , req - > op . mod . message - > elements [ i ] . name ) = = 0 | |
ldb_attr_cmp ( " userPassword " , req - > op . mod . message - > elements [ i ] . name ) = = 0 | |
ldb_attr_cmp ( " clearTextPassword " , req - > op . mod . message - > elements [ i ] . name ) = = 0 ) {
ret = acl_check_password_rights ( tmp_ctx ,
module ,
req ,
sd ,
sid ,
guid ) ;
if ( ret ! = LDB_SUCCESS ) {
goto fail ;
2010-06-28 10:34:14 +03:00
}
2009-11-15 22:31:44 +02:00
} else {
2010-07-05 00:17:38 +03:00
/* This basic attribute existence check with the right errorcode
* is needed since this module is the first one which requests
* schema attribute informations .
* The complete attribute checking is done in the
* " objectclass_attrs " module behind this one .
*/
if ( ! attr ) {
ldb_asprintf_errstring ( ldb , " acl_modify: attribute '%s' on entry '%s' was not found in the schema! " ,
req - > op . mod . message - > elements [ i ] . name ,
ldb_dn_get_linearized ( req - > op . mod . message - > dn ) ) ;
ret = LDB_ERR_NO_SUCH_ATTRIBUTE ;
goto fail ;
}
2009-11-15 22:31:44 +02:00
if ( ! insert_in_object_tree ( tmp_ctx ,
& attr - > attributeSecurityGUID , SEC_ADS_WRITE_PROP ,
& new_node , & new_node ) ) {
DEBUG ( 10 , ( " acl_modify: cannot add to object tree securityGUID \n " ) ) ;
2010-07-05 00:17:38 +03:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2009-11-15 22:31:44 +02:00
goto fail ;
}
if ( ! insert_in_object_tree ( tmp_ctx ,
& attr - > schemaIDGUID , SEC_ADS_WRITE_PROP , & new_node , & new_node ) ) {
DEBUG ( 10 , ( " acl_modify: cannot add to object tree attributeGUID \n " ) ) ;
2010-07-05 00:17:38 +03:00
ret = LDB_ERR_OPERATIONS_ERROR ;
2009-11-15 22:31:44 +02:00
goto fail ;
}
2009-11-05 17:34:12 +02:00
}
2009-11-15 22:31:44 +02:00
}
2009-09-21 17:27:50 -07:00
2009-11-15 22:31:44 +02:00
if ( root - > num_of_children > 0 ) {
status = sec_access_check_ds ( sd , acl_user_token ( module ) ,
SEC_ADS_WRITE_PROP ,
& access_granted ,
2009-12-17 17:25:11 +02:00
root ,
sid ) ;
2009-11-15 22:31:44 +02:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-05-10 12:37:50 +02:00
DEBUG ( 10 , ( " Object %s has no write property access \n " ,
2009-12-10 15:49:53 +02:00
ldb_dn_get_linearized ( req - > op . mod . message - > dn ) ) ) ;
2010-03-11 23:10:38 +02:00
dsdb_acl_debug ( sd ,
2009-11-15 22:31:44 +02:00
acl_user_token ( module ) ,
req - > op . mod . message - > dn ,
true ,
10 ) ;
2010-07-05 00:17:38 +03:00
ret = LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ;
goto fail ;
2009-11-15 22:31:44 +02:00
}
2009-11-05 17:34:12 +02:00
}
2010-07-05 00:17:38 +03:00
success :
2009-11-05 17:34:12 +02:00
talloc_free ( tmp_ctx ) ;
2009-09-21 17:27:50 -07:00
return ldb_next_request ( module , req ) ;
2009-11-05 17:34:12 +02:00
fail :
talloc_free ( tmp_ctx ) ;
2010-07-05 00:17:38 +03:00
return ret ;
2009-09-21 17:27:50 -07:00
}
/* similar to the modify for the time being.
* We need to concider the special delete tree case , though - TODO */
static int acl_delete ( struct ldb_module * module , struct ldb_request * req )
{
int ret ;
2009-11-05 17:34:12 +02:00
struct ldb_dn * parent = ldb_dn_get_parent ( req , req - > op . del . dn ) ;
2009-09-21 17:27:50 -07:00
struct ldb_context * ldb ;
2009-12-18 18:00:15 +02:00
struct ldb_control * as_system = ldb_request_get_control ( req , LDB_CONTROL_AS_SYSTEM_OID ) ;
2009-09-21 17:27:50 -07:00
2010-02-04 09:22:39 +01:00
if ( as_system ! = NULL ) {
as_system - > critical = 0 ;
}
2009-11-05 17:34:12 +02:00
DEBUG ( 10 , ( " ldb:acl_delete: %s \n " , ldb_dn_get_linearized ( req - > op . del . dn ) ) ) ;
2010-01-08 09:30:31 +11:00
if ( dsdb_module_am_system ( module ) | | as_system ) {
2009-09-21 17:27:50 -07:00
return ldb_next_request ( module , req ) ;
}
2009-11-05 17:34:12 +02:00
if ( ldb_dn_is_special ( req - > op . del . dn ) ) {
2009-09-21 17:27:50 -07:00
return ldb_next_request ( module , req ) ;
}
ldb = ldb_module_get_ctx ( module ) ;
2009-11-05 17:34:12 +02:00
/* first check if we have delete object right */
2010-03-12 03:13:51 +02:00
ret = dsdb_module_check_access_on_dn ( module , req , req - > op . del . dn , SEC_STD_DELETE , NULL ) ;
2009-11-05 17:34:12 +02:00
if ( ret = = LDB_SUCCESS ) {
2009-09-21 17:27:50 -07:00
return ldb_next_request ( module , req ) ;
}
2009-11-05 17:34:12 +02:00
/* Nope, we don't have delete object. Lets check if we have delete child on the parent */
/* No parent, so check fails */
2010-04-13 09:18:33 +02:00
/* FIXME: this has to be made dynamic at some point */
2009-11-05 17:34:12 +02:00
if ( ( ldb_dn_compare ( req - > op . del . dn , ( ldb_get_schema_basedn ( ldb ) ) ) = = 0 ) | |
( ldb_dn_compare ( req - > op . del . dn , ( ldb_get_config_basedn ( ldb ) ) ) = = 0 ) | |
2010-08-01 17:02:45 +02:00
( ldb_dn_compare ( req - > op . del . dn , ( ldb_get_default_basedn ( ldb ) ) ) = = 0 ) ) {
2009-11-05 17:34:12 +02:00
DEBUG ( 10 , ( " acl:deleting an NC \n " ) ) ;
return ldb_module_done ( req , NULL , NULL , LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ) ;
2009-09-21 17:27:50 -07:00
}
2010-03-12 03:13:51 +02:00
ret = dsdb_module_check_access_on_dn ( module , req , parent , SEC_ADS_DELETE_CHILD , NULL ) ;
2009-11-05 17:34:12 +02:00
if ( ret ! = LDB_SUCCESS ) {
2009-09-21 17:27:50 -07:00
return ret ;
2009-11-05 17:34:12 +02:00
}
return ldb_next_request ( module , req ) ;
2009-09-21 17:27:50 -07:00
}
2009-11-05 17:34:12 +02:00
static int acl_rename ( struct ldb_module * module , struct ldb_request * req )
2009-09-21 17:27:50 -07:00
{
2009-11-05 17:34:12 +02:00
int ret ;
struct ldb_dn * oldparent = ldb_dn_get_parent ( req , req - > op . rename . olddn ) ;
struct ldb_dn * newparent = ldb_dn_get_parent ( req , req - > op . rename . newdn ) ;
2010-03-16 14:43:33 +11:00
const struct dsdb_schema * schema ;
2009-09-21 17:27:50 -07:00
struct ldb_context * ldb ;
2009-11-05 17:34:12 +02:00
struct security_descriptor * sd = NULL ;
2009-12-17 17:25:11 +02:00
struct dom_sid * sid = NULL ;
2009-11-05 17:34:12 +02:00
struct ldb_result * acl_res ;
const struct GUID * guid ;
struct object_tree * root = NULL ;
struct object_tree * new_node = NULL ;
2009-12-18 18:00:15 +02:00
struct ldb_control * as_system = ldb_request_get_control ( req , LDB_CONTROL_AS_SYSTEM_OID ) ;
2009-11-05 17:34:12 +02:00
TALLOC_CTX * tmp_ctx = talloc_new ( req ) ;
2009-09-21 17:27:50 -07:00
NTSTATUS status ;
2009-11-05 17:34:12 +02:00
uint32_t access_granted ;
2010-03-07 21:42:53 +02:00
const char * rdn_name ;
2009-11-05 17:34:12 +02:00
static const char * acl_attrs [ ] = {
" nTSecurityDescriptor " ,
" objectClass " ,
2009-12-17 17:25:11 +02:00
" objectSid " ,
2009-11-05 17:34:12 +02:00
NULL
} ;
2010-02-04 09:22:39 +01:00
if ( as_system ! = NULL ) {
as_system - > critical = 0 ;
}
2009-11-05 17:34:12 +02:00
DEBUG ( 10 , ( " ldb:acl_rename: %s \n " , ldb_dn_get_linearized ( req - > op . rename . olddn ) ) ) ;
2010-01-08 09:30:31 +11:00
if ( dsdb_module_am_system ( module ) | | as_system ) {
2009-11-05 17:34:12 +02:00
return ldb_next_request ( module , req ) ;
2009-09-21 17:27:50 -07:00
}
2009-11-05 17:34:12 +02:00
if ( ldb_dn_is_special ( req - > op . rename . olddn ) ) {
return ldb_next_request ( module , req ) ;
2009-09-21 17:27:50 -07:00
}
2009-11-05 17:34:12 +02:00
ldb = ldb_module_get_ctx ( module ) ;
2009-09-21 17:27:50 -07:00
2010-03-12 02:21:16 +02:00
ret = dsdb_module_search_dn ( module , req , & acl_res , req - > op . rename . olddn ,
2010-07-06 03:26:03 +03:00
acl_attrs ,
DSDB_FLAG_NEXT_MODULE |
DSDB_SEARCH_SHOW_DELETED ) ;
2009-11-05 17:34:12 +02:00
/* we sould be able to find the parent */
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " acl: failed to find object %s \n " ,
ldb_dn_get_linearized ( req - > op . rename . olddn ) ) ) ;
return ret ;
2009-09-21 17:27:50 -07:00
}
2010-03-16 14:43:33 +11:00
schema = dsdb_get_schema ( ldb , acl_res ) ;
if ( ! schema ) {
talloc_free ( acl_res ) ;
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2010-03-16 14:43:33 +11:00
}
guid = get_oc_guid_from_message ( module , schema , acl_res - > msgs [ 0 ] ) ;
2009-11-05 17:34:12 +02:00
if ( ! insert_in_object_tree ( tmp_ctx , guid , SEC_ADS_WRITE_PROP ,
& root , & new_node ) ) {
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2009-11-05 17:34:12 +02:00
} ;
2009-09-21 17:27:50 -07:00
2010-03-16 14:43:33 +11:00
guid = attribute_schemaid_guid_by_lDAPDisplayName ( schema ,
2009-11-05 17:34:12 +02:00
" name " ) ;
if ( ! insert_in_object_tree ( tmp_ctx , guid , SEC_ADS_WRITE_PROP ,
& new_node , & new_node ) ) {
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2009-11-05 17:34:12 +02:00
} ;
2009-09-21 17:27:50 -07:00
2010-03-07 21:42:53 +02:00
rdn_name = ldb_dn_get_rdn_name ( req - > op . rename . olddn ) ;
if ( rdn_name = = NULL ) {
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2010-03-07 21:42:53 +02:00
}
2010-03-16 14:43:33 +11:00
guid = attribute_schemaid_guid_by_lDAPDisplayName ( schema ,
2010-03-07 21:42:53 +02:00
rdn_name ) ;
if ( ! insert_in_object_tree ( tmp_ctx , guid , SEC_ADS_WRITE_PROP ,
& new_node , & new_node ) ) {
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2010-03-07 21:42:53 +02:00
} ;
2010-07-06 13:21:54 +10:00
ret = dsdb_get_sd_from_ldb_message ( ldb , req , acl_res - > msgs [ 0 ] , & sd ) ;
2009-09-21 17:27:50 -07:00
2009-11-05 17:34:12 +02:00
if ( ret ! = LDB_SUCCESS ) {
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2009-11-05 17:34:12 +02:00
}
/* Theoretically we pass the check if the object has no sd */
if ( ! sd ) {
return LDB_SUCCESS ;
}
2010-04-16 14:28:09 +03:00
sid = samdb_result_dom_sid ( req , acl_res - > msgs [ 0 ] , " objectSid " ) ;
2009-11-05 17:34:12 +02:00
status = sec_access_check_ds ( sd , acl_user_token ( module ) ,
SEC_ADS_WRITE_PROP ,
& access_granted ,
2009-12-17 17:25:11 +02:00
root ,
sid ) ;
2009-11-05 17:34:12 +02:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2010-05-10 12:37:50 +02:00
DEBUG ( 10 , ( " Object %s has no wp on name \n " ,
2009-11-05 17:34:12 +02:00
ldb_dn_get_linearized ( req - > op . rename . olddn ) ) ) ;
2010-03-11 23:10:38 +02:00
dsdb_acl_debug ( sd ,
2009-11-05 17:34:12 +02:00
acl_user_token ( module ) ,
req - > op . rename . olddn ,
true ,
10 ) ;
return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ;
}
2009-09-21 17:27:50 -07:00
2009-11-05 17:34:12 +02:00
if ( ldb_dn_compare ( oldparent , newparent ) = = 0 ) {
/* regular rename, not move, nothing more to do */
2009-09-21 17:27:50 -07:00
return ldb_next_request ( module , req ) ;
2009-11-05 17:34:12 +02:00
}
2009-09-21 17:27:50 -07:00
2009-11-05 17:34:12 +02:00
/* What exactly to do in this case? It would fail anyway.. */
2010-04-13 09:18:33 +02:00
/* FIXME: this has to be made dynamic at some point */
2009-11-05 17:34:12 +02:00
if ( ( ldb_dn_compare ( req - > op . rename . newdn , ( ldb_get_schema_basedn ( ldb ) ) ) = = 0 ) | |
( ldb_dn_compare ( req - > op . rename . newdn , ( ldb_get_config_basedn ( ldb ) ) ) = = 0 ) | |
2010-08-01 17:02:45 +02:00
( ldb_dn_compare ( req - > op . rename . newdn , ( ldb_get_default_basedn ( ldb ) ) ) = = 0 ) ) {
2009-11-05 17:34:12 +02:00
DEBUG ( 10 , ( " acl:moving as an NC \n " ) ) ;
return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ;
2009-12-10 15:49:53 +02:00
}
2009-11-05 17:34:12 +02:00
/* new parent should have create child */
talloc_free ( tmp_ctx ) ;
tmp_ctx = talloc_new ( req ) ;
root = NULL ;
new_node = NULL ;
2010-03-16 14:43:33 +11:00
guid = get_oc_guid_from_message ( module , schema , acl_res - > msgs [ 0 ] ) ;
2009-11-05 17:34:12 +02:00
if ( ! guid ) {
DEBUG ( 10 , ( " acl:renamed object has no object class \n " ) ) ;
return ldb_module_done ( req , NULL , NULL , LDB_ERR_OPERATIONS_ERROR ) ;
}
2010-03-11 23:10:38 +02:00
2010-03-12 03:13:51 +02:00
ret = dsdb_module_check_access_on_dn ( module , req , newparent , SEC_ADS_CREATE_CHILD , guid ) ;
2009-11-05 17:34:12 +02:00
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " acl:access_denied renaming %s " , ldb_dn_get_linearized ( req - > op . rename . olddn ) ) ) ;
return ret ;
}
/* do we have delete object on the object? */
2009-09-21 17:27:50 -07:00
2009-11-05 17:34:12 +02:00
status = sec_access_check_ds ( sd , acl_user_token ( module ) ,
SEC_STD_DELETE ,
& access_granted ,
2009-12-17 17:25:11 +02:00
NULL ,
sid ) ;
2009-09-21 17:27:50 -07:00
2009-11-05 17:34:12 +02:00
if ( NT_STATUS_IS_OK ( status ) ) {
2009-09-21 17:27:50 -07:00
return ldb_next_request ( module , req ) ;
}
2009-11-05 17:34:12 +02:00
/* what about delete child on the current parent */
2010-03-12 03:13:51 +02:00
ret = dsdb_module_check_access_on_dn ( module , req , oldparent , SEC_ADS_DELETE_CHILD , NULL ) ;
2009-11-05 17:34:12 +02:00
if ( ret ! = LDB_SUCCESS ) {
DEBUG ( 10 , ( " acl:access_denied renaming %s " , ldb_dn_get_linearized ( req - > op . rename . olddn ) ) ) ;
return ldb_module_done ( req , NULL , NULL , ret ) ;
2009-09-21 17:27:50 -07:00
}
2009-11-05 17:34:12 +02:00
return ldb_next_request ( module , req ) ;
2009-09-21 17:27:50 -07:00
}
2009-12-10 15:49:53 +02:00
static int acl_search_callback ( struct ldb_request * req , struct ldb_reply * ares )
{
struct ldb_context * ldb ;
struct acl_context * ac ;
struct acl_private * data ;
struct ldb_result * acl_res ;
static const char * acl_attrs [ ] = {
" objectClass " ,
" nTSecurityDescriptor " ,
2009-12-17 17:25:11 +02:00
" objectSid " ,
2009-12-10 15:49:53 +02:00
NULL
} ;
int ret , i ;
ac = talloc_get_type ( req - > context , struct acl_context ) ;
data = talloc_get_type ( ldb_module_get_private ( ac - > module ) , struct acl_private ) ;
ldb = ldb_module_get_ctx ( ac - > module ) ;
if ( ! ares ) {
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
}
if ( ares - > error ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , ares - > controls ,
ares - > response , ares - > error ) ;
}
switch ( ares - > type ) {
case LDB_REPLY_ENTRY :
if ( ac - > allowedAttributes
| | ac - > allowedChildClasses
| | ac - > allowedChildClassesEffective
| | ac - > allowedAttributesEffective
| | ac - > sDRightsEffective ) {
2010-03-12 02:21:16 +02:00
ret = dsdb_module_search_dn ( ac - > module , ac , & acl_res , ares - > message - > dn ,
2010-07-06 03:26:03 +03:00
acl_attrs ,
DSDB_FLAG_NEXT_MODULE ) ;
2009-12-10 15:49:53 +02:00
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
if ( ac - > allowedAttributes | | ac - > allowedAttributesEffective ) {
2010-03-16 14:43:33 +11:00
ret = acl_allowedAttributes ( ac - > module , ac - > schema , acl_res - > msgs [ 0 ] , ares - > message , ac ) ;
2009-12-10 15:49:53 +02:00
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
}
if ( ac - > allowedChildClasses ) {
2010-03-16 14:43:33 +11:00
ret = acl_childClasses ( ac - > module , ac - > schema , acl_res - > msgs [ 0 ] ,
2009-12-10 15:49:53 +02:00
ares - > message , " allowedChildClasses " ) ;
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
}
if ( ac - > allowedChildClassesEffective ) {
2010-03-16 14:43:33 +11:00
ret = acl_childClassesEffective ( ac - > module , ac - > schema ,
2009-12-10 15:49:53 +02:00
acl_res - > msgs [ 0 ] , ares - > message , ac ) ;
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
}
if ( ac - > sDRightsEffective ) {
2010-03-16 14:43:33 +11:00
ret = acl_sDRightsEffective ( ac - > module ,
2009-12-10 15:49:53 +02:00
acl_res - > msgs [ 0 ] , ares - > message , ac ) ;
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
}
}
if ( data & & data - > password_attrs ) {
2010-01-08 09:30:31 +11:00
if ( ! ac - > am_system ) {
2009-12-10 15:49:53 +02:00
for ( i = 0 ; data - > password_attrs [ i ] ; i + + ) {
ldb_msg_remove_attr ( ares - > message , data - > password_attrs [ i ] ) ;
}
}
}
return ldb_module_send_entry ( ac - > req , ares - > message , ares - > controls ) ;
case LDB_REPLY_REFERRAL :
return ldb_module_send_referral ( ac - > req , ares - > referral ) ;
case LDB_REPLY_DONE :
return ldb_module_done ( ac - > req , ares - > controls ,
ares - > response , LDB_SUCCESS ) ;
}
return LDB_SUCCESS ;
}
static int acl_search ( struct ldb_module * module , struct ldb_request * req )
{
struct ldb_context * ldb ;
struct acl_context * ac ;
struct ldb_request * down_req ;
struct acl_private * data ;
int ret , i ;
ldb = ldb_module_get_ctx ( module ) ;
ac = talloc_zero ( req , struct acl_context ) ;
if ( ac = = NULL ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb ) ;
2009-12-10 15:49:53 +02:00
}
data = talloc_get_type ( ldb_module_get_private ( module ) , struct acl_private ) ;
ac - > module = module ;
ac - > req = req ;
2010-01-08 09:30:31 +11:00
ac - > am_system = dsdb_module_am_system ( module ) ;
2009-12-10 15:49:53 +02:00
ac - > allowedAttributes = ldb_attr_in_list ( req - > op . search . attrs , " allowedAttributes " ) ;
ac - > allowedAttributesEffective = ldb_attr_in_list ( req - > op . search . attrs , " allowedAttributesEffective " ) ;
ac - > allowedChildClasses = ldb_attr_in_list ( req - > op . search . attrs , " allowedChildClasses " ) ;
ac - > allowedChildClassesEffective = ldb_attr_in_list ( req - > op . search . attrs , " allowedChildClassesEffective " ) ;
ac - > sDRightsEffective = ldb_attr_in_list ( req - > op . search . attrs , " sDRightsEffective " ) ;
2010-03-16 14:43:33 +11:00
ac - > schema = dsdb_get_schema ( ldb , ac ) ;
2009-12-10 15:49:53 +02:00
/* replace any attributes in the parse tree that are private,
so we don ' t allow a search for ' userPassword = penguin ' ,
just as we would not allow that attribute to be returned */
2010-01-08 09:30:31 +11:00
if ( ac - > am_system ) {
2009-12-10 15:49:53 +02:00
/* FIXME: We should copy the tree and keep the original unmodified. */
/* remove password attributes */
if ( data & & data - > password_attrs ) {
for ( i = 0 ; data - > password_attrs [ i ] ; i + + ) {
ldb_parse_tree_attr_replace ( req - > op . search . tree ,
data - > password_attrs [ i ] ,
" kludgeACLredactedattribute " ) ;
}
}
}
ret = ldb_build_search_req_ex ( & down_req ,
ldb , ac ,
req - > op . search . base ,
req - > op . search . scope ,
req - > op . search . tree ,
req - > op . search . attrs ,
req - > controls ,
ac , acl_search_callback ,
req ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
/* perform the search */
return ldb_next_request ( module , down_req ) ;
}
2010-08-04 15:22:17 +03:00
static const char * acl_user_name ( TALLOC_CTX * mem_ctx , struct ldb_module * module )
{
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
struct auth_session_info * session_info
= ( struct auth_session_info * ) ldb_get_opaque ( ldb , " sessionInfo " ) ;
if ( ! session_info ) {
return " UNKNOWN (NULL) " ;
}
return talloc_asprintf ( mem_ctx , " %s \\ %s " ,
session_info - > server_info - > domain_name ,
session_info - > server_info - > account_name ) ;
}
static int acl_extended ( struct ldb_module * module , struct ldb_request * req )
{
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
struct ldb_control * as_system = ldb_request_get_control ( req , LDB_CONTROL_AS_SYSTEM_OID ) ;
/* allow everybody to read the sequence number */
if ( strcmp ( req - > op . extended . oid ,
LDB_EXTENDED_SEQUENCE_NUMBER ) = = 0 ) {
return ldb_next_request ( module , req ) ;
}
if ( dsdb_module_am_system ( module ) | |
dsdb_module_am_administrator ( module ) | | as_system ) {
return ldb_next_request ( module , req ) ;
} else {
ldb_asprintf_errstring ( ldb ,
" acl_extended: "
" attempted database modify not permitted. "
" User %s is not SYSTEM or an administrator " ,
acl_user_name ( req , module ) ) ;
return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS ;
}
}
2009-09-21 17:27:50 -07:00
_PUBLIC_ const struct ldb_module_ops ldb_acl_module_ops = {
. name = " acl " ,
2009-12-10 15:49:53 +02:00
. search = acl_search ,
2009-09-21 17:27:50 -07:00
. add = acl_add ,
. modify = acl_modify ,
. del = acl_delete ,
. rename = acl_rename ,
2010-08-04 15:22:17 +03:00
. extended = acl_extended ,
2009-09-21 17:27:50 -07:00
. init_context = acl_module_init
} ;