Includes support for update referral for each replicated backend.
Reworked replication test to use update referral.
Includes major rewrite of response encoding codes (result.c).
Includes reworked alias support and eliminates old suffix alias codes
(can be emulated using named alias).
Includes (untested) support for the Manage DSA IT control.
Works in LDAPv2 world. Still testing in LDAPv3 world.
Added default referral (test009) test.
Begin Project Dependency
Project_Dep_Name libldbm
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name backldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libslapd
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldap_r
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
}}}
###############################################################################
Package=<4>
{{{
+ Begin Project Dependency
+ Project_Dep_Name backldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldap_r
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldbm
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libslapd
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libavl
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldif
+ End Project Dependency
}}}
###############################################################################
int
main( int argc, char **argv )
{
- char *usage = "usage: %s [-n] [-v] [-k] [-W] [-d debug-level] [-f file] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [dn]...\n";
+ char *usage = "usage: %s [-n] [-v] [-k] [-W] [-M[M]] [-d debug-level] [-f file] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [dn]...\n";
char buf[ 4096 ];
FILE *fp;
- int i, rc, authmethod, want_bindpw, version, debug;
+ int i, rc, authmethod, want_bindpw, version, debug, manageDSAit;
- not = verbose = contoper = want_bindpw = debug = 0;
+ not = verbose = contoper = want_bindpw = debug = manageDSAit = 0;
fp = NULL;
authmethod = LDAP_AUTH_SIMPLE;
version = -1;
- while (( i = getopt( argc, argv, "WnvkKch:P:p:D:w:d:f:" )) != EOF ) {
+ while (( i = getopt( argc, argv, "WMnvkKch:P:p:D:w:d:f:" )) != EOF ) {
switch( i ) {
case 'k': /* kerberos bind */
#ifdef HAVE_KERBEROS
case 'v': /* verbose mode */
verbose++;
break;
+ case 'M':
+ /* enable Manage DSA IT */
+ manageDSAit++;
+ break;
case 'W':
want_bindpw++;
break;
return( EXIT_FAILURE );
}
+ if ( manageDSAit ) {
+ int err;
+ LDAPControl c;
+ LDAPControl *ctrls[2];
+ ctrls[0] = &c;
+ ctrls[1] = NULL;
+
+ c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+ c.ldctl_value.bv_val = NULL;
+ c.ldctl_value.bv_len = 0;
+ c.ldctl_iscritical = manageDSAit > 1;
+
+ err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
+
+ if( err != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set Manage DSA IT Control\n" );
+ if( c.ldctl_iscritical ) {
+ exit( EXIT_FAILURE );
+ }
+ }
+ }
+
if ( fp == NULL ) {
for ( ; optind < argc; ++optind ) {
rc = dodelete( ld, argv[ optind ] );
{
fprintf( stderr,
"Add or modify entries from an LDAP server\n\n"
- "usage: %s [-abcknrvF] [-d debug-level] [-P version] [-h ldaphost]\n"
+ "usage: %s [-abcknrvF] [-M[M]] [-d debug-level] [-P version] [-h ldaphost]\n"
" [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile ]\n"
" a - add values (default%s)\n"
" b - read values from files (for binary attributes)\n"
" c - continuous operation\n"
" D - bind DN\n"
+ " M - enable Manage DSA IT control (-MM for critical)\n"
" d - debug level\n"
" f - read from file\n"
" F - force all changes records to be used\n"
{
char *infile, *rbuf, *start, *p, *q;
FILE *fp;
- int rc, i, use_ldif, authmethod, version, want_bindpw, debug;
+ int rc, i, use_ldif, authmethod, version, want_bindpw, debug, manageDSAit;
if (( prog = strrchr( argv[ 0 ], *LDAP_DIRSEP )) == NULL ) {
prog = argv[ 0 ];
new = ( strcmp( prog, "ldapadd" ) == 0 );
infile = NULL;
- not = verbose = valsfromfiles = want_bindpw = debug = 0;
+ not = verbose = valsfromfiles = want_bindpw = debug = manageDSAit = 0;
authmethod = LDAP_AUTH_SIMPLE;
version = -1;
- while (( i = getopt( argc, argv, "WFabckKnrtvh:p:D:w:d:f:P:" )) != EOF ) {
+ while (( i = getopt( argc, argv, "WFMabckKnrtvh:p:D:w:d:f:P:" )) != EOF ) {
switch( i ) {
case 'a': /* add */
new = 1;
case 'v': /* verbose mode */
verbose++;
break;
+ case 'M':
+ /* enable Manage DSA IT */
+ manageDSAit++;
+ break;
case 'W':
want_bindpw++;
break;
rc = 0;
+ if ( manageDSAit ) {
+ int err;
+ LDAPControl c;
+ LDAPControl *ctrls[2];
+ ctrls[0] = &c;
+ ctrls[1] = NULL;
+
+ c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+ c.ldctl_value.bv_val = NULL;
+ c.ldctl_value.bv_len = 0;
+ c.ldctl_iscritical = manageDSAit > 1;
+
+ err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
+
+ if( err != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set Manage DSA IT Control\n" );
+ if( c.ldctl_iscritical ) {
+ exit( EXIT_FAILURE );
+ }
+ }
+ }
+
while (( rc == 0 || contoper ) &&
( rbuf = read_one_record( fp )) != NULL ) {
/*
int
main(int argc, char **argv)
{
- char *usage = "usage: %s [-nvkWc] [-d debug-level] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile | dn newrdn ] [-s newSuperior]\n";
+ char *usage = "usage: %s [-nvkWc] [-M[M]] [-d debug-level] [-h ldaphost] [-P version] [-p ldapport] [-D binddn] [-w passwd] [ -f file | < entryfile | dn newrdn ] [-s newSuperior]\n";
char *myname,*infile, *entrydn, *rdn, buf[ 4096 ];
FILE *fp;
- int rc, i, remove, havedn, authmethod, version, want_bindpw, debug;
+ int rc, i, remove, havedn, authmethod, version, want_bindpw, debug, manageDSAit;
char *newSuperior=NULL;
infile = NULL;
- not = contoper = verbose = remove = want_bindpw = debug = 0;
+ not = contoper = verbose = remove = want_bindpw = debug = manageDSAit = 0;
authmethod = LDAP_AUTH_SIMPLE;
version = -1;
myname = (myname = strrchr(argv[0], '/')) == NULL ? argv[0] : ++myname;
- while (( i = getopt( argc, argv, "WkKcnvrh:P:p:D:w:d:f:s:" )) != EOF ) {
+ while (( i = getopt( argc, argv, "WkKMcnvrh:P:p:D:w:d:f:s:" )) != EOF ) {
switch( i ) {
case 'k': /* kerberos bind */
#ifdef HAVE_KERBEROS
case 'r': /* remove old RDN */
remove++;
break;
+ case 'M':
+ /* enable Manage DSA IT */
+ manageDSAit++;
+ break;
case 'W':
want_bindpw++;
break;
return( EXIT_FAILURE );
}
+ if ( manageDSAit ) {
+ int err;
+ LDAPControl c;
+ LDAPControl *ctrls[2];
+ ctrls[0] = &c;
+ ctrls[1] = NULL;
+
+ c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+ c.ldctl_value.bv_val = NULL;
+ c.ldctl_value.bv_len = 0;
+ c.ldctl_iscritical = manageDSAit > 1;
+
+ err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
+
+ if( err != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set Manage DSA IT Control\n" );
+ if( c.ldctl_iscritical ) {
+ exit( EXIT_FAILURE );
+ }
+ }
+ }
+
rc = 0;
if (havedn)
rc = domodrdn(ld, entrydn, rdn, remove, newSuperior);
fprintf( stderr, "usage: %s [options] filter [attributes...]\nwhere:\n", s );
fprintf( stderr, " filter\tRFC-1558 compliant LDAP search filter\n" );
fprintf( stderr, " attributes\twhitespace-separated list of attributes to retrieve\n" );
- fprintf( stderr, "\t\t(if no attribute list is given, all are retrieved)\n" );
+ fprintf( stderr, "\t\t* -- all user attributes\n" );
+ fprintf( stderr, "\t\tempty list -- all non-operational attributes\n" );
+ fprintf( stderr, "\t\t1.1 -- no attributes\n" );
fprintf( stderr, "options:\n" );
fprintf( stderr, " -n\t\tshow what would be done but don't actually search\n" );
fprintf( stderr, " -v\t\trun in verbose mode (diagnostics to standard output)\n" );
fprintf( stderr, " -A\t\tretrieve attribute names only (no values)\n" );
fprintf( stderr, " -B\t\tdo not suppress printing of non-ASCII values\n" );
fprintf( stderr, " -L\t\tprint entries in LDIF format (-B is implied)\n" );
-#ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
+ fprintf( stderr, " -M\t\tenable Manage DSA IT control (-MM implies critical)\n" );
fprintf( stderr, " -R\t\tdo not automatically follow referrals\n" );
-#endif /* LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS */
fprintf( stderr, " -d level\tset LDAP debugging level to `level'\n" );
fprintf( stderr, " -F sep\tprint `sep' instead of `=' between attribute names and values\n" );
fprintf( stderr, " -S attr\tsort the results by attribute `attr'\n" );
{
char *infile, *filtpattern, **attrs, line[ BUFSIZ ];
FILE *fp;
- int rc, i, first, scope, deref, attrsonly;
+ int rc, i, first, scope, deref, attrsonly, manageDSAit;
int referrals, timelimit, sizelimit, debug;
int authmethod, version, want_bindpw;
LDAP *ld;
infile = NULL;
debug = verbose = allow_binary = not = vals2tmp =
- attrsonly = ldif = want_bindpw = 0;
+ attrsonly = manageDSAit = ldif = want_bindpw = 0;
deref = referrals = sizelimit = timelimit = version = -1;
scope = LDAP_SCOPE_SUBTREE;
authmethod = LDAP_AUTH_SIMPLE;
- while (( i = getopt( argc, argv, "WKknuvtRABLD:s:f:h:b:d:P:p:F:a:w:l:z:S:")) != EOF ) {
+ while (( i = getopt( argc, argv, "WKknuvtMRABLD:s:f:h:b:d:P:p:F:a:w:l:z:S:")) != EOF ) {
switch( i ) {
case 'n': /* do Not do any searches */
++not;
case 't': /* write attribute values to /tmp files */
++vals2tmp;
break;
+ case 'M':
+ /* enable Manage DSA IT */
+ manageDSAit++;
+ break;
case 'R': /* don't automatically chase referrals */
referrals = (int) LDAP_OPT_OFF;
break;
fprintf( stderr, "\n" );
}
+ if ( manageDSAit ) {
+ int err;
+ LDAPControl c;
+ LDAPControl *ctrls[2];
+ ctrls[0] = &c;
+ ctrls[1] = NULL;
+
+ c.ldctl_oid = LDAP_CONTROL_MANAGEDSAIT;
+ c.ldctl_value.bv_val = NULL;
+ c.ldctl_value.bv_len = 0;
+ c.ldctl_iscritical = manageDSAit > 1;
+
+ err = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &ctrls );
+
+ if( err != LDAP_OPT_SUCCESS ) {
+ fprintf( stderr, "Could not set Manage DSA IT Control\n" );
+ if( c.ldctl_iscritical ) {
+ exit( EXIT_FAILURE );
+ }
+ }
+ }
+
if ( infile == NULL ) {
rc = dosearch( ld, base, scope, attrs, attrsonly, filtpattern, "" );
} else {
[\c
.BR \-c ]
[\c
+.BR \-M[M] ]
+[\c
.BI \-d \ debuglevel\fR]
[\c
.BI \-f \ file\fR]
will continue with deletions. The default is to exit after
reporting an error.
.TP
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
.BI \-d \ debuglevel
Set the LDAP debugging level to \fIdebuglevel\fP.
.B ldapdelete
[\c
.BR \-k ]
[\c
+.BR \-M[M] ]
+[\c
.BI \-d \ debuglevel\fR]
[\c
.BI \-D \ binddn\fR]
(by default, replica: lines are compared against the LDAP server host
and port in use to decide if a replog record should actually be applied).
.TP
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
.BI \-d \ debuglevel
Set the LDAP debugging level to \fIdebuglevel\fP.
.B ldapmodify
[\c
.BR \-c ]
[\c
+.BR \-M[M] ]
+[\c
.BI \-d \ debuglevel\fR]
[\c
.BI \-D \ binddn\fR]
will continue with modifications. The default is to exit after
reporting an error.
.TP
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
.B \-d debuglevel
Set the LDAP debugging level to \fIdebuglevel\fP.
.B ldapmodrdn
[\c
.BR \-L ]
[\c
+.BR \-M[M] ]
+[\c
.BR \-R ]
[\c
.BI \-d \ debuglevel\fR]
format. This option also turns on the -B option, and causes the -F option
to be ignored.
.TP
+.B \-M[M]
+Enable manage DSA IT control.
+.B \-MM
+makes control critical.
+.TP
.B \-R
Do not automatically follow referrals returned while searching.
.B ldapsearch
Specify the referral to pass back when
.BR slapd (8)
cannot find a local database to handle a request.
+If specified multiple times, each url is provided.
.TP
.B schemacheck { on | off }
Turn schema checking on or off. The default is on.
this is the DN
.BR slurpd (8)
binds as when making changes to the replica).
+.TP
+.B updateref <url>
+Specify the referral to pass back when
+.BR slapd (8)
+is asked to modify a replicated local database.
+If specified multiple times, each url is provided.
.SH LDBM BACKEND-SPECIFIC OPTIONS
Options in this category only apply to the LDBM backend database. That is,
they must follow a "database ldbm" line and come before any subsequent
#define LDAP_CHASE_SUBORDINATE_REFERRALS 0x0020
#define LDAP_CHASE_EXTERNAL_REFERRALS 0x0040
+#define LDAP_CONTROL_MANAGEDSAIT "2.16.16.840.1.113730.3.4.2"
+
/* LDAP Unsolicited Notifications */
#define LDAP_NOTICE_DISCONNECT "1.3.6.1.4.1.1466.20036"
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"..\Debug\oldbm32.lib"
-# ADD LIB32 /nologo /out:"..\Debug\oldbm32.lib"
+# ADD LIB32 /nologo /out:"..\SDebug\oldbm32.lib"
!ELSEIF "$(CFG)" == "libldbm - Win32 Single Release"
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo /out:"..\Release\oldbm32.lib"
-# ADD LIB32 /nologo /out:"..\Release\oldbm32.lib"
+# ADD LIB32 /nologo /out:"..\SRelease\oldbm32.lib"
!ENDIF
value.c ava.c bind.c unbind.c abandon.c filterentry.c \
phonetic.c acl.c str2filter.c aclparse.c init.c user.c \
repl.c lock.c controls.c extended.c \
- suffixalias.c schema.c schemaparse.c monitor.c configinfo.c \
+ schema.c schemaparse.c monitor.c configinfo.c \
root_dse.c module.c
OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.o \
attr.o entry.o config.o backend.o result.o operation.o \
value.o ava.o bind.o unbind.o abandon.o filterentry.o \
phonetic.o acl.o str2filter.o aclparse.o init.o user.o \
repl.o lock.o controls.o extended.o \
- suffixalias.o schema.o schemaparse.o monitor.o configinfo.o \
+ schema.o schemaparse.o monitor.o configinfo.o \
root_dse.o module.o
LDAP_INCDIR= ../../include
ber_int_t id;
Operation *o;
Operation **oo;
- int rc;
+ int rc, notfound;
Debug( LDAP_DEBUG_TRACE, "do_abandon\n", 0, 0, 0 );
Debug( LDAP_DEBUG_ARGS, "do_abandon: id %d\n", id, 0 ,0 );
+ if( id <= 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "do_abandon: bad msgid %ld\n", (long) id, 0, 0 );
+ return LDAP_SUCCESS;
+ }
+
+ notfound = 1; /* not found */
+ ldap_pvt_thread_mutex_lock( &conn->c_mutex );
/*
* find the operation being abandoned and set the o_abandon
* flag. It's up to the backend to periodically check this
* flag and abort the operation at a convenient time.
*/
- ldap_pvt_thread_mutex_lock( &conn->c_mutex );
-
for ( o = conn->c_ops; o != NULL; o = o->o_next ) {
if ( o->o_msgid == id ) {
ldap_pvt_thread_mutex_lock( &o->o_abandonmutex );
o->o_abandon = 1;
ldap_pvt_thread_mutex_unlock( &o->o_abandonmutex );
- goto found_it;
+ notfound = 0;
+ goto done;
}
}
o = *oo;
*oo = (*oo)->o_next;
slap_op_free( o );
-
- goto found_it;
+ notfound = 0;
}
- Debug( LDAP_DEBUG_TRACE, "do_abandon: op not found\n", 0, 0, 0 );
-
-found_it:
+done:
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
+
+ Debug( LDAP_DEBUG_TRACE, "do_abandon: op=%ld %sfound\n",
+ id, notfound ? "not " : "", 0 );
+
return LDAP_SUCCESS;
}
strcat( buf, "read" );
} else if ( ACL_IS_WRITE(access) ) {
strcat( buf, "write" );
+
} else {
strcat( buf, "unknown" );
}
if( op->o_bind_in_progress ) {
Debug( LDAP_DEBUG_ANY, "do_add: SASL bind in progress.\n", 0, 0, 0 );
send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
- "SASL bind in progress" );
+ "SASL bind in progress", NULL, NULL );
return LDAP_SASL_BIND_IN_PROGRESS;
}
if ( vals == NULL ) {
Debug( LDAP_DEBUG_ANY, "no values for type %s\n", type,
0, 0 );
- send_ldap_result( conn, op,
- LDAP_PROTOCOL_ERROR, NULL, "no values for type" );
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ NULL, "no values for type", NULL, NULL );
free( type );
entry_free( e );
return LDAP_PROTOCOL_ERROR;
be = select_backend( e->e_ndn );
if ( be == NULL ) {
entry_free( e );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, LDAP_REFERRAL, NULL,
+ NULL, default_referral, NULL );
return rc;
}
} else {
entry_free( e );
- send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
+ be->be_update_refs ? be->be_update_refs : default_referral, NULL );
}
} else {
Debug( LDAP_DEBUG_ARGS, " do_add: HHH\n", 0, 0, 0 );
entry_free( e );
- send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
return rc;
if ( ( bdb2i_dn2id( be, e->e_ndn ) ) != NOID ) {
entry_free( e );
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+ NULL, NULL, NULL, NULL );
return( -1 );
}
0, 0, 0 );
entry_free( e );
- send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, "",
- "" );
+ send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+ NULL, NULL, NULL, NULL );
return( -1 );
}
pdn = dn_parent( be, e->e_ndn );
if( pdn != NULL && *pdn != '\0' && !be_issuffix(be, "") ) {
- char *matched = NULL;
+ Entry *matched = NULL;
assert( *pdn != '\0' );
/* get parent with writer lock */
if ( (p = bdb2i_dn2entry_w( be, pdn, &matched )) == NULL ) {
- Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
- 0, 0 );
+ char *matched_dn;
+ struct berval **refs;
+
+ if( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+
+ bdb2i_cache_return_entry_w( &li->li_cache, matched );
+
+ } else {
+ matched_dn = NULL;
+ refs = default_referral;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
+ 0, 0, 0 );
+
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- matched, "" );
+ matched_dn, NULL, NULL, NULL );
if ( matched != NULL ) {
- free( matched );
+ ber_bvecfree( refs );
+ free( matched_dn );
}
entry_free( e );
free(pdn);
- if ( matched != NULL ) {
- free( matched );
- }
-
if ( ! access_allowed( be, conn, op, p,
"children", NULL, ACL_WRITE ) )
{
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
+ NULL, NULL, NULL, NULL );
+
+ entry_free( e );
+ return -1;
+ }
+
+
+ if ( is_entry_alias( p ) ) {
+ /* parent is an alias, don't allow add */
+
+ /* free parent and writer lock */
+ bdb2i_cache_return_entry_w( &li->li_cache, p );
+
+ Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, NULL, NULL, NULL );
+
+ entry_free( e );
+ return -1;
+ }
+
+ if ( is_entry_referral( p ) ) {
+ /* parent is an referral, don't allow add */
+ char *matched_dn = ch_strdup( matched->e_dn );
+ struct berval **refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
/* free parent and writer lock */
bdb2i_cache_return_entry_w( &li->li_cache, p );
+ Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ free( matched_dn );
entry_free( e );
return -1;
}
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
+ NULL, NULL, NULL, NULL );
entry_free( e );
return -1;
/* free the entry */
entry_free( e );
- if(rc > 0) {
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
- } else {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- }
+ send_ldap_result( conn, op,
+ rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return( -1 );
}
if ( bdb2i_id2children_add( be, p, e ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "bdb2i_id2children_add failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2CHILDREN", conn, op );
if ( bdb2i_index_add_entry( be, e ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "bdb2i_index_add_entry failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
bdb2i_stop_timing( be->bd_info, time1, "ADD-INDEX", conn, op );
if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "bdb2i_dn2id_add failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
bdb2i_stop_timing( be->bd_info, time1, "ADD-DN2ID", conn, op );
Debug( LDAP_DEBUG_TRACE, "bdb2i_id2entry_add failed\n", 0,
0, 0 );
(void) bdb2i_dn2id_delete( be, e->e_ndn );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
bdb2i_stop_timing( be->bd_info, time1, "ADD-ID2ENTRY", conn, op );
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
rc = 0;
return_results:;
bdb2i_start_timing( be->bd_info, &time1 );
if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
-
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return( -1 );
-
}
/* check, if a new default attribute index will be created,
/*
- * Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to ITSD, Government of BC. The name of ITSD
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
#include "portable.h"
#include "back-bdb2.h"
#include "proto-back-bdb2.h"
-/*
- * given an alias object, dereference it to its end point.
- * Entry returned has reader lock or is NULL. Starting entry is not released.
- */
-Entry *bdb2i_derefAlias_r ( BackendDB *be,
- Connection *conn,
- Operation *op,
- Entry *e)
+static char* get_alias_dn(
+ Entry *e,
+ int *err,
+ char **errmsg );
+
+static char* new_superior(
+ char *dn,
+ char *oldSup,
+ char *newSup );
+
+static int dnlist_subordinate(
+ char** dnlist,
+ char *dn );
+
+Entry *bdb2i_deref_r(
+ Backend* be,
+ Entry* alias,
+ char* dn,
+ int* err,
+ Entry** matched,
+ char** text )
{
- /* to free cache entries */
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Attribute *a;
- int depth;
- char *matched;
- Entry *origDN = e;
-
- if (!e) return NULL; /* be sure we have a starting entry */
-
- Debug( LDAP_DEBUG_TRACE, "<= checking for alias for dn %s\n", e->e_dn, 0, 0 );
-
- /*
- * try to deref fully, up to a maximum depth. If the max depth exceeded
- * then send an error
- */
- for ( depth = 0;
- ( ( a = attr_find( e->e_attrs, "aliasedobjectname" ) ) != NULL) &&
- ( depth < be->be_maxDerefDepth );
- ++depth)
- {
-
- /*
- * make sure there is a defined aliasedobjectname.
- * can only have one value so just use first value (0) in the attr list.
- */
- if (a->a_vals[0] && a->a_vals[0]->bv_val) {
- char *newDN, *oldDN;
-
- Debug( LDAP_DEBUG_TRACE, "<= %s is an alias for %s\n",
- e->e_dn, a->a_vals[0]->bv_val, 0 );
- newDN = ch_strdup (a->a_vals[0]->bv_val);
- oldDN = ch_strdup (e->e_ndn);
-
- /*
- * release past lock if not original
- */
- if ( (depth > 0) && e ) {
- bdb2i_cache_return_entry_r(&li->li_cache, e);
- }
-
- /* make sure new and old DN are not same to avoid loops */
- dn_normalize_case (newDN);
- if ( strcmp (newDN, oldDN) == 0 ) {
-
- Debug( LDAP_DEBUG_TRACE,
- "<= %s alias is same as current %s\n",
- oldDN, newDN, 0 );
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
- "Circular alias" );
- free (newDN);
- free (oldDN);
- break;
- }
-
- /* make sure new and original are not same to avoid deadlocks */
- if ( strcmp (newDN, origDN->e_ndn) == 0 ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= %s alias is same as original %s\n",
- oldDN, origDN->e_ndn, 0 );
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
- "Circular alias" );
- free (newDN);
- free (oldDN);
- break;
- }
-
- /*
- * ok, so what happens if there is an alias in the DN of a dereferenced
- * alias object?
- */
- if ( (e = bdb2i_dn2entry_r( be, newDN, &matched )) == NULL ) {
-
- /* could not deref return error */
- Debug( LDAP_DEBUG_TRACE,
- "<= %s is a dangling alias to %s\n",
- oldDN, newDN, 0 );
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
- "Dangling Alias" );
-
- if(matched != NULL) free(matched);
- free (newDN);
- free (oldDN);
- break;
- }
-
- free (newDN);
- free (oldDN);
- }
- else {
- /*
- * there was an aliasedobjectname defined but no data.
- * this can't happen, right?
- */
- Debug( LDAP_DEBUG_TRACE,
- "<= %s has no data in aliasedobjectname attribute\n",
- (e && e->e_dn) ? e->e_dn : "(null)", 0, 0 );
- send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
- "Alias missing aliasedobjectname" );
- break;
- }
- }
-
- /*
- * warn if we pulled out due to exceeding the maximum deref depth
- */
- if ( depth >= be->be_maxDerefDepth ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= deref(\"%s\") exceeded maximum deref depth (%d) at \"%s\"\n",
- origDN->e_dn ? origDN->e_dn : "(null)",
- be->be_maxDerefDepth,
- (e && e->e_ndn) ? e->e_ndn : "(null)");
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
- "Maximum alias dereference depth exceeded" );
- }
-
- return e;
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Entry *entry;
+ Entry *sup;
+ unsigned depth;
+ char **dnlist;
+
+ assert( ( alias != NULL && dn == NULL ) || ( alias == NULL && dn != NULL ) );
+
+ *matched = NULL;
+ *err = LDAP_SUCCESS;
+ *text = NULL;
+
+ if( alias == NULL ) {
+ dn = ch_strdup( dn );
+ entry = bdb2i_dn2entry_r( be, dn, &sup );
+
+ } else {
+ dn = ch_strdup( alias->e_ndn );
+ entry = alias;
+ sup = NULL;
+ }
+
+ dnlist = NULL;
+ charray_add( &dnlist, dn );
+
+ for( depth=0 ; ; depth++ ) {
+ if( entry != NULL ) {
+ Entry *newe;
+ char *aliasDN;
+
+ /* have entry, may be an alias */
+
+ if( !is_entry_alias( entry ) ) {
+ /* entry is not an alias */
+ break;
+ }
+
+ /* entry is alias */
+ if( depth > be->be_max_deref_depth ) {
+ *matched = entry;
+ entry = NULL;
+ *err = LDAP_ALIAS_DEREF_PROBLEM;
+ *text = "maximum deref depth exceeded";
+ break;
+ }
+
+ /* deref entry */
+ aliasDN = get_alias_dn( entry, err, text );
+
+ if( aliasDN == NULL ) {
+ *matched = entry;
+ entry = NULL;
+ break;
+ }
+
+ /* check if aliasDN is a subordinate of any DN in our list */
+ if( dnlist_subordinate( dnlist, aliasDN ) ) {
+ *matched = entry;
+ entry = NULL;
+ *err = LDAP_ALIAS_PROBLEM;
+ *text = "circular alias";
+ break;
+ }
+
+ /* attempt to dereference alias */
+
+ newe = bdb2i_dn2entry_r( be, aliasDN, &sup );
+
+ if( newe != NULL ) {
+ free( dn );
+ bdb2i_cache_return_entry_r(&li->li_cache, entry );
+ entry = newe;
+ dn = ch_strdup( entry->e_ndn );
+ charray_add( &dnlist, dn );
+ continue;
+
+ }
+
+ if ( sup != NULL ) {
+ bdb2i_cache_return_entry_r(&li->li_cache, entry );
+ entry = NULL;
+ continue;
+ }
+
+ /* no newe and no superior, we're done */
+ break;
+
+ } else if( sup != NULL ) {
+ /* have superior, may be an alias */
+ Entry *newe;
+ Entry *newSup;
+ char *supDN;
+ char *aliasDN;
+
+ if( !is_entry_alias( sup ) ) {
+ /* entry is not an alias */
+ *matched = sup;
+ sup = NULL;
+ break;
+ }
+
+ /* entry is alias */
+ if( depth > be->be_max_deref_depth ) {
+ *matched = sup;
+ entry = NULL;
+ *err = LDAP_ALIAS_DEREF_PROBLEM;
+ *text = "maximum deref depth exceeded";
+ break;
+ }
+
+ /* deref entry */
+ supDN = get_alias_dn( sup, err, text );
+
+ if( supDN == NULL ) {
+ *matched = sup;
+ break;
+ }
+
+ aliasDN = new_superior( dn, sup->e_ndn, supDN );
+
+ if( aliasDN == NULL ) {
+ free(aliasDN);
+ *matched = sup;
+ *err = LDAP_ALIAS_PROBLEM;
+ *text = "superior alias problem";
+ break;
+ }
+
+ /* check if aliasDN is a subordinate of any DN in our list */
+ if( dnlist_subordinate( dnlist, aliasDN ) ) {
+ free(aliasDN);
+ *matched = entry;
+ entry = NULL;
+ *err = LDAP_ALIAS_PROBLEM;
+ *text = "subordinate circular alias";
+ break;
+ }
+
+ /* attempt to dereference alias */
+ newe = bdb2i_dn2entry_r( be, aliasDN, &newSup );
+
+ if( newe != NULL ) {
+ free(aliasDN);
+ free( dn );
+ bdb2i_cache_return_entry_r(&li->li_cache, sup );
+ entry = newe;
+ dn = ch_strdup( entry->e_ndn );
+ charray_add( &dnlist, dn );
+ continue;
+
+ }
+
+ if ( newSup != NULL ) {
+ free( dn );
+ bdb2i_cache_return_entry_r(&li->li_cache, sup );
+ sup = newSup;
+ dn = aliasDN;
+ continue;
+ }
+
+ break;
+
+ } else {
+ /* no newe and no superior, we're done */
+ break;
+ }
+ }
+
+ free( dn );
+ return entry;
}
-/*
- * given a DN fully deref it and return the real DN or original DN if it fails
- * This involves finding the last matched part then reconstructing forward
- * e.g.
- * ou=MyOU,o=MyAliasedOrg,c=MyCountry where o=MyAliasedOrg is an alias for o=MyOrg
- * loop starts with newDN = ou=MyOU,o=MyAliasedOrg,c=MyCountry
- * dn2entry_r on newDN gives null entry and o=MyAliasedOrg,c=MyCountry matched
- * dn2entry_r on matched gives o=MyAliasedOrg,c=MyCountry entry
- * remainder is ou=MyOU
- * dereferencing o=MyAliasedOrg,c=MyCountry yields entry o=MyOrg,c=MyCountry
- * release lock on o=MyAliasedOrg,c=MyCountry entry
- * reconstructed dn is ou=MyOU,o=MyOrg,c=MyCountry
- * release lock on o=MyOrg,c=MyCountry entry
- */
-char *bdb2i_derefDN ( BackendDB *be,
- Connection *conn,
- Operation *op,
- char *dn
-)
-{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = 0;
- char *newDN = NULL;
- int depth, i;
- Entry *eMatched;
- Entry *eDeref;
- Entry *eNew;
-
- if (!dn) return NULL;
-
- Debug( LDAP_DEBUG_TRACE,
- "<= dereferencing dn: \"%s\"\n",
- dn, 0, 0 );
-
- newDN = ch_strdup ( dn );
-
- /* while we don't have a matched dn, deref the DN */
- for ( depth = 0;
- ( (eMatched = bdb2i_dn2entry_r( be, newDN, &matched )) == NULL) &&
- (depth < be->be_maxDerefDepth);
- ++depth ) {
-
- if ((matched != NULL) && *matched) {
- char *submatch;
-
- /*
- * make sure there actually is an entry for the matched part
- */
- if ( (eMatched = bdb2i_dn2entry_r( be, matched, &submatch )) != NULL) {
- char *remainder; /* part before the aliased part */
- int rlen = strlen(newDN) - strlen(matched);
-
- Debug( LDAP_DEBUG_TRACE, "<= matched %s\n", matched, 0, 0 );
-
- remainder = ch_malloc (rlen + 1);
- strncpy ( remainder, newDN, rlen );
- remainder[rlen] = '\0';
-
- Debug( LDAP_DEBUG_TRACE, "<= remainder %s\n", remainder, 0, 0 );
-
- if ((eNew = bdb2i_derefAlias_r( be, conn, op, eMatched )) == NULL) {
- free (matched);
- matched = NULL;
- free (newDN);
- newDN = NULL;
- free (remainder);
- remainder = NULL;
-
- bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
- eMatched = NULL;
- break; /* no associated entry, dont deref */
+
+static char* get_alias_dn(
+ Entry *e,
+ int *err,
+ char **errmsg )
+{
+ Attribute *a = attr_find( e->e_attrs, "aliasedobjectname" );
+
+ if( a == NULL ) {
+ /*
+ * there was an aliasedobjectname defined but no data.
+ */
+ *err = LDAP_ALIAS_PROBLEM;
+ *errmsg = "alias missing aliasedObjectName attribute";
+ return NULL;
}
- else {
-
- Debug( LDAP_DEBUG_TRACE, "<= l&g we have %s vs %s \n", matched, eNew->e_dn, 0 );
-
- i = strcasecmp (matched, eNew->e_dn);
- /* free reader lock */
- bdb2i_cache_return_entry_r(&li->li_cache, eNew);
-
- free (matched);
- matched = NULL;
-
- if (! i) {
- /* newDN same as old so not an alias, no need to go further */
- free (newDN);
- newDN = NULL;
- free (remainder);
-
- bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
- eMatched = NULL;
- break;
- }
-
- /*
- * we have dereferenced the aliased part so put
- * the new dn together
- */
- free (newDN);
- newDN = ch_malloc (strlen(eMatched->e_dn) + rlen + 1);
- strcpy (newDN, remainder);
- strcat (newDN, eMatched->e_dn);
- Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 );
-
- free (remainder);
+
+ /*
+ * aliasedObjectName should be SINGLE-VALUED with a single value.
+ */
+ if ( a->a_vals[0] == NULL || a->a_vals[0]->bv_val != NULL ) {
+ /*
+ * there was an aliasedobjectname defined but no data.
+ */
+ *err = LDAP_ALIAS_PROBLEM;
+ *errmsg = "alias missing aliasedObjectName value";
+ return NULL;
}
- /* free reader lock */
- bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
- }
- else {
- if(submatch != NULL) free(submatch);
- break; /* there was no entry for the matched part */
- }
- }
- else {
- break; /* there was no matched part */
- }
- }
-
- /* release lock if a match terminated the loop, there should be no
- * outstanding locks at this point
- */
- if(eMatched != NULL) {
- /* free reader lock */
- bdb2i_cache_return_entry_r(&li->li_cache, eMatched);
- }
-
- /*
- * the final part of the DN might be an alias so try to dereference it.
- * e.g. if we had started with dn = o=MyAliasedOrg,c=MyCountry the dn would match
- * and the above loop complete but we would still be left with an aliased DN.
- */
- if (newDN != NULL) {
- if ( (eNew = bdb2i_dn2entry_r( be, newDN, &matched )) != NULL) {
- if ((eDeref = bdb2i_derefAlias_r( be, conn, op, eNew )) != NULL) {
- free (newDN);
- newDN = ch_strdup (eDeref->e_dn);
- /* free reader lock */
- bdb2i_cache_return_entry_r(&li->li_cache, eDeref);
- }
- /* free reader lock */
- bdb2i_cache_return_entry_r(&li->li_cache, eNew);
- }
- }
- if (matched != NULL) free(matched);
-
- /*
- * warn if we exceeded the max depth as the resulting DN may not be dereferenced
- */
- if (depth >= be->be_maxDerefDepth) {
- if (newDN) {
- Debug( LDAP_DEBUG_TRACE,
- "<= max deref depth exceeded in derefDN for \"%s\", result \"%s\"\n",
- dn, newDN, 0 );
- free (newDN);
- newDN = NULL;
- } else {
- Debug( LDAP_DEBUG_TRACE,
- "<= max deref depth exceeded in derefDN for \"%s\", result NULL\n",
- dn, 0, 0 );
+
+ if( a->a_vals[1] != NULL ) {
+ *err = LDAP_ALIAS_PROBLEM;
+ *errmsg = "alias has multivalued aliasedObjectName";
+ return NULL;
}
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
- "Maximum alias dereference depth exceeded for base" );
- }
- if (newDN == NULL) {
- newDN = ch_strdup ( dn );
- }
-
- Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 );
+ return a->a_vals[0]->bv_val;
+}
+
+static char* new_superior(
+ char *dn,
+ char *oldSup,
+ char *newSup )
+{
+ char *newDN;
+ size_t dnlen, olen, nlen;
+ assert( dn && oldSup && newSup );
+
+ dnlen = strlen( dn );
+ olen = strlen( oldSup );
+ nlen = strlen( newSup );
+
+ newDN = ch_malloc( dnlen - olen + nlen + 1 );
+
+ memcpy( newDN, dn, dnlen - olen );
+ memcpy( &newDN[dnlen - olen], newSup, nlen );
+ newDN[dnlen - olen + nlen] = '\0';
- return newDN;
+ return newDN;
}
+
+static int dnlist_subordinate(
+ char** dnlist,
+ char *dn )
+{
+ int i;
+ assert( dnlist );
+
+ for( i = 0; dnlist[i] != NULL; i++ ) {
+ if( dn_issuffix( dnlist[i], dn ) ) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
Entry *e;
Attribute *a;
int rc;
- char *matched;
+ Entry *matched;
#ifdef HAVE_KERBEROS
char krbname[MAX_K_NAME_SZ + 1];
AUTH_DAT ad;
/* get entry with reader lock */
if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
/* allow noauth binds */
rc = 1;
if ( method == LDAP_AUTH_SIMPLE ) {
if( cred->bv_len == 0 ) {
/* SUCCESS */
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
} else if ( be_isroot_pw( be, dn, cred ) ) {
/* front end will send result */
rc = 0;
} else {
- send_ldap_result( conn, op,
- LDAP_NO_SUCH_OBJECT, matched, NULL );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
}
} else if ( method == LDAP_AUTH_SASL ) {
if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) {
/* insert DIGEST calls here */
- send_ldap_result( conn, op,
- LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, NULL, NULL, NULL );
} else {
- send_ldap_result( conn, op,
- LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, NULL, NULL, NULL );
}
} else {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, NULL );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
rc = 1;
}
+
if ( matched != NULL ) {
- free( matched );
+ ber_bvecfree( refs );
+ free( matched_dn );
}
return( rc );
}
if ( ! access_allowed( be, conn, op, e,
"entry", NULL, ACL_AUTH ) )
{
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
+ }
+
+ if ( is_entry_alias( e ) ) {
+ /* entry is a alias, don't allow bind */
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, NULL, NULL, NULL );
+
+ rc = 1;
+ goto return_results;
+ }
+
+
+ if ( is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow bind */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
rc = 1;
goto return_results;
}
switch ( method ) {
case LDAP_AUTH_SIMPLE:
if ( cred->bv_len == 0 ) {
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
/* stop front end from sending result */
rc = 1;
if ( ! access_allowed( be, conn, op, e,
"userpassword", NULL, ACL_AUTH ) )
{
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL);
rc = 1;
goto return_results;
}
if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
- NULL, NULL );
+ NULL, NULL, NULL, NULL);
/* stop front end from sending result */
rc = 1;
if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 )
{
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
- NULL, NULL );
+ NULL, NULL, NULL, NULL);
/* stop front end from sending result */
rc = 1;
goto return_results;
case LDAP_AUTH_KRBV41:
if ( bdb2i_krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
- NULL, NULL );
+ NULL, NULL, NULL, NULL);
rc = 1;
goto return_results;
}
if ( ! access_allowed( be, conn, op, e,
"krbname", NULL, ACL_AUTH ) )
{
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL);
rc = 1;
goto return_results;
}
break;
}
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
- NULL, NULL );
+ NULL, NULL, NULL, NULL);
rc = 1;
goto return_results;
} else { /* look for krbName match */
krbval.bv_len = strlen( krbname );
if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) {
- send_ldap_result( conn, op,
- LDAP_INVALID_CREDENTIALS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
+ NULL, NULL, NULL, NULL);
rc = 1;
goto return_results;
}
break;
case LDAP_AUTH_KRBV42:
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
/* stop front end from sending result */
rc = 1;
goto return_results;
default:
send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
- NULL, "auth method not supported" );
+ NULL, "auth method not supported", NULL, NULL );
rc = 1;
goto return_results;
}
bdb2i_start_timing( be->bd_info, &time1 );
if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
-
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return( 1 );
-
}
ret = bdb2i_back_bind_internal( be, conn, op, dn, method, mech, cred, edn );
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched;
+ Entry *matched;
Entry *e;
Attribute *a;
int rc;
+ int manageDSAit = get_manageDSAit( op );
/* get entry with reader lock */
if ( (e = bdb2i_dn2entry_r( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
- if(matched == NULL) free(matched);
return( 1 );
}
- /* check for deleted */
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ rc = 1;
+ goto return_results;
+ }
+
if ( ! access_allowed( be, conn, op, e,
ava->ava_type, &ava->ava_value, ACL_COMPARE ) )
{
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
rc = 1;
goto return_results;
}
if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE, "", "" );
+ send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE,
+ NULL, NULL, NULL, NULL );
rc = 1;
goto return_results;
}
if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 )
- send_ldap_result( conn, op, LDAP_COMPARE_TRUE, "", "" );
+ send_ldap_result( conn, op, LDAP_COMPARE_TRUE,
+ NULL, NULL, NULL, NULL );
else
- send_ldap_result( conn, op, LDAP_COMPARE_FALSE, "", "" );
+ send_ldap_result( conn, op, LDAP_COMPARE_FALSE,
+ NULL, NULL, NULL, NULL );
rc = 0;
if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return( 1 );
}
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = NULL;
+ Entry *matched = NULL;
char *pdn = NULL;
Entry *e, *p = NULL;
- int rc = -1;
+ int rc = -1, manageDSAit;
Debug(LDAP_DEBUG_ARGS, "==> bdb2i_back_delete: %s\n", dn, 0, 0);
/* get entry with writer lock */
if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: no such object %s\n",
dn, 0, 0);
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+
if ( matched != NULL ) {
- free( matched );
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
}
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
return( -1 );
}
- /* check for deleted */
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ goto return_results;
+ }
+
if ( bdb2i_has_children( be, e ) ) {
Debug(LDAP_DEBUG_ARGS, "<=- bdb2i_back_delete: non leaf %s\n",
dn, 0, 0);
- send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, "",
- "" );
+ send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug(LDAP_DEBUG_ARGS,
"<=- bdb2i_back_delete: insufficient access %s\n",
dn, 0, 0);
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
#endif
Debug( LDAP_DEBUG_TRACE,
"<=- bdb2i_back_delete: parent does not exist\n", 0, 0, 0);
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- "", "");
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"<=- bdb2i_back_delete: no access to parent\n", 0, 0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"<=- bdb2i_back_delete: no parent & not root\n", 0, 0, 0);
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "");
+ NULL, NULL, NULL, NULL );
goto return_results;
}
}
Debug(LDAP_DEBUG_ARGS,
"<=- bdb2i_back_delete: operations error %s\n",
dn, 0, 0);
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "","" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug(LDAP_DEBUG_ARGS,
"<=- bdb2i_back_delete: operations error %s\n",
dn, 0, 0);
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug(LDAP_DEBUG_ARGS,
"<=- bdb2i_back_delete: operations error %s\n",
dn, 0, 0);
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
rc = 0;
return_results:;
bdb2i_start_timing( be->bd_info, &time1 );
if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
-
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return( -1 );
-
}
ret = bdb2i_back_delete_internal( be, conn, op, dn );
bdb2i_dn2entry_rw(
BackendDB *be,
char *dn,
- char **matched,
+ Entry **matched,
int rw
)
{
Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n",
rw ? "w" : "r", dn, 0);
- *matched = NULL;
+ if( matched != NULL ) {
+ /* caller cares about match */
+ *matched = NULL;
+ }
if ( (id = bdb2i_dn2id( be, dn )) != NOID &&
(e = bdb2i_id2entry_rw( be, id, rw )) != NULL )
/* treat as if NOID was found */
}
- /* stop when we get to the suffix */
- if ( be_issuffix( be, dn ) ) {
- return( NULL );
- }
+ /* caller doesn't care about match */
+ if( matched == NULL ) return NULL;
/* entry does not exist - see how much of the dn does exist */
+ /* dn_parent checks returns NULL if dn is suffix */
if ( (pdn = dn_parent( be, dn )) != NULL ) {
/* get entry with reader lock */
if ( (e = bdb2i_dn2entry_r( be, pdn, matched )) != NULL ) {
- if(*matched != NULL) {
- free(*matched);
- }
- *matched = pdn;
- /* free entry with reader lock */
- bdb2i_cache_return_entry_r( &li->li_cache, e );
- } else {
- free( pdn );
+ *matched = e;
}
+ free( pdn );
}
return( NULL );
char *groupattrName
)
{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Entry *e;
- char *matched;
- Attribute *objectClass;
- Attribute *member;
- int rc;
-
- Debug( LDAP_DEBUG_TRACE,
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Entry *e;
+ int rc = 1;
+ Attribute *attr;
+ struct berval bv;
+
+ Debug( LDAP_DEBUG_ARGS,
"=> bdb2i_back_group: gr dn: \"%s\"\n",
gr_ndn, 0, 0 );
- Debug( LDAP_DEBUG_TRACE,
+ Debug( LDAP_DEBUG_ARGS,
"=> bdb2i_back_group: op dn: \"%s\"\n",
op_ndn, 0, 0 );
- Debug( LDAP_DEBUG_TRACE,
+ Debug( LDAP_DEBUG_ARGS,
"=> bdb2i_back_group: objectClass: \"%s\" attrName: \"%s\"\n",
objectclassValue, groupattrName, 0 );
- Debug( LDAP_DEBUG_TRACE,
+ Debug( LDAP_DEBUG_ARGS,
"=> bdb2i_back_group: tr dn: \"%s\"\n",
target->e_ndn, 0, 0 );
if (strcmp(target->e_ndn, gr_ndn) == 0) {
/* we already have a LOCKED copy of the entry */
e = target;
- Debug( LDAP_DEBUG_ARGS,
+ Debug( LDAP_DEBUG_ARGS,
"=> bdb2i_back_group: target is group: \"%s\"\n",
gr_ndn, 0, 0 );
+
} else {
/* can we find group entry with reader lock */
- if ((e = bdb2i_dn2entry_r(be, gr_ndn, &matched )) == NULL) {
- Debug( LDAP_DEBUG_TRACE,
- "=> bdb2i_back_group: cannot find group: \"%s\" matched: \"%s\"\n",
- gr_ndn, (matched ? matched : ""), 0 );
- if (matched != NULL)
- free(matched);
+ if ((e = bdb2i_dn2entry_r(be, gr_ndn, NULL )) == NULL) {
+ Debug( LDAP_DEBUG_ACL,
+ "=> bdb2i_back_group: cannot find group: \"%s\"\n",
+ gr_ndn, 0, 0 );
return( 1 );
}
- Debug( LDAP_DEBUG_ARGS,
+
+ Debug( LDAP_DEBUG_ACL,
"=> bdb2i_back_group: found group: \"%s\"\n",
gr_ndn, 0, 0 );
- }
+ }
+ /* find it's objectClass and member attribute values
+ * make sure this is a group entry
+ * finally test if we can find op_dn in the member attribute value list
+ */
+
+ rc = 1;
- /* check for deleted */
+ if ((attr = attr_find(e->e_attrs, "objectclass")) == NULL) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: failed to find objectClass\n", 0, 0, 0 );
+ goto return_results;
+ }
- /* find it's objectClass and member attribute values
- * make sure this is a group entry
- * finally test if we can find op_dn in the member attribute value list *
- */
-
- rc = 1;
- if ((objectClass = attr_find(e->e_attrs, "objectclass")) == NULL) {
- Debug( LDAP_DEBUG_TRACE, "<= bdb2i_back_group: failed to find objectClass\n", 0, 0, 0 );
- }
- else if ((member = attr_find(e->e_attrs, groupattrName)) == NULL) {
- Debug( LDAP_DEBUG_TRACE, "<= bdb2i_back_group: failed to find %s\n", groupattrName, 0, 0 );
- }
- else {
- struct berval bvObjectClass;
- struct berval bvMembers;
-
- Debug( LDAP_DEBUG_ARGS, "<= bdb2i_back_group: found objectClass and %s\n", groupattrName, 0, 0 );
-
- bvObjectClass.bv_val = objectclassValue;
- bvObjectClass.bv_len = strlen( bvObjectClass.bv_val );
-
- bvMembers.bv_val = op_ndn;
- bvMembers.bv_len = strlen( op_ndn );
-
- if (value_find(objectClass->a_vals, &bvObjectClass, SYNTAX_CIS, 1) != 0) {
- Debug( LDAP_DEBUG_TRACE,
- "<= bdb2i_back_group: failed to find %s in objectClass\n",
- objectclassValue, 0, 0 );
- }
- else if (value_find(member->a_vals, &bvMembers, SYNTAX_CIS, 1) != 0) {
- Debug( LDAP_DEBUG_ACL,
- "<= bdb2i_back_group: \"%s\" not in \"%s\": %s\n",
- op_ndn, gr_ndn, groupattrName );
- }
- else {
- Debug( LDAP_DEBUG_ACL,
- "<= bdb2i_back_group: \"%s\" is in \"%s\": %s\n",
- op_ndn, gr_ndn, groupattrName );
- rc = 0;
- }
- }
+ bv.bv_val = "ALIAS";
+ bv.bv_len = sizeof("ALIAS")-1;
+
+ if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: group is an alias\n", 0, 0, 0 );
+ goto return_results;
+ }
+
+ bv.bv_val = "REFERRAL";
+ bv.bv_len = sizeof("REFERRAL")-1;
+
+ if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: group is a referral\n", 0, 0, 0 );
+ goto return_results;
+ }
+
+ bv.bv_val = objectclassValue;
+ bv.bv_len = strlen( bv.bv_val );
+
+ if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: failed to find %s in objectClass\n",
+ objectclassValue, 0, 0 );
+ goto return_results;
+ }
+
+ if ((attr = attr_find(e->e_attrs, groupattrName)) == NULL) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: failed to find %s\n",
+ groupattrName, 0, 0 );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: found objectClass %s and %s\n",
+ objectclassValue, groupattrName, 0 );
+
+
+ bv.bv_val = op_ndn;
+ bv.bv_len = strlen( op_ndn );
+
+ if (value_find( attr->a_vals, &bv, attr->a_syntax, 1) != 0 ) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: \"%s\" not in \"%s\": %s\n",
+ op_ndn, gr_ndn, groupattrName );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_ACL,
+ "<= bdb2i_back_group: \"%s\" is in \"%s\": %s\n",
+ op_ndn, gr_ndn, groupattrName );
+ rc = 0;
+return_results:
if( target != e ) {
/* free entry and reader lock */
bdb2i_cache_return_entry_r( &li->li_cache, e );
Debug(LDAP_DEBUG_ARGS, "bdb2i_back_modify:\n", 0, 0, 0);
if ( (err = acl_check_modlist( be, conn, op, e, modlist )) != LDAP_SUCCESS ) {
- send_ldap_result( conn, op, err, NULL, NULL );
+ send_ldap_result( conn, op, err,
+ NULL, NULL, NULL, NULL );
goto error_return;
}
if ( err != LDAP_SUCCESS ) {
/* unlock entry, delete from cache */
- send_ldap_result( conn, op, err, NULL, NULL );
+ send_ldap_result( conn, op, err,
+ NULL, NULL, NULL, NULL );
goto error_return;
}
}
/* check that the entry still obeys the schema */
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+ NULL, NULL, NULL, NULL );
goto error_return;
}
/* modify indexes */
if ( bdb2i_index_add_mods( be, modlist, e->e_id ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto error_return;
}
/* change the entry itself */
if ( bdb2i_id2entry_add( be, e ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto error_return;
}
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
- bdb2i_cache_return_entry_w( &li->li_cache, e );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
return( 0 );
error_return:;
- bdb2i_cache_return_entry_w( &li->li_cache, e );
return( -1 );
}
DB_LOCK lock;
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
struct timeval time1;
- int ret;
- char *matched;
+ int ret, manageDSAit;
+ Entry *matched;
Entry *e;
bdb2i_start_timing( be->bd_info, &time1 );
if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
-
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return( -1 );
-
}
/* check, if a new default attribute index will be created,
}
if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched,
- NULL );
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
if ( matched != NULL ) {
- free( matched );
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
}
ret = -1;
+ goto done;
+ }
- } else {
- ret = bdb2i_back_modify_internal( be, conn, op, dn, modlist, e );
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ bdb2i_cache_return_entry_w( &li->li_cache, e );
+
+ ber_bvecfree( refs );
+
+ ret = -1;
+ goto done;
}
+ ret = bdb2i_back_modify_internal( be, conn, op, dn, modlist, e );
+ bdb2i_cache_return_entry_w( &li->li_cache, e );
+
+done:
(void) bdb2i_leave_backend_w( lock );
bdb2i_stop_timing( be->bd_info, time1, "MOD", conn, op );
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = NULL;
+ Entry *matched = NULL;
char *p_dn = NULL, *p_ndn = NULL;
char *new_dn = NULL, *new_ndn = NULL;
char sep[2];
Entry *e, *p = NULL;
- int rc = -1;
+ int rc = -1, manageDSAit;
/* Added to support LDAP v2 correctly (deleteoldrdn thing) */
char *new_rdn_val = NULL; /* Val of new rdn */
char *new_rdn_type = NULL; /* Type of new rdn */
/* get entry with writer lock */
if ( (e = bdb2i_dn2entry_w( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
if ( matched != NULL ) {
- free( matched );
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
}
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
return( -1 );
}
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ goto return_results;
+ }
+
#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
/* check parent for "children" acl */
if ( ! access_allowed( be, conn, op, e,
Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
#endif
Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
0, 0, 0);
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- "", "");
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, "no parent & not root\n",
0, 0, 0);
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "");
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: newSup(ndn=%s) not here!\n",
np_ndn, 0, 0);
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "",
- "");
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"ldbm_back_modrdn: no wr to newSup children\n",
0, 0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
new_ndn, 0, 0 );
if ( (bdb2i_dn2id ( be, new_ndn ) ) != NOID ) {
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
/* delete old one */
if ( bdb2i_dn2id_delete( be, e->e_ndn ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
/* add new one */
if ( bdb2i_dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: can't figure out type of newrdn\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: can't figure out val of newrdn\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: can't figure out old_rdn from dn\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: can't figure out the old_rdn type\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n",
0, 0, 0 );
- send_ldap_result( conn, op,
- LDAP_OPERATIONS_ERROR,
- "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
/* id2entry index */
if ( bdb2i_id2entry_add( be, e ) != 0 ) {
entry_free( e );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results_after;
}
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
rc = 0;
goto return_results_after;
return_results:
if( new_dn != NULL ) free( new_dn );
if( new_ndn != NULL ) free( new_ndn );
+
return_results_after:
/* NOTE:
* new_dn and new_ndn are not deallocated because they are used by
if( p_dn != NULL ) free( p_dn );
if( p_ndn != NULL ) free( p_ndn );
- if( matched != NULL ) free( matched );
-
/* LDAP v2 supporting correct attribute handling. */
if( new_rdn_type != NULL ) free(new_rdn_type);
if( new_rdn_val != NULL ) free(new_rdn_val);
bdb2i_start_timing( be->bd_info, &time1 );
if ( bdb2i_enter_backend_w( &lock ) != 0 ) {
-
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return( -1 );
}
/*
* alias.c
*/
-Entry *bdb2i_derefAlias_r LDAP_P((
- BackendDB *be,
- Connection *conn,
- Operation *op,
- Entry *e ));
-char *bdb2i_derefDN LDAP_P((
- BackendDB *be,
- Connection *conn,
- Operation *op,
- char *dn ));
+
+Entry * bdb2i_deref_r LDAP_P((
+ Backend *be,
+ Entry *e,
+ char *dn,
+ int *err,
+ Entry **matched,
+ char **text ));
+
+#define deref_entry_r( be, e, err, matched, text ) \
+ bdb2i_deref_r( be, e, NULL, err, matched, text )
+#define deref_dn_r( be, dn, err, matched, text ) \
+ bdb2i_deref_r( be, NULL, dn, err, matched, text )
/*
* attr.c
ID bdb2i_dn2id LDAP_P(( BackendDB *be, char *dn ));
int bdb2i_dn2id_delete LDAP_P(( BackendDB *be, char *dn ));
-Entry * bdb2i_dn2entry_rw LDAP_P(( BackendDB *be, char *dn, char **matched,
- int rw ));
+Entry * bdb2i_dn2entry_rw LDAP_P((
+ BackendDB *be,
+ char *dn,
+ Entry **matched,
+ int rw ));
+
#define bdb2i_dn2entry_r(be, dn, m) bdb2i_dn2entry_rw((be), (dn), (m), 0)
#define bdb2i_dn2entry_w(be, dn, m) bdb2i_dn2entry_rw((be), (dn), (m), 1)
#include "back-bdb2.h"
#include "proto-back-bdb2.h"
-static ID_BLOCK *base_candidates(BackendDB *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
-static ID_BLOCK *onelevel_candidates(BackendDB *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
-static ID_BLOCK *subtree_candidates(BackendDB *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, Entry *e, int *err, int lookupbase);
-
-#define GRABSIZE BUFSIZ
-
-#define MAKE_SPACE( n ) { \
- if ( rcur + (n) > rbuf + rmaxsize ) { \
- int offset = rcur - rbuf; \
- rbuf = ch_realloc( rbuf, rmaxsize + GRABSIZE ); \
- rmaxsize += GRABSIZE; \
- rcur = rbuf + offset; \
- } \
-}
+static ID_BLOCK *base_candidate(
+ Backend *be, Entry *e );
+
+static ID_BLOCK *search_candidates(
+ Backend *be, Entry *e, Filter *filter,
+ int scope, int deref, int manageDSAit );
static int
bdb2i_back_search_internal(
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- int err;
+ int rc, err;
+ char *text;
time_t stoptime;
ID_BLOCK *candidates;
ID id;
Entry *e;
- Attribute *ref;
- char *matched = NULL;
- int rmaxsize, nrefs;
- char *rbuf, *rcur;
+ struct berval **v2refs = NULL;
+ Entry *matched = NULL;
+ char *realbase = NULL;
int nentries = 0;
- char *realBase;
+ int manageDSAit = get_manageDSAit( op );
+
+ Debug(LDAP_DEBUG_TRACE, "=> bdb2_back_search\n", 0, 0, 0);
+
+ /* get entry with reader lock */
+ if ( deref & LDAP_DEREF_FINDING ) {
+ e = deref_dn_r( be, base, &err, &matched, &text );
+
+ } else {
+ e = bdb2i_dn2entry_r( be, base, &matched );
+ err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL;
+ text = NULL;
+ }
+
+ if ( e == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+
+ bdb2i_cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, err,
+ matched_dn, text, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ return 1;
+ }
+
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ char *matched_dn = ch_strdup( e->e_dn );
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
- Debug(LDAP_DEBUG_ARGS, "=> bdb2i_back_search\n", 0, 0, 0);
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ free( matched_dn );
+
+ return 1;
+ }
if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
tlimit = -1; /* allow root to set no limit */
be->be_timelimit : tlimit;
stoptime = op->o_time + tlimit;
}
+
if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
slimit = -1; /* allow root to set no limit */
} else {
be->be_sizelimit : slimit;
}
- /*
- * check and apply aliasing where the dereferencing applies to
- * the subordinates of the base
- */
-
- switch ( deref ) {
- case LDAP_DEREF_FINDING:
- case LDAP_DEREF_ALWAYS:
- realBase = bdb2i_derefDN ( be, conn, op, base );
- break;
- default:
- realBase = ch_strdup(base);
- }
+ if ( scope == LDAP_SCOPE_BASE) {
+ candidates = base_candidate( be, e );
- (void) dn_normalize_case( realBase );
-
- Debug( LDAP_DEBUG_TRACE, "using base \"%s\"\n",
- realBase, 0, 0 );
-
- switch ( scope ) {
- case LDAP_SCOPE_BASE:
- candidates = base_candidates( be, conn, op, realBase, filter,
- attrs, attrsonly, &matched, &err );
- break;
-
- case LDAP_SCOPE_ONELEVEL:
- candidates = onelevel_candidates( be, conn, op, realBase, filter,
- attrs, attrsonly, &matched, &err );
- break;
-
- case LDAP_SCOPE_SUBTREE:
- candidates = subtree_candidates( be, conn, op, realBase, filter,
- attrs, attrsonly, &matched, NULL, &err, 1 );
- break;
-
- default:
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, "",
- "Bad scope" );
- if( realBase != NULL) {
- free( realBase );
- }
- return( -1 );
+ } else {
+ candidates = search_candidates( be, e, filter,
+ scope, deref, manageDSAit );
}
- /* null candidates means we could not find the base object */
+ /* need normalized dn below */
+ realbase = ch_strdup( e->e_ndn );
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+
if ( candidates == NULL ) {
- send_ldap_result( conn, op, err, matched, "" );
- if ( matched != NULL ) {
- free( matched );
- }
- if( realBase != NULL) {
- free( realBase );
- }
- return( -1 );
- }
+ /* no candidates */
+ Debug( LDAP_DEBUG_TRACE, "no candidates\n", 0,
+ 0, 0 );
+
+ send_search_result( conn, op,
+ LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 0 );
- if ( matched != NULL ) {
- free( matched );
+ rc = 1;
+ goto done;
}
- rmaxsize = 0;
- nrefs = 0;
- rbuf = rcur = NULL;
- MAKE_SPACE( sizeof("Referral:") + 1 );
- strcpy( rbuf, "Referral:" );
- rcur = strchr( rbuf, '\0' );
for ( id = bdb2i_idl_firstid( candidates ); id != NOID;
- id = bdb2i_idl_nextid( candidates, id ) ) {
+ id = bdb2i_idl_nextid( candidates, id ) )
+ {
+ int scopeok = 0;
+
/* check for abandon */
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+
if ( op->o_abandon ) {
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
- bdb2i_idl_free( candidates );
- free( rbuf );
- if( realBase != NULL) {
- free( realBase );
- }
- return( 0 );
+ rc = 0;
+ goto done;
}
+
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* check time limit */
if ( tlimit != -1 && slap_get_time() > stoptime ) {
- send_ldap_search_result( conn, op,
- LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
- NULL, nentries );
- bdb2i_idl_free( candidates );
- free( rbuf );
- if( realBase != NULL) {
- free( realBase );
- }
- return( 0 );
+ send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
+ NULL, NULL, v2refs, NULL, nentries );
+ rc = 0;
+ goto done;
}
/* get the entry with reader lock */
- if ( (e = bdb2i_id2entry_r( be, id )) == NULL ) {
- Debug( LDAP_DEBUG_ARGS, "candidate %ld not found\n",
- id, 0, 0 );
- continue;
+ e = bdb2i_id2entry_r( be, id );
+
+ if ( e == NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "search: candidate %ld not found\n",
+ id, 0, 0 );
+
+ goto loop_continue;
+ }
+
+ if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) {
+ Entry *matched;
+ int err;
+ char *text;
+
+ e = deref_entry_r( be, e, &err, &matched, &text );
+
+ if( e == NULL ) {
+ e = matched;
+ goto loop_continue;
+ }
+
+ if( e->e_id == id ) {
+ /* circular loop */
+ goto loop_continue;
+ }
+
+ /* need to skip alias which deref into scope */
+ if( scope & LDAP_SCOPE_ONELEVEL ) {
+ char *pdn = dn_parent( NULL, e->e_ndn );
+ if ( pdn != NULL ) {
+ if( strcmp( pdn, realbase ) ) {
+ free( pdn );
+ goto loop_continue;
+ }
+ free(pdn);
+ }
+
+ } else if ( dn_issuffix( e->e_ndn, realbase ) ) {
+ /* alias is within scope */
+ Debug( LDAP_DEBUG_ARGS, "search: \"%s\" in subtree\n",
+ e->e_dn, 0, 0 );
+ goto loop_continue;
+ }
+
+ scopeok = 1;
}
/*
* if it's a referral, add it to the list of referrals. only do
- * this for subtree searches, and don't check the filter explicitly
- * here since it's only a candidate anyway.
+ * this for non-base searches, and don't check the filter
+ * explicitly here since it's only a candidate anyway.
*/
- if ( scope == LDAP_SCOPE_SUBTREE &&
- e->e_ndn != NULL &&
- strncmp( e->e_ndn, "REF=", 4 ) == 0 &&
- (ref = attr_find( e->e_attrs, "ref" )) != NULL )
+ if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
+ is_entry_referral( e ) )
{
- int i;
+ struct berval **refs = get_entry_referrals(
+ be, conn, op, e );
- if ( ref->a_vals == NULL ) {
- Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n",
- e->e_dn, 0, 0 );
- } else {
- for ( i = 0; ref->a_vals[i] != NULL; i++ ) {
- /* referral + newline + null */
- MAKE_SPACE( ref->a_vals[i]->bv_len + 2 );
- *rcur++ = '\n';
- strncpy( rcur, ref->a_vals[i]->bv_val,
- ref->a_vals[i]->bv_len );
- rcur = rcur + ref->a_vals[i]->bv_len;
- *rcur = '\0';
- nrefs++;
- }
- }
+ send_search_reference( be, conn, op,
+ e, refs, scope, NULL, &v2refs );
- /* otherwise it's an entry - see if it matches the filter */
- } else {
- /* if it matches the filter and scope, send it */
- if ( test_filter( be, conn, op, e, filter ) == 0 ) {
- int scopeok;
- char *dn;
+ ber_bvecfree( refs );
- /* check scope */
- scopeok = 1;
- if ( scope == LDAP_SCOPE_ONELEVEL ) {
- if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
- (void) dn_normalize_case( dn );
- scopeok = (dn == realBase)
- ? 1
- : (strcmp( dn, realBase ) ? 0 : 1 );
- free( dn );
- } else {
- scopeok = (realBase == NULL || *realBase == '\0');
- }
- } else if ( scope == LDAP_SCOPE_SUBTREE ) {
- dn = ch_strdup( e->e_ndn );
- scopeok = dn_issuffix( dn, realBase );
+ goto loop_continue;
+ }
+
+ /* if it matches the filter and scope, send it */
+ if ( test_filter( be, conn, op, e, filter ) == 0 ) {
+ char *dn;
+
+ /* check scope */
+ if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
+ if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) {
+ (void) dn_normalize_case( dn );
+ scopeok = (dn == realbase)
+ ? 1
+ : (strcmp( dn, realbase ) ? 0 : 1 );
free( dn );
+
+ } else {
+ scopeok = (realbase == NULL || *realbase == '\0');
}
- if ( scopeok ) {
- /* check size limit */
- if ( --slimit == -1 ) {
- bdb2i_cache_return_entry_r( &li->li_cache, e );
- send_ldap_search_result( conn, op,
- LDAP_SIZELIMIT_EXCEEDED, NULL,
- nrefs > 0 ? rbuf : NULL, nentries );
- bdb2i_idl_free( candidates );
- free( rbuf );
-
- if( realBase != NULL) {
- free( realBase );
- }
- return( 0 );
- }
+ } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
+ dn = ch_strdup( e->e_ndn );
+ scopeok = dn_issuffix( dn, realbase );
+ free( dn );
- /*
- * check and apply aliasing where the dereferencing applies to
- * the subordinates of the base
- */
- switch ( deref ) {
- case LDAP_DEREF_SEARCHING:
- case LDAP_DEREF_ALWAYS:
- {
- Entry *newe = bdb2i_derefAlias_r( be, conn, op, e );
- if ( newe == NULL ) { /* problem with the alias */
- bdb2i_cache_return_entry_r( &li->li_cache, e );
- e = NULL;
- }
- else if ( newe != e ) { /* reassign e */
- bdb2i_cache_return_entry_r( &li->li_cache, e );
- e = newe;
- }
- }
- break;
- }
+ } else {
+ scopeok = 1;
+ }
- if (e) {
- switch ( send_search_entry( be, conn, op, e,
- attrs, attrsonly, 0 ) ) {
- case 0: /* entry sent ok */
- nentries++;
- break;
- case 1: /* entry not sent */
- break;
- case -1: /* connection closed */
- bdb2i_cache_return_entry_r( &li->li_cache, e );
- bdb2i_idl_free( candidates );
- free( rbuf );
-
- if( realBase != NULL) {
- free( realBase );
- }
- return( 0 );
- }
+ if ( scopeok ) {
+ /* check size limit */
+ if ( --slimit == -1 ) {
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ send_search_result( conn, op,
+ LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
+ v2refs, NULL, nentries );
+ rc = 0;
+ goto done;
+ }
+
+ if (e) {
+ switch ( send_search_entry( be, conn, op, e,
+ attrs, attrsonly, 0, NULL ) ) {
+ case 0: /* entry sent ok */
+ nentries++;
+ break;
+ case 1: /* entry not sent */
+ break;
+ case -1: /* connection closed */
+ bdb2i_cache_return_entry_r( &li->li_cache, e );
+ rc = 0;
+ goto done;
}
}
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "candidate %ld scope not okay\n",
+ id, 0, 0 );
}
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "candidate %ld does match filter\n",
+ id, 0, 0 );
}
+loop_continue:
if( e != NULL ) {
/* free reader lock */
bdb2i_cache_return_entry_r( &li->li_cache, e );
ldap_pvt_thread_yield();
}
+ send_search_result( conn, op,
+ v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+ NULL, NULL, v2refs, NULL, nentries );
+
+ rc = 0;
+
+done:
bdb2i_idl_free( candidates );
- if ( nrefs > 0 ) {
- send_ldap_search_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- rbuf, nentries );
- } else {
- send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL,
- nentries );
- }
- free( rbuf );
- if( realBase != NULL) {
- free( realBase );
- }
+ ber_bvecfree( v2refs );
+ if( realbase ) free( realbase );
- return( 0 );
+ return rc;
}
bdb2i_start_timing( be->bd_info, &time1 );
if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
-
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return( -1 );
}
static ID_BLOCK *
-base_candidates(
- BackendDB *be,
- Connection *conn,
- Operation *op,
- char *base,
- Filter *filter,
- char **attrs,
- int attrsonly,
- char **matched,
- int *err
+base_candidate(
+ Backend *be,
+ Entry *e
)
{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
ID_BLOCK *idl;
- Entry *e;
-
- Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n", base, 0, 0);
- *err = LDAP_SUCCESS;
-
- /* get entry with reader lock */
- if ( (e = bdb2i_dn2entry_r( be, base, matched )) == NULL ) {
- *err = LDAP_NO_SUCH_OBJECT;
- return( NULL );
- }
-
- /* check for deleted */
+ Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n",
+ e->e_dn, 0, 0);
idl = bdb2i_idl_alloc( 1 );
bdb2i_idl_insert( &idl, e->e_id, 1 );
-
- /* free reader lock */
- bdb2i_cache_return_entry_r( &li->li_cache, e );
-
return( idl );
}
static ID_BLOCK *
-onelevel_candidates(
- BackendDB *be,
- Connection *conn,
- Operation *op,
- char *base,
+search_candidates(
+ Backend *be,
+ Entry *e,
Filter *filter,
- char **attrs,
- int attrsonly,
- char **matched,
- int *err
+ int scope,
+ int deref,
+ int manageDSAit
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Entry *e = NULL;
- Filter *f;
- char buf[20];
ID_BLOCK *candidates;
+ Filter *f, *rf, *af, *lf;
- Debug(LDAP_DEBUG_TRACE, "onelevel_candidates: base: \"%s\"\n", base, 0, 0);
+ Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" s=%d d=%d\n",
+ e->e_ndn, scope, deref );
- *err = LDAP_SUCCESS;
+ f = NULL;
- /* get the base object with reader lock */
- if ( base != NULL && *base != '\0' &&
- (e = bdb2i_dn2entry_r( be, base, matched )) == NULL )
- {
- *err = LDAP_NO_SUCH_OBJECT;
- return( NULL );
+ if( !manageDSAit ) {
+ /* match referrals */
+ rf = (Filter *) ch_malloc( sizeof(Filter) );
+ rf->f_next = NULL;
+ rf->f_choice = LDAP_FILTER_OR;
+ rf->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+ rf->f_or->f_choice = LDAP_FILTER_EQUALITY;
+ rf->f_or->f_avtype = ch_strdup( "objectclass" );
+ rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
+ rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1;
+ rf->f_or->f_next = filter;
+ f = rf;
+ } else {
+ rf = NULL;
+ f = filter;
}
- /*
- * modify the filter to be something like this:
- *
- * parent=baseobject & originalfilter
- */
-
- f = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_next = NULL;
- f->f_choice = LDAP_FILTER_AND;
- f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_and->f_choice = LDAP_FILTER_EQUALITY;
- f->f_and->f_ava.ava_type = ch_strdup( "id2children" );
- sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
- f->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
- f->f_and->f_ava.ava_value.bv_len = strlen( buf );
- f->f_and->f_next = filter;
-
- /* from here, it's just like subtree_candidates */
- candidates = subtree_candidates( be, conn, op, base, f, attrs,
- attrsonly, matched, e, err, 0 );
-
- /* free up just the filter stuff we allocated above */
- f->f_and->f_next = NULL;
- filter_free( f );
-
- /* free entry and reader lock */
- if( e != NULL ) {
- bdb2i_cache_return_entry_r( &li->li_cache, e );
+ if( deref & LDAP_DEREF_SEARCHING ) {
+ /* match aliases */
+ af = (Filter *) ch_malloc( sizeof(Filter) );
+ af->f_next = NULL;
+ af->f_choice = LDAP_FILTER_OR;
+ af->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+ af->f_or->f_choice = LDAP_FILTER_EQUALITY;
+ af->f_or->f_avtype = ch_strdup( "objectclass" );
+ af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" );
+ af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1;
+ af->f_or->f_next = f;
+ f = af;
+ } else {
+ af = NULL;
}
- return( candidates );
-}
-static ID_BLOCK *
-subtree_candidates(
- BackendDB *be,
- Connection *conn,
- Operation *op,
- char *base,
- Filter *filter,
- char **attrs,
- int attrsonly,
- char **matched,
- Entry *e,
- int *err,
- int lookupbase
-)
-{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Filter *f, **filterarg_ptr;
- ID_BLOCK *candidates;
+ if ( scope == LDAP_SCOPE_SUBTREE ) {
+ lf = (Filter *) ch_malloc( sizeof(Filter) );
+ lf->f_next = NULL;
+ lf->f_choice = LDAP_FILTER_AND;
+ lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
- Debug(LDAP_DEBUG_TRACE, "subtree_candidates: base: \"%s\" %s\n",
- base ? base : "NULL", lookupbase ? "lookupbase" : "", 0);
-
- /*
- * get the base object - unless we already have it (from one-level).
- * also, unless this is a one-level search or a subtree search
- * starting at the very top of our subtree, we need to modify the
- * filter to be something like this:
- *
- * dn=*baseobjectdn & (originalfilter | ref=*)
- *
- * the "objectclass=referral" part is used to select referrals to return
- */
-
- *err = LDAP_SUCCESS;
- f = NULL;
- if ( lookupbase ) {
- e = NULL;
+ lf->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
+ lf->f_and->f_sub_type = ch_strdup( "dn" );
+ lf->f_and->f_sub_initial = NULL;
+ lf->f_and->f_sub_any = NULL;
+ lf->f_and->f_sub_final = ch_strdup( e->e_ndn );
- if ( base != NULL && *base != '\0' &&
- (e = bdb2i_dn2entry_r( be, base, matched )) == NULL )
- {
- *err = LDAP_NO_SUCH_OBJECT;
- return( NULL );
- }
+ lf->f_and->f_next = f;
+ f = lf;
- if (e) {
- bdb2i_cache_return_entry_r( &li->li_cache, e );
- }
+ } else if ( scope == LDAP_SCOPE_ONELEVEL ) {
+ char buf[16];
- f = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_next = NULL;
- f->f_choice = LDAP_FILTER_OR;
- f->f_or = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_or->f_choice = LDAP_FILTER_EQUALITY;
- f->f_or->f_avtype = ch_strdup( "objectclass" );
- /* Patch to use normalized uppercase */
- f->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
- f->f_or->f_avvalue.bv_len = strlen( "REFERRAL" );
- filterarg_ptr = &f->f_or->f_next;
- *filterarg_ptr = filter;
- filter = f;
-
- if ( ! be_issuffix( be, base ) ) {
- f = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_next = NULL;
- f->f_choice = LDAP_FILTER_AND;
- f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
- f->f_and->f_sub_type = ch_strdup( "dn" );
- f->f_and->f_sub_initial = NULL;
- f->f_and->f_sub_any = NULL;
- f->f_and->f_sub_final = ch_strdup( base );
- value_normalize( f->f_and->f_sub_final, SYNTAX_CIS );
- f->f_and->f_next = filter;
- filter = f;
- }
+ lf = (Filter *) ch_malloc( sizeof(Filter) );
+ lf->f_next = NULL;
+ lf->f_choice = LDAP_FILTER_AND;
+ lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
+
+ lf->f_and->f_choice = LDAP_FILTER_EQUALITY;
+ lf->f_and->f_ava.ava_type = ch_strdup( "id2children" );
+ sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
+ lf->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
+ lf->f_and->f_ava.ava_value.bv_len = strlen( buf );
+
+ lf->f_and->f_next = f;
+ f = lf;
+
+ } else {
+ lf = NULL;
}
- candidates = bdb2i_filter_candidates( be, filter );
+ candidates = bdb2i_filter_candidates( be, f );
+
+ /* free up filter additions we allocated above */
+ if( lf != NULL ) {
+ lf->f_and->f_next = NULL;
+ filter_free( lf );
+ }
+
+ if( af != NULL ) {
+ af->f_or->f_next = NULL;
+ filter_free( af );
+ }
- /* free up just the parts we allocated above */
- if ( f != NULL ) {
- *filterarg_ptr = NULL;
- filter_free( f );
+ if( rf != NULL ) {
+ rf->f_or->f_next = NULL;
+ filter_free( rf );
}
return( candidates );
if (!lc) {
ld = ldap_init(li->host, li->port);
if (!ld) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "ldap_init failed" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "ldap_init failed", NULL, NULL );
return( NULL );
}
lc = (struct ldapconn *)ch_malloc(sizeof(struct ldapconn));
ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER, &err);
ldap_get_option(lc->ld, LDAP_OPT_ERROR_STRING, &msg);
ldap_get_option(lc->ld, LDAP_OPT_MATCHED_DN, &match);
- send_ldap_result( lc->conn, op, err, match, msg);
+ send_ldap_result( lc->conn, op, err, match, msg, NULL, NULL );
free(match);
free(msg);
return( (err==LDAP_SUCCESS) ? 0 : -1 );
if (rc == -1)
goto fail;
- send_ldap_search_result( conn, op, sres, match, err, i );
+ send_search_result( conn, op, sres,
+ match, err, NULL, NULL, i );
if (match)
free(match);
if (err)
if (!attr->a_vals)
attr->a_vals = &dummy;
}
- send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly, 0 );
+ send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly, 0, NULL );
for (;ent.e_attrs;) {
attr=ent.e_attrs;
ent.e_attrs = attr->a_next;
if ( ( dn2id( be, e->e_ndn ) ) != NOID ) {
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
entry_free( e );
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+ NULL, NULL, NULL, NULL );
return( -1 );
}
0, 0, 0 );
entry_free( e );
- send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, "",
- "" );
+ send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+ NULL, NULL, NULL, NULL );
return( -1 );
}
pdn = dn_parent( be, e->e_ndn );
if( pdn != NULL && *pdn != '\0' && !be_issuffix(be, "") ) {
- char *matched = NULL;
+ Entry *matched = NULL;
assert( *pdn != '\0' );
/* get parent with writer lock */
if ( (p = dn2entry_w( be, pdn, &matched )) == NULL ) {
+ char *matched_dn;
+ struct berval **refs;
+
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
- Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
- 0, 0 );
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
- matched, "" );
if ( matched != NULL ) {
- free( matched );
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ cache_return_entry_r( &li->li_cache, matched );
+
+ } else {
+ matched_dn = NULL;
+ refs = default_referral;
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
+ 0, 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
}
entry_free( e );
free(pdn);
- if ( matched != NULL ) {
- free( matched );
- }
-
if ( ! access_allowed( be, conn, op, p,
"children", NULL, ACL_WRITE ) )
{
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
+ NULL, NULL, NULL, NULL );
+
+
+ entry_free( e );
+ return -1;
+ }
+
+ if ( is_entry_alias( p ) ) {
+ /* parent is an alias, don't allow add */
/* free parent and writer lock */
- cache_return_entry_w( &li->li_cache, p );
+ cache_return_entry_w( &li->li_cache, p );
+
+ Debug( LDAP_DEBUG_TRACE, "parent is alias\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, NULL, NULL, NULL );
entry_free( e );
return -1;
}
+ if ( is_entry_referral( p ) ) {
+ /* parent is a referral, don't allow add */
+ char *matched_dn = ch_strdup( p->e_dn );
+ struct berval **refs = is_entry_referral( p )
+ ? get_entry_referrals( be, conn, op, p )
+ : NULL;
+
+ /* free parent and writer lock */
+ cache_return_entry_w( &li->li_cache, p );
+
+ Debug( LDAP_DEBUG_TRACE, "parent is referral\n", 0,
+ 0, 0 );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ free( matched_dn );
+ entry_free( e );
+ return -1;
+ }
+
} else {
if(pdn != NULL) {
assert( *pdn == '\0' );
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
+ NULL, NULL, NULL, NULL );
entry_free( e );
return -1;
/* free the entry */
entry_free( e );
- if(rc > 0) {
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
- } else {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
- }
+ send_ldap_result( conn, op,
+ rc > 0 ? LDAP_ALREADY_EXISTS : LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return( -1 );
}
if ( id2children_add( be, p, e ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "id2children_add failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
if ( index_add_entry( be, e ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "index_add_entry failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
Debug( LDAP_DEBUG_TRACE, "dn2id_add failed\n", 0,
0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0,
0, 0 );
(void) dn2id_delete( be, e->e_ndn );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
rc = 0;
return_results:;
/*
- * Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to ITSD, Government of BC. The name of ITSD
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
+ * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
*/
#include "portable.h"
#include "back-ldbm.h"
#include "proto-back-ldbm.h"
-/*
- * given an alias object, dereference it to its end point.
- * Entry returned has reader lock or is NULL. Starting entry is not released.
- */
-Entry *derefAlias_r ( Backend *be,
- Connection *conn,
- Operation *op,
- Entry *e)
+
+static char* get_alias_dn(
+ Entry *e,
+ int *err,
+ char **errmsg );
+
+static char* new_superior(
+ char *dn,
+ char *oldSup,
+ char *newSup );
+
+static int dnlist_subordinate(
+ char** dnlist,
+ char *dn );
+
+Entry *deref_internal_r(
+ Backend* be,
+ Entry* alias,
+ char* dn,
+ int* err,
+ Entry** matched,
+ char** text )
+{
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Entry *entry;
+ Entry *sup;
+ unsigned depth;
+ char **dnlist;
+
+ assert( ( alias != NULL && dn == NULL ) || ( alias == NULL && dn != NULL ) );
+
+ *matched = NULL;
+ *err = LDAP_SUCCESS;
+ *text = NULL;
+
+ if( alias == NULL ) {
+ dn = ch_strdup( dn );
+ entry = dn2entry_r( be, dn, &sup );
+
+ } else {
+ dn = ch_strdup( alias->e_ndn );
+ entry = alias;
+ sup = NULL;
+ }
+
+ dnlist = NULL;
+ charray_add( &dnlist, dn );
+
+ for( depth=0 ; ; depth++ ) {
+ if( entry != NULL ) {
+ Entry *newe;
+ char *aliasDN;
+
+ /* have entry, may be an alias */
+
+ if( !is_entry_alias( entry ) ) {
+ /* entry is not an alias */
+ break;
+ }
+
+ /* entry is alias */
+ if( depth > be->be_max_deref_depth ) {
+ *matched = entry;
+ entry = NULL;
+ *err = LDAP_ALIAS_DEREF_PROBLEM;
+ *text = "maximum deref depth exceeded";
+ break;
+ }
+
+ /* deref entry */
+ aliasDN = get_alias_dn( entry, err, text );
+
+ if( aliasDN == NULL ) {
+ *matched = entry;
+ entry = NULL;
+ break;
+ }
+
+ /* check if aliasDN is a subordinate of any DN in our list */
+ if( dnlist_subordinate( dnlist, aliasDN ) ) {
+ *matched = entry;
+ entry = NULL;
+ *err = LDAP_ALIAS_PROBLEM;
+ *text = "circular alias";
+ break;
+ }
+
+ /* attempt to dereference alias */
+
+ newe = dn2entry_r( be, aliasDN, &sup );
+
+ if( newe != NULL ) {
+ free( dn );
+ cache_return_entry_r(&li->li_cache, entry );
+ entry = newe;
+ dn = ch_strdup( entry->e_ndn );
+ charray_add( &dnlist, dn );
+ continue;
+
+ }
+
+ if ( sup != NULL ) {
+ cache_return_entry_r(&li->li_cache, entry );
+ entry = NULL;
+ continue;
+ }
+
+ /* no newe and no superior, we're done */
+ break;
+
+ } else if( sup != NULL ) {
+ /* have superior, may be an alias */
+ Entry *newe;
+ Entry *newSup;
+ char *supDN;
+ char *aliasDN;
+
+ if( !is_entry_alias( sup ) ) {
+ /* entry is not an alias */
+ *matched = sup;
+ sup = NULL;
+ break;
+ }
+
+ /* entry is alias */
+ if( depth > be->be_max_deref_depth ) {
+ *matched = sup;
+ entry = NULL;
+ *err = LDAP_ALIAS_DEREF_PROBLEM;
+ *text = "maximum deref depth exceeded";
+ break;
+ }
+
+ /* deref entry */
+ supDN = get_alias_dn( sup, err, text );
+
+ if( supDN == NULL ) {
+ *matched = sup;
+ break;
+ }
+
+ aliasDN = new_superior( dn, sup->e_ndn, supDN );
+
+ if( aliasDN == NULL ) {
+ free(aliasDN);
+ *matched = sup;
+ *err = LDAP_ALIAS_PROBLEM;
+ *text = "superior alias problem";
+ break;
+ }
+
+ /* check if aliasDN is a subordinate of any DN in our list */
+ if( dnlist_subordinate( dnlist, aliasDN ) ) {
+ free(aliasDN);
+ *matched = entry;
+ entry = NULL;
+ *err = LDAP_ALIAS_PROBLEM;
+ *text = "subordinate circular alias";
+ break;
+ }
+
+ /* attempt to dereference alias */
+ newe = dn2entry_r( be, aliasDN, &newSup );
+
+ if( newe != NULL ) {
+ free(aliasDN);
+ free( dn );
+ cache_return_entry_r(&li->li_cache, sup );
+ entry = newe;
+ dn = ch_strdup( entry->e_ndn );
+ charray_add( &dnlist, dn );
+ continue;
+
+ }
+
+ if ( newSup != NULL ) {
+ free( dn );
+ cache_return_entry_r(&li->li_cache, sup );
+ sup = newSup;
+ dn = aliasDN;
+ continue;
+ }
+
+ break;
+
+ } else {
+ /* no newe and no superior, we're done */
+ break;
+ }
+ }
+
+ free( dn );
+ return entry;
+}
+
+
+static char* get_alias_dn(
+ Entry *e,
+ int *err,
+ char **errmsg )
+{
+ Attribute *a = attr_find( e->e_attrs, "aliasedobjectname" );
+
+ if( a == NULL ) {
+ /*
+ * there was an aliasedobjectname defined but no data.
+ */
+ *err = LDAP_ALIAS_PROBLEM;
+ *errmsg = "alias missing aliasedObjectName attribute";
+ return NULL;
+ }
+
+ /*
+ * aliasedObjectName should be SINGLE-VALUED with a single value.
+ */
+ if ( a->a_vals[0] == NULL || a->a_vals[0]->bv_val != NULL ) {
+ /*
+ * there was an aliasedobjectname defined but no data.
+ */
+ *err = LDAP_ALIAS_PROBLEM;
+ *errmsg = "alias missing aliasedObjectName value";
+ return NULL;
+ }
+
+ if( a->a_vals[1] != NULL ) {
+ *err = LDAP_ALIAS_PROBLEM;
+ *errmsg = "alias has multivalued aliasedObjectName";
+ return NULL;
+ }
+
+ return a->a_vals[0]->bv_val;
+}
+
+char* new_superior(
+ char *dn,
+ char *oldSup,
+ char *newSup )
{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private; /* to free cache entries */
- Attribute *a;
- int depth;
- char *matched;
- Entry *origDN = e;
-
- if (!e) return NULL; /* be sure we have a starting entry */
-
- Debug( LDAP_DEBUG_TRACE, "<= checking for alias for dn %s\n", e->e_dn, 0, 0 );
-
- /*
- * try to deref fully, up to a maximum depth. If the max depth exceeded
- * then send an error
- */
- for ( depth = 0;
- ( ( a = attr_find( e->e_attrs, "aliasedobjectname" ) ) != NULL) &&
- ( depth < be->be_maxDerefDepth );
- ++depth)
- {
-
- /*
- * make sure there is a defined aliasedobjectname.
- * can only have one value so just use first value (0) in the attr list.
- */
- if (a->a_vals[0] && a->a_vals[0]->bv_val) {
- char *newDN, *oldDN;
-
- Debug( LDAP_DEBUG_TRACE, "<= %s is an alias for %s\n",
- e->e_dn, a->a_vals[0]->bv_val, 0 );
- newDN = ch_strdup (a->a_vals[0]->bv_val);
- oldDN = ch_strdup (e->e_ndn);
-
- /*
- * release past lock if not original
- */
- if ( (depth > 0) && e ) {
- cache_return_entry_r(&li->li_cache, e);
- }
-
- /* make sure new and old DN are not same to avoid loops */
- dn_normalize_case (newDN);
- if ( strcmp (newDN, oldDN) == 0 ) {
-
- Debug( LDAP_DEBUG_TRACE,
- "<= %s alias is same as current %s\n",
- oldDN, newDN, 0 );
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
- "Circular alias" );
- free (newDN);
- free (oldDN);
- break;
- }
-
- /* make sure new and original are not same to avoid deadlocks */
- if ( strcmp (newDN, origDN->e_ndn) == 0 ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= %s alias is same as original %s\n",
- oldDN, origDN->e_ndn, 0 );
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
- "Circular alias" );
- free (newDN);
- free (oldDN);
- break;
- }
-
- /*
- * ok, so what happens if there is an alias in the DN of a dereferenced
- * alias object?
- */
- if ( (e = dn2entry_r( be, newDN, &matched )) == NULL ) {
-
- /* could not deref return error */
- Debug( LDAP_DEBUG_TRACE,
- "<= %s is a dangling alias to %s\n",
- oldDN, newDN, 0 );
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
- "Dangling Alias" );
-
- if (matched != NULL) free(matched);
- free (newDN);
- free (oldDN);
- break;
- }
-
- free (newDN);
- free (oldDN);
- }
- else {
- /*
- * there was an aliasedobjectname defined but no data.
- * this can't happen, right?
- */
- Debug( LDAP_DEBUG_TRACE,
- "<= %s has no data in aliasedobjectname attribute\n",
- (e && e->e_dn) ? e->e_dn : "(null)", 0, 0 );
- send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM, "",
- "Alias missing aliasedobjectname" );
- break;
- }
- }
-
- /*
- * warn if we pulled out due to exceeding the maximum deref depth
- */
- if ( depth >= be->be_maxDerefDepth ) {
- Debug( LDAP_DEBUG_TRACE,
- "<= deref(\"%s\") exceeded maximum deref depth (%d) at \"%s\"\n",
- origDN->e_dn ? origDN->e_dn : "(null)",
- be->be_maxDerefDepth,
- (e && e->e_ndn) ? e->e_ndn : "(null)");
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
- "Maximum alias dereference depth exceeded" );
- }
-
- return e;
+ char *newDN;
+ size_t dnlen, olen, nlen;
+ assert( dn && oldSup && newSup );
+
+ dnlen = strlen( dn );
+ olen = strlen( oldSup );
+ nlen = strlen( newSup );
+
+ newDN = ch_malloc( dnlen - olen + nlen + 1 );
+
+ memcpy( newDN, dn, dnlen - olen );
+ memcpy( &newDN[dnlen - olen], newSup, nlen );
+ newDN[dnlen - olen + nlen] = '\0';
+
+ return newDN;
}
-/*
- * given a DN fully deref it and return the real DN or original DN if it fails
- * This involves finding the last matched part then reconstructing forward
- * e.g.
- * ou=MyOU,o=MyAliasedOrg,c=MyCountry where o=MyAliasedOrg is an alias for o=MyOrg
- * loop starts with newDN = ou=MyOU,o=MyAliasedOrg,c=MyCountry
- * dn2entry_r on newDN gives null entry and o=MyAliasedOrg,c=MyCountry matched
- * dn2entry_r on matched gives o=MyAliasedOrg,c=MyCountry entry
- * remainder is ou=MyOU
- * dereferencing o=MyAliasedOrg,c=MyCountry yields entry o=MyOrg,c=MyCountry
- * release lock on o=MyAliasedOrg,c=MyCountry entry
- * reconstructed dn is ou=MyOU,o=MyOrg,c=MyCountry
- * release lock on o=MyOrg,c=MyCountry entry
- */
-char *derefDN ( Backend *be,
- Connection *conn,
- Operation *op,
- char *dn
-)
+static int dnlist_subordinate(
+ char** dnlist,
+ char *dn )
{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = 0;
- char *newDN = NULL;
- int depth, i;
- Entry *eMatched;
- Entry *eDeref;
- Entry *eNew;
-
- if (!dn) return NULL;
-
- Debug( LDAP_DEBUG_TRACE,
- "<= dereferencing dn: \"%s\"\n",
- dn, 0, 0 );
-
- newDN = ch_strdup ( dn );
-
- /* while we don't have a matched dn, deref the DN */
- for ( depth = 0;
- ( (eMatched = dn2entry_r( be, newDN, &matched )) == NULL) &&
- (depth < be->be_maxDerefDepth);
- ++depth ) {
-
- if ((matched != NULL) && *matched) {
- char *submatch;
-
- /*
- * make sure there actually is an entry for the matched part
- */
- if ( (eMatched = dn2entry_r( be, matched, &submatch )) != NULL) {
- char *remainder; /* part before the aliased part */
- int rlen = strlen(newDN) - strlen(matched);
-
- Debug( LDAP_DEBUG_TRACE, "<= matched %s\n", matched, 0, 0 );
-
- remainder = ch_malloc (rlen + 1);
- strncpy ( remainder, newDN, rlen );
- remainder[rlen] = '\0';
-
- Debug( LDAP_DEBUG_TRACE, "<= remainder %s\n", remainder, 0, 0 );
-
- if ((eNew = derefAlias_r( be, conn, op, eMatched )) == NULL) {
- free (matched);
- matched = NULL;
- free (newDN);
- newDN = NULL;
- free (remainder);
- remainder = NULL;
-
- cache_return_entry_r(&li->li_cache, eMatched);
- eMatched = NULL;
- break; /* no associated entry, dont deref */
- }
- else {
-
- Debug( LDAP_DEBUG_TRACE, "<= l&g we have %s vs %s \n", matched, eNew->e_dn, 0 );
-
- i = strcasecmp (matched, eNew->e_dn);
- /* free reader lock */
- cache_return_entry_r(&li->li_cache, eNew);
-
- free (matched);
- matched = NULL;
-
- if (! i) {
- /* newDN same as old so not an alias, no need to go further */
- free (newDN);
- newDN = NULL;
- free (remainder);
-
- cache_return_entry_r(&li->li_cache, eMatched);
- eMatched = NULL;
- break;
- }
-
- /*
- * we have dereferenced the aliased part so put
- * the new dn together
- */
- free (newDN);
- newDN = ch_malloc (strlen(eMatched->e_dn) + rlen + 1);
- strcpy (newDN, remainder);
- strcat (newDN, eMatched->e_dn);
- Debug( LDAP_DEBUG_TRACE, "<= expanded to %s\n", newDN, 0, 0 );
-
- free (remainder);
+ int i;
+ assert( dnlist );
+
+ for( i = 0; dnlist[i] != NULL; i++ ) {
+ if( dn_issuffix( dnlist[i], dn ) ) {
+ return 1;
+ }
}
- /* free reader lock */
- cache_return_entry_r(&li->li_cache, eMatched);
- }
- else {
- if(submatch != NULL) free(submatch);
- break; /* there was no entry for the matched part */
- }
- }
- else {
- break; /* there was no matched part */
- }
- }
-
- /* release lock if a match terminated the loop, there should be no
- * outstanding locks at this point
- */
- if(eMatched != NULL) {
- /* free reader lock */
- cache_return_entry_r(&li->li_cache, eMatched);
- }
-
- /*
- * the final part of the DN might be an alias so try to dereference it.
- * e.g. if we had started with dn = o=MyAliasedOrg,c=MyCountry the dn would match
- * and the above loop complete but we would still be left with an aliased DN.
- */
- if (newDN != NULL) {
- if ( (eNew = dn2entry_r( be, newDN, &matched )) != NULL) {
- if ((eDeref = derefAlias_r( be, conn, op, eNew )) != NULL) {
- free (newDN);
- newDN = ch_strdup (eDeref->e_dn);
- /* free reader lock */
- cache_return_entry_r(&li->li_cache, eDeref);
- }
- /* free reader lock */
- cache_return_entry_r(&li->li_cache, eNew);
- }
- }
- if (matched != NULL) free(matched);
-
- /*
- * warn if we exceeded the max depth as the resulting DN may not be dereferenced
- */
- if (depth >= be->be_maxDerefDepth) {
- if (newDN) {
- Debug( LDAP_DEBUG_TRACE,
- "<= max deref depth exceeded in derefDN for \"%s\", result \"%s\"\n",
- dn, newDN, 0 );
- free (newDN);
- newDN = NULL;
- }
- else {
- Debug( LDAP_DEBUG_TRACE,
- "<= max deref depth exceeded in derefDN for \"%s\", result NULL\n",
- dn, 0, 0 );
- }
- send_ldap_result( conn, op, LDAP_ALIAS_DEREF_PROBLEM, "",
- "Maximum alias dereference depth exceeded for base" );
- }
-
- if (newDN == NULL) {
- newDN = ch_strdup ( dn );
- }
-
- Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 );
-
- return newDN;
+
+ return 0;
}
+
Entry *e;
Attribute *a;
int rc;
- char *matched;
+ Entry *matched;
#ifdef HAVE_KERBEROS
char krbname[MAX_K_NAME_SZ + 1];
AUTH_DAT ad;
/* get entry with reader lock */
if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+
+ cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
/* allow noauth binds */
rc = 1;
if ( method == LDAP_AUTH_SIMPLE ) {
if( cred->bv_len == 0 ) {
/* SUCCESS */
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
} else if ( be_isroot_pw( be, dn, cred ) ) {
*edn = ch_strdup( be_root_dn( be ) );
rc = 0; /* front end will send result */
} else {
- send_ldap_result( conn, op,
- LDAP_NO_SUCH_OBJECT, matched, NULL );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
}
} else if ( method == LDAP_AUTH_SASL ) {
if( mech != NULL && strcasecmp(mech,"DIGEST-MD5") == 0 ) {
/* insert DIGEST calls here */
- send_ldap_result( conn, op,
- LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, NULL, NULL, NULL );
} else {
- send_ldap_result( conn, op,
- LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
+ NULL, NULL, NULL, NULL );
}
} else {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, NULL );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
}
if ( matched != NULL ) {
- free( matched );
+ ber_bvecfree( refs );
+ free( matched_dn );
}
return( rc );
}
if ( ! access_allowed( be, conn, op, e,
"entry", NULL, ACL_AUTH ) )
{
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
+ rc = 1;
+ goto return_results;
+ }
+
+ if ( is_entry_alias( e ) ) {
+ /* entry is an alias, don't allow bind */
+ Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, NULL, NULL, NULL );
+
+ rc = 1;
+ goto return_results;
+ }
+
+ if ( is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow bind */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
rc = 1;
goto return_results;
}
switch ( method ) {
case LDAP_AUTH_SIMPLE:
if ( cred->bv_len == 0 ) {
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
/* stop front end from sending result */
rc = 1;
if ( ! access_allowed( be, conn, op, e,
"userpassword", NULL, ACL_AUTH ) )
{
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
rc = 1;
goto return_results;
}
if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
- NULL, NULL );
+ NULL, NULL, NULL, NULL );
/* stop front end from sending result */
rc = 1;
if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 )
{
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
- NULL, NULL );
+ NULL, NULL, NULL, NULL );
/* stop front end from sending result */
rc = 1;
goto return_results;
if ( ! access_allowed( be, conn, op, e,
"krbname", NULL, ACL_AUTH ) )
{
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
rc = 1;
goto return_results;
}
if ( krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) {
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
- NULL, NULL );
+ NULL, NULL, NULL, NULL );
rc = 1;
goto return_results;
}
if ( ! access_allowed( be, conn, op, e,
"krbname", NULL, ACL_AUTH ) )
{
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
rc = 1;
goto return_results;
}
break;
}
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
- NULL, NULL );
+ NULL, NULL, NULL, NULL );
rc = 1;
goto return_results;
if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) {
send_ldap_result( conn, op,
- LDAP_INVALID_CREDENTIALS, NULL, NULL );
+ LDAP_INVALID_CREDENTIALS,
+ NULL, NULL, NULL, NULL );
rc = 1;
goto return_results;
}
break;
case LDAP_AUTH_KRBV42:
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
/* stop front end from sending result */
rc = 1;
goto return_results;
default:
send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
- NULL, "auth method not supported" );
+ NULL, "auth method not supported", NULL, NULL );
rc = 1;
goto return_results;
}
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched;
+ Entry *matched;
Entry *e;
Attribute *a;
int rc;
+ int manageDSAit = get_manageDSAit( op );
/* get entry with reader lock */
if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
- if(matched == NULL) free(matched);
return( 1 );
}
- /* check for deleted */
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ rc = 1;
+ goto return_results;
+ }
+
if ( ! access_allowed( be, conn, op, e,
ava->ava_type, &ava->ava_value, ACL_COMPARE ) )
{
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
rc = 1;
goto return_results;
}
if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE, "", "" );
+ send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE,
+ NULL, NULL, NULL, NULL );
rc = 1;
goto return_results;
}
if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 )
- send_ldap_result( conn, op, LDAP_COMPARE_TRUE, "", "" );
+ send_ldap_result( conn, op, LDAP_COMPARE_TRUE,
+ NULL, NULL, NULL, NULL );
else
- send_ldap_result( conn, op, LDAP_COMPARE_FALSE, "", "" );
+ send_ldap_result( conn, op, LDAP_COMPARE_FALSE,
+ NULL, NULL, NULL, NULL );
rc = 0;
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = NULL;
+ Entry *matched = NULL;
char *pdn = NULL;
Entry *e, *p = NULL;
int rootlock = 0;
int rc = -1;
+ int manageDSAit = get_manageDSAit( op );
Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_delete: %s\n", dn, 0, 0);
/* get entry with writer lock */
if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: no such object %s\n",
dn, 0, 0);
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+
if ( matched != NULL ) {
- free( matched );
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
}
- return( -1 );
- }
- /* check for deleted */
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
- if ( has_children( be, e ) ) {
- Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: non leaf %s\n",
- dn, 0, 0);
- send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, "",
- "" );
- goto return_results;
+ if ( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ return( -1 );
}
#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
Debug(LDAP_DEBUG_ARGS,
"<=- ldbm_back_delete: insufficient access %s\n",
dn, 0, 0);
- send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
#endif
+ if ( !manageDSAit && is_entry_referral( e ) ) {
+ /* parent is a referral, don't allow add */
+ /* parent is an alias, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ rc = 1;
+ goto return_results;
+ }
+
+
+ if ( has_children( be, e ) ) {
+ Debug(LDAP_DEBUG_ARGS, "<=- ldbm_back_delete: non leaf %s\n",
+ dn, 0, 0);
+ send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF,
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
/* delete from parent's id2children entry */
if( (pdn = dn_parent( be, e->e_ndn )) != NULL ) {
if( (p = dn2entry_w( be, pdn, &matched )) == NULL) {
"<=- ldbm_back_delete: parent does not exist\n",
0, 0, 0);
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- "", "");
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"<=- ldbm_back_delete: no access to parent\n", 0,
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"<=- ldbm_back_delete: no parent & not root\n",
0, 0, 0);
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "");
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug(LDAP_DEBUG_ARGS,
"<=- ldbm_back_delete: operations error %s\n",
dn, 0, 0);
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "","" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug(LDAP_DEBUG_ARGS,
"<=- ldbm_back_delete: operations error %s\n",
dn, 0, 0);
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug(LDAP_DEBUG_ARGS,
"<=- ldbm_back_delete: operations error %s\n",
dn, 0, 0);
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
rc = 0;
return_results:;
dn2entry_rw(
Backend *be,
char *dn,
- char **matched,
+ Entry **matched,
int rw
)
{
Debug(LDAP_DEBUG_TRACE, "dn2entry_%s: dn: \"%s\"\n",
rw ? "w" : "r", dn, 0);
- *matched = NULL;
+ if( matched != NULL ) {
+ /* caller cares about match */
+ *matched = NULL;
+ }
if ( (id = dn2id( be, dn )) != NOID &&
(e = id2entry_rw( be, id, rw )) != NULL )
/* treat as if NOID was found */
}
- /* stop when we get to the suffix */
- if ( be_issuffix( be, dn ) ) {
- return( NULL );
- }
+ /* caller doesn't care about match */
+ if( matched == NULL ) return NULL;
/* entry does not exist - see how much of the dn does exist */
+ /* dn_parent checks returns NULL if dn is suffix */
if ( (pdn = dn_parent( be, dn )) != NULL ) {
/* get entry with reader lock */
if ( (e = dn2entry_r( be, pdn, matched )) != NULL ) {
- if(*matched != NULL) {
- free(*matched);
- }
- *matched = pdn;
- /* free entry with reader lock */
- cache_return_entry_r( &li->li_cache, e );
- } else {
- free( pdn );
+ *matched = e;
}
+ free( pdn );
}
- return( NULL );
+ return NULL;
}
char *groupattrName
)
{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Entry *e;
- char *matched;
- Attribute *objectClass;
- Attribute *member;
- int rc;
-
- Debug( LDAP_DEBUG_TRACE,
+ struct ldbminfo *li = (struct ldbminfo *) be->be_private;
+ Entry *e;
+ int rc = 1;
+
+ Attribute *attr;
+ struct berval bv;
+
+ Debug( LDAP_DEBUG_ARGS,
"=> ldbm_back_group: gr dn: \"%s\"\n",
gr_ndn, 0, 0 );
- Debug( LDAP_DEBUG_TRACE,
+ Debug( LDAP_DEBUG_ARGS,
"=> ldbm_back_group: op dn: \"%s\"\n",
op_ndn, 0, 0 );
- Debug( LDAP_DEBUG_TRACE,
+ Debug( LDAP_DEBUG_ARGS,
"=> ldbm_back_group: objectClass: \"%s\" attrName: \"%s\"\n",
objectclassValue, groupattrName, 0 );
- Debug( LDAP_DEBUG_TRACE,
+ Debug( LDAP_DEBUG_ARGS,
"=> ldbm_back_group: tr dn: \"%s\"\n",
target->e_ndn, 0, 0 );
e = target;
Debug( LDAP_DEBUG_ARGS,
"=> ldbm_back_group: target is group: \"%s\"\n",
- gr_ndn, 0, 0 );
+ gr_ndn, 0, 0 );
+
} else {
/* can we find group entry with reader lock */
- if ((e = dn2entry_r(be, gr_ndn, &matched )) == NULL) {
- Debug( LDAP_DEBUG_TRACE,
- "=> ldbm_back_group: cannot find group: \"%s\" matched: \"%s\"\n",
- gr_ndn, (matched ? matched : ""), 0 );
- if (matched != NULL)
- free(matched);
+ if ((e = dn2entry_r(be, gr_ndn, NULL )) == NULL) {
+ Debug( LDAP_DEBUG_ACL,
+ "=> ldbm_back_group: cannot find group: \"%s\"\n",
+ gr_ndn, 0, 0 );
return( 1 );
}
- Debug( LDAP_DEBUG_ARGS,
+
+ Debug( LDAP_DEBUG_ACL,
"=> ldbm_back_group: found group: \"%s\"\n",
gr_ndn, 0, 0 );
- }
+ }
+ /* find it's objectClass and member attribute values
+ * make sure this is a group entry
+ * finally test if we can find op_dn in the member attribute value list *
+ */
+
+ rc = 1;
+
+ if ((attr = attr_find(e->e_attrs, "objectclass")) == NULL) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: failed to find objectClass\n", 0, 0, 0 );
+ goto return_results;
+ }
+
+ bv.bv_val = "ALIAS";
+ bv.bv_len = sizeof("ALIAS")-1;
+
+ if ( value_find(attr->a_vals, &bv, attr->a_syntax, 1) == 0) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: group is an alias\n", 0, 0, 0 );
+ goto return_results;
+ }
- /* check for deleted */
+ bv.bv_val = "REFERRAL";
+ bv.bv_len = sizeof("REFERRAL")-1;
- /* find it's objectClass and member attribute values
- * make sure this is a group entry
- * finally test if we can find op_dn in the member attribute value list *
- */
-
- rc = 1;
- if ((objectClass = attr_find(e->e_attrs, "objectclass")) == NULL) {
- Debug( LDAP_DEBUG_TRACE, "<= ldbm_back_group: failed to find objectClass\n", 0, 0, 0 );
- }
- else if ((member = attr_find(e->e_attrs, groupattrName)) == NULL) {
- Debug( LDAP_DEBUG_TRACE, "<= ldbm_back_group: failed to find %s\n", groupattrName, 0, 0 );
- }
- else {
- struct berval bvObjectClass;
- struct berval bvMembers;
-
- Debug( LDAP_DEBUG_ARGS, "<= ldbm_back_group: found objectClass and %s\n", groupattrName, 0, 0 );
-
- bvObjectClass.bv_val = objectclassValue;
- bvObjectClass.bv_len = strlen( bvObjectClass.bv_val );
-
- bvMembers.bv_val = op_ndn;
- bvMembers.bv_len = strlen( op_ndn );
-
- if (value_find(objectClass->a_vals, &bvObjectClass, SYNTAX_CIS, 1) != 0) {
- Debug( LDAP_DEBUG_TRACE,
- "<= ldbm_back_group: failed to find %s in objectClass\n",
- objectclassValue, 0, 0 );
- }
- else if (value_find(member->a_vals, &bvMembers, SYNTAX_CIS, 1) != 0) {
- Debug( LDAP_DEBUG_ACL,
- "<= ldbm_back_group: \"%s\" not in \"%s\": %s\n",
- op_ndn, gr_ndn, groupattrName );
- }
- else {
- Debug( LDAP_DEBUG_ACL,
- "<= ldbm_back_group: \"%s\" is in \"%s\": %s\n",
- op_ndn, gr_ndn, groupattrName );
- rc = 0;
- }
- }
+ if ( value_find(attr->a_vals, &bv, attr->a_syntax, 1) == 0) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: group is a referral\n",
+ 0, 0, 0 );
+ goto return_results;
+ }
+
+ bv.bv_val = objectclassValue;
+ bv.bv_len = strlen( bv.bv_val );
+
+ if (value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: failed to find %s in objectClass\n",
+ objectclassValue, 0, 0 );
+ goto return_results;
+ }
+
+ if ((attr = attr_find(e->e_attrs, groupattrName)) == NULL) {
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: failed to find %s\n",
+ groupattrName, 0, 0 );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: found objectClass %s and %s\n",
+ objectclassValue, groupattrName, 0 );
+
+ bv.bv_val = op_ndn;
+ bv.bv_len = strlen( op_ndn );
+
+ if( value_find( attr->a_vals, &bv, attr->a_syntax, 1) != 0 )
+ {
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: \"%s\" not in \"%s\": %s\n",
+ op_ndn, gr_ndn, groupattrName );
+ goto return_results;
+ }
+
+ Debug( LDAP_DEBUG_ACL,
+ "<= ldbm_back_group: \"%s\" is in \"%s\": %s\n",
+ op_ndn, gr_ndn, groupattrName );
+
+ rc = 0;
+return_results:
if( target != e ) {
/* free entry and reader lock */
cache_return_entry_r( &li->li_cache, e );
}
- Debug( LDAP_DEBUG_ARGS, "ldbm_back_group: rc: %d\n", rc, 0, 0 );
+ Debug( LDAP_DEBUG_TRACE, "ldbm_back_group: rc=%d\n", rc, 0, 0 );
return(rc);
}
if ( (err = acl_check_modlist( be, conn, op, e, modlist ))
- != LDAP_SUCCESS ) {
- send_ldap_result( conn, op, err, NULL, NULL );
+ != LDAP_SUCCESS )
+ {
+ send_ldap_result( conn, op, err,
+ NULL, NULL, NULL, NULL );
return -1;
}
if ( err != LDAP_SUCCESS ) {
/* unlock entry, delete from cache */
- send_ldap_result( conn, op, err, NULL, NULL );
+ send_ldap_result( conn, op, err,
+ NULL, NULL, NULL, NULL );
return -1;
}
}
/* check that the entry still obeys the schema */
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
Debug( LDAP_DEBUG_ANY, "entry failed schema check\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
+ NULL, NULL, NULL, NULL );
return -1;
}
/* modify indexes */
if ( index_add_mods( be, modlist, e->e_id ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
return -1;
}
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched;
+ Entry *matched;
Entry *e;
+ int manageDSAit = get_manageDSAit( op );
Debug(LDAP_DEBUG_ARGS, "ldbm_back_modify:\n", 0, 0, 0);
/* acquire and lock entry */
if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched,
- NULL );
+ char* matched_dn = NULL;
+ struct berval **refs = NULL;
+
if ( matched != NULL ) {
- free( matched );
+ matched_dn = ch_strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
}
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ if ( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
return( -1 );
}
+ if ( !manageDSAit && is_entry_referral( e ) ) {
+ /* parent is a referral, don't allow add */
+ /* parent is an alias, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ goto error_return;
+ }
+
/* Modify the entry */
if ( ldbm_modify_internal( be, conn, op, dn, modlist, e ) != 0 ) {
-
goto error_return;
-
}
/* change the entry itself */
if ( id2entry_add( be, e ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto error_return;
}
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
cache_return_entry_w( &li->li_cache, e );
return( 0 );
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- char *matched = NULL;
char *p_dn = NULL, *p_ndn = NULL;
char *new_dn = NULL, *new_ndn = NULL;
Entry *e, *p = NULL;
+ Entry *matched = NULL;
int rootlock = 0;
int rc = -1;
/* Added to support LDAP v2 correctly (deleteoldrdn thing) */
struct berval del_bv; /* Stores old rdn att */
struct berval *del_bvals[2]; /* Stores old rdn att */
LDAPModList mod[2]; /* Used to delete old rdn */
-
+ int manageDSAit = get_manageDSAit( op );
Debug( LDAP_DEBUG_TRACE, "==>ldbm_back_modrdn(newSuperior=%s)\n",
(newSuperior ? newSuperior : "NULL"),
/* get entry with writer lock */
if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
- send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
+ char* matched_dn = NULL;
+ struct berval** refs = NULL;
+
+ if( matched != NULL ) {
+ matched_dn = strdup( matched->e_dn );
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+ cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
if ( matched != NULL ) {
- free( matched );
+ ber_bvecfree( refs );
+ free( matched_dn );
}
+
return( -1 );
}
#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
- /* check parent for "children" acl */
if ( ! access_allowed( be, conn, op, e,
"entry", NULL, ACL_WRITE ) )
{
Debug( LDAP_DEBUG_TRACE, "no access to entry\n", 0,
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
#endif
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* parent is a referral, don't allow add */
+ /* parent is an alias, don't allow add */
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ e->e_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+
+ goto return_results;
+ }
+
if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) {
- /* Make sure parent entry exist and we can write its
+ /* Make sure parent entry exist and we can write its
* children.
*/
Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
0, 0, 0);
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- "", "");
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE, "no parent & not root\n",
0, 0, 0);
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "");
+ NULL, NULL, NULL, NULL );
goto return_results;
}
/* Get Entry with dn=newSuperior. Does newSuperior exist? */
if( (np = dn2entry_w( be, np_ndn, &matched )) == NULL) {
-
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: newSup(ndn=%s) not here!\n",
np_ndn, 0, 0);
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "",
- "");
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
"ldbm_back_modrdn: no wr to newSup children\n",
0, 0, 0 );
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
- "", "" );
+ NULL, NULL, NULL, NULL );
+ goto return_results;
+ }
+
+ if ( is_entry_alias( np ) ) {
+ /* entry is an alias, don't allow bind */
+ Debug( LDAP_DEBUG_TRACE, "entry is alias\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_ALIAS_PROBLEM,
+ NULL, NULL, NULL, NULL );
+
+ goto return_results;
+ }
+
+ if ( is_entry_referral( np ) ) {
+ /* parent is a referral, don't allow add */
+ /* parent is an alias, don't allow add */
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
+
goto return_results;
}
"ldbm_back_modrdn: wr to new parent's children OK\n",
0, 0 , 0 );
-
new_parent_dn = np_dn;
-
}
/* Build target dn and make sure target entry doesn't exist already. */
new_ndn, 0, 0 );
if (dn2id ( be, new_ndn ) != NOID) {
- send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
/* delete old one */
if ( dn2id_delete( be, e->e_ndn ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
/* add new one */
if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: can't figure out type of newrdn\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: can't figure out val of newrdn\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: can't figure out old_rdn from dn\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: can't figure out the old_rdn type\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
/* Remove old rdn value if required */
if (deleteoldrdn) {
-
/* Get value of old rdn */
if ((old_rdn_val = rdn_attr_value( old_rdn ))
Debug( LDAP_DEBUG_TRACE,
"ldbm_back_modrdn: can't figure out old_rdn_val from old_rdn\n",
0, 0, 0 );
- send_ldap_result( conn, op,
- LDAP_OPERATIONS_ERROR,
- "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
-
-
}
del_bvals[0] = &del_bv; /* Array of bervals */
"ldbm_back_modrdn: not fully implemented...\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- NULL );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results;
}
/* id2entry index */
if ( id2entry_add( be, e ) != 0 ) {
entry_free( e );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
goto return_results_after;
}
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
rc = 0;
goto return_results_after;
/*
* alias.c
*/
-Entry *derefAlias_r LDAP_P((
- Backend *be,
- Connection *conn,
- Operation *op,
- Entry *e ));
-char *derefDN LDAP_P((
- Backend *be,
- Connection *conn,
- Operation *op,
- char *dn ));
+Entry *deref_internal_r LDAP_P((
+ Backend *be,
+ Entry *e,
+ char *dn,
+ int *err,
+ Entry **matched,
+ char **text ));
+
+#define deref_entry_r( be, e, err, matched, text ) \
+ deref_internal_r( be, e, NULL, err, matched, text )
+#define deref_dn_r( be, dn, err, matched, text ) \
+ deref_internal_r( be, NULL, dn, err, matched, text)
/*
* attr.c
ID dn2id LDAP_P(( Backend *be, char *dn ));
int dn2id_delete LDAP_P(( Backend *be, char *dn ));
-Entry * dn2entry_rw LDAP_P(( Backend *be, char *dn, char **matched, int rw ));
+Entry * dn2entry_rw LDAP_P(( Backend *be, char *dn, Entry **matched, int rw ));
#define dn2entry_r(be, dn, m) dn2entry_rw((be), (dn), (m), 0)
#define dn2entry_w(be, dn, m) dn2entry_rw((be), (dn), (m), 1)
#include "back-ldbm.h"
#include "proto-back-ldbm.h"
-static ID_BLOCK *base_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
-static ID_BLOCK *onelevel_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, int *err);
-static ID_BLOCK *subtree_candidates(Backend *be, Connection *conn, Operation *op, char *base, Filter *filter, char **attrs, int attrsonly, char **matched, Entry *e, int *err, int lookupbase);
-
-#define GRABSIZE BUFSIZ
-
-#define MAKE_SPACE( n ) { \
- if ( rcur + (n) > rbuf + rmaxsize ) { \
- int offset = rcur - rbuf; \
- rbuf = ch_realloc( rbuf, rmaxsize + GRABSIZE ); \
- rmaxsize += GRABSIZE; \
- rcur = rbuf + offset; \
- } \
-}
+static ID_BLOCK *base_candidate(
+ Backend *be, Entry *e );
+
+static ID_BLOCK *search_candidates(
+ Backend *be, Entry *e, Filter *filter,
+ int scope, int deref, int manageDSAit );
+
int
ldbm_back_search(
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- int err;
+ int rc, err;
+ char *text;
time_t stoptime;
ID_BLOCK *candidates;
ID id;
Entry *e;
- Attribute *ref;
- char *matched = NULL;
- int rmaxsize, nrefs;
- char *rbuf, *rcur;
+ struct berval **v2refs = NULL;
+ Entry *matched = NULL;
+ char *realbase = NULL;
int nentries = 0;
- char *realBase;
+ int manageDSAit = get_manageDSAit( op );
+
+ Debug(LDAP_DEBUG_TRACE, "=> ldbm_back_search\n", 0, 0, 0);
+
+ /* get entry with reader lock */
+ if ( deref & LDAP_DEREF_FINDING ) {
+ e = deref_dn_r( be, base, &err, &matched, &text );
- Debug(LDAP_DEBUG_ARGS, "=> ldbm_back_search\n", 0, 0, 0);
+ } else {
+ e = dn2entry_r( be, base, &matched );
+ err = e != NULL ? LDAP_SUCCESS : LDAP_REFERRAL;
+ text = NULL;
+ }
+
+ if ( e == NULL ) {
+ char *matched_dn = NULL;
+ struct berval **refs = NULL;
+
+ if ( matched != NULL ) {
+ matched_dn = ch_strdup( matched->e_dn );
+
+ refs = is_entry_referral( matched )
+ ? get_entry_referrals( be, conn, op, matched )
+ : NULL;
+
+ cache_return_entry_r( &li->li_cache, matched );
+ } else {
+ refs = default_referral;
+ }
+
+ send_ldap_result( conn, op, err,
+ matched_dn, text, refs, NULL );
+
+ if( matched != NULL ) {
+ ber_bvecfree( refs );
+ free( matched_dn );
+ }
+
+ return 1;
+ }
+
+ if (!manageDSAit && is_entry_referral( e ) ) {
+ /* entry is a referral, don't allow add */
+ char *matched_dn = ch_strdup( e->e_dn );
+ struct berval **refs = get_entry_referrals( be,
+ conn, op, e );
+
+ cache_return_entry_r( &li->li_cache, e );
+
+ Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0,
+ 0, 0 );
+
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ matched_dn, NULL, refs, NULL );
+
+ ber_bvecfree( refs );
+ free( matched_dn );
+
+ return 1;
+ }
if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
tlimit = -1; /* allow root to set no limit */
be->be_timelimit : tlimit;
stoptime = op->o_time + tlimit;
}
+
if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
slimit = -1; /* allow root to set no limit */
} else {
be->be_sizelimit : slimit;
}
- /*
- * check and apply aliasing where the dereferencing applies to
- * the subordinates of the base
- */
-
- switch ( deref ) {
- case LDAP_DEREF_FINDING:
- case LDAP_DEREF_ALWAYS:
- realBase = derefDN ( be, conn, op, base );
- break;
- default:
- realBase = ch_strdup(base);
- }
-
- (void) dn_normalize_case( realBase );
-
- Debug( LDAP_DEBUG_TRACE, "using base \"%s\"\n",
- realBase, 0, 0 );
-
- switch ( scope ) {
- case LDAP_SCOPE_BASE:
- candidates = base_candidates( be, conn, op, realBase, filter,
- attrs, attrsonly, &matched, &err );
- break;
+ if ( scope == LDAP_SCOPE_BASE) {
+ candidates = base_candidate( be, e );
- case LDAP_SCOPE_ONELEVEL:
- candidates = onelevel_candidates( be, conn, op, realBase, filter,
- attrs, attrsonly, &matched, &err );
- break;
-
- case LDAP_SCOPE_SUBTREE:
- candidates = subtree_candidates( be, conn, op, realBase, filter,
- attrs, attrsonly, &matched, NULL, &err, 1 );
- break;
-
- default:
- send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, "",
- "Bad scope" );
- if( realBase != NULL) {
- free( realBase );
- }
- return( -1 );
+ } else {
+ candidates = search_candidates( be, e, filter,
+ scope, deref, manageDSAit );
}
- /* null candidates means we could not find the base object */
+ /* need normalized dn below */
+ realbase = ch_strdup( e->e_ndn );
+ cache_return_entry_r( &li->li_cache, e );
+
if ( candidates == NULL ) {
- send_ldap_result( conn, op, err, matched, "" );
- if ( matched != NULL ) {
- free( matched );
- }
- if( realBase != NULL) {
- free( realBase );
- }
- return( -1 );
- }
+ /* no candidates */
+ Debug( LDAP_DEBUG_TRACE, "no candidates\n", 0,
+ 0, 0 );
+
+ send_search_result( conn, op,
+ LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 0 );
- if ( matched != NULL ) {
- free( matched );
+ rc = 1;
+ goto done;
}
- rmaxsize = 0;
- nrefs = 0;
- rbuf = rcur = NULL;
- MAKE_SPACE( sizeof("Referral:") + 1 );
- strcpy( rbuf, "Referral:" );
- rcur = strchr( rbuf, '\0' );
for ( id = idl_firstid( candidates ); id != NOID;
- id = idl_nextid( candidates, id ) ) {
+ id = idl_nextid( candidates, id ) )
+ {
+ int scopeok = 0;
/* check for abandon */
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
+
if ( op->o_abandon ) {
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
- idl_free( candidates );
- free( rbuf );
- if( realBase != NULL) {
- free( realBase );
- }
- return( 0 );
+ rc = 0;
+ goto done;
}
+
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
/* check time limit */
if ( tlimit != -1 && slap_get_time() > stoptime ) {
- send_ldap_search_result( conn, op,
- LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
- NULL, nentries );
- idl_free( candidates );
- free( rbuf );
- if( realBase != NULL) {
- free( realBase );
- }
- return( 0 );
+ send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
+ NULL, NULL, v2refs, NULL, nentries );
+ rc = 0;
+ goto done;
}
/* get the entry with reader lock */
- if ( (e = id2entry_r( be, id )) == NULL ) {
- Debug( LDAP_DEBUG_ARGS, "candidate %ld not found\n",
- id, 0, 0 );
- continue;
+ e = id2entry_r( be, id );
+
+ if ( e == NULL ) {
+ Debug( LDAP_DEBUG_ARGS, "search: candidate %ld not found\n",
+ id, 0, 0 );
+
+ goto loop_continue;
+ }
+
+ if ( deref & LDAP_DEREF_SEARCHING && is_entry_alias( e ) ) {
+ Entry *matched;
+ int err;
+ char *text;
+
+ e = deref_entry_r( be, e, &err, &matched, &text );
+
+ if( e == NULL ) {
+ e = matched;
+ goto loop_continue;
+ }
+
+ if( e->e_id == id ) {
+ /* circular loop */
+ goto loop_continue;
+ }
+
+ /* need to skip alias which deref into scope */
+ if( scope & LDAP_SCOPE_ONELEVEL ) {
+ char *pdn = dn_parent( NULL, e->e_ndn );
+ if ( pdn != NULL ) {
+ if( strcmp( pdn, realbase ) ) {
+ free( pdn );
+ goto loop_continue;
+ }
+ free(pdn);
+ }
+
+ } else if ( dn_issuffix( e->e_ndn, realbase ) ) {
+ /* alias is within scope */
+ Debug( LDAP_DEBUG_ARGS, "search: \"%s\" in subtree\n",
+ e->e_dn, 0, 0 );
+ goto loop_continue;
+ }
+
+ scopeok = 1;
}
/*
* if it's a referral, add it to the list of referrals. only do
- * this for subtree searches, and don't check the filter explicitly
- * here since it's only a candidate anyway.
+ * this for non-base searches, and don't check the filter
+ * explicitly here since it's only a candidate anyway.
*/
- if ( scope == LDAP_SCOPE_SUBTREE &&
- e->e_ndn != NULL &&
- strncmp( e->e_ndn, "REF=", 4 ) == 0 &&
- (ref = attr_find( e->e_attrs, "ref" )) != NULL )
+ if ( !manageDSAit && scope != LDAP_SCOPE_BASE &&
+ is_entry_referral( e ) )
{
- int i;
+ struct berval **refs = get_entry_referrals(
+ be, conn, op, e );
- if ( ref->a_vals == NULL ) {
- Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n",
- e->e_dn, 0, 0 );
- } else {
- for ( i = 0; ref->a_vals[i] != NULL; i++ ) {
- /* referral + newline + null */
- MAKE_SPACE( ref->a_vals[i]->bv_len + 2 );
- *rcur++ = '\n';
- strncpy( rcur, ref->a_vals[i]->bv_val,
- ref->a_vals[i]->bv_len );
- rcur = rcur + ref->a_vals[i]->bv_len;
- *rcur = '\0';
- nrefs++;
- }
- }
+ send_search_reference( be, conn, op,
+ e, refs, scope, NULL, &v2refs );
- /* otherwise it's an entry - see if it matches the filter */
- } else {
- /* if it matches the filter and scope, send it */
- if ( test_filter( be, conn, op, e, filter ) == 0 ) {
- int scopeok;
- char *dn;
+ ber_bvecfree( refs );
- /* check scope */
- scopeok = 1;
- if ( scope == LDAP_SCOPE_ONELEVEL ) {
- if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
- (void) dn_normalize_case( dn );
- scopeok = (dn == realBase)
- ? 1
- : (strcmp( dn, realBase ) ? 0 : 1 );
- free( dn );
- } else {
- scopeok = (realBase == NULL || *realBase == '\0');
- }
- } else if ( scope == LDAP_SCOPE_SUBTREE ) {
- dn = ch_strdup( e->e_ndn );
- scopeok = dn_issuffix( dn, realBase );
+ goto loop_continue;
+ }
+
+ /* if it matches the filter and scope, send it */
+ if ( test_filter( be, conn, op, e, filter ) == 0 ) {
+ char *dn;
+
+ /* check scope */
+ if ( !scopeok && scope == LDAP_SCOPE_ONELEVEL ) {
+ if ( (dn = dn_parent( be, e->e_ndn )) != NULL ) {
+ (void) dn_normalize_case( dn );
+ scopeok = (dn == realbase)
+ ? 1
+ : (strcmp( dn, realbase ) ? 0 : 1 );
free( dn );
+
+ } else {
+ scopeok = (realbase == NULL || *realbase == '\0');
}
- if ( scopeok ) {
- /* check size limit */
- if ( --slimit == -1 ) {
- cache_return_entry_r( &li->li_cache, e );
- send_ldap_search_result( conn, op,
- LDAP_SIZELIMIT_EXCEEDED, NULL,
- nrefs > 0 ? rbuf : NULL, nentries );
- idl_free( candidates );
- free( rbuf );
-
- if( realBase != NULL) {
- free( realBase );
- }
- return( 0 );
- }
+ } else if ( !scopeok && scope == LDAP_SCOPE_SUBTREE ) {
+ dn = ch_strdup( e->e_ndn );
+ scopeok = dn_issuffix( dn, realbase );
+ free( dn );
+
+ } else {
+ scopeok = 1;
+ }
+
+ if ( scopeok ) {
+ /* check size limit */
+ if ( --slimit == -1 ) {
+ cache_return_entry_r( &li->li_cache, e );
+ send_search_result( conn, op,
+ LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
+ v2refs, NULL, nentries );
+ rc = 0;
+ goto done;
+ }
- /*
- * check and apply aliasing where the dereferencing applies to
- * the subordinates of the base
- */
- switch ( deref ) {
- case LDAP_DEREF_SEARCHING:
- case LDAP_DEREF_ALWAYS:
- {
- Entry *newe = derefAlias_r( be, conn, op, e );
- if ( newe == NULL ) { /* problem with the alias */
- cache_return_entry_r( &li->li_cache, e );
- e = NULL;
- }
- else if ( newe != e ) { /* reassign e */
- cache_return_entry_r( &li->li_cache, e );
- e = newe;
- }
- }
+ if (e) {
+ switch ( send_search_entry( be, conn, op, e,
+ attrs, attrsonly, 0, NULL ) ) {
+ case 0: /* entry sent ok */
+ nentries++;
break;
- }
- if (e) {
- switch ( send_search_entry( be, conn, op, e,
- attrs, attrsonly, 0 ) ) {
- case 0: /* entry sent ok */
- nentries++;
- break;
- case 1: /* entry not sent */
- break;
- case -1: /* connection closed */
- cache_return_entry_r( &li->li_cache, e );
- idl_free( candidates );
- free( rbuf );
-
- if( realBase != NULL) {
- free( realBase );
- }
- return( 0 );
- }
+ case 1: /* entry not sent */
+ break;
+ case -1: /* connection closed */
+ cache_return_entry_r( &li->li_cache, e );
+ rc = 0;
+ goto done;
}
}
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "candidate %ld scope not okay\n",
+ id, 0, 0 );
}
+ } else {
+ Debug( LDAP_DEBUG_TRACE, "candidate %ld does match filter\n",
+ id, 0, 0 );
}
+loop_continue:
if( e != NULL ) {
/* free reader lock */
cache_return_entry_r( &li->li_cache, e );
ldap_pvt_thread_yield();
}
+ send_search_result( conn, op,
+ v2refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
+ NULL, NULL, v2refs, NULL, nentries );
+
+ rc = 0;
+
+done:
idl_free( candidates );
- if ( nrefs > 0 ) {
- send_ldap_search_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- rbuf, nentries );
- } else {
- send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL,
- nentries );
- }
- free( rbuf );
- if( realBase != NULL) {
- free( realBase );
- }
+ ber_bvecfree( v2refs );
+ if( realbase ) free( realbase );
- return( 0 );
+ return rc;
}
static ID_BLOCK *
-base_candidates(
+base_candidate(
Backend *be,
- Connection *conn,
- Operation *op,
- char *base,
- Filter *filter,
- char **attrs,
- int attrsonly,
- char **matched,
- int *err
+ Entry *e
)
{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
ID_BLOCK *idl;
- Entry *e;
-
- Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n", base, 0, 0);
- *err = LDAP_SUCCESS;
-
- /* get entry with reader lock */
- if ( (e = dn2entry_r( be, base, matched )) == NULL ) {
- *err = LDAP_NO_SUCH_OBJECT;
- return( NULL );
- }
-
- /* check for deleted */
+ Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n",
+ e->e_dn, 0, 0);
idl = idl_alloc( 1 );
idl_insert( &idl, e->e_id, 1 );
-
- /* free reader lock */
- cache_return_entry_r( &li->li_cache, e );
-
return( idl );
}
static ID_BLOCK *
-onelevel_candidates(
+search_candidates(
Backend *be,
- Connection *conn,
- Operation *op,
- char *base,
+ Entry *e,
Filter *filter,
- char **attrs,
- int attrsonly,
- char **matched,
- int *err
+ int scope,
+ int deref,
+ int manageDSAit
)
{
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Entry *e = NULL;
- Filter *f;
- char buf[20];
ID_BLOCK *candidates;
+ Filter *f, *rf, *af, *lf;
- Debug(LDAP_DEBUG_TRACE, "onelevel_candidates: base: \"%s\"\n", base, 0, 0);
+ Debug(LDAP_DEBUG_TRACE, "search_candidates: base=\"%s\" s=%d d=%d\n",
+ e->e_ndn, scope, deref );
- *err = LDAP_SUCCESS;
+ f = NULL;
- /* get the base object with reader lock */
- if ( base != NULL && *base != '\0' &&
- (e = dn2entry_r( be, base, matched )) == NULL )
- {
- *err = LDAP_NO_SUCH_OBJECT;
- return( NULL );
+ if( !manageDSAit ) {
+ /* match referrals */
+ rf = (Filter *) ch_malloc( sizeof(Filter) );
+ rf->f_next = NULL;
+ rf->f_choice = LDAP_FILTER_OR;
+ rf->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+ rf->f_or->f_choice = LDAP_FILTER_EQUALITY;
+ rf->f_or->f_avtype = ch_strdup( "objectclass" );
+ rf->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
+ rf->f_or->f_avvalue.bv_len = sizeof("REFERRAL")-1;
+ rf->f_or->f_next = filter;
+ f = rf;
+ } else {
+ rf = NULL;
+ f = filter;
}
- /*
- * modify the filter to be something like this:
- *
- * parent=baseobject & originalfilter
- */
-
- f = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_next = NULL;
- f->f_choice = LDAP_FILTER_AND;
- f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_and->f_choice = LDAP_FILTER_EQUALITY;
- f->f_and->f_ava.ava_type = ch_strdup( "id2children" );
- sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
- f->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
- f->f_and->f_ava.ava_value.bv_len = strlen( buf );
- f->f_and->f_next = filter;
-
- /* from here, it's just like subtree_candidates */
- candidates = subtree_candidates( be, conn, op, base, f, attrs,
- attrsonly, matched, e, err, 0 );
-
- /* free up just the filter stuff we allocated above */
- f->f_and->f_next = NULL;
- filter_free( f );
-
- /* free entry and reader lock */
- if( e != NULL ) {
- cache_return_entry_r( &li->li_cache, e );
+ if( deref & LDAP_DEREF_SEARCHING ) {
+ /* match aliases */
+ af = (Filter *) ch_malloc( sizeof(Filter) );
+ af->f_next = NULL;
+ af->f_choice = LDAP_FILTER_OR;
+ af->f_or = (Filter *) ch_malloc( sizeof(Filter) );
+ af->f_or->f_choice = LDAP_FILTER_EQUALITY;
+ af->f_or->f_avtype = ch_strdup( "objectclass" );
+ af->f_or->f_avvalue.bv_val = ch_strdup( "ALIAS" );
+ af->f_or->f_avvalue.bv_len = sizeof("ALIAS")-1;
+ af->f_or->f_next = f;
+ f = af;
+ } else {
+ af = NULL;
}
- return( candidates );
-}
-static ID_BLOCK *
-subtree_candidates(
- Backend *be,
- Connection *conn,
- Operation *op,
- char *base,
- Filter *filter,
- char **attrs,
- int attrsonly,
- char **matched,
- Entry *e,
- int *err,
- int lookupbase
-)
-{
- struct ldbminfo *li = (struct ldbminfo *) be->be_private;
- Filter *f, **filterarg_ptr;
- ID_BLOCK *candidates;
+ if ( scope == LDAP_SCOPE_SUBTREE ) {
+ lf = (Filter *) ch_malloc( sizeof(Filter) );
+ lf->f_next = NULL;
+ lf->f_choice = LDAP_FILTER_AND;
+ lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
- Debug(LDAP_DEBUG_TRACE, "subtree_candidates: base: \"%s\" %s\n",
- base ? base : "NULL", lookupbase ? "lookupbase" : "", 0);
-
- /*
- * get the base object - unless we already have it (from one-level).
- * also, unless this is a one-level search or a subtree search
- * starting at the very top of our subtree, we need to modify the
- * filter to be something like this:
- *
- * dn=*baseobjectdn & (originalfilter | ref=*)
- *
- * the "objectclass=referral" part is used to select referrals to return
- */
-
- *err = LDAP_SUCCESS;
- f = NULL;
- if ( lookupbase ) {
- e = NULL;
+ lf->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
+ lf->f_and->f_sub_type = ch_strdup( "dn" );
+ lf->f_and->f_sub_initial = NULL;
+ lf->f_and->f_sub_any = NULL;
+ lf->f_and->f_sub_final = ch_strdup( e->e_ndn );
- if ( base != NULL && *base != '\0' &&
- (e = dn2entry_r( be, base, matched )) == NULL )
- {
- *err = LDAP_NO_SUCH_OBJECT;
- return( NULL );
- }
+ lf->f_and->f_next = f;
+ f = lf;
- if (e) {
- cache_return_entry_r( &li->li_cache, e );
- }
+ } else if ( scope == LDAP_SCOPE_ONELEVEL ) {
+ char buf[16];
- f = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_next = NULL;
- f->f_choice = LDAP_FILTER_OR;
- f->f_or = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_or->f_choice = LDAP_FILTER_EQUALITY;
- f->f_or->f_avtype = ch_strdup( "objectclass" );
- /* Patch to use normalized uppercase */
- f->f_or->f_avvalue.bv_val = ch_strdup( "REFERRAL" );
- f->f_or->f_avvalue.bv_len = strlen( "REFERRAL" );
- filterarg_ptr = &f->f_or->f_next;
- *filterarg_ptr = filter;
- filter = f;
-
- if ( ! be_issuffix( be, base ) ) {
- f = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_next = NULL;
- f->f_choice = LDAP_FILTER_AND;
- f->f_and = (Filter *) ch_malloc( sizeof(Filter) );
- f->f_and->f_choice = LDAP_FILTER_SUBSTRINGS;
- f->f_and->f_sub_type = ch_strdup( "dn" );
- f->f_and->f_sub_initial = NULL;
- f->f_and->f_sub_any = NULL;
- f->f_and->f_sub_final = ch_strdup( base );
- value_normalize( f->f_and->f_sub_final, SYNTAX_CIS );
- f->f_and->f_next = filter;
- filter = f;
- }
+ lf = (Filter *) ch_malloc( sizeof(Filter) );
+ lf->f_next = NULL;
+ lf->f_choice = LDAP_FILTER_AND;
+ lf->f_and = (Filter *) ch_malloc( sizeof(Filter) );
+
+ lf->f_and->f_choice = LDAP_FILTER_EQUALITY;
+ lf->f_and->f_ava.ava_type = ch_strdup( "id2children" );
+ sprintf( buf, "%ld", e != NULL ? e->e_id : 0 );
+ lf->f_and->f_ava.ava_value.bv_val = ch_strdup( buf );
+ lf->f_and->f_ava.ava_value.bv_len = strlen( buf );
+
+ lf->f_and->f_next = f;
+ f = lf;
+
+ } else {
+ lf = NULL;
}
- candidates = filter_candidates( be, filter );
+ candidates = filter_candidates( be, f );
+
+ /* free up filter additions we allocated above */
+ if( lf != NULL ) {
+ lf->f_and->f_next = NULL;
+ filter_free( lf );
+ }
+
+ if( af != NULL ) {
+ af->f_or->f_next = NULL;
+ filter_free( af );
+ }
- /* free up just the parts we allocated above */
- if ( f != NULL ) {
- *filterarg_ptr = NULL;
- filter_free( f );
+ if( rf != NULL ) {
+ rf->f_or->f_next = NULL;
+ filter_free( rf );
}
return( candidates );
int attrsonly
)
{
- int sent = 0;
struct passwd *pw;
Entry *e;
char *s;
time_t stoptime;
- int err = LDAP_NO_SUCH_OBJECT;
+
+ int sent = 0;
+ int err = LDAP_SUCCESS;
char *rdn = NULL;
char *parent = NULL;
vals[0] = &val;
vals[1] = NULL;
- /* Create an entry corresponding to the base DN */
- e = (Entry *) ch_calloc(1, sizeof(Entry));
- e->e_attrs = NULL;
- e->e_dn = strdup(base);
-
- /* Use the first attribute of the DN
- * as an attribute within the entry itself.
- */
- rdn = dn_rdn(NULL, base);
+ matched = ch_strdup( base );
- if( rdn == NULL || (s = strchr(rdn, '=')) == NULL ) {
- err = LDAP_INVALID_DN_SYNTAX;
- goto done;
- }
+ if( scope != LDAP_SCOPE_ONELEVEL ) {
+ /* Create an entry corresponding to the base DN */
+ e = (Entry *) ch_calloc(1, sizeof(Entry));
+ e->e_attrs = NULL;
+ e->e_dn = ch_strdup( base );
- val.bv_val = rdn_attr_value(rdn);
- val.bv_len = strlen( val.bv_val );
- attr_merge( e, rdn_attr_type(rdn), vals );
+ /* Use the first attribute of the DN
+ * as an attribute within the entry itself.
+ */
+ rdn = dn_rdn(NULL, base);
- free(rdn);
- rdn = NULL;
+ if( rdn == NULL || (s = strchr(rdn, '=')) == NULL ) {
+ err = LDAP_INVALID_DN_SYNTAX;
+ goto done;
+ }
- /* Every entry needs an objectclass. We don't really
- * know if our hardcoded choice here agrees with the
- * DN that was configured for this backend, but it's
- * better than nothing.
- *
- * should be a configuratable item
- */
- val.bv_val = "organizationalUnit";
- val.bv_len = strlen( val.bv_val );
- attr_merge( e, "objectClass", vals );
+ val.bv_val = rdn_attr_value(rdn);
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, rdn_attr_type(rdn), vals );
+
+ free(rdn);
+ rdn = NULL;
+
+ /* Every entry needs an objectclass. We don't really
+ * know if our hardcoded choice here agrees with the
+ * DN that was configured for this backend, but it's
+ * better than nothing.
+ *
+ * should be a configuratable item
+ */
+ val.bv_val = "organizationalUnit";
+ val.bv_len = strlen( val.bv_val );
+ attr_merge( e, "objectClass", vals );
- if ( test_filter( be, conn, op, e, filter ) == 0 ) {
- send_search_entry( be, conn, op, e, attrs, attrsonly, 0 );
- matched = strdup( be->be_suffix[0] );
- sent++;
+ if ( test_filter( be, conn, op, e, filter ) == 0 ) {
+ send_search_entry( be, conn, op,
+ e, attrs, attrsonly, 0, NULL );
+ sent++;
+ }
}
if ( scope != LDAP_SCOPE_BASE ) {
/* check time limit */
if ( slap_get_time() > stoptime ) {
send_ldap_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
- NULL, NULL );
+ NULL, NULL, NULL, NULL );
endpwent();
return( 0 );
}
/* check size limit */
if ( --slimit == -1 ) {
send_ldap_result( conn, op, LDAP_SIZELIMIT_EXCEEDED,
- NULL, NULL );
+ NULL, NULL, NULL, NULL );
endpwent();
return( 0 );
}
- send_search_entry( be, conn, op, e, attrs, attrsonly, 0 );
+ send_search_entry( be, conn, op,
+ e, attrs, attrsonly, 0, NULL );
sent++;
}
* anything deeper than that.
*/
if( !be_issuffix( be, parent ) ) {
+ int i;
+ for( i=0; be->be_suffix[i] != NULL; i++ ) {
+ if( dn_issuffix( base, be->be_suffix[i] ) ) {
+ matched = ch_strdup( be->be_suffix[i] );
+ break;
+ }
+ }
+ err = LDAP_NO_SUCH_OBJECT;
+ goto done;
+ }
+
+ if( scope == LDAP_SCOPE_ONELEVEL ) {
goto done;
}
rdn = dn_rdn( NULL, base );
if ( (user = rdn_attr_value(rdn)) == NULL) {
- err = LDAP_INVALID_DN_SYNTAX;
+ err = LDAP_OPERATIONS_ERROR;
goto done;
}
}
if ( (pw = getpwnam( user )) == NULL ) {
+ matched = parent;
+ parent = NULL;
+ err = LDAP_NO_SUCH_OBJECT;
goto done;
}
e = pw2entry( be, pw, rdn );
if ( test_filter( be, conn, op, e, filter ) == 0 ) {
- send_search_entry( be, conn, op, e, attrs, attrsonly, 0 );
+ send_search_entry( be, conn, op,
+ e, attrs, attrsonly, 0, NULL );
sent++;
}
}
done:
- if( sent ) {
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
-
- } else {
- send_ldap_result( conn, op, err, matched, NULL );
- }
+ send_ldap_result( conn, op,
+ err, err == LDAP_NO_SUCH_OBJECT ? matched : NULL, NULL,
+ NULL, NULL );
if( matched != NULL ) free( matched );
if( parent != NULL ) free( parent );
ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
if( return_code != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
} else {
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
}
Debug( LDAP_DEBUG_ANY, "Here ADD\n", 0, 0, 0 );
PerlBackend *perl_back = (PerlBackend *)be->be_private;
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
- "", "not yet implemented" );
+ NULL, "not yet implemented", NULL, NULL );
#ifdef notdef
ldap_pvt_thread_mutex_lock( &perl_interpreter_mutex );
ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
if( return_code != 0 ) {
- send_ldap_result( conn, op, LDAP_COMPARE_TRUE, "", "" );
+ send_ldap_result( conn, op, LDAP_COMPARE_TRUE, NULL, NULL );
} else {
- send_ldap_result( conn, op, LDAP_COMPARE_FALSE, "", "" );
+ send_ldap_result( conn, op, LDAP_COMPARE_FALSE, NULL, NULL );
}
#endif
ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
if( return_code != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
} else {
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
}
Debug( LDAP_DEBUG_ANY, "Here DELETE\n", 0, 0, 0 );
ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
if( return_code != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
} else {
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
}
Debug( LDAP_DEBUG_ANY, "Perl MODIFY\n", 0, 0, 0 );
ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
if( return_code != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
} else {
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
}
Debug( LDAP_DEBUG_ANY, "Perl MODRDN\n", 0, 0, 0 );
Debug( LDAP_DEBUG_ANY, "str2entry(%s) failed\n", buf, 0, 0 );
} else {
- send_search_entry( be,
- conn,
- op,
- e,
- attrs,
- attrsonly,
- 0 );
+ send_search_entry( be, conn, op,
+ e, attrs, attrsonly, 0, NULL );
entry_free( e );
}
ldap_pvt_thread_mutex_unlock( &perl_interpreter_mutex );
if( return_code != 0 ) {
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, NULL, NULL, NULL );
} else {
- send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
}
}
Operation *op
)
{
- send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM,
- "", "not yet implemented" );
Debug( LDAP_DEBUG_TRACE, "Perl UNBIND\n", 0, 0, 0 );
return 0;
}
if ( si->si_add == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "add not implemented" );
+ "add not implemented", NULL, NULL );
return( -1 );
}
if ( (op->o_private = (void *) forkandexec( si->si_add, &rfp, &wfp )) == (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
+ "could not fork/exec", NULL, NULL );
return( -1 );
}
if ( si->si_bind == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "bind not implemented" );
+ "bind not implemented", NULL, NULL );
return( -1 );
}
if ( (op->o_private = (void *) forkandexec( si->si_bind, &rfp, &wfp ))
== (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
+ "could not fork/exec", NULL, NULL );
return( -1 );
}
if ( si->si_compare == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "compare not implemented" );
+ "compare not implemented", NULL, NULL );
return( -1 );
}
if ( (op->o_private = (void *) forkandexec( si->si_compare, &rfp, &wfp ))
== (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
+ "could not fork/exec", NULL, NULL );
return( -1 );
}
if ( si->si_delete == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "delete not implemented" );
+ "delete not implemented", NULL, NULL );
return( -1 );
}
if ( (op->o_private = (void *) forkandexec( si->si_delete, &rfp, &wfp ))
== (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
+ "could not fork/exec", NULL, NULL );
return( -1 );
}
if ( si->si_modify == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "modify not implemented" );
+ "modify not implemented", NULL, NULL );
return( -1 );
}
if ( (op->o_private = (void *) forkandexec( si->si_modify, &rfp, &wfp ))
== (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
+ "could not fork/exec", NULL, NULL );
return( -1 );
}
if ( si->si_modrdn == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "modrdn not implemented" );
+ "modrdn not implemented", NULL, NULL );
return( -1 );
}
if ( (op->o_private = (void *) forkandexec( si->si_modrdn, &rfp, &wfp ))
== (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
+ "could not fork/exec", NULL, NULL );
return( -1 );
}
buf, 0, 0 );
} else {
send_search_entry( be, conn, op, e, attrs,
- attrsonly, 0 );
+ attrsonly, 0, NULL );
entry_free( e );
}
/* otherwise, front end will send this result */
if ( err != 0 || op->o_tag != LDAP_REQ_BIND ) {
- send_ldap_result( conn, op, err, matched, info );
+ send_ldap_result( conn, op, err, matched, info, NULL, NULL );
}
free( buf );
if ( si->si_search == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "search not implemented" );
+ "search not implemented", NULL, NULL );
return( -1 );
}
if ( (op->o_private = (void *) forkandexec( si->si_search, &rfp, &wfp ))
== (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
+ "could not fork/exec", NULL, NULL );
return( -1 );
}
if ( si->si_unbind == NULL ) {
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "unbind not implemented" );
+ "unbind not implemented", NULL, NULL );
return 0;
}
if ( (op->o_private = (void *) forkandexec( si->si_unbind, &rfp, &wfp ))
== (void *) -1 ) {
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "could not fork/exec" );
+ "could not fork/exec", NULL, NULL );
return 0;
}
/* add.c - tcl add routine
*
- * $Id: tcl_add.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $
+ * $Id: tcl_add.c,v 1.5.6.1 1999/07/09 18:02:59 kdz Exp $
*
* Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
*
if (ti->ti_add == NULL) {
send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "add not implemented");
+ "add not implemented", NULL );
return (-1);
}
if (err != LDAP_SUCCESS)
send_ldap_result (conn, op, err, NULL,
- "internal backend error");
+ "internal backend error", NULL );
free (results);
return (err);
/* bind.c - tcl bind routines
*
- * $Id: tcl_bind.c,v 1.5 1999/02/28 04:55:48 bcollins Exp $
+ * $Id: tcl_bind.c,v 1.6.2.1 1999/07/09 18:02:59 kdz Exp $
*
* Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
*
if (ti->ti_bind == NULL) {
send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "bind not implemented");
+ "bind not implemented", NULL );
return (-1);
}
if (err != LDAP_SUCCESS)
send_ldap_result (conn, op, err, NULL,
- "internal backend error");
+ "internal backend error", NULL );
free (results);
return (err);
/* compare.c - tcl compare routines
*
- * $Id: tcl_compare.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $
+ * $Id: tcl_compare.c,v 1.5.6.1 1999/07/09 18:02:59 kdz Exp $
*
* Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
*
if (ti->ti_compare == NULL) {
send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "compare not implemented");
+ "compare not implemented", NULL );
return (-1);
}
if (err != LDAP_SUCCESS)
send_ldap_result (conn, op, err, NULL,
- "internal backend error");
+ "internal backend error", NULL );
free (results);
return (err);
/* delete.c - tcl delete routines
*
- * $Id: tcl_delete.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $
+ * $Id: tcl_delete.c,v 1.5.6.1 1999/07/09 18:02:59 kdz Exp $
*
* Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
*
if (ti->ti_delete == NULL) {
send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "delete not implemented");
+ "delete not implemented", NULL );
return (-1);
}
if (err != LDAP_SUCCESS)
send_ldap_result (conn, op, err, NULL,
- "internal backend error");
+ "internal backend error", NULL );
free (results);
return (err);
/* modify.c - tcl modify routines
*
- * $Id: tcl_modify.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $
+ * $Id: tcl_modify.c,v 1.5.6.1 1999/07/09 18:02:59 kdz Exp $
*
* Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
*
if (ti->ti_modify == NULL) {
send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "modify not implemented");
+ "modify not implemented", NULL );
return (-1);
}
if (err != LDAP_SUCCESS)
send_ldap_result (conn, op, err, NULL,
- "internal backend error");
+ "internal backend error", NULL );
free (results);
return (err);
/* modrdn.c - tcl modify rdn routines
*
- * $Id: tcl_modrdn.c,v 1.6 1999/03/05 02:42:46 gomez Exp $
+ * $Id: tcl_modrdn.c,v 1.7.6.1 1999/07/09 18:02:59 kdz Exp $
*
* Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
*
if (ti->ti_modrdn == NULL) {
send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "modrdn not implemented");
+ "modrdn not implemented", NULL );
return (-1);
}
if (err != LDAP_SUCCESS)
send_ldap_result (conn, op, err, NULL,
- "internal backend error");
+ "internal backend error", NULL );
free (results);
return (err);
/* search.c - tcl search routines
*
- * $Id: tcl_search.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $
+ * $Id: tcl_search.c,v 1.5.6.1 1999/07/09 18:02:59 kdz Exp $
*
* Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
*
if (ti->ti_search == NULL) {
send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "search not implemented");
+ "search not implemented", NULL );
return (-1);
}
if (err != LDAP_SUCCESS)
send_ldap_result (conn, op, err, NULL,
- "internal backend error");
+ "internal backend error", NULL );
free (results);
return (err);
/* unbind.c - tcl unbind routines
*
- * $Id: tcl_unbind.c,v 1.4 1999/02/19 06:55:20 bcollins Exp $
+ * $Id: tcl_unbind.c,v 1.5.6.1 1999/07/09 18:02:59 kdz Exp $
*
* Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
*
struct tclinfo *ti = (struct tclinfo *) be->be_private;
if (ti->ti_unbind == NULL) {
- send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "unbind not implemented");
return (-1);
}
/* result.c - tcl backend utility functions
*
- * $Id: tcl_util.c,v 1.5 1999/02/28 04:55:49 bcollins Exp $
+ * $Id: tcl_util.c,v 1.6.2.2 1999/07/14 00:54:37 kdz Exp $
*
* Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
*
if (code != TCL_OK) {
argcPtr = 0;
send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
- "internal backend error");
+ "internal backend error", NULL );
return -1;
}
for (i = 0; i < argcPtr; i++) {
buf, 0, 0);
} else {
send_search_entry (be, conn, op, e, attrs,
- attrsonly, 0 );
+ attrsonly, 0, NULL );
entry_free (e);
}
* otherwise, front end will send this result
*/
if (err != 0 || op->o_tag != LDAP_REQ_BIND) {
- send_ldap_result (conn, op, err, matched, info);
+ send_ldap_result (conn, op, err, matched, info, NULL );
}
free (buf);
}
}
- /* if no proper suffix could be found then check for aliases */
- for ( i = 0; i < nbackends; i++ ) {
- for ( j = 0;
- backends[i].be_suffixAlias != NULL &&
- backends[i].be_suffixAlias[j] != NULL;
- j += 2 )
- {
- len = strlen( backends[i].be_suffixAlias[j] );
-
- if ( len > dnlen ) {
- continue;
- }
-
- if ( strcmp( backends[i].be_suffixAlias[j],
- dn + (dnlen - len) ) == 0 ) {
- return( &backends[i] );
- }
- }
- }
-
#ifdef LDAP_ALLOW_NULL_SEARCH_BASE
/* Add greg@greg.rim.or.jp
* It's quick hack for cheap client
if ( version < LDAP_VERSION_MIN || version > LDAP_VERSION_MAX ) {
Debug( LDAP_DEBUG_ANY, "unknown version %d\n", version, 0, 0 );
- send_ldap_result( conn, op,
- rc = LDAP_PROTOCOL_ERROR, NULL, "version not supported" );
+ send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
+ NULL, "version not supported", NULL, NULL );
goto cleanup;
}
"do_bind: no sasl mechanism provided\n",
version, 0, 0 );
send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
- NULL, "no sasl mechanism provided" );
+ NULL, "no sasl mechanism provided", NULL, NULL );
goto cleanup;
}
"do_bind: sasl mechanism \"%s\" not supported.\n",
mech, 0, 0 );
send_ldap_result( conn, op, rc = LDAP_AUTH_METHOD_NOT_SUPPORTED,
- NULL, "sasl mechanism not supported" );
+ NULL, "sasl mechanism not supported", NULL, NULL );
goto cleanup;
}
* we already forced connection to "anonymous", we just
* need to send success
*/
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
goto cleanup;
}
if ( (be = select_backend( ndn )) == NULL ) {
if ( cred.bv_len == 0 ) {
send_ldap_result( conn, op, LDAP_SUCCESS,
- NULL, NULL );
+ NULL, NULL, NULL, NULL );
- } else if ( default_referral && *default_referral ) {
- send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS,
- NULL, default_referral );
+ } else if ( default_referral ) {
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
} else {
send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS,
- NULL, default_referral );
+ NULL, NULL, NULL, NULL );
}
goto cleanup;
/* alias suffix */
char *edn;
- ndn = suffixAlias( ndn, op, be );
-
if ( (*be->be_bind)( be, conn, op, ndn, method, mech, &cred, &edn ) == 0 ) {
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
/* send this here to avoid a race condition */
- send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
+ send_ldap_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL );
} else if (edn != NULL) {
free( edn );
}
} else {
- send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
cleanup:
return( new );
}
+
+char *
+charray2str( char **a )
+{
+ char *s;
+ int i;
+ size_t cur, len = 0;
+
+ if( a == NULL ) return NULL;
+
+ for( i=0 ; a[i] != NULL ; i++ ) {
+ len += strlen( a[i] );
+ }
+
+ if( len == 0 ) return NULL;
+
+ s = ch_malloc( len + 1 );
+
+ cur = 0;
+ for( i=0 ; a[i] != NULL ; i++ ) {
+ len = strlen( a[i] );
+ strncpy( &s[cur], a[i], len );
+ cur += len;
+ }
+ s[len] = '\0';
+ return s;
+}
+
+
char **
str2charray( char *str, char *brkstr )
{
if( op->o_bind_in_progress ) {
Debug( LDAP_DEBUG_ANY, "do_compare: SASL bind in progress.\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
- "SASL bind in progress" );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ NULL, "SASL bind in progress", NULL, NULL );
return LDAP_SASL_BIND_IN_PROGRESS;
}
free( ndn );
ava_free( &ava, 0 );
- send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
return 1;
}
- /* alias suffix if approp */
- ndn = suffixAlias( ndn, op, be );
-
if ( be->be_compare ) {
(*be->be_compare)( be, conn, op, ndn, &ava );
} else {
- send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
free( ndn );
char *cargv[MAXARGS];
int lineno, i, rc;
+ struct berval *vals[2];
+ struct berval val;
+
static BackendInfo *bi = NULL;
static BackendDB *be = NULL;
+ vals[0] = &val;
+ vals[1] = NULL;
+
if ( (fp = fopen( fname, "r" )) == NULL ) {
ldap_syslog = 1;
Debug( LDAP_DEBUG_ANY,
be = backend_db_init( cargv[1] );
/* assign a default depth limit for alias deref */
- be->be_maxDerefDepth = SLAPD_DEFAULT_MAXDEREFDEPTH;
+ be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH;
/* get pid file name */
} else if ( strcasecmp( cargv[0], "pidfile" ) == 0 ) {
free( dn );
}
- /* set database suffixAlias */
- } else if ( strcasecmp( cargv[0], "suffixAlias" ) == 0 ) {
- if ( cargc < 2 ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: missing alias and aliased_dn in \"suffixAlias <alias> <aliased_dn>\" line\n",
- fname, lineno, 0 );
- return( 1 );
- } else if ( cargc < 3 ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: missing aliased_dn in \"suffixAlias <alias> <aliased_dn>\" line\n",
- fname, lineno, 0 );
- return( 1 );
- } else if ( cargc > 3 ) {
- Debug( LDAP_DEBUG_ANY,
- "%s: line %d: extra cruft in suffixAlias line (ignored)\n",
- fname, lineno, 0 );
- }
- if ( be == NULL ) {
- Debug( LDAP_DEBUG_ANY,
-"%s: line %d: suffixAlias line must appear inside a database definition (ignored)\n",
- fname, lineno, 0 );
- } else {
- char *alias, *aliased_dn;
-
- alias = ch_strdup( cargv[1] );
- (void) dn_normalize( alias );
-
- aliased_dn = ch_strdup( cargv[2] );
- (void) dn_normalize( aliased_dn );
-
-
- if ( strcasecmp( alias, aliased_dn) == 0 ) {
- Debug( LDAP_DEBUG_ANY,
-"%s: line %d: suffixAlias %s is not different from aliased dn (ignored)\n",
- fname, lineno, alias );
- } else {
- (void) dn_normalize_case( alias );
- (void) dn_normalize_case( aliased_dn );
- charray_add( &be->be_suffixAlias, alias );
- charray_add( &be->be_suffixAlias, aliased_dn );
- }
-
- free(alias);
- free(aliased_dn);
- }
-
/* set max deref depth */
} else if ( strcasecmp( cargv[0], "maxDerefDepth" ) == 0 ) {
+ int i;
if ( cargc < 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: missing depth in \"maxDerefDepth <depth>\" line\n",
Debug( LDAP_DEBUG_ANY,
"%s: line %d: depth line must appear inside a database definition (ignored)\n",
fname, lineno, 0 );
+ } else if ((i = atoi(cargv[i])) < 0) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: depth must be positive (ignored)\n",
+ fname, lineno, 0 );
+
} else {
- be->be_maxDerefDepth = atoi (cargv[1]);
- }
+ be->be_max_deref_depth = i;
+ }
/* set magic "root" dn for this database */
fname, lineno, 0 );
return( 1 );
}
- default_referral = (char *) ch_malloc( strlen( cargv[1] )
- + sizeof("Referral:\n") + 1 );
- strcpy( default_referral, "Referral:\n" );
- strcat( default_referral, cargv[1] );
+
+ vals[0]->bv_val = cargv[1];
+ vals[0]->bv_len = strlen( vals[0]->bv_val );
+ value_add( &default_referral, vals );
/* specify locale */
} else if ( strcasecmp( cargv[0], "locale" ) == 0 ) {
(void) dn_normalize_case( be->be_update_ndn );
}
+ } else if ( strcasecmp( cargv[0], "updateref" ) == 0 ) {
+ if ( cargc < 2 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "%s: line %d: missing dn in \"updateref <ldapurl>\" line\n",
+ fname, lineno, 0 );
+ return( 1 );
+ }
+ if ( be == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: updateref line must appear inside a database definition (ignored)\n",
+ fname, lineno, 0 );
+ } else if ( be->be_update_ndn == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+"%s: line %d: updateref line must after updatedn (ignored)\n",
+ fname, lineno, 0 );
+ } else {
+ vals[0]->bv_val = cargv[1];
+ vals[0]->bv_len = strlen( vals[0]->bv_val );
+ value_add( &be->be_update_refs, vals );
+ }
+
/* replication log file to which changes are appended */
} else if ( strcasecmp( cargv[0], "replogfile" ) == 0 ) {
if ( cargc < 2 ) {
attr_merge( e, "database", vals );
}
- if ( default_referral != NULL ) {
- strcpy( buf, default_referral );
- val.bv_val = buf;
- val.bv_len = strlen( buf );
- attr_merge( e, "database", vals );
- }
-
- send_search_entry( &backends[0], conn, op, e, NULL, 0, 1 );
- send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+ send_search_entry( &backends[0], conn, op, e,
+ NULL, 0, 1, NULL );
+ send_search_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 1 );
entry_free( e );
}
#include "../../libraries/liblber/lber-int.h"
char *supportedControls[] = {
+ LDAP_CONTROL_MANAGEDSAIT,
NULL
};
if( rc == -1 ) {
send_ldap_disconnect( conn, op, rc, errmsg );
} else {
- send_ldap_result( conn, op, rc, NULL, errmsg );
+ send_ldap_result( conn, op, rc,
+ NULL, errmsg, NULL, NULL );
}
}
return rc;
}
+
+
+int get_manageDSAit( Operation *op )
+{
+ int i;
+ if( op == NULL || op->o_ctrls == NULL ) {
+ return 0;
+ }
+
+ for( i=0; op->o_ctrls[i] != NULL; i++ ) {
+ if( strcmp( LDAP_CONTROL_MANAGEDSAIT, op->o_ctrls[i]->ldctl_oid )
+ == 0 )
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
\ No newline at end of file
if( op->o_bind_in_progress ) {
Debug( LDAP_DEBUG_ANY, "do_delete: SASL bind in progress.\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
- "SASL bind in progress" );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ NULL, "SASL bind in progress", NULL, NULL );
return LDAP_SASL_BIND_IN_PROGRESS;
}
*/
if ( (be = select_backend( ndn )) == NULL ) {
free( ndn );
- send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
return rc;
}
- /* alias suffix if approp */
- ndn = suffixAlias( ndn, op, be );
-
/*
* do the delete if 1 && (2 || 3)
* 1) there is a delete function implemented in this backend;
replog( be, LDAP_REQ_DELETE, ndn, NULL, 0 );
}
} else {
- send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
+ be->be_update_refs ? be->be_update_refs : default_referral, NULL );
}
} else {
- send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
free( ndn );
if( !charray_inlist( supportedExtensions, reqoid ) ) {
Debug( LDAP_DEBUG_ANY, "do_extended: unsupported operation \"%s\"\n",
reqoid, 0 ,0 );
- send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL,
- "unsuppored operation" );
+ send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
+ NULL, "unsuppored extended operation", NULL, NULL );
goto done;
}
Debug( LDAP_DEBUG_ARGS, "do_extended: oid \"%s\"\n", reqoid, 0 ,0 );
send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
- NULL, "unsupported extended operation" );
+ NULL, "unsupported extended operation", NULL, NULL );
done:
if ( reqoid != NULL ) {
#endif
int ldap_syslog_level = LOG_DEBUG;
-char *default_referral;
+struct berval **default_referral = NULL;
int g_argc;
char **g_argv;
ldap_pvt_thread_mutex_t num_ops_mutex;
long num_entries_sent;
+long num_refs_sent;
long num_bytes_sent;
+long num_pdu_sent;
ldap_pvt_thread_mutex_t num_sent_mutex;
/*
* these mutexes must be used when calling the entry2str()
# End Source File
# Begin Source File
-SOURCE=.\suffixalias.c
-# End Source File
-# Begin Source File
-
SOURCE=.\unbind.c
# End Source File
# Begin Source File
if( op->o_bind_in_progress ) {
Debug( LDAP_DEBUG_ANY, "do_modify: SASL bind in progress.\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
- "SASL bind in progress" );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ NULL, "SASL bind in progress", NULL, NULL );
return LDAP_SASL_BIND_IN_PROGRESS;
}
(*modtail)->ml_op != LDAP_MOD_REPLACE )
{
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
- NULL, "unrecognized modify operation" );
+ NULL, "unrecognized modify operation", NULL, NULL );
free( ndn );
modlist_free( modlist );
return LDAP_PROTOCOL_ERROR;
&& (*modtail)->ml_op != LDAP_MOD_DELETE )
{
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
- NULL, "unrecognized modify operation" );
+ NULL, "unrecognized modify operation", NULL, NULL );
free( ndn );
modlist_free( modlist );
return LDAP_PROTOCOL_ERROR;
if ( (be = select_backend( ndn )) == NULL ) {
free( ndn );
modlist_free( modlist );
- send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
return rc;
}
- /* alias suffix if approp */
- ndn = suffixAlias ( ndn, op, be );
-
/*
* do the modify if 1 && (2 || 3)
* 1) there is a modify function implemented in this backend;
/* send a referral */
} else {
- send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
+ be->be_update_refs ? be->be_update_refs : default_referral, NULL );
}
} else {
- send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
free( ndn );
if( op->o_bind_in_progress ) {
Debug( LDAP_DEBUG_ANY, "do_modrdn: SASL bind in progress.\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
- "SASL bind in progress" );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ NULL, "SASL bind in progress", NULL, NULL );
return LDAP_SASL_BIND_IN_PROGRESS;
}
free( newrdn );
free( newSuperior );
free( nnewSuperior );
- send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
return 0;
}
}
free( newrdn );
free( newSuperior );
free( nnewSuperior );
- send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
return rc;
}
free( nnewSuperior );
send_ldap_result( conn, op, rc = LDAP_AFFECTS_MULTIPLE_DSAS,
- NULL, "" );
+ NULL, NULL, NULL, NULL );
return rc;
}
-
- /* alias suffix if approp */
- ndn = suffixAlias( ndn, op, be );
-
/*
* do the add if 1 && (2 || 3)
* 1) there is an add function implemented in this backend;
deloldrdn );
}
} else {
- send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL, NULL,
+ be->be_update_refs ? be->be_update_refs : default_referral, NULL );
}
} else {
- send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
free( ndn );
sprintf( buf, "%d", nconns );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "currentconnections", vals );
+ attr_merge( e, "currentConnections", vals );
sprintf( buf, "%ld", connections_nextid() );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "totalconnections", vals );
+ attr_merge( e, "totalConnections", vals );
sprintf( buf, "%ld", (long) dtblsize );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "dtablesize", vals );
+ attr_merge( e, "dTableSize", vals );
sprintf( buf, "%d", nwritewaiters );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "writewaiters", vals );
+ attr_merge( e, "writeWaiters", vals );
sprintf( buf, "%d", nreadwaiters );
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "readwaiters", vals );
+ attr_merge( e, "readWaiters", vals );
ldap_pvt_thread_mutex_lock(&num_ops_mutex);
sprintf( buf, "%ld", num_ops_initiated );
ldap_pvt_thread_mutex_unlock(&num_ops_mutex);
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "opsinitiated", vals );
+ attr_merge( e, "opsInitiated", vals );
ldap_pvt_thread_mutex_lock(&num_ops_mutex);
sprintf( buf, "%ld", num_ops_completed );
ldap_pvt_thread_mutex_unlock(&num_ops_mutex);
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "opscompleted", vals );
+ attr_merge( e, "opsCompleted", vals );
ldap_pvt_thread_mutex_lock(&num_sent_mutex);
sprintf( buf, "%ld", num_entries_sent );
ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "entriessent", vals );
+ attr_merge( e, "entriesSent", vals );
+
+ ldap_pvt_thread_mutex_lock(&num_sent_mutex);
+ sprintf( buf, "%ld", num_refs_sent );
+ ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ attr_merge( e, "referencesSent", vals );
+
+ ldap_pvt_thread_mutex_lock(&num_sent_mutex);
+ sprintf( buf, "%ld", num_pdu_sent );
+ ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
+ val.bv_val = buf;
+ val.bv_len = strlen( buf );
+ attr_merge( e, "pduSent", vals );
ldap_pvt_thread_mutex_lock(&num_sent_mutex);
sprintf( buf, "%ld", num_bytes_sent );
ldap_pvt_thread_mutex_unlock(&num_sent_mutex);
val.bv_val = buf;
val.bv_len = strlen( buf );
- attr_merge( e, "bytessent", vals );
+ attr_merge( e, "bytesSent", vals );
currenttime = slap_get_time();
attr_merge( e, "concurrency", vals );
#endif
- send_search_entry( &backends[0], conn, op, e, NULL, 0, 1 );
- send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+ send_search_entry( &backends[0], conn, op, e,
+ NULL, 0, 1, NULL );
+ send_search_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 1 );
entry_free( e );
}
int charray_inlist LDAP_P(( char **a, char *s ));
char ** charray_dup LDAP_P(( char **a ));
char ** str2charray LDAP_P(( char *str, char *brkstr ));
+char * charray2str LDAP_P(( char **a ));
/*
* controls.c
Operation *op,
int senderrors ));
+int get_manageDSAit LDAP_P(( Operation *op ));
+
/*
* config.c
*/
* result.c
*/
+struct berval **get_entry_referrals LDAP_P((
+ Backend *be, Connection *conn, Operation *op,
+ Entry *e ));
+
void send_ldap_result LDAP_P((
Connection *conn, Operation *op,
- int err, char *matched, char *text ));
+ int err, char *matched, char *text,
+ struct berval **refs,
+ LDAPControl **ctrls ));
void send_ldap_disconnect LDAP_P((
Connection *conn, Operation *op,
int err, char *text ));
-void send_ldap_search_result LDAP_P((
+void send_search_result LDAP_P((
Connection *conn, Operation *op,
- int err, char *matched, char *text, int nentries ));
+ int err, char *matched, char *text,
+ struct berval **refs,
+ LDAPControl **ctrls,
+ int nentries ));
+
+int send_search_reference LDAP_P((
+ Backend *be, Connection *conn, Operation *op,
+ Entry *e, struct berval **refs, int scope,
+ LDAPControl **ctrls,
+ struct berval ***v2refs ));
+
+int send_search_entry LDAP_P((
+ Backend *be, Connection *conn, Operation *op,
+ Entry *e, char **attrs, int attrsonly, int opattrs,
+ LDAPControl **ctrls ));
+
+int str2result LDAP_P(( char *s,
+ int *code, char **matched, char **info ));
/*
* schema.c
void schema_info LDAP_P((Connection *conn, Operation *op, char **attrs, int attrsonly));
int schema_init LDAP_P((void));
+int is_entry_objectclass LDAP_P(( Entry *, char* objectclass ));
+#define is_entry_alias(e) is_entry_objectclass((e), "ALIAS")
+#define is_entry_referral(e) is_entry_objectclass((e), "REFERRAL")
+
/*
* schemaparse.c
int value_find LDAP_P(( struct berval **vals, struct berval *v, int syntax,
int normalize ));
-/*
- * suffixAlias.c
- */
-char *suffixAlias LDAP_P(( char *dn, Operation *op, Backend *be ));
-
/*
* user.c
*/
* Other...
*/
-extern char *default_referral;
+extern struct berval **default_referral;
extern char *replogfile;
extern const char Versionstr[];
extern int active_threads;
extern ldap_pvt_thread_mutex_t num_sent_mutex;
extern long num_bytes_sent;
+extern long num_pdu_sent;
extern long num_entries_sent;
+extern long num_refs_sent;
extern ldap_pvt_thread_mutex_t num_ops_mutex;
extern long num_ops_completed;
extern struct acl *global_acl;
-extern int slap_init LDAP_P((int mode, char* name));
-extern int slap_startup LDAP_P((int dbnum));
-extern int slap_shutdown LDAP_P((int dbnum));
-extern int slap_destroy LDAP_P((void));
+int slap_init LDAP_P((int mode, char* name));
+int slap_startup LDAP_P((int dbnum));
+int slap_shutdown LDAP_P((int dbnum));
+int slap_destroy LDAP_P((void));
struct sockaddr_in;
extern int do_unbind LDAP_P((Connection *conn, Operation *op));
extern int do_extended LDAP_P((Connection *conn, Operation *op));
-extern int send_search_entry LDAP_P((
- Backend *be, Connection *conn, Operation *op,
- Entry *e, char **attrs, int attrsonly, int opattrs ));
-
-extern int str2result LDAP_P(( char *s, int *code, char **matched, char **info ));
extern ber_socket_t dtblsize;
#include <ac/signal.h>
#include <ac/string.h>
#include <ac/time.h>
-#include <ac/unistd.h> /* get close() */
+#include <ac/unistd.h>
#include "slap.h"
/* we need LBER internals */
#include "../../libraries/liblber/lber-int.h"
-static void
-send_ldap_result2(
- Connection *conn,
- Operation *op,
- int disconnect,
- ber_int_t err,
- char *matched,
- char *text,
- int nentries
-)
+static char *v2ref( struct berval **ref )
{
- BerElement *ber;
- int rc;
- ber_tag_t tag;
- ber_len_t bytes;
- int msgid;
+ size_t len, i;
+ char *v2;
- assert( !LDAP_API_ERROR( err ) );
+ if(ref == NULL) return NULL;
- if ( err == LDAP_PARTIAL_RESULTS && (text == NULL || *text == '\0') )
- err = LDAP_NO_SUCH_OBJECT;
+ len = sizeof("Referral:");
+ v2 = ch_strdup("Referral:");
- if( disconnect ) {
- msgid = 0; /* unsolicited */
- if ( op->o_protocol > LDAP_VERSION3 ) {
- tag = LDAP_RES_EXTENDED;
- }
-
-#define LDAP_UNSOLICITED_ERROR(e) \
- ( (e) == LDAP_PROTOCOL_ERROR \
- || (e) == LDAP_STRONG_AUTH_REQUIRED \
- || (e) == LDAP_UNAVAILABLE )
+ for( i=0; ref[i] != NULL; i++ ) {
+ v2 = ch_realloc( v2, len + ref[i]->bv_len + 1 );
+ v2[len-1] = '\n';
+ memcpy(&v2[len], ref[i]->bv_val, ref[i]->bv_len );
+ len += ref[i]->bv_len;
+ }
- assert( LDAP_UNSOLICITED_ERROR( err ) );
+ v2[len-1] = '\0';
+ return v2;
+}
- } else {
- msgid = op->o_msgid;
-
- switch ( op->o_tag ) {
- case LDAP_REQ_ABANDON:
- case LDAP_REQ_UNBIND:
- case LBER_ERROR:
- tag = LBER_SEQUENCE;
- msgid = 0;
- assert( LDAP_UNSOLICITED_ERROR( err ) );
- break;
+static ber_tag_t req2res( ber_tag_t tag )
+{
+ switch( tag ) {
+ case LDAP_REQ_ADD:
+ case LDAP_REQ_BIND:
+ case LDAP_REQ_COMPARE:
+ case LDAP_REQ_EXTENDED:
+ case LDAP_REQ_MODIFY:
+ case LDAP_REQ_MODRDN:
+ tag++;
+ break;
+
+ case LDAP_REQ_DELETE:
+ tag = LDAP_RES_DELETE;
+ break;
+
+ case LDAP_REQ_ABANDON:
+ case LDAP_REQ_UNBIND:
+ tag = LBER_SEQUENCE;
+ break;
+
+ case LDAP_REQ_SEARCH:
+ tag = LDAP_RES_SEARCH_RESULT;
+ break;
+
+ default:
+ assert( 0 );
+ tag = LBER_ERROR;
+ }
+ return tag;
+}
- case LDAP_REQ_SEARCH:
- tag = LDAP_RES_SEARCH_RESULT;
- break;
+static void trim_refs_urls(
+ struct berval **refs )
+{
+ unsigned i;
- case LDAP_REQ_DELETE:
- tag = LDAP_RES_DELETE;
- break;
+ if( refs == NULL ) return;
- default:
- tag = op->o_tag + 1;
- break;
+ for( i=0; refs[i] != NULL; i++ ) {
+ if( refs[i]->bv_len > sizeof("ldap://") &&
+ strncasecmp( refs[i]->bv_val, "ldap://",
+ sizeof("ldap://")-1 ) == 0 )
+ {
+ unsigned j;
+ for( j=sizeof("ldap://"); j<refs[i]->bv_len ; j++ ) {
+ if( refs[i]->bv_val[j] = '/' ) {
+ refs[i]->bv_val[j] = '\0';
+ refs[i]->bv_len = j;
+ break;
+ }
+ }
}
}
+}
+struct berval **get_entry_referrals(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e )
+{
+ Attribute *attr;
+ struct berval **refs;
+ unsigned i, j;
- ber = ber_alloc_t( LBER_USE_DER );
+ attr = attr_find( e->e_attrs, "ref" );
- if ( ber == NULL ) {
- Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
- return;
+ if( attr == NULL ) return NULL;
+
+ for( i=0; attr->a_vals[i] != NULL; i++ ) {
+ /* count references */
}
-#ifdef LDAP_CONNECTIONLESS
- if ( op->o_cldap ) {
- rc = ber_printf( ber, "{is{t{ess}}}", msgid, "", tag,
- err, matched ? matched : "", text ? text : "" );
- } else
-#endif
- if( tag == LDAP_RES_EXTENDED ) {
- rc = ber_printf( ber, "{it{esss}}",
- msgid, tag, err,
- "", text ? text : "",
- LDAP_NOTICE_DISCONNECT );
+ if( i < 1 ) return NULL;
- } else {
- rc = ber_printf( ber, "{it{ess}}",
- msgid, tag, err,
- matched ? matched : "", text ? text : "" );
+ refs = ch_malloc( i + 1 );
+
+ for( i=0, j=0; attr->a_vals[i] != NULL; i++ ) {
+ unsigned k;
+ struct berval *ref = ber_bvdup( attr->a_vals[i] );
+
+ /* trim the label */
+ for( k=0; k<ref->bv_len; k++ ) {
+ if( isspace(ref->bv_val[k]) ) {
+ ref->bv_val[k] = '\0';
+ ref->bv_len = k;
+ break;
+ }
+ }
+
+ if( ref->bv_len > 0 ) {
+ refs[j++] = ref;
+
+ } else {
+ ber_bvfree( ref );
+ }
}
- if ( rc == -1 ) {
- Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
- return;
+ refs[j] = NULL;
+
+ if( j == 0 ) {
+ ber_bvecfree( refs );
+ refs = NULL;
}
+ /* we should check that a referral value exists... */
+
+ return refs;
+}
+
+static long send_ldap_ber(
+ Connection *conn,
+ BerElement *ber )
+{
+ ber_len_t bytes = ber_pvt_ber_bytes( ber );
+
/* write only one pdu at a time - wait til it's our turn */
ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
- /* lock the connection */
+ /* lock the connection */
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
/* write the pdu */
- bytes = ber_pvt_ber_bytes( ber );
-
- while ( 1 ) {
+ while( 1 ) {
int err;
if ( connection_state_closing( conn ) ) {
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
- return;
+ return 0;
}
if ( ber_flush( conn->c_sb, ber, 1 ) == 0 ) {
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
- return;
+ return( -1 );
}
/* wait for socket to be write-ready */
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
+ return bytes;
+}
+
+static void
+send_ldap_response(
+ Connection *conn,
+ Operation *op,
+ ber_tag_t tag,
+ ber_int_t msgid,
+ ber_int_t err,
+ char *matched,
+ char *text,
+ struct berval **ref,
+ char *resoid,
+ struct berval *resdata,
+ LDAPControl **ctrls
+)
+{
+ BerElement *ber;
+ int rc;
+ long bytes;
+
+ assert( ctrls == NULL ); /* ctrls not implemented */
+
+ ber = ber_alloc_t( LBER_USE_DER );
+
+ Debug( LDAP_DEBUG_TRACE, "send_ldap_response: tag=%ld msgid=%ld err=%ld\n",
+ (long) tag, (long) msgid, (long) err );
+
+ if ( ber == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
+ return;
+ }
+
+#ifdef LDAP_CONNECTIONLESS
+ if ( op->o_cldap ) {
+ rc = ber_printf( ber, "{is{t{ess}}}", msgid, "", tag,
+ err, matched ? matched : "", text ? text : "" );
+ } else
+#endif
+ {
+ rc = ber_printf( ber, "{it{ess",
+ msgid, tag, err,
+ matched == NULL ? "" : matched,
+ text == NULL ? "" : text );
+
+ if( rc != -1 && ref != NULL ) {
+ rc = ber_printf( ber, "{V}", ref );
+ }
+
+ if( rc != -1 && resoid != NULL ) {
+ rc = ber_printf( ber, "s", resoid );
+ }
+
+ if( rc != -1 && resdata != NULL ) {
+ rc = ber_printf( ber, "O", resdata );
+
+ }
+
+ if( rc != -1 ) {
+ rc = ber_printf( ber, "}}" );
+ }
+ }
+
+ if ( rc == -1 ) {
+ Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
+ return;
+ }
+
+ /* send BER */
+ bytes = send_ldap_ber( conn, ber );
+
+ if ( bytes < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_ldap_response: ber write failed\n",
+ 0, 0, 0 );
+ return;
+ }
+
ldap_pvt_thread_mutex_lock( &num_sent_mutex );
num_bytes_sent += bytes;
+ num_pdu_sent++;
ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
-
- Statslog( LDAP_DEBUG_STATS,
- "conn=%ld op=%ld RESULT err=%ld tag=%lu nentries=%d\n",
- (long) conn->c_connid, (long) op->o_opid,
- (long) err, (long) tag, nentries );
-
return;
}
+
void
-send_ldap_result(
+send_ldap_disconnect(
Connection *conn,
Operation *op,
ber_int_t err,
- char *matched,
char *text
)
{
- assert( !LDAP_API_ERROR( err ) );
+ ber_tag_t tag;
+ ber_int_t msgid;
+ char *reqoid;
- Debug( LDAP_DEBUG_TRACE, "send_ldap_result %d:%s:%s\n",
- err, matched ? matched : "", text ? text : "" );
+#define LDAP_UNSOLICITED_ERROR(e) \
+ ( (e) == LDAP_PROTOCOL_ERROR \
+ || (e) == LDAP_STRONG_AUTH_REQUIRED \
+ || (e) == LDAP_UNAVAILABLE )
+
+ assert( LDAP_UNSOLICITED_ERROR( err ) );
+
+ Debug( LDAP_DEBUG_TRACE,
+ "send_ldap_disconnect %d:%s\n",
+ err, text ? text : "", NULL );
+
+ if ( op->o_protocol < LDAP_VERSION3 ) {
+ reqoid = NULL;
+ tag = req2res( op->o_tag );
+ msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
+
+ } else {
+ reqoid = LDAP_NOTICE_DISCONNECT;
+ tag = LDAP_RES_EXTENDED;
+ msgid = 0;
+ }
#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
0 );
}
#endif
- send_ldap_result2( conn, op, 0, err, matched, text, 0 );
+ send_ldap_response( conn, op, tag, msgid,
+ err, NULL, text, NULL,
+ reqoid, NULL, NULL );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "conn=%ld op=%ld DISCONNECT err=%ld tag=%lu text=%s\n",
+ (long) conn->c_connid, (long) op->o_opid,
+ (long) tag, (long) err, text );
}
void
-send_ldap_disconnect(
+send_ldap_result(
Connection *conn,
Operation *op,
ber_int_t err,
- char *text
+ char *matched,
+ char *text,
+ struct berval **ref,
+ LDAPControl **ctrls
)
{
+ ber_tag_t tag;
+ ber_int_t msgid;
+ char *tmp = NULL;
+
assert( !LDAP_API_ERROR( err ) );
- Debug( LDAP_DEBUG_TRACE,
- "send_ldap_disconnect %d:%s\n",
- err, text ? text : "", NULL );
+ Debug( LDAP_DEBUG_TRACE, "send_ldap_result %d:%s:%s\n",
+ err, matched ? matched : "", text ? text : "" );
+
+ assert( err != LDAP_PARTIAL_RESULTS );
+
+ if( op->o_tag != LDAP_REQ_SEARCH ) {
+ trim_refs_urls( ref );
+ }
+
+ if ( err == LDAP_REFERRAL ) {
+ if( ref == NULL ) {
+ err = LDAP_NO_SUCH_OBJECT;
+ } else if ( op->o_protocol < LDAP_VERSION3 ) {
+ err = LDAP_PARTIAL_RESULTS;
+ tmp = text = v2ref( ref );
+ ref = NULL;
+ }
+ }
+
+ tag = req2res( op->o_tag );
+ msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
#ifdef LDAP_CONNECTIONLESS
if ( op->o_cldap ) {
0 );
}
#endif
- send_ldap_result2( conn, op, 0, err, NULL, text, 0 );
+
+ send_ldap_response( conn, op, tag, msgid,
+ err, matched, text, ref,
+ NULL, NULL, ctrls );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "conn=%ld op=%ld RESULT err=%ld tag=%lu text=%s\n",
+ (long) conn->c_connid, (long) op->o_opid,
+ (long) err, (long) tag, text );
+
+ if( tmp != NULL ) {
+ free(tmp);
+ }
}
+
void
-send_ldap_search_result(
+send_search_result(
Connection *conn,
Operation *op,
ber_int_t err,
char *matched,
- char *text,
+ char *text,
+ struct berval **refs,
+ LDAPControl **ctrls,
int nentries
)
{
+ ber_tag_t tag;
+ ber_int_t msgid;
+ char *tmp = NULL;
+ assert( !LDAP_API_ERROR( err ) );
+
Debug( LDAP_DEBUG_TRACE, "send_ldap_search_result %d:%s:%s\n",
err, matched ? matched : "", text ? text : "" );
- send_ldap_result2( conn, op, 0, err, matched, text, nentries );
+ assert( err != LDAP_PARTIAL_RESULTS );
+
+ trim_refs_urls( refs );
+
+ if( op->o_protocol < LDAP_VERSION3 ) {
+ /* send references in search results */
+ if( err == LDAP_REFERRAL ) {
+ err = LDAP_PARTIAL_RESULTS;
+ tmp = text = v2ref( refs );
+ refs = NULL;
+ }
+
+ } else {
+ /* don't send references in search results */
+ if( err == LDAP_REFERRAL ) {
+ err = LDAP_SUCCESS;
+ refs = NULL;
+ }
+ }
+
+ tag = req2res( op->o_tag );
+ msgid = (tag != LBER_SEQUENCE) ? op->o_msgid : 0;
+
+#ifdef LDAP_CONNECTIONLESS
+ if ( op->o_cldap ) {
+ ber_pvt_sb_udp_set_dst( &conn->c_sb, &op->o_clientaddr );
+ Debug( LDAP_DEBUG_TRACE, "UDP response to %s port %d\n",
+ inet_ntoa(((struct sockaddr_in *)
+ &op->o_clientaddr)->sin_addr ),
+ ((struct sockaddr_in *) &op->o_clientaddr)->sin_port,
+ 0 );
+ }
+#endif
+
+ send_ldap_response( conn, op, tag, msgid,
+ err, matched, text, refs,
+ NULL, NULL, ctrls );
+
+ Statslog( LDAP_DEBUG_STATS,
+ "conn=%ld op=%ld SEARCH RESULT err=%ld tag=%lu text=%s\n",
+ (long) conn->c_connid, (long) op->o_opid,
+ (long) err, (long) tag, text );
+
}
+
int
send_search_entry(
Backend *be,
Entry *e,
char **attrs,
int attrsonly,
- int opattrs
+ int opattrs,
+ LDAPControl **ctrls
)
{
BerElement *ber;
int i, rc=-1, bytes;
struct acl *acl;
char *edn;
+ int allattrs;
Debug( LDAP_DEBUG_TRACE, "=> send_search_entry (%s)\n", e->e_dn, 0, 0 );
if ( ber == NULL ) {
Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "ber_alloc" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "allocating BER error", NULL, NULL );
goto error_return;
}
if ( rc == -1 ) {
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "ber_printf dn" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encoding dn error", NULL, NULL );
goto error_return;
}
+ /* check for special all user attributes ("*") attribute */
+ allattrs = attrs == NULL
+ ? 1
+ : charray_inlist( attrs, LDAP_ALL_USER_ATTRIBUTES );
+
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
regmatch_t matches[MAXREMATCHES];
if ( attrs == NULL ) {
/* all addrs request, skip operational attributes */
- if( !opattrs && oc_check_operational_attr( a->a_type )) {
+ if( !opattrs && oc_check_operational_attr( a->a_type ) ) {
continue;
}
} else {
/* specific addrs requested */
- if ( !charray_inlist( attrs, a->a_type )
- && !charray_inlist( attrs, LDAP_ALL_USER_ATTRIBUTES ) )
- {
+ if ( !allattrs && !charray_inlist( attrs, a->a_type ) ) {
continue;
}
}
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, "ber_printf type" );
+ NULL, "encoding type error", NULL, NULL );
goto error_return;
}
Debug( LDAP_DEBUG_ANY,
"ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
- send_ldap_result( conn, op,
- LDAP_OPERATIONS_ERROR, NULL,
- "ber_printf value" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encoding value error", NULL, NULL );
goto error_return;
}
}
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
- NULL, "ber_printf type end" );
+ NULL, "encode end error", NULL, NULL );
goto error_return;
}
}
if ( rc == -1 ) {
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
ber_free( ber, 1 );
- send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL,
- "ber_printf entry end" );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encode entry end error", NULL, NULL );
return( 1 );
}
- bytes = ber_pvt_ber_bytes( ber );
+ bytes = send_ldap_ber( conn, ber );
- /* write only one pdu at a time - wait til it's our turn */
- ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
+ if ( bytes < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_ldap_response: ber write failed\n",
+ 0, 0, 0 );
+ return -1;
+ }
- /* lock the connection */
- ldap_pvt_thread_mutex_lock( &conn->c_mutex );
+ ldap_pvt_thread_mutex_lock( &num_sent_mutex );
+ num_bytes_sent += bytes;
+ num_entries_sent++;
+ num_pdu_sent++;
+ ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
- /* write the pdu */
- while( 1 ) {
- int err;
+ Statslog( LDAP_DEBUG_STATS2, "conn=%ld op=%ld ENTRY dn=\"%s\"\n",
+ (long) conn->c_connid, (long) op->o_opid, e->e_dn, 0, 0 );
- if ( connection_state_closing( conn ) ) {
- ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
- ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
- return 0;
- }
+ Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
- if ( ber_flush( conn->c_sb, ber, 1 ) == 0 ) {
- break;
- }
+ rc = 0;
- err = errno;
+error_return:;
+ return( rc );
+}
- /*
- * we got an error. if it's ewouldblock, we need to
- * wait on the socket being writable. otherwise, figure
- * it's a hard error and return.
- */
+int
+send_search_reference(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ struct berval **refs,
+ int scope,
+ LDAPControl **ctrls,
+ struct berval ***v2refs
+)
+{
+ BerElement *ber;
+ int rc;
+ int bytes;
- Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno %d msg (%s)\n",
- err, err > -1 && err < sys_nerr ? sys_errlist[err]
- : "unknown", 0 );
+ Debug( LDAP_DEBUG_TRACE, "=> send_search_entry (%s)\n", e->e_dn, 0, 0 );
- if ( err != EWOULDBLOCK && err != EAGAIN ) {
- connection_closing( conn );
+ if ( ! access_allowed( be, conn, op, e,
+ "entry", NULL, ACL_READ ) )
+ {
+ Debug( LDAP_DEBUG_ACL,
+ "send_search_reference: access to entry not allowed\n",
+ 0, 0, 0 );
+ return( 1 );
+ }
- ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
- ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
- return( -1 );
+ if ( ! access_allowed( be, conn, op, e,
+ "ref", NULL, ACL_READ ) )
+ {
+ Debug( LDAP_DEBUG_ACL,
+ "send_search_reference: access to reference not allowed\n",
+ 0, 0, 0 );
+ return( 1 );
+ }
+
+ if( refs == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_search_reference: null ref in (%s)\n",
+ e->e_dn, 0, 0 );
+ return( 1 );
+ }
+
+ if( op->o_protocol < LDAP_VERSION3 ) {
+ /* save the references for the result */
+ if( *refs == NULL ) {
+ value_add( v2refs, refs );
}
+ return 0;
+ }
- /* wait for socket to be write-ready */
- conn->c_writewaiter = 1;
- slapd_set_write( ber_pvt_sb_get_desc( conn->c_sb ), 1 );
+ ber = ber_alloc_t( LBER_USE_DER );
- ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
- conn->c_writewaiter = 0;
+ if ( ber == NULL ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_search_reference: ber_alloc failed\n", 0, 0, 0 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "alloc BER error", NULL, NULL );
+ return -1;
}
- ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
- ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
+ rc = ber_printf( ber, "{it{V}}", op->o_msgid,
+ LDAP_RES_SEARCH_REFERENCE, refs );
+
+ if ( rc == -1 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "send_search_reference: ber_printf failed\n", 0, 0, 0 );
+ ber_free( ber, 1 );
+ send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
+ NULL, "encode dn error", NULL, NULL );
+ return -1;
+ }
+
+ bytes = send_ldap_ber( conn, ber );
ldap_pvt_thread_mutex_lock( &num_sent_mutex );
num_bytes_sent += bytes;
- num_entries_sent++;
+ num_refs_sent++;
+ num_pdu_sent++;
ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
Statslog( LDAP_DEBUG_STATS2, "conn=%ld op=%ld ENTRY dn=\"%s\"\n",
Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
- rc = 0;
-
-error_return:;
- return( rc );
+ return 0;
}
+
int
str2result(
char *s,
attr_merge( e, "supportedSASLMechanism", vals );
}
+ if ( default_referral != NULL ) {
+ attr_merge( e, "ref", default_referral );
+ }
- send_search_entry( &backends[0], conn, op, e, attrs, attrsonly, 1 );
- send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+ send_search_entry( &backends[0], conn, op,
+ e, attrs, attrsonly, 1, NULL );
+ send_search_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 1 );
entry_free( e );
}
return;
}
- send_search_entry( &backends[0], conn, op, e, attrs, attrsonly, 0 );
- send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
+ send_search_entry( &backends[0], conn, op,
+ e, attrs, attrsonly, 0, NULL );
+ send_search_result( conn, op, LDAP_SUCCESS,
+ NULL, NULL, NULL, NULL, 1 );
entry_free( e );
}
}
#endif
+
+
+int is_entry_objectclass(
+ Entry* e,
+ char* oc)
+{
+ Attribute *attr;
+ struct berval bv;
+
+ if( e == NULL || oc == NULL || *oc == '\0' )
+ return 0;
+
+ /*
+ * find objectClass attribute
+ */
+ attr = attr_find(e->e_attrs, "objectclass");
+
+ if( attr == NULL ) {
+ /* no objectClass attribute */
+ return 0;
+ }
+
+ bv.bv_val = oc;
+ bv.bv_len = strlen( bv.bv_val );
+
+ if( value_find(attr->a_vals, &bv, attr->a_syntax, 1) != 0) {
+ /* entry is not of this objectclass */
+ return 0;
+ }
+
+ return 1;
+}
\ No newline at end of file
objectclass ( 1.3.6.1.4.1.1466.101.120.111 NAME 'extensibleObject'
SUP top AUXILIARY )
+
+#
+# From draft-ietf-ldapext-nameref-00.txt
+# used to represent referrals in the directory
+#
+attribute ( 2.16.840.1.113730.3.1.34 NAME 'ref' DESC 'URL Reference'
+ EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.1466.115.121.1.26
+ USAGE distributedOperation )
+
+objectclass ( 2.16.840.1.113730.3.2.6 NAME 'referral'
+ SUP top STRUCTURAL MAY ( ref ) )
if( op->o_bind_in_progress ) {
Debug( LDAP_DEBUG_ANY, "do_search: SASL bind in progress.\n",
0, 0, 0 );
- send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL,
- "SASL bind in progress" );
+ send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS,
+ NULL, "SASL bind in progress", NULL, NULL );
return LDAP_SASL_BIND_IN_PROGRESS;
}
goto return_results;
}
- if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
- && scope != LDAP_SCOPE_SUBTREE ) {
- send_ldap_disconnect( conn, op,
- LDAP_PROTOCOL_ERROR, "decoding error" );
+ switch( scope ) {
+ case LDAP_SCOPE_BASE:
+ case LDAP_SCOPE_ONELEVEL:
+ case LDAP_SCOPE_SUBTREE:
+ break;
+ default:
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ NULL, "invalid scope", NULL, NULL );
+ rc = -1;
+ goto return_results;
+ }
+
+ switch( deref ) {
+ case LDAP_DEREF_NEVER:
+ case LDAP_DEREF_FINDING:
+ case LDAP_DEREF_SEARCHING:
+ case LDAP_DEREF_ALWAYS:
+ break;
+ default:
+ send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
+ NULL, "invalid deref", NULL, NULL );
rc = -1;
goto return_results;
}
send_ldap_disconnect( conn, op,
LDAP_PROTOCOL_ERROR, "decode error" );
} else {
- send_ldap_result( conn, op, err, NULL, "Bad search filter" );
+ send_ldap_result( conn, op, err,
+ NULL, "Bad search filter", NULL, NULL );
}
goto return_results;
}
"conn=%d op=%d SRCH base=\"%s\" scope=%d filter=\"%s\"\n",
conn->c_connid, op->o_opid, base, scope, fstr );
-#if defined( SLAPD_MONITOR_DN ) || defined( SLAPD_CONFIG_DN ) || defined( SLAPD_SCHEMA_DN )
if ( scope == LDAP_SCOPE_BASE ) {
#if defined( SLAPD_MONITOR_DN )
if ( strcmp( base, SLAPD_MONITOR_DN ) == 0 ) {
goto return_results;
}
#endif
+
#if defined( SLAPD_CONFIG_DN )
if ( strcmp( base, SLAPD_CONFIG_DN ) == 0 ) {
config_info( conn, op );
goto return_results;
}
#endif
+
#if defined( SLAPD_SCHEMA_DN )
if ( strcmp( base, SLAPD_SCHEMA_DN ) == 0 ) {
schema_info( conn, op, attrs, attrsonly );
goto return_results;
}
#endif
- }
-#endif /* monitor or config or schema dn */
- if ( strcmp( base, LDAP_ROOT_DSE ) == 0 && scope == LDAP_SCOPE_BASE ) {
- root_dse_info( conn, op, attrs, attrsonly );
- goto return_results;
+ if ( strcmp( base, LDAP_ROOT_DSE ) == 0 ) {
+ root_dse_info( conn, op, attrs, attrsonly );
+ goto return_results;
+ }
}
/*
* if we don't hold it.
*/
if ( (be = select_backend( base )) == NULL ) {
- send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL,
- default_referral );
+ send_ldap_result( conn, op, rc = LDAP_REFERRAL,
+ NULL, NULL, default_referral, NULL );
goto return_results;
}
- /* translate the base if it matches an aliased base part */
- base = suffixAlias ( base, op, be );
-
/* actually do the search and send the result(s) */
if ( be->be_search ) {
(*be->be_search)( be, conn, op, base, scope, deref, sizelimit,
timelimit, filter, fstr, attrs, attrsonly );
} else {
- send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL,
- "Function not implemented" );
+ send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
+ NULL, "Function not implemented", NULL, NULL );
}
return_results:;
struct access {
#define ACL_NONE 0x0001
-#define ACL_AUTH 0x0002
-#define ACL_COMPARE 0x0004
-#define ACL_SEARCH 0x0008
-#define ACL_READ 0x0010
-#define ACL_WRITE 0x0020
+#define ACL_AUTH 0x0004
+#define ACL_COMPARE 0x0008
+#define ACL_SEARCH 0x0010
+#define ACL_READ 0x0020
+#define ACL_WRITE 0x0040
#define ACL_PRIV_MASK 0x00ff
#define ACL_SELF 0x4000
/* these should be renamed from be_ to bd_ */
char **be_suffix; /* the DN suffixes of data in this backend */
char **be_nsuffix; /* the normalized DN suffixes in this backend */
- char **be_suffixAlias; /* the DN suffix aliases of data in this backend */
char *be_root_dn; /* the magic "root" dn for this db */
char *be_root_ndn; /* the magic "root" normalized dn for this db */
char *be_root_pw; /* the magic "root" password for this db */
int be_readonly; /* 1 => db is in "read only" mode */
- int be_maxDerefDepth; /* limit for depth of an alias deref */
+ unsigned int be_max_deref_depth; /* limit for depth of an alias deref */
int be_sizelimit; /* size limit for this backend */
int be_timelimit; /* time limit for this backend */
struct acl *be_acl; /* access control list for this backend */
char **be_replica; /* replicas of this backend (in master) */
char *be_replogfile; /* replication log file (in master) */
char *be_update_ndn; /* allowed to make changes (in replicas) */
+ struct berval **be_update_refs; /* where to refer modifying clients to */
int be_lastmod; /* keep track of lastmodified{by,time} */
char *be_realm;
attribute jpegphoto bin
attribute audio bin
attribute labeledurl ces
+attribute ref ces
attribute userpassword ces
attribute telephonenumber tel
attribute facsimiletelephonenumber fax tel
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 hs_regex.lib libdb.lib wsock32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "slapd - Win32 Debug"
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 hs_regex.lib libdb.lib wsock32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib advapi32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ELSEIF "$(CFG)" == "slapd - Win32 Single Debug"
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 hs_regexd.lib libdbs.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 hs_regex.lib libdb.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ELSEIF "$(CFG)" == "slapd - Win32 Single Release"
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 hs_regex.lib libdb.lib wsock32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 hs_regex.lib libdb.lib wsock32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 hs_regex.lib libdb.lib ws2_32.lib /nologo /subsystem:console /machine:I386
!ENDIF
###############################################################################
+Project: "setup"=..\..\include\setup.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
Project: "slapd"=.\slapd.dsp - Package Owner=<4>
Package=<5>
Begin Project Dependency
Project_Dep_Name libslapd
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name setup
+ End Project Dependency
}}}
###############################################################################
aliasedObjectName,
objectClass
+objectclass referral
+ requires
+ ref,
+ objectClass
+
objectclass dcobject
requires
objectClass,
+++ /dev/null
-/*
- * Copyright 1999 The OpenLDAP Foundation, All Rights Reserved.
- *
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file in the top level
- * directory of this package.
- */
-/* Portions
- * Copyright (c) 1998 Will Ballantyne, ITSD, Government of BC
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to ITSD, Government of BC. The name of ITSD
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-
-#include "portable.h"
-
-#include <stdio.h>
-#include <ac/string.h>
-#include <ac/socket.h>
-#include "slap.h"
-
-/*
- * given a normalized uppercased dn (or root part), return an aliased dn if any of the
- * alias suffixes match
- */
-char *suffixAlias (char *dn, Operation *op, Backend *be)
-{
- int i, dnLength;
-
- if(dn == NULL) return NULL;
-
- dnLength = strlen ( dn );
- for ( i = 0;
- be->be_suffixAlias != NULL && be->be_suffixAlias[i] != NULL;
- i += 2) {
- int aliasLength = strlen (be->be_suffixAlias[i]);
- int diff = dnLength - aliasLength;
-
- if ( diff < 0 ) {
- /* alias is longer than dn */
- continue;
- } else if ( diff > 0 ) {
- if ( ! DNSEPARATOR(dn[diff-1]) ) {
- /* boundary is not at a DN separator */
- continue;
- }
- /* At a DN Separator */
- /* XXX or an escaped separator... oh well */
- }
-
- if (!strcmp(be->be_suffixAlias[i], &dn[diff])) {
- char *oldDN = dn;
- dn = ch_malloc( diff + strlen(be->be_suffixAlias[i+1]) + 1 );
- strncpy( dn, oldDN, diff );
- strcpy( &dn[diff], be->be_suffixAlias[i+1] );
- Debug( LDAP_DEBUG_ARGS, "SuffixAlias: converted \"%s\" to \"%s\"\n",
- oldDN, dn, 0);
- free (oldDN);
- break;
- }
- }
- return dn;
-}
../module.o ../aclparse.o ../schema.o ../filterentry.o \
../acl.o ../phonetic.o ../attr.o ../value.o ../entry.o \
../dn.o ../filter.o ../str2filter.o ../ava.o ../init.o \
- ../schemaparse.o
+ ../controls.o ../schemaparse.o
all-local: build-ldbm build-bdb2 build-edb2ldif build-chlog2replog
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib libdb.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release"
-# ADD LINK32 libdb.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release"
+# ADD LINK32 libdbs.lib /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\libraries\Release"
!ENDIF
SOURCE=.\ldbmcat.c
# End Source File
+# Begin Source File
+
+SOURCE=.\mimic.c
+# End Source File
# End Target
# End Project
free_and_close( dbc, key, data );
break;
+#ifndef HAVE_WINSOCK
case 'e': /* edit an entry */
if ( (dbc = openchoice( buf[1], LDBM_WRITER, 1, NULL ))
== NULL ) {
free_and_close( dbc, key, data );
break;
+#endif
case 'a': /* add an entry */
if ( (dbc = openchoice( buf[1], LDBM_WRITER, 1, NULL ))
data->dsize = psize + 1;
}
+#ifndef HAVE_WINSOCK
static void
edit_entry( char c, Datum *data )
{
fclose( fp );
unlink( tmpname );
}
+#endif
static struct dbcache *
openfile( char *name, int namesiz, int mode, int verbose, char c )
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 libdb.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 libdb.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "ldbmtest - Win32 Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 libdb.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libdb.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ELSEIF "$(CFG)" == "ldbmtest - Win32 Single Debug"
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 libdb.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 libdbs.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ELSEIF "$(CFG)" == "ldbmtest - Win32 Single Release"
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 libdb.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 libdbs.lib hs_regex.lib ws2_32.lib /nologo /subsystem:console /machine:I386
!ENDIF
SOURCE=.\ldbmtest.c
# End Source File
+# Begin Source File
+
+SOURCE=.\mimic.c
+# End Source File
# End Target
# End Project
return 0;
}
+void
+send_ldap_disconnect(
+ Connection *conn,
+ Operation *op,
+ ber_int_t err,
+ char *text
+)
+{
+ assert(0);
+}
+
void
send_ldap_result(
Connection *conn,
Operation *op,
int err,
char *matched,
- char *text
+ char *text,
+ struct berval **refs,
+ LDAPControl **ctrls
)
{
assert(0);
}
void
-send_ldap_search_result(
+send_search_result(
Connection *conn,
Operation *op,
int err,
char *matched,
char *text,
+ struct berval **refs,
+ LDAPControl **ctrls,
int nentries
)
{
Entry *e,
char **attrs,
int attrsonly,
- int opattrs
+ int opattrs,
+ LDAPControl **ctrls
)
{
assert(0);
return -1;
}
+
+int send_search_reference(
+ Backend *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ struct berval **refs,
+ int scope,
+ LDAPControl **ctrls,
+ struct berval ***v2refs
+)
+{
+ assert(0);
+ return -1;
+}
+
+struct berval **get_entry_referrals(
+ Backend *be, Connection *conn, Operation *op, Entry *e )
+{
+ assert(0);
+ return NULL;
+}
--- /dev/null
+dn: c=US
+c: US
+objectclass: country
+
+dn: o=ABC, c=US
+o: ABC
+ref: ldap//hostA/o=abc,c=us HostA
+ref: ldap//hostB/o=abc,c=us HostB
+objectclass: referral
+objectclass: extensibleObject
+
+dn: o=XYZ, c=US
+o: XYZ
+ref: ldap//hostC/o=xyz,c=us HostC
+objectclass: referral
+objectclass: extensibleObject
+
+dn: o=Alias, c=US
+o: Alias
+aliasedObjectName: o=University of Michigan, c=US
+objectclass: alias
+objectclass: extensibleObject
+
+dn: o=University of Michigan, c=US
+o: University of Michigan
+objectclass: organization
+
+dn: cn=Manager, o=University of Michigan, c=US
+cn: Manager
+cn: Directory Manager
+cn: Dir Man
+sn: Manager
+description: Manager of the directory
+userpassword: secret
+objectclass: person
+
+dn: cn=Alias, o=University of Michigan, c=US
+cn: Alias
+aliasedobjectname: cn=Manager, o=University of Michigan, c=US
+objectclass: extensibleObject
+
+dn: cn=Circular, o=University of Michigan, c=US
+cn: Circular
+aliasedobjectname: cn=Circular, o=University of Michigan, c=US
+objectclass: extensibleObject
+
+dn: cn=Subordinate, o=University of Michigan, c=US
+cn: Subordinate
+aliasedobjectname: cn=Subordinate, cn=Alias, o=University of Michigan, c=US
+objectclass: extensibleObject
lastmod on
defaultaccess none
+#
+# normal installations should protect root dse,
+# cn=monitor, cn=schema, and cn=config
+#
+
access to attr=objectclass
by * read
--- /dev/null
+#
+# slave slapd config -- for default referral testing
+#
+include ./data/slapd.at.conf
+include ./data/slapd.oc.conf
+schemacheck off
+pidfile ./test-repl/slapd.pid
+argsfile ./test-repl/slapd.args
+
+#######################################################################
+# ldbm database definitions
+#######################################################################
+
+referral "ldap://localhost:9009/"
+
+backend bdb2
+home ./test-db
+
+database bdb2
+cachesize 0
+suffix "o=University of Mich, c=US"
+directory ./test-repl
+rootdn "cn=Manager, o=University of Mich, c=US"
+rootpw secret
+index cn,sn,uid pres,eq,approx
+index default none
+# index default pres,eq,approx
+lastmod on
replogfile ./test-db/slapd.replog
replica host=localhost:9010
- binddn="cn=Manager, o=University of Michigan, c=US"
+ binddn="cn=Replica, o=University of Michigan, c=US"
bindmethod=simple
credentials=secret
pidfile ./test-repl/slapd.pid
argsfile ./test-repl/slapd.args
+referral "ldap://localhost:9009/"
+
#######################################################################
# ldbm database definitions
#######################################################################
cachesize 0
suffix "o=University of Michigan, c=US"
directory ./test-repl
-rootdn "cn=Manager, o=University of Michigan, c=US"
+rootdn "cn=Replica, o=University of Michigan, c=US"
rootpw secret
-updatedn "cn=Manager, o=University of Michigan, c=US"
+updatedn "cn=Replica, o=University of Michigan, c=US"
+updateref "ldap://localhost:9009/o=University%20of%20Michigan,c=US"
index cn,sn,uid pres,eq,approx
index default none
# index default pres,eq,approx
--- /dev/null
+#
+# slave slapd config -- for default referral testing
+#
+include ./data/slapd.at.conf
+include ./data/slapd.oc.conf
+schemacheck off
+pidfile ./test-repl/slapd.pid
+argsfile ./test-repl/slapd.args
+
+#######################################################################
+# ldbm database definitions
+#######################################################################
+
+referral "ldap://localhost:9009/"
+
+database ldbm
+cachesize 0
+suffix "o=University of Mich, c=US"
+directory ./test-repl
+rootdn "cn=Manager, o=University of Mich, c=US"
+rootpw secret
+index cn,sn,uid pres,eq,approx
+index default none
+# index default pres,eq,approx
+lastmod on
replogfile ./test-db/slapd.replog
replica host=localhost:9010
- binddn="cn=Manager, o=University of Michigan, c=US"
+ binddn="cn=Replica, o=University of Michigan, c=US"
bindmethod=simple
credentials=secret
pidfile ./test-repl/slapd.pid
argsfile ./test-repl/slapd.args
+referral "ldap://localhost:9009/"
+
#######################################################################
# ldbm database definitions
#######################################################################
cachesize 0
suffix "o=University of Michigan, c=US"
directory ./test-repl
-rootdn "cn=Manager, o=University of Michigan, c=US"
+rootdn "cn=Replica, o=University of Michigan, c=US"
rootpw secret
-updatedn "cn=Manager, o=University of Michigan, c=US"
+updatedn "cn=Replica, o=University of Michigan, c=US"
+updateref "ldap://localhost:9009/o=University%20of%20Michigan,c=US"
index cn,sn,uid pres,eq,approx
index default none
# index default pres,eq,approx
attribute jpegphoto bin
attribute audio bin
attribute labeledurl ces
+attribute ref ces
attribute userpassword ces
attribute telephonenumber tel
attribute facsimiletelephonenumber fax tel
aliasedObjectName,
objectClass
+objectclass referral
+ requires
+ ref,
+ objectClass
+
objectclass country
requires
objectClass,
ACLCONF=$DATADIR/slapd-bdb2-acl.conf
MASTERCONF=$DATADIR/slapd-bdb2-repl-master.conf
SLAVECONF=$DATADIR/slapd-bdb2-repl-slave.conf
+ REFSLAVECONF=$DATADIR/slapd-bdb2-ref-slave.conf
TIMING="-t"
else
LDIF2LDBM=../servers/slapd/tools/ldif2ldbm
ACLCONF=$DATADIR/slapd-acl.conf
MASTERCONF=$DATADIR/slapd-repl-master.conf
SLAVECONF=$DATADIR/slapd-repl-slave.conf
+ REFSLAVECONF=$DATADIR/slapd-ref-slave.conf
fi
if test "$LDAP_PROTO" ; then
REPLDIR=./test-repl
LDIF=$DATADIR/test.ldif
LDIFORDERED=$DATADIR/test-ordered.ldif
+MONITOR="cn=monitor"
BASEDN="o=University of Michigan, c=US"
MANAGERDN="cn=Manager, o=University of Michigan, c=US"
+UPDATEDN="cn=Replica, o=University of Michigan, c=US"
PASSWD=secret
BABSDN="cn=Barbara Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US"
BJORNSDN="cn=Bjorn Jensen, ou=Information Technology Division, ou=People, o=University of Michigan, c=US"
echo "Using ldapsearch to check that slapd is running..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -b "$BASEDN" -h localhost -p $PORT \
- 'cn=Monitor' > /dev/null 2>&1
+ $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
echo "Testing slapd searching..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- 'cn=Manager' > /dev/null 2>&1
+ $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
echo "Testing slapd modify operations..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- 'cn=Manager' > /dev/null 2>&1
+ $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
# Make sure we can search the database
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- 'cn=Manager' > /dev/null 2>&1
+ $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
echo "Testing slapd access control..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $PORT \
- 'cn=Monitor' > /dev/null 2>&1
+ $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
echo "Using ldapsearch to check that master slapd is running..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -b "$BASEDN" -h localhost -p $PORT \
- 'cn=Monitor' > /dev/null 2>&1
+ $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
echo "Using ldapsearch to check that slave slapd is running..."
for i in 0 1 2 3 4 5; do
- $LDAPSEARCH -L -b "$BASEDN" -h localhost -p $SLAVEPORT \
- 'cn=Monitor' > /dev/null 2>&1
+ $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 1 ; then
echo "Waiting 5 seconds for slapd to start..."
$SLURPD -f $MASTERCONF -d 4 -t $REPLDIR > $SLURPLOG 2>&1 &
SLURPPID=$!
-echo "Using ldapadd to populate the database..."
+echo "Using ldapadd to populate the master directory..."
$LDAPADD -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD < \
$LDIFORDERED > /dev/null 2>&1
RC=$?
exit $RC
fi
-echo "Using ldapmodify to modify the database..."
+echo "Waiting 15 seconds for slurpd to send changes..."
+sleep 15
+
+echo "Using ldapmodify to modify slave directory..."
+
#
# Do some modifications
#
-$LDAPMODIFY -v -D "$MANAGERDN" -h localhost -p $PORT -w $PASSWD > \
+$LDAPMODIFY -v -D "$MANAGERDN" -h localhost -p $SLAVEPORT -w $PASSWD > \
/dev/null 2>&1 << EOMODS
dn: cn=James A Jones 1, ou=Alumni Association, ou=People, o=University of Michigan, c=US
changetype: modify
$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
PID=$!
-echo "Waiting 5 seconds for slapd to start..."
-sleep 5
+echo "Using ldapsearch to check that slapd is running..."
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 1 ; then
+ echo "Waiting 5 seconds for slapd to start..."
+ sleep 5
+ fi
+done
echo "Using tester for concurrent server access..."
$SLAPDTESTER -b "$BASEDN" -P "$PROGDIR" -d "$DATADIR" -h localhost -p $PORT -D "$MANAGERDN" -w $PASSWD -l 50
--- /dev/null
+#! /bin/sh
+
+#
+# Test default referral
+#
+
+if test $# -eq 0 ; then
+ SRCDIR="."
+else
+ SRCDIR=$1; shift
+fi
+if test $# -eq 1 ; then
+ BACKEND=$1; shift
+fi
+
+echo "running defines.sh $SRCDIR $BACKEND"
+. $SRCDIR/scripts/defines.sh
+
+echo "Cleaning up in $DBDIR and $REPLDIR ..."
+
+rm -f $DBDIR/[!C]*
+rm -f $REPLDIR/[!C]*
+
+echo "Running ldif2ldbm to build slapd database..."
+$LDIF2LDBM -f $CONF -i $LDIF -e ../servers/slapd/tools
+RC=$?
+if test $RC != 0 ; then
+ echo "ldif2ldbm failed!"
+ exit $RC
+fi
+
+echo "Starting master slapd on TCP/IP port $PORT..."
+$SLAPD -f $CONF -p $PORT -d $LVL $TIMING > $MASTERLOG 2>&1 &
+PID=$!
+
+echo "Starting slave slapd on TCP/IP port $SLAVEPORT..."
+$SLAPD -f $REFSLAVECONF -p $SLAVEPORT -d $LVL $TIMING > $SLAVELOG 2>&1 &
+SLAVEPID=$!
+
+echo "Testing for master slapd..."
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $PORT \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 1 ; then
+ echo "Waiting 5 seconds for slapd to start..."
+ sleep 5
+ fi
+done
+
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID
+ exit $RC
+fi
+
+echo "Testing for slave slapd..."
+for i in 0 1 2 3 4 5; do
+ $LDAPSEARCH -L -s base -b "$MONITOR" -h localhost -p $SLAVEPORT \
+ 'objectclass=*' > /dev/null 2>&1
+ RC=$?
+ if test $RC = 1 ; then
+ echo "Waiting 5 seconds for slapd to start..."
+ sleep 5
+ fi
+done
+
+cat /dev/null > $SEARCHOUT
+
+echo "Testing exact searching..."
+$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+ 'sn=jensen' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID $SLAVEPID
+ exit $RC
+fi
+
+echo "Testing OR searching..."
+$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+ '(|(objectclass=rfc822mailgroup)(sn=jones))' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID $SLAVEPID
+ exit $RC
+fi
+
+echo "Testing AND matching and ends-with searching..."
+$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+ '(&(objectclass=rfc822mailgroup)(cn=A*))' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID $SLAVEPID
+ exit $RC
+fi
+
+echo "Testing NOT searching..."
+$LDAPSEARCH -L -S "" -b "$BASEDN" -h localhost -p $SLAVEPORT \
+ '(!(objectclass=person))' >> $SEARCHOUT 2>&1
+if test $RC != 0 ; then
+ echo "ldapsearch failed!"
+ kill -HUP $PID $SLAVEPID
+ exit $RC
+fi
+
+kill -HUP $PID $SLAVEPID
+
+TESTOUT=$SEARCHOUT
+LDIF=$SEARCHOUTMASTER
+
+echo "Filtering ldapsearch results..."
+. $SRCDIR/scripts/acfilter.sh < $SEARCHOUT > $SEARCHFLT
+echo "Filtering original ldif used to create database..."
+. $SRCDIR/scripts/acfilter.sh < $LDIF > $LDIFFLT
+echo "Comparing filter output..."
+cmp $SEARCHFLT $LDIFFLT
+
+if test $? != 0 ; then
+ echo "Comparison failed"
+ exit 1
+fi
+
+echo ">>>>> Test succeeded"
+
+
+exit 0