2005-06-27 00:00:50 +00:00
/*
ldb database library
r8037: a fairly major update to the internals of ldb. Changes are:
- moved the knowledge of attribute types out of ldb_tdb and into the
generic ldb code. This allows the ldb_match() message match logic
to be generic, so it can be used by other backend
- added the generic ability to load attribute handlers, for
canonicalisation, compare, ldif read and ldif write. In the future
this will be used by the schema module to allow us to correctly
obey the attributetype schema elements
- added attribute handlers for some of the core ldap attribute types,
Integer, DirectoryString, DN, ObjectClass etc
- added automatic registration of attribute handlers for well-known
attribute names 'cn', 'dc', 'dn', 'ou' and 'objectClass'
- converted the objectSid special handlers for Samba to the new system
- added more correct handling of indexing in tdb backend based on the
attribute canonicalisation function
- added generic support for subclasses, moving it out of the tdb
backend. This will be used in future by the schema module
- fixed several bugs in the dn_explode code. It still needs more
work, but doesn't corrupt ldb dbs any more.
(This used to be commit 944c5844ab441b96d8e5d7b2d151982139d1fab9)
2005-07-01 06:21:26 +00:00
Copyright ( C ) Simo Sorce 2005
2005-06-27 00:00:50 +00: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
*/
/*
* Name : ldb
*
2006-11-22 00:59:34 +00:00
* Component : ldb dn creation and manipulation utility functions
2005-06-27 00:00:50 +00:00
*
* Description : - explode a dn into it ' s own basic elements
2006-11-22 00:59:34 +00:00
* and put them in a structure ( only if necessary )
2005-06-27 00:00:50 +00:00
* - manipulate ldb_dn structures
*
* Author : Simo Sorce
*/
# include "includes.h"
2006-11-22 00:59:34 +00:00
# include <ctype.h>
2006-01-10 16:48:32 +00:00
# include "ldb/include/includes.h"
2005-06-27 00:00:50 +00:00
r8037: a fairly major update to the internals of ldb. Changes are:
- moved the knowledge of attribute types out of ldb_tdb and into the
generic ldb code. This allows the ldb_match() message match logic
to be generic, so it can be used by other backend
- added the generic ability to load attribute handlers, for
canonicalisation, compare, ldif read and ldif write. In the future
this will be used by the schema module to allow us to correctly
obey the attributetype schema elements
- added attribute handlers for some of the core ldap attribute types,
Integer, DirectoryString, DN, ObjectClass etc
- added automatic registration of attribute handlers for well-known
attribute names 'cn', 'dc', 'dn', 'ou' and 'objectClass'
- converted the objectSid special handlers for Samba to the new system
- added more correct handling of indexing in tdb backend based on the
attribute canonicalisation function
- added generic support for subclasses, moving it out of the tdb
backend. This will be used in future by the schema module
- fixed several bugs in the dn_explode code. It still needs more
work, but doesn't corrupt ldb dbs any more.
(This used to be commit 944c5844ab441b96d8e5d7b2d151982139d1fab9)
2005-07-01 06:21:26 +00:00
# define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
# define LDB_FREE(x) do { talloc_free(x); x = NULL; } while(0)
2005-08-18 15:02:01 +00:00
2006-11-01 23:31:26 +00:00
/**
internal ldb exploded dn structures
*/
struct ldb_dn_component {
2006-11-22 00:59:34 +00:00
char * name ;
2006-11-01 23:31:26 +00:00
struct ldb_val value ;
2006-11-22 00:59:34 +00:00
char * cf_name ;
struct ldb_val cf_value ;
2006-11-01 23:31:26 +00:00
} ;
struct ldb_dn {
2006-11-22 00:59:34 +00:00
struct ldb_context * ldb ;
/* Special DNs are always linearized */
bool special ;
bool invalid ;
bool valid_lin ;
bool valid_comp ;
bool valid_case ;
char * linearized ;
char * casefold ;
unsigned int comp_num ;
2006-11-01 23:31:26 +00:00
struct ldb_dn_component * components ;
2006-11-22 00:59:34 +00:00
2006-11-01 23:31:26 +00:00
} ;
2006-11-22 00:59:34 +00:00
/* strdn may be NULL */
struct ldb_dn * ldb_dn_new ( void * mem_ctx , struct ldb_context * ldb , const char * strdn )
2005-08-18 15:02:01 +00:00
{
2006-11-22 00:59:34 +00:00
struct ldb_dn * dn ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( ( ! mem_ctx ) | | ( ! ldb ) ) return NULL ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
dn = talloc_zero ( mem_ctx , struct ldb_dn ) ;
LDB_DN_NULL_FAILED ( dn ) ;
dn - > ldb = ldb ;
if ( strdn ) {
if ( strdn [ 0 ] = = ' @ ' ) {
dn - > special = true ;
}
if ( strncasecmp ( strdn , " <GUID= " , 6 ) = = 0 ) {
/* this is special DN returned when the
* exploded_dn control is used */
dn - > special = true ;
/* FIXME: add a GUID string to ldb_dn structure */
}
dn - > linearized = talloc_strdup ( dn , strdn ) ;
} else {
dn - > linearized = talloc_strdup ( dn , " " ) ;
}
LDB_DN_NULL_FAILED ( dn - > linearized ) ;
dn - > valid_lin = true ;
return dn ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
failed :
talloc_free ( dn ) ;
return NULL ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
struct ldb_dn * ldb_dn_new_fmt ( void * mem_ctx , struct ldb_context * ldb , const char * new_fmt , . . . )
2005-06-27 00:00:50 +00:00
{
2006-11-22 00:59:34 +00:00
struct ldb_dn * dn ;
char * strdn ;
va_list ap ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
if ( ( ! mem_ctx ) | | ( ! ldb ) ) return NULL ;
dn = talloc_zero ( mem_ctx , struct ldb_dn ) ;
LDB_DN_NULL_FAILED ( dn ) ;
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
dn - > ldb = ldb ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
va_start ( ap , new_fmt ) ;
strdn = talloc_vasprintf ( dn , new_fmt , ap ) ;
va_end ( ap ) ;
LDB_DN_NULL_FAILED ( strdn ) ;
if ( strdn [ 0 ] = = ' @ ' ) {
dn - > special = true ;
}
if ( strncasecmp ( strdn , " <GUID= " , 6 ) = = 0 ) {
/* this is special DN returned when the
* exploded_dn control is used */
dn - > special = true ;
/* FIXME: add a GUID string to ldb_dn structure */
}
dn - > linearized = strdn ;
dn - > valid_lin = true ;
return dn ;
failed :
talloc_free ( dn ) ;
return NULL ;
}
static int ldb_dn_escape_internal ( char * dst , const char * src , int len )
{
const char * p , * s ;
char * d ;
int l ;
p = s = src ;
d = dst ;
2005-06-27 00:00:50 +00:00
2005-07-02 17:30:03 +00:00
while ( p - src < len ) {
2005-06-27 00:00:50 +00:00
p + = strcspn ( p , " ,= \n +<>#; \\ \" " ) ;
2005-07-02 17:30:03 +00:00
if ( p - src = = len ) /* found no escapable chars */
2005-06-27 00:00:50 +00:00
break ;
2005-07-02 17:30:03 +00:00
memcpy ( d , s , p - s ) ; /* copy the part of the string before the stop */
d + = ( p - s ) ; /* move to current position */
if ( * p ) { /* it is a normal escapable character */
2005-06-27 00:00:50 +00:00
* d + + = ' \\ ' ;
* d + + = * p + + ;
2005-07-02 17:30:03 +00:00
} else { /* we have a zero byte in the string */
strncpy ( d , " \00 " , 3 ) ; /* escape the zero */
2006-11-22 00:59:34 +00:00
d + = 3 ;
2005-07-02 17:30:03 +00:00
p + + ; /* skip the zero */
2005-06-27 00:00:50 +00:00
}
2005-07-02 17:30:03 +00:00
s = p ; /* move forward */
2005-06-27 00:00:50 +00:00
}
/* copy the last part (with zero) and return */
2006-11-22 00:59:34 +00:00
l = len - ( s - src ) ;
memcpy ( d , s , l + 1 ) ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
/* return the length of the resulting string */
return ( l + ( d - dst ) ) ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
char * ldb_dn_escape_value ( void * mem_ctx , struct ldb_val value )
2005-06-27 00:00:50 +00:00
{
2006-11-22 00:59:34 +00:00
char * dst ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
if ( ! value . length )
return NULL ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
/* allocate destination string, it will be at most 3 times the source */
dst = talloc_array ( mem_ctx , char , value . length * 3 + 1 ) ;
if ( ! dst ) {
talloc_free ( dst ) ;
return NULL ;
2005-06-27 00:00:50 +00:00
}
2006-11-22 00:59:34 +00:00
ldb_dn_escape_internal ( dst , ( const char * ) value . data , value . length ) ;
2005-07-02 17:30:03 +00:00
2006-11-23 22:06:07 +00:00
dst = talloc_realloc ( mem_ctx , dst , char , strlen ( dst ) + 1 ) ;
2006-11-22 00:59:34 +00:00
return dst ;
2005-06-27 00:00:50 +00:00
}
2006-11-22 00:59:34 +00:00
/*
explode a DN string into a ldb_dn structure
based on RFC4514 except that we don ' t support multiple valued RDNs
*/
static bool ldb_dn_explode ( struct ldb_dn * dn )
2005-07-02 17:30:03 +00:00
{
2006-11-22 00:59:34 +00:00
char * p , * data , * d , * dt , * t ;
bool trim = false ;
bool in_attr = false ;
bool in_value = false ;
bool in_quote = false ;
bool is_oid = false ;
bool escape = false ;
unsigned x ;
int l ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
if ( ! dn | | dn - > invalid ) return false ;
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
if ( dn - > valid_comp ) {
return true ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
if ( ! dn - > valid_lin ) {
return false ;
}
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
/* Empty DNs */
if ( dn - > linearized [ 0 ] = = ' \0 ' ) {
dn - > valid_comp = true ;
return true ;
2005-07-02 17:30:03 +00:00
}
2006-11-22 00:59:34 +00:00
/* Special DNs case */
if ( dn - > special ) {
return true ;
}
2005-07-02 17:30:03 +00:00
2006-11-23 22:06:07 +00:00
/* make sure we free this if alloced previously before replacing */
talloc_free ( dn - > components ) ;
2006-11-22 00:59:34 +00:00
/* in the common case we have 3 or more components */
/* make sure all components are zeroed, other functions depend on this */
dn - > components = talloc_zero_array ( dn , struct ldb_dn_component , 3 ) ;
if ( ! dn - > components ) {
return false ;
}
dn - > comp_num = 0 ;
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
/* Components data space is allocated here once */
data = talloc_array ( dn - > components , char , strlen ( dn - > linearized ) + 1 ) ;
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
p = dn - > linearized ;
in_attr = true ;
trim = true ;
t = NULL ;
d = dt = data ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
while ( * p ) {
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
if ( in_attr ) {
if ( trim ) {
if ( * p = = ' ' ) {
p + + ;
continue ;
}
/* first char */
trim = false ;
if ( isdigit ( * p ) ) {
is_oid = true ;
} else
if ( ! isalpha ( * p ) ) {
/* not a digit nor an alpha, invalid attribute name */
dn - > invalid = true ;
goto failed ;
}
* d + + = * p + + ;
continue ;
}
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
if ( * p = = ' ' ) {
p + + ;
/* valid only if we are at the end */
trim = true ;
continue ;
}
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
if ( trim & & ( * p ! = ' = ' ) ) {
/* spaces/tabs are not allowed in attribute names */
dn - > invalid = true ;
goto failed ;
}
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
if ( * p = = ' = ' ) {
/* attribute terminated */
in_attr = false ;
in_value = true ;
trim = true ;
l = 0 ;
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
* d + + = ' \0 ' ;
2006-11-23 22:06:07 +00:00
dn - > components [ dn - > comp_num ] . name = talloc_strdup ( dn - > components , dt ) ;
if ( ! dn - > components [ dn - > comp_num ] . name ) {
/* ouch */
goto failed ;
}
2006-11-22 00:59:34 +00:00
dt = d ;
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
p + + ;
continue ;
}
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
if ( is_oid & & ( ! ( isdigit ( * p ) | | ( * p = = ' . ' ) ) ) ) {
/* not a digit nor a dot, invalid attribute oid */
dn - > invalid = true ;
goto failed ;
} else
if ( ! ( isalpha ( * p ) | | isdigit ( * p ) | | ( * p = = ' - ' ) ) ) {
/* not ALPHA, DIGIT or HYPHEN */
dn - > invalid = true ;
goto failed ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
* d + + = * p + + ;
continue ;
2006-01-06 21:39:37 +00:00
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
if ( in_value ) {
if ( in_quote ) {
if ( * p = = ' \" ' ) {
if ( p [ - 1 ] ! = ' \\ ' ) {
p + + ;
in_quote = false ;
continue ;
}
}
* d + + = * p + + ;
l + + ;
continue ;
}
r8037: a fairly major update to the internals of ldb. Changes are:
- moved the knowledge of attribute types out of ldb_tdb and into the
generic ldb code. This allows the ldb_match() message match logic
to be generic, so it can be used by other backend
- added the generic ability to load attribute handlers, for
canonicalisation, compare, ldif read and ldif write. In the future
this will be used by the schema module to allow us to correctly
obey the attributetype schema elements
- added attribute handlers for some of the core ldap attribute types,
Integer, DirectoryString, DN, ObjectClass etc
- added automatic registration of attribute handlers for well-known
attribute names 'cn', 'dc', 'dn', 'ou' and 'objectClass'
- converted the objectSid special handlers for Samba to the new system
- added more correct handling of indexing in tdb backend based on the
attribute canonicalisation function
- added generic support for subclasses, moving it out of the tdb
backend. This will be used in future by the schema module
- fixed several bugs in the dn_explode code. It still needs more
work, but doesn't corrupt ldb dbs any more.
(This used to be commit 944c5844ab441b96d8e5d7b2d151982139d1fab9)
2005-07-01 06:21:26 +00:00
2006-11-22 00:59:34 +00:00
if ( trim ) {
if ( * p = = ' ' ) {
p + + ;
continue ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
/* first char */
trim = false ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
if ( * p = = ' \" ' ) {
in_quote = true ;
p + + ;
continue ;
}
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
switch ( * p ) {
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
/* TODO: support ber encoded values
case ' # ' :
*/
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
case ' , ' :
if ( escape ) {
* d + + = * p + + ;
l + + ;
escape = false ;
continue ;
}
/* ok found value terminator */
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
if ( t ) {
/* trim back */
d - = ( p - t ) ;
l - = ( p - t ) ;
}
2005-10-12 08:51:12 +00:00
2006-11-22 00:59:34 +00:00
in_attr = true ;
in_value = false ;
trim = true ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
p + + ;
* d + + = ' \0 ' ;
2006-11-23 22:06:07 +00:00
dn - > components [ dn - > comp_num ] . value . data = ( uint8_t * ) talloc_strdup ( dn - > components , dt ) ;
2006-11-22 00:59:34 +00:00
dn - > components [ dn - > comp_num ] . value . length = l ;
2006-11-23 22:06:07 +00:00
if ( ! dn - > components [ dn - > comp_num ] . value . data ) {
/* ouch ! */
goto failed ;
}
2006-11-22 00:59:34 +00:00
dt = d ;
dn - > comp_num + + ;
if ( dn - > comp_num > 2 ) {
dn - > components = talloc_realloc ( dn ,
dn - > components ,
struct ldb_dn_component ,
dn - > comp_num + 1 ) ;
if ( ! dn - > components ) {
/* ouch ! */
goto failed ;
}
/* make sure all components are zeroed, other functions depend on this */
memset ( & dn - > components [ dn - > comp_num ] , ' \0 ' , sizeof ( struct ldb_dn_component ) ) ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
continue ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
case ' = ' :
case ' \n ' :
case ' + ' :
case ' < ' :
case ' > ' :
case ' # ' :
case ' ; ' :
case ' \" ' :
/* a string with not escaped specials is invalid (tested) */
if ( ! escape ) {
dn - > invalid = true ;
goto failed ;
}
escape = false ;
* d + + = * p + + ;
l + + ;
if ( t ) t = NULL ;
break ;
case ' \\ ' :
if ( ! escape ) {
escape = true ;
p + + ;
continue ;
}
escape = false ;
* d + + = * p + + ;
l + + ;
if ( t ) t = NULL ;
break ;
default :
if ( escape ) {
if ( sscanf ( p , " %02x " , & x ) ! = 1 ) {
/* invalid escaping sequence */
dn - > invalid = true ;
goto failed ;
}
escape = false ;
p + = 2 ;
* d + + = ( unsigned char ) x ;
l + + ;
if ( t ) t = NULL ;
break ;
}
if ( * p = = ' ' ) {
if ( ! t ) t = p ;
} else {
if ( t ) t = NULL ;
}
* d + + = * p + + ;
l + + ;
break ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
}
2005-07-02 18:34:13 +00:00
}
2006-11-22 00:59:34 +00:00
if ( in_attr | | in_quote ) {
/* invalid dn */
dn - > invalid = true ;
2005-07-02 17:30:03 +00:00
goto failed ;
2005-06-27 00:00:50 +00:00
}
2006-11-22 00:59:34 +00:00
/* save last element */
if ( t ) {
/* trim back */
d - = ( p - t ) ;
l - = ( p - t ) ;
2005-07-02 17:30:03 +00:00
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
* d + + = ' \0 ' ;
2006-11-23 22:06:07 +00:00
dn - > components [ dn - > comp_num ] . value . data = ( uint8_t * ) talloc_strdup ( dn - > components , dt ) ;
2006-11-22 00:59:34 +00:00
dn - > components [ dn - > comp_num ] . value . length = l ;
2006-11-23 22:06:07 +00:00
if ( ! dn - > components [ dn - > comp_num ] . value . data ) {
/* ouch */
goto failed ;
}
2006-11-22 00:59:34 +00:00
dn - > comp_num + + ;
dn - > valid_comp = true ;
2006-11-23 22:06:07 +00:00
talloc_free ( data ) ;
2006-11-22 00:59:34 +00:00
return true ;
2005-06-27 00:00:50 +00:00
2005-07-02 17:30:03 +00:00
failed :
2006-11-23 22:06:07 +00:00
dn - > comp_num = 0 ;
2006-11-22 00:59:34 +00:00
talloc_free ( dn - > components ) ;
return false ;
2005-06-27 00:00:50 +00:00
}
2006-11-22 00:59:34 +00:00
bool ldb_dn_validate ( struct ldb_dn * dn )
2005-06-27 00:00:50 +00:00
{
2006-11-22 00:59:34 +00:00
return ldb_dn_explode ( dn ) ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
const char * ldb_dn_get_linearized ( struct ldb_dn * dn )
2005-08-18 15:02:01 +00:00
{
2006-11-22 00:59:34 +00:00
int i , len ;
char * d , * n ;
if ( ! dn | | ( dn - > invalid ) ) return NULL ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( dn - > valid_lin ) return dn - > linearized ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( ! dn - > valid_comp ) {
dn - > invalid = true ;
2006-10-04 19:03:29 +00:00
return NULL ;
}
2006-11-22 00:59:34 +00:00
if ( dn - > comp_num = = 0 ) {
dn - > linearized = talloc_strdup ( dn , " " ) ;
if ( ! dn - > linearized ) return NULL ;
dn - > valid_lin = true ;
return dn - > linearized ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
/* calculate maximum possible length of DN */
for ( len = 0 , i = 0 ; i < dn - > comp_num ; i + + ) {
len + = strlen ( dn - > components [ i ] . name ) ; /* name len */
len + = ( dn - > components [ i ] . value . length * 3 ) ; /* max escaped data len */
len + = 2 ; /* '=' and ',' */
2005-07-12 12:04:54 +00:00
}
2006-11-22 00:59:34 +00:00
dn - > linearized = talloc_array ( dn , char , len ) ;
if ( ! dn - > linearized ) return NULL ;
2005-07-12 12:04:54 +00:00
2006-11-22 00:59:34 +00:00
d = dn - > linearized ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
for ( i = 0 ; i < dn - > comp_num ; i + + ) {
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
/* copy the name */
n = dn - > components [ i ] . name ;
while ( * n ) * d + + = * n + + ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
* d + + = ' = ' ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
/* and the value */
d + = ldb_dn_escape_internal ( d ,
( char * ) dn - > components [ i ] . value . data ,
dn - > components [ i ] . value . length ) ;
* d + + = ' , ' ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
* ( - - d ) = ' \0 ' ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
dn - > valid_lin = true ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
/* don't waste more memory than necessary */
dn - > linearized = talloc_realloc ( dn , dn - > linearized , char , ( d - dn - > linearized + 1 ) ) ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
return dn - > linearized ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 02:05:19 +00:00
char * ldb_dn_alloc_linearized ( void * mem_ctx , struct ldb_dn * dn )
2006-11-22 00:59:34 +00:00
{
return talloc_strdup ( mem_ctx , ldb_dn_get_linearized ( dn ) ) ;
2005-06-27 00:00:50 +00:00
}
2006-11-22 00:59:34 +00:00
/*
casefold a dn . We need to casefold the attribute names , and canonicalize
attribute values of case insensitive attributes .
*/
static bool ldb_dn_casefold_internal ( struct ldb_dn * dn )
2006-01-06 04:01:23 +00:00
{
2006-11-22 00:59:34 +00:00
int i , ret ;
2006-01-06 04:01:23 +00:00
2006-11-22 00:59:34 +00:00
if ( ! dn | | dn - > invalid ) return false ;
2006-01-06 04:01:23 +00:00
2006-11-22 00:59:34 +00:00
if ( dn - > valid_case ) return true ;
if ( ( ! dn - > valid_comp ) & & ( ! ldb_dn_explode ( dn ) ) ) {
return false ;
}
2006-01-06 04:01:23 +00:00
2006-11-22 00:59:34 +00:00
for ( i = 0 ; i < dn - > comp_num ; i + + ) {
const struct ldb_attrib_handler * h ;
2006-01-06 04:01:23 +00:00
2006-11-22 00:59:34 +00:00
dn - > components [ i ] . cf_name = ldb_attr_casefold ( dn - > components , dn - > components [ i ] . name ) ;
if ( ! dn - > components [ i ] . cf_name ) {
2006-11-23 22:06:07 +00:00
goto failed ;
2006-11-22 00:59:34 +00:00
}
2006-01-06 04:01:23 +00:00
2006-11-22 00:59:34 +00:00
h = ldb_attrib_handler ( dn - > ldb , dn - > components [ i ] . cf_name ) ;
ret = h - > canonicalise_fn ( dn - > ldb , dn - > components ,
& ( dn - > components [ i ] . value ) ,
& ( dn - > components [ i ] . cf_value ) ) ;
if ( ret ! = 0 ) {
2006-11-23 22:06:07 +00:00
goto failed ;
2006-11-22 00:59:34 +00:00
}
2006-01-06 04:01:23 +00:00
}
2006-11-23 22:06:07 +00:00
dn - > valid_case = true ;
2006-11-22 00:59:34 +00:00
return true ;
2006-11-23 22:06:07 +00:00
failed :
for ( i = 0 ; i < dn - > comp_num ; i + + ) {
LDB_FREE ( dn - > components [ i ] . cf_name ) ;
LDB_FREE ( dn - > components [ i ] . cf_value . data ) ;
}
return false ;
2006-01-06 04:01:23 +00:00
}
2006-11-22 00:59:34 +00:00
const char * ldb_dn_get_casefold ( struct ldb_dn * dn )
2005-06-27 00:00:50 +00:00
{
2006-11-22 00:59:34 +00:00
int i , len ;
char * d , * n ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_casefold_internal ( dn ) ) {
return NULL ;
2005-07-12 12:04:54 +00:00
}
2006-11-22 00:59:34 +00:00
if ( dn - > casefold ) return dn - > casefold ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
if ( dn - > comp_num = = 0 ) {
if ( dn - > special ) {
len = strlen ( dn - > linearized ) ;
dn - > casefold = talloc_array ( dn , char , len * 3 + 1 ) ;
if ( ! dn - > casefold ) return NULL ;
ldb_dn_escape_internal ( dn - > casefold , dn - > linearized , len ) ;
/* don't waste more memory than necessary */
dn - > casefold = talloc_realloc ( dn , dn - > casefold , char , strlen ( dn - > casefold ) + 1 ) ;
2005-07-04 15:06:05 +00:00
} else {
2006-11-22 00:59:34 +00:00
dn - > casefold = talloc_strdup ( dn , " " ) ;
if ( ! dn - > casefold ) return NULL ;
2005-07-04 15:06:05 +00:00
}
2006-11-22 00:59:34 +00:00
dn - > valid_case = true ;
return dn - > casefold ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
/* calculate maximum possible length of DN */
for ( len = 0 , i = 0 ; i < dn - > comp_num ; i + + ) {
len + = strlen ( dn - > components [ i ] . cf_name ) ; /* name len */
len + = ( dn - > components [ i ] . cf_value . length * 3 ) ; /* max escaped data len */
len + = 2 ; /* '=' and ',' */
2005-06-27 00:00:50 +00:00
}
2006-11-22 00:59:34 +00:00
dn - > casefold = talloc_array ( dn , char , len ) ;
if ( ! dn - > casefold ) return NULL ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
d = dn - > casefold ;
2005-07-02 17:30:03 +00:00
2006-11-22 00:59:34 +00:00
for ( i = 0 ; i < dn - > comp_num ; i + + ) {
/* copy the name */
n = dn - > components [ i ] . cf_name ;
while ( * n ) * d + + = * n + + ;
* d + + = ' = ' ;
/* and the value */
d + = ldb_dn_escape_internal ( d ,
( char * ) dn - > components [ i ] . cf_value . data ,
dn - > components [ i ] . cf_value . length ) ;
* d + + = ' , ' ;
}
* ( - - d ) = ' \0 ' ;
2006-11-23 22:06:07 +00:00
/* don't waste more memory than necessary */
dn - > casefold = talloc_realloc ( dn , dn - > casefold , char , strlen ( dn - > casefold ) + 1 ) ;
2006-11-22 00:59:34 +00:00
return dn - > casefold ;
}
2006-11-22 02:05:19 +00:00
char * ldb_dn_alloc_casefold ( void * mem_ctx , struct ldb_dn * dn )
2006-11-22 00:59:34 +00:00
{
return talloc_strdup ( mem_ctx , ldb_dn_get_casefold ( dn ) ) ;
2005-06-27 00:00:50 +00:00
}
2006-06-08 01:00:46 +00:00
/* Determine if dn is below base, in the ldap tree. Used for
* evaluating a subtree search .
* 0 if they match , otherwise non - zero
*/
2005-07-12 12:04:54 +00:00
2006-11-22 00:59:34 +00:00
int ldb_dn_compare_base ( struct ldb_dn * base , struct ldb_dn * dn )
2005-06-27 00:00:50 +00:00
{
2005-07-17 09:06:58 +00:00
int ret ;
2006-11-22 00:59:34 +00:00
int n_base , n_dn ;
if ( ! base | | base - > invalid ) return 1 ;
if ( ! dn | | dn - > invalid ) return - 1 ;
if ( ( ! base - > valid_case ) | | ( ! dn - > valid_case ) ) {
if ( base - > valid_lin & & dn - > valid_lin ) {
/* try with a normal compare first, if we are lucky
* we will avoid exploding and casfolding */
int dif ;
dif = strlen ( dn - > linearized ) - strlen ( base - > linearized ) ;
if ( dif < 0 ) return dif ;
if ( strcmp ( base - > linearized , & dn - > linearized [ dif ] ) = = 0 ) return 0 ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_casefold_internal ( base ) ) {
return 1 ;
}
2006-06-08 01:00:46 +00:00
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_casefold_internal ( dn ) ) {
return - 1 ;
}
}
/* if base has more components,
* they don ' t have the same base */
r9318: fix searches with scope ONE and SUB,
the problem was that ldb_dn_compare_base() just looked at if
both dn's mtach some how, and the following happens:
basedn: CN=bar,DC=foo,DC=com
dn: DC=foo,DC=com
and dn: DC=foo,DC=com was return as result of a sub and base search
and also the ONE search with
basedn: DC=foo,DC=com
returned this
dn: CN=bla,CN=bar,DC=foo,DC=com
metze
(This used to be commit 2a107472c373e425013050e28b944c830f653a87)
2005-08-16 06:55:40 +00:00
if ( base - > comp_num > dn - > comp_num ) {
return ( dn - > comp_num - base - > comp_num ) ;
}
2006-11-22 00:59:34 +00:00
if ( dn - > comp_num = = 0 ) {
if ( dn - > special & & base - > special ) {
return strcmp ( base - > linearized , dn - > linearized ) ;
2006-11-23 22:06:07 +00:00
} else if ( dn - > special ) {
return - 1 ;
} else if ( base - > special ) {
return 1 ;
2006-11-22 00:59:34 +00:00
} else {
return 0 ;
2005-07-02 17:30:03 +00:00
}
2006-11-22 00:59:34 +00:00
}
n_base = base - > comp_num - 1 ;
n_dn = dn - > comp_num - 1 ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
while ( n_base > = 0 ) {
/* compare attr names */
ret = strcmp ( base - > components [ n_base ] . cf_name , dn - > components [ n_dn ] . cf_name ) ;
if ( ret ! = 0 ) return ret ;
/* compare attr.cf_value. */
if ( base - > components [ n_base ] . cf_value . length ! = dn - > components [ n_dn ] . cf_value . length ) {
return base - > components [ n_base ] . cf_value . length - dn - > components [ n_dn ] . cf_value . length ;
2005-06-27 00:00:50 +00:00
}
2006-11-22 00:59:34 +00:00
ret = strcmp ( ( char * ) base - > components [ n_base ] . cf_value . data , ( char * ) dn - > components [ n_dn ] . cf_value . data ) ;
if ( ret ! = 0 ) return ret ;
n_base - - ;
n_dn - - ;
2005-06-27 00:00:50 +00:00
}
r8037: a fairly major update to the internals of ldb. Changes are:
- moved the knowledge of attribute types out of ldb_tdb and into the
generic ldb code. This allows the ldb_match() message match logic
to be generic, so it can be used by other backend
- added the generic ability to load attribute handlers, for
canonicalisation, compare, ldif read and ldif write. In the future
this will be used by the schema module to allow us to correctly
obey the attributetype schema elements
- added attribute handlers for some of the core ldap attribute types,
Integer, DirectoryString, DN, ObjectClass etc
- added automatic registration of attribute handlers for well-known
attribute names 'cn', 'dc', 'dn', 'ou' and 'objectClass'
- converted the objectSid special handlers for Samba to the new system
- added more correct handling of indexing in tdb backend based on the
attribute canonicalisation function
- added generic support for subclasses, moving it out of the tdb
backend. This will be used in future by the schema module
- fixed several bugs in the dn_explode code. It still needs more
work, but doesn't corrupt ldb dbs any more.
(This used to be commit 944c5844ab441b96d8e5d7b2d151982139d1fab9)
2005-07-01 06:21:26 +00:00
return 0 ;
2005-06-27 00:00:50 +00:00
}
2006-06-08 01:00:46 +00:00
/* compare DNs using casefolding compare functions.
If they match , then return 0
*/
2006-11-22 00:59:34 +00:00
int ldb_dn_compare ( struct ldb_dn * dn0 , struct ldb_dn * dn1 )
2005-07-12 12:04:54 +00:00
{
2006-11-22 00:59:34 +00:00
int i , ret ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( ( ! dn0 ) | | dn0 - > invalid | | ! dn1 | | dn1 - > invalid ) return - 1 ;
2005-07-12 12:04:54 +00:00
2006-11-22 00:59:34 +00:00
if ( ( ! dn0 - > valid_case ) | | ( ! dn1 - > valid_case ) ) {
if ( dn0 - > valid_lin & & dn1 - > valid_lin ) {
/* try with a normal compare first, if we are lucky
* we will avoid exploding and casfolding */
if ( strcmp ( dn0 - > linearized , dn1 - > linearized ) = = 0 ) return 0 ;
}
if ( ! ldb_dn_casefold_internal ( dn0 ) ) {
return 1 ;
}
if ( ! ldb_dn_casefold_internal ( dn1 ) ) {
return - 1 ;
}
}
if ( dn0 - > comp_num ! = dn1 - > comp_num ) {
return ( dn1 - > comp_num - dn0 - > comp_num ) ;
}
if ( dn0 - > comp_num = = 0 ) {
if ( dn0 - > special & & dn1 - > special ) {
return strcmp ( dn0 - > linearized , dn1 - > linearized ) ;
2006-11-23 22:06:07 +00:00
} else if ( dn0 - > special ) {
return 1 ;
} else if ( dn1 - > special ) {
return - 1 ;
2006-11-22 00:59:34 +00:00
} else {
return 0 ;
}
}
for ( i = 0 ; i < dn0 - > comp_num ; i + + ) {
/* compare attr names */
ret = strcmp ( dn0 - > components [ i ] . cf_name , dn1 - > components [ i ] . cf_name ) ;
if ( ret ! = 0 ) return ret ;
/* compare attr.cf_value. */
if ( dn0 - > components [ i ] . cf_value . length ! = dn1 - > components [ i ] . cf_value . length ) {
return dn0 - > components [ i ] . cf_value . length - dn1 - > components [ i ] . cf_value . length ;
}
ret = strcmp ( ( char * ) dn0 - > components [ i ] . cf_value . data , ( char * ) dn1 - > components [ i ] . cf_value . data ) ;
if ( ret ! = 0 ) return ret ;
}
return 0 ;
2005-07-12 12:04:54 +00:00
}
2006-11-22 00:59:34 +00:00
static struct ldb_dn_component ldb_dn_copy_component ( void * mem_ctx , struct ldb_dn_component * src )
2005-07-16 18:16:32 +00:00
{
2006-11-22 00:59:34 +00:00
struct ldb_dn_component dst ;
memset ( & dst , 0 , sizeof ( dst ) ) ;
2005-07-16 18:16:32 +00:00
2006-11-22 00:59:34 +00:00
if ( src = = NULL ) {
return dst ;
}
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
dst . value = ldb_val_dup ( mem_ctx , & ( src - > value ) ) ;
if ( dst . value . data = = NULL ) {
return dst ;
}
2005-07-16 18:16:32 +00:00
2006-11-22 00:59:34 +00:00
dst . name = talloc_strdup ( mem_ctx , src - > name ) ;
if ( dst . name = = NULL ) {
LDB_FREE ( dst . value . data ) ;
2006-11-23 22:06:07 +00:00
return dst ;
2005-07-16 18:16:32 +00:00
}
2006-11-22 00:59:34 +00:00
if ( src - > cf_value . data ) {
dst . cf_value = ldb_val_dup ( mem_ctx , & ( src - > cf_value ) ) ;
if ( dst . cf_value . data = = NULL ) {
LDB_FREE ( dst . value . data ) ;
LDB_FREE ( dst . name ) ;
return dst ;
}
2005-07-16 18:16:32 +00:00
2006-11-22 00:59:34 +00:00
dst . cf_name = talloc_strdup ( mem_ctx , src - > cf_name ) ;
if ( dst . cf_name = = NULL ) {
LDB_FREE ( dst . cf_name ) ;
LDB_FREE ( dst . value . data ) ;
LDB_FREE ( dst . name ) ;
return dst ;
}
} else {
dst . cf_value . data = NULL ;
dst . cf_name = NULL ;
}
2005-07-16 18:16:32 +00:00
2006-11-22 00:59:34 +00:00
return dst ;
2005-07-16 18:16:32 +00:00
}
2006-11-22 00:59:34 +00:00
struct ldb_dn * ldb_dn_copy ( void * mem_ctx , struct ldb_dn * dn )
2005-06-27 00:00:50 +00:00
{
2006-11-22 00:59:34 +00:00
struct ldb_dn * new_dn ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( ! dn | | dn - > invalid ) {
2006-07-06 07:37:41 +00:00
return NULL ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
new_dn = talloc_zero ( mem_ctx , struct ldb_dn ) ;
if ( ! new_dn ) {
2006-07-06 05:51:39 +00:00
return NULL ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
* new_dn = * dn ;
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
if ( dn - > valid_comp ) {
int i ;
new_dn - > components = talloc_zero_array ( new_dn , struct ldb_dn_component , dn - > comp_num ) ;
if ( ! new_dn - > components ) {
talloc_free ( new_dn ) ;
2006-07-06 05:51:39 +00:00
return NULL ;
}
2005-06-27 00:00:50 +00:00
2006-11-22 00:59:34 +00:00
for ( i = 0 ; i < dn - > comp_num ; i + + ) {
new_dn - > components [ i ] = ldb_dn_copy_component ( new_dn - > components , & dn - > components [ i ] ) ;
if ( ! new_dn - > components [ i ] . value . data ) {
talloc_free ( new_dn ) ;
return NULL ;
}
2005-06-27 00:00:50 +00:00
}
2006-11-23 22:06:07 +00:00
}
2005-06-27 00:00:50 +00:00
2006-11-23 22:06:07 +00:00
if ( dn - > casefold ) {
new_dn - > casefold = talloc_strdup ( new_dn , dn - > casefold ) ;
if ( ! new_dn - > casefold ) {
talloc_free ( new_dn ) ;
return NULL ;
2006-11-22 00:59:34 +00:00
}
2005-06-27 00:00:50 +00:00
}
2006-11-22 00:59:34 +00:00
if ( dn - > valid_lin ) {
new_dn - > linearized = talloc_strdup ( new_dn , dn - > linearized ) ;
if ( ! new_dn - > linearized ) {
talloc_free ( new_dn ) ;
return NULL ;
}
}
return new_dn ;
2005-06-27 00:00:50 +00:00
}
2006-11-22 00:59:34 +00:00
/* modify the given dn by adding a base.
*
* return true if successful and false if not
* if false is returned the dn may be marked invalid
*/
bool ldb_dn_add_base ( struct ldb_dn * dn , struct ldb_dn * base )
2005-07-12 12:04:54 +00:00
{
2006-11-22 00:59:34 +00:00
const char * s ;
char * t ;
2005-07-12 12:04:54 +00:00
2006-11-22 00:59:34 +00:00
if ( ! base | | base - > invalid | | ! dn | | dn - > invalid ) {
return false ;
}
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( dn - > valid_comp ) {
int i ;
2005-07-12 12:04:54 +00:00
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_validate ( base ) ) {
return false ;
}
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
s = NULL ;
if ( dn - > valid_case ) {
if ( ! ( s = ldb_dn_get_casefold ( base ) ) ) {
return false ;
}
}
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
dn - > components = talloc_realloc ( dn ,
dn - > components ,
struct ldb_dn_component ,
dn - > comp_num + base - > comp_num ) ;
if ( ! dn - > components ) {
dn - > invalid = true ;
return false ;
}
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
for ( i = 0 ; i < base - > comp_num ; dn - > comp_num + + , i + + ) {
dn - > components [ dn - > comp_num ] = ldb_dn_copy_component ( dn - > components , & base - > components [ i ] ) ;
if ( dn - > components [ dn - > comp_num ] . value . data = = NULL ) {
dn - > invalid = true ;
return false ;
}
}
2006-11-23 22:06:07 +00:00
if ( dn - > casefold & & s ) {
2006-11-22 00:59:34 +00:00
t = talloc_asprintf ( dn , " %s,%s " , dn - > casefold , s ) ;
LDB_FREE ( dn - > casefold ) ;
dn - > casefold = t ;
}
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
if ( dn - > valid_lin ) {
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
s = ldb_dn_get_linearized ( base ) ;
if ( ! s ) {
return false ;
}
t = talloc_asprintf ( dn , " %s,%s " , dn - > linearized , s ) ;
if ( ! t ) {
dn - > invalid = true ;
return false ;
}
LDB_FREE ( dn - > linearized ) ;
dn - > linearized = t ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
return true ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
/* modify the given dn by adding a base.
*
* return true if successful and false if not
* if false is returned the dn may be marked invalid
*/
bool ldb_dn_add_base_fmt ( struct ldb_dn * dn , const char * base_fmt , . . . )
2005-08-18 15:02:01 +00:00
{
2006-11-22 00:59:34 +00:00
struct ldb_dn * base ;
char * base_str ;
va_list ap ;
bool ret ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( ! dn | | dn - > invalid ) {
return false ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
va_start ( ap , base_fmt ) ;
base_str = talloc_vasprintf ( dn , base_fmt , ap ) ;
va_end ( ap ) ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( base_str = = NULL ) {
return false ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
base = ldb_dn_new ( base_str , dn - > ldb , base_str ) ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
ret = ldb_dn_add_base ( dn , base ) ;
talloc_free ( base_str ) ;
return ret ;
}
/* modify the given dn by adding children elements.
*
* return true if successful and false if not
* if false is returned the dn may be marked invalid
*/
bool ldb_dn_add_child ( struct ldb_dn * dn , struct ldb_dn * child )
2006-11-01 23:31:26 +00:00
{
2006-11-22 00:59:34 +00:00
const char * s ;
char * t ;
2006-11-01 23:31:26 +00:00
2006-11-22 00:59:34 +00:00
if ( ! child | | child - > invalid | | ! dn | | dn - > invalid ) {
return false ;
2006-11-01 23:31:26 +00:00
}
2006-11-22 00:59:34 +00:00
if ( dn - > valid_comp ) {
int n , i , j ;
2006-11-01 23:31:26 +00:00
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_validate ( child ) ) {
return false ;
}
2006-11-01 23:31:26 +00:00
2006-11-22 00:59:34 +00:00
s = NULL ;
if ( dn - > valid_case ) {
if ( ! ( s = ldb_dn_get_casefold ( child ) ) ) {
return false ;
}
}
n = dn - > comp_num + child - > comp_num ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
dn - > components = talloc_realloc ( dn ,
dn - > components ,
struct ldb_dn_component ,
n ) ;
if ( ! dn - > components ) {
dn - > invalid = true ;
return false ;
}
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
for ( i = dn - > comp_num - 1 , j = n - 1 ; i > = 0 ; i - - , j - - ) {
dn - > components [ j ] = dn - > components [ i ] ;
}
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
for ( i = 0 ; i < child - > comp_num ; i + + ) {
dn - > components [ i ] = ldb_dn_copy_component ( dn - > components , & child - > components [ i ] ) ;
if ( dn - > components [ i ] . value . data = = NULL ) {
dn - > invalid = true ;
return false ;
}
}
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
dn - > comp_num = n ;
2005-08-18 15:02:01 +00:00
2006-11-23 22:06:07 +00:00
if ( dn - > casefold & & s ) {
2006-11-22 00:59:34 +00:00
t = talloc_asprintf ( dn , " %s,%s " , s , dn - > casefold ) ;
LDB_FREE ( dn - > casefold ) ;
dn - > casefold = t ;
2005-08-18 15:02:01 +00:00
}
}
2006-11-22 00:59:34 +00:00
if ( dn - > valid_lin ) {
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
s = ldb_dn_get_linearized ( child ) ;
if ( ! s ) {
return false ;
}
t = talloc_asprintf ( dn , " %s,%s " , s , dn - > linearized ) ;
if ( ! t ) {
dn - > invalid = true ;
return false ;
}
LDB_FREE ( dn - > linearized ) ;
dn - > linearized = t ;
}
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
return true ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
/* modify the given dn by adding children elements.
*
* return true if successful and false if not
* if false is returned the dn may be marked invalid
*/
bool ldb_dn_add_child_fmt ( struct ldb_dn * dn , const char * child_fmt , . . . )
2005-08-18 15:02:01 +00:00
{
2006-11-22 00:59:34 +00:00
struct ldb_dn * child ;
char * child_str ;
va_list ap ;
bool ret ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( ! dn | | dn - > invalid ) {
return false ;
}
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
va_start ( ap , child_fmt ) ;
child_str = talloc_vasprintf ( dn , child_fmt , ap ) ;
va_end ( ap ) ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( child_str = = NULL ) {
return false ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
child = ldb_dn_new ( child_str , dn - > ldb , child_str ) ;
ret = ldb_dn_add_child ( dn , child ) ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
talloc_free ( child_str ) ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
return ret ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
bool ldb_dn_remove_base_components ( struct ldb_dn * dn , unsigned int num )
2005-08-18 15:02:01 +00:00
{
2006-11-23 22:06:07 +00:00
int i ;
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_validate ( dn ) ) {
return false ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
if ( dn - > comp_num < num ) {
return false ;
}
2005-08-18 15:02:01 +00:00
2006-11-23 22:06:07 +00:00
/* free components */
for ( i = num ; i > 0 ; i - - ) {
LDB_FREE ( dn - > components [ dn - > comp_num - i ] . name ) ;
LDB_FREE ( dn - > components [ dn - > comp_num - i ] . value . data ) ;
LDB_FREE ( dn - > components [ dn - > comp_num - i ] . cf_name ) ;
LDB_FREE ( dn - > components [ dn - > comp_num - i ] . cf_value . data ) ;
}
2006-11-22 00:59:34 +00:00
dn - > comp_num - = num ;
2005-08-18 15:02:01 +00:00
2006-11-23 22:06:07 +00:00
if ( dn - > valid_case ) {
for ( i = 0 ; i < dn - > comp_num ; i + + ) {
LDB_FREE ( dn - > components [ i ] . cf_name ) ;
LDB_FREE ( dn - > components [ i ] . cf_value . data ) ;
}
dn - > valid_case = false ;
LDB_FREE ( dn - > casefold ) ;
}
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( dn - > valid_lin ) {
dn - > valid_lin = false ;
LDB_FREE ( dn - > linearized ) ;
}
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
return true ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
bool ldb_dn_remove_child_components ( struct ldb_dn * dn , unsigned int num )
2005-08-18 15:02:01 +00:00
{
2006-11-22 00:59:34 +00:00
int i , j ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_validate ( dn ) ) {
return false ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
if ( dn - > comp_num < num ) {
return false ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
for ( i = 0 , j = num ; j < dn - > comp_num ; i + + , j + + ) {
2006-11-23 22:06:07 +00:00
if ( i < num ) {
LDB_FREE ( dn - > components [ i ] . name ) ;
LDB_FREE ( dn - > components [ i ] . value . data ) ;
LDB_FREE ( dn - > components [ i ] . cf_name ) ;
LDB_FREE ( dn - > components [ i ] . cf_value . data ) ;
}
2006-11-22 00:59:34 +00:00
dn - > components [ i ] = dn - > components [ j ] ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
dn - > comp_num - = num ;
2005-08-18 15:02:01 +00:00
2006-11-23 22:06:07 +00:00
if ( dn - > valid_case ) {
for ( i = 0 ; i < dn - > comp_num ; i + + ) {
LDB_FREE ( dn - > components [ i ] . cf_name ) ;
LDB_FREE ( dn - > components [ i ] . cf_value . data ) ;
}
dn - > valid_case = false ;
}
LDB_FREE ( dn - > casefold ) ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
if ( dn - > valid_lin ) {
dn - > valid_lin = false ;
LDB_FREE ( dn - > linearized ) ;
}
return true ;
2005-08-18 15:02:01 +00:00
}
2006-11-22 00:59:34 +00:00
struct ldb_dn * ldb_dn_get_parent ( void * mem_ctx , struct ldb_dn * dn )
2005-08-18 15:02:01 +00:00
{
2006-11-22 00:59:34 +00:00
struct ldb_dn * new_dn ;
2005-08-18 15:02:01 +00:00
2006-11-22 00:59:34 +00:00
new_dn = ldb_dn_copy ( mem_ctx , dn ) ;
if ( ! new_dn ) {
return NULL ;
}
2005-08-18 16:18:48 +00:00
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_remove_child_components ( new_dn , 1 ) ) {
talloc_free ( new_dn ) ;
return NULL ;
}
2005-08-18 16:18:48 +00:00
2006-11-22 00:59:34 +00:00
return new_dn ;
2005-08-18 15:02:01 +00:00
}
2005-10-13 07:47:57 +00:00
/* Create a 'canonical name' string from a DN:
ie dc = samba , dc = org - > samba . org /
uid = administrator , ou = users , dc = samba , dc = org = samba . org / users / administrator
There are two formats , the EX format has the last / replaced with a newline ( \ n ) .
*/
2006-11-22 00:59:34 +00:00
static char * ldb_dn_canonical ( void * mem_ctx , struct ldb_dn * dn , int ex_format ) {
2005-10-13 04:24:49 +00:00
int i ;
2006-11-23 22:06:07 +00:00
TALLOC_CTX * tmpctx ;
2005-10-13 04:24:49 +00:00
char * cracked = NULL ;
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_validate ( dn ) ) {
return NULL ;
}
2006-11-23 22:06:07 +00:00
tmpctx = talloc_new ( mem_ctx ) ;
2005-10-13 07:47:57 +00:00
/* Walk backwards down the DN, grabbing 'dc' components at first */
2005-10-13 04:24:49 +00:00
for ( i = dn - > comp_num - 1 ; i > = 0 ; i - - ) {
2005-10-14 02:05:51 +00:00
if ( ldb_attr_cmp ( dn - > components [ i ] . name , " dc " ) ! = 0 ) {
2005-10-13 04:24:49 +00:00
break ;
}
if ( cracked ) {
2006-11-23 22:06:07 +00:00
cracked = talloc_asprintf ( tmpctx , " %s.%s " ,
ldb_dn_escape_value ( tmpctx , dn - > components [ i ] . value ) ,
2005-10-13 04:24:49 +00:00
cracked ) ;
} else {
2006-11-23 22:06:07 +00:00
cracked = ldb_dn_escape_value ( tmpctx , dn - > components [ i ] . value ) ;
2005-10-13 04:24:49 +00:00
}
if ( ! cracked ) {
2006-11-23 22:06:07 +00:00
goto done ;
2005-10-13 04:24:49 +00:00
}
}
2005-10-13 07:47:57 +00:00
/* Only domain components? Finish here */
2005-10-13 04:24:49 +00:00
if ( i < 0 ) {
if ( ex_format ) {
2006-11-23 22:06:07 +00:00
cracked = talloc_asprintf ( tmpctx , " %s \n " , cracked ) ;
2005-10-13 04:24:49 +00:00
} else {
2006-11-23 22:06:07 +00:00
cracked = talloc_asprintf ( tmpctx , " %s/ " , cracked ) ;
2005-10-13 04:24:49 +00:00
}
2006-11-23 22:06:07 +00:00
talloc_steal ( mem_ctx , cracked ) ;
goto done ;
2005-10-13 04:24:49 +00:00
}
2005-10-13 07:47:57 +00:00
/* Now walk backwards appending remaining components */
2005-10-13 04:24:49 +00:00
for ( ; i > 0 ; i - - ) {
2006-11-23 22:06:07 +00:00
cracked = talloc_asprintf ( tmpctx , " %s/%s " , cracked ,
ldb_dn_escape_value ( tmpctx , dn - > components [ i ] . value ) ) ;
2005-10-13 04:24:49 +00:00
if ( ! cracked ) {
2006-11-23 22:06:07 +00:00
goto done ;
2005-10-13 04:24:49 +00:00
}
}
2005-10-13 07:47:57 +00:00
/* Last one, possibly a newline for the 'ex' format */
2005-10-13 04:24:49 +00:00
if ( ex_format ) {
2006-11-23 22:06:07 +00:00
cracked = talloc_asprintf ( tmpctx , " %s \n %s " , cracked ,
ldb_dn_escape_value ( tmpctx , dn - > components [ i ] . value ) ) ;
2005-10-13 04:24:49 +00:00
} else {
2006-11-23 22:06:07 +00:00
cracked = talloc_asprintf ( tmpctx , " %s/%s " , cracked ,
ldb_dn_escape_value ( tmpctx , dn - > components [ i ] . value ) ) ;
2005-10-13 04:24:49 +00:00
}
2006-11-23 22:06:07 +00:00
talloc_steal ( mem_ctx , cracked ) ;
done :
talloc_free ( tmpctx ) ;
2005-10-13 04:24:49 +00:00
return cracked ;
}
2005-10-13 07:47:57 +00:00
/* Wrapper functions for the above, for the two different string formats */
2006-11-22 00:59:34 +00:00
char * ldb_dn_canonical_string ( void * mem_ctx , struct ldb_dn * dn ) {
2005-10-13 04:24:49 +00:00
return ldb_dn_canonical ( mem_ctx , dn , 0 ) ;
}
2006-11-22 00:59:34 +00:00
char * ldb_dn_canonical_ex_string ( void * mem_ctx , struct ldb_dn * dn ) {
2005-10-13 04:24:49 +00:00
return ldb_dn_canonical ( mem_ctx , dn , 1 ) ;
}
2006-11-01 23:31:26 +00:00
2006-11-22 00:59:34 +00:00
int ldb_dn_get_comp_num ( struct ldb_dn * dn )
2006-11-01 23:31:26 +00:00
{
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_validate ( dn ) ) {
return - 1 ;
}
2006-11-01 23:31:26 +00:00
return dn - > comp_num ;
}
2006-11-22 00:59:34 +00:00
const char * ldb_dn_get_component_name ( struct ldb_dn * dn , unsigned int num )
2006-11-01 23:31:26 +00:00
{
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_validate ( dn ) ) {
return NULL ;
}
2006-11-01 23:31:26 +00:00
if ( num > = dn - > comp_num ) return NULL ;
return dn - > components [ num ] . name ;
}
2006-11-22 00:59:34 +00:00
const struct ldb_val * ldb_dn_get_component_val ( struct ldb_dn * dn , unsigned int num )
2006-11-01 23:31:26 +00:00
{
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_validate ( dn ) ) {
return NULL ;
}
2006-11-01 23:31:26 +00:00
if ( num > = dn - > comp_num ) return NULL ;
return & dn - > components [ num ] . value ;
}
2006-11-22 00:59:34 +00:00
const char * ldb_dn_get_rdn_name ( struct ldb_dn * dn )
{
if ( ! ldb_dn_validate ( dn ) ) {
return NULL ;
}
2006-11-01 23:31:26 +00:00
if ( dn - > comp_num = = 0 ) return NULL ;
return dn - > components [ 0 ] . name ;
}
2006-11-22 00:59:34 +00:00
const struct ldb_val * ldb_dn_get_rdn_val ( struct ldb_dn * dn )
{
if ( ! ldb_dn_validate ( dn ) ) {
return NULL ;
}
2006-11-01 23:31:26 +00:00
if ( dn - > comp_num = = 0 ) return NULL ;
return & dn - > components [ 0 ] . value ;
}
int ldb_dn_set_component ( struct ldb_dn * dn , int num , const char * name , const struct ldb_val val )
{
char * n ;
struct ldb_val v ;
2006-11-22 00:59:34 +00:00
if ( ! ldb_dn_validate ( dn ) ) {
return LDB_ERR_OTHER ;
}
2006-11-01 23:31:26 +00:00
if ( num > = dn - > comp_num ) {
return LDB_ERR_OTHER ;
}
n = talloc_strdup ( dn , name ) ;
if ( ! n ) {
return LDB_ERR_OTHER ;
}
v . length = val . length ;
v . data = ( uint8_t * ) talloc_memdup ( dn , val . data , v . length + 1 ) ;
if ( ! v . data ) {
2006-11-23 22:06:07 +00:00
talloc_free ( n ) ;
2006-11-01 23:31:26 +00:00
return LDB_ERR_OTHER ;
}
talloc_free ( dn - > components [ num ] . name ) ;
talloc_free ( dn - > components [ num ] . value . data ) ;
dn - > components [ num ] . name = n ;
dn - > components [ num ] . value = v ;
2006-11-23 22:06:07 +00:00
if ( dn - > valid_case ) {
int i ;
for ( i = 0 ; i < dn - > comp_num ; i + + ) {
LDB_FREE ( dn - > components [ i ] . cf_name ) ;
LDB_FREE ( dn - > components [ i ] . cf_value . data ) ;
}
dn - > valid_case = false ;
}
LDB_FREE ( dn - > casefold ) ;
2006-11-22 00:59:34 +00:00
2006-11-01 23:31:26 +00:00
return LDB_SUCCESS ;
}
2006-11-22 00:59:34 +00:00
bool ldb_dn_is_valid ( struct ldb_dn * dn )
{
if ( ! dn ) return false ;
return ! dn - > invalid ;
}
bool ldb_dn_is_special ( struct ldb_dn * dn )
{
if ( ! dn | | dn - > invalid ) return false ;
return dn - > special ;
}
bool ldb_dn_check_special ( struct ldb_dn * dn , const char * check )
{
if ( ! dn | | dn - > invalid ) return false ;
return ! strcmp ( dn - > linearized , check ) ;
}
bool ldb_dn_is_null ( struct ldb_dn * dn )
{
if ( ! dn | | dn - > invalid ) return false ;
if ( dn - > special ) return false ;
if ( dn - > valid_comp ) {
if ( dn - > comp_num = = 0 ) return true ;
return false ;
} else {
if ( dn - > linearized [ 0 ] = = ' \0 ' ) return true ;
}
return false ;
}