2008-12-16 09:21:55 +01:00
/*
ldb database library
Copyright ( C ) Simo Sorce 2005 - 2008
2009-11-05 17:04:10 +11:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2007 - 2009
2008-12-16 09:21:55 +01: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 .
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 : ldb
*
* Component : ldb extended dn control module
*
* Description : this module builds a special dn for returned search
* results , and fixes some other aspects of the result ( returned case issues )
* values .
*
* Authors : Simo Sorce
* Andrew Bartlett
*/
# include "includes.h"
2011-02-10 14:12:51 +11:00
# include <ldb.h>
# include <ldb_errors.h>
# include <ldb_module.h>
2010-09-20 17:42:13 +10:00
# include "libcli/security/security.h"
2008-12-16 09:21:55 +01:00
# include "librpc/gen_ndr/ndr_misc.h"
2009-10-23 22:59:48 -05:00
# include "librpc/gen_ndr/ndr_security.h"
2008-12-16 09:21:55 +01:00
# include "librpc/ndr/libndr.h"
# include "dsdb/samdb/samdb.h"
2011-09-20 14:26:36 -07:00
# include "dsdb/samdb/ldb_modules/util.h"
2008-12-16 09:21:55 +01:00
2020-08-07 13:27:39 -07:00
# undef strcasecmp
# undef strncasecmp
2008-12-16 09:21:55 +01:00
struct extended_dn_out_private {
bool dereference ;
bool normalise ;
2010-10-21 21:08:45 +11:00
const char * * attrs ;
2008-12-16 09:21:55 +01:00
} ;
static char * * copy_attrs ( void * mem_ctx , const char * const * attrs )
{
2009-02-02 08:19:11 +01:00
char * * nattrs ;
2010-03-07 19:03:21 +01:00
unsigned int i , num ;
2008-12-16 09:21:55 +01:00
for ( num = 0 ; attrs [ num ] ; num + + ) ;
2009-02-02 08:19:11 +01:00
nattrs = talloc_array ( mem_ctx , char * , num + 1 ) ;
if ( ! nattrs ) return NULL ;
2008-12-16 09:21:55 +01:00
for ( i = 0 ; i < num ; i + + ) {
2009-02-02 08:19:11 +01:00
nattrs [ i ] = talloc_strdup ( nattrs , attrs [ i ] ) ;
if ( ! nattrs [ i ] ) {
talloc_free ( nattrs ) ;
2008-12-16 09:21:55 +01:00
return NULL ;
}
}
2009-02-02 08:19:11 +01:00
nattrs [ i ] = NULL ;
2008-12-16 09:21:55 +01:00
2009-02-02 08:19:11 +01:00
return nattrs ;
2008-12-16 09:21:55 +01:00
}
static bool add_attrs ( void * mem_ctx , char * * * attrs , const char * attr )
{
2009-02-02 08:19:11 +01:00
char * * nattrs ;
2010-03-07 19:03:21 +01:00
unsigned int num ;
2008-12-16 09:21:55 +01:00
for ( num = 0 ; ( * attrs ) [ num ] ; num + + ) ;
2009-02-02 08:19:11 +01:00
nattrs = talloc_realloc ( mem_ctx , * attrs , char * , num + 2 ) ;
if ( ! nattrs ) return false ;
2008-12-16 09:21:55 +01:00
2009-02-02 08:19:11 +01:00
* attrs = nattrs ;
2008-12-16 09:21:55 +01:00
2009-02-02 08:19:11 +01:00
nattrs [ num ] = talloc_strdup ( nattrs , attr ) ;
if ( ! nattrs [ num ] ) return false ;
2008-12-16 09:21:55 +01:00
2009-02-02 08:19:11 +01:00
nattrs [ num + 1 ] = NULL ;
2008-12-16 09:21:55 +01:00
return true ;
}
/* Inject the extended DN components, so the DN cn=Adminstrator,cn=users,dc=samba,dc=example,dc=com becomes
< GUID = 541203 ae - f7d6 - 47 ef - 8390 - bfcf019f9583 > ; < SID = S - 1 - 5 - 21 - 4177067393 - 1453636373 - 93818737 - 500 > ; cn = Adminstrator , cn = users , dc = samba , dc = example , dc = com */
static int inject_extended_dn_out ( struct ldb_reply * ares ,
struct ldb_context * ldb ,
int type ,
bool remove_guid ,
bool remove_sid )
{
int ret ;
const DATA_BLOB * guid_blob ;
const DATA_BLOB * sid_blob ;
guid_blob = ldb_msg_find_ldb_val ( ares - > message , " objectGUID " ) ;
2010-09-13 22:39:50 +02:00
sid_blob = ldb_msg_find_ldb_val ( ares - > message , " objectSid " ) ;
2008-12-16 09:21:55 +01:00
if ( ! guid_blob ) {
ldb_set_errstring ( ldb , " Did not find objectGUID to inject into extended DN " ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
ret = ldb_dn_set_extended_component ( ares - > message - > dn , " GUID " , guid_blob ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
if ( sid_blob ) {
ret = ldb_dn_set_extended_component ( ares - > message - > dn , " SID " , sid_blob ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
}
if ( remove_guid ) {
ldb_msg_remove_attr ( ares - > message , " objectGUID " ) ;
}
if ( sid_blob & & remove_sid ) {
2010-09-13 22:39:50 +02:00
ldb_msg_remove_attr ( ares - > message , " objectSid " ) ;
2008-12-16 09:21:55 +01:00
}
return LDB_SUCCESS ;
}
/* search */
struct extended_search_context {
struct ldb_module * module ;
const struct dsdb_schema * schema ;
struct ldb_request * req ;
bool inject ;
bool remove_guid ;
bool remove_sid ;
int extended_type ;
} ;
2011-08-01 13:55:58 +10:00
/*
fix one - way links to have the right string DN , to cope with
renames of the target
*/
2011-10-07 13:20:35 +11:00
static int fix_one_way_link ( struct extended_search_context * ac , struct ldb_dn * dn ,
2016-07-13 13:29:19 +12:00
bool is_deleted_objects , bool * remove_value ,
uint32_t linkID )
2011-08-01 13:55:58 +10:00
{
struct GUID guid ;
NTSTATUS status ;
int ret ;
struct ldb_dn * real_dn ;
2011-10-07 13:20:35 +11:00
uint32_t search_flags ;
TALLOC_CTX * tmp_ctx = talloc_new ( ac ) ;
const char * attrs [ ] = { NULL } ;
struct ldb_result * res ;
( * remove_value ) = false ;
2011-08-01 13:55:58 +10:00
status = dsdb_get_extended_dn_guid ( dn , & guid , " GUID " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
/* this is a strange DN that doesn't have a GUID! just
return the current DN string ? ? */
2011-10-07 13:20:35 +11:00
talloc_free ( tmp_ctx ) ;
2011-08-01 13:55:58 +10:00
return LDB_SUCCESS ;
}
2011-10-07 13:20:35 +11:00
search_flags = DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SEARCH_ALL_PARTITIONS | DSDB_SEARCH_ONE_ONLY ;
2016-07-13 13:29:19 +12:00
if ( linkID = = 0 ) {
/* You must ALWAYS show one-way links regardless of the state of the target */
search_flags | = ( DSDB_SEARCH_SHOW_DELETED | DSDB_SEARCH_SHOW_RECYCLED ) ;
2011-10-07 13:20:35 +11:00
}
ret = dsdb_module_search ( ac - > module , tmp_ctx , & res , NULL , LDB_SCOPE_SUBTREE , attrs ,
search_flags , ac - > req , " objectguid=%s " , GUID_string ( tmp_ctx , & guid ) ) ;
if ( ret ! = LDB_SUCCESS | | res - > count ! = 1 ) {
/* if we can't resolve this GUID, then we don't
display the link . This could be a link to a NC that we don ' t
have , or it could be a link to a deleted object
*/
( * remove_value ) = true ;
talloc_free ( tmp_ctx ) ;
2011-08-01 13:55:58 +10:00
return LDB_SUCCESS ;
}
2011-10-07 13:20:35 +11:00
real_dn = res - > msgs [ 0 ] - > dn ;
2011-08-01 13:55:58 +10:00
if ( strcmp ( ldb_dn_get_linearized ( dn ) , ldb_dn_get_linearized ( real_dn ) ) = = 0 ) {
/* its already correct */
2011-10-07 13:20:35 +11:00
talloc_free ( tmp_ctx ) ;
2011-08-01 13:55:58 +10:00
return LDB_SUCCESS ;
}
/* fix the DN by replacing its components with those from the
* real DN
*/
if ( ! ldb_dn_replace_components ( dn , real_dn ) ) {
2011-10-07 13:20:35 +11:00
talloc_free ( tmp_ctx ) ;
2011-08-01 13:55:58 +10:00
return ldb_operr ( ldb_module_get_ctx ( ac - > module ) ) ;
}
2011-10-07 13:20:35 +11:00
talloc_free ( tmp_ctx ) ;
2011-08-01 13:55:58 +10:00
return LDB_SUCCESS ;
}
/*
this is called to post - process the results from the search
*/
2019-03-12 11:43:15 +13:00
static int extended_callback ( struct ldb_request * req , struct ldb_reply * ares )
2008-12-16 09:21:55 +01:00
{
struct extended_search_context * ac ;
2010-03-07 19:03:21 +01:00
int ret ;
2019-04-11 13:14:24 +12:00
unsigned int i , j , k ;
2010-09-10 20:15:00 +10:00
struct ldb_message * msg ;
2009-02-02 08:19:11 +01:00
struct extended_dn_out_private * p ;
2009-11-07 12:07:06 +11:00
struct ldb_context * ldb ;
2018-09-28 14:55:14 +12:00
bool have_reveal_control = false ;
2009-12-10 23:46:34 +11:00
2008-12-16 09:21:55 +01:00
ac = talloc_get_type ( req - > context , struct extended_search_context ) ;
2009-06-30 15:12:29 +10:00
p = talloc_get_type ( ldb_module_get_private ( ac - > module ) , struct extended_dn_out_private ) ;
2009-11-07 12:07:06 +11:00
ldb = ldb_module_get_ctx ( ac - > module ) ;
2008-12-16 09:21:55 +01:00
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 ) ;
}
2010-09-10 20:15:00 +10:00
msg = ares - > message ;
2008-12-16 09:21:55 +01:00
switch ( ares - > type ) {
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 ) ;
case LDB_REPLY_ENTRY :
break ;
}
2009-02-02 08:19:11 +01:00
if ( p & & p - > normalise ) {
2013-09-19 10:41:16 -07:00
ret = dsdb_fix_dn_rdncase ( ldb , ares - > message - > dn ) ;
2008-12-16 09:21:55 +01:00
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
}
if ( ac - > inject ) {
/* for each record returned post-process to add any derived
attributes that have been asked for */
2009-11-07 12:07:06 +11:00
ret = inject_extended_dn_out ( ares , ldb ,
2008-12-16 09:21:55 +01:00
ac - > extended_type , ac - > remove_guid ,
ac - > remove_sid ) ;
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
}
2009-02-02 08:19:11 +01:00
if ( ( p & & p - > normalise ) | | ac - > inject ) {
2008-12-16 09:21:55 +01:00
const struct ldb_val * val = ldb_msg_find_ldb_val ( ares - > message , " distinguishedName " ) ;
if ( val ) {
ldb_msg_remove_attr ( ares - > message , " distinguishedName " ) ;
if ( ac - > inject ) {
ret = ldb_msg_add_steal_string ( ares - > message , " distinguishedName " ,
ldb_dn_get_extended_linearized ( ares - > message , ares - > message - > dn , ac - > extended_type ) ) ;
} else {
2009-11-23 15:47:51 -02:00
ret = ldb_msg_add_linearized_dn ( ares - > message ,
" distinguishedName " ,
ares - > message - > dn ) ;
2008-12-16 09:21:55 +01:00
}
if ( ret ! = LDB_SUCCESS ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb ) ;
2008-12-16 09:21:55 +01:00
}
}
}
2018-09-28 14:55:14 +12:00
have_reveal_control =
2018-10-11 17:50:52 +13:00
dsdb_request_has_control ( req , LDB_CONTROL_REVEAL_INTERNALS ) ;
2016-06-15 09:59:57 +12:00
/*
* Shortcut for repl_meta_data . We asked for the data
* ' as - is ' , so stop processing here !
*/
if ( have_reveal_control & & p - > normalise = = false & & ac - > inject = = true ) {
return ldb_module_send_entry ( ac - > req , msg , ares - > controls ) ;
}
2010-03-07 19:03:21 +01:00
/* Walk the returned elements (but only if we have a schema to
* interpret the list with ) */
2008-12-16 09:21:55 +01:00
for ( i = 0 ; ac - > schema & & i < msg - > num_elements ; i + + ) {
2009-11-22 17:48:32 +02:00
bool make_extended_dn ;
2023-02-09 15:04:26 +01:00
bool bl_requested = true ;
2008-12-16 09:21:55 +01:00
const struct dsdb_attribute * attribute ;
2011-08-01 13:55:58 +10:00
2008-12-16 09:21:55 +01:00
attribute = dsdb_attribute_by_lDAPDisplayName ( ac - > schema , msg - > elements [ i ] . name ) ;
if ( ! attribute ) {
continue ;
}
2018-04-10 16:34:21 +12:00
if ( p & & p - > normalise ) {
2008-12-16 09:21:55 +01:00
/* If we are also in 'normalise' mode, then
* fix the attribute names to be in the
* correct case */
msg - > elements [ i ] . name = talloc_strdup ( msg - > elements , attribute - > lDAPDisplayName ) ;
if ( ! msg - > elements [ i ] . name ) {
2009-11-07 12:07:06 +11:00
ldb_oom ( ldb ) ;
2008-12-16 09:21:55 +01:00
return ldb_module_done ( ac - > req , NULL , NULL , LDB_ERR_OPERATIONS_ERROR ) ;
}
}
/* distinguishedName has been dealt with above */
if ( ldb_attr_cmp ( msg - > elements [ i ] . name , " distinguishedName " ) = = 0 ) {
continue ;
}
/* Look to see if this attributeSyntax is a DN */
2011-08-05 11:28:12 +10:00
if ( attribute - > dn_format = = DSDB_INVALID_DN ) {
2008-12-16 09:21:55 +01:00
continue ;
}
2009-11-22 17:48:32 +02:00
make_extended_dn = ac - > inject ;
/* Always show plain DN in case of Object(OR-Name) syntax */
if ( make_extended_dn ) {
make_extended_dn = ( strcmp ( attribute - > syntax - > ldap_oid , DSDB_SYNTAX_OR_NAME ) ! = 0 ) ;
}
2023-02-09 15:04:26 +01:00
if ( attribute - > linkID & 1 & &
attribute - > bl_maybe_invisible & &
! have_reveal_control )
{
const char * const * attrs = ac - > req - > op . search . attrs ;
if ( attrs ! = NULL ) {
2023-02-14 12:03:10 +13:00
bl_requested = ldb_attr_in_list ( attrs ,
2023-02-09 15:04:26 +01:00
attribute - > lDAPDisplayName ) ;
} else {
bl_requested = false ;
}
}
2019-04-11 13:14:24 +12:00
for ( k = 0 , j = 0 ; j < msg - > elements [ i ] . num_values ; j + + ) {
2008-12-16 09:21:55 +01:00
const char * dn_str ;
2009-11-05 17:04:10 +11:00
struct ldb_dn * dn ;
struct dsdb_dn * dsdb_dn = NULL ;
2019-04-11 13:14:24 +12:00
struct ldb_val * plain_dn = & msg - > elements [ i ] . values [ j ] ;
2011-10-07 15:25:59 +11:00
bool is_deleted_objects = false ;
2023-02-09 15:04:26 +01:00
uint32_t rmd_flags ;
2009-12-15 11:01:18 +11:00
/* this is a fast method for detecting deleted
linked attributes , working on the unparsed
ldb_val */
2023-02-09 15:04:26 +01:00
rmd_flags = dsdb_dn_val_rmd_flags ( plain_dn ) ;
if ( rmd_flags & DSDB_RMD_FLAG_DELETED & & ! have_reveal_control ) {
2009-12-15 11:01:18 +11:00
/* it's a deleted linked attribute,
and we don ' t have the reveal control */
2019-04-11 13:14:24 +12:00
/* we won't keep this one, so not incrementing k */
2009-12-15 11:01:18 +11:00
continue ;
}
2023-02-09 15:04:26 +01:00
if ( rmd_flags & DSDB_RMD_FLAG_HIDDEN_BL & & ! bl_requested ) {
/*
* Hidden backlinks are not revealed unless
* requested .
*
* we won ' t keep this one , so not incrementing k
*/
continue ;
}
2009-12-15 11:01:18 +11:00
2016-09-01 14:54:25 +12:00
dsdb_dn = dsdb_dn_parse_trusted ( msg , ldb , plain_dn , attribute - > syntax - > ldap_oid ) ;
2009-12-10 23:46:34 +11:00
2016-09-01 14:54:25 +12:00
if ( ! dsdb_dn ) {
2019-04-11 13:14:24 +12:00
ldb_asprintf_errstring ( ldb ,
" could not parse %.*s in %s on %s as a %s DN " ,
2009-11-12 15:35:54 +11:00
( int ) plain_dn - > length , plain_dn - > data ,
msg - > elements [ i ] . name , ldb_dn_get_linearized ( msg - > dn ) ,
2009-11-05 17:04:10 +11:00
attribute - > syntax - > ldap_oid ) ;
talloc_free ( dsdb_dn ) ;
2008-12-16 09:21:55 +01:00
return ldb_module_done ( ac - > req , NULL , NULL , LDB_ERR_INVALID_DN_SYNTAX ) ;
}
2009-11-05 17:04:10 +11:00
dn = dsdb_dn - > dn ;
2008-12-16 09:21:55 +01:00
2011-10-07 15:25:59 +11:00
/* we need to know if this is a link to the
deleted objects container for fixing one way
links */
if ( dsdb_dn - > extra_part . length = = 16 ) {
char * hex_string = data_blob_hex_string_upper ( req , & dsdb_dn - > extra_part ) ;
if ( hex_string & & strcmp ( hex_string , DS_GUID_DELETED_OBJECTS_CONTAINER ) = = 0 ) {
is_deleted_objects = true ;
}
talloc_free ( hex_string ) ;
}
2009-02-02 08:19:11 +01:00
if ( p - > normalise ) {
2013-09-19 10:41:16 -07:00
ret = dsdb_fix_dn_rdncase ( ldb , dn ) ;
2008-12-16 09:21:55 +01:00
if ( ret ! = LDB_SUCCESS ) {
2009-11-05 17:04:10 +11:00
talloc_free ( dsdb_dn ) ;
2008-12-16 09:21:55 +01:00
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
}
2019-04-11 13:14:24 +12:00
2008-12-16 09:21:55 +01:00
/* Look for this value in the attribute */
2011-08-01 13:55:58 +10:00
/* note that we don't fixup objectCategory as
it should not be possible to move
objectCategory elements in the schema */
if ( attribute - > one_way_link & &
strcasecmp ( attribute - > lDAPDisplayName , " objectCategory " ) ! = 0 ) {
2011-10-07 13:20:35 +11:00
bool remove_value ;
2016-07-13 13:29:19 +12:00
ret = fix_one_way_link ( ac , dn , is_deleted_objects , & remove_value ,
attribute - > linkID ) ;
2011-08-01 13:55:58 +10:00
if ( ret ! = LDB_SUCCESS ) {
2009-11-05 17:04:10 +11:00
talloc_free ( dsdb_dn ) ;
2008-12-16 09:21:55 +01:00
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
2023-02-09 15:03:58 +01:00
if ( remove_value & & ! have_reveal_control ) {
2011-10-07 13:20:35 +11:00
/* we show these with REVEAL
to allow dbcheck to find and
cleanup these orphaned links */
2019-04-11 13:14:24 +12:00
/* we won't keep this one, so not incrementing k */
2011-10-07 13:20:35 +11:00
continue ;
}
2008-12-16 09:21:55 +01:00
}
2009-11-22 17:48:32 +02:00
if ( make_extended_dn ) {
2016-09-01 14:54:25 +12:00
if ( ! ldb_dn_validate ( dsdb_dn - > dn ) ) {
ldb_asprintf_errstring ( ldb ,
" could not parse %.*s in %s on %s as a %s DN " ,
( int ) plain_dn - > length , plain_dn - > data ,
msg - > elements [ i ] . name , ldb_dn_get_linearized ( msg - > dn ) ,
attribute - > syntax - > ldap_oid ) ;
talloc_free ( dsdb_dn ) ;
return ldb_module_done ( ac - > req , NULL , NULL , LDB_ERR_INVALID_DN_SYNTAX ) ;
}
/* don't let users see the internal extended
GUID components */
if ( ! have_reveal_control ) {
const char * accept [ ] = { " GUID " , " SID " , NULL } ;
ldb_dn_extended_filter ( dn , accept ) ;
}
2009-11-22 17:48:32 +02:00
dn_str = dsdb_dn_get_extended_linearized ( msg - > elements [ i ] . values ,
dsdb_dn , ac - > extended_type ) ;
} else {
2019-04-11 13:14:24 +12:00
dn_str = dsdb_dn_get_linearized ( msg - > elements [ i ] . values ,
2009-11-05 17:04:10 +11:00
dsdb_dn ) ;
2008-12-16 09:21:55 +01:00
}
2019-04-11 13:14:24 +12:00
2008-12-16 09:21:55 +01:00
if ( ! dn_str ) {
2009-11-07 12:07:06 +11:00
ldb_oom ( ldb ) ;
2009-11-05 17:04:10 +11:00
talloc_free ( dsdb_dn ) ;
2008-12-16 09:21:55 +01:00
return ldb_module_done ( ac - > req , NULL , NULL , LDB_ERR_OPERATIONS_ERROR ) ;
}
2019-04-11 13:14:24 +12:00
msg - > elements [ i ] . values [ k ] = data_blob_string_const ( dn_str ) ;
2009-11-05 17:04:10 +11:00
talloc_free ( dsdb_dn ) ;
2019-04-11 13:14:24 +12:00
k + + ;
2008-12-16 09:21:55 +01:00
}
2019-04-11 13:14:24 +12:00
if ( k = = 0 ) {
2009-12-10 23:46:34 +11:00
/* we've deleted all of the values from this
* element - remove the element */
2019-04-10 16:37:23 +12:00
ldb_msg_remove_element ( msg , & msg - > elements [ i ] ) ;
2009-12-10 23:46:34 +11:00
i - - ;
2019-04-11 13:14:24 +12:00
} else {
msg - > elements [ i ] . num_values = k ;
2009-12-10 23:46:34 +11:00
}
2008-12-16 09:21:55 +01:00
}
return ldb_module_send_entry ( ac - > req , msg , ares - > controls ) ;
}
2009-11-12 21:31:11 +11:00
static int extended_callback_ldb ( struct ldb_request * req , struct ldb_reply * ares )
{
2019-03-12 11:43:15 +13:00
return extended_callback ( req , ares ) ;
2009-10-21 16:02:18 -05:00
}
static int extended_dn_out_search ( struct ldb_module * module , struct ldb_request * req ,
int ( * callback ) ( struct ldb_request * req , struct ldb_reply * ares ) )
2008-12-16 09:21:55 +01:00
{
struct ldb_control * control ;
struct ldb_control * storage_format_control ;
struct ldb_extended_dn_control * extended_ctrl = NULL ;
struct extended_search_context * ac ;
struct ldb_request * down_req ;
char * * new_attrs ;
const char * const * const_attrs ;
2009-11-07 12:07:06 +11:00
struct ldb_context * ldb = ldb_module_get_ctx ( module ) ;
2008-12-16 09:21:55 +01:00
int ret ;
2009-06-30 15:12:29 +10:00
struct extended_dn_out_private * p = talloc_get_type ( ldb_module_get_private ( module ) , struct extended_dn_out_private ) ;
2008-12-16 09:21:55 +01:00
2010-03-22 15:17:58 +11:00
/* The schema manipulation does not apply to special DNs */
if ( ldb_dn_is_special ( req - > op . search . base ) ) {
return ldb_next_request ( module , req ) ;
}
2008-12-16 09:21:55 +01:00
/* check if there's an extended dn control */
control = ldb_request_get_control ( req , LDB_CONTROL_EXTENDED_DN_OID ) ;
if ( control & & control - > data ) {
extended_ctrl = talloc_get_type ( control - > data , struct ldb_extended_dn_control ) ;
if ( ! extended_ctrl ) {
return LDB_ERR_PROTOCOL_ERROR ;
}
}
/* Look to see if, as we are in 'store DN+GUID+SID' mode, the
* client is after the storage format ( to fill in linked
* attributes ) */
storage_format_control = ldb_request_get_control ( req , DSDB_CONTROL_DN_STORAGE_FORMAT_OID ) ;
if ( ! control & & storage_format_control & & storage_format_control - > data ) {
extended_ctrl = talloc_get_type ( storage_format_control - > data , struct ldb_extended_dn_control ) ;
if ( ! extended_ctrl ) {
2009-11-07 12:07:06 +11:00
ldb_set_errstring ( ldb , " extended_dn_out: extended_ctrl was of the wrong data type " ) ;
2008-12-16 09:21:55 +01:00
return LDB_ERR_PROTOCOL_ERROR ;
}
}
ac = talloc_zero ( req , struct extended_search_context ) ;
if ( ac = = NULL ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb ) ;
2008-12-16 09:21:55 +01:00
}
ac - > module = module ;
2010-03-16 14:52:39 +11:00
ac - > schema = dsdb_get_schema ( ldb , ac ) ;
2008-12-16 09:21:55 +01:00
ac - > req = req ;
ac - > inject = false ;
ac - > remove_guid = false ;
ac - > remove_sid = false ;
const_attrs = req - > op . search . attrs ;
/* We only need to do special processing if we were asked for
* the extended DN , or we are ' store DN + GUID + SID '
* ( ! dereference ) mode . ( This is the normal mode for LDB on
* tdb ) . */
2019-03-12 11:43:15 +13:00
if ( control | | ( storage_format_control & & p ) ) {
2008-12-16 09:21:55 +01:00
ac - > inject = true ;
if ( extended_ctrl ) {
ac - > extended_type = extended_ctrl - > type ;
} else {
ac - > extended_type = 0 ;
}
2019-01-07 15:07:22 +01:00
/* check if attrs only is specified, in that case check whether we need to modify them */
2023-02-14 12:03:10 +13:00
if ( req - > op . search . attrs & & ! ldb_attr_in_list ( req - > op . search . attrs , " * " ) ) {
if ( ! ldb_attr_in_list ( req - > op . search . attrs , " objectGUID " ) ) {
2008-12-16 09:21:55 +01:00
ac - > remove_guid = true ;
}
2023-02-14 12:03:10 +13:00
if ( ! ldb_attr_in_list ( req - > op . search . attrs , " objectSid " ) ) {
2008-12-16 09:21:55 +01:00
ac - > remove_sid = true ;
}
if ( ac - > remove_guid | | ac - > remove_sid ) {
new_attrs = copy_attrs ( ac , req - > op . search . attrs ) ;
if ( new_attrs = = NULL ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb ) ;
2008-12-16 09:21:55 +01:00
}
if ( ac - > remove_guid ) {
if ( ! add_attrs ( ac , & new_attrs , " objectGUID " ) )
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2008-12-16 09:21:55 +01:00
}
if ( ac - > remove_sid ) {
2010-09-13 22:39:50 +02:00
if ( ! add_attrs ( ac , & new_attrs , " objectSid " ) )
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb ) ;
2008-12-16 09:21:55 +01:00
}
const_attrs = ( const char * const * ) new_attrs ;
}
}
}
ret = ldb_build_search_req_ex ( & down_req ,
2009-11-07 12:07:06 +11:00
ldb , ac ,
2008-12-16 09:21:55 +01:00
req - > op . search . base ,
req - > op . search . scope ,
req - > op . search . tree ,
const_attrs ,
req - > controls ,
2009-10-21 16:02:18 -05:00
ac , callback ,
2008-12-16 09:21:55 +01:00
req ) ;
2010-09-24 12:09:26 -07:00
LDB_REQ_SET_LOCATION ( down_req ) ;
2008-12-16 09:21:55 +01:00
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2009-12-16 20:45:02 +11:00
/* mark extended DN and storage format controls as done */
2008-12-16 09:21:55 +01:00
if ( control ) {
2009-12-16 20:45:02 +11:00
control - > critical = 0 ;
2008-12-16 09:21:55 +01:00
}
if ( storage_format_control ) {
2009-12-16 20:45:02 +11:00
storage_format_control - > critical = 0 ;
2008-12-16 09:21:55 +01:00
}
/* perform the search */
return ldb_next_request ( module , down_req ) ;
}
2009-10-21 16:02:18 -05:00
static int extended_dn_out_ldb_search ( struct ldb_module * module , struct ldb_request * req )
{
2009-11-12 21:31:11 +11:00
return extended_dn_out_search ( module , req , extended_callback_ldb ) ;
2009-10-21 16:02:18 -05:00
}
2008-12-16 09:21:55 +01:00
static int extended_dn_out_ldb_init ( struct ldb_module * module )
{
int ret ;
2009-02-02 08:19:11 +01:00
struct extended_dn_out_private * p = talloc ( module , struct extended_dn_out_private ) ;
2009-11-16 18:46:28 +11:00
struct dsdb_extended_dn_store_format * dn_format ;
2008-12-16 09:21:55 +01:00
2009-06-30 15:12:29 +10:00
ldb_module_set_private ( module , p ) ;
2008-12-16 09:21:55 +01:00
2009-02-02 08:19:11 +01:00
if ( ! p ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2008-12-16 09:21:55 +01:00
}
2009-11-16 18:46:28 +11:00
dn_format = talloc ( p , struct dsdb_extended_dn_store_format ) ;
if ( ! dn_format ) {
talloc_free ( p ) ;
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2009-11-16 18:46:28 +11:00
}
dn_format - > store_extended_dn_in_ldb = true ;
ret = ldb_set_opaque ( ldb_module_get_ctx ( module ) , DSDB_EXTENDED_DN_STORE_FORMAT_OPAQUE_NAME , dn_format ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( p ) ;
return ret ;
}
2009-02-02 08:19:11 +01:00
p - > dereference = false ;
p - > normalise = false ;
2008-12-16 09:21:55 +01:00
ret = ldb_mod_register_control ( module , LDB_CONTROL_EXTENDED_DN_OID ) ;
if ( ret ! = LDB_SUCCESS ) {
2009-06-30 15:12:29 +10:00
ldb_debug ( ldb_module_get_ctx ( module ) , LDB_DEBUG_ERROR ,
2008-12-16 09:21:55 +01:00
" extended_dn_out: Unable to register control with rootdse! \n " ) ;
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb_module_get_ctx ( module ) ) ;
2008-12-16 09:21:55 +01:00
}
return ldb_next_init ( module ) ;
}
2010-11-01 12:39:06 +11:00
static const struct ldb_module_ops ldb_extended_dn_out_ldb_module_ops = {
2008-12-16 09:21:55 +01:00
. name = " extended_dn_out_ldb " ,
2009-10-21 16:02:18 -05:00
. search = extended_dn_out_ldb_search ,
2008-12-16 09:21:55 +01:00
. init_context = extended_dn_out_ldb_init ,
} ;
2010-11-01 12:39:06 +11:00
/*
initialise the module
*/
2010-11-01 22:30:45 +11:00
_PUBLIC_ int ldb_extended_dn_out_module_init ( const char * version )
2010-11-01 12:39:06 +11:00
{
int ret ;
2010-11-01 22:30:45 +11:00
LDB_MODULE_CHECK_VERSION ( version ) ;
2010-11-01 12:39:06 +11:00
ret = ldb_register_module ( & ldb_extended_dn_out_ldb_module_ops ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
return LDB_SUCCESS ;
}