2023-08-02 11:44:50 +03:00
/*
2009-03-05 08:52:11 +03:00
schema conversion routines
2006-08-17 12:49:57 +04:00
2008-08-15 07:18:48 +04:00
Copyright ( C ) Andrew Bartlett 2006 - 2008
2023-08-02 11:44:50 +03:00
2009-03-05 08:52:11 +03: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 .
2023-08-02 11:44:50 +03:00
2009-03-05 08:52:11 +03:00
This program is distributed in the hope that it will be useful ,
2006-08-17 12:49:57 +04:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2009-03-05 08:52:11 +03:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2023-08-02 11:44:50 +03:00
2009-03-05 08:52:11 +03:00
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2023-08-02 11:44:50 +03:00
2006-08-17 12:49:57 +04:00
*/
# include "includes.h"
2009-01-30 02:39:30 +03:00
# include "ldb.h"
2008-07-02 15:30:08 +04:00
# include "dsdb/samdb/samdb.h"
2009-03-05 08:52:11 +03:00
# include "system/locale.h"
2006-08-17 12:49:57 +04:00
2020-08-07 23:27:39 +03:00
# undef strcasecmp
2023-08-02 11:44:02 +03:00
# define SEPARATOR "\n "
2009-03-06 04:12:24 +03:00
struct attr_map {
char * old_attr ;
char * new_attr ;
} ;
struct oid_map {
char * old_oid ;
char * new_oid ;
} ;
static char * print_schema_recursive ( char * append_to_string , struct dsdb_schema * schema , const char * print_class ,
2023-08-02 11:44:50 +03:00
enum dsdb_schema_convert_target target ,
const char * * attrs_skip , const struct attr_map * attr_map , const struct oid_map * oid_map )
2009-03-06 04:12:24 +03:00
{
char * out = append_to_string ;
const struct dsdb_class * objectclass ;
objectclass = dsdb_class_by_lDAPDisplayName ( schema , print_class ) ;
if ( ! objectclass ) {
DEBUG ( 0 , ( " Cannot find class %s in schema \n " , print_class ) ) ;
return NULL ;
}
do {
TALLOC_CTX * mem_ctx = talloc_new ( append_to_string ) ;
const char * name = objectclass - > lDAPDisplayName ;
const char * oid = objectclass - > governsID_oid ;
const char * subClassOf = objectclass - > subClassOf ;
int objectClassCategory = objectclass - > objectClassCategory ;
const char * * must ;
const char * * may ;
char * schema_entry = NULL ;
2009-08-05 02:53:11 +04:00
struct ldb_val objectclass_name_as_ldb_val = data_blob_string_const ( objectclass - > lDAPDisplayName ) ;
struct ldb_message_element objectclass_name_as_el = {
. name = " objectClass " ,
. num_values = 1 ,
. values = & objectclass_name_as_ldb_val
2009-03-06 04:12:24 +03:00
} ;
2009-11-06 22:14:41 +03:00
unsigned int j ;
unsigned int attr_idx ;
2023-08-02 11:44:50 +03:00
2009-03-06 04:12:24 +03:00
if ( ! mem_ctx ) {
DEBUG ( 0 , ( " Failed to create new talloc context \n " ) ) ;
return NULL ;
}
/* We have been asked to skip some attributes/objectClasses */
if ( attrs_skip & & str_list_check_ci ( attrs_skip , name ) ) {
continue ;
}
/* We might have been asked to remap this oid, due to a conflict */
for ( j = 0 ; oid_map & & oid_map [ j ] . old_oid ; j + + ) {
if ( strcasecmp ( oid , oid_map [ j ] . old_oid ) = = 0 ) {
oid = oid_map [ j ] . new_oid ;
break ;
}
}
2023-08-02 11:44:50 +03:00
2009-03-06 04:12:24 +03:00
/* We might have been asked to remap this name, due to a conflict */
for ( j = 0 ; name & & attr_map & & attr_map [ j ] . old_attr ; j + + ) {
if ( strcasecmp ( name , attr_map [ j ] . old_attr ) = = 0 ) {
name = attr_map [ j ] . new_attr ;
break ;
}
}
2023-08-02 11:44:50 +03:00
2009-10-24 05:09:07 +04:00
/* We might have been asked to remap this subClassOf, due to a conflict */
for ( j = 0 ; subClassOf & & attr_map & & attr_map [ j ] . old_attr ; j + + ) {
if ( strcasecmp ( subClassOf , attr_map [ j ] . old_attr ) = = 0 ) {
subClassOf = attr_map [ j ] . new_attr ;
break ;
}
}
2023-08-02 11:44:50 +03:00
2009-08-05 02:53:11 +04:00
may = dsdb_full_attribute_list ( mem_ctx , schema , & objectclass_name_as_el , DSDB_SCHEMA_ALL_MAY ) ;
2009-03-06 04:12:24 +03:00
for ( j = 0 ; may & & may [ j ] ; j + + ) {
2023-08-02 11:44:50 +03:00
/* We might have been asked to remap this name, due to a conflict */
for ( attr_idx = 0 ; attr_map & & attr_map [ attr_idx ] . old_attr ; attr_idx + + ) {
if ( strcasecmp ( may [ j ] , attr_map [ attr_idx ] . old_attr ) = = 0 ) {
may [ j ] = attr_map [ attr_idx ] . new_attr ;
break ;
}
}
2009-03-06 04:12:24 +03:00
}
2009-08-05 02:53:11 +04:00
must = dsdb_full_attribute_list ( mem_ctx , schema , & objectclass_name_as_el , DSDB_SCHEMA_ALL_MUST ) ;
2009-03-06 04:12:24 +03:00
for ( j = 0 ; must & & must [ j ] ; j + + ) {
2023-08-02 11:44:50 +03:00
/* We might have been asked to remap this name, due to a conflict */
for ( attr_idx = 0 ; attr_map & & attr_map [ attr_idx ] . old_attr ; attr_idx + + ) {
if ( strcasecmp ( must [ j ] , attr_map [ attr_idx ] . old_attr ) = = 0 ) {
must [ j ] = attr_map [ attr_idx ] . new_attr ;
break ;
}
}
2009-03-06 04:12:24 +03:00
}
2023-08-02 11:44:50 +03:00
schema_entry = schema_class_description ( mem_ctx , target ,
2023-08-02 11:44:02 +03:00
SEPARATOR ,
2023-08-02 11:44:50 +03:00
oid ,
2009-03-06 04:12:24 +03:00
name ,
2023-08-02 11:44:50 +03:00
NULL ,
2009-03-06 04:12:24 +03:00
subClassOf ,
objectClassCategory ,
must ,
may ,
NULL ) ;
if ( schema_entry = = NULL ) {
2011-06-09 11:17:16 +04:00
talloc_free ( mem_ctx ) ;
2009-03-06 04:12:24 +03:00
DEBUG ( 0 , ( " failed to generate schema description for %s \n " , name ) ) ;
return NULL ;
}
switch ( target ) {
case TARGET_OPENLDAP :
out = talloc_asprintf_append ( out , " objectclass %s \n \n " , schema_entry ) ;
break ;
case TARGET_FEDORA_DS :
out = talloc_asprintf_append ( out , " objectClasses: %s \n " , schema_entry ) ;
break ;
2011-06-08 20:55:23 +04:00
default :
2011-06-09 11:17:16 +04:00
talloc_free ( mem_ctx ) ;
2023-07-31 07:18:17 +03:00
DEBUG ( 0 , ( __location__ " Wrong type of target %u! \n " , ( unsigned ) target ) ) ;
2011-06-08 20:55:23 +04:00
return NULL ;
2009-03-06 04:12:24 +03:00
}
talloc_free ( mem_ctx ) ;
} while ( 0 ) ;
2023-08-02 11:44:50 +03:00
2009-03-06 04:12:24 +03:00
for ( objectclass = schema - > classes ; objectclass ; objectclass = objectclass - > next ) {
2023-08-02 11:44:50 +03:00
if ( ldb_attr_cmp ( objectclass - > subClassOf , print_class ) = = 0
2009-03-06 04:12:24 +03:00
& & ldb_attr_cmp ( objectclass - > lDAPDisplayName , print_class ) ! = 0 ) {
2023-08-02 11:44:50 +03:00
out = print_schema_recursive ( out , schema , objectclass - > lDAPDisplayName ,
2009-03-06 04:12:24 +03:00
target , attrs_skip , attr_map , oid_map ) ;
}
}
return out ;
}
2009-03-05 08:52:11 +03:00
/* Routine to linearise our internal schema into the format that
2023-08-02 11:44:50 +03:00
OpenLDAP and Fedora DS use for their backend .
2006-08-18 07:52:50 +04:00
2009-03-05 08:52:11 +03:00
The ' mappings ' are of a format like :
2006-08-17 12:49:57 +04:00
2009-03-05 08:52:11 +03:00
# Standard OpenLDAP attributes
labeledURI
# The memberOf plugin provides this attribute
memberOf
# These conflict with OpenLDAP builtins
attributeTypes : samba4AttributeTypes
2.5 .21 .5 : 1.3 .6 .1 .4 .1 .7165 .4 .255 .7
2007-05-29 05:20:47 +04:00
2009-03-05 08:52:11 +03:00
*/
2006-08-17 12:49:57 +04:00
2008-07-02 09:15:54 +04:00
2023-08-02 11:44:50 +03:00
char * dsdb_convert_schema_to_openldap ( struct ldb_context * ldb , char * target_str , const char * mappings )
2006-08-17 12:49:57 +04:00
{
/* Read list of attributes to skip, OIDs to map */
TALLOC_CTX * mem_ctx = talloc_new ( ldb ) ;
char * line ;
2009-03-05 08:52:11 +03:00
char * out ;
2006-08-17 12:49:57 +04:00
const char * * attrs_skip = NULL ;
2009-11-06 22:14:41 +03:00
unsigned int num_skip = 0 ;
2009-03-06 04:12:24 +03:00
struct oid_map * oid_map = NULL ;
2009-11-06 22:14:41 +03:00
unsigned int num_oid_maps = 0 ;
2009-03-06 04:12:24 +03:00
struct attr_map * attr_map = NULL ;
2009-11-06 22:14:41 +03:00
unsigned int num_attr_maps = 0 ;
2008-07-10 09:52:44 +04:00
struct dsdb_attribute * attribute ;
2008-07-02 15:30:08 +04:00
struct dsdb_schema * schema ;
2009-03-05 08:52:11 +03:00
enum dsdb_schema_convert_target target ;
char * next_line = talloc_strdup ( mem_ctx , mappings ) ;
2006-08-18 07:52:50 +04:00
2009-03-05 08:52:11 +03:00
if ( ! target_str | | strcasecmp ( target_str , " openldap " ) = = 0 ) {
target = TARGET_OPENLDAP ;
} else if ( strcasecmp ( target_str , " fedora-ds " ) = = 0 ) {
target = TARGET_FEDORA_DS ;
} else {
2011-06-09 11:17:16 +04:00
talloc_free ( mem_ctx ) ;
2009-03-05 08:52:11 +03:00
DEBUG ( 0 , ( " Invalid target type for schema conversion %s \n " , target_str ) ) ;
return NULL ;
}
2006-08-17 12:49:57 +04:00
2013-05-15 20:23:49 +04:00
/* The mappings are line-separated, and specify details such as OIDs to skip etc */
2009-03-05 08:52:11 +03:00
while ( 1 ) {
line = next_line ;
next_line = strchr ( line , ' \n ' ) ;
if ( ! next_line ) {
break ;
}
next_line [ 0 ] = ' \0 ' ;
next_line + + ;
2006-08-17 12:49:57 +04:00
2006-08-18 10:14:21 +04:00
/* Blank Line */
if ( line [ 0 ] = = ' \0 ' ) {
continue ;
}
/* Comment */
if ( line [ 0 ] = = ' # ' ) {
continue ;
2006-08-17 12:49:57 +04:00
}
2009-03-05 08:52:11 +03:00
2006-08-18 10:14:21 +04:00
if ( isdigit ( line [ 0 ] ) ) {
2006-08-17 12:49:57 +04:00
char * p = strchr ( line , ' : ' ) ;
2008-08-15 07:18:48 +04:00
if ( ! p ) {
2009-03-05 08:52:11 +03:00
DEBUG ( 0 , ( " schema mapping file line has OID but no OID to map to: %s \n " , line ) ) ;
return NULL ;
2008-08-15 07:18:48 +04:00
}
2006-08-18 10:14:21 +04:00
p [ 0 ] = ' \0 ' ;
2006-08-17 12:49:57 +04:00
p + + ;
2007-04-24 09:57:56 +04:00
oid_map = talloc_realloc ( mem_ctx , oid_map , struct oid_map , num_oid_maps + 2 ) ;
2006-08-18 10:14:21 +04:00
trim_string ( line , " " , " " ) ;
2009-03-05 08:52:11 +03:00
oid_map [ num_oid_maps ] . old_oid = talloc_strdup ( oid_map , line ) ;
2006-08-18 10:14:21 +04:00
trim_string ( p , " " , " " ) ;
2007-04-24 09:57:56 +04:00
oid_map [ num_oid_maps ] . new_oid = p ;
num_oid_maps + + ;
oid_map [ num_oid_maps ] . old_oid = NULL ;
2006-08-17 12:49:57 +04:00
} else {
2007-04-24 09:57:56 +04:00
char * p = strchr ( line , ' : ' ) ;
if ( p ) {
/* remap attribute/objectClass */
p [ 0 ] = ' \0 ' ;
p + + ;
attr_map = talloc_realloc ( mem_ctx , attr_map , struct attr_map , num_attr_maps + 2 ) ;
trim_string ( line , " " , " " ) ;
2009-03-05 08:52:11 +03:00
attr_map [ num_attr_maps ] . old_attr = talloc_strdup ( attr_map , line ) ;
2007-04-24 09:57:56 +04:00
trim_string ( p , " " , " " ) ;
attr_map [ num_attr_maps ] . new_attr = p ;
num_attr_maps + + ;
attr_map [ num_attr_maps ] . old_attr = NULL ;
} else {
/* skip attribute/objectClass */
attrs_skip = talloc_realloc ( mem_ctx , attrs_skip , const char * , num_skip + 2 ) ;
trim_string ( line , " " , " " ) ;
2009-03-05 08:52:11 +03:00
attrs_skip [ num_skip ] = talloc_strdup ( attrs_skip , line ) ;
2007-04-24 09:57:56 +04:00
num_skip + + ;
attrs_skip [ num_skip ] = NULL ;
}
2006-08-17 12:49:57 +04:00
}
}
2010-03-16 06:52:39 +03:00
schema = dsdb_get_schema ( ldb , mem_ctx ) ;
2009-03-05 08:52:11 +03:00
if ( ! schema ) {
2011-06-09 11:17:16 +04:00
talloc_free ( mem_ctx ) ;
2009-03-05 08:52:11 +03:00
DEBUG ( 0 , ( " No schema on ldb to convert! \n " ) ) ;
return NULL ;
2008-07-02 15:30:08 +04:00
}
2009-03-06 04:12:24 +03:00
2006-08-22 14:49:54 +04:00
switch ( target ) {
case TARGET_OPENLDAP :
2009-03-05 08:52:11 +03:00
out = talloc_strdup ( mem_ctx , " " ) ;
2006-08-22 14:49:54 +04:00
break ;
case TARGET_FEDORA_DS :
2009-03-05 08:52:11 +03:00
out = talloc_strdup ( mem_ctx , " dn: cn=schema \n " ) ;
2006-08-22 14:49:54 +04:00
break ;
2011-06-08 20:55:23 +04:00
default :
2011-06-09 11:17:16 +04:00
talloc_free ( mem_ctx ) ;
2023-07-31 07:18:17 +03:00
DEBUG ( 0 , ( __location__ " Wrong type of target %u! \n " , ( unsigned ) target ) ) ;
2011-06-08 20:55:23 +04:00
return NULL ;
2006-08-22 14:49:54 +04:00
}
2008-07-10 09:52:44 +04:00
for ( attribute = schema - > attributes ; attribute ; attribute = attribute - > next ) {
const char * name = attribute - > lDAPDisplayName ;
const char * oid = attribute - > attributeID_oid ;
const char * syntax = attribute - > attributeSyntax_oid ;
2008-08-15 14:40:57 +04:00
const char * equality = NULL , * substring = NULL ;
2008-07-10 09:52:44 +04:00
bool single_value = attribute - > isSingleValued ;
2006-08-18 10:14:21 +04:00
2006-08-17 12:49:57 +04:00
char * schema_entry = NULL ;
2009-11-06 22:14:41 +03:00
unsigned int j ;
2006-08-17 12:49:57 +04:00
/* We have been asked to skip some attributes/objectClasses */
2006-10-16 05:36:22 +04:00
if ( attrs_skip & & str_list_check_ci ( attrs_skip , name ) ) {
2006-08-17 12:49:57 +04:00
continue ;
}
/* We might have been asked to remap this oid, due to a conflict */
2007-01-02 14:36:50 +03:00
for ( j = 0 ; oid & & oid_map & & oid_map [ j ] . old_oid ; j + + ) {
2007-04-28 20:39:24 +04:00
if ( strcasecmp ( oid , oid_map [ j ] . old_oid ) = = 0 ) {
2006-08-17 12:49:57 +04:00
oid = oid_map [ j ] . new_oid ;
break ;
}
}
2023-08-02 11:44:50 +03:00
2008-12-02 06:13:41 +03:00
if ( attribute - > syntax ) {
2008-08-15 06:08:10 +04:00
/* We might have been asked to remap this oid,
* due to a conflict , or lack of
* implementation */
2008-12-02 06:13:41 +03:00
syntax = attribute - > syntax - > ldap_oid ;
2008-08-15 14:40:57 +04:00
/* We might have been asked to remap this oid, due to a conflict */
for ( j = 0 ; syntax & & oid_map & & oid_map [ j ] . old_oid ; j + + ) {
if ( strcasecmp ( syntax , oid_map [ j ] . old_oid ) = = 0 ) {
syntax = oid_map [ j ] . new_oid ;
2008-08-15 06:08:10 +04:00
break ;
}
}
2023-08-02 11:44:50 +03:00
2008-12-02 06:13:41 +03:00
equality = attribute - > syntax - > equality ;
substring = attribute - > syntax - > substring ;
2006-08-18 07:52:50 +04:00
}
2006-08-17 12:49:57 +04:00
2007-04-24 09:57:56 +04:00
/* We might have been asked to remap this name, due to a conflict */
for ( j = 0 ; name & & attr_map & & attr_map [ j ] . old_attr ; j + + ) {
2007-04-28 20:39:24 +04:00
if ( strcasecmp ( name , attr_map [ j ] . old_attr ) = = 0 ) {
2007-04-24 09:57:56 +04:00
name = attr_map [ j ] . new_attr ;
break ;
}
}
2023-08-02 11:44:50 +03:00
schema_entry = schema_attribute_description ( mem_ctx ,
target ,
2023-08-02 11:44:02 +03:00
SEPARATOR ,
2023-08-02 11:44:50 +03:00
oid ,
name ,
equality ,
substring ,
syntax ,
single_value ,
2008-11-14 10:49:06 +03:00
false ,
NULL , NULL ,
NULL , NULL ,
false , false ) ;
2006-08-17 12:49:57 +04:00
2008-08-15 07:18:48 +04:00
if ( schema_entry = = NULL ) {
2011-06-09 11:17:16 +04:00
talloc_free ( mem_ctx ) ;
2009-03-05 08:52:11 +03:00
DEBUG ( 0 , ( " failed to generate attribute description for %s \n " , name ) ) ;
return NULL ;
2006-08-17 12:49:57 +04:00
}
2006-08-22 14:49:54 +04:00
switch ( target ) {
case TARGET_OPENLDAP :
2009-03-05 08:52:11 +03:00
out = talloc_asprintf_append ( out , " attributetype %s \n \n " , schema_entry ) ;
2006-08-22 14:49:54 +04:00
break ;
case TARGET_FEDORA_DS :
2009-03-05 08:52:11 +03:00
out = talloc_asprintf_append ( out , " attributeTypes: %s \n " , schema_entry ) ;
2006-08-22 14:49:54 +04:00
break ;
2011-06-08 20:55:23 +04:00
default :
2011-06-09 11:17:16 +04:00
talloc_free ( mem_ctx ) ;
2023-07-31 07:18:17 +03:00
DEBUG ( 0 , ( __location__ " Wrong type of target %u! \n " , ( unsigned ) target ) ) ;
2011-06-08 20:55:23 +04:00
return NULL ;
2006-08-22 14:49:54 +04:00
}
2006-08-17 12:49:57 +04:00
}
2009-03-06 04:12:24 +03:00
out = print_schema_recursive ( out , schema , " top " , target , attrs_skip , attr_map , oid_map ) ;
2006-08-18 07:52:50 +04:00
2011-06-09 11:17:16 +04:00
talloc_steal ( ldb , out ) ;
talloc_free ( mem_ctx ) ;
2009-03-05 08:52:11 +03:00
return out ;
2006-08-17 12:49:57 +04:00
}