2008-12-16 09:21:55 +01:00
/*
ldb database library
Copyright ( C ) Simo Sorce 2005 - 2008
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2007 - 2008
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 interprets DNs of the form < SID = S - 1 - 2 - 4456 > into normal DNs .
*
* 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>
2011-08-01 17:48:53 +10:00
# include "dsdb/samdb/samdb.h"
2011-09-20 14:26:36 -07:00
# include "dsdb/samdb/ldb_modules/util.h"
2016-01-07 10:28:12 +13:00
# include "lib/ldb-samba/ldb_matching_rules.h"
2008-12-16 09:21:55 +01:00
2020-08-07 13:27:39 -07:00
# undef strncasecmp
2009-12-10 23:49:02 +11:00
/*
TODO : if relax is not set then we need to reject the fancy RMD_ * and
DELETED extended DN codes
*/
2008-12-16 09:21:55 +01:00
/* search */
struct extended_search_context {
struct ldb_module * module ;
struct ldb_request * req ;
struct ldb_dn * basedn ;
2011-07-11 12:01:18 +10:00
struct ldb_dn * dn ;
2008-12-16 09:21:55 +01:00
char * wellknown_object ;
int extended_type ;
} ;
2012-05-14 20:16:11 -07:00
static const char * wkattr [ ] = {
" wellKnownObjects " ,
" otherWellKnownObjects " ,
NULL
} ;
2013-09-16 19:51:20 -07:00
static const struct ldb_module_ops ldb_extended_dn_in_openldap_module_ops ;
2008-12-16 09:21:55 +01:00
/* An extra layer of indirection because LDB does not allow the original request to be altered */
static int extended_final_callback ( struct ldb_request * req , struct ldb_reply * ares )
{
int ret = LDB_ERR_OPERATIONS_ERROR ;
struct extended_search_context * ac ;
ac = talloc_get_type ( req - > context , struct extended_search_context ) ;
if ( ares - > error ! = LDB_SUCCESS ) {
ret = ldb_module_done ( ac - > req , ares - > controls ,
ares - > response , ares - > error ) ;
} else {
switch ( ares - > type ) {
case LDB_REPLY_ENTRY :
ret = ldb_module_send_entry ( ac - > req , ares - > message , ares - > controls ) ;
break ;
case LDB_REPLY_REFERRAL :
ret = ldb_module_send_referral ( ac - > req , ares - > referral ) ;
break ;
case LDB_REPLY_DONE :
ret = ldb_module_done ( ac - > req , ares - > controls ,
ares - > response , ares - > error ) ;
break ;
}
}
return ret ;
}
static int extended_base_callback ( struct ldb_request * req , struct ldb_reply * ares )
{
struct extended_search_context * ac ;
struct ldb_request * down_req ;
struct ldb_message_element * el ;
int ret ;
2012-05-14 20:16:11 -07:00
unsigned int i , j ;
2008-12-16 09:21:55 +01:00
size_t wkn_len = 0 ;
char * valstr = NULL ;
const char * found = NULL ;
ac = talloc_get_type ( req - > context , struct extended_search_context ) ;
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 :
2011-06-22 17:05:08 +10:00
if ( ac - > basedn ) {
/* we have more than one match! This can
happen as S - 1 - 5 - 17 appears twice in a
normal provision . We need to return
NO_SUCH_OBJECT */
const char * str = talloc_asprintf ( req , " Duplicate base-DN matches found for '%s' " ,
2011-07-11 12:01:18 +10:00
ldb_dn_get_extended_linearized ( req , ac - > dn , 1 ) ) ;
2011-06-22 17:05:08 +10:00
ldb_set_errstring ( ldb_module_get_ctx ( ac - > module ) , str ) ;
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_NO_SUCH_OBJECT ) ;
}
2008-12-16 09:21:55 +01:00
if ( ! ac - > wellknown_object ) {
ac - > basedn = talloc_steal ( ac , ares - > message - > dn ) ;
break ;
}
wkn_len = strlen ( ac - > wellknown_object ) ;
2012-05-14 20:16:11 -07:00
for ( j = 0 ; wkattr [ j ] ; j + + ) {
2008-12-16 09:21:55 +01:00
2012-05-14 20:16:11 -07:00
el = ldb_msg_find_element ( ares - > message , wkattr [ j ] ) ;
if ( ! el ) {
ac - > basedn = NULL ;
2008-12-16 09:21:55 +01:00
continue ;
}
2012-05-14 20:16:11 -07:00
for ( i = 0 ; i < el - > num_values ; i + + ) {
valstr = talloc_strndup ( ac ,
( const char * ) el - > values [ i ] . data ,
el - > values [ i ] . length ) ;
if ( ! valstr ) {
ldb_oom ( ldb_module_get_ctx ( ac - > module ) ) ;
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
}
if ( strncasecmp ( valstr , ac - > wellknown_object , wkn_len ) ! = 0 ) {
talloc_free ( valstr ) ;
continue ;
}
found = & valstr [ wkn_len ] ;
break ;
}
if ( found ) {
break ;
}
2008-12-16 09:21:55 +01:00
}
if ( ! found ) {
break ;
}
2009-06-30 15:12:29 +10:00
ac - > basedn = ldb_dn_new ( ac , ldb_module_get_ctx ( ac - > module ) , found ) ;
2008-12-16 09:21:55 +01:00
talloc_free ( valstr ) ;
if ( ! ac - > basedn ) {
2009-06-30 15:12:29 +10:00
ldb_oom ( ldb_module_get_ctx ( ac - > module ) ) ;
2008-12-16 09:21:55 +01:00
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
}
break ;
case LDB_REPLY_REFERRAL :
break ;
case LDB_REPLY_DONE :
if ( ! ac - > basedn ) {
const char * str = talloc_asprintf ( req , " Base-DN '%s' not found " ,
2011-07-11 12:01:18 +10:00
ldb_dn_get_extended_linearized ( req , ac - > dn , 1 ) ) ;
2009-06-30 15:12:29 +10:00
ldb_set_errstring ( ldb_module_get_ctx ( ac - > module ) , str ) ;
2008-12-16 09:21:55 +01:00
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_NO_SUCH_OBJECT ) ;
}
switch ( ac - > req - > operation ) {
case LDB_SEARCH :
ret = ldb_build_search_req_ex ( & down_req ,
2009-06-30 15:12:29 +10:00
ldb_module_get_ctx ( ac - > module ) , ac - > req ,
2008-12-16 09:21:55 +01:00
ac - > basedn ,
ac - > req - > op . search . scope ,
ac - > req - > op . search . tree ,
ac - > req - > op . search . attrs ,
ac - > req - > controls ,
ac , extended_final_callback ,
ac - > req ) ;
2010-09-24 12:09:26 -07:00
LDB_REQ_SET_LOCATION ( down_req ) ;
2008-12-16 09:21:55 +01:00
break ;
case LDB_ADD :
{
struct ldb_message * add_msg = ldb_msg_copy_shallow ( ac , ac - > req - > op . add . message ) ;
if ( ! add_msg ) {
2009-06-30 15:12:29 +10:00
ldb_oom ( ldb_module_get_ctx ( ac - > module ) ) ;
2008-12-16 09:21:55 +01:00
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
}
add_msg - > dn = ac - > basedn ;
ret = ldb_build_add_req ( & down_req ,
2009-06-30 15:12:29 +10:00
ldb_module_get_ctx ( ac - > module ) , ac - > req ,
2008-12-16 09:21:55 +01:00
add_msg ,
ac - > req - > controls ,
ac , extended_final_callback ,
ac - > req ) ;
2010-09-24 12:09:26 -07:00
LDB_REQ_SET_LOCATION ( down_req ) ;
2008-12-16 09:21:55 +01:00
break ;
}
case LDB_MODIFY :
{
struct ldb_message * mod_msg = ldb_msg_copy_shallow ( ac , ac - > req - > op . mod . message ) ;
if ( ! mod_msg ) {
2009-06-30 15:12:29 +10:00
ldb_oom ( ldb_module_get_ctx ( ac - > module ) ) ;
2008-12-16 09:21:55 +01:00
return ldb_module_done ( ac - > req , NULL , NULL ,
LDB_ERR_OPERATIONS_ERROR ) ;
}
mod_msg - > dn = ac - > basedn ;
ret = ldb_build_mod_req ( & down_req ,
2009-06-30 15:12:29 +10:00
ldb_module_get_ctx ( ac - > module ) , ac - > req ,
2008-12-16 09:21:55 +01:00
mod_msg ,
ac - > req - > controls ,
ac , extended_final_callback ,
ac - > req ) ;
2010-09-24 12:50:13 -07:00
LDB_REQ_SET_LOCATION ( down_req ) ;
2008-12-16 09:21:55 +01:00
break ;
}
case LDB_DELETE :
ret = ldb_build_del_req ( & down_req ,
2009-06-30 15:12:29 +10:00
ldb_module_get_ctx ( ac - > module ) , ac - > req ,
2008-12-16 09:21:55 +01:00
ac - > basedn ,
ac - > req - > controls ,
ac , extended_final_callback ,
ac - > req ) ;
2010-09-24 12:50:13 -07:00
LDB_REQ_SET_LOCATION ( down_req ) ;
2008-12-16 09:21:55 +01:00
break ;
case LDB_RENAME :
ret = ldb_build_rename_req ( & down_req ,
2009-06-30 15:12:29 +10:00
ldb_module_get_ctx ( ac - > module ) , ac - > req ,
2008-12-16 09:21:55 +01:00
ac - > basedn ,
ac - > req - > op . rename . newdn ,
ac - > req - > controls ,
ac , extended_final_callback ,
ac - > req ) ;
2010-09-24 12:50:13 -07:00
LDB_REQ_SET_LOCATION ( down_req ) ;
2008-12-16 09:21:55 +01:00
break ;
default :
return ldb_module_done ( ac - > req , NULL , NULL , LDB_ERR_OPERATIONS_ERROR ) ;
}
if ( ret ! = LDB_SUCCESS ) {
return ldb_module_done ( ac - > req , NULL , NULL , ret ) ;
}
return ldb_next_request ( ac - > module , down_req ) ;
}
talloc_free ( ares ) ;
return LDB_SUCCESS ;
}
2011-08-01 17:48:53 +10:00
2011-08-02 17:19:16 +10:00
/*
windows ldap searchs don ' t allow a baseDN with more
than one extended component , or an extended
component and a string DN
We only enforce this over ldap , not for internal
use , as there are just too many places where we
internally want to use a DN that has come from a
search with extended DN enabled , or comes from a DRS
naming context .
Enforcing this would also make debugging samba much
harder , as we ' d need to use ldb_dn_minimise ( ) in a
lot of places , and that would lose the DN string
which is so useful for working out what a request is
for
*/
static bool ldb_dn_match_allowed ( struct ldb_dn * dn , struct ldb_request * req )
{
int num_components = ldb_dn_get_comp_num ( dn ) ;
int num_ex_components = ldb_dn_get_extended_comp_num ( dn ) ;
if ( num_ex_components = = 0 ) {
return true ;
}
if ( ( num_components ! = 0 | | num_ex_components ! = 1 ) & &
ldb_req_is_untrusted ( req ) ) {
return false ;
}
return true ;
}
2011-08-01 17:48:53 +10:00
struct extended_dn_filter_ctx {
bool test_only ;
bool matched ;
struct ldb_module * module ;
struct ldb_request * req ;
struct dsdb_schema * schema ;
2014-07-07 12:00:14 +02:00
uint32_t dsdb_flags ;
2011-08-01 17:48:53 +10:00
} ;
2011-08-02 17:19:16 +10:00
/*
create a always non - matching node from a equality node
*/
static void set_parse_tree_false ( struct ldb_parse_tree * tree )
{
const char * attr = tree - > u . equality . attr ;
struct ldb_val value = tree - > u . equality . value ;
tree - > operation = LDB_OP_EXTENDED ;
tree - > u . extended . attr = attr ;
tree - > u . extended . value = value ;
tree - > u . extended . rule_id = SAMBA_LDAP_MATCH_ALWAYS_FALSE ;
tree - > u . extended . dnAttributes = 0 ;
}
2011-08-01 17:48:53 +10:00
/*
called on all nodes in the parse tree
*/
static int extended_dn_filter_callback ( struct ldb_parse_tree * tree , void * private_context )
{
struct extended_dn_filter_ctx * filter_ctx ;
int ret ;
2014-10-28 11:53:01 +01:00
struct ldb_dn * dn = NULL ;
2011-08-01 17:48:53 +10:00
const struct ldb_val * sid_val , * guid_val ;
const char * no_attrs [ ] = { NULL } ;
struct ldb_result * res ;
2014-10-28 11:53:01 +01:00
const struct dsdb_attribute * attribute = NULL ;
bool has_extended_component = false ;
2011-08-02 17:19:16 +10:00
enum ldb_scope scope ;
struct ldb_dn * base_dn ;
const char * expression ;
2011-08-19 17:34:12 +10:00
uint32_t dsdb_flags ;
2011-08-01 17:48:53 +10:00
2014-10-28 11:53:01 +01:00
if ( tree - > operation ! = LDB_OP_EQUALITY & & tree - > operation ! = LDB_OP_EXTENDED ) {
2011-08-01 17:48:53 +10:00
return LDB_SUCCESS ;
}
filter_ctx = talloc_get_type_abort ( private_context , struct extended_dn_filter_ctx ) ;
2011-08-05 13:10:22 +10:00
if ( filter_ctx - > test_only & & filter_ctx - > matched ) {
/* the tree already matched */
return LDB_SUCCESS ;
}
2012-05-30 10:57:06 -07:00
if ( ! filter_ctx - > schema ) {
/* Schema not setup yet */
return LDB_SUCCESS ;
}
2014-10-28 11:53:01 +01:00
if ( tree - > operation = = LDB_OP_EQUALITY ) {
attribute = dsdb_attribute_by_lDAPDisplayName ( filter_ctx - > schema , tree - > u . equality . attr ) ;
} else if ( tree - > operation = = LDB_OP_EXTENDED ) {
attribute = dsdb_attribute_by_lDAPDisplayName ( filter_ctx - > schema , tree - > u . extended . attr ) ;
}
2011-08-01 17:48:53 +10:00
if ( attribute = = NULL ) {
return LDB_SUCCESS ;
}
if ( attribute - > dn_format ! = DSDB_NORMAL_DN ) {
return LDB_SUCCESS ;
}
2014-10-28 11:53:01 +01:00
if ( tree - > operation = = LDB_OP_EQUALITY ) {
has_extended_component = ( memchr ( tree - > u . equality . value . data , ' < ' ,
tree - > u . equality . value . length ) ! = NULL ) ;
} else if ( tree - > operation = = LDB_OP_EXTENDED ) {
has_extended_component = ( memchr ( tree - > u . extended . value . data , ' < ' ,
tree - > u . extended . value . length ) ! = NULL ) ;
}
2011-08-01 17:48:53 +10:00
2013-09-16 19:51:20 -07:00
/*
* Don ' t turn it into an extended DN if we ' re talking to OpenLDAP .
* We just check the module_ops pointer instead of adding a private
* pointer and a boolean to tell us the exact same thing .
*/
if ( ! has_extended_component ) {
2014-12-19 15:39:59 +13:00
if ( ! attribute - > one_way_link ) {
return LDB_SUCCESS ;
}
if ( ldb_module_get_ops ( filter_ctx - > module ) = = & ldb_extended_dn_in_openldap_module_ops ) {
return LDB_SUCCESS ;
}
2011-08-01 17:48:53 +10:00
}
2014-10-28 11:53:01 +01:00
if ( tree - > operation = = LDB_OP_EQUALITY ) {
dn = ldb_dn_from_ldb_val ( filter_ctx , ldb_module_get_ctx ( filter_ctx - > module ) , & tree - > u . equality . value ) ;
2016-01-07 10:28:12 +13:00
} else if ( tree - > operation = = LDB_OP_EXTENDED
& & ( strcmp ( tree - > u . extended . rule_id , SAMBA_LDAP_MATCH_RULE_TRANSITIVE_EVAL ) = = 0 ) ) {
2014-10-28 11:53:01 +01:00
dn = ldb_dn_from_ldb_val ( filter_ctx , ldb_module_get_ctx ( filter_ctx - > module ) , & tree - > u . extended . value ) ;
}
2011-08-01 17:48:53 +10:00
if ( dn = = NULL ) {
/* testing against windows shows that we don't raise
an error here */
return LDB_SUCCESS ;
}
2011-08-05 13:10:22 +10:00
guid_val = ldb_dn_get_extended_component ( dn , " GUID " ) ;
sid_val = ldb_dn_get_extended_component ( dn , " SID " ) ;
if ( ! guid_val & & ! sid_val & & ( attribute - > searchFlags & SEARCH_FLAG_ATTINDEX ) ) {
/* if it is indexed, then fixing the string DN will do
no good here , as we will not find the attribute in
the index . So for now fall through to a standard DN
component comparison */
return LDB_SUCCESS ;
}
2011-08-02 17:19:16 +10:00
if ( filter_ctx - > test_only ) {
2011-08-05 13:10:22 +10:00
/* we need to copy the tree */
2011-08-02 17:19:16 +10:00
filter_ctx - > matched = true ;
2011-08-01 17:48:53 +10:00
return LDB_SUCCESS ;
}
2011-08-02 17:19:16 +10:00
if ( ! ldb_dn_match_allowed ( dn , filter_ctx - > req ) ) {
/* we need to make this element of the filter always
be false */
set_parse_tree_false ( tree ) ;
2011-08-01 17:48:53 +10:00
return LDB_SUCCESS ;
}
2014-07-07 12:00:14 +02:00
dsdb_flags = filter_ctx - > dsdb_flags | DSDB_FLAG_NEXT_MODULE ;
2011-08-19 17:34:12 +10:00
2011-08-01 17:48:53 +10:00
if ( guid_val ) {
expression = talloc_asprintf ( filter_ctx , " objectGUID=%s " , ldb_binary_encode ( filter_ctx , * guid_val ) ) ;
2011-08-02 17:19:16 +10:00
scope = LDB_SCOPE_SUBTREE ;
base_dn = NULL ;
2011-08-19 17:34:12 +10:00
dsdb_flags | = DSDB_SEARCH_SEARCH_ALL_PARTITIONS ;
2011-08-02 17:19:16 +10:00
} else if ( sid_val ) {
2011-08-01 17:48:53 +10:00
expression = talloc_asprintf ( filter_ctx , " objectSID=%s " , ldb_binary_encode ( filter_ctx , * sid_val ) ) ;
2011-08-02 17:19:16 +10:00
scope = LDB_SCOPE_SUBTREE ;
base_dn = NULL ;
2011-08-19 17:34:12 +10:00
dsdb_flags | = DSDB_SEARCH_SEARCH_ALL_PARTITIONS ;
2011-08-02 17:19:16 +10:00
} else {
/* fallback to searching using the string DN as the base DN */
expression = " objectClass=* " ;
base_dn = dn ;
scope = LDB_SCOPE_BASE ;
2011-08-01 17:48:53 +10:00
}
ret = dsdb_module_search ( filter_ctx - > module ,
filter_ctx ,
& res ,
2011-08-02 17:19:16 +10:00
base_dn ,
scope ,
2011-08-01 17:48:53 +10:00
no_attrs ,
2011-08-19 17:34:12 +10:00
dsdb_flags ,
2011-08-01 17:48:53 +10:00
filter_ctx - > req ,
" %s " , expression ) ;
2011-08-02 17:19:16 +10:00
if ( scope = = LDB_SCOPE_BASE & & ret = = LDB_ERR_NO_SUCH_OBJECT ) {
/* note that this will need to change for multi-domain
support */
set_parse_tree_false ( tree ) ;
return LDB_SUCCESS ;
}
2011-08-01 17:48:53 +10:00
if ( ret ! = LDB_SUCCESS ) {
return LDB_SUCCESS ;
}
2011-08-02 17:19:16 +10:00
2011-08-01 17:48:53 +10:00
if ( res - > count ! = 1 ) {
return LDB_SUCCESS ;
}
/* replace the search expression element with the matching DN */
2014-10-28 11:53:01 +01:00
if ( tree - > operation = = LDB_OP_EQUALITY ) {
tree - > u . equality . value . data =
( uint8_t * ) talloc_strdup ( tree , ldb_dn_get_extended_linearized ( tree , res - > msgs [ 0 ] - > dn , 1 ) ) ;
if ( tree - > u . equality . value . data = = NULL ) {
return ldb_oom ( ldb_module_get_ctx ( filter_ctx - > module ) ) ;
}
tree - > u . equality . value . length = strlen ( ( const char * ) tree - > u . equality . value . data ) ;
} else if ( tree - > operation = = LDB_OP_EXTENDED ) {
tree - > u . extended . value . data =
( uint8_t * ) talloc_strdup ( tree , ldb_dn_get_extended_linearized ( tree , res - > msgs [ 0 ] - > dn , 1 ) ) ;
if ( tree - > u . extended . value . data = = NULL ) {
return ldb_oom ( ldb_module_get_ctx ( filter_ctx - > module ) ) ;
}
tree - > u . extended . value . length = strlen ( ( const char * ) tree - > u . extended . value . data ) ;
2011-08-01 17:48:53 +10:00
}
talloc_free ( res ) ;
filter_ctx - > matched = true ;
return LDB_SUCCESS ;
}
/*
fix the parse tree to change any extended DN components to their
2021-01-05 15:41:45 +01:00
canonical form
2011-08-01 17:48:53 +10:00
*/
2014-07-07 12:00:14 +02:00
static int extended_dn_fix_filter ( struct ldb_module * module ,
struct ldb_request * req ,
uint32_t default_dsdb_flags )
2011-08-01 17:48:53 +10:00
{
struct extended_dn_filter_ctx * filter_ctx ;
int ret ;
filter_ctx = talloc_zero ( req , struct extended_dn_filter_ctx ) ;
if ( filter_ctx = = NULL ) {
return ldb_module_oom ( module ) ;
}
/* first pass through the existing tree to see if anything
needs to be modified . Filtering DNs on the input side is rare ,
so this avoids copying the parse tree in most cases */
filter_ctx - > test_only = true ;
filter_ctx - > matched = false ;
filter_ctx - > module = module ;
filter_ctx - > req = req ;
filter_ctx - > schema = dsdb_get_schema ( ldb_module_get_ctx ( module ) , filter_ctx ) ;
2014-07-07 12:00:14 +02:00
filter_ctx - > dsdb_flags = default_dsdb_flags ;
2011-08-01 17:48:53 +10:00
ret = ldb_parse_tree_walk ( req - > op . search . tree , extended_dn_filter_callback , filter_ctx ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( filter_ctx ) ;
return ret ;
}
if ( ! filter_ctx - > matched ) {
/* nothing matched, no need for a new parse tree */
talloc_free ( filter_ctx ) ;
return LDB_SUCCESS ;
}
filter_ctx - > test_only = false ;
filter_ctx - > matched = false ;
2011-08-02 17:19:16 +10:00
req - > op . search . tree = ldb_parse_tree_copy_shallow ( req , req - > op . search . tree ) ;
if ( req - > op . search . tree = = NULL ) {
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
}
2011-08-01 17:48:53 +10:00
ret = ldb_parse_tree_walk ( req - > op . search . tree , extended_dn_filter_callback , filter_ctx ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( filter_ctx ) ;
return ret ;
}
talloc_free ( filter_ctx ) ;
return LDB_SUCCESS ;
}
/*
fix DNs and filter expressions to cope with the semantics of
extended DNs
*/
2008-12-16 09:21:55 +01:00
static int extended_dn_in_fix ( struct ldb_module * module , struct ldb_request * req , struct ldb_dn * dn )
{
struct extended_search_context * ac ;
struct ldb_request * down_req ;
int ret ;
struct ldb_dn * base_dn = NULL ;
enum ldb_scope base_dn_scope = LDB_SCOPE_BASE ;
const char * base_dn_filter = NULL ;
const char * const * base_dn_attrs = NULL ;
char * wellknown_object = NULL ;
static const char * no_attr [ ] = {
NULL
} ;
2014-07-07 12:00:14 +02:00
uint32_t dsdb_flags = DSDB_FLAG_AS_SYSTEM | DSDB_SEARCH_SHOW_EXTENDED_DN ;
if ( ldb_request_get_control ( req , LDB_CONTROL_SHOW_DELETED_OID ) ) {
dsdb_flags | = DSDB_SEARCH_SHOW_DELETED ;
}
if ( ldb_request_get_control ( req , LDB_CONTROL_SHOW_RECYCLED_OID ) ) {
dsdb_flags | = DSDB_SEARCH_SHOW_RECYCLED ;
}
if ( ldb_request_get_control ( req , DSDB_CONTROL_DBCHECK ) ) {
dsdb_flags | = DSDB_SEARCH_SHOW_RECYCLED ;
}
2008-12-16 09:21:55 +01:00
2011-08-02 17:19:16 +10:00
if ( req - > operation = = LDB_SEARCH ) {
2014-07-07 12:00:14 +02:00
ret = extended_dn_fix_filter ( module , req , dsdb_flags ) ;
2011-08-02 17:19:16 +10:00
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2011-08-01 17:48:53 +10:00
}
2008-12-16 09:21:55 +01:00
if ( ! ldb_dn_has_extended ( dn ) ) {
/* Move along there isn't anything to see here */
return ldb_next_request ( module , req ) ;
} else {
/* It looks like we need to map the DN */
const struct ldb_val * sid_val , * guid_val , * wkguid_val ;
2011-01-13 11:08:40 +11:00
2011-08-02 17:19:16 +10:00
if ( ! ldb_dn_match_allowed ( dn , req ) ) {
2011-01-14 16:39:28 +11:00
return ldb_error ( ldb_module_get_ctx ( module ) ,
LDB_ERR_INVALID_DN_SYNTAX , " invalid number of DN components " ) ;
2011-01-13 11:08:40 +11:00
}
2008-12-16 09:21:55 +01:00
sid_val = ldb_dn_get_extended_component ( dn , " SID " ) ;
guid_val = ldb_dn_get_extended_component ( dn , " GUID " ) ;
wkguid_val = ldb_dn_get_extended_component ( dn , " WKGUID " ) ;
2011-06-22 17:07:39 +10:00
/*
prioritise the GUID - we have had instances of
duplicate SIDs in the database in the
ForeignSecurityPrinciples due to provision errors
*/
if ( guid_val ) {
2014-07-07 12:00:14 +02:00
dsdb_flags | = DSDB_SEARCH_SEARCH_ALL_PARTITIONS ;
2011-08-19 17:34:12 +10:00
base_dn = NULL ;
2011-06-22 17:07:39 +10:00
base_dn_filter = talloc_asprintf ( req , " (objectGUID=%s) " ,
ldb_binary_encode ( req , * guid_val ) ) ;
2008-12-16 09:21:55 +01:00
if ( ! base_dn_filter ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2008-12-16 09:21:55 +01:00
}
base_dn_scope = LDB_SCOPE_SUBTREE ;
base_dn_attrs = no_attr ;
2011-06-22 17:07:39 +10:00
} else if ( sid_val ) {
2014-07-07 12:00:14 +02:00
dsdb_flags | = DSDB_SEARCH_SEARCH_ALL_PARTITIONS ;
2011-08-19 17:34:12 +10:00
base_dn = NULL ;
2011-06-22 17:07:39 +10:00
base_dn_filter = talloc_asprintf ( req , " (objectSid=%s) " ,
ldb_binary_encode ( req , * sid_val ) ) ;
2008-12-16 09:21:55 +01:00
if ( ! base_dn_filter ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2008-12-16 09:21:55 +01:00
}
base_dn_scope = LDB_SCOPE_SUBTREE ;
base_dn_attrs = no_attr ;
} else if ( wkguid_val ) {
char * wkguid_dup ;
char * tail_str ;
char * p ;
wkguid_dup = talloc_strndup ( req , ( char * ) wkguid_val - > data , wkguid_val - > length ) ;
p = strchr ( wkguid_dup , ' , ' ) ;
if ( ! p ) {
2011-01-13 11:08:40 +11:00
return ldb_error ( ldb_module_get_ctx ( module ) , LDB_ERR_INVALID_DN_SYNTAX ,
" Invalid WKGUID format " ) ;
2008-12-16 09:21:55 +01:00
}
p [ 0 ] = ' \0 ' ;
p + + ;
wellknown_object = talloc_asprintf ( req , " B:32:%s: " , wkguid_dup ) ;
if ( ! wellknown_object ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2008-12-16 09:21:55 +01:00
}
tail_str = p ;
2009-06-30 15:12:29 +10:00
base_dn = ldb_dn_new ( req , ldb_module_get_ctx ( module ) , tail_str ) ;
2008-12-16 09:21:55 +01:00
talloc_free ( wkguid_dup ) ;
if ( ! base_dn ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2008-12-16 09:21:55 +01:00
}
base_dn_filter = talloc_strdup ( req , " (objectClass=*) " ) ;
if ( ! base_dn_filter ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2008-12-16 09:21:55 +01:00
}
base_dn_scope = LDB_SCOPE_BASE ;
base_dn_attrs = wkattr ;
} else {
2011-01-13 11:08:40 +11:00
return ldb_error ( ldb_module_get_ctx ( module ) , LDB_ERR_INVALID_DN_SYNTAX ,
" Invalid extended DN component " ) ;
2008-12-16 09:21:55 +01:00
}
ac = talloc_zero ( req , struct extended_search_context ) ;
if ( ac = = NULL ) {
2010-07-06 13:21:54 +10:00
return ldb_oom ( ldb_module_get_ctx ( module ) ) ;
2008-12-16 09:21:55 +01:00
}
ac - > module = module ;
ac - > req = req ;
2011-07-11 12:01:18 +10:00
ac - > dn = dn ;
2008-12-16 09:21:55 +01:00
ac - > basedn = NULL ; /* Filled in if the search finds the DN by SID/GUID etc */
ac - > wellknown_object = wellknown_object ;
/* If the base DN was an extended DN (perhaps a well known
* GUID ) then search for that , so we can proceed with the original operation */
ret = ldb_build_search_req ( & down_req ,
2009-06-30 15:12:29 +10:00
ldb_module_get_ctx ( module ) , ac ,
2008-12-16 09:21:55 +01:00
base_dn ,
base_dn_scope ,
base_dn_filter ,
base_dn_attrs ,
2012-11-19 06:59:33 +01:00
NULL ,
2008-12-16 09:21:55 +01:00
ac , extended_base_callback ,
req ) ;
2010-09-24 12:50:13 -07:00
LDB_REQ_SET_LOCATION ( down_req ) ;
2008-12-16 09:21:55 +01:00
if ( ret ! = LDB_SUCCESS ) {
2010-07-06 13:21:54 +10:00
return ldb_operr ( ldb_module_get_ctx ( module ) ) ;
2008-12-16 09:21:55 +01:00
}
2012-11-19 06:59:33 +01:00
ret = dsdb_request_add_controls ( down_req , dsdb_flags ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
2009-09-25 20:37:45 -07:00
}
2008-12-16 09:21:55 +01:00
/* perform the search */
return ldb_next_request ( module , down_req ) ;
}
}
static int extended_dn_in_search ( struct ldb_module * module , struct ldb_request * req )
{
return extended_dn_in_fix ( module , req , req - > op . search . base ) ;
}
static int extended_dn_in_modify ( struct ldb_module * module , struct ldb_request * req )
{
return extended_dn_in_fix ( module , req , req - > op . mod . message - > dn ) ;
}
static int extended_dn_in_del ( struct ldb_module * module , struct ldb_request * req )
{
return extended_dn_in_fix ( module , req , req - > op . del . dn ) ;
}
static int extended_dn_in_rename ( struct ldb_module * module , struct ldb_request * req )
{
return extended_dn_in_fix ( module , req , req - > op . rename . olddn ) ;
}
2010-11-01 15:28:02 +11:00
static const struct ldb_module_ops ldb_extended_dn_in_module_ops = {
2008-12-16 09:21:55 +01:00
. name = " extended_dn_in " ,
. search = extended_dn_in_search ,
. modify = extended_dn_in_modify ,
. del = extended_dn_in_del ,
. rename = extended_dn_in_rename ,
} ;
2010-11-01 15:28:02 +11:00
2013-09-16 19:51:20 -07:00
static const struct ldb_module_ops ldb_extended_dn_in_openldap_module_ops = {
. name = " extended_dn_in_openldap " ,
. search = extended_dn_in_search ,
. modify = extended_dn_in_modify ,
. del = extended_dn_in_del ,
. rename = extended_dn_in_rename ,
} ;
2010-11-01 15:28:02 +11:00
int ldb_extended_dn_in_module_init ( const char * version )
{
2013-09-16 19:51:20 -07:00
int ret ;
2010-11-01 22:30:45 +11:00
LDB_MODULE_CHECK_VERSION ( version ) ;
2013-09-16 19:51:20 -07:00
ret = ldb_register_module ( & ldb_extended_dn_in_openldap_module_ops ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2010-11-01 15:28:02 +11:00
return ldb_register_module ( & ldb_extended_dn_in_module_ops ) ;
}