mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-30 13:30:57 +08:00
add (and honor) a (configurable) baseObject to workaround ldap_entries view for RDBMSes that do not support UNION in views
This commit is contained in:
parent
fa8ee16d38
commit
796dce8657
@ -107,7 +107,7 @@ Note that the parameter number and order must not be changed.
|
||||
Specifies the name of a function that converts a given value to uppercase.
|
||||
This is used for CIS matching when the RDBMS is case sensitive.
|
||||
.TP
|
||||
.B upper_needs_cast { yes | no }
|
||||
.B upper_needs_cast { NO | yes}
|
||||
Set this directive to
|
||||
.B yes
|
||||
if
|
||||
@ -151,7 +151,7 @@ This is
|
||||
.B experimental
|
||||
and may change in future releases.
|
||||
.TP
|
||||
.B has_ldapinfo_dn_ru { yes | no }
|
||||
.B has_ldapinfo_dn_ru { NO | yes }
|
||||
Explicitly inform the backend whether the SQL schema has dn_ru column
|
||||
(dn in reverse uppercased form) or not.
|
||||
Overrides automatic check (required by PostgreSQL/unixODBC).
|
||||
@ -160,7 +160,7 @@ This is
|
||||
and may change in future releases.
|
||||
|
||||
.TP
|
||||
.B fail_if_no_mapping { yes | no }
|
||||
.B fail_if_no_mapping { NO | yes }
|
||||
When set to
|
||||
.B yes
|
||||
it forces
|
||||
@ -181,6 +181,37 @@ This is
|
||||
.B experimental
|
||||
and may change in future releases.
|
||||
|
||||
.TP
|
||||
.B allow_orphans { NO | yes }
|
||||
When set to
|
||||
.B yes
|
||||
orphaned entries (i.e. without the parent entry in the database)
|
||||
can be added. This option should be used with care, possibly
|
||||
in conjunction with some special rule on the RDBMS side that
|
||||
dynamically creates the missing parent.
|
||||
|
||||
.TP
|
||||
.B baseObject [filename]
|
||||
Instructs the database to create and manage an in-memory baseObject
|
||||
entry instead of looking for one in the RDBMS.
|
||||
If the (optional)
|
||||
.B filename
|
||||
argument is given, the entry is read from file
|
||||
.B filename
|
||||
in
|
||||
.BR LDIF (5)
|
||||
form.
|
||||
This is particularly useful when
|
||||
.B ldap_entries
|
||||
information is stored in a view rather than in a table, and
|
||||
.B union
|
||||
is not supported for views, so that the view can only specify
|
||||
one rule to compute the entry structure for one objectClass.
|
||||
This topic is discussed further in section "METAINFORMATION USED".
|
||||
This is
|
||||
.B experimental
|
||||
and may change in future releases.
|
||||
|
||||
.SH METAINFORMATION USED
|
||||
.LP
|
||||
Almost everything mentioned later is illustrated in examples located
|
||||
@ -369,13 +400,26 @@ like this (by Robin Elfrink):
|
||||
.LP
|
||||
.nf
|
||||
CREATE VIEW ldap_entries (id, dn, oc_map_id, parent, keyval)
|
||||
AS SELECT (1000000000+userid),
|
||||
AS
|
||||
SELECT 0, UPPER('o=MyCompany,c=NL'),
|
||||
3, 0, 'baseObject' FROM unixusers WHERE userid='root' UNION
|
||||
SELECT (1000000000+userid),
|
||||
UPPER(CONCAT(CONCAT('cn=',gecos),',o=MyCompany,c=NL')),
|
||||
1, 0, userid FROM unixusers UNION
|
||||
SELECT (2000000000+groupnummer),
|
||||
UPPER(CONCAT(CONCAT('cn=',groupnaam),',o=MyCompany,c=NL')),
|
||||
2, 0, groupnummer FROM groups;
|
||||
.fi
|
||||
|
||||
.LP
|
||||
If your RDBMS does not support
|
||||
.B unions
|
||||
in views, only one objectClass can be mapped in
|
||||
.BR ldap_entries ,
|
||||
and the baseObject cannot be created; in this case, see the
|
||||
.B baseObject
|
||||
directive for a possible workaround.
|
||||
|
||||
.LP
|
||||
.SH Typical SQL backend operation
|
||||
Having metainformation loaded, the SQL backend uses these tables to
|
||||
|
@ -357,6 +357,19 @@ typedef struct {
|
||||
(!BER_BVISNULL( &(si)->sql_upper_func ))
|
||||
#define BACKSQL_ALLOW_ORPHANS(si) \
|
||||
((si)->sql_flags & BSQLF_ALLOW_ORPHANS)
|
||||
|
||||
Entry *sql_baseObject;
|
||||
#ifdef BACKSQL_ARBITRARY_KEY
|
||||
#define BACKSQL_BASEOBJECT_IDSTR "baseObject"
|
||||
#define BACKSQL_BASEOBJECT_KEYVAL BACKSQL_BASEOBJECT_IDSTR
|
||||
#define BACKSQL_IS_BASEOBJECT_ID(id) (bvmatch((id), &backsql_baseObject_bv)
|
||||
#else /* ! BACKSQL_ARBITRARY_KEY */
|
||||
#define BACKSQL_BASEOBJECT_ID 0
|
||||
#define BACKSQL_BASEOBJECT_IDSTR "0"
|
||||
#define BACKSQL_BASEOBJECT_KEYVAL 0
|
||||
#define BACKSQL_IS_BASEOBJECT_ID(id) (*(id) == BACKSQL_BASEOBJECT_ID)
|
||||
#endif /* ! BACKSQL_ARBITRARY_KEY */
|
||||
#define BACKSQL_BASEOBJECT_OC 0
|
||||
|
||||
Avlnode *sql_db_conns;
|
||||
Avlnode *sql_oc_by_oc;
|
||||
|
@ -73,7 +73,7 @@ backsql_bind( Operation *op, SlapReply *rs )
|
||||
return 1;
|
||||
}
|
||||
|
||||
dn = op->o_req_dn;
|
||||
dn = op->o_req_ndn;
|
||||
if ( backsql_api_dn2odbc( op, rs, &dn ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
|
||||
"backsql_api_dn2odbc failed\n",
|
||||
|
@ -58,7 +58,7 @@ backsql_compare( Operation *op, SlapReply *rs )
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
dn = op->o_req_dn;
|
||||
dn = op->o_req_ndn;
|
||||
if ( backsql_api_dn2odbc( op, rs, &dn ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
|
||||
"backsql_api_dn2odbc failed\n",
|
||||
|
@ -27,8 +27,20 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "ldif.h"
|
||||
#include "proto-sql.h"
|
||||
|
||||
static int
|
||||
create_baseObject(
|
||||
BackendDB *be,
|
||||
const char *fname,
|
||||
int lineno );
|
||||
|
||||
static int
|
||||
read_baseObject(
|
||||
BackendDB *be,
|
||||
const char *fname );
|
||||
|
||||
int
|
||||
backsql_db_config(
|
||||
BackendDB *be,
|
||||
@ -389,6 +401,39 @@ backsql_db_config(
|
||||
"allow_orphans=%s\n",
|
||||
BACKSQL_ALLOW_ORPHANS( bi ) ? "yes" : "no", 0, 0 );
|
||||
|
||||
} else if ( !strcasecmp( argv[ 0 ], "baseobject" ) ) {
|
||||
if ( be->be_suffix == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<==backsql_db_config (%s line %d): : "
|
||||
"must be defined after \"suffix\"\n",
|
||||
fname, lineno, 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( bi->sql_baseObject ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<==backsql_db_config (%s line %d): : "
|
||||
"\"baseObject\" already provided (will be overwritten)\n",
|
||||
fname, lineno, 0 );
|
||||
entry_free( bi->sql_baseObject );
|
||||
}
|
||||
|
||||
switch ( argc ) {
|
||||
case 1:
|
||||
return create_baseObject( be, fname, lineno );
|
||||
|
||||
case 2:
|
||||
return read_baseObject( be, argv[ 1 ] );
|
||||
|
||||
default:
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<==backsql_db_config (%s line %d): "
|
||||
"trailing values "
|
||||
"in \"baseObject\" directive?\n",
|
||||
fname, lineno, 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
} else if ( !strcasecmp( argv[ 0 ], "sqllayer") ) {
|
||||
if ( backsql_api_config( bi, argv[ 1 ] ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
@ -405,5 +450,207 @@ backsql_db_config(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the entries specified in fname and merge the attributes
|
||||
* to the user defined baseObject entry. Note that if we find any errors
|
||||
* what so ever, we will discard the entire entries, print an
|
||||
* error message and return.
|
||||
*/
|
||||
static int
|
||||
read_baseObject(
|
||||
BackendDB *be,
|
||||
const char *fname )
|
||||
{
|
||||
backsql_info *bi = (backsql_info *)be->be_private;
|
||||
FILE *fp;
|
||||
int rc = 0, lineno = 0, lmax = 0;
|
||||
char *buf = NULL;
|
||||
|
||||
assert( fname );
|
||||
|
||||
fp = fopen( fname, "r" );
|
||||
if ( fp == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"could not open back-sql baseObject attr file \"%s\" - absolute path?\n",
|
||||
fname, 0, 0 );
|
||||
perror( fname );
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
bi->sql_baseObject = (Entry *) SLAP_CALLOC( 1, sizeof(Entry) );
|
||||
if ( bi->sql_baseObject == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"read_baseObject_file: SLAP_CALLOC failed", 0, 0, 0 );
|
||||
fclose( fp );
|
||||
return LDAP_NO_MEMORY;
|
||||
}
|
||||
bi->sql_baseObject->e_name = be->be_suffix[0];
|
||||
bi->sql_baseObject->e_nname = be->be_nsuffix[0];
|
||||
bi->sql_baseObject->e_attrs = NULL;
|
||||
|
||||
while ( ldif_read_record( fp, &lineno, &buf, &lmax ) ) {
|
||||
Entry *e = str2entry( buf );
|
||||
Attribute *a;
|
||||
|
||||
if( e == NULL ) {
|
||||
fprintf( stderr, "back-sql baseObject: could not parse entry (line=%d)\n",
|
||||
lineno );
|
||||
rc = LDAP_OTHER;
|
||||
break;
|
||||
}
|
||||
|
||||
/* make sure the DN is the database's suffix */
|
||||
if ( !be_issuffix( be, &e->e_nname ) ) {
|
||||
fprintf( stderr,
|
||||
"back-sql: invalid baseObject - dn=\"%s\" (line=%d)\n",
|
||||
e->e_dn, lineno );
|
||||
entry_free( e );
|
||||
rc = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* we found a valid entry, so walk thru all the attributes in the
|
||||
* entry, and add each attribute type and description to baseObject
|
||||
*/
|
||||
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
|
||||
if ( attr_merge( bi->sql_baseObject, a->a_desc, a->a_vals,
|
||||
( a->a_nvals == a->a_vals ) ? NULL : a->a_nvals ) )
|
||||
{
|
||||
rc = LDAP_OTHER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
entry_free( e );
|
||||
if ( rc ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( rc ) {
|
||||
entry_free( bi->sql_baseObject );
|
||||
bi->sql_baseObject = NULL;
|
||||
}
|
||||
|
||||
ch_free( buf );
|
||||
|
||||
fclose( fp );
|
||||
|
||||
Debug( LDAP_DEBUG_CONFIG, "back-sql baseObject file \"%s\" read.\n", fname, 0, 0 );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
create_baseObject(
|
||||
BackendDB *be,
|
||||
const char *fname,
|
||||
int lineno )
|
||||
{
|
||||
backsql_info *bi = (backsql_info *)be->be_private;
|
||||
LDAPRDN rdn;
|
||||
char *p;
|
||||
int rc, iAVA;
|
||||
char buf[1024];
|
||||
|
||||
snprintf( buf, sizeof(buf),
|
||||
"dn: %s\n"
|
||||
"objectClass: extensibleObject\n"
|
||||
"description: builtin baseObject for back-sql\n"
|
||||
"description: all entries mapped in the \"ldap_entries\" table\n"
|
||||
"description: must have \"" BACKSQL_BASEOBJECT_IDSTR "\" "
|
||||
"in the \"parent\" column",
|
||||
be->be_suffix[0].bv_val );
|
||||
|
||||
bi->sql_baseObject = str2entry( buf );
|
||||
if ( bi->sql_baseObject == NULL ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<==backsql_db_config (%s line %d): "
|
||||
"unable to parse baseObject entry\n",
|
||||
fname, lineno, 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( BER_BVISEMPTY( &be->be_suffix[ 0 ] ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = ldap_bv2rdn( &be->be_suffix[ 0 ], &rdn, (char **) &p, LDAP_DN_FORMAT_LDAP );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
snprintf( buf, sizeof(buf),
|
||||
"unable to extract RDN from baseObject DN \"%s\" (%d: %s)",
|
||||
be->be_suffix[ 0 ].bv_val, rc, ldap_err2string( rc ) );
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<==backsql_db_config (%s line %d): %s\n",
|
||||
fname, lineno, buf );
|
||||
return 1;
|
||||
}
|
||||
|
||||
for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
|
||||
LDAPAVA *ava = rdn[ iAVA ];
|
||||
AttributeDescription *ad = NULL;
|
||||
slap_syntax_transform_func *transf = NULL;
|
||||
struct berval bv = BER_BVNULL;
|
||||
const char *text = NULL;
|
||||
|
||||
assert( ava );
|
||||
|
||||
rc = slap_bv2ad( &ava->la_attr, &ad, &text );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
snprintf( buf, sizeof(buf),
|
||||
"AttributeDescription of naming "
|
||||
"attribute #%d from baseObject "
|
||||
"DN \"%s\": %d: %s",
|
||||
iAVA, be->be_suffix[ 0 ].bv_val,
|
||||
rc, ldap_err2string( rc ) );
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<==backsql_db_config (%s line %d): %s\n",
|
||||
fname, lineno, buf );
|
||||
return 1;
|
||||
}
|
||||
|
||||
transf = ad->ad_type->sat_syntax->ssyn_pretty;
|
||||
if ( transf ) {
|
||||
/*
|
||||
* transform value by pretty function
|
||||
* if value is empty, use empty_bv
|
||||
*/
|
||||
rc = ( *transf )( ad->ad_type->sat_syntax,
|
||||
ava->la_value.bv_len
|
||||
? &ava->la_value
|
||||
: (struct berval *) &slap_empty_bv,
|
||||
&bv, NULL );
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
snprintf( buf, sizeof(buf),
|
||||
"prettying of attribute #%d from baseObject "
|
||||
"DN \"%s\" failed: %d: %s",
|
||||
iAVA, be->be_suffix[ 0 ].bv_val,
|
||||
rc, ldap_err2string( rc ) );
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<==backsql_db_config (%s line %d): %s\n",
|
||||
fname, lineno, buf );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &bv ) ) {
|
||||
if ( ava->la_flags & LDAP_AVA_FREE_VALUE ) {
|
||||
ber_memfree( ava->la_value.bv_val );
|
||||
}
|
||||
ava->la_value = bv;
|
||||
ava->la_flags |= LDAP_AVA_FREE_VALUE;
|
||||
}
|
||||
|
||||
attr_merge_normalize_one( bi->sql_baseObject,
|
||||
ad, &ava->la_value, NULL );
|
||||
}
|
||||
|
||||
ldap_rdnfree( rdn );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SLAPD_SQL */
|
||||
|
||||
|
@ -29,6 +29,10 @@
|
||||
#include "slap.h"
|
||||
#include "proto-sql.h"
|
||||
|
||||
#ifdef BACKSQL_ARBITRARY_KEY
|
||||
struct berval backsql_baseObject_bv = BER_BVC( BACKSQL_BASEOBJECT_IDSTR );
|
||||
#endif /* BACKSQL_ARBITRARY_KEY */
|
||||
|
||||
backsql_entryID *
|
||||
backsql_free_entryID( backsql_entryID *id, int freeit )
|
||||
{
|
||||
@ -40,15 +44,18 @@ backsql_free_entryID( backsql_entryID *id, int freeit )
|
||||
|
||||
if ( id->eid_dn.bv_val != NULL ) {
|
||||
free( id->eid_dn.bv_val );
|
||||
BER_BVZERO( &id->eid_dn );
|
||||
}
|
||||
|
||||
#ifdef BACKSQL_ARBITRARY_KEY
|
||||
if ( id->eid_id.bv_val ) {
|
||||
free( id->eid_id.bv_val );
|
||||
BER_BVZERO( &id->eid_id );
|
||||
}
|
||||
|
||||
if ( id->eid_keyval.bv_val ) {
|
||||
free( id->eid_keyval.bv_val );
|
||||
BER_BVZERO( &id->eid_keyval );
|
||||
}
|
||||
#endif /* BACKSQL_ARBITRARY_KEY */
|
||||
|
||||
@ -93,9 +100,29 @@ backsql_dn2id(
|
||||
dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN );
|
||||
return LDAP_OTHER;
|
||||
}
|
||||
|
||||
/* return baseObject if available and matches */
|
||||
if ( bi->sql_baseObject != NULL && bvmatch( dn, &bi->sql_baseObject->e_nname ) ) {
|
||||
if ( id != NULL ) {
|
||||
#ifdef BACKSQL_ARBITRARY_KEY
|
||||
ber_dupbv( &id->eid_id, &backsql_baseObject_bv );
|
||||
ber_dupbv( &id->eid_keyval, &backsql_baseObject_bv );
|
||||
#else /* ! BACKSQL_ARBITRARY_KEY */
|
||||
id->eid_id = BACKSQL_BASEOBJECT_ID;
|
||||
id->eid_keyval = BACKSQL_BASEOBJECT_KEYVAL;
|
||||
#endif /* ! BACKSQL_ARBITRARY_KEY */
|
||||
id->eid_oc_id = BACKSQL_BASEOBJECT_OC;
|
||||
|
||||
ber_dupbv( &id->eid_dn, &bi->sql_baseObject->e_nname );
|
||||
|
||||
id->eid_next = NULL;
|
||||
}
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
/* begin TimesTen */
|
||||
Debug(LDAP_DEBUG_TRACE, "id_query \"%s\"\n", bi->sql_id_query, 0, 0);
|
||||
Debug( LDAP_DEBUG_TRACE, "id_query \"%s\"\n", bi->sql_id_query, 0, 0 );
|
||||
assert( bi->sql_id_query );
|
||||
rc = backsql_Prepare( dbh, &sth, bi->sql_id_query, 0 );
|
||||
if ( rc != SQL_SUCCESS ) {
|
||||
@ -405,6 +432,7 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
|
||||
int
|
||||
backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
|
||||
{
|
||||
backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private;
|
||||
int i;
|
||||
int rc;
|
||||
AttributeDescription *ad_oc = slap_schema.si_ad_objectClass;
|
||||
@ -415,6 +443,19 @@ backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid )
|
||||
|
||||
memset( bsi->bsi_e, 0, sizeof( Entry ) );
|
||||
|
||||
if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
|
||||
Entry *e;
|
||||
|
||||
e = entry_dup( bi->sql_baseObject );
|
||||
if ( e == NULL ) {
|
||||
return LDAP_NO_MEMORY;
|
||||
}
|
||||
|
||||
*bsi->bsi_e = *e;
|
||||
free( e );
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = dnPrettyNormal( NULL, &eid->eid_dn,
|
||||
&bsi->bsi_e->e_name, &bsi->bsi_e->e_nname,
|
||||
bsi->bsi_op->o_tmpmemctx );
|
||||
@ -528,6 +569,7 @@ next:;
|
||||
}
|
||||
}
|
||||
|
||||
done:;
|
||||
Debug( LDAP_DEBUG_TRACE, "<==backsql_id2entry()\n", 0, 0, 0 );
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
|
@ -163,6 +163,11 @@ backsql_db_destroy(
|
||||
free( bi->sql_delentry_query );
|
||||
free( bi->sql_delobjclasses_query );
|
||||
free( bi->sql_delreferrals_query );
|
||||
|
||||
if ( bi->sql_baseObject ) {
|
||||
entry_free( bi->sql_baseObject );
|
||||
}
|
||||
|
||||
free( bi );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<==backsql_db_destroy()\n", 0, 0, 0 );
|
||||
|
@ -105,6 +105,9 @@ int backsql_api_odbc2dn( Operation *op, SlapReply *rs, struct berval *dn );
|
||||
/*
|
||||
* entry-id.c
|
||||
*/
|
||||
#ifdef BACKSQL_ARBITRARY_KEY
|
||||
extern struct berval backsql_baseObject_bv;
|
||||
#endif /* BACKSQL_ARBITRARY_KEY */
|
||||
|
||||
/* stores in *id the ID in table ldap_entries corresponding to DN, if any */
|
||||
int backsql_dn2id( backsql_info *bi, backsql_entryID *id,
|
||||
|
@ -184,6 +184,8 @@ backsql_init_search(
|
||||
bsi->bsi_filter_oc = NULL;
|
||||
|
||||
if ( get_base_id ) {
|
||||
assert( op->o_bd->be_private );
|
||||
|
||||
rc = backsql_dn2id( (backsql_info *)op->o_bd->be_private,
|
||||
&bsi->bsi_base_id, dbh, base );
|
||||
}
|
||||
@ -1393,8 +1395,9 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
|
||||
backsql_BindRowAsStrings( sth, &row );
|
||||
rc = SQLFetch( sth );
|
||||
for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) {
|
||||
struct berval dn;
|
||||
struct berval dn, ndn;
|
||||
backsql_entryID *c_id = NULL;
|
||||
int ret;
|
||||
|
||||
ber_str2bv( row.cols[ 3 ], 0, 0, &dn );
|
||||
|
||||
@ -1402,6 +1405,20 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL );
|
||||
if ( dn.bv_val != row.cols[ 3 ] ) {
|
||||
free( dn.bv_val );
|
||||
}
|
||||
|
||||
if ( ret != LDAP_SUCCESS ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( bi->sql_baseObject && bvmatch( &ndn, &bi->sql_baseObject->e_nname ) ) {
|
||||
free( ndn.bv_val );
|
||||
continue;
|
||||
}
|
||||
|
||||
c_id = (backsql_entryID *)ch_calloc( 1,
|
||||
sizeof( backsql_entryID ) );
|
||||
#ifdef BACKSQL_ARBITRARY_KEY
|
||||
@ -1413,10 +1430,10 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi )
|
||||
#endif /* ! BACKSQL_ARBITRARY_KEY */
|
||||
c_id->eid_oc_id = bsi->bsi_oc->bom_id;
|
||||
|
||||
if ( dn.bv_val == row.cols[ 3 ] ) {
|
||||
ber_dupbv( &c_id->eid_dn, &dn );
|
||||
if ( ndn.bv_val == row.cols[ 3 ] ) {
|
||||
ber_dupbv( &c_id->eid_dn, &ndn );
|
||||
} else {
|
||||
c_id->eid_dn = dn;
|
||||
c_id->eid_dn = ndn;
|
||||
}
|
||||
|
||||
/* append at end of list ... */
|
||||
@ -1459,7 +1476,7 @@ backsql_search( Operation *op, SlapReply *rs )
|
||||
Entry user_entry = { 0 };
|
||||
int manageDSAit;
|
||||
time_t stoptime = 0;
|
||||
backsql_srch_info srch_info;
|
||||
backsql_srch_info bsi;
|
||||
backsql_entryID *eid = NULL;
|
||||
struct berval base;
|
||||
|
||||
@ -1504,7 +1521,7 @@ backsql_search( Operation *op, SlapReply *rs )
|
||||
/* compute it anyway; root does not use it */
|
||||
stoptime = op->o_time + op->ors_tlimit;
|
||||
|
||||
base = op->o_req_dn;
|
||||
base = op->o_req_ndn;
|
||||
if ( backsql_api_dn2odbc( op, rs, &base ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
|
||||
"backsql_api_dn2odbc failed\n",
|
||||
@ -1516,7 +1533,7 @@ backsql_search( Operation *op, SlapReply *rs )
|
||||
}
|
||||
|
||||
/* init search */
|
||||
rs->sr_err = backsql_init_search( &srch_info, &base,
|
||||
rs->sr_err = backsql_init_search( &bsi, &base,
|
||||
op->ors_scope,
|
||||
op->ors_slimit, op->ors_tlimit,
|
||||
stoptime, op->ors_filter,
|
||||
@ -1526,20 +1543,47 @@ backsql_search( Operation *op, SlapReply *rs )
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* for each objectclass we try to construct query which gets IDs
|
||||
* of entries matching LDAP query filter and scope (or at least
|
||||
* candidates), and get the IDs
|
||||
*/
|
||||
srch_info.bsi_n_candidates =
|
||||
( op->ors_limit == NULL /* isroot == FALSE */ ? -2 :
|
||||
bsi.bsi_n_candidates =
|
||||
( op->ors_limit == NULL /* isroot == TRUE */ ? -2 :
|
||||
( op->ors_limit->lms_s_unchecked == -1 ? -2 :
|
||||
( op->ors_limit->lms_s_unchecked ) ) );
|
||||
avl_apply( bi->sql_oc_by_oc, backsql_oc_get_candidates,
|
||||
&srch_info, BACKSQL_AVL_STOP, AVL_INORDER );
|
||||
if ( op->ors_limit != NULL /* isroot == TRUE */
|
||||
|
||||
switch ( bsi.bsi_scope ) {
|
||||
case LDAP_SCOPE_BASE:
|
||||
case BACKSQL_SCOPE_BASE_LIKE:
|
||||
/*
|
||||
* probably already found...
|
||||
*/
|
||||
bsi.bsi_id_list = &bsi.bsi_base_id;
|
||||
bsi.bsi_id_listtail = &bsi.bsi_base_id.eid_next;
|
||||
break;
|
||||
|
||||
case LDAP_SCOPE_SUBTREE:
|
||||
/*
|
||||
* if baseObject is defined, and if it is the root
|
||||
* of the search, add it to the candidate list
|
||||
*/
|
||||
if ( bi->sql_baseObject && BACKSQL_IS_BASEOBJECT_ID( &bsi.bsi_base_id.eid_id ) )
|
||||
{
|
||||
bsi.bsi_id_list = &bsi.bsi_base_id;
|
||||
bsi.bsi_id_listtail = &bsi.bsi_base_id.eid_next;
|
||||
}
|
||||
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
|
||||
/*
|
||||
* for each objectclass we try to construct query which gets IDs
|
||||
* of entries matching LDAP query filter and scope (or at least
|
||||
* candidates), and get the IDs
|
||||
*/
|
||||
avl_apply( bi->sql_oc_by_oc, backsql_oc_get_candidates,
|
||||
&bsi, BACKSQL_AVL_STOP, AVL_INORDER );
|
||||
}
|
||||
|
||||
if ( op->ors_limit != NULL /* isroot == FALSE */
|
||||
&& op->ors_limit->lms_s_unchecked != -1
|
||||
&& srch_info.bsi_n_candidates == -1 )
|
||||
&& bsi.bsi_n_candidates == -1 )
|
||||
{
|
||||
rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED;
|
||||
send_ldap_result( op, rs );
|
||||
@ -1549,15 +1593,16 @@ backsql_search( Operation *op, SlapReply *rs )
|
||||
/*
|
||||
* now we load candidate entries (only those attributes
|
||||
* mentioned in attrs and filter), test it against full filter
|
||||
* and then send to client
|
||||
* and then send to client; don't free entry_id if baseObject...
|
||||
*/
|
||||
for ( eid = srch_info.bsi_id_list;
|
||||
for ( eid = bsi.bsi_id_list;
|
||||
eid != NULL;
|
||||
eid = backsql_free_entryID( eid, 1 ) )
|
||||
eid = backsql_free_entryID( eid, eid == &bsi.bsi_base_id ? 0 : 1 ) )
|
||||
{
|
||||
int rc;
|
||||
Attribute *hasSubordinate = NULL,
|
||||
*a = NULL;
|
||||
Entry *e = NULL;
|
||||
|
||||
/* check for abandon */
|
||||
if ( op->o_abandon ) {
|
||||
@ -1588,20 +1633,28 @@ backsql_search( Operation *op, SlapReply *rs )
|
||||
eid->eid_id, eid->eid_oc_id, eid->eid_keyval );
|
||||
#endif /* ! BACKSQL_ARBITRARY_KEY */
|
||||
|
||||
srch_info.bsi_e = &user_entry;
|
||||
rc = backsql_id2entry( &srch_info, eid );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
|
||||
"error %d in backsql_id2entry() "
|
||||
"- skipping\n", rc, 0, 0 );
|
||||
continue;
|
||||
/* don't recollect baseObject ... */
|
||||
if ( BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) {
|
||||
e = bi->sql_baseObject;
|
||||
|
||||
} else {
|
||||
bsi.bsi_e = &user_entry;
|
||||
rc = backsql_id2entry( &bsi, eid );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
|
||||
"error %d in backsql_id2entry() "
|
||||
"- skipping\n", rc, 0, 0 );
|
||||
continue;
|
||||
}
|
||||
|
||||
e = &user_entry;
|
||||
}
|
||||
|
||||
/* check scope */
|
||||
switch ( op->ors_scope ) {
|
||||
case LDAP_SCOPE_BASE:
|
||||
case BACKSQL_SCOPE_BASE_LIKE:
|
||||
if ( !bvmatch( &user_entry.e_nname, &op->o_req_ndn ) ) {
|
||||
if ( !bvmatch( &e->e_nname, &op->o_req_ndn ) ) {
|
||||
goto next_entry;
|
||||
}
|
||||
break;
|
||||
@ -1617,7 +1670,7 @@ backsql_search( Operation *op, SlapReply *rs )
|
||||
}
|
||||
|
||||
case LDAP_SCOPE_SUBTREE:
|
||||
if ( !dnIsSuffix( &user_entry.e_nname, &op->o_req_ndn ) ) {
|
||||
if ( !dnIsSuffix( &e->e_nname, &op->o_req_ndn ) ) {
|
||||
goto next_entry;
|
||||
}
|
||||
break;
|
||||
@ -1626,23 +1679,23 @@ backsql_search( Operation *op, SlapReply *rs )
|
||||
if ( !manageDSAit &&
|
||||
op->ors_scope != LDAP_SCOPE_BASE &&
|
||||
op->ors_scope != BACKSQL_SCOPE_BASE_LIKE &&
|
||||
is_entry_referral( &user_entry ) )
|
||||
is_entry_referral( e ) )
|
||||
{
|
||||
BerVarray refs;
|
||||
|
||||
refs = get_entry_referrals( op, &user_entry );
|
||||
refs = get_entry_referrals( op, e );
|
||||
if ( !refs ) {
|
||||
backsql_srch_info srch_info2 = { 0 };
|
||||
backsql_srch_info bsi2 = { 0 };
|
||||
Entry user_entry2 = { 0 };
|
||||
|
||||
/* retry with the full entry... */
|
||||
(void)backsql_init_search( &srch_info2,
|
||||
&user_entry.e_name,
|
||||
(void)backsql_init_search( &bsi2,
|
||||
&e->e_nname,
|
||||
LDAP_SCOPE_BASE,
|
||||
-1, -1, -1, NULL,
|
||||
dbh, op, rs, NULL, 0 );
|
||||
srch_info2.bsi_e = &user_entry2;
|
||||
rc = backsql_id2entry( &srch_info2, eid );
|
||||
bsi2.bsi_e = &user_entry2;
|
||||
rc = backsql_id2entry( &bsi2, eid );
|
||||
if ( rc == LDAP_SUCCESS ) {
|
||||
if ( is_entry_referral( &user_entry2 ) )
|
||||
{
|
||||
@ -1655,7 +1708,7 @@ backsql_search( Operation *op, SlapReply *rs )
|
||||
|
||||
if ( refs ) {
|
||||
rs->sr_ref = referral_rewrite( refs,
|
||||
&user_entry.e_name,
|
||||
&e->e_name,
|
||||
&op->o_req_dn,
|
||||
op->ors_scope );
|
||||
ber_bvarray_free( refs );
|
||||
@ -1681,8 +1734,8 @@ backsql_search( Operation *op, SlapReply *rs )
|
||||
* anyway; we should have used the frontend API function
|
||||
* filter_has_subordinates()
|
||||
*/
|
||||
if ( srch_info.bsi_flags & BSQL_SF_FILTER_HASSUBORDINATE ) {
|
||||
rc = backsql_has_children( bi, dbh, &user_entry.e_nname );
|
||||
if ( bsi.bsi_flags & BSQL_SF_FILTER_HASSUBORDINATE ) {
|
||||
rc = backsql_has_children( bi, dbh, &e->e_nname );
|
||||
|
||||
switch ( rc ) {
|
||||
case LDAP_COMPARE_TRUE:
|
||||
@ -1708,9 +1761,9 @@ backsql_search( Operation *op, SlapReply *rs )
|
||||
}
|
||||
}
|
||||
|
||||
if ( test_filter( op, &user_entry, op->ors_filter )
|
||||
if ( test_filter( op, e, op->ors_filter )
|
||||
== LDAP_COMPARE_TRUE ) {
|
||||
if ( hasSubordinate && !( srch_info.bsi_flags & BSQL_SF_ALL_OPER )
|
||||
if ( hasSubordinate && !( bsi.bsi_flags & BSQL_SF_ALL_OPER )
|
||||
&& !ad_inlist( slap_schema.si_ad_hasSubordinates, op->ors_attrs ) ) {
|
||||
a->a_next = NULL;
|
||||
attr_free( hasSubordinate );
|
||||
@ -1719,8 +1772,10 @@ backsql_search( Operation *op, SlapReply *rs )
|
||||
|
||||
rs->sr_attrs = op->ors_attrs;
|
||||
rs->sr_operational_attrs = NULL;
|
||||
rs->sr_entry = &user_entry;
|
||||
rs->sr_flags = REP_ENTRY_MODIFIABLE;
|
||||
rs->sr_entry = e;
|
||||
if ( e == &user_entry ) {
|
||||
rs->sr_flags = REP_ENTRY_MODIFIABLE;
|
||||
}
|
||||
sres = send_search_entry( op, rs );
|
||||
rs->sr_entry = NULL;
|
||||
rs->sr_attrs = NULL;
|
||||
@ -1764,7 +1819,7 @@ end_of_search:;
|
||||
: LDAP_REFERRAL;
|
||||
|
||||
} else {
|
||||
rs->sr_err = srch_info.bsi_status;
|
||||
rs->sr_err = bsi.bsi_status;
|
||||
}
|
||||
send_ldap_result( op, rs );
|
||||
|
||||
@ -1774,12 +1829,12 @@ end_of_search:;
|
||||
}
|
||||
|
||||
done:;
|
||||
if ( !BER_BVISNULL( &srch_info.bsi_base_id.eid_dn ) ) {
|
||||
(void)backsql_free_entryID( &srch_info.bsi_base_id, 0 );
|
||||
if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_dn ) ) {
|
||||
(void)backsql_free_entryID( &bsi.bsi_base_id, 0 );
|
||||
}
|
||||
|
||||
if ( srch_info.bsi_attrs ) {
|
||||
ch_free( srch_info.bsi_attrs );
|
||||
if ( bsi.bsi_attrs ) {
|
||||
ch_free( bsi.bsi_attrs );
|
||||
}
|
||||
|
||||
if ( base.bv_val != op->o_req_ndn.bv_val ) {
|
||||
|
Loading…
Reference in New Issue
Block a user