2009-10-10 09:06:07 +11:00
/*
Unix SMB / CIFS implementation .
Samba utility functions
Copyright ( C ) Andrew Tridgell 2009
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2009
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/>.
*/
2009-11-16 18:32:17 +11:00
# include "includes.h"
2009-10-10 09:06:07 +11:00
# include "ldb.h"
# include "ldb_module.h"
2009-12-16 11:31:30 +11:00
# include "librpc/ndr/libndr.h"
2009-11-16 18:32:17 +11:00
# include "dsdb/samdb/ldb_modules/util.h"
# include "dsdb/samdb/samdb.h"
2009-12-14 20:36:44 -05:00
# include "util.h"
2010-01-08 09:29:01 +11:00
# include "libcli/security/security.h"
2010-09-24 12:09:26 -07:00
# include "lib/ldb/include/ldb_private.h"
2009-11-16 18:32:17 +11:00
2009-10-10 09:06:07 +11:00
/*
search for attrs on one DN , in the modules below
*/
int dsdb_module_search_dn ( struct ldb_module * module ,
TALLOC_CTX * mem_ctx ,
struct ldb_result * * _res ,
struct ldb_dn * basedn ,
2009-11-16 18:32:17 +11:00
const char * const * attrs ,
2009-12-16 11:30:03 +11:00
uint32_t dsdb_flags )
2009-10-10 09:06:07 +11:00
{
int ret ;
struct ldb_request * req ;
TALLOC_CTX * tmp_ctx ;
struct ldb_result * res ;
tmp_ctx = talloc_new ( mem_ctx ) ;
res = talloc_zero ( tmp_ctx , struct ldb_result ) ;
if ( ! res ) {
2010-05-30 20:46:57 +02:00
talloc_free ( tmp_ctx ) ;
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2009-10-10 09:06:07 +11:00
}
ret = ldb_build_search_req ( & req , ldb_module_get_ctx ( module ) , tmp_ctx ,
basedn ,
LDB_SCOPE_BASE ,
NULL ,
attrs ,
NULL ,
res ,
ldb_search_default_callback ,
NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
2010-02-16 14:23:21 +11:00
ret = dsdb_request_add_controls ( req , dsdb_flags ) ;
2009-11-16 18:32:17 +11:00
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
2010-07-06 03:31:17 +03:00
/* Run the new request */
2010-07-06 04:06:23 +03:00
if ( dsdb_flags & DSDB_FLAG_NEXT_MODULE ) {
ret = ldb_next_request ( module , req ) ;
2010-07-06 03:31:17 +03:00
} else if ( dsdb_flags & DSDB_FLAG_TOP_MODULE ) {
ret = ldb_request ( ldb_module_get_ctx ( module ) , req ) ;
} else {
2010-07-06 04:06:23 +03:00
const struct ldb_module_ops * ops = ldb_module_get_ops ( module ) ;
SMB_ASSERT ( dsdb_flags & DSDB_FLAG_OWN_MODULE ) ;
2010-09-25 10:19:11 -07:00
ret = ops - > search ( module , req ) ;
2010-07-06 03:31:17 +03:00
}
2009-10-10 09:06:07 +11:00
if ( ret = = LDB_SUCCESS ) {
ret = ldb_wait ( req - > handle , LDB_WAIT_ALL ) ;
}
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
if ( res - > count ! = 1 ) {
/* we may be reading a DB that does not have the 'check base on search' option... */
ret = LDB_ERR_NO_SUCH_OBJECT ;
2009-10-23 12:34:41 +11:00
ldb_asprintf_errstring ( ldb_module_get_ctx ( module ) ,
" dsdb_module_search_dn: did not find base dn %s (%d results) " ,
ldb_dn_get_linearized ( basedn ) , res - > count ) ;
2009-10-10 09:06:07 +11:00
} else {
* _res = talloc_steal ( mem_ctx , res ) ;
}
talloc_free ( tmp_ctx ) ;
return ret ;
}
/*
search for attrs in the modules below
*/
int dsdb_module_search ( struct ldb_module * module ,
TALLOC_CTX * mem_ctx ,
struct ldb_result * * _res ,
struct ldb_dn * basedn , enum ldb_scope scope ,
const char * const * attrs ,
2009-11-16 18:32:17 +11:00
int dsdb_flags ,
2009-12-18 20:55:23 +11:00
const char * format , . . . ) _PRINTF_ATTRIBUTE ( 8 , 9 )
2009-10-10 09:06:07 +11:00
{
int ret ;
struct ldb_request * req ;
TALLOC_CTX * tmp_ctx ;
struct ldb_result * res ;
2009-12-18 20:55:23 +11:00
va_list ap ;
char * expression ;
2009-10-10 09:06:07 +11:00
tmp_ctx = talloc_new ( mem_ctx ) ;
2010-05-30 20:46:31 +02:00
if ( format ) {
va_start ( ap , format ) ;
expression = talloc_vasprintf ( tmp_ctx , format , ap ) ;
va_end ( ap ) ;
if ( ! expression ) {
talloc_free ( tmp_ctx ) ;
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2010-05-30 20:46:31 +02:00
}
} else {
expression = NULL ;
}
2009-12-18 20:55:23 +11:00
2009-10-10 09:06:07 +11:00
res = talloc_zero ( tmp_ctx , struct ldb_result ) ;
if ( ! res ) {
2010-05-30 20:46:31 +02:00
talloc_free ( tmp_ctx ) ;
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2009-10-10 09:06:07 +11:00
}
ret = ldb_build_search_req ( & req , ldb_module_get_ctx ( module ) , tmp_ctx ,
basedn ,
scope ,
expression ,
attrs ,
NULL ,
res ,
ldb_search_default_callback ,
NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
2010-02-16 14:23:21 +11:00
ret = dsdb_request_add_controls ( req , dsdb_flags ) ;
2009-11-16 18:32:17 +11:00
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
2010-07-06 04:06:23 +03:00
if ( dsdb_flags & DSDB_FLAG_NEXT_MODULE ) {
ret = ldb_next_request ( module , req ) ;
2010-01-07 18:15:34 +11:00
} else if ( dsdb_flags & DSDB_FLAG_TOP_MODULE ) {
ret = ldb_request ( ldb_module_get_ctx ( module ) , req ) ;
2009-12-21 20:59:08 +11:00
} else {
2010-07-06 04:06:23 +03:00
const struct ldb_module_ops * ops = ldb_module_get_ops ( module ) ;
SMB_ASSERT ( dsdb_flags & DSDB_FLAG_OWN_MODULE ) ;
ret = ops - > search ( module , req ) ;
2009-12-21 20:59:08 +11:00
}
2009-10-10 09:06:07 +11:00
if ( ret = = LDB_SUCCESS ) {
ret = ldb_wait ( req - > handle , LDB_WAIT_ALL ) ;
}
talloc_free ( req ) ;
if ( ret = = LDB_SUCCESS ) {
* _res = talloc_steal ( mem_ctx , res ) ;
}
talloc_free ( tmp_ctx ) ;
return ret ;
}
2009-12-16 10:27:32 +11:00
/*
find a DN given a GUID . This searches across all partitions
*/
int dsdb_module_dn_by_guid ( struct ldb_module * module , TALLOC_CTX * mem_ctx ,
const struct GUID * guid , struct ldb_dn * * dn )
{
struct ldb_result * res ;
const char * attrs [ ] = { NULL } ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
int ret ;
ret = dsdb_module_search ( module , tmp_ctx , & res , NULL , LDB_SCOPE_SUBTREE ,
2009-12-16 11:31:30 +11:00
attrs ,
2010-06-28 21:29:05 +03:00
DSDB_FLAG_NEXT_MODULE |
2009-12-16 11:31:30 +11:00
DSDB_SEARCH_SHOW_DELETED |
DSDB_SEARCH_SEARCH_ALL_PARTITIONS |
DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT ,
2009-12-19 20:58:00 +11:00
" objectGUID=%s " , GUID_string ( tmp_ctx , guid ) ) ;
2009-12-16 10:27:32 +11:00
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
2009-12-16 11:31:30 +11:00
if ( res - > count = = 0 ) {
2009-12-16 10:27:32 +11:00
talloc_free ( tmp_ctx ) ;
return LDB_ERR_NO_SUCH_OBJECT ;
}
if ( res - > count ! = 1 ) {
2009-12-19 20:58:00 +11:00
ldb_asprintf_errstring ( ldb_module_get_ctx ( module ) , " More than one object found matching objectGUID %s \n " ,
GUID_string ( tmp_ctx , guid ) ) ;
2009-12-16 10:27:32 +11:00
talloc_free ( tmp_ctx ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2009-12-16 11:31:30 +11:00
* dn = talloc_steal ( mem_ctx , res - > msgs [ 0 ] - > dn ) ;
2009-12-16 10:27:32 +11:00
talloc_free ( tmp_ctx ) ;
return LDB_SUCCESS ;
}
2009-12-16 11:32:57 +11:00
2009-12-21 20:59:08 +11:00
/*
find a GUID given a DN .
*/
int dsdb_module_guid_by_dn ( struct ldb_module * module , struct ldb_dn * dn , struct GUID * guid )
{
const char * attrs [ ] = { NULL } ;
struct ldb_result * res ;
TALLOC_CTX * tmp_ctx = talloc_new ( module ) ;
int ret ;
NTSTATUS status ;
ret = dsdb_module_search_dn ( module , tmp_ctx , & res , dn , attrs ,
2010-07-06 03:22:09 +03:00
DSDB_FLAG_NEXT_MODULE |
DSDB_SEARCH_SHOW_DELETED |
2009-12-21 20:59:08 +11:00
DSDB_SEARCH_SHOW_EXTENDED_DN ) ;
if ( ret ! = LDB_SUCCESS ) {
ldb_asprintf_errstring ( ldb_module_get_ctx ( module ) , " Failed to find GUID for %s " ,
ldb_dn_get_linearized ( dn ) ) ;
talloc_free ( tmp_ctx ) ;
return ret ;
}
status = dsdb_get_extended_dn_guid ( res - > msgs [ 0 ] - > dn , guid , " GUID " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( tmp_ctx ) ;
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb_module_get_ctx ( module ) ) ;
2009-12-21 20:59:08 +11:00
}
talloc_free ( tmp_ctx ) ;
return LDB_SUCCESS ;
}
2009-12-16 11:32:57 +11:00
/*
a ldb_modify request operating on modules below the
current module
*/
int dsdb_module_modify ( struct ldb_module * module ,
const struct ldb_message * message ,
uint32_t dsdb_flags )
{
struct ldb_request * mod_req ;
int ret ;
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
TALLOC_CTX * tmp_ctx = talloc_new ( module ) ;
2010-05-04 11:49:18 +02:00
struct ldb_result * res ;
res = talloc_zero ( tmp_ctx , struct ldb_result ) ;
if ( ! res ) {
2010-05-30 20:46:57 +02:00
talloc_free ( tmp_ctx ) ;
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2010-05-04 11:49:18 +02:00
}
2009-12-16 11:32:57 +11:00
ret = ldb_build_mod_req ( & mod_req , ldb , tmp_ctx ,
message ,
NULL ,
2010-05-04 11:49:18 +02:00
res ,
ldb_modify_default_callback ,
2009-12-16 11:32:57 +11:00
NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
2010-02-16 14:23:21 +11:00
ret = dsdb_request_add_controls ( mod_req , dsdb_flags ) ;
2009-12-16 11:32:57 +11:00
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
/* Run the new request */
2010-07-06 04:06:23 +03:00
if ( dsdb_flags & DSDB_FLAG_NEXT_MODULE ) {
ret = ldb_next_request ( module , mod_req ) ;
2010-01-07 18:15:34 +11:00
} else if ( dsdb_flags & DSDB_FLAG_TOP_MODULE ) {
ret = ldb_request ( ldb_module_get_ctx ( module ) , mod_req ) ;
2009-12-21 20:59:08 +11:00
} else {
2010-07-06 04:06:23 +03:00
const struct ldb_module_ops * ops = ldb_module_get_ops ( module ) ;
SMB_ASSERT ( dsdb_flags & DSDB_FLAG_OWN_MODULE ) ;
ret = ops - > modify ( module , mod_req ) ;
2009-12-21 20:59:08 +11:00
}
2009-12-16 11:32:57 +11:00
if ( ret = = LDB_SUCCESS ) {
ret = ldb_wait ( mod_req - > handle , LDB_WAIT_ALL ) ;
}
talloc_free ( tmp_ctx ) ;
return ret ;
}
2009-12-16 12:01:16 +11:00
/*
a ldb_rename request operating on modules below the
current module
*/
int dsdb_module_rename ( struct ldb_module * module ,
struct ldb_dn * olddn , struct ldb_dn * newdn ,
uint32_t dsdb_flags )
{
struct ldb_request * req ;
int ret ;
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
TALLOC_CTX * tmp_ctx = talloc_new ( module ) ;
2010-05-04 11:49:18 +02:00
struct ldb_result * res ;
res = talloc_zero ( tmp_ctx , struct ldb_result ) ;
if ( ! res ) {
2010-05-30 20:46:57 +02:00
talloc_free ( tmp_ctx ) ;
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2010-05-04 11:49:18 +02:00
}
2009-12-16 12:01:16 +11:00
ret = ldb_build_rename_req ( & req , ldb , tmp_ctx ,
olddn ,
newdn ,
NULL ,
2010-05-04 11:49:18 +02:00
res ,
ldb_modify_default_callback ,
2009-12-16 12:01:16 +11:00
NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
2010-02-16 14:23:21 +11:00
ret = dsdb_request_add_controls ( req , dsdb_flags ) ;
2009-12-16 12:01:16 +11:00
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
/* Run the new request */
2010-07-06 04:06:23 +03:00
if ( dsdb_flags & DSDB_FLAG_NEXT_MODULE ) {
ret = ldb_next_request ( module , req ) ;
2010-01-07 18:15:34 +11:00
} else if ( dsdb_flags & DSDB_FLAG_TOP_MODULE ) {
ret = ldb_request ( ldb_module_get_ctx ( module ) , req ) ;
2009-12-21 20:59:08 +11:00
} else {
2010-07-06 04:06:23 +03:00
const struct ldb_module_ops * ops = ldb_module_get_ops ( module ) ;
SMB_ASSERT ( dsdb_flags & DSDB_FLAG_OWN_MODULE ) ;
ret = ops - > rename ( module , req ) ;
2009-12-21 20:59:08 +11:00
}
2009-12-16 12:01:16 +11:00
if ( ret = = LDB_SUCCESS ) {
ret = ldb_wait ( req - > handle , LDB_WAIT_ALL ) ;
}
talloc_free ( tmp_ctx ) ;
return ret ;
}
2009-12-14 20:36:44 -05:00
2010-01-06 09:17:19 +11:00
/*
a ldb_add request operating on modules below the
current module
*/
int dsdb_module_add ( struct ldb_module * module ,
const struct ldb_message * message ,
uint32_t dsdb_flags )
{
struct ldb_request * req ;
int ret ;
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
TALLOC_CTX * tmp_ctx = talloc_new ( module ) ;
2010-05-04 11:49:18 +02:00
struct ldb_result * res ;
res = talloc_zero ( tmp_ctx , struct ldb_result ) ;
if ( ! res ) {
2010-05-30 20:46:57 +02:00
talloc_free ( tmp_ctx ) ;
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2010-05-04 11:49:18 +02:00
}
2010-01-06 09:17:19 +11:00
ret = ldb_build_add_req ( & req , ldb , tmp_ctx ,
message ,
NULL ,
2010-05-04 11:49:18 +02:00
res ,
ldb_modify_default_callback ,
2010-01-06 09:17:19 +11:00
NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
2010-02-16 14:23:21 +11:00
ret = dsdb_request_add_controls ( req , dsdb_flags ) ;
2010-01-06 09:17:19 +11:00
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
/* Run the new request */
2010-07-06 04:06:23 +03:00
if ( dsdb_flags & DSDB_FLAG_NEXT_MODULE ) {
ret = ldb_next_request ( module , req ) ;
2010-01-07 18:15:34 +11:00
} else if ( dsdb_flags & DSDB_FLAG_TOP_MODULE ) {
ret = ldb_request ( ldb_module_get_ctx ( module ) , req ) ;
2010-01-06 09:17:19 +11:00
} else {
2010-07-06 04:06:23 +03:00
const struct ldb_module_ops * ops = ldb_module_get_ops ( module ) ;
SMB_ASSERT ( dsdb_flags & DSDB_FLAG_OWN_MODULE ) ;
ret = ops - > add ( module , req ) ;
2010-01-06 09:17:19 +11:00
}
if ( ret = = LDB_SUCCESS ) {
ret = ldb_wait ( req - > handle , LDB_WAIT_ALL ) ;
}
talloc_free ( tmp_ctx ) ;
return ret ;
}
2010-06-20 12:43:49 +02:00
/*
a ldb_delete request operating on modules below the
current module
*/
int dsdb_module_del ( struct ldb_module * module ,
struct ldb_dn * dn ,
uint32_t dsdb_flags )
{
struct ldb_request * req ;
int ret ;
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
TALLOC_CTX * tmp_ctx = talloc_new ( module ) ;
struct ldb_result * res ;
res = talloc_zero ( tmp_ctx , struct ldb_result ) ;
if ( ! res ) {
talloc_free ( tmp_ctx ) ;
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb ) ;
2010-06-20 12:43:49 +02:00
}
ret = ldb_build_del_req ( & req , ldb , tmp_ctx ,
dn ,
NULL ,
res ,
ldb_modify_default_callback ,
NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
ret = dsdb_request_add_controls ( req , dsdb_flags ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
/* Run the new request */
2010-07-06 04:06:23 +03:00
if ( dsdb_flags & DSDB_FLAG_NEXT_MODULE ) {
ret = ldb_next_request ( module , req ) ;
2010-06-20 12:43:49 +02:00
} else if ( dsdb_flags & DSDB_FLAG_TOP_MODULE ) {
ret = ldb_request ( ldb_module_get_ctx ( module ) , req ) ;
} else {
2010-07-06 04:06:23 +03:00
const struct ldb_module_ops * ops = ldb_module_get_ops ( module ) ;
SMB_ASSERT ( dsdb_flags & DSDB_FLAG_OWN_MODULE ) ;
ret = ops - > del ( module , req ) ;
2010-06-20 12:43:49 +02:00
}
if ( ret = = LDB_SUCCESS ) {
ret = ldb_wait ( req - > handle , LDB_WAIT_ALL ) ;
}
talloc_free ( tmp_ctx ) ;
return ret ;
}
2010-01-06 09:17:19 +11:00
2009-12-14 20:36:44 -05:00
const struct dsdb_class * get_last_structural_class ( const struct dsdb_schema * schema , const struct ldb_message_element * element )
{
const struct dsdb_class * last_class = NULL ;
2010-03-22 23:53:17 +01:00
unsigned int i ;
2009-12-14 20:36:44 -05:00
for ( i = 0 ; i < element - > num_values ; i + + ) {
const struct dsdb_class * tmp_class = dsdb_class_by_lDAPDisplayName_ldb_val ( schema , & element - > values [ i ] ) ;
if ( tmp_class = = NULL ) {
continue ;
}
2010-06-04 21:10:41 +02:00
if ( tmp_class - > objectClassCategory > 1 ) {
2009-12-14 20:36:44 -05:00
continue ;
}
if ( ! last_class ) {
last_class = tmp_class ;
} else {
if ( tmp_class - > subClass_order > last_class - > subClass_order )
last_class = tmp_class ;
}
}
return last_class ;
}
2009-12-19 21:40:55 +11:00
/*
check if a single valued link has multiple non - deleted values
This is needed when we will be using the RELAX control to stop
ldb_tdb from checking single valued links
*/
int dsdb_check_single_valued_link ( const struct dsdb_attribute * attr ,
const struct ldb_message_element * el )
{
bool found_active = false ;
2010-03-22 23:53:17 +01:00
unsigned int i ;
2009-12-19 21:40:55 +11:00
if ( ! ( attr - > ldb_schema_attribute - > flags & LDB_ATTR_FLAG_SINGLE_VALUE ) | |
el - > num_values < 2 ) {
return LDB_SUCCESS ;
}
for ( i = 0 ; i < el - > num_values ; i + + ) {
if ( ! dsdb_dn_is_deleted_val ( & el - > values [ i ] ) ) {
if ( found_active ) {
return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS ;
}
found_active = true ;
}
}
return LDB_SUCCESS ;
}
2010-01-06 09:19:04 +11:00
2010-03-10 16:21:29 -03:00
int dsdb_check_optional_feature ( struct ldb_module * module , struct ldb_dn * scope ,
struct GUID op_feature_guid , bool * feature_enabled )
{
TALLOC_CTX * tmp_ctx ;
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
struct ldb_result * res ;
struct ldb_dn * search_dn ;
struct GUID search_guid ;
const char * attrs [ ] = { " msDS-EnabledFeature " , NULL } ;
int ret ;
2010-03-12 18:56:44 +01:00
unsigned int i ;
2010-03-10 16:21:29 -03:00
struct ldb_message_element * el ;
* feature_enabled = false ;
tmp_ctx = talloc_new ( ldb ) ;
ret = ldb_search ( ldb , tmp_ctx , & res ,
scope , LDB_SCOPE_BASE , attrs ,
NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
ldb_asprintf_errstring ( ldb ,
" Could no find the scope object - dn: %s \n " ,
ldb_dn_get_linearized ( scope ) ) ;
talloc_free ( tmp_ctx ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
if ( res - > msgs [ 0 ] - > num_elements > 0 ) {
el = ldb_msg_find_element ( res - > msgs [ 0 ] , " msDS-EnabledFeature " ) ;
attrs [ 0 ] = " msDS-OptionalFeatureGUID " ;
for ( i = 0 ; i < el - > num_values ; i + + ) {
search_dn = ldb_dn_from_ldb_val ( tmp_ctx , ldb , & el - > values [ i ] ) ;
ret = ldb_search ( ldb , tmp_ctx , & res ,
search_dn , LDB_SCOPE_BASE , attrs ,
NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
ldb_asprintf_errstring ( ldb ,
" Could no find object dn: %s \n " ,
ldb_dn_get_linearized ( search_dn ) ) ;
talloc_free ( tmp_ctx ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
search_guid = samdb_result_guid ( res - > msgs [ 0 ] , " msDS-OptionalFeatureGUID " ) ;
if ( GUID_compare ( & search_guid , & op_feature_guid ) = = 0 ) {
* feature_enabled = true ;
break ;
}
}
}
talloc_free ( tmp_ctx ) ;
return LDB_SUCCESS ;
}
2010-01-06 09:19:04 +11:00
/*
find a ' reference ' DN that points at another object
( eg . serverReference , rIDManagerReference etc )
*/
int dsdb_module_reference_dn ( struct ldb_module * module , TALLOC_CTX * mem_ctx , struct ldb_dn * base ,
const char * attribute , struct ldb_dn * * dn )
{
const char * attrs [ 2 ] ;
struct ldb_result * res ;
int ret ;
attrs [ 0 ] = attribute ;
attrs [ 1 ] = NULL ;
2010-07-06 03:22:09 +03:00
ret = dsdb_module_search_dn ( module , mem_ctx , & res , base , attrs ,
DSDB_FLAG_NEXT_MODULE ) ;
2010-01-06 09:19:04 +11:00
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
* dn = ldb_msg_find_attr_as_dn ( ldb_module_get_ctx ( module ) ,
mem_ctx , res - > msgs [ 0 ] , attribute ) ;
if ( ! * dn ) {
talloc_free ( res ) ;
return LDB_ERR_NO_SUCH_ATTRIBUTE ;
}
talloc_free ( res ) ;
return LDB_SUCCESS ;
}
/*
find the RID Manager $ DN via the rIDManagerReference attribute in the
base DN
*/
int dsdb_module_rid_manager_dn ( struct ldb_module * module , TALLOC_CTX * mem_ctx , struct ldb_dn * * dn )
{
return dsdb_module_reference_dn ( module , mem_ctx ,
2010-04-13 08:41:10 +02:00
ldb_get_default_basedn ( ldb_module_get_ctx ( module ) ) ,
2010-01-06 09:19:04 +11:00
" rIDManagerReference " , dn ) ;
}
2010-01-06 09:20:35 +11:00
/*
update an integer attribute safely via a constrained delete / add
*/
int dsdb_module_constrainted_update_integer ( struct ldb_module * module , struct ldb_dn * dn ,
const char * attr , uint64_t old_val , uint64_t new_val )
{
struct ldb_message * msg ;
struct ldb_message_element * el ;
struct ldb_val v1 , v2 ;
int ret ;
char * vstring ;
msg = ldb_msg_new ( module ) ;
msg - > dn = dn ;
ret = ldb_msg_add_empty ( msg , attr , LDB_FLAG_MOD_DELETE , & el ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return ret ;
}
el - > num_values = 1 ;
el - > values = & v1 ;
vstring = talloc_asprintf ( msg , " %llu " , ( unsigned long long ) old_val ) ;
if ( ! vstring ) {
talloc_free ( msg ) ;
2010-07-06 13:21:54 +10:00
return ldb_module_oom ( module ) ;
2010-01-06 09:20:35 +11:00
}
v1 = data_blob_string_const ( vstring ) ;
ret = ldb_msg_add_empty ( msg , attr , LDB_FLAG_MOD_ADD , & el ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return ret ;
}
el - > num_values = 1 ;
el - > values = & v2 ;
vstring = talloc_asprintf ( msg , " %llu " , ( unsigned long long ) new_val ) ;
if ( ! vstring ) {
talloc_free ( msg ) ;
2010-07-06 13:21:54 +10:00
return ldb_module_oom ( module ) ;
2010-01-06 09:20:35 +11:00
}
v2 = data_blob_string_const ( vstring ) ;
2010-06-28 21:29:05 +03:00
ret = dsdb_module_modify ( module , msg , DSDB_FLAG_NEXT_MODULE ) ;
2010-01-06 09:20:35 +11:00
talloc_free ( msg ) ;
return ret ;
}
2010-01-06 09:21:21 +11:00
/*
used to chain to the callers callback
*/
int dsdb_next_callback ( struct ldb_request * req , struct ldb_reply * ares )
{
struct ldb_request * up_req = talloc_get_type ( req - > context , struct ldb_request ) ;
talloc_steal ( up_req , req ) ;
return up_req - > callback ( up_req , ares ) ;
}
2010-01-06 14:48:55 +11:00
/*
set an integer attribute
*/
int dsdb_module_set_integer ( struct ldb_module * module , struct ldb_dn * dn ,
const char * attr , uint64_t new_val )
{
struct ldb_message * msg ;
int ret ;
msg = ldb_msg_new ( module ) ;
msg - > dn = dn ;
ret = ldb_msg_add_fmt ( msg , attr , " %llu " , ( unsigned long long ) new_val ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return ret ;
}
msg - > elements [ 0 ] . flags = LDB_FLAG_MOD_REPLACE ;
2010-06-28 21:29:05 +03:00
ret = dsdb_module_modify ( module , msg , DSDB_FLAG_NEXT_MODULE ) ;
2010-01-06 14:48:55 +11:00
talloc_free ( msg ) ;
return ret ;
}
2010-01-08 09:29:01 +11:00
2010-03-22 16:00:39 +11:00
/*
load the uSNHighest and the uSNUrgent attributes from the @ REPLCHANGED
object for a partition
*/
int dsdb_module_load_partition_usn ( struct ldb_module * module , struct ldb_dn * dn ,
uint64_t * uSN , uint64_t * urgent_uSN )
{
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
struct ldb_request * req ;
int ret ;
TALLOC_CTX * tmp_ctx = talloc_new ( module ) ;
struct dsdb_control_current_partition * p_ctrl ;
struct ldb_result * res ;
res = talloc_zero ( tmp_ctx , struct ldb_result ) ;
if ( ! res ) {
talloc_free ( tmp_ctx ) ;
2010-07-06 13:21:54 +10:00
return ldb_module_oom ( module ) ;
2010-03-22 16:00:39 +11:00
}
ret = ldb_build_search_req ( & req , ldb , tmp_ctx ,
ldb_dn_new ( tmp_ctx , ldb , " @REPLCHANGED " ) ,
LDB_SCOPE_BASE ,
NULL , NULL ,
NULL ,
res , ldb_search_default_callback ,
NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
p_ctrl = talloc ( req , struct dsdb_control_current_partition ) ;
if ( p_ctrl = = NULL ) {
2010-05-30 20:46:57 +02:00
talloc_free ( tmp_ctx ) ;
2010-07-06 13:21:54 +10:00
return ldb_module_oom ( module ) ;
2010-03-22 16:00:39 +11:00
}
p_ctrl - > version = DSDB_CONTROL_CURRENT_PARTITION_VERSION ;
p_ctrl - > dn = dn ;
ret = ldb_request_add_control ( req ,
DSDB_CONTROL_CURRENT_PARTITION_OID ,
false , p_ctrl ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
/* Run the new request */
ret = ldb_next_request ( module , req ) ;
if ( ret = = LDB_SUCCESS ) {
ret = ldb_wait ( req - > handle , LDB_WAIT_ALL ) ;
}
2010-03-27 21:46:27 -05:00
if ( ret = = LDB_ERR_NO_SUCH_OBJECT | | ret = = LDB_ERR_INVALID_DN_SYNTAX ) {
2010-03-22 16:00:39 +11:00
/* it hasn't been created yet, which means
an implicit value of zero */
* uSN = 0 ;
talloc_free ( tmp_ctx ) ;
return LDB_SUCCESS ;
}
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( tmp_ctx ) ;
return ret ;
}
2010-07-03 12:47:46 +02:00
if ( res - > count ! = 1 ) {
2010-03-22 16:00:39 +11:00
* uSN = 0 ;
if ( urgent_uSN ) {
* urgent_uSN = 0 ;
}
} else {
* uSN = ldb_msg_find_attr_as_uint64 ( res - > msgs [ 0 ] , " uSNHighest " , 0 ) ;
if ( urgent_uSN ) {
* urgent_uSN = ldb_msg_find_attr_as_uint64 ( res - > msgs [ 0 ] , " uSNUrgent " , 0 ) ;
}
}
talloc_free ( tmp_ctx ) ;
return LDB_SUCCESS ;
}
/*
save uSNHighest and uSNUrgent attributes in the @ REPLCHANGED object for a
partition
*/
int dsdb_module_save_partition_usn ( struct ldb_module * module , struct ldb_dn * dn ,
uint64_t uSN , uint64_t urgent_uSN )
{
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
struct ldb_request * req ;
struct ldb_message * msg ;
struct dsdb_control_current_partition * p_ctrl ;
int ret ;
2010-05-04 11:49:18 +02:00
struct ldb_result * res ;
2010-03-22 16:00:39 +11:00
msg = ldb_msg_new ( module ) ;
if ( msg = = NULL ) {
2010-07-06 13:21:54 +10:00
return ldb_module_oom ( module ) ;
2010-03-22 16:00:39 +11:00
}
msg - > dn = ldb_dn_new ( msg , ldb , " @REPLCHANGED " ) ;
if ( msg - > dn = = NULL ) {
talloc_free ( msg ) ;
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb_module_get_ctx ( module ) ) ;
2010-03-22 16:00:39 +11:00
}
2010-05-04 11:49:18 +02:00
res = talloc_zero ( msg , struct ldb_result ) ;
if ( ! res ) {
2010-05-30 20:46:57 +02:00
talloc_free ( msg ) ;
2010-07-06 13:21:54 +10:00
return ldb_module_oom ( module ) ;
2010-05-04 11:49:18 +02:00
}
2010-03-22 16:00:39 +11:00
ret = ldb_msg_add_fmt ( msg , " uSNHighest " , " %llu " , ( unsigned long long ) uSN ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return ret ;
}
msg - > elements [ 0 ] . flags = LDB_FLAG_MOD_REPLACE ;
/* urgent_uSN is optional so may not be stored */
if ( urgent_uSN ) {
ret = ldb_msg_add_fmt ( msg , " uSNUrgent " , " %llu " , ( unsigned long long ) urgent_uSN ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return ret ;
}
msg - > elements [ 1 ] . flags = LDB_FLAG_MOD_REPLACE ;
}
p_ctrl = talloc ( msg , struct dsdb_control_current_partition ) ;
if ( p_ctrl = = NULL ) {
talloc_free ( msg ) ;
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb ) ;
2010-03-22 16:00:39 +11:00
}
p_ctrl - > version = DSDB_CONTROL_CURRENT_PARTITION_VERSION ;
p_ctrl - > dn = dn ;
ret = ldb_build_mod_req ( & req , ldb , msg ,
msg ,
NULL ,
2010-05-04 11:49:18 +02:00
res ,
ldb_modify_default_callback ,
2010-03-22 16:00:39 +11:00
NULL ) ;
again :
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return ret ;
}
ret = ldb_request_add_control ( req ,
DSDB_CONTROL_CURRENT_PARTITION_OID ,
false , p_ctrl ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return ret ;
}
/* Run the new request */
ret = ldb_next_request ( module , req ) ;
if ( ret = = LDB_SUCCESS ) {
ret = ldb_wait ( req - > handle , LDB_WAIT_ALL ) ;
}
if ( ret = = LDB_ERR_NO_SUCH_OBJECT ) {
ret = ldb_build_add_req ( & req , ldb , msg ,
msg ,
NULL ,
2010-05-04 11:49:18 +02:00
res ,
ldb_modify_default_callback ,
2010-03-22 16:00:39 +11:00
NULL ) ;
goto again ;
}
talloc_free ( msg ) ;
return ret ;
}
2010-01-08 09:29:01 +11:00
bool dsdb_module_am_system ( struct ldb_module * module )
{
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
struct auth_session_info * session_info
2010-08-17 14:55:23 +10:00
= talloc_get_type ( ldb_get_opaque ( ldb , " sessionInfo " ) , struct auth_session_info ) ;
2010-04-22 16:48:01 +10:00
return security_session_user_level ( session_info , NULL ) = = SECURITY_SYSTEM ;
2010-01-08 09:29:01 +11:00
}
2010-03-24 16:21:15 -03:00
2010-08-04 15:22:17 +03:00
bool dsdb_module_am_administrator ( struct ldb_module * module )
{
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
struct auth_session_info * session_info
2010-08-17 14:55:23 +10:00
= talloc_get_type ( ldb_get_opaque ( ldb , " sessionInfo " ) , struct auth_session_info ) ;
2010-08-04 15:22:17 +03:00
return security_session_user_level ( session_info , NULL ) = = SECURITY_ADMINISTRATOR ;
}
2010-03-24 16:21:15 -03:00
/*
check if the recyclebin is enabled
*/
int dsdb_recyclebin_enabled ( struct ldb_module * module , bool * enabled )
{
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
struct ldb_dn * partitions_dn ;
struct GUID recyclebin_guid ;
int ret ;
partitions_dn = samdb_partitions_dn ( ldb , module ) ;
GUID_from_string ( DS_GUID_FEATURE_RECYCLE_BIN , & recyclebin_guid ) ;
ret = dsdb_check_optional_feature ( module , partitions_dn , recyclebin_guid , enabled ) ;
if ( ret ! = LDB_SUCCESS ) {
ldb_asprintf_errstring ( ldb , " Could not verify if Recycle Bin is enabled \n " ) ;
talloc_free ( partitions_dn ) ;
return LDB_ERR_UNWILLING_TO_PERFORM ;
}
talloc_free ( partitions_dn ) ;
return LDB_SUCCESS ;
}
2010-04-26 09:56:59 +03:00
bool is_attr_in_list ( const char * const * attrs , const char * attr )
{
unsigned int i ;
for ( i = 0 ; attrs [ i ] ; i + + ) {
if ( ldb_attr_cmp ( attrs [ i ] , attr ) = = 0 )
return true ;
}
return false ;
}
2010-07-08 11:32:26 +02:00
int dsdb_msg_constrainted_update_int32 ( struct ldb_module * module ,
struct ldb_message * msg ,
const char * attr ,
const int32_t * old_val ,
const int32_t * new_val )
{
struct ldb_message_element * el ;
int ret ;
char * vstring ;
if ( old_val ) {
ret = ldb_msg_add_empty ( msg , attr , LDB_FLAG_MOD_DELETE , & el ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
el - > num_values = 1 ;
el - > values = talloc_array ( msg , struct ldb_val , el - > num_values ) ;
if ( ! el - > values ) {
return ldb_module_oom ( module ) ;
}
vstring = talloc_asprintf ( el - > values , " %ld " , ( long ) * old_val ) ;
if ( ! vstring ) {
return ldb_module_oom ( module ) ;
}
* el - > values = data_blob_string_const ( vstring ) ;
}
if ( new_val ) {
ret = ldb_msg_add_empty ( msg , attr , LDB_FLAG_MOD_ADD , & el ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
el - > num_values = 1 ;
el - > values = talloc_array ( msg , struct ldb_val , el - > num_values ) ;
if ( ! el - > values ) {
return ldb_module_oom ( module ) ;
}
vstring = talloc_asprintf ( el - > values , " %ld " , ( long ) * new_val ) ;
if ( ! vstring ) {
return ldb_module_oom ( module ) ;
}
* el - > values = data_blob_string_const ( vstring ) ;
}
return LDB_SUCCESS ;
}
2010-07-08 12:01:44 +02:00
int dsdb_msg_constrainted_update_uint32 ( struct ldb_module * module ,
struct ldb_message * msg ,
const char * attr ,
const uint32_t * old_val ,
const uint32_t * new_val )
{
return dsdb_msg_constrainted_update_int32 ( module , msg , attr ,
( const int32_t * ) old_val ,
( const int32_t * ) new_val ) ;
}
2010-07-08 11:32:26 +02:00
int dsdb_msg_constrainted_update_int64 ( struct ldb_module * module ,
struct ldb_message * msg ,
const char * attr ,
const int64_t * old_val ,
const int64_t * new_val )
{
struct ldb_message_element * el ;
int ret ;
char * vstring ;
if ( old_val ) {
ret = ldb_msg_add_empty ( msg , attr , LDB_FLAG_MOD_DELETE , & el ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
el - > num_values = 1 ;
el - > values = talloc_array ( msg , struct ldb_val , el - > num_values ) ;
if ( ! el - > values ) {
return ldb_module_oom ( module ) ;
}
vstring = talloc_asprintf ( el - > values , " %lld " , ( long long ) * old_val ) ;
if ( ! vstring ) {
return ldb_module_oom ( module ) ;
}
* el - > values = data_blob_string_const ( vstring ) ;
}
if ( new_val ) {
ret = ldb_msg_add_empty ( msg , attr , LDB_FLAG_MOD_ADD , & el ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
el - > num_values = 1 ;
el - > values = talloc_array ( msg , struct ldb_val , el - > num_values ) ;
if ( ! el - > values ) {
return ldb_module_oom ( module ) ;
}
vstring = talloc_asprintf ( el - > values , " %lld " , ( long long ) * new_val ) ;
if ( ! vstring ) {
return ldb_module_oom ( module ) ;
}
* el - > values = data_blob_string_const ( vstring ) ;
}
return LDB_SUCCESS ;
}
2010-07-08 11:32:59 +02:00
2010-07-08 12:01:44 +02:00
int dsdb_msg_constrainted_update_uint64 ( struct ldb_module * module ,
struct ldb_message * msg ,
const char * attr ,
const uint64_t * old_val ,
const uint64_t * new_val )
{
return dsdb_msg_constrainted_update_int64 ( module , msg , attr ,
( const int64_t * ) old_val ,
( const int64_t * ) new_val ) ;
}
2010-07-08 11:32:59 +02:00
/*
update an int32 attribute safely via a constrained delete / add
*/
int dsdb_module_constrainted_update_int32 ( struct ldb_module * module ,
struct ldb_dn * dn ,
const char * attr ,
const int32_t * old_val ,
const int32_t * new_val )
{
struct ldb_message * msg ;
int ret ;
msg = ldb_msg_new ( module ) ;
msg - > dn = dn ;
ret = dsdb_msg_constrainted_update_int32 ( module ,
msg , attr ,
old_val ,
new_val ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return ret ;
}
ret = dsdb_module_modify ( module , msg , DSDB_FLAG_NEXT_MODULE ) ;
talloc_free ( msg ) ;
return ret ;
}
2010-07-08 12:02:42 +02:00
int dsdb_module_constrainted_update_uint32 ( struct ldb_module * module ,
struct ldb_dn * dn ,
const char * attr ,
const uint32_t * old_val ,
const uint32_t * new_val )
{
return dsdb_module_constrainted_update_int32 ( module , dn , attr ,
( const int32_t * ) old_val ,
( const int32_t * ) new_val ) ;
}
2010-07-08 11:32:59 +02:00
/*
update an int64 attribute safely via a constrained delete / add
*/
int dsdb_module_constrainted_update_int64 ( struct ldb_module * module ,
struct ldb_dn * dn ,
const char * attr ,
const int64_t * old_val ,
const int64_t * new_val )
{
struct ldb_message * msg ;
int ret ;
msg = ldb_msg_new ( module ) ;
msg - > dn = dn ;
ret = dsdb_msg_constrainted_update_int64 ( module ,
msg , attr ,
old_val ,
new_val ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( msg ) ;
return ret ;
}
ret = dsdb_module_modify ( module , msg , DSDB_FLAG_NEXT_MODULE ) ;
talloc_free ( msg ) ;
return ret ;
}
2010-07-08 12:02:42 +02:00
int dsdb_module_constrainted_update_uint64 ( struct ldb_module * module ,
struct ldb_dn * dn ,
const char * attr ,
const uint64_t * old_val ,
const uint64_t * new_val )
{
return dsdb_module_constrainted_update_int64 ( module , dn , attr ,
( const int64_t * ) old_val ,
( const int64_t * ) new_val ) ;
}
2010-08-26 17:18:40 +03:00
const struct ldb_val * dsdb_module_find_dsheuristics ( struct ldb_module * module ,
TALLOC_CTX * mem_ctx )
{
int ret ;
struct ldb_dn * new_dn ;
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
static const char * attrs [ ] = { " dsHeuristics " , NULL } ;
struct ldb_result * res ;
new_dn = ldb_dn_copy ( mem_ctx , ldb_get_config_basedn ( ldb ) ) ;
2010-08-26 17:37:49 +03:00
if ( ! ldb_dn_add_child_fmt ( new_dn ,
2010-08-26 17:18:40 +03:00
" CN=Directory Service,CN=Windows NT,CN=Services " ) ) {
talloc_free ( new_dn ) ;
return NULL ;
}
ret = dsdb_module_search_dn ( module , mem_ctx , & res ,
new_dn ,
attrs ,
DSDB_FLAG_NEXT_MODULE ) ;
if ( ret = = LDB_SUCCESS & & res - > count = = 1 ) {
2010-08-26 18:37:00 +02:00
talloc_free ( new_dn ) ;
2010-08-26 17:18:40 +03:00
return ldb_msg_find_ldb_val ( res - > msgs [ 0 ] ,
" dsHeuristics " ) ;
}
2010-08-26 18:37:00 +02:00
talloc_free ( new_dn ) ;
2010-08-26 17:18:40 +03:00
return NULL ;
}
bool dsdb_block_anonymous_ops ( struct ldb_module * module ,
TALLOC_CTX * mem_ctx )
{
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
bool result ;
const struct ldb_val * hr_val = dsdb_module_find_dsheuristics ( module ,
tmp_ctx ) ;
if ( hr_val = = NULL | | hr_val - > length < DS_HR_BLOCK_ANONYMOUS_OPS ) {
result = true ;
} else if ( hr_val - > data [ DS_HR_BLOCK_ANONYMOUS_OPS - 1 ] = = ' 2 ' ) {
result = false ;
} else {
result = true ;
}
talloc_free ( tmp_ctx ) ;
return result ;
}
2010-09-24 12:09:26 -07:00
/*
show the chain of requests , useful for debugging async requests
*/
void dsdb_req_chain_debug ( struct ldb_request * req , int level )
{
char * ret ;
int i = 0 ;
while ( req & & req - > handle ) {
DEBUG ( level , ( " req[%u] %p : %s \n " , i + + , req , ldb_req_location ( req ) ) ) ;
req = req - > handle - > parent ;
}
}