2008-08-20 13:22:16 +10:00
/*
Unix SMB / CIFS mplementation .
DSDB schema header
Copyright ( C ) Stefan Metzmacher < metze @ samba . org > 2006 - 2007
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2006 - 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/>.
*/
# include "includes.h"
# include "dsdb/samdb/samdb.h"
2009-04-02 16:42:21 +11:00
/* a binary array search, where the array is an array of pointers to structures,
and we want to find a match for ' target ' on ' field ' in those structures .
Inputs :
array : base pointer to an array of structures
arrray_size : number of elements in the array
field : the name of the field in the structure we are keying off
target : the field value we are looking for
comparison_fn : the comparison function
result : where the result of the search is put
if the element is found , then ' result ' is set to point to the found array element . If not ,
then ' result ' is set to NULL .
The array is assumed to be sorted by the same comparison_fn as the
search ( with , for example , qsort )
*/
# define BINARY_ARRAY_SEARCH(array, array_size, field, target, comparison_fn, result) do { \
int32_t _b , _e ; \
( result ) = NULL ; \
for ( _b = 0 , _e = ( array_size ) - 1 ; _b < = _e ; ) { \
int32_t _i = ( _b + _e ) / 2 ; \
int _r = comparison_fn ( target , array [ _i ] - > field ) ; \
if ( _r = = 0 ) { ( result ) = array [ _i ] ; break ; } \
if ( _r < 0 ) _e = _i - 1 ; else _b = _i + 1 ; \
} } while ( 0 )
static int uint32_cmp ( uint32_t c1 , uint32_t c2 )
{
return c1 - c2 ;
}
2008-08-20 13:22:16 +10:00
const struct dsdb_attribute * dsdb_attribute_by_attributeID_id ( const struct dsdb_schema * schema ,
uint32_t id )
{
2009-04-02 16:42:21 +11:00
struct dsdb_attribute * c ;
2008-08-20 13:22:16 +10:00
/*
* 0xFFFFFFFF is used as value when no mapping table is available ,
* so don ' t try to match with it
*/
if ( id = = 0xFFFFFFFF ) return NULL ;
2009-04-02 16:42:21 +11:00
BINARY_ARRAY_SEARCH ( schema - > attributes_by_attributeID_id ,
schema - > num_attributes , attributeID_id , id , uint32_cmp , c ) ;
return c ;
2008-08-20 13:22:16 +10:00
}
const struct dsdb_attribute * dsdb_attribute_by_attributeID_oid ( const struct dsdb_schema * schema ,
const char * oid )
{
2009-04-02 16:42:21 +11:00
struct dsdb_attribute * c ;
2008-08-20 13:22:16 +10:00
if ( ! oid ) return NULL ;
2009-04-02 16:42:21 +11:00
BINARY_ARRAY_SEARCH ( schema - > attributes_by_attributeID_oid ,
schema - > num_attributes , attributeID_oid , oid , strcasecmp , c ) ;
return c ;
2008-08-20 13:22:16 +10:00
}
const struct dsdb_attribute * dsdb_attribute_by_lDAPDisplayName ( const struct dsdb_schema * schema ,
const char * name )
{
2009-04-02 16:42:21 +11:00
struct dsdb_attribute * c ;
2008-08-20 13:22:16 +10:00
if ( ! name ) return NULL ;
2009-04-02 16:42:21 +11:00
BINARY_ARRAY_SEARCH ( schema - > attributes_by_lDAPDisplayName ,
schema - > num_attributes , lDAPDisplayName , name , strcasecmp , c ) ;
return c ;
2008-08-20 13:22:16 +10:00
}
const struct dsdb_attribute * dsdb_attribute_by_linkID ( const struct dsdb_schema * schema ,
int linkID )
{
2009-04-02 16:42:21 +11:00
struct dsdb_attribute * c ;
2008-08-20 13:22:16 +10:00
2009-04-02 16:42:21 +11:00
BINARY_ARRAY_SEARCH ( schema - > attributes_by_linkID ,
schema - > num_attributes , linkID , linkID , uint32_cmp , c ) ;
return c ;
2008-08-20 13:22:16 +10:00
}
const struct dsdb_class * dsdb_class_by_governsID_id ( const struct dsdb_schema * schema ,
uint32_t id )
{
2009-04-02 16:42:21 +11:00
struct dsdb_class * c ;
2008-08-20 13:22:16 +10:00
/*
* 0xFFFFFFFF is used as value when no mapping table is available ,
* so don ' t try to match with it
*/
if ( id = = 0xFFFFFFFF ) return NULL ;
2009-04-02 16:42:21 +11:00
BINARY_ARRAY_SEARCH ( schema - > classes_by_governsID_id ,
schema - > num_classes , governsID_id , id , uint32_cmp , c ) ;
return c ;
2008-08-20 13:22:16 +10:00
}
const struct dsdb_class * dsdb_class_by_governsID_oid ( const struct dsdb_schema * schema ,
const char * oid )
{
2009-04-02 16:42:21 +11:00
struct dsdb_class * c ;
2008-08-20 13:22:16 +10:00
if ( ! oid ) return NULL ;
2009-04-02 16:42:21 +11:00
BINARY_ARRAY_SEARCH ( schema - > classes_by_governsID_oid ,
schema - > num_classes , governsID_oid , oid , strcasecmp , c ) ;
return c ;
2008-08-20 13:22:16 +10:00
}
const struct dsdb_class * dsdb_class_by_lDAPDisplayName ( const struct dsdb_schema * schema ,
const char * name )
{
2009-04-02 16:42:21 +11:00
struct dsdb_class * c ;
2008-08-20 13:22:16 +10:00
if ( ! name ) return NULL ;
2009-04-02 16:42:21 +11:00
BINARY_ARRAY_SEARCH ( schema - > classes_by_lDAPDisplayName ,
schema - > num_classes , lDAPDisplayName , name , strcasecmp , c ) ;
return c ;
2008-08-20 13:22:16 +10:00
}
const struct dsdb_class * dsdb_class_by_cn ( const struct dsdb_schema * schema ,
const char * cn )
{
2009-04-02 16:42:21 +11:00
struct dsdb_class * c ;
2008-08-20 13:22:16 +10:00
if ( ! cn ) return NULL ;
2009-04-02 16:42:21 +11:00
BINARY_ARRAY_SEARCH ( schema - > classes_by_cn ,
schema - > num_classes , cn , cn , strcasecmp , c ) ;
return c ;
2008-08-20 13:22:16 +10:00
}
const char * dsdb_lDAPDisplayName_by_id ( const struct dsdb_schema * schema ,
uint32_t id )
{
const struct dsdb_attribute * a ;
const struct dsdb_class * c ;
a = dsdb_attribute_by_attributeID_id ( schema , id ) ;
if ( a ) {
return a - > lDAPDisplayName ;
}
c = dsdb_class_by_governsID_id ( schema , id ) ;
if ( c ) {
return c - > lDAPDisplayName ;
}
return NULL ;
}
/**
Return a list of linked attributes , in lDAPDisplayName format .
This may be used to determine if a modification would require
backlinks to be updated , for example
*/
WERROR dsdb_linked_attribute_lDAPDisplayName_list ( const struct dsdb_schema * schema , TALLOC_CTX * mem_ctx , const char * * * attr_list_ret )
{
const char * * attr_list = NULL ;
struct dsdb_attribute * cur ;
int i = 0 ;
for ( cur = schema - > attributes ; cur ; cur = cur - > next ) {
if ( cur - > linkID = = 0 ) continue ;
attr_list = talloc_realloc ( mem_ctx , attr_list , const char * , i + 2 ) ;
if ( ! attr_list ) {
return WERR_NOMEM ;
}
attr_list [ i ] = cur - > lDAPDisplayName ;
i + + ;
}
attr_list [ i ] = NULL ;
* attr_list_ret = attr_list ;
return WERR_OK ;
}
2008-12-23 22:57:11 +01:00
const char * * merge_attr_list ( TALLOC_CTX * mem_ctx ,
const char * * attrs , const char * const * new_attrs )
2008-08-20 13:22:16 +10:00
{
2008-12-23 22:57:11 +01:00
const char * * ret_attrs ;
2008-08-20 13:22:16 +10:00
int i ;
2008-12-23 22:57:11 +01:00
size_t new_len , orig_len = str_list_length ( attrs ) ;
2008-08-20 13:22:16 +10:00
if ( ! new_attrs ) {
return attrs ;
}
ret_attrs = talloc_realloc ( mem_ctx ,
2008-12-23 22:57:11 +01:00
attrs , const char * , orig_len + str_list_length ( new_attrs ) + 1 ) ;
2008-08-20 13:22:16 +10:00
if ( ret_attrs ) {
for ( i = 0 ; i < str_list_length ( new_attrs ) ; i + + ) {
ret_attrs [ orig_len + i ] = new_attrs [ i ] ;
}
new_len = orig_len + str_list_length ( new_attrs ) ;
ret_attrs [ new_len ] = NULL ;
}
return ret_attrs ;
}
/*
Return a merged list of the attributes of exactly one class ( not
considering subclasses , auxillary classes etc )
*/
2009-02-02 09:20:36 +01:00
const char * * dsdb_attribute_list ( TALLOC_CTX * mem_ctx , const struct dsdb_class * sclass , enum dsdb_attr_list_query query )
2008-08-20 13:22:16 +10:00
{
2008-12-23 22:57:11 +01:00
const char * * attr_list = NULL ;
2008-08-20 13:22:16 +10:00
switch ( query ) {
case DSDB_SCHEMA_ALL_MAY :
2009-02-02 09:20:36 +01:00
attr_list = merge_attr_list ( mem_ctx , attr_list , sclass - > mayContain ) ;
attr_list = merge_attr_list ( mem_ctx , attr_list , sclass - > systemMayContain ) ;
2008-08-20 13:22:16 +10:00
break ;
case DSDB_SCHEMA_ALL_MUST :
2009-02-02 09:20:36 +01:00
attr_list = merge_attr_list ( mem_ctx , attr_list , sclass - > mustContain ) ;
attr_list = merge_attr_list ( mem_ctx , attr_list , sclass - > systemMustContain ) ;
2008-08-20 13:22:16 +10:00
break ;
case DSDB_SCHEMA_SYS_MAY :
2009-02-02 09:20:36 +01:00
attr_list = merge_attr_list ( mem_ctx , attr_list , sclass - > systemMayContain ) ;
2008-08-20 13:22:16 +10:00
break ;
case DSDB_SCHEMA_SYS_MUST :
2009-02-02 09:20:36 +01:00
attr_list = merge_attr_list ( mem_ctx , attr_list , sclass - > systemMustContain ) ;
2008-08-20 13:22:16 +10:00
break ;
case DSDB_SCHEMA_MAY :
2009-02-02 09:20:36 +01:00
attr_list = merge_attr_list ( mem_ctx , attr_list , sclass - > mayContain ) ;
2008-08-20 13:22:16 +10:00
break ;
case DSDB_SCHEMA_MUST :
2009-02-02 09:20:36 +01:00
attr_list = merge_attr_list ( mem_ctx , attr_list , sclass - > mustContain ) ;
2008-08-20 13:22:16 +10:00
break ;
case DSDB_SCHEMA_ALL :
2009-02-02 09:20:36 +01:00
attr_list = merge_attr_list ( mem_ctx , attr_list , sclass - > mayContain ) ;
attr_list = merge_attr_list ( mem_ctx , attr_list , sclass - > systemMayContain ) ;
attr_list = merge_attr_list ( mem_ctx , attr_list , sclass - > mustContain ) ;
attr_list = merge_attr_list ( mem_ctx , attr_list , sclass - > systemMustContain ) ;
2008-08-20 13:22:16 +10:00
break ;
}
return attr_list ;
}
2008-12-23 22:57:11 +01:00
static const char * * dsdb_full_attribute_list_internal ( TALLOC_CTX * mem_ctx ,
2008-08-20 13:22:16 +10:00
const struct dsdb_schema * schema ,
const char * * class_list ,
enum dsdb_attr_list_query query )
{
int i ;
2009-02-02 09:20:36 +01:00
const struct dsdb_class * sclass ;
2008-08-20 13:22:16 +10:00
2008-12-23 22:57:11 +01:00
const char * * attr_list = NULL ;
const char * * this_class_list ;
const char * * recursive_list ;
2008-08-20 13:22:16 +10:00
for ( i = 0 ; class_list & & class_list [ i ] ; i + + ) {
2009-02-02 09:20:36 +01:00
sclass = dsdb_class_by_lDAPDisplayName ( schema , class_list [ i ] ) ;
2008-08-20 13:22:16 +10:00
2009-02-02 09:20:36 +01:00
this_class_list = dsdb_attribute_list ( mem_ctx , sclass , query ) ;
2008-12-23 22:57:11 +01:00
attr_list = merge_attr_list ( mem_ctx , attr_list , this_class_list ) ;
2008-08-20 13:22:16 +10:00
recursive_list = dsdb_full_attribute_list_internal ( mem_ctx , schema ,
2009-02-02 09:20:36 +01:00
sclass - > systemAuxiliaryClass ,
2008-08-20 13:22:16 +10:00
query ) ;
2008-12-23 22:57:11 +01:00
attr_list = merge_attr_list ( mem_ctx , attr_list , recursive_list ) ;
2008-08-20 13:22:16 +10:00
recursive_list = dsdb_full_attribute_list_internal ( mem_ctx , schema ,
2009-02-02 09:20:36 +01:00
sclass - > auxiliaryClass ,
2008-08-20 13:22:16 +10:00
query ) ;
2008-12-23 22:57:11 +01:00
attr_list = merge_attr_list ( mem_ctx , attr_list , recursive_list ) ;
2008-08-20 13:22:16 +10:00
}
return attr_list ;
}
2008-12-23 22:57:11 +01:00
const char * * dsdb_full_attribute_list ( TALLOC_CTX * mem_ctx ,
2008-08-20 13:22:16 +10:00
const struct dsdb_schema * schema ,
const char * * class_list ,
enum dsdb_attr_list_query query )
{
2008-12-23 22:57:11 +01:00
const char * * attr_list = dsdb_full_attribute_list_internal ( mem_ctx , schema , class_list , query ) ;
size_t new_len = str_list_length ( attr_list ) ;
2008-08-20 13:22:16 +10:00
/* Remove duplicates */
if ( new_len > 1 ) {
int i ;
qsort ( attr_list , new_len ,
sizeof ( * attr_list ) ,
( comparison_fn_t ) strcasecmp ) ;
for ( i = 1 ; i < new_len ; i + + ) {
2008-12-23 22:57:11 +01:00
const char * * val1 = & attr_list [ i - 1 ] ;
const char * * val2 = & attr_list [ i ] ;
2008-08-20 13:22:16 +10:00
if ( ldb_attr_cmp ( * val1 , * val2 ) = = 0 ) {
memmove ( val1 , val2 , ( new_len - i ) * sizeof ( * attr_list ) ) ;
new_len - - ;
i - - ;
}
}
}
return attr_list ;
}