2016-01-25 14:38:36 +03:00
/*
2004-03-31 10:45:39 +04:00
ldb database library
Copyright ( C ) Andrew Tridgell 2004
* * NOTE ! The following LGPL license applies to the ldb
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
2016-01-25 14:38:36 +03:00
2004-03-31 10:45:39 +04:00
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
2007-07-10 06:46:15 +04:00
version 3 of the License , or ( at your option ) any later version .
2004-03-31 10:45:39 +04:00
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
2007-07-10 07:42:26 +04:00
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2004-03-31 10:45:39 +04:00
*/
/*
* Name : ldb
*
* Component : ldif routines
*
* Description : ldif pack / unpack routines
*
* Author : Andrew Tridgell
*/
2004-04-03 16:29:21 +04:00
/*
see RFC2849 for the LDIF format definition
*/
2009-01-30 02:39:30 +03:00
# include "ldb_private.h"
2006-09-06 08:58:06 +04:00
# include "system/locale.h"
2005-06-21 11:52:00 +04:00
2005-06-21 15:14:54 +04:00
/*
2016-01-25 14:38:36 +03:00
2005-06-21 15:14:54 +04:00
*/
2010-07-13 03:37:58 +04:00
static int ldb_read_data_file ( TALLOC_CTX * mem_ctx , struct ldb_val * value )
2005-06-21 15:14:54 +04:00
{
struct stat statbuf ;
char * buf ;
lib:ldb: Use correct integer types for sizes
Error: INTEGER_OVERFLOW (CWE-190):
ldb-2.9.0/common/ldb_ldif.c:84: tainted_data_return: Called function "read(f, buf, size)", and a possible return value may be less than zero.
ldb-2.9.0/common/ldb_ldif.c:84: cast_overflow: An assign that casts to a different type, which might trigger an overflow.
ldb-2.9.0/common/ldb_ldif.c:92: overflow: The expression "size" is considered to have possibly overflowed.
ldb-2.9.0/common/ldb_ldif.c:84: overflow_sink: "size", which might be negative, is passed to "read(f, buf, size)". [Note: The source code implementation of the function has been overridden by a builtin model.]
82| buf = (char *)value->data;
83| while (count < statbuf.st_size) {
84|-> bytes = read(f, buf, size);
85| if (bytes == -1) {
86| talloc_free(value->data);
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
Autobuild-User(master): Volker Lendecke <vl@samba.org>
Autobuild-Date(master): Tue Apr 30 15:33:32 UTC 2024 on atb-devel-224
2024-04-30 15:33:51 +03:00
size_t count , size ;
ssize_t bytes ;
2005-06-21 15:14:54 +04:00
int ret ;
int f ;
2006-09-14 22:50:12 +04:00
const char * fname = ( const char * ) value - > data ;
2005-06-21 15:14:54 +04:00
2006-09-14 22:50:12 +04:00
if ( strncmp ( fname , " file:// " , 7 ) ! = 0 ) {
return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX ;
}
fname + = 7 ;
f = open ( fname , O_RDONLY ) ;
2005-06-21 15:14:54 +04:00
if ( f = = - 1 ) {
return - 1 ;
}
if ( fstat ( f , & statbuf ) ! = 0 ) {
ret = - 1 ;
goto done ;
}
if ( statbuf . st_size = = 0 ) {
ret = - 1 ;
goto done ;
}
2006-10-09 12:00:18 +04:00
value - > data = ( uint8_t * ) talloc_size ( mem_ctx , statbuf . st_size + 1 ) ;
2005-06-21 15:14:54 +04:00
if ( value - > data = = NULL ) {
ret = - 1 ;
goto done ;
}
value - > data [ statbuf . st_size ] = 0 ;
count = 0 ;
size = statbuf . st_size ;
2005-10-12 10:10:23 +04:00
buf = ( char * ) value - > data ;
2005-06-21 15:14:54 +04:00
while ( count < statbuf . st_size ) {
bytes = read ( f , buf , size ) ;
if ( bytes = = - 1 ) {
talloc_free ( value - > data ) ;
ret = - 1 ;
goto done ;
}
count + = bytes ;
buf + = bytes ;
size - = bytes ;
}
value - > length = statbuf . st_size ;
ret = statbuf . st_size ;
done :
close ( f ) ;
return ret ;
}
2004-03-31 10:45:39 +04:00
/*
this base64 decoder was taken from jitterbug ( written by tridge ) .
we might need to replace it with a new version
*/
2005-06-19 05:31:27 +04:00
int ldb_base64_decode ( char * s )
2004-03-31 10:45:39 +04:00
{
const char * b64 = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ " ;
2005-06-21 10:35:55 +04:00
int bit_offset = 0 , byte_offset , idx , i , n ;
2004-05-29 12:11:46 +04:00
uint8_t * d = ( uint8_t * ) s ;
2005-06-21 10:35:55 +04:00
char * p = NULL ;
2004-03-31 10:45:39 +04:00
n = i = 0 ;
while ( * s & & ( p = strchr ( b64 , * s ) ) ) {
idx = ( int ) ( p - b64 ) ;
byte_offset = ( i * 6 ) / 8 ;
bit_offset = ( i * 6 ) % 8 ;
d [ byte_offset ] & = ~ ( ( 1 < < ( 8 - bit_offset ) ) - 1 ) ;
if ( bit_offset < 3 ) {
d [ byte_offset ] | = ( idx < < ( 2 - bit_offset ) ) ;
n = byte_offset + 1 ;
} else {
d [ byte_offset ] | = ( idx > > ( bit_offset - 2 ) ) ;
d [ byte_offset + 1 ] = 0 ;
d [ byte_offset + 1 ] | = ( idx < < ( 8 - ( bit_offset - 2 ) ) ) & 0xFF ;
n = byte_offset + 2 ;
}
s + + ; i + + ;
}
2005-06-19 05:17:29 +04:00
if ( bit_offset > = 3 ) {
n - - ;
}
2004-03-31 10:45:39 +04:00
if ( * s & & ! p ) {
/* the only termination allowed */
if ( * s ! = ' = ' ) {
return - 1 ;
}
}
/* null terminate */
d [ n ] = 0 ;
return n ;
}
/*
encode as base64
caller frees
*/
2010-07-13 03:37:58 +04:00
char * ldb_base64_encode ( TALLOC_CTX * mem_ctx , const char * buf , int len )
2004-03-31 10:45:39 +04:00
{
const char * b64 = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ " ;
int bit_offset , byte_offset , idx , i ;
2004-05-29 12:11:46 +04:00
const uint8_t * d = ( const uint8_t * ) buf ;
2005-08-27 05:42:20 +04:00
int bytes = ( len * 8 + 5 ) / 6 , pad_bytes = ( bytes % 4 ) ? 4 - ( bytes % 4 ) : 0 ;
2004-03-31 10:45:39 +04:00
char * out ;
2005-08-27 05:42:20 +04:00
out = talloc_array ( mem_ctx , char , bytes + pad_bytes + 1 ) ;
2004-03-31 10:45:39 +04:00
if ( ! out ) return NULL ;
for ( i = 0 ; i < bytes ; i + + ) {
byte_offset = ( i * 6 ) / 8 ;
bit_offset = ( i * 6 ) % 8 ;
if ( bit_offset < 3 ) {
idx = ( d [ byte_offset ] > > ( 2 - bit_offset ) ) & 0x3F ;
} else {
idx = ( d [ byte_offset ] < < ( bit_offset - 2 ) ) & 0x3F ;
if ( byte_offset + 1 < len ) {
idx | = ( d [ byte_offset + 1 ] > > ( 8 - ( bit_offset - 2 ) ) ) ;
}
}
out [ i ] = b64 [ idx ] ;
}
2005-08-27 05:42:20 +04:00
for ( ; i < bytes + pad_bytes ; i + + )
out [ i ] = ' = ' ;
2004-03-31 10:45:39 +04:00
out [ i ] = 0 ;
return out ;
}
/*
see if a buffer should be base64 encoded
*/
2009-09-08 14:57:31 +04:00
int ldb_should_b64_encode ( struct ldb_context * ldb , const struct ldb_val * val )
2004-03-31 10:45:39 +04:00
{
2004-07-07 05:02:54 +04:00
unsigned int i ;
2004-05-29 12:11:46 +04:00
uint8_t * p = val - > data ;
2004-03-31 10:45:39 +04:00
2004-11-30 05:15:43 +03:00
if ( val - > length = = 0 ) {
return 0 ;
}
if ( p [ 0 ] = = ' ' | | p [ 0 ] = = ' : ' ) {
2004-03-31 10:45:39 +04:00
return 1 ;
}
for ( i = 0 ; i < val - > length ; i + + ) {
if ( ! isprint ( p [ i ] ) | | p [ i ] = = ' \n ' ) {
return 1 ;
}
}
return 0 ;
}
/* this macro is used to handle the return checking on fprintf_fn() */
# define CHECK_RET do { if (ret < 0) return ret; total += ret; } while (0)
/*
write a line folded string onto a file
*/
2004-04-28 17:06:25 +04:00
static int fold_string ( int ( * fprintf_fn ) ( void * , const char * , . . . ) , void * private_data ,
2004-03-31 10:45:39 +04:00
const char * buf , size_t length , int start_pos )
{
2009-11-06 20:35:17 +03:00
size_t i ;
2017-12-08 12:03:00 +03:00
size_t total = 0 ;
int ret ;
2004-03-31 10:45:39 +04:00
for ( i = 0 ; i < length ; i + + ) {
2004-04-28 17:06:25 +04:00
ret = fprintf_fn ( private_data , " %c " , buf [ i ] ) ;
2004-03-31 10:45:39 +04:00
CHECK_RET ;
if ( i ! = ( length - 1 ) & & ( i + start_pos ) % 77 = = 0 ) {
2004-04-28 17:06:25 +04:00
ret = fprintf_fn ( private_data , " \n " ) ;
2004-03-31 10:45:39 +04:00
CHECK_RET ;
}
}
return total ;
}
2006-10-16 05:01:37 +04:00
# undef CHECK_RET
2004-03-31 10:45:39 +04:00
/*
encode as base64 to a file
*/
2004-05-06 08:40:15 +04:00
static int base64_encode_f ( struct ldb_context * ldb ,
2016-01-25 14:38:36 +03:00
int ( * fprintf_fn ) ( void * , const char * , . . . ) ,
2004-05-06 08:40:15 +04:00
void * private_data ,
2004-03-31 10:45:39 +04:00
const char * buf , int len , int start_pos )
{
2004-05-06 08:40:15 +04:00
char * b = ldb_base64_encode ( ldb , buf , len ) ;
2004-03-31 10:45:39 +04:00
int ret ;
if ( ! b ) {
return - 1 ;
}
2004-04-28 17:06:25 +04:00
ret = fold_string ( fprintf_fn , private_data , b , strlen ( b ) , start_pos ) ;
2004-03-31 10:45:39 +04:00
2005-01-02 10:49:29 +03:00
talloc_free ( b ) ;
2004-03-31 10:45:39 +04:00
return ret ;
}
2004-04-03 16:29:21 +04:00
static const struct {
const char * name ;
enum ldb_changetype changetype ;
} ldb_changetypes [ ] = {
{ " add " , LDB_CHANGETYPE_ADD } ,
{ " delete " , LDB_CHANGETYPE_DELETE } ,
{ " modify " , LDB_CHANGETYPE_MODIFY } ,
2011-04-05 16:41:27 +04:00
{ " modrdn " , LDB_CHANGETYPE_MODRDN } ,
{ " moddn " , LDB_CHANGETYPE_MODRDN } ,
2004-04-03 16:29:21 +04:00
{ NULL , 0 }
} ;
2006-10-16 05:01:37 +04:00
/* this macro is used to handle the return checking on fprintf_fn() */
# define CHECK_RET do { if (ret < 0) { talloc_free(mem_ctx); return ret; } total += ret; } while (0)
2004-03-31 10:45:39 +04:00
/*
2012-08-29 05:29:44 +04:00
write to ldif , using a caller supplied write method , and only printing secrets if we are not in a trace
2004-03-31 10:45:39 +04:00
*/
2012-08-29 05:29:44 +04:00
static int ldb_ldif_write_trace ( struct ldb_context * ldb ,
2016-01-25 14:38:36 +03:00
int ( * fprintf_fn ) ( void * , const char * , . . . ) ,
2012-08-29 05:29:44 +04:00
void * private_data ,
2016-01-25 14:38:36 +03:00
const struct ldb_ldif * ldif ,
2012-08-29 05:29:44 +04:00
bool in_trace )
2004-03-31 10:45:39 +04:00
{
2006-10-16 05:01:37 +04:00
TALLOC_CTX * mem_ctx ;
2004-07-07 05:02:54 +04:00
unsigned int i , j ;
2017-12-08 12:03:00 +03:00
size_t total = 0 ;
int ret ;
2008-12-16 10:33:32 +03:00
char * p ;
2004-04-03 16:29:21 +04:00
const struct ldb_message * msg ;
2012-08-29 05:29:44 +04:00
const char * const * secret_attributes = ldb_get_opaque ( ldb , LDB_SECRET_ATTRIBUTE_LIST_OPAQUE ) ;
2004-04-03 16:29:21 +04:00
2006-10-16 05:01:37 +04:00
mem_ctx = talloc_named_const ( NULL , 0 , " ldb_ldif_write " ) ;
2005-01-02 10:49:29 +03:00
msg = ldif - > msg ;
2008-12-16 10:33:32 +03:00
p = ldb_dn_get_extended_linearized ( mem_ctx , msg - > dn , 1 ) ;
ret = fprintf_fn ( private_data , " dn: %s \n " , p ) ;
talloc_free ( p ) ;
2004-03-31 10:45:39 +04:00
CHECK_RET ;
2004-04-03 16:29:21 +04:00
if ( ldif - > changetype ! = LDB_CHANGETYPE_NONE ) {
for ( i = 0 ; ldb_changetypes [ i ] . name ; i + + ) {
if ( ldb_changetypes [ i ] . changetype = = ldif - > changetype ) {
break ;
}
}
if ( ! ldb_changetypes [ i ] . name ) {
2009-07-11 00:44:27 +04:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " Error: Invalid ldif changetype %d " ,
2004-05-06 13:55:05 +04:00
ldif - > changetype ) ;
2006-10-16 05:01:37 +04:00
talloc_free ( mem_ctx ) ;
2004-04-03 16:29:21 +04:00
return - 1 ;
}
2004-04-28 17:06:25 +04:00
ret = fprintf_fn ( private_data , " changetype: %s \n " , ldb_changetypes [ i ] . name ) ;
2004-04-03 16:29:21 +04:00
CHECK_RET ;
}
2004-03-31 10:45:39 +04:00
for ( i = 0 ; i < msg - > num_elements ; i + + ) {
2006-12-15 16:08:57 +03:00
const struct ldb_schema_attribute * a ;
2018-10-19 00:21:21 +03:00
size_t namelen ;
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 10:21:26 +04:00
2014-11-12 03:12:31 +03:00
if ( msg - > elements [ i ] . name = = NULL ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: Invalid element name (NULL) at position %d " , i ) ;
talloc_free ( mem_ctx ) ;
return - 1 ;
}
2018-10-19 00:21:21 +03:00
namelen = strlen ( msg - > elements [ i ] . name ) ;
2006-12-15 16:08:57 +03:00
a = ldb_schema_attribute_by_name ( ldb , msg - > elements [ i ] . name ) ;
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 10:21:26 +04:00
2004-04-11 00:18:22 +04:00
if ( ldif - > changetype = = LDB_CHANGETYPE_MODIFY ) {
switch ( msg - > elements [ i ] . flags & LDB_FLAG_MOD_MASK ) {
case LDB_FLAG_MOD_ADD :
2016-01-25 14:38:36 +03:00
fprintf_fn ( private_data , " add: %s \n " ,
2004-04-11 00:18:22 +04:00
msg - > elements [ i ] . name ) ;
break ;
case LDB_FLAG_MOD_DELETE :
2016-01-25 14:38:36 +03:00
fprintf_fn ( private_data , " delete: %s \n " ,
2004-04-11 00:18:22 +04:00
msg - > elements [ i ] . name ) ;
break ;
case LDB_FLAG_MOD_REPLACE :
2016-01-25 14:38:36 +03:00
fprintf_fn ( private_data , " replace: %s \n " ,
2004-04-11 00:18:22 +04:00
msg - > elements [ i ] . name ) ;
break ;
}
}
2016-01-25 14:38:36 +03:00
2012-08-29 05:29:44 +04:00
if ( in_trace & & secret_attributes & & ldb_attr_in_list ( secret_attributes , msg - > elements [ i ] . name ) ) {
2023-04-03 11:07:39 +03:00
/* Deliberately skip printing this password */
2012-11-12 14:42:52 +04:00
ret = fprintf_fn ( private_data , " # %s::: REDACTED SECRET ATTRIBUTE \n " ,
2012-08-29 05:29:44 +04:00
msg - > elements [ i ] . name ) ;
CHECK_RET ;
continue ;
}
2004-04-03 16:29:21 +04:00
for ( j = 0 ; j < msg - > elements [ i ] . num_values ; j + + ) {
2005-06-21 10:35:55 +04:00
struct ldb_val v ;
2016-02-05 15:55:31 +03:00
bool use_b64_encode = false ;
2019-02-19 14:14:37 +03:00
bool copy_raw_bytes = false ;
2016-02-05 15:55:31 +03:00
2006-12-15 16:08:57 +03:00
ret = a - > syntax - > ldif_write_fn ( ldb , mem_ctx , & msg - > elements [ i ] . values [ j ] , & v ) ;
2008-11-14 01:40:02 +03:00
if ( ret ! = LDB_SUCCESS ) {
v = msg - > elements [ i ] . values [ j ] ;
}
2016-02-05 15:55:31 +03:00
if ( ldb - > flags & LDB_FLG_SHOW_BINARY ) {
use_b64_encode = false ;
2019-02-19 14:14:37 +03:00
copy_raw_bytes = true ;
2016-02-05 15:55:31 +03:00
} else if ( a - > flags & LDB_ATTR_FLAG_FORCE_BASE64_LDIF ) {
use_b64_encode = true ;
2019-02-19 14:29:58 +03:00
} else if ( msg - > elements [ i ] . flags &
LDB_FLAG_FORCE_NO_BASE64_LDIF ) {
use_b64_encode = false ;
copy_raw_bytes = true ;
2016-02-05 15:55:31 +03:00
} else {
use_b64_encode = ldb_should_b64_encode ( ldb , & v ) ;
}
2011-01-18 01:51:30 +03:00
if ( ret ! = LDB_SUCCESS | | use_b64_encode ) {
2016-01-25 14:38:36 +03:00
ret = fprintf_fn ( private_data , " %s:: " ,
2004-04-03 16:29:21 +04:00
msg - > elements [ i ] . name ) ;
CHECK_RET ;
2016-01-25 14:38:36 +03:00
ret = base64_encode_f ( ldb , fprintf_fn , private_data ,
2005-10-12 10:10:23 +04:00
( char * ) v . data , v . length ,
2018-10-17 06:28:25 +03:00
namelen + 3 ) ;
2004-04-03 16:29:21 +04:00
CHECK_RET ;
2004-04-28 17:06:25 +04:00
ret = fprintf_fn ( private_data , " \n " ) ;
2004-04-03 16:29:21 +04:00
CHECK_RET ;
} else {
2004-04-28 17:06:25 +04:00
ret = fprintf_fn ( private_data , " %s: " , msg - > elements [ i ] . name ) ;
2004-04-03 16:29:21 +04:00
CHECK_RET ;
2019-02-19 14:14:37 +03:00
if ( copy_raw_bytes ) {
2016-01-25 14:38:36 +03:00
ret = fprintf_fn ( private_data , " %*.*s " ,
2009-09-08 15:39:09 +04:00
v . length , v . length , ( char * ) v . data ) ;
} else {
ret = fold_string ( fprintf_fn , private_data ,
( char * ) v . data , v . length ,
2018-10-17 06:28:25 +03:00
namelen + 2 ) ;
2009-09-08 15:39:09 +04:00
}
2004-04-03 16:29:21 +04:00
CHECK_RET ;
2004-04-28 17:06:25 +04:00
ret = fprintf_fn ( private_data , " \n " ) ;
2004-04-03 16:29:21 +04:00
CHECK_RET ;
}
2005-06-21 10:35:55 +04:00
if ( v . data ! = msg - > elements [ i ] . values [ j ] . data ) {
talloc_free ( v . data ) ;
}
2004-03-31 10:45:39 +04:00
}
2004-04-11 00:18:22 +04:00
if ( ldif - > changetype = = LDB_CHANGETYPE_MODIFY ) {
2004-04-28 17:06:25 +04:00
fprintf_fn ( private_data , " - \n " ) ;
2004-04-11 00:18:22 +04:00
}
2004-03-31 10:45:39 +04:00
}
2004-04-28 17:06:25 +04:00
ret = fprintf_fn ( private_data , " \n " ) ;
2004-03-31 10:45:39 +04:00
CHECK_RET ;
2009-12-05 23:49:59 +03:00
talloc_free ( mem_ctx ) ;
2004-03-31 10:45:39 +04:00
return total ;
}
# undef CHECK_RET
2012-08-29 05:29:44 +04:00
/*
write to ldif , using a caller supplied write method
*/
int ldb_ldif_write ( struct ldb_context * ldb ,
2016-01-25 14:38:36 +03:00
int ( * fprintf_fn ) ( void * , const char * , . . . ) ,
2012-08-29 05:29:44 +04:00
void * private_data ,
const struct ldb_ldif * ldif )
{
return ldb_ldif_write_trace ( ldb , fprintf_fn , private_data , ldif , false ) ;
}
2004-03-31 10:45:39 +04:00
/*
pull a ldif chunk , which is defined as a piece of data ending in \ n \ n or EOF
this routine removes any RFC2849 continuations and comments
caller frees
*/
2016-01-25 14:40:53 +03:00
static char * next_chunk ( struct ldb_context * ldb , TALLOC_CTX * mem_ctx ,
2004-05-06 08:40:15 +04:00
int ( * fgetc_fn ) ( void * ) , void * private_data )
2004-03-31 10:45:39 +04:00
{
size_t alloc_size = 0 , chunk_size = 0 ;
char * chunk = NULL ;
int c ;
int in_comment = 0 ;
2004-04-28 17:06:25 +04:00
while ( ( c = fgetc_fn ( private_data ) ) ! = EOF ) {
2004-04-03 16:29:21 +04:00
if ( chunk_size + 1 > = alloc_size ) {
2004-03-31 10:45:39 +04:00
char * c2 ;
alloc_size + = 1024 ;
2016-01-25 14:40:53 +03:00
c2 = talloc_realloc ( mem_ctx , chunk , char , alloc_size ) ;
2004-03-31 10:45:39 +04:00
if ( ! c2 ) {
2005-01-02 10:49:29 +03:00
talloc_free ( chunk ) ;
2004-03-31 10:45:39 +04:00
errno = ENOMEM ;
return NULL ;
}
chunk = c2 ;
}
if ( in_comment ) {
if ( c = = ' \n ' ) {
in_comment = 0 ;
}
2016-01-25 14:38:36 +03:00
continue ;
2004-03-31 10:45:39 +04:00
}
2016-01-25 14:38:36 +03:00
2004-03-31 10:45:39 +04:00
/* handle continuation lines - see RFC2849 */
if ( c = = ' ' & & chunk_size > 1 & & chunk [ chunk_size - 1 ] = = ' \n ' ) {
chunk_size - - ;
continue ;
}
2016-01-25 14:38:36 +03:00
2004-03-31 10:45:39 +04:00
/* chunks are terminated by a double line-feed */
if ( c = = ' \n ' & & chunk_size > 0 & & chunk [ chunk_size - 1 ] = = ' \n ' ) {
chunk [ chunk_size - 1 ] = 0 ;
return chunk ;
}
if ( c = = ' # ' & & ( chunk_size = = 0 | | chunk [ chunk_size - 1 ] = = ' \n ' ) ) {
in_comment = 1 ;
continue ;
}
/* ignore leading blank lines */
if ( chunk_size = = 0 & & c = = ' \n ' ) {
continue ;
}
chunk [ chunk_size + + ] = c ;
}
2004-04-03 16:29:21 +04:00
if ( chunk ) {
chunk [ chunk_size ] = 0 ;
}
2004-03-31 10:45:39 +04:00
return chunk ;
}
/* simple ldif attribute parser */
2010-07-13 03:37:58 +04:00
static int next_attr ( TALLOC_CTX * mem_ctx , char * * s , const char * * attr , struct ldb_val * value )
2004-03-31 10:45:39 +04:00
{
char * p ;
int base64_encoded = 0 ;
2005-06-21 15:14:54 +04:00
int binary_file = 0 ;
2004-03-31 10:45:39 +04:00
2004-04-03 16:29:21 +04:00
if ( strncmp ( * s , " - \n " , 2 ) = = 0 ) {
value - > length = 0 ;
* attr = " - " ;
* s + = 2 ;
return 0 ;
}
2004-03-31 10:45:39 +04:00
p = strchr ( * s , ' : ' ) ;
if ( ! p ) {
return - 1 ;
}
* p + + = 0 ;
if ( * p = = ' : ' ) {
base64_encoded = 1 ;
p + + ;
}
2005-06-21 15:14:54 +04:00
if ( * p = = ' < ' ) {
binary_file = 1 ;
p + + ;
}
2004-03-31 10:45:39 +04:00
* attr = * s ;
2004-11-30 05:15:43 +03:00
while ( * p = = ' ' | | * p = = ' \t ' ) {
2004-03-31 10:45:39 +04:00
p + + ;
}
2005-10-12 10:10:23 +04:00
value - > data = ( uint8_t * ) p ;
2004-03-31 10:45:39 +04:00
p = strchr ( p , ' \n ' ) ;
if ( ! p ) {
value - > length = strlen ( ( char * ) value - > data ) ;
* s = ( ( char * ) value - > data ) + value - > length ;
} else {
value - > length = p - ( char * ) value - > data ;
* s = p + 1 ;
* p = 0 ;
}
if ( base64_encoded ) {
2005-10-12 10:10:23 +04:00
int len = ldb_base64_decode ( ( char * ) value - > data ) ;
2004-03-31 10:45:39 +04:00
if ( len = = - 1 ) {
/* it wasn't valid base64 data */
return - 1 ;
}
value - > length = len ;
}
2005-06-21 15:14:54 +04:00
if ( binary_file ) {
int len = ldb_read_data_file ( mem_ctx , value ) ;
if ( len = = - 1 ) {
2010-02-21 09:22:45 +03:00
/* an error occurred while trying to retrieve the file */
2005-06-21 15:14:54 +04:00
return - 1 ;
}
}
2004-03-31 10:45:39 +04:00
return 0 ;
}
/*
free a message from a ldif_read
*/
2004-05-20 17:25:06 +04:00
void ldb_ldif_read_free ( struct ldb_context * ldb , struct ldb_ldif * ldif )
2004-03-31 10:45:39 +04:00
{
2005-01-02 10:49:29 +03:00
talloc_free ( ldif ) ;
2004-04-03 16:29:21 +04:00
}
2011-04-05 16:41:27 +04:00
int ldb_ldif_parse_modrdn ( struct ldb_context * ldb ,
const struct ldb_ldif * ldif ,
TALLOC_CTX * mem_ctx ,
struct ldb_dn * * _olddn ,
struct ldb_dn * * _newrdn ,
bool * _deleteoldrdn ,
struct ldb_dn * * _newsuperior ,
struct ldb_dn * * _newdn )
{
struct ldb_message * msg = ldif - > msg ;
2023-02-23 16:56:39 +03:00
struct ldb_val _newrdn_val = { } ;
2011-04-05 16:41:27 +04:00
struct ldb_val * newrdn_val = NULL ;
struct ldb_val * deleteoldrdn_val = NULL ;
struct ldb_val * newsuperior_val = NULL ;
struct ldb_dn * olddn = NULL ;
struct ldb_dn * newrdn = NULL ;
bool deleteoldrdn = true ;
struct ldb_dn * newsuperior = NULL ;
struct ldb_dn * newdn = NULL ;
struct ldb_val tmp_false ;
struct ldb_val tmp_true ;
bool ok ;
TALLOC_CTX * tmp_ctx = talloc_new ( mem_ctx ) ;
if ( tmp_ctx = = NULL ) {
ldb_debug ( ldb , LDB_DEBUG_FATAL ,
" Error: talloc_new() failed " ) ;
goto err_op ;
}
if ( ldif - > changetype ! = LDB_CHANGETYPE_MODRDN ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: invalid changetype '%d' " ,
ldif - > changetype ) ;
goto err_other ;
}
if ( msg - > num_elements < 2 ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: num_elements[%u] < 2 " ,
msg - > num_elements ) ;
goto err_other ;
}
if ( msg - > num_elements > 3 ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: num_elements[%u] > 3 " ,
msg - > num_elements ) ;
goto err_other ;
}
# define CHECK_ELEMENT(i, _name, v, needed) do { \
v = NULL ; \
if ( msg - > num_elements < ( i + 1 ) ) { \
if ( needed ) { \
ldb_debug ( ldb , LDB_DEBUG_ERROR , \
" Error: num_elements[%u] < (%u + 1) " , \
msg - > num_elements , i ) ; \
goto err_other ; \
} \
} else if ( ldb_attr_cmp ( msg - > elements [ i ] . name , _name ) ! = 0 ) { \
ldb_debug ( ldb , LDB_DEBUG_ERROR , \
" Error: elements[%u].name[%s] != [%s] " , \
i , msg - > elements [ i ] . name , _name ) ; \
goto err_other ; \
} else if ( msg - > elements [ i ] . flags ! = 0 ) { \
ldb_debug ( ldb , LDB_DEBUG_ERROR , \
" Error: elements[%u].flags[0x%X} != [0x0] " , \
i , msg - > elements [ i ] . flags ) ; \
goto err_other ; \
} else if ( msg - > elements [ i ] . num_values ! = 1 ) { \
ldb_debug ( ldb , LDB_DEBUG_ERROR , \
" Error: elements[%u].num_values[%u] != 1 " , \
i , msg - > elements [ i ] . num_values ) ; \
goto err_other ; \
} else { \
v = & msg - > elements [ i ] . values [ 0 ] ; \
} \
} while ( 0 )
CHECK_ELEMENT ( 0 , " newrdn " , newrdn_val , true ) ;
CHECK_ELEMENT ( 1 , " deleteoldrdn " , deleteoldrdn_val , true ) ;
CHECK_ELEMENT ( 2 , " newsuperior " , newsuperior_val , false ) ;
# undef CHECK_ELEMENT
olddn = ldb_dn_copy ( tmp_ctx , msg - > dn ) ;
if ( olddn = = NULL ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: failed to copy olddn '%s' " ,
ldb_dn_get_linearized ( msg - > dn ) ) ;
goto err_op ;
}
2023-02-23 16:56:39 +03:00
if ( newrdn_val - > length ! = 0 & & strchr ( ( const char * ) newrdn_val - > data , ' = ' ) = = NULL ) {
const char * rdn_name = ldb_dn_get_rdn_name ( olddn ) ;
char * new_rdn = NULL ;
new_rdn = talloc_asprintf ( tmp_ctx ,
" %s=%s " ,
rdn_name ,
( const char * ) newrdn_val - > data ) ;
if ( new_rdn = = NULL ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: failed to allocate '%s=%s' " ,
rdn_name , ( char * ) newrdn_val - > data ) ;
goto err_op ;
}
_newrdn_val . data = ( uint8_t * ) new_rdn ;
_newrdn_val . length = strlen ( new_rdn ) ;
newrdn_val = & _newrdn_val ;
}
2011-04-05 16:41:27 +04:00
newrdn = ldb_dn_from_ldb_val ( tmp_ctx , ldb , newrdn_val ) ;
if ( ! ldb_dn_validate ( newrdn ) ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: Unable to parse dn '%s' " ,
( char * ) newrdn_val - > data ) ;
goto err_dn ;
}
tmp_false . length = 1 ;
tmp_false . data = discard_const_p ( uint8_t , " 0 " ) ;
tmp_true . length = 1 ;
tmp_true . data = discard_const_p ( uint8_t , " 1 " ) ;
if ( ldb_val_equal_exact ( deleteoldrdn_val , & tmp_false ) = = 1 ) {
deleteoldrdn = false ;
} else if ( ldb_val_equal_exact ( deleteoldrdn_val , & tmp_true ) = = 1 ) {
deleteoldrdn = true ;
} else {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: deleteoldrdn value invalid '%s' not '0'/'1' " ,
( char * ) deleteoldrdn_val - > data ) ;
goto err_attr ;
}
if ( newsuperior_val ) {
newsuperior = ldb_dn_from_ldb_val ( tmp_ctx , ldb , newsuperior_val ) ;
if ( ! ldb_dn_validate ( newsuperior ) ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: Unable to parse dn '%s' " ,
( char * ) newsuperior_val - > data ) ;
goto err_dn ;
}
} else {
newsuperior = ldb_dn_get_parent ( tmp_ctx , msg - > dn ) ;
if ( newsuperior = = NULL ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: Unable to get parent dn '%s' " ,
ldb_dn_get_linearized ( msg - > dn ) ) ;
goto err_dn ;
}
}
newdn = ldb_dn_copy ( tmp_ctx , newrdn ) ;
if ( newdn = = NULL ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: failed to copy newrdn '%s' " ,
ldb_dn_get_linearized ( newrdn ) ) ;
goto err_op ;
}
ok = ldb_dn_add_base ( newdn , newsuperior ) ;
if ( ! ok ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: failed to base '%s' to newdn '%s' " ,
ldb_dn_get_linearized ( newsuperior ) ,
ldb_dn_get_linearized ( newdn ) ) ;
goto err_op ;
}
if ( _olddn ) {
* _olddn = talloc_move ( mem_ctx , & olddn ) ;
}
if ( _newrdn ) {
* _newrdn = talloc_move ( mem_ctx , & newrdn ) ;
}
if ( _deleteoldrdn ) {
* _deleteoldrdn = deleteoldrdn ;
}
2019-05-08 03:49:53 +03:00
if ( _newsuperior ! = NULL & & _newrdn ! = NULL ) {
2011-04-05 16:41:27 +04:00
if ( newsuperior_val ) {
* _newrdn = talloc_move ( mem_ctx , & newrdn ) ;
} else {
* _newrdn = NULL ;
}
}
if ( _newdn ) {
* _newdn = talloc_move ( mem_ctx , & newdn ) ;
}
talloc_free ( tmp_ctx ) ;
return LDB_SUCCESS ;
err_other :
talloc_free ( tmp_ctx ) ;
return LDB_ERR_OTHER ;
err_op :
talloc_free ( tmp_ctx ) ;
return LDB_ERR_OPERATIONS_ERROR ;
err_attr :
talloc_free ( tmp_ctx ) ;
return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX ;
err_dn :
talloc_free ( tmp_ctx ) ;
return LDB_ERR_INVALID_DN_SYNTAX ;
}
2004-03-31 10:45:39 +04:00
/*
read from a LDIF source , creating a ldb_message
*/
2004-05-20 17:25:06 +04:00
struct ldb_ldif * ldb_ldif_read ( struct ldb_context * ldb ,
int ( * fgetc_fn ) ( void * ) , void * private_data )
2004-03-31 10:45:39 +04:00
{
2004-04-03 16:29:21 +04:00
struct ldb_ldif * ldif ;
2004-03-31 10:45:39 +04:00
struct ldb_message * msg ;
2004-05-05 08:27:29 +04:00
const char * attr = NULL ;
char * chunk = NULL , * s ;
2004-03-31 10:45:39 +04:00
struct ldb_val value ;
2004-04-03 16:29:21 +04:00
unsigned flags = 0 ;
2004-03-31 10:45:39 +04:00
value . data = NULL ;
2005-01-12 19:00:01 +03:00
ldif = talloc ( ldb , struct ldb_ldif ) ;
2004-04-03 16:29:21 +04:00
if ( ! ldif ) return NULL ;
2019-04-06 03:55:06 +03:00
ldif - > msg = ldb_msg_new ( ldif ) ;
2005-01-02 10:49:29 +03:00
if ( ldif - > msg = = NULL ) {
talloc_free ( ldif ) ;
return NULL ;
}
2004-04-03 16:29:21 +04:00
ldif - > changetype = LDB_CHANGETYPE_NONE ;
2005-01-02 10:49:29 +03:00
msg = ldif - > msg ;
2004-03-31 10:45:39 +04:00
2016-01-25 14:40:53 +03:00
chunk = next_chunk ( ldb , ldif , fgetc_fn , private_data ) ;
2004-03-31 10:45:39 +04:00
if ( ! chunk ) {
goto failed ;
}
s = chunk ;
2005-06-21 15:14:54 +04:00
if ( next_attr ( ldif , & s , & attr , & value ) ! = 0 ) {
2004-03-31 10:45:39 +04:00
goto failed ;
}
2016-01-25 14:38:36 +03:00
2004-03-31 10:45:39 +04:00
/* first line must be a dn */
2004-05-01 13:45:56 +04:00
if ( ldb_attr_cmp ( attr , " dn " ) ! = 0 ) {
2009-07-11 00:44:27 +04:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " Error: First line of ldif must be a dn not '%s' " ,
2004-05-06 13:55:05 +04:00
attr ) ;
2004-03-31 10:45:39 +04:00
goto failed ;
}
2008-10-27 05:32:23 +03:00
msg - > dn = ldb_dn_from_ldb_val ( msg , ldb , & value ) ;
2004-03-31 10:45:39 +04:00
2006-11-22 03:59:34 +03:00
if ( ! ldb_dn_validate ( msg - > dn ) ) {
2009-07-11 00:44:27 +04:00
ldb_debug ( ldb , LDB_DEBUG_ERROR , " Error: Unable to parse dn '%s' " ,
2008-10-27 05:32:23 +03:00
( char * ) value . data ) ;
2005-08-30 04:43:26 +04:00
goto failed ;
}
2005-06-21 15:14:54 +04:00
while ( next_attr ( ldif , & s , & attr , & value ) = = 0 ) {
2006-12-15 16:08:57 +03:00
const struct ldb_schema_attribute * a ;
2004-04-03 16:29:21 +04:00
struct ldb_message_element * el ;
2005-06-21 10:35:55 +04:00
int ret , empty = 0 ;
2004-04-03 16:29:21 +04:00
2004-05-01 13:45:56 +04:00
if ( ldb_attr_cmp ( attr , " changetype " ) = = 0 ) {
2004-04-03 16:29:21 +04:00
int i ;
for ( i = 0 ; ldb_changetypes [ i ] . name ; i + + ) {
2004-05-01 13:45:56 +04:00
if ( ldb_attr_cmp ( ( char * ) value . data , ldb_changetypes [ i ] . name ) = = 0 ) {
2004-04-03 16:29:21 +04:00
ldif - > changetype = ldb_changetypes [ i ] . changetype ;
break ;
}
}
if ( ! ldb_changetypes [ i ] . name ) {
2009-07-11 00:44:27 +04:00
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
" Error: Bad ldif changetype '%s' " , ( char * ) value . data ) ;
2004-04-03 16:29:21 +04:00
}
flags = 0 ;
continue ;
}
2004-05-01 13:45:56 +04:00
if ( ldb_attr_cmp ( attr , " add " ) = = 0 ) {
2004-04-03 16:29:21 +04:00
flags = LDB_FLAG_MOD_ADD ;
empty = 1 ;
}
2004-05-01 13:45:56 +04:00
if ( ldb_attr_cmp ( attr , " delete " ) = = 0 ) {
2004-04-03 16:29:21 +04:00
flags = LDB_FLAG_MOD_DELETE ;
empty = 1 ;
}
2004-05-01 13:45:56 +04:00
if ( ldb_attr_cmp ( attr , " replace " ) = = 0 ) {
2004-04-03 16:29:21 +04:00
flags = LDB_FLAG_MOD_REPLACE ;
empty = 1 ;
}
2004-05-01 13:45:56 +04:00
if ( ldb_attr_cmp ( attr , " - " ) = = 0 ) {
2004-04-03 16:29:21 +04:00
flags = 0 ;
continue ;
}
if ( empty ) {
2006-10-25 05:42:59 +04:00
if ( ldb_msg_add_empty ( msg , ( char * ) value . data , flags , NULL ) ! = 0 ) {
2004-04-03 16:29:21 +04:00
goto failed ;
}
continue ;
}
2016-01-25 14:38:36 +03:00
2006-12-15 16:08:57 +03:00
a = ldb_schema_attribute_by_name ( ldb , attr ) ;
2023-05-02 13:43:54 +03:00
el = ( msg - > num_elements > 0
? & msg - > elements [ msg - > num_elements - 1 ]
: NULL ) ;
2005-06-21 10:35:55 +04:00
2023-05-02 13:43:54 +03:00
if ( el & & ldb_attr_cmp ( attr , el - > name ) = = 0 & & flags = = el - > flags ) {
2004-04-03 16:29:21 +04:00
/* its a continuation */
2016-01-25 14:38:36 +03:00
el - > values =
talloc_realloc ( msg - > elements , el - > values ,
2005-01-02 10:49:29 +03:00
struct ldb_val , el - > num_values + 1 ) ;
2004-04-03 16:29:21 +04:00
if ( ! el - > values ) {
goto failed ;
}
2009-07-06 03:24:18 +04:00
ret = a - > syntax - > ldif_read_fn ( ldb , el - > values , & value , & el - > values [ el - > num_values ] ) ;
2005-06-21 10:35:55 +04:00
if ( ret ! = 0 ) {
goto failed ;
}
2005-09-18 14:46:21 +04:00
if ( value . length = = 0 ) {
ldb_debug ( ldb , LDB_DEBUG_ERROR ,
2009-07-11 00:44:27 +04:00
" Error: Attribute value cannot be empty for attribute '%s' " , el - > name ) ;
2005-09-18 14:46:21 +04:00
goto failed ;
}
2005-06-21 10:35:55 +04:00
if ( value . data ! = el - > values [ el - > num_values ] . data ) {
talloc_steal ( el - > values , el - > values [ el - > num_values ] . data ) ;
}
2004-04-03 16:29:21 +04:00
el - > num_values + + ;
} else {
/* its a new attribute */
2016-01-25 14:38:36 +03:00
msg - > elements = talloc_realloc ( msg , msg - > elements ,
struct ldb_message_element ,
2005-01-02 10:49:29 +03:00
msg - > num_elements + 1 ) ;
2004-04-03 16:29:21 +04:00
if ( ! msg - > elements ) {
goto failed ;
}
el = & msg - > elements [ msg - > num_elements ] ;
2004-05-01 13:45:56 +04:00
el - > flags = flags ;
2005-01-02 10:49:29 +03:00
el - > name = talloc_strdup ( msg - > elements , attr ) ;
2005-01-12 19:00:01 +03:00
el - > values = talloc ( msg - > elements , struct ldb_val ) ;
2004-05-01 13:45:56 +04:00
if ( ! el - > values | | ! el - > name ) {
2004-04-03 16:29:21 +04:00
goto failed ;
}
el - > num_values = 1 ;
2009-07-06 03:24:18 +04:00
ret = a - > syntax - > ldif_read_fn ( ldb , el - > values , & value , & el - > values [ 0 ] ) ;
2005-06-21 10:35:55 +04:00
if ( ret ! = 0 ) {
goto failed ;
}
if ( value . data ! = el - > values [ 0 ] . data ) {
talloc_steal ( el - > values , el - > values [ 0 ] . data ) ;
}
2004-04-03 16:29:21 +04:00
msg - > num_elements + + ;
2004-03-31 10:45:39 +04:00
}
}
2011-04-05 16:41:27 +04:00
if ( ldif - > changetype = = LDB_CHANGETYPE_MODRDN ) {
int ret ;
ret = ldb_ldif_parse_modrdn ( ldb , ldif , ldif ,
NULL , NULL , NULL , NULL , NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
goto failed ;
}
}
2004-04-03 16:29:21 +04:00
return ldif ;
2004-03-31 10:45:39 +04:00
failed :
2005-01-02 10:49:29 +03:00
talloc_free ( ldif ) ;
2004-03-31 10:45:39 +04:00
return NULL ;
}
/*
a wrapper around ldif_read ( ) for reading from FILE *
*/
2004-04-28 17:06:25 +04:00
static int fgetc_file ( void * private_data )
2004-03-31 10:45:39 +04:00
{
2012-04-10 11:29:11 +04:00
int c ;
2006-10-09 12:00:18 +04:00
struct ldif_read_file_state * state =
( struct ldif_read_file_state * ) private_data ;
2012-04-10 11:29:11 +04:00
c = fgetc ( state - > f ) ;
if ( c = = ' \n ' ) {
state - > line_no + + ;
}
return c ;
}
2016-01-25 14:38:36 +03:00
struct ldb_ldif * ldb_ldif_read_file_state ( struct ldb_context * ldb ,
2012-04-10 11:29:11 +04:00
struct ldif_read_file_state * state )
{
return ldb_ldif_read ( ldb , fgetc_file , state ) ;
2004-03-31 10:45:39 +04:00
}
2004-05-20 17:25:06 +04:00
struct ldb_ldif * ldb_ldif_read_file ( struct ldb_context * ldb , FILE * f )
2004-03-31 10:45:39 +04:00
{
struct ldif_read_file_state state ;
state . f = f ;
2012-04-10 11:29:11 +04:00
return ldb_ldif_read_file_state ( ldb , & state ) ;
2004-03-31 10:45:39 +04:00
}
/*
a wrapper around ldif_read ( ) for reading from const char *
*/
struct ldif_read_string_state {
const char * s ;
} ;
2004-04-28 17:06:25 +04:00
static int fgetc_string ( void * private_data )
2004-03-31 10:45:39 +04:00
{
2006-10-09 12:00:18 +04:00
struct ldif_read_string_state * state =
( struct ldif_read_string_state * ) private_data ;
2004-03-31 10:45:39 +04:00
if ( state - > s [ 0 ] ! = 0 ) {
return * state - > s + + ;
}
return EOF ;
}
2005-07-12 09:56:06 +04:00
struct ldb_ldif * ldb_ldif_read_string ( struct ldb_context * ldb , const char * * s )
2004-03-31 10:45:39 +04:00
{
struct ldif_read_string_state state ;
2005-07-12 09:56:06 +04:00
struct ldb_ldif * ldif ;
state . s = * s ;
ldif = ldb_ldif_read ( ldb , fgetc_string , & state ) ;
* s = state . s ;
return ldif ;
2004-03-31 10:45:39 +04:00
}
/*
wrapper around ldif_write ( ) for a file
*/
struct ldif_write_file_state {
FILE * f ;
} ;
2004-08-25 11:15:21 +04:00
static int fprintf_file ( void * private_data , const char * fmt , . . . ) PRINTF_ATTRIBUTE ( 2 , 3 ) ;
2004-04-28 17:06:25 +04:00
static int fprintf_file ( void * private_data , const char * fmt , . . . )
2004-03-31 10:45:39 +04:00
{
2006-10-09 12:00:18 +04:00
struct ldif_write_file_state * state =
( struct ldif_write_file_state * ) private_data ;
2004-03-31 10:45:39 +04:00
int ret ;
va_list ap ;
va_start ( ap , fmt ) ;
ret = vfprintf ( state - > f , fmt , ap ) ;
va_end ( ap ) ;
return ret ;
}
2004-05-20 17:25:06 +04:00
int ldb_ldif_write_file ( struct ldb_context * ldb , FILE * f , const struct ldb_ldif * ldif )
2004-03-31 10:45:39 +04:00
{
struct ldif_write_file_state state ;
state . f = f ;
2004-05-20 17:25:06 +04:00
return ldb_ldif_write ( ldb , fprintf_file , & state , ldif ) ;
2004-03-31 10:45:39 +04:00
}
2009-08-26 09:59:00 +04:00
/*
wrapper around ldif_write ( ) for a string
*/
struct ldif_write_string_state {
char * string ;
} ;
static int ldif_printf_string ( void * private_data , const char * fmt , . . . ) PRINTF_ATTRIBUTE ( 2 , 3 ) ;
static int ldif_printf_string ( void * private_data , const char * fmt , . . . )
{
struct ldif_write_string_state * state =
( struct ldif_write_string_state * ) private_data ;
va_list ap ;
2009-09-22 03:29:22 +04:00
size_t oldlen = talloc_get_size ( state - > string ) ;
2009-08-26 09:59:00 +04:00
va_start ( ap , fmt ) ;
2016-01-25 14:38:36 +03:00
2009-08-26 09:59:00 +04:00
state - > string = talloc_vasprintf_append ( state - > string , fmt , ap ) ;
va_end ( ap ) ;
if ( ! state - > string ) {
return - 1 ;
}
2009-09-22 03:29:22 +04:00
return talloc_get_size ( state - > string ) - oldlen ;
2009-08-26 09:59:00 +04:00
}
2016-01-25 14:38:36 +03:00
char * ldb_ldif_write_redacted_trace_string ( struct ldb_context * ldb , TALLOC_CTX * mem_ctx ,
2012-08-29 05:29:44 +04:00
const struct ldb_ldif * ldif )
{
struct ldif_write_string_state state ;
state . string = talloc_strdup ( mem_ctx , " " ) ;
if ( ! state . string ) {
return NULL ;
}
if ( ldb_ldif_write_trace ( ldb , ldif_printf_string , & state , ldif , true ) = = - 1 ) {
return NULL ;
}
return state . string ;
}
2016-01-25 14:38:36 +03:00
char * ldb_ldif_write_string ( struct ldb_context * ldb , TALLOC_CTX * mem_ctx ,
2009-08-26 09:59:00 +04:00
const struct ldb_ldif * ldif )
{
struct ldif_write_string_state state ;
state . string = talloc_strdup ( mem_ctx , " " ) ;
if ( ! state . string ) {
return NULL ;
}
if ( ldb_ldif_write ( ldb , ldif_printf_string , & state , ldif ) = = - 1 ) {
return NULL ;
}
return state . string ;
}
2009-09-02 05:14:33 +04:00
/*
convenient function to turn a ldb_message into a string . Useful for
debugging
*/
2016-01-25 14:38:36 +03:00
char * ldb_ldif_message_string ( struct ldb_context * ldb , TALLOC_CTX * mem_ctx ,
2009-09-02 05:14:33 +04:00
enum ldb_changetype changetype ,
const struct ldb_message * msg )
{
struct ldb_ldif ldif ;
ldif . changetype = changetype ;
2009-09-08 15:39:09 +04:00
ldif . msg = discard_const_p ( struct ldb_message , msg ) ;
2009-09-02 05:14:33 +04:00
return ldb_ldif_write_string ( ldb , mem_ctx , & ldif ) ;
}
2017-09-05 05:05:43 +03:00
/*
* convenient function to turn a ldb_message into a string . Useful for
* debugging but also safer if some of the LDIF could be sensitive .
*
* The secret attributes are specified in a ' const char * const * ' within
* the LDB_SECRET_ATTRIBUTE_LIST opaque set on the ldb
*
*/
char * ldb_ldif_message_redacted_string ( struct ldb_context * ldb ,
TALLOC_CTX * mem_ctx ,
enum ldb_changetype changetype ,
const struct ldb_message * msg )
{
struct ldb_ldif ldif ;
ldif . changetype = changetype ;
ldif . msg = discard_const_p ( struct ldb_message , msg ) ;
return ldb_ldif_write_redacted_trace_string ( ldb , mem_ctx , & ldif ) ;
}