2005-10-12 10:10:23 +04:00
/*
ldb database library
Copyright ( C ) Andrew Tridgell 2005
2006-03-14 08:38:05 +03:00
Copyright ( C ) Simo Sorce 2006
2005-10-12 10:10:23 +04:00
* * NOTE ! The following LGPL license applies to the ldb
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 2 of the License , or ( at your option ) any later version .
This library 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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
License along with this library ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
/*
handle operational attributes
*/
/*
createTimestamp : HIDDEN , searchable , ldaptime , alias for whenCreated
modifyTimestamp : HIDDEN , searchable , ldaptime , alias for whenChanged
for the above two , we do the search as normal , and if
createTimestamp or modifyTimestamp is asked for , then do
additional searches for whenCreated and whenChanged and fill in
the resulting values
we also need to replace these with the whenCreated / whenChanged
equivalent in the search expression trees
whenCreated : not - HIDDEN , CONSTRUCTED , SEARCHABLE
whenChanged : not - HIDDEN , CONSTRUCTED , SEARCHABLE
on init we need to setup attribute handlers for these so
comparisons are done correctly . The resolution is 1 second .
on add we need to add both the above , for current time
on modify we need to change whenChanged
subschemaSubentry : HIDDEN , not - searchable ,
points at DN CN = Aggregate , CN = Schema , CN = Configuration , $ BASEDN
for this one we do the search as normal , then add the static
value if requested . How do we work out the $ BASEDN from inside a
module ?
structuralObjectClass : HIDDEN , CONSTRUCTED , not - searchable . always same as objectclass ?
for this one we do the search as normal , then if requested ask
for objectclass , change the attribute name , and add it
2005-10-12 12:51:12 +04:00
allowedAttributesEffective : HIDDEN , CONSTRUCTED , not - searchable ,
list of attributes that can be modified - requires schema lookup
2005-10-12 10:10:23 +04:00
attributeTypes : in schema only
objectClasses : in schema only
matchingRules : in schema only
matchingRuleUse : in schema only
creatorsName : not supported by w2k3 ?
modifiersName : not supported by w2k3 ?
*/
# include "includes.h"
2006-01-10 19:48:32 +03:00
# include "ldb/include/includes.h"
2005-10-12 10:10:23 +04:00
2005-10-13 09:04:16 +04:00
/*
construct a canonical name from a message
*/
static int construct_canonical_name ( struct ldb_module * module , struct ldb_message * msg )
{
char * canonicalName ;
canonicalName = ldb_dn_canonical_string ( msg , msg - > dn ) ;
if ( canonicalName = = NULL ) {
return - 1 ;
}
2006-02-22 12:28:58 +03:00
return ldb_msg_add_steal_string ( msg , " canonicalName " , canonicalName ) ;
2005-10-13 09:04:16 +04:00
}
2005-10-12 10:10:23 +04:00
/*
a list of attribute names that should be substituted in the parse
tree before the search is done
*/
static const struct {
const char * attr ;
const char * replace ;
} parse_tree_sub [ ] = {
{ " createTimestamp " , " whenCreated " } ,
{ " modifyTimestamp " , " whenChanged " }
} ;
2005-10-13 09:04:16 +04:00
2005-10-12 10:10:23 +04:00
/*
a list of attribute names that are hidden , but can be searched for
using another ( non - hidden ) name to produce the correct result
*/
static const struct {
const char * attr ;
const char * replace ;
2005-10-13 09:04:16 +04:00
int ( * constructor ) ( struct ldb_module * , struct ldb_message * ) ;
2005-10-12 10:10:23 +04:00
} search_sub [ ] = {
2005-10-13 09:04:16 +04:00
{ " createTimestamp " , " whenCreated " , NULL } ,
{ " modifyTimestamp " , " whenChanged " , NULL } ,
{ " structuralObjectClass " , " objectClass " , NULL } ,
{ " canonicalName " , " distinguishedName " , construct_canonical_name }
2005-10-12 10:10:23 +04:00
} ;
2005-10-13 09:04:16 +04:00
/*
post process a search result record . For any search_sub [ ] attributes that were
asked for , we need to call the appropriate copy routine to copy the result
into the message , then remove any attributes that we added to the search but were
not asked for by the user
*/
static int operational_search_post_process ( struct ldb_module * module ,
struct ldb_message * msg ,
const char * const * attrs )
{
int i , a = 0 ;
for ( a = 0 ; attrs & & attrs [ a ] ; a + + ) {
for ( i = 0 ; i < ARRAY_SIZE ( search_sub ) ; i + + ) {
if ( ldb_attr_cmp ( attrs [ a ] , search_sub [ i ] . attr ) ! = 0 ) {
continue ;
}
/* construct the new attribute, using either a supplied
constructor or a simple copy */
if ( search_sub [ i ] . constructor ) {
if ( search_sub [ i ] . constructor ( module , msg ) ! = 0 ) {
goto failed ;
}
} else if ( ldb_msg_copy_attr ( msg ,
search_sub [ i ] . replace ,
search_sub [ i ] . attr ) ! = 0 ) {
goto failed ;
}
/* remove the added search attribute, unless it was asked for
by the user */
if ( search_sub [ i ] . replace = = NULL | |
ldb_attr_in_list ( attrs , search_sub [ i ] . replace ) | |
ldb_attr_in_list ( attrs , " * " ) ) {
continue ;
}
ldb_msg_remove_attr ( msg , search_sub [ i ] . replace ) ;
}
}
return 0 ;
failed :
ldb_debug_set ( module - > ldb , LDB_DEBUG_WARNING ,
" operational_search_post_process failed for attribute '%s' \n " ,
attrs [ a ] ) ;
return - 1 ;
}
2005-10-12 11:57:39 +04:00
2006-03-14 08:38:05 +03:00
/*
hook search operations
*/
2006-07-22 21:21:59 +04:00
struct operational_context {
2006-03-14 08:38:05 +03:00
struct ldb_module * module ;
void * up_context ;
2006-07-22 20:56:33 +04:00
int ( * up_callback ) ( struct ldb_context * , void * , struct ldb_reply * ) ;
2006-03-14 08:38:05 +03:00
const char * const * attrs ;
} ;
2006-07-22 21:21:59 +04:00
static int operational_callback ( struct ldb_context * ldb , void * context , struct ldb_reply * ares )
2006-03-14 20:39:58 +03:00
{
2006-07-22 21:21:59 +04:00
struct operational_context * ac ;
2006-03-14 08:38:05 +03:00
if ( ! context | | ! ares ) {
2006-08-13 11:33:57 +04:00
ldb_set_errstring ( ldb , " NULL Context or Result in callback " ) ;
2006-03-14 08:38:05 +03:00
goto error ;
}
2006-07-22 21:21:59 +04:00
ac = talloc_get_type ( context , struct operational_context ) ;
2006-03-14 08:38:05 +03:00
if ( ares - > type = = LDB_REPLY_ENTRY ) {
/* for each record returned post-process to add any derived
attributes that have been asked for */
if ( operational_search_post_process ( ac - > module , ares - > message , ac - > attrs ) ! = 0 ) {
goto error ;
}
}
return ac - > up_callback ( ldb , ac - > up_context , ares ) ;
error :
talloc_free ( ares ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
2006-05-29 05:30:02 +04:00
static int operational_search ( struct ldb_module * module , struct ldb_request * req )
2006-03-14 08:38:05 +03:00
{
2006-07-22 21:21:59 +04:00
struct operational_context * ac ;
2006-03-14 08:38:05 +03:00
struct ldb_request * down_req ;
const char * * search_attrs = NULL ;
int i , a , ret ;
2006-07-22 21:21:59 +04:00
req - > handle = NULL ;
2006-03-14 08:38:05 +03:00
2006-07-22 21:21:59 +04:00
ac = talloc ( req , struct operational_context ) ;
2006-03-14 08:38:05 +03:00
if ( ac = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
ac - > module = module ;
2006-07-22 21:21:59 +04:00
ac - > up_context = req - > context ;
ac - > up_callback = req - > callback ;
2006-03-14 08:38:05 +03:00
ac - > attrs = req - > op . search . attrs ;
down_req = talloc_zero ( req , struct ldb_request ) ;
if ( down_req = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
down_req - > operation = req - > operation ;
down_req - > op . search . base = req - > op . search . base ;
down_req - > op . search . scope = req - > op . search . scope ;
down_req - > op . search . tree = req - > op . search . tree ;
/* FIXME: I hink we should copy the tree and keep the original
* unmodified . SSS */
/* replace any attributes in the parse tree that are
searchable , but are stored using a different name in the
backend */
for ( i = 0 ; i < ARRAY_SIZE ( parse_tree_sub ) ; i + + ) {
ldb_parse_tree_attr_replace ( req - > op . search . tree ,
parse_tree_sub [ i ] . attr ,
parse_tree_sub [ i ] . replace ) ;
}
/* in the list of attributes we are looking for, rename any
attributes to the alias for any hidden attributes that can
be fetched directly using non - hidden names */
for ( a = 0 ; ac - > attrs & & ac - > attrs [ a ] ; a + + ) {
for ( i = 0 ; i < ARRAY_SIZE ( search_sub ) ; i + + ) {
if ( ldb_attr_cmp ( ac - > attrs [ a ] , search_sub [ i ] . attr ) = = 0 & &
search_sub [ i ] . replace ) {
if ( ! search_attrs ) {
search_attrs = ldb_attr_list_copy ( req , ac - > attrs ) ;
if ( search_attrs = = NULL ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
}
search_attrs [ a ] = search_sub [ i ] . replace ;
}
}
}
/* use new set of attrs if any */
if ( search_attrs ) down_req - > op . search . attrs = search_attrs ;
else down_req - > op . search . attrs = req - > op . search . attrs ;
down_req - > controls = req - > controls ;
2006-07-22 21:21:59 +04:00
down_req - > context = ac ;
down_req - > callback = operational_callback ;
2006-06-04 09:28:13 +04:00
ldb_set_timeout_from_prev_req ( module - > ldb , req , down_req ) ;
2006-03-14 08:38:05 +03:00
/* perform the search */
ret = ldb_next_request ( module , down_req ) ;
/* do not free down_req as the call results may be linked to it,
* it will be freed when the upper level request get freed */
if ( ret = = LDB_SUCCESS ) {
2006-07-22 21:21:59 +04:00
req - > handle = down_req - > handle ;
2006-03-14 08:38:05 +03:00
}
return ret ;
}
2006-03-02 19:32:53 +03:00
static int operational_init ( struct ldb_module * ctx )
{
2006-12-15 16:08:57 +03:00
int ret = 0 ;
2006-03-02 19:32:53 +03:00
/* setup some standard attribute handlers */
2006-12-15 16:08:57 +03:00
ret | = ldb_schema_attribute_add ( ctx - > ldb , " whenCreated " , 0 , LDB_SYNTAX_UTC_TIME ) ;
ret | = ldb_schema_attribute_add ( ctx - > ldb , " whenChanged " , 0 , LDB_SYNTAX_UTC_TIME ) ;
ret | = ldb_schema_attribute_add ( ctx - > ldb , " subschemaSubentry " , 0 , LDB_SYNTAX_DN ) ;
ret | = ldb_schema_attribute_add ( ctx - > ldb , " structuralObjectClass " , 0 , LDB_SYNTAX_OBJECTCLASS ) ;
if ( ret ! = 0 ) {
return ret ;
}
2006-03-02 19:32:53 +03:00
return ldb_next_init ( ctx ) ;
}
2005-10-12 10:10:23 +04:00
static const struct ldb_module_ops operational_ops = {
. name = " operational " ,
2006-05-29 05:30:02 +04:00
. search = operational_search ,
2006-03-02 19:32:53 +03:00
. init_context = operational_init
2005-10-12 10:10:23 +04:00
} ;
2006-03-02 19:32:53 +03:00
int ldb_operational_init ( void )
2005-10-12 10:10:23 +04:00
{
2006-03-02 19:32:53 +03:00
return ldb_register_module ( & operational_ops ) ;
2005-10-12 10:10:23 +04:00
}