2009-04-07 10:34:36 +04:00
/*
2010-08-03 05:14:45 +04:00
Unix SMB / CIFS implementation .
2009-04-07 10:34:36 +04:00
implement possibleInferiors calculation
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/>.
*/
/*
This module is a C implementation of the logic in the
dsdb / samdb / ldb_modules / tests / possibleInferiors . py code
To understand the C code , please see the python code first
*/
# include "includes.h"
# include "dsdb/samdb/samdb.h"
/*
create the SUPCLASSES ( ) list
*/
2009-10-18 00:25:12 +04:00
static const char * * schema_supclasses ( const struct dsdb_schema * schema ,
struct dsdb_class * schema_class )
2009-04-07 10:34:36 +04:00
{
2009-10-18 00:25:12 +04:00
const char * * list ;
2009-04-08 17:18:49 +04:00
2013-01-17 17:40:24 +04:00
if ( schema_class - > tmp . supclasses ) {
return schema_class - > tmp . supclasses ;
2009-04-08 17:18:49 +04:00
}
2009-04-07 10:34:36 +04:00
2009-10-18 00:25:12 +04:00
list = const_str_list ( str_list_make_empty ( schema_class ) ) ;
2009-04-07 10:34:36 +04:00
if ( list = = NULL ) {
DEBUG ( 0 , ( __location__ " out of memory \n " ) ) ;
return NULL ;
}
2010-08-03 05:14:45 +04:00
/* Cope with 'top SUP top', i.e. top is subClassOf top */
2009-09-10 06:06:20 +04:00
if ( schema_class - > subClassOf & &
strcmp ( schema_class - > lDAPDisplayName , schema_class - > subClassOf ) = = 0 ) {
2013-01-17 17:40:24 +04:00
schema_class - > tmp . supclasses = list ;
2009-04-07 10:34:36 +04:00
return list ;
}
2009-04-08 17:18:49 +04:00
if ( schema_class - > subClassOf ) {
2009-10-18 00:25:12 +04:00
const struct dsdb_class * schema_class2 = dsdb_class_by_lDAPDisplayName ( schema , schema_class - > subClassOf ) ;
2009-04-09 08:29:36 +04:00
const char * * list2 ;
2009-10-18 00:25:12 +04:00
list = str_list_add_const ( list , schema_class - > subClassOf ) ;
2009-04-08 17:18:49 +04:00
2009-10-18 00:25:12 +04:00
list2 = schema_supclasses ( schema , discard_const_p ( struct dsdb_class , schema_class2 ) ) ;
2009-04-09 08:29:36 +04:00
list = str_list_append_const ( list , list2 ) ;
2009-04-07 10:34:36 +04:00
}
2013-01-17 17:40:24 +04:00
schema_class - > tmp . supclasses = str_list_unique ( list ) ;
2009-11-16 21:41:46 +03:00
2013-01-17 17:40:24 +04:00
return schema_class - > tmp . supclasses ;
2009-04-07 10:34:36 +04:00
}
/*
this one is used internally
matches SUBCLASSES ( ) python function
*/
2009-10-18 00:25:12 +04:00
static const char * * schema_subclasses ( const struct dsdb_schema * schema ,
TALLOC_CTX * mem_ctx ,
const char * * oclist )
2009-04-07 10:34:36 +04:00
{
2009-10-18 00:25:12 +04:00
const char * * list = const_str_list ( str_list_make_empty ( mem_ctx ) ) ;
2009-11-06 22:14:41 +03:00
unsigned int i ;
2009-04-07 10:34:36 +04:00
for ( i = 0 ; oclist & & oclist [ i ] ; i + + ) {
2009-10-18 00:25:12 +04:00
const struct dsdb_class * schema_class = dsdb_class_by_lDAPDisplayName ( schema , oclist [ i ] ) ;
2009-09-11 19:57:34 +04:00
if ( ! schema_class ) {
DEBUG ( 0 , ( " ERROR: Unable to locate subClass: '%s' \n " , oclist [ i ] ) ) ;
continue ;
}
2013-01-17 17:40:24 +04:00
list = str_list_append_const ( list , schema_class - > tmp . subclasses ) ;
2009-04-07 10:34:36 +04:00
}
return list ;
}
/*
equivalent of the POSSSUPERIORS ( ) python function
*/
2009-10-18 00:25:12 +04:00
static const char * * schema_posssuperiors ( const struct dsdb_schema * schema ,
struct dsdb_class * schema_class )
2009-04-07 10:34:36 +04:00
{
2013-01-17 17:40:24 +04:00
if ( schema_class - > tmp . posssuperiors = = NULL ) {
2009-10-18 00:25:12 +04:00
const char * * list2 = const_str_list ( str_list_make_empty ( schema_class ) ) ;
const char * * list3 ;
2009-11-06 22:14:41 +03:00
unsigned int i ;
2009-04-07 10:34:36 +04:00
2009-04-09 08:29:36 +04:00
list2 = str_list_append_const ( list2 , schema_class - > systemPossSuperiors ) ;
list2 = str_list_append_const ( list2 , schema_class - > possSuperiors ) ;
list3 = schema_supclasses ( schema , schema_class ) ;
2009-04-09 07:46:18 +04:00
for ( i = 0 ; list3 & & list3 [ i ] ; i + + ) {
2009-10-18 00:25:12 +04:00
const struct dsdb_class * class2 = dsdb_class_by_lDAPDisplayName ( schema , list3 [ i ] ) ;
2009-09-11 19:57:34 +04:00
if ( ! class2 ) {
DEBUG ( 0 , ( " ERROR: Unable to locate supClass: '%s' \n " , list3 [ i ] ) ) ;
continue ;
}
2009-10-18 00:25:12 +04:00
list2 = str_list_append_const ( list2 , schema_posssuperiors ( schema ,
discard_const_p ( struct dsdb_class , class2 ) ) ) ;
2009-04-09 07:46:18 +04:00
}
2009-04-09 08:29:36 +04:00
list2 = str_list_append_const ( list2 , schema_subclasses ( schema , list2 , list2 ) ) ;
2009-04-08 17:18:49 +04:00
2013-01-17 17:40:24 +04:00
schema_class - > tmp . posssuperiors = str_list_unique ( list2 ) ;
2009-04-07 10:34:36 +04:00
}
2013-01-17 17:40:24 +04:00
return schema_class - > tmp . posssuperiors ;
2009-04-07 10:34:36 +04:00
}
2009-10-18 00:25:12 +04:00
static const char * * schema_subclasses_recurse ( const struct dsdb_schema * schema ,
struct dsdb_class * schema_class )
2009-04-07 10:34:36 +04:00
{
2013-01-17 17:40:24 +04:00
const char * * list = str_list_copy_const ( schema_class , schema_class - > tmp . subclasses_direct ) ;
2009-11-06 22:14:41 +03:00
unsigned int i ;
2009-04-07 10:34:36 +04:00
for ( i = 0 ; list & & list [ i ] ; i + + ) {
2009-10-18 00:25:12 +04:00
const struct dsdb_class * schema_class2 = dsdb_class_by_lDAPDisplayName ( schema , list [ i ] ) ;
2009-04-08 17:18:49 +04:00
if ( schema_class ! = schema_class2 ) {
2009-10-18 00:25:12 +04:00
list = str_list_append_const ( list , schema_subclasses_recurse ( schema ,
discard_const_p ( struct dsdb_class , schema_class2 ) ) ) ;
2009-04-08 17:18:49 +04:00
}
2009-04-07 10:34:36 +04:00
}
return list ;
}
2009-09-15 19:14:54 +04:00
/* Walk down the subClass tree, setting a higher index as we go down
* each level . top is 1 , subclasses of top are 2 , etc */
2013-01-17 17:14:37 +04:00
static void schema_subclasses_order_recurse ( const struct dsdb_schema * schema ,
struct dsdb_class * schema_class ,
const int order )
2009-09-15 19:14:54 +04:00
{
2013-01-17 17:40:24 +04:00
const char * * list = schema_class - > tmp . subclasses_direct ;
2009-11-06 22:14:41 +03:00
unsigned int i ;
2009-09-15 19:14:54 +04:00
schema_class - > subClass_order = order ;
for ( i = 0 ; list & & list [ i ] ; i + + ) {
2009-10-18 00:25:12 +04:00
const struct dsdb_class * schema_class2 = dsdb_class_by_lDAPDisplayName ( schema , list [ i ] ) ;
schema_subclasses_order_recurse ( schema , discard_const_p ( struct dsdb_class , schema_class2 ) , order + 1 ) ;
2009-09-15 19:14:54 +04:00
}
return ;
}
2009-10-18 00:25:12 +04:00
static int schema_create_subclasses ( const struct dsdb_schema * schema )
2009-04-07 10:34:36 +04:00
{
2009-10-12 06:17:09 +04:00
struct dsdb_class * schema_class , * top ;
2009-04-08 17:18:49 +04:00
for ( schema_class = schema - > classes ; schema_class ; schema_class = schema_class - > next ) {
2009-10-18 00:25:12 +04:00
struct dsdb_class * schema_class2 = discard_const_p ( struct dsdb_class ,
dsdb_class_by_lDAPDisplayName ( schema , schema_class - > subClassOf ) ) ;
2009-09-10 06:06:20 +04:00
if ( schema_class2 = = NULL ) {
2010-08-03 05:26:57 +04:00
DEBUG ( 0 , ( " ERROR: no subClassOf '%s' for '%s' \n " ,
schema_class - > subClassOf ,
schema_class - > lDAPDisplayName ) ) ;
2009-10-12 06:17:09 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
2009-09-10 06:06:20 +04:00
}
if ( schema_class2 & & schema_class ! = schema_class2 ) {
2013-01-17 17:40:24 +04:00
if ( schema_class2 - > tmp . subclasses_direct = = NULL ) {
schema_class2 - > tmp . subclasses_direct = const_str_list ( str_list_make_empty ( schema_class2 ) ) ;
if ( ! schema_class2 - > tmp . subclasses_direct ) {
2009-10-12 06:17:09 +04:00
return LDB_ERR_OPERATIONS_ERROR ;
}
2009-04-07 10:34:36 +04:00
}
2013-01-17 17:40:24 +04:00
schema_class2 - > tmp . subclasses_direct = str_list_add_const ( schema_class2 - > tmp . subclasses_direct ,
2009-10-18 00:25:12 +04:00
schema_class - > lDAPDisplayName ) ;
2009-04-07 10:34:36 +04:00
}
}
2009-04-08 17:18:49 +04:00
for ( schema_class = schema - > classes ; schema_class ; schema_class = schema_class - > next ) {
2013-01-17 17:40:24 +04:00
schema_class - > tmp . subclasses = str_list_unique ( schema_subclasses_recurse ( schema , schema_class ) ) ;
2009-09-15 19:14:54 +04:00
2010-08-03 05:14:45 +04:00
/* Initialize the subClass order, to ensure we can't have uninitialized sort on the subClass hierarchy */
2009-09-15 19:14:54 +04:00
schema_class - > subClass_order = 0 ;
}
2009-10-18 00:25:12 +04:00
top = discard_const_p ( struct dsdb_class , dsdb_class_by_lDAPDisplayName ( schema , " top " ) ) ;
2009-10-12 06:17:09 +04:00
if ( ! top ) {
DEBUG ( 0 , ( " ERROR: no 'top' class in loaded schema \n " ) ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
schema_subclasses_order_recurse ( schema , top , 1 ) ;
return LDB_SUCCESS ;
2009-04-07 10:34:36 +04:00
}
2009-10-18 00:25:12 +04:00
static void schema_fill_possible_inferiors ( const struct dsdb_schema * schema ,
struct dsdb_class * schema_class )
2009-04-07 10:34:36 +04:00
{
struct dsdb_class * c2 ;
2013-05-23 10:46:31 +04:00
const char * * poss_inf = NULL ;
const char * * sys_poss_inf = NULL ;
2009-04-08 17:18:49 +04:00
2013-01-22 10:27:10 +04:00
for ( c2 = schema - > classes ; c2 ; c2 = c2 - > next ) {
2009-10-18 00:25:12 +04:00
const char * * superiors = schema_posssuperiors ( schema , c2 ) ;
2013-01-22 10:27:10 +04:00
if ( c2 - > objectClassCategory ! = 2 & &
c2 - > objectClassCategory ! = 3 & &
str_list_check ( superiors , schema_class - > lDAPDisplayName ) )
{
if ( c2 - > systemOnly = = false ) {
if ( poss_inf = = NULL ) {
poss_inf = const_str_list ( str_list_make_empty ( schema_class ) ) ;
}
poss_inf = str_list_add_const ( poss_inf ,
c2 - > lDAPDisplayName ) ;
2009-04-08 17:18:49 +04:00
}
2013-01-22 10:27:10 +04:00
if ( sys_poss_inf = = NULL ) {
sys_poss_inf = const_str_list ( str_list_make_empty ( schema_class ) ) ;
2009-09-25 02:12:49 +04:00
}
2013-01-22 10:27:10 +04:00
sys_poss_inf = str_list_add_const ( sys_poss_inf ,
c2 - > lDAPDisplayName ) ;
2009-09-25 02:12:49 +04:00
}
}
2013-01-22 10:27:10 +04:00
schema_class - > systemPossibleInferiors = str_list_unique ( sys_poss_inf ) ;
schema_class - > possibleInferiors = str_list_unique ( poss_inf ) ;
2009-09-25 02:12:49 +04:00
}
2009-07-02 08:49:40 +04:00
/*
fill in a string class name from a governs_ID
*/
2009-10-18 00:25:12 +04:00
static void schema_fill_from_class_one ( const struct dsdb_schema * schema ,
const struct dsdb_class * c ,
const char * * s ,
const uint32_t id )
2009-07-02 08:49:40 +04:00
{
if ( * s = = NULL & & id ! = 0 ) {
2009-10-18 00:25:12 +04:00
const struct dsdb_class * c2 =
dsdb_class_by_governsID_id ( schema , id ) ;
2009-07-02 08:49:40 +04:00
if ( c2 ) {
* s = c2 - > lDAPDisplayName ;
}
}
}
/*
fill in a list of string class names from a governs_ID list
*/
2009-10-18 00:25:12 +04:00
static void schema_fill_from_class_list ( const struct dsdb_schema * schema ,
const struct dsdb_class * c ,
const char * * * s ,
const uint32_t * ids )
2009-07-02 08:49:40 +04:00
{
if ( * s = = NULL & & ids ! = NULL ) {
2009-11-06 22:14:41 +03:00
unsigned int i ;
2009-07-02 08:49:40 +04:00
for ( i = 0 ; ids [ i ] ; i + + ) ;
* s = talloc_array ( c , const char * , i + 1 ) ;
for ( i = 0 ; ids [ i ] ; i + + ) {
2009-10-18 00:25:12 +04:00
const struct dsdb_class * c2 =
dsdb_class_by_governsID_id ( schema , ids [ i ] ) ;
2009-07-02 08:49:40 +04:00
if ( c2 ) {
( * s ) [ i ] = c2 - > lDAPDisplayName ;
} else {
( * s ) [ i ] = NULL ;
}
}
( * s ) [ i ] = NULL ;
}
}
/*
fill in a list of string attribute names from a attributeID list
*/
2009-10-18 00:25:12 +04:00
static void schema_fill_from_attribute_list ( const struct dsdb_schema * schema ,
const struct dsdb_class * c ,
const char * * * s ,
const uint32_t * ids )
2009-07-02 08:49:40 +04:00
{
if ( * s = = NULL & & ids ! = NULL ) {
2009-11-06 22:14:41 +03:00
unsigned int i ;
2009-07-02 08:49:40 +04:00
for ( i = 0 ; ids [ i ] ; i + + ) ;
* s = talloc_array ( c , const char * , i + 1 ) ;
for ( i = 0 ; ids [ i ] ; i + + ) {
2009-10-18 00:25:12 +04:00
const struct dsdb_attribute * a =
dsdb_attribute_by_attributeID_id ( schema , ids [ i ] ) ;
2009-07-02 08:49:40 +04:00
if ( a ) {
( * s ) [ i ] = a - > lDAPDisplayName ;
} else {
( * s ) [ i ] = NULL ;
}
}
( * s ) [ i ] = NULL ;
}
}
/*
if the schema came from DRS then some attributes will be setup as IDs
*/
2009-10-18 00:25:12 +04:00
static void schema_fill_from_ids ( const struct dsdb_schema * schema )
2009-07-02 08:49:40 +04:00
{
struct dsdb_class * c ;
for ( c = schema - > classes ; c ; c = c - > next ) {
schema_fill_from_class_one ( schema , c , & c - > subClassOf , c - > subClassOf_id ) ;
schema_fill_from_attribute_list ( schema , c , & c - > systemMayContain , c - > systemMayContain_ids ) ;
schema_fill_from_attribute_list ( schema , c , & c - > systemMustContain , c - > systemMustContain_ids ) ;
schema_fill_from_attribute_list ( schema , c , & c - > mustContain , c - > mustContain_ids ) ;
schema_fill_from_attribute_list ( schema , c , & c - > mayContain , c - > mayContain_ids ) ;
schema_fill_from_class_list ( schema , c , & c - > possSuperiors , c - > possSuperiors_ids ) ;
schema_fill_from_class_list ( schema , c , & c - > systemPossSuperiors , c - > systemPossSuperiors_ids ) ;
schema_fill_from_class_list ( schema , c , & c - > systemAuxiliaryClass , c - > systemAuxiliaryClass_ids ) ;
schema_fill_from_class_list ( schema , c , & c - > auxiliaryClass , c - > auxiliaryClass_ids ) ;
}
}
2009-10-18 00:25:12 +04:00
int schema_fill_constructed ( const struct dsdb_schema * schema )
2009-04-08 17:18:49 +04:00
{
2009-10-12 06:17:09 +04:00
int ret ;
2009-04-08 17:18:49 +04:00
struct dsdb_class * schema_class ;
2013-01-17 17:40:24 +04:00
/* make sure we start with a clean cache */
for ( schema_class = schema - > classes ; schema_class ; schema_class = schema_class - > next ) {
ZERO_STRUCT ( schema_class - > tmp ) ;
}
2009-07-02 08:49:40 +04:00
schema_fill_from_ids ( schema ) ;
2009-10-12 06:17:09 +04:00
ret = schema_create_subclasses ( schema ) ;
if ( ret ! = LDB_SUCCESS ) {
return ret ;
}
2009-04-08 17:18:49 +04:00
for ( schema_class = schema - > classes ; schema_class ; schema_class = schema_class - > next ) {
schema_fill_possible_inferiors ( schema , schema_class ) ;
}
2009-04-09 08:29:36 +04:00
/* free up our internal cache elements */
for ( schema_class = schema - > classes ; schema_class ; schema_class = schema_class - > next ) {
2013-01-17 17:40:24 +04:00
TALLOC_FREE ( schema_class - > tmp . supclasses ) ;
TALLOC_FREE ( schema_class - > tmp . subclasses_direct ) ;
TALLOC_FREE ( schema_class - > tmp . subclasses ) ;
TALLOC_FREE ( schema_class - > tmp . posssuperiors ) ;
2009-04-09 08:29:36 +04:00
}
2009-10-18 00:25:12 +04:00
2009-10-12 06:17:09 +04:00
return LDB_SUCCESS ;
2009-04-08 17:18:49 +04:00
}