Commit 73276e84 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Import experimental referral implementation from OPENLDAP_DEVEL_REFERRALS.

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.
parent 9568a013
......@@ -272,6 +272,21 @@ Package=<4>
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
}}}
###############################################################################
......@@ -284,6 +299,30 @@ Package=<5>
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
}}}
###############################################################################
......
......@@ -29,17 +29,17 @@ static int dodelete LDAP_P((
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
......@@ -96,6 +96,10 @@ main( int argc, char **argv )
case 'v': /* verbose mode */
verbose++;
break;
case 'M':
/* enable Manage DSA IT */
manageDSAit++;
break;
case 'W':
want_bindpw++;
break;
......@@ -164,6 +168,28 @@ main( int argc, char **argv )
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 ] );
......
......@@ -72,12 +72,13 @@ usage( const char *prog )
{
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"
......@@ -97,7 +98,7 @@ main( int argc, char **argv )
{
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 ];
......@@ -112,11 +113,11 @@ main( int argc, char **argv )
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;
......@@ -182,6 +183,10 @@ main( int argc, char **argv )
case 'v': /* verbose mode */
verbose++;
break;
case 'M':
/* enable Manage DSA IT */
manageDSAit++;
break;
case 'W':
want_bindpw++;
break;
......@@ -259,6 +264,28 @@ main( int argc, char **argv )
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 ) {
/*
......
......@@ -44,20 +44,20 @@ static int domodrdn LDAP_P((
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
......@@ -116,6 +116,10 @@ main(int argc, char **argv)
case 'r': /* remove old RDN */
remove++;
break;
case 'M':
/* enable Manage DSA IT */
manageDSAit++;
break;
case 'W':
want_bindpw++;
break;
......@@ -217,6 +221,28 @@ main(int argc, char **argv)
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);
......
......@@ -22,7 +22,9 @@ usage( char *s )
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" );
......@@ -31,9 +33,8 @@ usage( char *s )
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" );
......@@ -89,21 +90,21 @@ main( int argc, char **argv )
{
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;
......@@ -134,6 +135,10 @@ main( int argc, char **argv )
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;
......@@ -339,6 +344,28 @@ main( int argc, char **argv )
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 {
......
......@@ -14,6 +14,8 @@ ldapdelete \- ldap delete entry tool
[\c
.BR \-c ]
[\c
.BR \-M[M] ]
[\c
.BI \-d \ debuglevel\fR]
[\c
.BI \-f \ file\fR]
......@@ -71,6 +73,11 @@ Continuous operation mode. Errors are reported, but
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
......
......@@ -18,6 +18,8 @@ ldapmodify, ldapadd \- ldap modify entry and ldap add entry tools
[\c
.BR \-k ]
[\c
.BR \-M[M] ]
[\c
.BI \-d \ debuglevel\fR]
[\c
.BI \-D \ binddn\fR]
......@@ -124,6 +126,11 @@ lines that begin with
(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
......
......@@ -16,6 +16,8 @@ ldapmodrdn \- ldap modify entry RDN tool
[\c
.BR \-c ]
[\c
.BR \-M[M] ]
[\c
.BI \-d \ debuglevel\fR]
[\c
.BI \-D \ binddn\fR]
......@@ -74,6 +76,11 @@ Continuous operation mode. Errors are reported, but ldapmodify
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
......
......@@ -22,6 +22,8 @@ ldapsearch \- ldap search tool
[\c
.BR \-L ]
[\c
.BR \-M[M] ]
[\c
.BR \-R ]
[\c
.BI \-d \ debuglevel\fR]
......@@ -114,6 +116,11 @@ Display search results in
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
......
......@@ -198,6 +198,7 @@ used in conjunction with the schemacheck option.
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.
......@@ -284,6 +285,12 @@ It specifies the DN allowed to make changes to the replica (typically,
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
......
......@@ -167,6 +167,8 @@ typedef struct ldapcontrol {
#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"
......
......@@ -90,7 +90,7 @@ BSC32=bscmake.exe
# 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"
......@@ -111,7 +111,7 @@ BSC32=bscmake.exe
# 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
......
......@@ -10,7 +10,7 @@ SRCS = main.c daemon.c connection.c search.c filter.c add.c charray.c \
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 \
......@@ -18,7 +18,7 @@ OBJS = main.o daemon.o connection.o search.o filter.o add.o charray.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
......
......@@ -28,7 +28,7 @@ do_abandon(
ber_int_t id;
Operation *o;
Operation **oo;
int rc;
int rc, notfound;
Debug( LDAP_DEBUG_TRACE, "do_abandon\n", 0, 0, 0 );
......@@ -52,21 +52,28 @@ do_abandon(
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;
}
}
......@@ -81,13 +88,14 @@ do_abandon(
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;
}
......@@ -330,6 +330,7 @@ access2str( int access )
strcat( buf, "read" );
} else if ( ACL_IS_WRITE(access) ) {
strcat( buf, "write" );
} else {
strcat( buf, "unknown" );
}
......
......@@ -38,7 +38,7 @@ do_add( Connection *conn, Operation *op )
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;
}
......@@ -89,8 +89,8 @@ do_add( Connection *conn, Operation *op )
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;
......@@ -127,8 +127,8 @@ do_add( Connection *conn, Operation *op )
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;
}
......@@ -155,14 +155,14 @@ do_add( Connection *conn, Operation *op )
} 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;
......
......@@ -32,7 +32,8 @@ bdb2i_back_add_internal(
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 );