mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-06-09 08:42:22 -04:00
LDAPv3 Referrals (using old style referral entries) initial commit.
Have not completed work on backends other than LDBM. All send_() routines have new parameters (which will likely change some more to support responses with controls). slapd/back-ldbm only compiles. NOT TESTED. This is a work in progress.
This commit is contained in:
parent
59a6663312
commit
fe242e3ca7
33 changed files with 8194 additions and 2009 deletions
1698
include/ldap.h
1698
include/ldap.h
File diff suppressed because it is too large
Load diff
|
|
@ -12,24 +12,23 @@
|
|||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
extern Backend *select_backend();
|
||||
|
||||
extern char *default_referral;
|
||||
|
||||
void
|
||||
int
|
||||
do_abandon(
|
||||
Connection *conn,
|
||||
Operation *op
|
||||
)
|
||||
{
|
||||
int id;
|
||||
Backend *be;
|
||||
ber_int_t id;
|
||||
Operation *o;
|
||||
Operation **oo;
|
||||
int rc, notfound;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "do_abandon\n", 0, 0, 0 );
|
||||
|
||||
|
|
@ -40,31 +39,63 @@ do_abandon(
|
|||
*/
|
||||
|
||||
if ( ber_scanf( op->o_ber, "i", &id ) == LBER_ERROR ) {
|
||||
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0 ,0 );
|
||||
return;
|
||||
Debug( LDAP_DEBUG_ANY, "do_abandon: ber_scanf failed\n", 0, 0 ,0 );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( (rc = get_ctrls( conn, op, 0 )) != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_abandon: get_ctrls failed\n", 0, 0 ,0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
pthread_mutex_lock( &conn->c_opsmutex );
|
||||
for ( o = conn->c_ops; o != NULL; o = o->o_next ) {
|
||||
if ( o->o_msgid == id )
|
||||
break;
|
||||
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 );
|
||||
|
||||
notfound = 0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if ( o != NULL ) {
|
||||
pthread_mutex_lock( &o->o_abandonmutex );
|
||||
o->o_abandon = 1;
|
||||
pthread_mutex_unlock( &o->o_abandonmutex );
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE, "do_abandon: op not found\n", 0, 0,
|
||||
0 );
|
||||
for ( oo = &conn->c_pending_ops;
|
||||
(*oo != NULL) && ((*oo)->o_msgid != id);
|
||||
oo = &(*oo)->o_next )
|
||||
{
|
||||
/* EMPTY */ ;
|
||||
}
|
||||
pthread_mutex_unlock( &conn->c_opsmutex );
|
||||
|
||||
if( *oo != NULL ) {
|
||||
o = *oo;
|
||||
*oo = (*oo)->o_next;
|
||||
slap_op_free( o );
|
||||
notfound = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,36 +10,38 @@
|
|||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/time.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
extern Backend *select_backend();
|
||||
extern char *dn_normalize();
|
||||
static void add_created_attrs(Operation *op, Entry *e);
|
||||
|
||||
extern char *default_referral;
|
||||
extern time_t currenttime;
|
||||
extern pthread_mutex_t currenttime_mutex;
|
||||
extern int global_lastmod;
|
||||
|
||||
static void add_created_attrs();
|
||||
|
||||
void
|
||||
do_add( conn, op )
|
||||
Connection *conn;
|
||||
Operation *op;
|
||||
int
|
||||
do_add( Connection *conn, Operation *op )
|
||||
{
|
||||
BerElement *ber = op->o_ber;
|
||||
char *dn, *last;
|
||||
unsigned long len, tag;
|
||||
ber_len_t len;
|
||||
ber_tag_t tag;
|
||||
Entry *e;
|
||||
Backend *be;
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "do_add\n", 0, 0, 0 );
|
||||
|
||||
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", NULL );
|
||||
return LDAP_SASL_BIND_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the add request. It looks like this:
|
||||
*
|
||||
|
|
@ -52,18 +54,23 @@ do_add( conn, op )
|
|||
* }
|
||||
*/
|
||||
|
||||
/* get the name */
|
||||
if ( ber_scanf( ber, "{a", /*}*/ &dn ) == LBER_ERROR ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
|
||||
|
||||
/* get the name */
|
||||
if ( ber_scanf( ber, "{a", &dn ) == LBER_ERROR ) {
|
||||
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
|
||||
"decoding error" );
|
||||
return;
|
||||
}
|
||||
e->e_dn = dn;
|
||||
dn = dn_normalize( strdup( dn ) );
|
||||
Debug( LDAP_DEBUG_ARGS, " do_add: dn (%s)\n", dn, 0, 0 );
|
||||
e->e_ndn = dn_normalize_case( ch_strdup( dn ) );
|
||||
e->e_private = NULL;
|
||||
|
||||
dn = NULL;
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, " do_add: ndn (%s)\n", e->e_ndn, 0, 0 );
|
||||
|
||||
/* get the attrs */
|
||||
e->e_attrs = NULL;
|
||||
|
|
@ -73,19 +80,20 @@ do_add( conn, op )
|
|||
struct berval **vals;
|
||||
|
||||
if ( ber_scanf( ber, "{a{V}}", &type, &vals ) == LBER_ERROR ) {
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
|
||||
NULL, "decoding error" );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
entry_free( e );
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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,
|
||||
NULL );
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
|
||||
NULL, "no values for type", NULL );
|
||||
free( type );
|
||||
entry_free( e );
|
||||
return;
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
attr_merge( e, type, vals );
|
||||
|
|
@ -94,19 +102,34 @@ do_add( conn, op )
|
|||
ber_bvecfree( vals );
|
||||
}
|
||||
|
||||
if ( ber_scanf( ber, /*{*/ "}") == LBER_ERROR ) {
|
||||
entry_free( e );
|
||||
Debug( LDAP_DEBUG_ANY, "do_add: ber_scanf failed\n", 0, 0, 0 );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
|
||||
entry_free( e );
|
||||
Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d ADD dn=\"%s\"\n",
|
||||
conn->c_connid, op->o_opid, dn, 0, 0 );
|
||||
conn->c_connid, op->o_opid, e->e_ndn, 0, 0 );
|
||||
|
||||
/*
|
||||
* We could be serving multiple database backends. Select the
|
||||
* appropriate one, or send a referral to our "referral server"
|
||||
* if we don't hold it.
|
||||
*/
|
||||
if ( (be = select_backend( dn )) == NULL ) {
|
||||
be = select_backend( e->e_ndn );
|
||||
if ( be == NULL ) {
|
||||
entry_free( e );
|
||||
send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
|
||||
default_referral );
|
||||
return;
|
||||
send_ldap_result( conn, op, LDAP_REFERRAL, NULL,
|
||||
NULL, default_referral );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -115,38 +138,46 @@ do_add( conn, op )
|
|||
* 2) this backend is master for what it holds;
|
||||
* 3) it's a replica and the dn supplied is the updatedn.
|
||||
*/
|
||||
if ( be->be_add != NULL ) {
|
||||
if ( be->be_add ) {
|
||||
/* do the update here */
|
||||
if ( be->be_updatedn == NULL || strcasecmp( be->be_updatedn,
|
||||
op->o_dn ) == 0 ) {
|
||||
if ( (be->be_lastmod == ON || be->be_lastmod == 0 &&
|
||||
global_lastmod == ON) && be->be_updatedn == NULL ) {
|
||||
if ( be->be_update_ndn == NULL ||
|
||||
strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
|
||||
{
|
||||
if ( (be->be_lastmod == ON || (be->be_lastmod == UNDEFINED &&
|
||||
global_lastmod == ON)) && be->be_update_ndn == NULL ) {
|
||||
|
||||
add_created_attrs( op, e );
|
||||
}
|
||||
if ( (*be->be_add)( be, conn, op, e ) == 0 ) {
|
||||
replog( be, LDAP_REQ_ADD, e->e_dn, e, 0 );
|
||||
be_entry_release_w( be, e );
|
||||
}
|
||||
|
||||
} else {
|
||||
entry_free( e );
|
||||
send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
|
||||
default_referral );
|
||||
send_ldap_result( conn, op, rc = LDAP_REFERRAL, NULL,
|
||||
NULL, default_referral );
|
||||
}
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_ARGS, " do_add: HHH\n", 0, 0, 0 );
|
||||
entry_free( e );
|
||||
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
|
||||
"Function not implemented" );
|
||||
send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
|
||||
NULL, "Function not implemented", NULL );
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
add_created_attrs( Operation *op, Entry *e )
|
||||
{
|
||||
char buf[20];
|
||||
char buf[22];
|
||||
struct berval bv;
|
||||
struct berval *bvals[2];
|
||||
Attribute **a, **next;
|
||||
Attribute *tmp;
|
||||
struct tm *ltm;
|
||||
time_t currenttime;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "add_created_attrs\n", 0, 0, 0 );
|
||||
|
||||
|
|
@ -155,8 +186,7 @@ add_created_attrs( Operation *op, Entry *e )
|
|||
|
||||
/* remove any attempts by the user to add these attrs */
|
||||
for ( a = &e->e_attrs; *a != NULL; a = next ) {
|
||||
if ( strcasecmp( (*a)->a_type, "createtimestamp" ) == 0
|
||||
|| strcasecmp( (*a)->a_type, "creatorsname" ) == 0 ) {
|
||||
if ( oc_check_no_usermod_attr( (*a)->a_type ) ) {
|
||||
tmp = *a;
|
||||
*a = (*a)->a_next;
|
||||
attr_free( tmp );
|
||||
|
|
@ -167,7 +197,7 @@ add_created_attrs( Operation *op, Entry *e )
|
|||
}
|
||||
|
||||
if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
|
||||
bv.bv_val = "NULLDN";
|
||||
bv.bv_val = "<anonymous>";
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
} else {
|
||||
bv.bv_val = op->o_dn;
|
||||
|
|
@ -175,10 +205,16 @@ add_created_attrs( Operation *op, Entry *e )
|
|||
}
|
||||
attr_merge( e, "creatorsname", bvals );
|
||||
|
||||
pthread_mutex_lock( ¤ttime_mutex );
|
||||
ltm = localtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
|
||||
pthread_mutex_unlock( ¤ttime_mutex );
|
||||
currenttime = slap_get_time();
|
||||
ldap_pvt_thread_mutex_lock( &gmtime_mutex );
|
||||
#ifndef LDAP_LOCALTIME
|
||||
ltm = gmtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
|
||||
#else
|
||||
ltm = localtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
|
||||
#endif
|
||||
ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
|
||||
|
||||
bv.bv_val = buf;
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
|
|
|
|||
547
servers/slapd/back-bdb2/search.c
Normal file
547
servers/slapd/back-bdb2/search.c
Normal file
|
|
@ -0,0 +1,547 @@
|
|||
/* search.c - bdb2 backend search function */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/time.h>
|
||||
|
||||
#include "slap.h"
|
||||
#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 int
|
||||
bdb2i_back_search_internal(
|
||||
BackendDB *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *base,
|
||||
int scope,
|
||||
int deref,
|
||||
int slimit,
|
||||
int tlimit,
|
||||
Filter *filter,
|
||||
char *filterstr,
|
||||
char **attrs,
|
||||
int attrsonly
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int err;
|
||||
time_t stoptime;
|
||||
ID_BLOCK *candidates;
|
||||
ID id;
|
||||
Entry *e;
|
||||
Attribute *ref;
|
||||
char *matched = NULL;
|
||||
int rmaxsize, nrefs;
|
||||
char *rbuf, *rcur;
|
||||
int nentries = 0;
|
||||
char *realBase;
|
||||
|
||||
Debug(LDAP_DEBUG_ARGS, "=> bdb2i_back_search\n", 0, 0, 0);
|
||||
|
||||
if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
|
||||
tlimit = -1; /* allow root to set no limit */
|
||||
} else {
|
||||
tlimit = (tlimit > be->be_timelimit || tlimit < 1) ?
|
||||
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 {
|
||||
slimit = (slimit > be->be_sizelimit || slimit < 1) ?
|
||||
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);
|
||||
}
|
||||
|
||||
(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 );
|
||||
}
|
||||
|
||||
/* null candidates means we could not find the base object */
|
||||
if ( candidates == NULL ) {
|
||||
send_ldap_result( conn, op, err, matched, "" );
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
|
||||
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 ) ) {
|
||||
/* 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 );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
/* check time limit */
|
||||
if ( tlimit != -1 && slap_get_time() > stoptime ) {
|
||||
send_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 );
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if ( scope == LDAP_SCOPE_SUBTREE &&
|
||||
e->e_ndn != NULL &&
|
||||
strncmp( e->e_ndn, "REF=", 4 ) == 0 &&
|
||||
(ref = attr_find( e->e_attrs, "ref" )) != NULL )
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( ref->a_vals == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n",
|
||||
e->e_dn, 0, 0 );
|
||||
} else {
|
||||
if( op->o_protocol < LDAP_VERSION3 ) {
|
||||
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++;
|
||||
}
|
||||
} else {
|
||||
send_search_reference( conn, op, ref->a_vals );
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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 );
|
||||
free( dn );
|
||||
}
|
||||
|
||||
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,
|
||||
nrefs > 0 ? rbuf : NULL, nentries );
|
||||
bdb2i_idl_free( candidates );
|
||||
free( rbuf );
|
||||
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
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( e != NULL ) {
|
||||
/* free reader lock */
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
}
|
||||
|
||||
ldap_pvt_thread_yield();
|
||||
}
|
||||
bdb2i_idl_free( candidates );
|
||||
if ( nrefs > 0 ) {
|
||||
send_search_result( conn, op, LDAP_REFERRALS, NULL,
|
||||
rbuf, nentries );
|
||||
} else {
|
||||
send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL,
|
||||
nentries );
|
||||
}
|
||||
free( rbuf );
|
||||
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bdb2_back_search(
|
||||
BackendDB *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *base,
|
||||
int scope,
|
||||
int deref,
|
||||
int slimit,
|
||||
int tlimit,
|
||||
Filter *filter,
|
||||
char *filterstr,
|
||||
char **attrs,
|
||||
int attrsonly
|
||||
)
|
||||
{
|
||||
DB_LOCK lock;
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
struct timeval time1;
|
||||
int ret;
|
||||
|
||||
bdb2i_start_timing( be->bd_info, &time1 );
|
||||
|
||||
if ( bdb2i_enter_backend_r( &lock ) != 0 ) {
|
||||
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
return( -1 );
|
||||
|
||||
}
|
||||
|
||||
ret = bdb2i_back_search_internal( be, conn, op, base, scope, deref,
|
||||
slimit, tlimit, filter, filterstr, attrs, attrsonly );
|
||||
|
||||
(void) bdb2i_leave_backend_r( lock );
|
||||
bdb2i_stop_timing( be->bd_info, time1, "SRCH", conn, op );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
|
||||
static ID_BLOCK *
|
||||
base_candidates(
|
||||
BackendDB *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *base,
|
||||
Filter *filter,
|
||||
char **attrs,
|
||||
int attrsonly,
|
||||
char **matched,
|
||||
int *err
|
||||
)
|
||||
{
|
||||
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 */
|
||||
|
||||
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,
|
||||
Filter *filter,
|
||||
char **attrs,
|
||||
int attrsonly,
|
||||
char **matched,
|
||||
int *err
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Entry *e = NULL;
|
||||
Filter *f;
|
||||
char buf[20];
|
||||
ID_BLOCK *candidates;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "onelevel_candidates: base: \"%s\"\n", base, 0, 0);
|
||||
|
||||
*err = LDAP_SUCCESS;
|
||||
|
||||
/* 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 );
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 );
|
||||
}
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
if ( base != NULL && *base != '\0' &&
|
||||
(e = bdb2i_dn2entry_r( be, base, matched )) == NULL )
|
||||
{
|
||||
*err = LDAP_NO_SUCH_OBJECT;
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
if (e) {
|
||||
bdb2i_cache_return_entry_r( &li->li_cache, e );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
candidates = bdb2i_filter_candidates( be, filter );
|
||||
|
||||
/* free up just the parts we allocated above */
|
||||
if ( f != NULL ) {
|
||||
*filterarg_ptr = NULL;
|
||||
filter_free( f );
|
||||
}
|
||||
|
||||
return( candidates );
|
||||
}
|
||||
172
servers/slapd/back-ldap/search.c
Normal file
172
servers/slapd/back-ldap/search.c
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/* search.c - ldap backend search function */
|
||||
|
||||
/*
|
||||
* Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose
|
||||
* on any computer system, and to alter it and redistribute it, subject
|
||||
* to the following restrictions:
|
||||
*
|
||||
* 1. The author is not responsible for the consequences of use of this
|
||||
* software, no matter how awful, even if they arise from flaws in it.
|
||||
*
|
||||
* 2. The origin of this software must not be misrepresented, either by
|
||||
* explicit claim or by omission. Since few users ever read sources,
|
||||
* credits should appear in the documentation.
|
||||
*
|
||||
* 3. Altered versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software. Since few users
|
||||
* ever read sources, credits should appear in the documentation.
|
||||
*
|
||||
* 4. This notice may not be removed or altered.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/time.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldap.h"
|
||||
|
||||
int
|
||||
ldap_back_search(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *base,
|
||||
int scope,
|
||||
int deref,
|
||||
int size,
|
||||
int time,
|
||||
Filter *filter,
|
||||
char *filterstr,
|
||||
char **attrs,
|
||||
int attrsonly
|
||||
)
|
||||
{
|
||||
struct ldapinfo *li = (struct ldapinfo *) be->be_private;
|
||||
struct ldapconn *lc;
|
||||
struct timeval tv;
|
||||
LDAPMessage *res, *e;
|
||||
int i, rc, msgid, sres = LDAP_SUCCESS;
|
||||
char *match = NULL, *err = NULL;
|
||||
|
||||
lc = ldap_back_getconn(li, conn, op);
|
||||
if (!lc)
|
||||
return( -1 );
|
||||
|
||||
if (deref != -1)
|
||||
ldap_set_option( lc->ld, LDAP_OPT_DEREF, (void *)&deref);
|
||||
if (time != -1)
|
||||
ldap_set_option( lc->ld, LDAP_OPT_TIMELIMIT, (void *)&time);
|
||||
if (size != -1)
|
||||
ldap_set_option( lc->ld, LDAP_OPT_SIZELIMIT, (void *)&size);
|
||||
if (!lc->bound) {
|
||||
ldap_back_dobind(lc, op);
|
||||
if (!lc->bound)
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ((msgid = ldap_search(lc->ld, base, scope, filterstr, attrs,
|
||||
attrsonly)) == -1)
|
||||
fail: return( ldap_back_op_result(lc, op) );
|
||||
|
||||
/* We pull apart the ber result, stuff it into a slapd entry, and
|
||||
* let send_search_entry stuff it back into ber format. Slow & ugly,
|
||||
* but this is necessary for version matching, and for ACL processing.
|
||||
*/
|
||||
|
||||
for (i=0, rc=0; rc != -1;
|
||||
rc = ldap_result(lc->ld, LDAP_RES_ANY, 0, &tv, &res)) {
|
||||
int ab;
|
||||
|
||||
/* check for abandon */
|
||||
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
|
||||
ab = op->o_abandon;
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
if (ab) {
|
||||
ldap_abandon(lc->ld, msgid);
|
||||
} else if (rc == 0) {
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 100000;
|
||||
ldap_pvt_thread_yield();
|
||||
continue;
|
||||
} else if (rc == LDAP_RES_SEARCH_ENTRY) {
|
||||
e = ldap_first_entry(lc->ld,res);
|
||||
ldap_send_entry(be, op, lc, e, attrs, attrsonly);
|
||||
i++;
|
||||
} else {
|
||||
sres = ldap_result2error(lc->ld, res, 1);
|
||||
ldap_get_option(lc->ld, LDAP_OPT_ERROR_STRING, &err);
|
||||
ldap_get_option(lc->ld, LDAP_OPT_MATCHED_DN, &match);
|
||||
rc = 0;
|
||||
}
|
||||
ldap_msgfree(res);
|
||||
if (ab)
|
||||
return (0);
|
||||
else if (rc == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc == -1)
|
||||
goto fail;
|
||||
|
||||
send_search_result( conn, op, sres, match, err, i );
|
||||
if (match)
|
||||
free(match);
|
||||
if (err)
|
||||
free(err);
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
ldap_send_entry(
|
||||
Backend *be,
|
||||
Operation *op,
|
||||
struct ldapconn *lc,
|
||||
LDAPMessage *e,
|
||||
char **attrs,
|
||||
int attrsonly
|
||||
)
|
||||
{
|
||||
char *a;
|
||||
Entry ent;
|
||||
BerElement *ber = NULL;
|
||||
Attribute *attr;
|
||||
struct berval *dummy = NULL;
|
||||
|
||||
ent.e_dn = ldap_get_dn(lc->ld, e);
|
||||
ent.e_ndn = dn_normalize_case( ch_strdup( ent.e_dn));
|
||||
ent.e_id = 0;
|
||||
ent.e_attrs = 0;
|
||||
ent.e_private = 0;
|
||||
attr = (Attribute *)4;
|
||||
attr = (Attribute *)((long)&ent.e_attrs - ((long)&attr->a_next-4));
|
||||
|
||||
for (a = ldap_first_attribute(lc->ld, e, &ber); a;
|
||||
a = ldap_next_attribute(lc->ld, e, ber)) {
|
||||
attr->a_next = (Attribute *)ch_malloc( sizeof(Attribute) );
|
||||
attr=attr->a_next;
|
||||
attr->a_next = 0;
|
||||
attr->a_type = ch_strdup(a);
|
||||
attr->a_syntax = attr_syntax(a);
|
||||
attr->a_vals = ldap_get_values_len(lc->ld, e, a);
|
||||
if (!attr->a_vals)
|
||||
attr->a_vals = &dummy;
|
||||
}
|
||||
send_search_entry( be, lc->conn, op, &ent, attrs, attrsonly, 0 );
|
||||
for (;ent.e_attrs;) {
|
||||
attr=ent.e_attrs;
|
||||
ent.e_attrs = attr->a_next;
|
||||
free(attr->a_type);
|
||||
if (attr->a_vals != &dummy)
|
||||
ber_bvecfree(attr->a_vals);
|
||||
free(attr);
|
||||
}
|
||||
if (ber)
|
||||
ber_free(ber,0);
|
||||
}
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
/* add.c - ldap ldbm back-end add routine */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
extern int global_schemacheck;
|
||||
extern char *dn_parent();
|
||||
extern char *dn_normalize();
|
||||
extern Entry *dn2entry();
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
int
|
||||
ldbm_back_add(
|
||||
|
|
@ -21,49 +20,33 @@ ldbm_back_add(
|
|||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char *matched;
|
||||
char *dn = NULL, *pdn = NULL;
|
||||
Entry *p;
|
||||
char *pdn;
|
||||
Entry *p = NULL;
|
||||
int rootlock = 0;
|
||||
int rc;
|
||||
|
||||
dn = dn_normalize( strdup( e->e_dn ) );
|
||||
matched = NULL;
|
||||
if ( (p = dn2entry( be, dn, &matched )) != NULL ) {
|
||||
cache_return_entry( &li->li_cache, p );
|
||||
Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_add: %s\n", e->e_dn, 0, 0);
|
||||
|
||||
/* nobody else can add until we lock our parent */
|
||||
ldap_pvt_thread_mutex_lock(&li->li_add_mutex);
|
||||
|
||||
if ( ( dn2id( be, e->e_ndn ) ) != NOID ) {
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
|
||||
entry_free( e );
|
||||
free( dn );
|
||||
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
|
||||
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
|
||||
NULL, NULL, NULL );
|
||||
return( -1 );
|
||||
}
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
/* XXX race condition here til we cache_add_entry_lock below XXX */
|
||||
|
||||
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n", 0, 0,
|
||||
0 );
|
||||
entry_free( e );
|
||||
free( dn );
|
||||
send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, "",
|
||||
"" );
|
||||
return( -1 );
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
|
||||
|
||||
/*
|
||||
* Try to add the entry to the cache, assign it a new dnid
|
||||
* and mark it locked. This should only fail if the entry
|
||||
* already exists.
|
||||
*/
|
||||
Debug( LDAP_DEBUG_TRACE, "entry failed schema check\n",
|
||||
0, 0, 0 );
|
||||
|
||||
e->e_id = next_id( be );
|
||||
if ( cache_add_entry_lock( &li->li_cache, e, ENTRY_STATE_CREATING )
|
||||
!= 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
|
||||
0 );
|
||||
next_id_return( be, e->e_id );
|
||||
entry_free( e );
|
||||
free( dn );
|
||||
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, "", "" );
|
||||
send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION,
|
||||
NULL, NULL, NULL );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
|
|
@ -73,42 +56,122 @@ ldbm_back_add(
|
|||
* add the entry.
|
||||
*/
|
||||
|
||||
if ( (pdn = dn_parent( be, dn )) != NULL ) {
|
||||
/* no parent */
|
||||
matched = NULL;
|
||||
if ( (p = dn2entry( be, pdn, &matched )) == NULL ) {
|
||||
pdn = dn_parent( be, e->e_ndn );
|
||||
|
||||
if( pdn != NULL && *pdn != '\0' && !be_issuffix(be, "") ) {
|
||||
char *matched = NULL;
|
||||
|
||||
assert( *pdn != '\0' );
|
||||
|
||||
/* get parent with writer lock */
|
||||
if ( (p = dn2entry_w( be, pdn, &matched )) == NULL ) {
|
||||
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, "" );
|
||||
matched, NULL, NULL );
|
||||
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
Debug( LDAP_DEBUG_TRACE, "parent does not exist\n", 0,
|
||||
0, 0 );
|
||||
goto error_return;
|
||||
|
||||
entry_free( e );
|
||||
free( pdn );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* don't need the add lock anymore */
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
|
||||
|
||||
free(pdn);
|
||||
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
|
||||
if ( ! access_allowed( be, conn, op, p, "children", NULL,
|
||||
op->o_dn, ACL_WRITE ) ) {
|
||||
if ( ! access_allowed( be, conn, op, p,
|
||||
"children", NULL, ACL_WRITE ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
|
||||
0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
"", "" );
|
||||
goto error_return;
|
||||
NULL, NULL, NULL );
|
||||
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
|
||||
entry_free( e );
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
if ( ! be_isroot( be, op->o_dn ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "no parent & not root\n", 0,
|
||||
0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
"", "" );
|
||||
goto error_return;
|
||||
if(pdn != NULL) {
|
||||
assert( *pdn == '\0' );
|
||||
free(pdn);
|
||||
}
|
||||
p = NULL;
|
||||
|
||||
/* no parent, must be adding entry to root */
|
||||
if ( ! be_isroot( be, op->o_ndn ) ) {
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "%s add denied\n",
|
||||
pdn == NULL ? "suffix" : "entry at root",
|
||||
0, 0 );
|
||||
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL, NULL, NULL );
|
||||
|
||||
entry_free( e );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* no parent, acquire the root write lock
|
||||
* and release the add lock.
|
||||
*/
|
||||
ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
|
||||
rootlock = 1;
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_add_mutex);
|
||||
}
|
||||
|
||||
e->e_id = next_id( be );
|
||||
|
||||
/*
|
||||
* Try to add the entry to the cache, assign it a new dnid.
|
||||
*/
|
||||
rc = cache_add_entry_rw(&li->li_cache, e, CACHE_WRITE_LOCK);
|
||||
|
||||
if ( rc != 0 ) {
|
||||
if( p != NULL) {
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
}
|
||||
|
||||
if ( rootlock ) {
|
||||
/* release root lock */
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "cache_add_entry_lock failed\n", 0, 0,
|
||||
0 );
|
||||
|
||||
/* return the id */
|
||||
next_id_return( be, e->e_id );
|
||||
|
||||
/* free the entry */
|
||||
entry_free( e );
|
||||
|
||||
if(rc > 0) {
|
||||
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL, NULL );
|
||||
} else {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
|
||||
}
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
rc = -1;
|
||||
|
||||
/*
|
||||
* add it to the id2children index for the parent
|
||||
*/
|
||||
|
|
@ -116,9 +179,9 @@ ldbm_back_add(
|
|||
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, "",
|
||||
"" );
|
||||
goto error_return;
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -130,44 +193,48 @@ ldbm_back_add(
|
|||
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, "", "" );
|
||||
goto error_return;
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* dn2id index */
|
||||
if ( dn2id_add( be, dn, e->e_id ) != 0 ) {
|
||||
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, "", "" );
|
||||
goto error_return;
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* id2entry index */
|
||||
if ( id2entry_add( be, e ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "id2entry_add failed\n", 0,
|
||||
0, 0 );
|
||||
(void) dn2id_delete( be, dn );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
goto error_return;
|
||||
(void) dn2id_delete( be, e->e_ndn );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL, NULL );
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
|
||||
if ( dn != NULL )
|
||||
free( dn );
|
||||
if ( pdn != NULL )
|
||||
free( pdn );
|
||||
cache_set_state( &li->li_cache, e, 0 );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( 0 );
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
|
||||
rc = 0;
|
||||
|
||||
error_return:;
|
||||
if ( dn != NULL )
|
||||
free( dn );
|
||||
if ( pdn != NULL )
|
||||
free( pdn );
|
||||
next_id_return( be, e->e_id );
|
||||
cache_delete_entry( &li->li_cache, e );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return_results:;
|
||||
if (p != NULL) {
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
}
|
||||
|
||||
return( -1 );
|
||||
if ( rootlock ) {
|
||||
/* release root lock */
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
|
||||
}
|
||||
|
||||
if ( rc ) {
|
||||
/* free entry and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, e );
|
||||
}
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
|
|
|||
321
servers/slapd/back-ldbm/alias.c
Normal file
321
servers/slapd/back-ldbm/alias.c
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
/*
|
||||
* 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"
|
||||
#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)
|
||||
{
|
||||
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,
|
||||
NULL, "circular alias", NULL );
|
||||
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,
|
||||
NULL, "circular alias", NULL );
|
||||
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,
|
||||
NULL, "dangling alias", NULL );
|
||||
|
||||
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,
|
||||
NULL, "alias missing aliasedObjectName", NULL );
|
||||
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,
|
||||
NULL, "maximum alias dereference depth exceeded", NULL );
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
)
|
||||
{
|
||||
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);
|
||||
}
|
||||
/* 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,
|
||||
NULL, "maximum alias dereference depth exceeded for base", NULL );
|
||||
}
|
||||
|
||||
if (newDN == NULL) {
|
||||
newDN = ch_strdup ( dn );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= returning deref DN of \"%s\"\n", newDN, 0, 0 );
|
||||
|
||||
return newDN;
|
||||
}
|
||||
|
|
@ -1,22 +1,63 @@
|
|||
/* bind.c - ldbm backend bind and unbind routines */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/krb.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/unistd.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#ifdef KERBEROS
|
||||
#include "krb.h"
|
||||
#endif
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
extern Entry *dn2entry();
|
||||
extern Attribute *attr_find();
|
||||
#include <lutil.h>
|
||||
|
||||
#ifdef KERBEROS
|
||||
#ifdef HAVE_KERBEROS
|
||||
extern int krbv4_ldap_auth();
|
||||
#endif
|
||||
|
||||
static int
|
||||
crypted_value_find(
|
||||
struct berval **vals,
|
||||
struct berval *v,
|
||||
int syntax,
|
||||
int normalize,
|
||||
struct berval *cred
|
||||
)
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; vals[i] != NULL; i++ ) {
|
||||
if ( syntax != SYNTAX_BIN ) {
|
||||
int result;
|
||||
|
||||
#ifdef SLAPD_CRYPT
|
||||
ldap_pvt_thread_mutex_lock( &crypt_mutex );
|
||||
#endif
|
||||
|
||||
result = lutil_passwd(
|
||||
(char*) cred->bv_val,
|
||||
(char*) vals[i]->bv_val,
|
||||
NULL );
|
||||
|
||||
#ifdef SLAPD_CRYPT
|
||||
ldap_pvt_thread_mutex_unlock( &crypt_mutex );
|
||||
#endif
|
||||
|
||||
return result;
|
||||
|
||||
} else {
|
||||
if ( value_cmp( vals[i], v, syntax, normalize ) == 0 ) {
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
int
|
||||
ldbm_back_bind(
|
||||
Backend *be,
|
||||
|
|
@ -24,127 +65,209 @@ ldbm_back_bind(
|
|||
Operation *op,
|
||||
char *dn,
|
||||
int method,
|
||||
struct berval *cred
|
||||
char *mech,
|
||||
struct berval *cred,
|
||||
char** edn
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Entry *e;
|
||||
Attribute *a;
|
||||
int rc;
|
||||
char *matched = NULL;
|
||||
#ifdef KERBEROS
|
||||
char *matched;
|
||||
#ifdef HAVE_KERBEROS
|
||||
char krbname[MAX_K_NAME_SZ + 1];
|
||||
AUTH_DAT ad;
|
||||
#endif
|
||||
|
||||
if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
|
||||
Debug(LDAP_DEBUG_ARGS, "==> ldbm_back_bind: dn: %s\n", dn, 0, 0);
|
||||
|
||||
*edn = NULL;
|
||||
|
||||
/* get entry with reader lock */
|
||||
if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) {
|
||||
/* allow noauth binds */
|
||||
if ( method == LDAP_AUTH_SIMPLE && cred->bv_len == 0 ) {
|
||||
/*
|
||||
* bind successful, but return 1 so we don't
|
||||
* authorize based on noauth credentials
|
||||
*/
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
rc = 1;
|
||||
} else if ( be_isroot_pw( be, dn, cred ) ) {
|
||||
/* front end will send result */
|
||||
rc = 0;
|
||||
rc = 1;
|
||||
if ( method == LDAP_AUTH_SIMPLE ) {
|
||||
if( cred->bv_len == 0 ) {
|
||||
/* SUCCESS */
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS,
|
||||
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, 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, NULL );
|
||||
|
||||
} else {
|
||||
send_ldap_result( conn, op, LDAP_AUTH_METHOD_NOT_SUPPORTED,
|
||||
NULL, NULL, NULL );
|
||||
}
|
||||
|
||||
} else {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
|
||||
matched, NULL );
|
||||
rc = 1;
|
||||
matched, NULL, NULL );
|
||||
}
|
||||
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
return( rc );
|
||||
}
|
||||
|
||||
*edn = ch_strdup( e->e_dn );
|
||||
|
||||
/* check for deleted */
|
||||
|
||||
if ( ! access_allowed( be, conn, op, e,
|
||||
"entry", NULL, ACL_AUTH ) )
|
||||
{
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL, NULL, NULL );
|
||||
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 );
|
||||
return( 1 );
|
||||
} else if ( be_isroot_pw( be, dn, cred ) ) {
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS,
|
||||
NULL, NULL, NULL );
|
||||
|
||||
/* stop front end from sending result */
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* check for root dn/passwd */
|
||||
if ( be_isroot_pw( be, dn, cred ) ) {
|
||||
/* front end will send result */
|
||||
return( 0 );
|
||||
if(*edn != NULL) free( *edn );
|
||||
*edn = ch_strdup( be_root_dn( be ) );
|
||||
rc = 0;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( ! access_allowed( be, conn, op, e,
|
||||
"userpassword", NULL, ACL_AUTH ) )
|
||||
{
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL, NULL, NULL );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
|
||||
if ( be_isroot_pw( be, dn, cred ) ) {
|
||||
/* front end will send result */
|
||||
return( 0 );
|
||||
}
|
||||
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
|
||||
NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( 1 );
|
||||
NULL, NULL, NULL );
|
||||
|
||||
/* stop front end from sending result */
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( value_find( a->a_vals, cred, a->a_syntax, 0 ) != 0 ) {
|
||||
if ( be_isroot_pw( be, dn, cred ) ) {
|
||||
/* front end will send result */
|
||||
return( 0 );
|
||||
}
|
||||
if ( crypted_value_find( a->a_vals, cred, a->a_syntax, 0, cred ) != 0 )
|
||||
{
|
||||
send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
|
||||
NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( 1 );
|
||||
NULL, NULL, NULL );
|
||||
/* stop front end from sending result */
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
break;
|
||||
|
||||
#ifdef KERBEROS
|
||||
#ifdef HAVE_KERBEROS
|
||||
case LDAP_AUTH_KRBV41:
|
||||
if ( ! access_allowed( be, conn, op, e,
|
||||
"krbname", NULL, ACL_AUTH ) )
|
||||
{
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, 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 );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( 1 );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( ! access_allowed( be, conn, op, e,
|
||||
"krbname", NULL, ACL_AUTH ) )
|
||||
{
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
sprintf( krbname, "%s%s%s@%s", ad.pname, *ad.pinst ? "."
|
||||
: "", ad.pinst, ad.prealm );
|
||||
|
||||
|
||||
if ( (a = attr_find( e->e_attrs, "krbname" )) == NULL ) {
|
||||
/*
|
||||
* no krbName values present: check against DN
|
||||
*/
|
||||
if ( strcasecmp( dn, krbname ) == 0 ) {
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
|
||||
NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( 1 );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
|
||||
} else { /* look for krbName match */
|
||||
struct berval krbval;
|
||||
|
||||
krbval.bv_val = krbname;
|
||||
krbval.bv_len = strlen( krbname );
|
||||
|
||||
if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 )
|
||||
!= 0 ) {
|
||||
if ( value_find( a->a_vals, &krbval, a->a_syntax, 3 ) != 0 ) {
|
||||
send_ldap_result( conn, op,
|
||||
LDAP_INVALID_CREDENTIALS, NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( 1 );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
}
|
||||
rc = 0;
|
||||
break;
|
||||
|
||||
case LDAP_AUTH_KRBV42:
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( 1 );
|
||||
/* stop front end from sending result */
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
#endif
|
||||
|
||||
case LDAP_AUTH_SASL:
|
||||
/* insert SASL code here */
|
||||
|
||||
default:
|
||||
send_ldap_result( conn, op, LDAP_STRONG_AUTH_NOT_SUPPORTED,
|
||||
NULL, "auth method not supported" );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( 1 );
|
||||
NULL, "auth method not supported", NULL );
|
||||
rc = 1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return_results:;
|
||||
/* free entry and reader lock */
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
|
||||
/* success: front end will send result */
|
||||
return( 0 );
|
||||
/* front end with send result on success (rc==0) */
|
||||
return( rc );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
/* compare.c - ldbm backend compare routine */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
extern Entry *dn2entry();
|
||||
extern Attribute *attr_find();
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
int
|
||||
ldbm_back_compare(
|
||||
|
|
@ -23,33 +24,44 @@ ldbm_back_compare(
|
|||
char *matched;
|
||||
Entry *e;
|
||||
Attribute *a;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
|
||||
/* get entry with reader lock */
|
||||
if ( (e = dn2entry_r( be, dn, &matched )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
|
||||
matched, NULL, NULL );
|
||||
|
||||
if(matched == NULL) free(matched);
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if ( ! access_allowed( be, conn, op, e, ava->ava_type, &ava->ava_value,
|
||||
op->o_dn, ACL_COMPARE ) ) {
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( 1 );
|
||||
/* check for deleted */
|
||||
if ( ! access_allowed( be, conn, op, e,
|
||||
ava->ava_type, &ava->ava_value, ACL_COMPARE ) )
|
||||
{
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
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, "", "" );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( 1 );
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_ATTRIBUTE,
|
||||
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, "", "" );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( 0 );
|
||||
}
|
||||
if ( value_find( a->a_vals, &ava->ava_value, a->a_syntax, 1 ) == 0 )
|
||||
send_ldap_result( conn, op, LDAP_COMPARE_TRUE,
|
||||
NULL, NULL, NULL );
|
||||
else
|
||||
send_ldap_result( conn, op, LDAP_COMPARE_FALSE,
|
||||
NULL, NULL, NULL );
|
||||
|
||||
send_ldap_result( conn, op, LDAP_COMPARE_FALSE, "", "" );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( 0 );
|
||||
rc = 0;
|
||||
|
||||
return_results:;
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
return( rc );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
/* delete.c - ldbm backend delete routine */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
extern Entry *dn2entry();
|
||||
extern Attribute *attr_find();
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
int
|
||||
ldbm_back_delete(
|
||||
|
|
@ -19,49 +20,137 @@ ldbm_back_delete(
|
|||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char *matched = NULL;
|
||||
Entry *e;
|
||||
char *matched = NULL;
|
||||
char *pdn = NULL;
|
||||
Entry *e, *p = NULL;
|
||||
int rootlock = 0;
|
||||
int rc = -1;
|
||||
|
||||
if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
|
||||
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 ) {
|
||||
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, NULL, NULL );
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* check for deleted */
|
||||
|
||||
if ( has_children( be, e ) ) {
|
||||
send_ldap_result( conn, op, LDAP_NOT_ALLOWED_ON_NONLEAF, "",
|
||||
"" );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
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 );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( ! access_allowed( be, conn, op, e, "entry", NULL, op->o_dn,
|
||||
ACL_WRITE ) ) {
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
#ifdef SLAPD_CHILD_MODIFICATION_WITH_ENTRY_ACL
|
||||
if ( ! access_allowed( be, conn, op, e,
|
||||
"entry", NULL, ACL_WRITE ) )
|
||||
{
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"<=- ldbm_back_delete: insufficient access %s\n",
|
||||
dn, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* delete from parent's id2children entry */
|
||||
if( (pdn = dn_parent( be, e->e_ndn )) != NULL ) {
|
||||
if( (p = dn2entry_w( be, pdn, &matched )) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- ldbm_back_delete: parent does not exist\n",
|
||||
0, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* check parent for "children" acl */
|
||||
if ( ! access_allowed( be, conn, op, p,
|
||||
"children", NULL, ACL_WRITE ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- ldbm_back_delete: no access to parent\n", 0,
|
||||
0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* no parent, must be root to delete */
|
||||
if( ! be_isroot( be, op->o_ndn ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"<=- ldbm_back_delete: no parent & not root\n",
|
||||
0, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
|
||||
rootlock = 1;
|
||||
}
|
||||
|
||||
/* XXX delete from parent's id2children entry XXX */
|
||||
if ( id2children_remove( be, p, e ) != 0 ) {
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"<=- ldbm_back_delete: operations error %s\n",
|
||||
dn, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* delete from dn2id mapping */
|
||||
if ( dn2id_delete( be, e->e_dn ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
if ( dn2id_delete( be, e->e_ndn ) != 0 ) {
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"<=- ldbm_back_delete: operations error %s\n",
|
||||
dn, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* delete from disk and cache */
|
||||
if ( id2entry_delete( be, e ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
Debug(LDAP_DEBUG_ARGS,
|
||||
"<=- ldbm_back_delete: operations error %s\n",
|
||||
dn, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, "", "" );
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS,
|
||||
NULL, NULL, NULL );
|
||||
rc = 0;
|
||||
|
||||
return( 0 );
|
||||
return_results:;
|
||||
if ( pdn != NULL ) free(pdn);
|
||||
|
||||
if( p != NULL ) {
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
}
|
||||
|
||||
if ( rootlock ) {
|
||||
/* release root lock */
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
|
||||
}
|
||||
|
||||
/* free entry and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, e );
|
||||
|
||||
if ( matched != NULL ) free(matched);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,218 @@
|
|||
/* modify.c - ldbm backend modify routine */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
#include <ac/time.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
extern int global_schemacheck;
|
||||
extern Entry *dn2entry();
|
||||
extern Attribute *attr_find();
|
||||
static void add_lastmods(Operation *op, LDAPModList **ml);
|
||||
|
||||
|
||||
static void
|
||||
add_lastmods( Operation *op, LDAPModList **modlist )
|
||||
{
|
||||
char buf[22];
|
||||
struct berval bv;
|
||||
struct berval *bvals[2];
|
||||
LDAPModList **m;
|
||||
LDAPModList *tmp;
|
||||
struct tm *ltm;
|
||||
time_t currenttime;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
|
||||
|
||||
bvals[0] = &bv;
|
||||
bvals[1] = NULL;
|
||||
|
||||
/* remove any attempts by the user to modify these attrs */
|
||||
for ( m = modlist; *m != NULL; m = &(*m)->ml_next ) {
|
||||
if ( oc_check_no_usermod_attr( (*m)->ml_type ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"add_lastmods: found no user mod attr: %s\n",
|
||||
(*m)->ml_type, 0, 0 );
|
||||
tmp = *m;
|
||||
*m = (*m)->ml_next;
|
||||
free( tmp->ml_type );
|
||||
if ( tmp->ml_bvalues != NULL ) {
|
||||
ber_bvecfree( tmp->ml_bvalues );
|
||||
}
|
||||
free( tmp );
|
||||
if (!*m)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
|
||||
bv.bv_val = "NULLDN";
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
} else {
|
||||
bv.bv_val = op->o_dn;
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
}
|
||||
tmp = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
|
||||
tmp->ml_type = ch_strdup( "modifiersname" );
|
||||
tmp->ml_op = LDAP_MOD_REPLACE;
|
||||
tmp->ml_bvalues = (struct berval **) ch_calloc(2, sizeof(struct berval *));
|
||||
tmp->ml_bvalues[0] = ber_bvdup( &bv );
|
||||
tmp->ml_next = *modlist;
|
||||
*modlist = tmp;
|
||||
|
||||
currenttime = slap_get_time();
|
||||
ldap_pvt_thread_mutex_lock( &gmtime_mutex );
|
||||
#ifndef LDAP_LOCALTIME
|
||||
ltm = gmtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
|
||||
#else
|
||||
ltm = localtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
|
||||
#endif
|
||||
ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
|
||||
|
||||
bv.bv_val = buf;
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
tmp = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
|
||||
tmp->ml_type = ch_strdup( "modifytimestamp" );
|
||||
tmp->ml_op = LDAP_MOD_REPLACE;
|
||||
tmp->ml_bvalues = (struct berval **) ch_calloc(2, sizeof(struct berval *));
|
||||
tmp->ml_bvalues[0] = ber_bvdup( &bv );
|
||||
tmp->ml_next = *modlist;
|
||||
*modlist = tmp;
|
||||
|
||||
}
|
||||
|
||||
/* We need this function because of LDAP modrdn. If we do not
|
||||
* add this there would be a bunch of code replication here
|
||||
* and there and of course the likelihood of bugs increases.
|
||||
* Juan C. Gomez (gomez@engr.sgi.com) 05/18/99
|
||||
*/
|
||||
|
||||
int ldbm_modify_internal(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn,
|
||||
LDAPModList *modlist,
|
||||
Entry *e
|
||||
)
|
||||
{
|
||||
int err;
|
||||
LDAPMod *mod;
|
||||
LDAPModList *ml;
|
||||
Attribute *a;
|
||||
|
||||
if ( ((be->be_lastmod == ON)
|
||||
|| ((be->be_lastmod == UNDEFINED)&&(global_lastmod == ON)))
|
||||
&& (be->be_update_ndn == NULL)) {
|
||||
|
||||
/* XXX: It may be wrong, it changes mod time even if
|
||||
* mod fails!
|
||||
*/
|
||||
add_lastmods( op, &modlist );
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ( (err = acl_check_modlist( be, conn, op, e, modlist ))
|
||||
!= LDAP_SUCCESS ) {
|
||||
send_ldap_result( conn, op, err, NULL, NULL, NULL );
|
||||
return -1;
|
||||
}
|
||||
|
||||
for ( ml = modlist; ml != NULL; ml = ml->ml_next ) {
|
||||
|
||||
mod = &ml->ml_mod;
|
||||
|
||||
switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
|
||||
case LDAP_MOD_ADD:
|
||||
err = add_values( e, mod, op->o_ndn );
|
||||
break;
|
||||
|
||||
case LDAP_MOD_DELETE:
|
||||
err = delete_values( e, mod, op->o_ndn );
|
||||
break;
|
||||
|
||||
case LDAP_MOD_REPLACE:
|
||||
/* Need to remove all values from indexes before they
|
||||
* are lost.
|
||||
*/
|
||||
if( e->e_attrs
|
||||
&& ((a = attr_find( e->e_attrs, mod->mod_type ))
|
||||
!= NULL) ) {
|
||||
|
||||
(void) index_change_values( be,
|
||||
mod->mod_type,
|
||||
a->a_vals,
|
||||
e->e_id,
|
||||
__INDEX_DELETE_OP);
|
||||
}
|
||||
|
||||
err = replace_values( e, mod, op->o_ndn );
|
||||
break;
|
||||
|
||||
case LDAP_MOD_SOFTADD:
|
||||
/* Avoid problems in index_add_mods()
|
||||
* We need to add index if necessary.
|
||||
*/
|
||||
mod->mod_op = LDAP_MOD_ADD;
|
||||
if ( (err = add_values( e, mod, op->o_ndn ))
|
||||
== LDAP_TYPE_OR_VALUE_EXISTS ) {
|
||||
|
||||
err = LDAP_SUCCESS;
|
||||
mod->mod_op = LDAP_MOD_SOFTADD;
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ( err != LDAP_SUCCESS ) {
|
||||
/* unlock entry, delete from cache */
|
||||
send_ldap_result( conn, op, err, 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, NULL );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check for abandon */
|
||||
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
|
||||
if ( op->o_abandon ) {
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
return -1;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
/* modify indexes */
|
||||
if ( index_add_mods( be, modlist, e->e_id ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, NULL, NULL );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check for abandon */
|
||||
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
|
||||
if ( op->o_abandon ) {
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
return -1;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
return 0;
|
||||
|
||||
}/* int ldbm_modify_internal() */
|
||||
|
||||
static int add_values();
|
||||
static int delete_values();
|
||||
static int replace_values();
|
||||
|
||||
int
|
||||
ldbm_back_modify(
|
||||
|
|
@ -21,101 +220,48 @@ ldbm_back_modify(
|
|||
Connection *conn,
|
||||
Operation *op,
|
||||
char *dn,
|
||||
LDAPMod *mods
|
||||
LDAPModList *modlist
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char *matched = NULL;
|
||||
char *matched;
|
||||
Entry *e;
|
||||
int i, err, modtype;
|
||||
LDAPMod *mod;
|
||||
|
||||
if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched,
|
||||
NULL );
|
||||
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, NULL );
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
/* lock entry */
|
||||
|
||||
if ( (err = acl_check_mods( be, conn, op, e, mods )) != LDAP_SUCCESS ) {
|
||||
send_ldap_result( conn, op, err, NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
/* Modify the entry */
|
||||
if ( ldbm_modify_internal( be, conn, op, dn, modlist, e ) != 0 ) {
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
for ( mod = mods; mod != NULL; mod = mod->mod_next ) {
|
||||
switch ( mod->mod_op & ~LDAP_MOD_BVALUES ) {
|
||||
case LDAP_MOD_ADD:
|
||||
err = add_values( e, mod, op->o_dn );
|
||||
break;
|
||||
|
||||
case LDAP_MOD_DELETE:
|
||||
err = delete_values( e, mod, op->o_dn );
|
||||
break;
|
||||
|
||||
case LDAP_MOD_REPLACE:
|
||||
err = replace_values( e, mod, op->o_dn );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( err != LDAP_SUCCESS ) {
|
||||
/* unlock entry, delete from cache */
|
||||
send_ldap_result( conn, op, err, NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
}
|
||||
}
|
||||
|
||||
/* check for abandon */
|
||||
pthread_mutex_lock( &op->o_abandonmutex );
|
||||
if ( op->o_abandon ) {
|
||||
pthread_mutex_unlock( &op->o_abandonmutex );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
}
|
||||
pthread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
/* check that the entry still obeys the schema */
|
||||
if ( global_schemacheck && oc_schema_check( e ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OBJECT_CLASS_VIOLATION, NULL,
|
||||
NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* modify indexes */
|
||||
if ( index_add_mods( be, mods, e->e_id ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* check for abandon */
|
||||
pthread_mutex_lock( &op->o_abandonmutex );
|
||||
if ( op->o_abandon ) {
|
||||
pthread_mutex_unlock( &op->o_abandonmutex );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
}
|
||||
pthread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
/* change the entry itself */
|
||||
if ( id2entry_add( be, e ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, NULL, NULL );
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS,
|
||||
NULL, NULL, NULL );
|
||||
cache_return_entry_w( &li->li_cache, e );
|
||||
return( 0 );
|
||||
|
||||
error_return:;
|
||||
cache_return_entry_w( &li->li_cache, e );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
add_values(
|
||||
Entry *e,
|
||||
LDAPMod *mod,
|
||||
|
|
@ -143,7 +289,7 @@ add_values(
|
|||
return( LDAP_SUCCESS );
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
delete_values(
|
||||
Entry *e,
|
||||
LDAPMod *mod,
|
||||
|
|
@ -199,13 +345,18 @@ delete_values(
|
|||
return( LDAP_SUCCESS );
|
||||
}
|
||||
|
||||
static int
|
||||
int
|
||||
replace_values(
|
||||
Entry *e,
|
||||
LDAPMod *mod,
|
||||
char *dn
|
||||
)
|
||||
{
|
||||
|
||||
/* XXX: BEFORE YOU GET RID OF PREVIOUS VALUES REMOVE FROM INDEX
|
||||
* FILES
|
||||
*/
|
||||
|
||||
(void) attr_delete( &e->e_attrs, mod->mod_type );
|
||||
|
||||
if ( attr_merge( e, mod->mod_type, mod->mod_bvalues ) != 0 ) {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,31 @@
|
|||
/* modrdn.c - ldbm backend modrdn routine */
|
||||
|
||||
/*
|
||||
* LDAP v3 newSuperior support. Add new rdn as an attribute.
|
||||
* (Full support for v2 also used software/ideas contributed
|
||||
* by Roy Hooper rhooper@cyberus.ca, thanks to him for his
|
||||
* submission!.)
|
||||
*
|
||||
* Copyright 1999, Juan C. Gomez, All rights reserved.
|
||||
* This software is not subject to any license of Silicon Graphics
|
||||
* Inc. or Purdue University.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* without restriction or fee of any kind as long as this notice
|
||||
* is preserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
|
||||
extern Entry *dn2entry();
|
||||
extern char *dn_parent();
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
int
|
||||
ldbm_back_modrdn(
|
||||
|
|
@ -17,116 +34,422 @@ ldbm_back_modrdn(
|
|||
Operation *op,
|
||||
char *dn,
|
||||
char *newrdn,
|
||||
int deleteoldrdn
|
||||
int deleteoldrdn,
|
||||
char *newSuperior
|
||||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
char *matched;
|
||||
char *pdn, *newdn, *p;
|
||||
char sep[2];
|
||||
Entry *e, *e2;
|
||||
char *matched = NULL;
|
||||
char *p_dn = NULL, *p_ndn = NULL;
|
||||
char *new_dn = NULL, *new_ndn = NULL;
|
||||
Entry *e, *p = NULL;
|
||||
int rootlock = 0;
|
||||
int rc = -1;
|
||||
/* 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 */
|
||||
char *old_rdn; /* Old rdn's attr type & val */
|
||||
char *old_rdn_type = NULL; /* Type of old rdn attr. */
|
||||
char *old_rdn_val = NULL; /* Old rdn attribute value */
|
||||
/* Added to support newSuperior */
|
||||
Entry *np = NULL; /* newSuperior Entry */
|
||||
char *np_dn = NULL; /* newSuperior dn */
|
||||
char *np_ndn = NULL; /* newSuperior ndn */
|
||||
char *new_parent_dn = NULL; /* np_dn, p_dn, or NULL */
|
||||
/* Used to interface with ldbm_modify_internal() */
|
||||
struct berval add_bv; /* Stores new rdn att */
|
||||
struct berval *add_bvals[2]; /* Stores new rdn att */
|
||||
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 */
|
||||
|
||||
matched = NULL;
|
||||
if ( (e = dn2entry( be, dn, &matched )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT, matched, "" );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "==>ldbm_back_modrdn(newSuperior=%s)\n",
|
||||
(newSuperior ? newSuperior : "NULL"),
|
||||
0, 0 );
|
||||
|
||||
/* get entry with writer lock */
|
||||
if ( (e = dn2entry_w( be, dn, &matched )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_NO_SUCH_OBJECT,
|
||||
matched, NULL, NULL );
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
if ( (pdn = dn_parent( be, dn )) != NULL ) {
|
||||
/* parent + rdn + separator(s) + null */
|
||||
newdn = (char *) ch_malloc( strlen( pdn ) + strlen( newrdn )
|
||||
+ 3 );
|
||||
if ( dn_type( dn ) == DN_X500 ) {
|
||||
strcpy( newdn, newrdn );
|
||||
strcat( newdn, ", " );
|
||||
strcat( newdn, pdn );
|
||||
} else {
|
||||
strcpy( newdn, newrdn );
|
||||
p = strchr( newrdn, '\0' );
|
||||
p--;
|
||||
if ( *p != '.' && *p != '@' ) {
|
||||
if ( (p = strpbrk( dn, ".@" )) != NULL ) {
|
||||
sep[0] = *p;
|
||||
sep[1] = '\0';
|
||||
strcat( newdn, sep );
|
||||
}
|
||||
}
|
||||
strcat( newdn, pdn );
|
||||
}
|
||||
} else {
|
||||
newdn = strdup( newrdn );
|
||||
#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,
|
||||
"", "" );
|
||||
goto return_results;
|
||||
}
|
||||
(void) dn_normalize( newdn );
|
||||
#endif
|
||||
|
||||
if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) {
|
||||
|
||||
/* Make sure parent entry exist and we can write its
|
||||
* children.
|
||||
*/
|
||||
|
||||
if( (p = dn2entry_w( be, p_ndn, &matched )) == NULL) {
|
||||
Debug( LDAP_DEBUG_TRACE, "parent does not exist\n",
|
||||
0, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* check parent for "children" acl */
|
||||
if ( ! access_allowed( be, conn, op, p,
|
||||
"children", NULL, ACL_WRITE ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE, "no access to parent\n", 0,
|
||||
0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: wr to children of entry %s OK\n",
|
||||
p_ndn, 0, 0 );
|
||||
|
||||
p_dn = dn_parent( be, e->e_dn );
|
||||
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: parent dn=%s\n",
|
||||
p_dn, 0, 0 );
|
||||
|
||||
} else {
|
||||
/* no parent, modrdn entry directly under root */
|
||||
if( ! be_isroot( be, op->o_ndn ) ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "no parent & not root\n",
|
||||
0, 0, 0);
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock(&li->li_root_mutex);
|
||||
rootlock = 1;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: no parent, locked root\n",
|
||||
0, 0, 0 );
|
||||
|
||||
}/* if ( (p_ndn = dn_parent( be, e->e_ndn )) != NULL ) else */
|
||||
|
||||
new_parent_dn = p_dn; /* New Parent unless newSuperior given */
|
||||
|
||||
if ( (np_dn = newSuperior) != NULL) {
|
||||
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: new parent requested...\n",
|
||||
0, 0, 0 );
|
||||
|
||||
np_ndn = dn_normalize_case( ch_strdup( np_dn ) );
|
||||
|
||||
/* newSuperior == oldParent?, if so ==> ERROR */
|
||||
|
||||
/* newSuperior == entry being moved?, if so ==> ERROR */
|
||||
|
||||
/* 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,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: wr to new parent OK np=%p, id=%d\n",
|
||||
np, np->e_id, 0 );
|
||||
|
||||
/* check newSuperior for "children" acl */
|
||||
if ( !access_allowed( be, conn, op, np, "children", NULL,
|
||||
ACL_WRITE ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: no wr to newSup children\n",
|
||||
0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: wr to new parent's children OK\n",
|
||||
0, 0 , 0 );
|
||||
|
||||
|
||||
new_parent_dn = np_dn;
|
||||
|
||||
matched = NULL;
|
||||
if ( (e2 = dn2entry( be, newdn, &matched )) != NULL ) {
|
||||
free( newdn );
|
||||
free( pdn );
|
||||
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS, NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e2 );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
}
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
|
||||
/* Build target dn and make sure target entry doesn't exist already. */
|
||||
|
||||
build_new_dn( &new_dn, e->e_dn, new_parent_dn, newrdn );
|
||||
|
||||
|
||||
new_ndn = dn_normalize_case( ch_strdup(new_dn) );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: new ndn=%s\n",
|
||||
new_ndn, 0, 0 );
|
||||
|
||||
if (dn2id ( be, new_ndn ) != NOID) {
|
||||
send_ldap_result( conn, op, LDAP_ALREADY_EXISTS,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: new ndn=%s does not exist\n",
|
||||
new_ndn, 0, 0 );
|
||||
|
||||
/* check for abandon */
|
||||
pthread_mutex_lock( &op->o_abandonmutex );
|
||||
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
|
||||
if ( op->o_abandon ) {
|
||||
pthread_mutex_unlock( &op->o_abandonmutex );
|
||||
free( newdn );
|
||||
free( pdn );
|
||||
cache_return_entry( &li->li_cache, e2 );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
}
|
||||
pthread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
/* add new one */
|
||||
if ( dn2id_add( be, newdn, e->e_id ) != 0 ) {
|
||||
free( newdn );
|
||||
free( pdn );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
goto return_results;
|
||||
}
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
/* delete old one */
|
||||
if ( dn2id_delete( be, dn ) != 0 ) {
|
||||
free( newdn );
|
||||
free( pdn );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, NULL, NULL );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
return( -1 );
|
||||
if ( dn2id_delete( be, e->e_ndn ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
(void) cache_delete_entry( &li->li_cache, e );
|
||||
free( e->e_dn );
|
||||
e->e_dn = newdn;
|
||||
free( e->e_ndn );
|
||||
e->e_dn = new_dn;
|
||||
e->e_ndn = new_ndn;
|
||||
|
||||
/* XXX
|
||||
* At some point here we need to update the attribute values in
|
||||
* the entry itself that were effected by this RDN change
|
||||
* (respecting the value of the deleteoldrdn parameter).
|
||||
*
|
||||
* Since the code to do this has not yet been written, treat this
|
||||
* omission as a (documented) bug.
|
||||
/* add new one */
|
||||
if ( dn2id_add( be, e->e_ndn, e->e_id ) != 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
|
||||
/* Get attribute type and attribute value of our new rdn, we will
|
||||
* need to add that to our new entry
|
||||
*/
|
||||
|
||||
if ( (new_rdn_type = rdn_attr_type( newrdn )) == NULL ) {
|
||||
|
||||
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,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
|
||||
}
|
||||
|
||||
if ( (new_rdn_val = rdn_attr_value( newrdn )) == NULL ) {
|
||||
|
||||
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,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: new_rdn_val=\"%s\", new_rdn_type=\"%s\"\n",
|
||||
new_rdn_val, new_rdn_type, 0 );
|
||||
|
||||
/* Retrieve the old rdn from the entry's dn */
|
||||
|
||||
if ( (old_rdn = dn_rdn( be, dn )) == NULL ) {
|
||||
|
||||
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,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
|
||||
}
|
||||
|
||||
if ( (old_rdn_type = rdn_attr_type( old_rdn )) == NULL ) {
|
||||
|
||||
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,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
|
||||
}
|
||||
|
||||
if ( strcasecmp( old_rdn_type, new_rdn_type ) != 0 ) {
|
||||
|
||||
/* Not a big deal but we may say something */
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: old_rdn_type=%s, new_rdn_type=%s!\n",
|
||||
old_rdn_type, new_rdn_type, 0 );
|
||||
|
||||
}
|
||||
|
||||
if ( dn_type( old_rdn ) == DN_X500 ) {
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DN_X500\n",
|
||||
0, 0, 0 );
|
||||
|
||||
/* Add new attribute value to the entry.
|
||||
*/
|
||||
|
||||
add_bvals[0] = &add_bv; /* Array of bervals */
|
||||
add_bvals[1] = NULL;
|
||||
|
||||
add_bv.bv_val = new_rdn_val;
|
||||
add_bv.bv_len = strlen(new_rdn_val);
|
||||
|
||||
mod[0].ml_type = new_rdn_type;
|
||||
mod[0].ml_bvalues = add_bvals;
|
||||
mod[0].ml_op = LDAP_MOD_SOFTADD;
|
||||
mod[0].ml_next = NULL;
|
||||
|
||||
/* Remove old rdn value if required */
|
||||
|
||||
if (deleteoldrdn) {
|
||||
|
||||
/* Get value of old rdn */
|
||||
|
||||
if ((old_rdn_val = rdn_attr_value( old_rdn ))
|
||||
== NULL) {
|
||||
|
||||
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,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
|
||||
|
||||
}
|
||||
|
||||
del_bvals[0] = &del_bv; /* Array of bervals */
|
||||
del_bvals[1] = NULL;
|
||||
|
||||
/* Remove old value of rdn as an attribute. */
|
||||
|
||||
del_bv.bv_val = old_rdn_val;
|
||||
del_bv.bv_len = strlen(old_rdn_val);
|
||||
|
||||
/* No need to normalize old_rdn_type, delete_values()
|
||||
* does that for us
|
||||
*/
|
||||
mod[0].ml_next = &mod[1];
|
||||
mod[1].ml_type = old_rdn_type;
|
||||
mod[1].ml_bvalues = del_bvals;
|
||||
mod[1].ml_op = LDAP_MOD_DELETE;
|
||||
mod[1].ml_next = NULL;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: removing old_rdn_val=%s\n",
|
||||
old_rdn_val, 0, 0 );
|
||||
|
||||
}/* if (deleteoldrdn) */
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "ldbm_back_modrdn: DNS DN\n",
|
||||
0, 0, 0 );
|
||||
/* XXXV3: not sure of what to do here */
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"ldbm_back_modrdn: not fully implemented...\n",
|
||||
0, 0, 0 );
|
||||
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results;
|
||||
|
||||
}
|
||||
|
||||
/* modify memory copy of entry */
|
||||
if ( ldbm_modify_internal( be, conn, op, dn, &mod[0], e )
|
||||
!= 0 ) {
|
||||
|
||||
goto return_results;
|
||||
|
||||
}
|
||||
|
||||
(void) cache_update_entry( &li->li_cache, e );
|
||||
|
||||
/* NOTE: after this you must not free new_dn or new_ndn!
|
||||
* They are used by cache.
|
||||
*/
|
||||
|
||||
/* id2entry index */
|
||||
if ( id2entry_add( be, e ) != 0 ) {
|
||||
entry_free( e );
|
||||
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR, "", "" );
|
||||
return( -1 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, NULL, NULL );
|
||||
goto return_results_after;
|
||||
}
|
||||
free( pdn );
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
|
||||
return( 0 );
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, 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
|
||||
* the cache entry.
|
||||
*/
|
||||
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);
|
||||
if( old_rdn != NULL ) free(old_rdn);
|
||||
if( old_rdn_type != NULL ) free(old_rdn_type);
|
||||
if( old_rdn_val != NULL ) free(old_rdn_val);
|
||||
|
||||
|
||||
/* LDAP v3 Support */
|
||||
if ( np_dn != NULL ) free( np_dn );
|
||||
if ( np_ndn != NULL ) free( np_ndn );
|
||||
|
||||
if( p != NULL ) {
|
||||
/* free parent and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, p );
|
||||
}
|
||||
|
||||
if ( rootlock ) {
|
||||
/* release root writer lock */
|
||||
ldap_pvt_thread_mutex_unlock(&li->li_root_mutex);
|
||||
}
|
||||
|
||||
/* free entry and writer lock */
|
||||
cache_return_entry_w( &li->li_cache, e );
|
||||
return( rc );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,38 +1,19 @@
|
|||
/* search.c - ldbm backend search function */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
#include "back-ldbm.h"
|
||||
#include "proto-back-ldbm.h"
|
||||
|
||||
extern time_t currenttime;
|
||||
extern pthread_mutex_t currenttime_mutex;
|
||||
|
||||
extern ID dn2id();
|
||||
extern IDList *idl_alloc();
|
||||
extern Entry *id2entry();
|
||||
extern Entry *dn2entry();
|
||||
extern Attribute *attr_find();
|
||||
extern IDList *filter_candidates();
|
||||
extern char *ch_realloc();
|
||||
extern char *dn_parent();
|
||||
|
||||
static IDList *base_candidates();
|
||||
static IDList *onelevel_candidates();
|
||||
static IDList *subtree_candidates();
|
||||
|
||||
#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_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);
|
||||
|
||||
int
|
||||
ldbm_back_search(
|
||||
|
|
@ -53,125 +34,141 @@ ldbm_back_search(
|
|||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int err;
|
||||
time_t stoptime;
|
||||
IDList *candidates;
|
||||
ID_BLOCK *candidates;
|
||||
ID id;
|
||||
Entry *e;
|
||||
Attribute *ref;
|
||||
struct berval **refs;
|
||||
char *matched = NULL;
|
||||
int rmaxsize, nrefs;
|
||||
char *rbuf, *rcur, *r;
|
||||
int nentries = 0;
|
||||
char *realBase;
|
||||
|
||||
if ( tlimit == 0 && be_isroot( be, op->o_dn ) ) {
|
||||
Debug(LDAP_DEBUG_ARGS, "=> ldbm_back_search\n", 0, 0, 0);
|
||||
|
||||
if ( tlimit == 0 && be_isroot( be, op->o_ndn ) ) {
|
||||
tlimit = -1; /* allow root to set no limit */
|
||||
} else {
|
||||
tlimit = (tlimit > be->be_timelimit || tlimit < 1) ?
|
||||
be->be_timelimit : tlimit;
|
||||
stoptime = op->o_time + tlimit;
|
||||
}
|
||||
if ( slimit == 0 && be_isroot( be, op->o_dn ) ) {
|
||||
if ( slimit == 0 && be_isroot( be, op->o_ndn ) ) {
|
||||
slimit = -1; /* allow root to set no limit */
|
||||
} else {
|
||||
slimit = (slimit > be->be_sizelimit || slimit < 1) ?
|
||||
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, base, filter,
|
||||
candidates = base_candidates( be, conn, op, realBase, filter,
|
||||
attrs, attrsonly, &matched, &err );
|
||||
break;
|
||||
|
||||
case LDAP_SCOPE_ONELEVEL:
|
||||
candidates = onelevel_candidates( be, conn, op, base, filter,
|
||||
candidates = onelevel_candidates( be, conn, op, realBase, filter,
|
||||
attrs, attrsonly, &matched, &err );
|
||||
break;
|
||||
|
||||
case LDAP_SCOPE_SUBTREE:
|
||||
candidates = subtree_candidates( be, conn, op, base, filter,
|
||||
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" );
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
|
||||
"", "Bad search scope", NULL );
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* null candidates means we could not find the base object */
|
||||
if ( candidates == NULL ) {
|
||||
send_ldap_result( conn, op, err, matched, "" );
|
||||
send_ldap_result( conn, op, err,
|
||||
matched, NULL, NULL );
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
rmaxsize = 0;
|
||||
nrefs = 0;
|
||||
rbuf = rcur = NULL;
|
||||
MAKE_SPACE( sizeof("Referral:") + 1 );
|
||||
strcpy( rbuf, "Referral:" );
|
||||
rcur = strchr( rbuf, '\0' );
|
||||
if ( matched != NULL ) {
|
||||
free( matched );
|
||||
}
|
||||
|
||||
refs = NULL;
|
||||
|
||||
for ( id = idl_firstid( candidates ); id != NOID;
|
||||
id = idl_nextid( candidates, id ) ) {
|
||||
|
||||
/* check for abandon */
|
||||
pthread_mutex_lock( &op->o_abandonmutex );
|
||||
ldap_pvt_thread_mutex_lock( &op->o_abandonmutex );
|
||||
if ( op->o_abandon ) {
|
||||
pthread_mutex_unlock( &op->o_abandonmutex );
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
idl_free( candidates );
|
||||
free( rbuf );
|
||||
ber_bvecfree( refs );
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
pthread_mutex_unlock( &op->o_abandonmutex );
|
||||
ldap_pvt_thread_mutex_unlock( &op->o_abandonmutex );
|
||||
|
||||
/* check time limit */
|
||||
pthread_mutex_lock( ¤ttime_mutex );
|
||||
time( ¤ttime );
|
||||
if ( tlimit != -1 && currenttime > stoptime ) {
|
||||
pthread_mutex_unlock( ¤ttime_mutex );
|
||||
send_ldap_search_result( conn, op,
|
||||
LDAP_TIMELIMIT_EXCEEDED, NULL, nrefs > 0 ? rbuf :
|
||||
NULL, nentries );
|
||||
if ( tlimit != -1 && slap_get_time() > stoptime ) {
|
||||
send_search_result( conn, op, LDAP_TIMELIMIT_EXCEEDED,
|
||||
NULL, NULL, refs, nentries );
|
||||
idl_free( candidates );
|
||||
free( rbuf );
|
||||
ber_bvecfree( refs );
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
pthread_mutex_unlock( ¤ttime_mutex );
|
||||
|
||||
/* get the entry */
|
||||
if ( (e = id2entry( be, id )) == NULL ) {
|
||||
Debug( LDAP_DEBUG_ARGS, "candidate %d not found\n", id,
|
||||
0, 0 );
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 subtree searches, and don't check the filter
|
||||
* explicitly here since it's only a candidate anyway.
|
||||
*/
|
||||
if ( e->e_dn != NULL && strncasecmp( e->e_dn, "ref=", 4 )
|
||||
== 0 && (ref = attr_find( e->e_attrs, "ref" )) != NULL &&
|
||||
scope == LDAP_SCOPE_SUBTREE )
|
||||
if ( scope == LDAP_SCOPE_SUBTREE &&
|
||||
e->e_ndn != NULL &&
|
||||
strncmp( e->e_ndn, "REF=", 4 ) == 0 &&
|
||||
(ref = attr_find( e->e_attrs, "ref" )) != NULL )
|
||||
{
|
||||
int i, len;
|
||||
|
||||
if ( ref->a_vals == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY, "null ref in (%s)\n", 0,
|
||||
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, ref->a_vals, &refs );
|
||||
|
||||
/* otherwise it's an entry - see if it matches the filter */
|
||||
} else {
|
||||
|
|
@ -184,66 +181,102 @@ ldbm_back_search(
|
|||
scopeok = 1;
|
||||
if ( scope == LDAP_SCOPE_ONELEVEL ) {
|
||||
if ( (dn = dn_parent( be, e->e_dn )) != NULL ) {
|
||||
(void) dn_normalize( dn );
|
||||
scopeok = (dn == base) ? 1 : (! strcasecmp( dn, base ));
|
||||
(void) dn_normalize_case( dn );
|
||||
scopeok = (dn == realBase)
|
||||
? 1
|
||||
: (strcmp( dn, realBase ) ? 0 : 1 );
|
||||
free( dn );
|
||||
} else {
|
||||
scopeok = (base == NULL || *base == '\0');
|
||||
scopeok = (realBase == NULL || *realBase == '\0');
|
||||
}
|
||||
free( dn );
|
||||
} else if ( scope == LDAP_SCOPE_SUBTREE ) {
|
||||
dn = strdup( e->e_dn );
|
||||
(void) dn_normalize( dn );
|
||||
scopeok = dn_issuffix( dn, base );
|
||||
dn = ch_strdup( e->e_ndn );
|
||||
scopeok = dn_issuffix( dn, realBase );
|
||||
free( dn );
|
||||
}
|
||||
|
||||
if ( scopeok ) {
|
||||
/* check size limit */
|
||||
if ( --slimit == -1 ) {
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
send_ldap_search_result( conn, op,
|
||||
LDAP_SIZELIMIT_EXCEEDED, NULL,
|
||||
nrefs > 0 ? rbuf : NULL, nentries );
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
send_search_result( conn, op,
|
||||
LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
|
||||
refs, nentries );
|
||||
idl_free( candidates );
|
||||
free( rbuf );
|
||||
ber_bvecfree( refs );
|
||||
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
switch ( send_search_entry( be, conn, op, e,
|
||||
attrs, attrsonly ) ) {
|
||||
case 0: /* entry sent ok */
|
||||
nentries++;
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: /* entry not sent */
|
||||
break;
|
||||
case -1: /* connection closed */
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
idl_free( candidates );
|
||||
free( rbuf );
|
||||
return( 0 );
|
||||
}
|
||||
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 );
|
||||
ber_bvecfree( refs );
|
||||
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
if( e != NULL ) {
|
||||
/* free reader lock */
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
}
|
||||
|
||||
pthread_yield();
|
||||
ldap_pvt_thread_yield();
|
||||
}
|
||||
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 );
|
||||
|
||||
send_search_result( conn, op,
|
||||
refs == NULL ? LDAP_SUCCESS : LDAP_REFERRAL,
|
||||
NULL, NULL, refs, nentries );
|
||||
|
||||
ber_bvecfree( refs );
|
||||
|
||||
if( realBase != NULL) {
|
||||
free( realBase );
|
||||
}
|
||||
free( rbuf );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static IDList *
|
||||
static ID_BLOCK *
|
||||
base_candidates(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
|
|
@ -257,26 +290,32 @@ base_candidates(
|
|||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
int rc;
|
||||
ID id;
|
||||
IDList *idl;
|
||||
ID_BLOCK *idl;
|
||||
Entry *e;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "base_candidates: base: \"%s\"\n", base, 0, 0);
|
||||
|
||||
*err = LDAP_SUCCESS;
|
||||
if ( (e = dn2entry( be, base, matched )) == NULL ) {
|
||||
|
||||
/* get entry with reader lock */
|
||||
if ( (e = dn2entry_r( be, base, matched )) == NULL ) {
|
||||
*err = LDAP_NO_SUCH_OBJECT;
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
/* check for deleted */
|
||||
|
||||
idl = idl_alloc( 1 );
|
||||
idl_insert( &idl, e->e_id, 1 );
|
||||
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
|
||||
/* free reader lock */
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
|
||||
return( idl );
|
||||
}
|
||||
|
||||
static IDList *
|
||||
static ID_BLOCK *
|
||||
onelevel_candidates(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
|
|
@ -290,16 +329,19 @@ onelevel_candidates(
|
|||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Entry *e;
|
||||
Entry *e = NULL;
|
||||
Filter *f;
|
||||
char buf[20];
|
||||
IDList *candidates;
|
||||
ID_BLOCK *candidates;
|
||||
|
||||
Debug(LDAP_DEBUG_TRACE, "onelevel_candidates: base: \"%s\"\n", base, 0, 0);
|
||||
|
||||
*err = LDAP_SUCCESS;
|
||||
e = NULL;
|
||||
/* get the base object */
|
||||
if ( base != NULL && *base != '\0' && (e = dn2entry( be, base,
|
||||
matched )) == 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 );
|
||||
}
|
||||
|
|
@ -315,9 +357,9 @@ onelevel_candidates(
|
|||
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 = strdup( "id2children" );
|
||||
sprintf( buf, "%d", e != NULL ? e->e_id : 0 );
|
||||
f->f_and->f_ava.ava_value.bv_val = strdup( buf );
|
||||
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;
|
||||
|
||||
|
|
@ -329,10 +371,14 @@ onelevel_candidates(
|
|||
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 );
|
||||
}
|
||||
return( candidates );
|
||||
}
|
||||
|
||||
static IDList *
|
||||
static ID_BLOCK *
|
||||
subtree_candidates(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
|
|
@ -348,8 +394,11 @@ subtree_candidates(
|
|||
)
|
||||
{
|
||||
struct ldbminfo *li = (struct ldbminfo *) be->be_private;
|
||||
Filter *f;
|
||||
IDList *candidates;
|
||||
Filter *f, **filterarg_ptr;
|
||||
ID_BLOCK *candidates;
|
||||
|
||||
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).
|
||||
|
|
@ -365,21 +414,30 @@ subtree_candidates(
|
|||
*err = LDAP_SUCCESS;
|
||||
f = NULL;
|
||||
if ( lookupbase ) {
|
||||
if ( base != NULL && *base != '\0' && (e = dn2entry( be, base,
|
||||
matched )) == NULL ) {
|
||||
e = NULL;
|
||||
|
||||
if ( base != NULL && *base != '\0' &&
|
||||
(e = dn2entry_r( be, base, matched )) == NULL )
|
||||
{
|
||||
*err = LDAP_NO_SUCH_OBJECT;
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
if (e) {
|
||||
cache_return_entry_r( &li->li_cache, e );
|
||||
}
|
||||
|
||||
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 = strdup( "objectclass" );
|
||||
f->f_or->f_avvalue.bv_val = strdup( "referral" );
|
||||
f->f_or->f_avvalue.bv_len = strlen( "referral" );
|
||||
f->f_or->f_next = filter;
|
||||
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 ) ) {
|
||||
|
|
@ -388,10 +446,10 @@ subtree_candidates(
|
|||
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 = strdup( "dn" );
|
||||
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 = strdup( base );
|
||||
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;
|
||||
|
|
@ -402,13 +460,9 @@ subtree_candidates(
|
|||
|
||||
/* free up just the parts we allocated above */
|
||||
if ( f != NULL ) {
|
||||
f->f_and->f_next = NULL;
|
||||
*filterarg_ptr = NULL;
|
||||
filter_free( f );
|
||||
}
|
||||
|
||||
if ( e != NULL ) {
|
||||
cache_return_entry( &li->li_cache, e );
|
||||
}
|
||||
|
||||
return( candidates );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,30 +12,72 @@
|
|||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
extern Backend *select_backend();
|
||||
char *supportedSASLMechanisms[] = {
|
||||
"X-DIGEST-MD5",
|
||||
NULL
|
||||
};
|
||||
|
||||
extern char *default_referral;
|
||||
|
||||
void
|
||||
int
|
||||
do_bind(
|
||||
Connection *conn,
|
||||
Operation *op
|
||||
)
|
||||
{
|
||||
BerElement *ber = op->o_ber;
|
||||
int version, method, len, rc;
|
||||
char *dn;
|
||||
ber_int_t version;
|
||||
ber_tag_t method;
|
||||
char *mech;
|
||||
char *cdn, *ndn;
|
||||
ber_tag_t tag;
|
||||
int rc = LDAP_SUCCESS;
|
||||
struct berval cred;
|
||||
Backend *be;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
|
||||
|
||||
cdn = NULL;
|
||||
ndn = NULL;
|
||||
mech = NULL;
|
||||
cred.bv_val = NULL;
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
|
||||
|
||||
/* Force to connection to "anonymous" until bind succeeds.
|
||||
* This may need to be relocated or done on a case by case basis
|
||||
* to handle certain SASL mechanisms.
|
||||
*/
|
||||
|
||||
if ( conn->c_cdn != NULL ) {
|
||||
free( conn->c_cdn );
|
||||
conn->c_cdn = NULL;
|
||||
}
|
||||
|
||||
if ( conn->c_dn != NULL ) {
|
||||
free( conn->c_dn );
|
||||
conn->c_dn = NULL;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
|
||||
|
||||
if ( op->o_dn != NULL ) {
|
||||
free( op->o_dn );
|
||||
op->o_dn = ch_strdup( "" );
|
||||
}
|
||||
|
||||
if ( op->o_ndn != NULL ) {
|
||||
free( op->o_ndn );
|
||||
op->o_ndn = ch_strdup( "" );
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the bind request. It looks like this:
|
||||
*
|
||||
|
|
@ -45,90 +87,163 @@ do_bind(
|
|||
* authentication CHOICE {
|
||||
* simple [0] OCTET STRING -- passwd
|
||||
* krbv42ldap [1] OCTET STRING
|
||||
* krbv42dsa [1] OCTET STRING
|
||||
* krbv42dsa [2] OCTET STRING
|
||||
* SASL [3] SaslCredentials
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* SaslCredentials ::= SEQUENCE {
|
||||
* mechanism LDAPString,
|
||||
* credentials OCTET STRING OPTIONAL
|
||||
* }
|
||||
*/
|
||||
|
||||
#ifdef COMPAT30
|
||||
/*
|
||||
* in version 3.0 there is an extra SEQUENCE tag after the
|
||||
* BindRequest SEQUENCE tag.
|
||||
*/
|
||||
tag = ber_scanf( ber, "{iat" /*}*/, &version, &cdn, &method );
|
||||
|
||||
{
|
||||
BerElement tber;
|
||||
unsigned long tlen, ttag;
|
||||
if ( tag == LBER_ERROR ) {
|
||||
Debug( LDAP_DEBUG_ANY, "bind: ber_scanf failed\n", 0, 0, 0 );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
rc = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
op->o_protocol = version;
|
||||
|
||||
if( method != LDAP_AUTH_SASL ) {
|
||||
tag = ber_scanf( ber, /*{*/ "o}", &cred );
|
||||
|
||||
tber = *op->o_ber;
|
||||
ttag = ber_skip_tag( &tber, &tlen );
|
||||
if ( ber_peek_tag( &tber, &tlen ) == LBER_SEQUENCE ) {
|
||||
Debug( LDAP_DEBUG_ANY, "version 3.0 detected\n", 0, 0, 0 );
|
||||
conn->c_version = 30;
|
||||
rc = ber_scanf(ber, "{{iato}}", &version, &dn, &method, &cred);
|
||||
} else {
|
||||
rc = ber_scanf( ber, "{iato}", &version, &dn, &method, &cred );
|
||||
}
|
||||
}
|
||||
#else
|
||||
rc = ber_scanf( ber, "{iato}", &version, &dn, &method, &cred );
|
||||
#endif
|
||||
if ( rc == LBER_ERROR ) {
|
||||
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
|
||||
"decoding error" );
|
||||
return;
|
||||
}
|
||||
#ifdef COMPAT30
|
||||
if ( conn->c_version == 30 ) {
|
||||
switch ( method ) {
|
||||
case LDAP_AUTH_SIMPLE_30:
|
||||
method = LDAP_AUTH_SIMPLE;
|
||||
break;
|
||||
#ifdef KERBEROS
|
||||
case LDAP_AUTH_KRBV41_30:
|
||||
method = LDAP_AUTH_KRBV41;
|
||||
break;
|
||||
case LDAP_AUTH_KRBV42_30:
|
||||
method = LDAP_AUTH_KRBV42;
|
||||
break;
|
||||
#endif
|
||||
tag = ber_scanf( ber, "{a" /*}*/, &mech );
|
||||
|
||||
if ( tag != LBER_ERROR ) {
|
||||
ber_len_t len;
|
||||
tag = ber_peek_tag( ber, &len );
|
||||
|
||||
if ( tag == LDAP_TAG_LDAPCRED ) {
|
||||
tag = ber_scanf( ber, "o", &cred );
|
||||
}
|
||||
|
||||
if ( tag != LBER_ERROR ) {
|
||||
tag = ber_scanf( ber, /*{{*/ "}}" );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* compat30 */
|
||||
dn_normalize( dn );
|
||||
|
||||
if ( tag == LBER_ERROR ) {
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR,
|
||||
"decoding error" );
|
||||
rc = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_bind: get_ctrls failed\n", 0, 0, 0 );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if( method == LDAP_AUTH_SASL ) {
|
||||
Debug( LDAP_DEBUG_TRACE, "do_sasl_bind: dn (%s) mech %s\n",
|
||||
cdn, mech, NULL );
|
||||
} else {
|
||||
Debug( LDAP_DEBUG_TRACE, "do_bind: version %d dn (%s) method %d\n",
|
||||
version, cdn, method );
|
||||
}
|
||||
|
||||
ndn = dn_normalize_case( ch_strdup( cdn ) );
|
||||
|
||||
Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d BIND dn=\"%s\" method=%d\n",
|
||||
conn->c_connid, op->o_opid, dn, method, 0 );
|
||||
|
||||
if ( version != LDAP_VERSION2 ) {
|
||||
if ( dn != NULL ) {
|
||||
free( dn );
|
||||
}
|
||||
if ( cred.bv_val != NULL ) {
|
||||
free( cred.bv_val );
|
||||
}
|
||||
conn->c_connid, op->o_opid, ndn, method, 0 );
|
||||
|
||||
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, LDAP_PROTOCOL_ERROR, NULL,
|
||||
"version not supported" );
|
||||
return;
|
||||
send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
|
||||
NULL, "version not supported", NULL );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "do_bind: version %d dn (%s) method %d\n",
|
||||
version, dn, method );
|
||||
if ( method == LDAP_AUTH_SASL ) {
|
||||
if ( version < LDAP_VERSION3 ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_bind: sasl with LDAPv%d\n",
|
||||
version, 0, 0 );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "sasl bind requires LDAPv3" );
|
||||
rc = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if( mech == NULL || *mech == '\0' ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"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 );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if( !charray_inlist( supportedSASLMechanisms, mech ) ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"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 );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
|
||||
|
||||
if ( conn->c_authmech != NULL ) {
|
||||
assert( conn->c_bind_in_progress );
|
||||
|
||||
if((strcmp(conn->c_authmech, mech) != 0)) {
|
||||
/* mechanism changed, cancel in progress bind */
|
||||
conn->c_bind_in_progress = 0;
|
||||
if( conn->c_authstate != NULL ) {
|
||||
free(conn->c_authstate);
|
||||
conn->c_authstate = NULL;
|
||||
}
|
||||
free(conn->c_authmech);
|
||||
conn->c_authmech = NULL;
|
||||
}
|
||||
|
||||
#ifdef LDAP_DEBUG
|
||||
} else {
|
||||
assert( !conn->c_bind_in_progress );
|
||||
assert( conn->c_authmech == NULL );
|
||||
assert( conn->c_authstate == NULL );
|
||||
#endif
|
||||
}
|
||||
|
||||
} else {
|
||||
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
|
||||
|
||||
if ( conn->c_authmech != NULL ) {
|
||||
assert( conn->c_bind_in_progress );
|
||||
|
||||
/* cancel in progress bind */
|
||||
conn->c_bind_in_progress = 0;
|
||||
|
||||
if( conn->c_authstate != NULL ) {
|
||||
free(conn->c_authstate);
|
||||
conn->c_authstate = NULL;
|
||||
}
|
||||
free(conn->c_authmech);
|
||||
conn->c_authmech = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
conn->c_protocol = version;
|
||||
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
|
||||
|
||||
/* accept null binds */
|
||||
if ( dn == NULL || *dn == '\0' ) {
|
||||
if ( dn != NULL ) {
|
||||
free( dn );
|
||||
}
|
||||
if ( cred.bv_val != NULL ) {
|
||||
free( cred.bv_val );
|
||||
}
|
||||
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
return;
|
||||
if ( ndn == NULL || *ndn == '\0' ) {
|
||||
/*
|
||||
* we already forced connection to "anonymous", we just
|
||||
* need to send success
|
||||
*/
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL );
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -137,39 +252,73 @@ do_bind(
|
|||
* if we don't hold it.
|
||||
*/
|
||||
|
||||
if ( (be = select_backend( dn )) == NULL ) {
|
||||
free( dn );
|
||||
if ( cred.bv_val != NULL ) {
|
||||
free( cred.bv_val );
|
||||
}
|
||||
if ( (be = select_backend( ndn )) == NULL ) {
|
||||
if ( cred.bv_len == 0 ) {
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS, NULL, NULL );
|
||||
send_ldap_result( conn, op, LDAP_SUCCESS,
|
||||
NULL, NULL, NULL );
|
||||
|
||||
} else if ( default_referral ) {
|
||||
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
|
||||
NULL, NULL, default_referral );
|
||||
|
||||
} else {
|
||||
send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
|
||||
default_referral );
|
||||
send_ldap_result( conn, op, rc = LDAP_INVALID_CREDENTIALS,
|
||||
NULL, NULL, NULL );
|
||||
}
|
||||
return;
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ( be->be_bind != NULL ) {
|
||||
if ( (*be->be_bind)( be, conn, op, dn, method, &cred ) == 0 ) {
|
||||
pthread_mutex_lock( &conn->c_dnmutex );
|
||||
if ( conn->c_dn != NULL ) {
|
||||
free( conn->c_dn );
|
||||
if ( be->be_bind ) {
|
||||
/* 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 );
|
||||
|
||||
conn->c_cdn = cdn;
|
||||
cdn = NULL;
|
||||
|
||||
if(edn != NULL) {
|
||||
conn->c_dn = edn;
|
||||
} else {
|
||||
conn->c_dn = ndn;
|
||||
ndn = NULL;
|
||||
}
|
||||
conn->c_dn = strdup( dn );
|
||||
pthread_mutex_unlock( &conn->c_dnmutex );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "do_bind: bound \"%s\" to \"%s\"\n",
|
||||
conn->c_cdn, conn->c_dn, method );
|
||||
|
||||
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 );
|
||||
|
||||
} else if (edn != NULL) {
|
||||
free( edn );
|
||||
}
|
||||
|
||||
} else {
|
||||
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
|
||||
"Function not implemented" );
|
||||
send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
|
||||
NULL, "Function not implemented", NULL );
|
||||
}
|
||||
|
||||
free( dn );
|
||||
cleanup:
|
||||
if( cdn != NULL ) {
|
||||
free( cdn );
|
||||
}
|
||||
if( ndn != NULL ) {
|
||||
free( ndn );
|
||||
}
|
||||
if ( mech != NULL ) {
|
||||
free( mech );
|
||||
}
|
||||
if ( cred.bv_val != NULL ) {
|
||||
free( cred.bv_val );
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
/* charray.c - routines for dealing with char * arrays */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
void
|
||||
|
|
@ -26,7 +29,7 @@ charray_add(
|
|||
(n + 2) * sizeof(char *) );
|
||||
}
|
||||
|
||||
(*a)[n++] = s;
|
||||
(*a)[n++] = ch_strdup(s);
|
||||
(*a)[n] = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +51,7 @@ charray_merge(
|
|||
*a = (char **) ch_realloc( (char *) *a, (n + nn + 1) * sizeof(char *) );
|
||||
|
||||
for ( i = 0; i < nn; i++ ) {
|
||||
(*a)[n + i] = s[i];
|
||||
(*a)[n + i] = ch_strdup(s[i]);
|
||||
}
|
||||
(*a)[n + nn] = NULL;
|
||||
}
|
||||
|
|
@ -99,20 +102,53 @@ charray_dup( char **a )
|
|||
new = (char **) ch_malloc( (i + 1) * sizeof(char *) );
|
||||
|
||||
for ( i = 0; a[i] != NULL; i++ ) {
|
||||
new[i] = strdup( a[i] );
|
||||
new[i] = ch_strdup( a[i] );
|
||||
}
|
||||
new[i] = NULL;
|
||||
|
||||
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 )
|
||||
{
|
||||
char **res;
|
||||
char *s;
|
||||
char *lasts;
|
||||
int i;
|
||||
|
||||
/* protect the input string from strtok */
|
||||
str = ch_strdup( str );
|
||||
|
||||
i = 1;
|
||||
for ( s = str; *s; s++ ) {
|
||||
if ( strchr( brkstr, *s ) != NULL ) {
|
||||
|
|
@ -122,11 +158,16 @@ str2charray( char *str, char *brkstr )
|
|||
|
||||
res = (char **) ch_malloc( (i + 1) * sizeof(char *) );
|
||||
i = 0;
|
||||
for ( s = strtok( str, brkstr ); s != NULL; s = strtok( NULL,
|
||||
brkstr ) ) {
|
||||
res[i++] = strdup( s );
|
||||
|
||||
for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
|
||||
s != NULL;
|
||||
s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
|
||||
{
|
||||
res[i++] = ch_strdup( s );
|
||||
}
|
||||
|
||||
res[i] = NULL;
|
||||
|
||||
free( str );
|
||||
return( res );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,28 +10,35 @@
|
|||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
extern Backend *select_backend();
|
||||
|
||||
extern char *default_referral;
|
||||
|
||||
void
|
||||
int
|
||||
do_compare(
|
||||
Connection *conn,
|
||||
Operation *op
|
||||
)
|
||||
{
|
||||
char *dn;
|
||||
char *ndn;
|
||||
Ava ava;
|
||||
int rc;
|
||||
Backend *be;
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "do_compare\n", 0, 0, 0 );
|
||||
|
||||
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", NULL );
|
||||
return LDAP_SASL_BIND_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the compare request. It looks like this:
|
||||
*
|
||||
|
|
@ -44,42 +51,57 @@ do_compare(
|
|||
* }
|
||||
*/
|
||||
|
||||
if ( ber_scanf( op->o_ber, "{a{ao}}", &dn, &ava.ava_type,
|
||||
if ( ber_scanf( op->o_ber, "{a{ao}}", &ndn, &ava.ava_type,
|
||||
&ava.ava_value ) == LBER_ERROR ) {
|
||||
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
|
||||
return;
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( ( rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
|
||||
free( ndn );
|
||||
ava_free( &ava, 0 );
|
||||
Debug( LDAP_DEBUG_ANY, "do_compare: get_ctrls failed\n", 0, 0, 0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
value_normalize( ava.ava_value.bv_val, attr_syntax( ava.ava_type ) );
|
||||
dn_normalize( dn );
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n",
|
||||
dn, ava.ava_type, ava.ava_value.bv_val );
|
||||
ndn, ava.ava_type, ava.ava_value.bv_val );
|
||||
|
||||
ndn = dn_normalize_case( ndn );
|
||||
|
||||
Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d CMP dn=\"%s\" attr=\"%s\"\n",
|
||||
conn->c_connid, op->o_opid, dn, ava.ava_type, 0 );
|
||||
conn->c_connid, op->o_opid, ndn, ava.ava_type, 0 );
|
||||
|
||||
/*
|
||||
* We could be serving multiple database backends. Select the
|
||||
* appropriate one, or send a referral to our "referral server"
|
||||
* if we don't hold it.
|
||||
*/
|
||||
if ( (be = select_backend( dn )) == NULL ) {
|
||||
free( dn );
|
||||
if ( (be = select_backend( ndn )) == NULL ) {
|
||||
free( ndn );
|
||||
ava_free( &ava, 0 );
|
||||
|
||||
send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
|
||||
default_referral );
|
||||
return;
|
||||
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
|
||||
NULL, NULL, default_referral );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( be->be_compare != NULL ) {
|
||||
(*be->be_compare)( be, conn, op, dn, &ava );
|
||||
/* 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, LDAP_UNWILLING_TO_PERFORM, NULL,
|
||||
"Function not implemented" );
|
||||
send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
|
||||
NULL, "Function not implemented", NULL );
|
||||
}
|
||||
|
||||
free( dn );
|
||||
free( ndn );
|
||||
ava_free( &ava, 0 );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,21 @@
|
|||
/* config.c - configuration file handling routines */
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/ctype.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "ldap_defaults.h"
|
||||
#include "slap.h"
|
||||
#include "ldapconfig.h"
|
||||
|
||||
#define MAXARGS 100
|
||||
|
||||
extern Backend *new_backend();
|
||||
extern char *default_referral;
|
||||
extern int ldap_syslog;
|
||||
extern int global_schemacheck;
|
||||
|
||||
/*
|
||||
* defaults for various global variables
|
||||
*/
|
||||
|
|
@ -23,36 +25,57 @@ struct acl *global_acl = NULL;
|
|||
int global_default_access = ACL_READ;
|
||||
char *replogfile;
|
||||
int global_lastmod;
|
||||
int global_idletimeout = 0;
|
||||
char *global_realm = NULL;
|
||||
char *ldap_srvtab = "";
|
||||
|
||||
static char *fp_getline();
|
||||
static void fp_getline_init();
|
||||
static void fp_parse_line();
|
||||
char *slapd_pid_file = NULL;
|
||||
char *slapd_args_file = NULL;
|
||||
|
||||
static char *strtok_quote();
|
||||
static char *fp_getline(FILE *fp, int *lineno);
|
||||
static void fp_getline_init(int *lineno);
|
||||
static int fp_parse_line(char *line, int *argcp, char **argv);
|
||||
|
||||
void
|
||||
read_config( char *fname, Backend **bep, FILE *pfp )
|
||||
static char *strtok_quote(char *line, char *sep);
|
||||
|
||||
int
|
||||
read_config( char *fname )
|
||||
{
|
||||
FILE *fp;
|
||||
char *line, *savefname, *dn;
|
||||
char *line, *savefname, *saveline;
|
||||
int cargc, savelineno;
|
||||
char *cargv[MAXARGS];
|
||||
int lineno, i;
|
||||
Backend *be;
|
||||
|
||||
if ( (fp = pfp) == NULL && (fp = fopen( fname, "r" )) == NULL ) {
|
||||
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,
|
||||
"could not open config file \"%s\" - absolute path?\n",
|
||||
fname, 0, 0 );
|
||||
perror( fname );
|
||||
exit( 1 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0 );
|
||||
be = *bep;
|
||||
|
||||
if ( schema_init( ) != 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"error initializing the schema\n",
|
||||
0, 0, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
fp_getline_init( &lineno );
|
||||
|
||||
while ( (line = fp_getline( fp, &lineno )) != NULL ) {
|
||||
/* skip comments and blank lines */
|
||||
if ( line[0] == '#' || line[0] == '\0' ) {
|
||||
|
|
@ -61,7 +84,12 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
|
||||
Debug( LDAP_DEBUG_CONFIG, "line %d (%s)\n", lineno, line, 0 );
|
||||
|
||||
fp_parse_line( line, &cargc, cargv );
|
||||
/* fp_parse_line is destructive, we save a copy */
|
||||
saveline = ch_strdup( line );
|
||||
|
||||
if ( fp_parse_line( line, &cargc, cargv ) != 0 ) {
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if ( cargc < 1 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
|
|
@ -70,24 +98,87 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
continue;
|
||||
}
|
||||
|
||||
if ( strcasecmp( cargv[0], "backend" ) == 0 ) {
|
||||
if ( cargc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing type in \"backend <type>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if( be != NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: backend line must appear before any database definition\n",
|
||||
fname, lineno, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
bi = backend_info( cargv[1] );
|
||||
|
||||
/* start of a new database definition */
|
||||
if ( strcasecmp( cargv[0], "database" ) == 0 ) {
|
||||
} else if ( strcasecmp( cargv[0], "database" ) == 0 ) {
|
||||
if ( cargc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing type in \"database <type>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
*bep = new_backend( cargv[1] );
|
||||
be = *bep;
|
||||
bi = NULL;
|
||||
be = backend_db_init( cargv[1] );
|
||||
|
||||
/* set size limit */
|
||||
/* assign a default depth limit for alias deref */
|
||||
be->be_maxDerefDepth = SLAPD_DEFAULT_MAXDEREFDEPTH;
|
||||
|
||||
/* get pid file name */
|
||||
} else if ( strcasecmp( cargv[0], "pidfile" ) == 0 ) {
|
||||
if ( cargc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing file name in \"pidfile <file>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
slapd_pid_file = ch_strdup( cargv[1] );
|
||||
|
||||
/* get args file name */
|
||||
} else if ( strcasecmp( cargv[0], "argsfile" ) == 0 ) {
|
||||
if ( cargc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing file name in \"argsfile <file>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
slapd_args_file = ch_strdup( cargv[1] );
|
||||
|
||||
/* set DIGEST realm */
|
||||
} else if ( strcasecmp( cargv[0], "digest-realm" ) == 0 ) {
|
||||
if ( cargc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing realm in \"digest-realm <realm>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( be != NULL ) {
|
||||
be->be_realm = ch_strdup( cargv[1] );
|
||||
|
||||
} else if ( global_realm != NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: already set global realm!\n",
|
||||
fname, lineno, 0 );
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
global_realm = ch_strdup( cargv[1] );
|
||||
}
|
||||
|
||||
/* set time limit */
|
||||
} else if ( strcasecmp( cargv[0], "sizelimit" ) == 0 ) {
|
||||
if ( cargc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing limit in \"sizelimit <limit>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( be == NULL ) {
|
||||
defsize = atoi( cargv[1] );
|
||||
|
|
@ -101,7 +192,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing limit in \"timelimit <limit>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( be == NULL ) {
|
||||
deftime = atoi( cargv[1] );
|
||||
|
|
@ -115,7 +206,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing dn in \"suffix <dn>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
} else if ( cargc > 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: extra cruft after <dn> in \"suffix %s\" line (ignored)\n",
|
||||
|
|
@ -126,27 +217,92 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
"%s: line %d: suffix line must appear inside a database definition (ignored)\n",
|
||||
fname, lineno, 0 );
|
||||
} else {
|
||||
dn = strdup( cargv[1] );
|
||||
char *dn = ch_strdup( cargv[1] );
|
||||
(void) dn_normalize( dn );
|
||||
charray_add( &be->be_suffix, dn );
|
||||
(void) dn_upcase( dn );
|
||||
charray_add( &be->be_nsuffix, dn );
|
||||
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 ) {
|
||||
if ( cargc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing depth in \"maxDerefDepth <depth>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( be == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: depth line must appear inside a database definition (ignored)\n",
|
||||
fname, lineno, 0 );
|
||||
} else {
|
||||
be->be_maxDerefDepth = atoi (cargv[1]);
|
||||
}
|
||||
|
||||
|
||||
/* set magic "root" dn for this database */
|
||||
} else if ( strcasecmp( cargv[0], "rootdn" ) == 0 ) {
|
||||
if ( cargc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing dn in \"rootdn <dn>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( be == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: rootdn line must appear inside a database definition (ignored)\n",
|
||||
fname, lineno, 0 );
|
||||
} else {
|
||||
dn = strdup( cargv[1] );
|
||||
(void) dn_normalize( dn );
|
||||
be->be_rootdn = dn;
|
||||
be->be_root_dn = ch_strdup( cargv[1] );
|
||||
be->be_root_ndn = dn_normalize_case( ch_strdup( cargv[1] ) );
|
||||
}
|
||||
|
||||
/* set super-secret magic database password */
|
||||
|
|
@ -155,14 +311,14 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing passwd in \"rootpw <passwd>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( be == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: rootpw line must appear inside a database definition (ignored)\n",
|
||||
fname, lineno, 0 );
|
||||
} else {
|
||||
be->be_rootpw = strdup( cargv[1] );
|
||||
be->be_root_pw = ch_strdup( cargv[1] );
|
||||
}
|
||||
|
||||
/* make this database read-only */
|
||||
|
|
@ -171,7 +327,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing on|off in \"readonly <on|off>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( be == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
|
|
@ -191,21 +347,62 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing URL in \"referral <URL>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
default_referral = (char *) 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 ) {
|
||||
#ifdef HAVE_LOCALE_H
|
||||
char *locale;
|
||||
if ( cargc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing locale in \"locale <name | on | off>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
locale = (strcasecmp( cargv[1], "on" ) == 0 ? ""
|
||||
: strcasecmp( cargv[1], "off" ) == 0 ? "C"
|
||||
: ch_strdup( cargv[1] ) );
|
||||
|
||||
if ( setlocale( LC_CTYPE, locale ) == 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
(*locale
|
||||
? "%s: line %d: bad locale \"%s\"\n"
|
||||
: "%s: line %d: bad locale\n"),
|
||||
fname, lineno, locale );
|
||||
return( 1 );
|
||||
}
|
||||
#else
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: \"locale\" unsupported\n",
|
||||
fname, lineno, 0 );
|
||||
return( 1 );
|
||||
#endif
|
||||
/* specify an objectclass */
|
||||
} else if ( strcasecmp( cargv[0], "objectclass" ) == 0 ) {
|
||||
parse_oc( be, fname, lineno, cargc, cargv );
|
||||
if ( *cargv[1] == '(' ) {
|
||||
char * p;
|
||||
p = strchr(saveline,'(');
|
||||
parse_oc( fname, lineno, p );
|
||||
} else {
|
||||
parse_oc_old( be, fname, lineno, cargc, cargv );
|
||||
}
|
||||
|
||||
/* specify an attribute */
|
||||
} else if ( strcasecmp( cargv[0], "attribute" ) == 0 ) {
|
||||
attr_syntax_config( fname, lineno, cargc - 1,
|
||||
&cargv[1] );
|
||||
if ( *cargv[1] == '(' ) {
|
||||
char * p;
|
||||
p = strchr(saveline,'(');
|
||||
parse_at( fname, lineno, p );
|
||||
} else {
|
||||
attr_syntax_config( fname, lineno, cargc - 1,
|
||||
&cargv[1] );
|
||||
}
|
||||
|
||||
/* turn on/off schema checking */
|
||||
} else if ( strcasecmp( cargv[0], "schemacheck" ) == 0 ) {
|
||||
|
|
@ -213,12 +410,12 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing on|off in \"schemacheck <on|off>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( strcasecmp( cargv[1], "on" ) == 0 ) {
|
||||
global_schemacheck = 1;
|
||||
} else {
|
||||
if ( strcasecmp( cargv[1], "off" ) == 0 ) {
|
||||
global_schemacheck = 0;
|
||||
} else {
|
||||
global_schemacheck = 1;
|
||||
}
|
||||
|
||||
/* specify access control info */
|
||||
|
|
@ -231,23 +428,26 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing limit in \"defaultaccess <access>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( be == NULL ) {
|
||||
if ( (global_default_access =
|
||||
str2access( cargv[1] )) == -1 ) {
|
||||
if ( ACL_IS_INVALID(ACL_SET(global_default_access,
|
||||
str2access(cargv[1]))) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: bad access \"%s\" expecting [self]{none|compare|read|write}\n",
|
||||
fname, lineno, cargv[1] );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
} else {
|
||||
if ( (be->be_dfltaccess =
|
||||
str2access( cargv[1] )) == -1 ) {
|
||||
if ( ACL_IS_INVALID(ACL_SET(be->be_dfltaccess,
|
||||
str2access(cargv[1]))) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: bad access \"%s\" expecting [self]{none|compare|read|write}\n",
|
||||
"%s: line %d: bad access \"%s\", "
|
||||
"expecting [self]{none|compare|search|read|write}\n",
|
||||
fname, lineno, cargv[1] );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -257,7 +457,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing level in \"loglevel <level>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
ldap_syslog = atoi( cargv[1] );
|
||||
|
||||
|
|
@ -267,7 +467,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing host in \"replica <host[:port]>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( be == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
|
|
@ -278,7 +478,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
if ( strncasecmp( cargv[i], "host=", 5 )
|
||||
== 0 ) {
|
||||
charray_add( &be->be_replica,
|
||||
strdup( cargv[i] + 5 ) );
|
||||
cargv[i] + 5 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -295,15 +495,15 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing dn in \"updatedn <dn>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( be == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: updatedn line must appear inside a database definition (ignored)\n",
|
||||
fname, lineno, 0 );
|
||||
} else {
|
||||
be->be_updatedn = strdup( cargv[1] );
|
||||
(void) dn_normalize( be->be_updatedn );
|
||||
be->be_update_ndn = ch_strdup( cargv[1] );
|
||||
(void) dn_normalize_case( be->be_update_ndn );
|
||||
}
|
||||
|
||||
/* replication log file to which changes are appended */
|
||||
|
|
@ -312,12 +512,12 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing dn in \"replogfile <filename>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( be ) {
|
||||
be->be_replogfile = strdup( cargv[1] );
|
||||
be->be_replogfile = ch_strdup( cargv[1] );
|
||||
} else {
|
||||
replogfile = strdup( cargv[1] );
|
||||
replogfile = ch_strdup( cargv[1] );
|
||||
}
|
||||
|
||||
/* maintain lastmodified{by,time} attributes */
|
||||
|
|
@ -326,7 +526,7 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing on|off in \"lastmod <on|off>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
if ( strcasecmp( cargv[1], "on" ) == 0 ) {
|
||||
if ( be )
|
||||
|
|
@ -340,18 +540,42 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
global_lastmod = OFF;
|
||||
}
|
||||
|
||||
/* set idle timeout value */
|
||||
} else if ( strcasecmp( cargv[0], "idletimeout" ) == 0 ) {
|
||||
int i;
|
||||
if ( cargc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing timeout value in \"idletimeout <seconds>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
i = atoi( cargv[1] );
|
||||
|
||||
if( i < 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: timeout value (%d) invalid \"idletimeout <seconds>\" line\n",
|
||||
fname, lineno, i );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
global_idletimeout = i;
|
||||
|
||||
/* include another config file */
|
||||
} else if ( strcasecmp( cargv[0], "include" ) == 0 ) {
|
||||
if ( cargc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing filename in \"include <filename>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
savefname = strdup( cargv[1] );
|
||||
savefname = ch_strdup( cargv[1] );
|
||||
savelineno = lineno;
|
||||
read_config( savefname, bep, NULL );
|
||||
be = *bep;
|
||||
|
||||
if ( read_config( savefname ) != 0 ) {
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
free( savefname );
|
||||
lineno = savelineno - 1;
|
||||
|
||||
|
|
@ -361,30 +585,66 @@ read_config( char *fname, Backend **bep, FILE *pfp )
|
|||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing filename in \"srvtab <filename>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
ldap_srvtab = strdup( cargv[1] );
|
||||
ldap_srvtab = ch_strdup( cargv[1] );
|
||||
|
||||
/* pass anything else to the current backend config routine */
|
||||
#ifdef SLAPD_MODULES
|
||||
} else if (strcasecmp( cargv[0], "loadmodule") == 0 ) {
|
||||
if ( cargc < 2 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing filename in \"loadmodule <filename>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
exit( 1 );
|
||||
}
|
||||
if (!load_module(cargv[1], cargc - 2, (cargc > 2) ? cargv + 2 : NULL)) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: failed to load or initialize module %s\n",
|
||||
fname, lineno, cargv[1]);
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
#endif /*SLAPD_MODULES*/
|
||||
|
||||
/* pass anything else to the current backend info/db config routine */
|
||||
} else {
|
||||
if ( be == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: unknown directive \"%s\" outside database definition (ignored)\n",
|
||||
fname, lineno, cargv[0] );
|
||||
} else if ( be->be_config == NULL ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: unknown directive \"%s\" inside database definition (ignored)\n",
|
||||
fname, lineno, cargv[0] );
|
||||
if ( bi != NULL ) {
|
||||
if ( bi->bi_config == 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: unknown directive \"%s\" inside backend info definition (ignored)\n",
|
||||
fname, lineno, cargv[0] );
|
||||
} else {
|
||||
if ( (*bi->bi_config)( bi, fname, lineno, cargc, cargv )
|
||||
!= 0 )
|
||||
{
|
||||
return( 1 );
|
||||
}
|
||||
}
|
||||
} else if ( be != NULL ) {
|
||||
if ( be->be_config == 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: unknown directive \"%s\" inside backend database definition (ignored)\n",
|
||||
fname, lineno, cargv[0] );
|
||||
} else {
|
||||
if ( (*be->be_config)( be, fname, lineno, cargc, cargv )
|
||||
!= 0 )
|
||||
{
|
||||
return( 1 );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(*be->be_config)( be, fname, lineno, cargc,
|
||||
cargv );
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: unknown directive \"%s\" outside backend info and database definitions (ignored)\n",
|
||||
fname, lineno, cargv[0] );
|
||||
}
|
||||
}
|
||||
free( saveline );
|
||||
}
|
||||
fclose( fp );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
fp_parse_line(
|
||||
char *line,
|
||||
int *argcp,
|
||||
|
|
@ -399,11 +659,12 @@ fp_parse_line(
|
|||
if ( *argcp == MAXARGS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "Too many tokens (max %d)\n",
|
||||
MAXARGS, 0, 0 );
|
||||
exit( 1 );
|
||||
return( 1 );
|
||||
}
|
||||
argv[(*argcp)++] = token;
|
||||
}
|
||||
argv[*argcp] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
|
|
@ -434,11 +695,14 @@ strtok_quote( char *line, char *sep )
|
|||
} else {
|
||||
inquote = 1;
|
||||
}
|
||||
strcpy( next, next + 1 );
|
||||
SAFEMEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
strcpy( next, next + 1 );
|
||||
if ( next[1] )
|
||||
SAFEMEMCPY( next,
|
||||
next + 1, strlen( next + 1 ) + 1 );
|
||||
next++; /* dont parse the escaped character */
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -490,7 +754,7 @@ fp_getline( FILE *fp, int *lineno )
|
|||
if ( (p = strchr( buf, '\n' )) != NULL ) {
|
||||
*p = '\0';
|
||||
}
|
||||
if ( ! isspace( buf[0] ) ) {
|
||||
if ( ! isspace( (unsigned char) buf[0] ) ) {
|
||||
return( line );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,19 +10,18 @@
|
|||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "ldap_defaults.h"
|
||||
#include "slap.h"
|
||||
#include "ldapconfig.h"
|
||||
|
||||
#if defined( SLAPD_CONFIG_DN )
|
||||
|
||||
extern int nbackends;
|
||||
extern Backend *backends;
|
||||
extern char *default_referral;
|
||||
|
||||
/*
|
||||
* no mutex protection in here - take our chances!
|
||||
*/
|
||||
|
|
@ -40,8 +39,11 @@ config_info( Connection *conn, Operation *op )
|
|||
vals[1] = NULL;
|
||||
|
||||
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
|
||||
|
||||
e->e_attrs = NULL;
|
||||
e->e_dn = strdup( SLAPD_CONFIG_DN );
|
||||
e->e_dn = ch_strdup( SLAPD_CONFIG_DN );
|
||||
e->e_ndn = dn_normalize_case( ch_strdup( SLAPD_CONFIG_DN ));
|
||||
e->e_private = NULL;
|
||||
|
||||
for ( i = 0; i < nbackends; i++ ) {
|
||||
strcpy( buf, backends[i].be_type );
|
||||
|
|
@ -54,15 +56,8 @@ config_info( Connection *conn, Operation *op )
|
|||
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 );
|
||||
send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
|
||||
send_search_entry( &backends[0], conn, op, e, NULL, 0, 1 );
|
||||
send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, 1 );
|
||||
|
||||
entry_free( e );
|
||||
}
|
||||
|
|
|
|||
163
servers/slapd/controls.c
Normal file
163
servers/slapd/controls.c
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright 1999 The OpenLDAP Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted only
|
||||
* as authorized by the OpenLDAP Public License. A copy of this
|
||||
* license is available at http://www.OpenLDAP.org/license.html or
|
||||
* in file LICENSE in the top-level directory of the distribution.
|
||||
*/
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
#include "../../libraries/liblber/lber-int.h"
|
||||
|
||||
char *supportedControls[] = {
|
||||
LDAP_CONTROL_MANAGEDSAIT,
|
||||
NULL
|
||||
};
|
||||
|
||||
int get_ctrls(
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
int sendres )
|
||||
{
|
||||
int nctrls;
|
||||
ber_tag_t tag;
|
||||
ber_len_t len;
|
||||
char *opaque;
|
||||
BerElement *ber = op->o_ber;
|
||||
LDAPControl ***ctrls = &op->o_ctrls;
|
||||
int rc = LDAP_SUCCESS;
|
||||
char *errmsg = NULL;
|
||||
|
||||
len = ber_pvt_ber_remaining(ber);
|
||||
|
||||
if( len == 0) {
|
||||
/* no controls */
|
||||
rc = LDAP_SUCCESS;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
|
||||
if( tag == LBER_ERROR ) {
|
||||
rc = -1;
|
||||
errmsg = "unexpected data in PDU";
|
||||
}
|
||||
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if( op->o_protocol < LDAP_VERSION3 ) {
|
||||
rc = -1;
|
||||
errmsg = "controls require LDAPv3";
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
/* set through each element */
|
||||
nctrls = 0;
|
||||
*ctrls = ch_malloc( 1 * sizeof(LDAPControl *) );
|
||||
|
||||
#if 0
|
||||
if( *ctrls == NULL ) {
|
||||
rc = LDAP_NO_MEMORY;
|
||||
errmsg = "no memory";
|
||||
goto return_results;
|
||||
}
|
||||
#endif
|
||||
|
||||
ctrls[nctrls] = NULL;
|
||||
|
||||
for( tag = ber_first_element( ber, &len, &opaque );
|
||||
tag != LBER_ERROR;
|
||||
tag = ber_next_element( ber, &len, opaque ) )
|
||||
{
|
||||
LDAPControl *tctrl;
|
||||
LDAPControl **tctrls;
|
||||
|
||||
tctrl = ch_calloc( 1, sizeof(LDAPControl) );
|
||||
|
||||
/* allocate pointer space for current controls (nctrls)
|
||||
* + this control + extra NULL
|
||||
*/
|
||||
tctrls = (tctrl == NULL) ? NULL :
|
||||
ch_realloc(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
|
||||
|
||||
#if 0
|
||||
if( tctrls == NULL ) {
|
||||
/* one of the above allocation failed */
|
||||
|
||||
if( tctrl != NULL ) {
|
||||
ch_free( tctrl );
|
||||
}
|
||||
|
||||
ldap_controls_free(*ctrls);
|
||||
*ctrls = NULL;
|
||||
|
||||
rc = LDAP_NO_MEMORY;
|
||||
errmsg = "no memory";
|
||||
goto return_results;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
tctrls[nctrls++] = tctrl;
|
||||
tctrls[nctrls] = NULL;
|
||||
|
||||
tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
|
||||
|
||||
if( tag != LBER_ERROR ) {
|
||||
tag = ber_peek_tag( ber, &len );
|
||||
}
|
||||
|
||||
if( tag == LBER_BOOLEAN ) {
|
||||
ber_int_t crit;
|
||||
tag = ber_scanf( ber, "b", &crit );
|
||||
tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
|
||||
}
|
||||
|
||||
if( tag != LBER_ERROR ) {
|
||||
tag = ber_peek_tag( ber, &len );
|
||||
}
|
||||
|
||||
if( tag == LBER_OCTETSTRING ) {
|
||||
tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
|
||||
|
||||
} else {
|
||||
tctrl->ldctl_value.bv_val = NULL;
|
||||
}
|
||||
|
||||
if( tag == LBER_ERROR ) {
|
||||
*ctrls = NULL;
|
||||
ldap_controls_free( tctrls );
|
||||
rc = -1;
|
||||
errmsg = "decoding controls error";
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if( tctrl->ldctl_iscritical &&
|
||||
!charray_inlist( supportedControls, tctrl->ldctl_oid ) )
|
||||
{
|
||||
rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
|
||||
errmsg = "critical extension is unavailable ";
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
*ctrls = tctrls;
|
||||
}
|
||||
|
||||
return_results:
|
||||
if( sendres && rc != LDAP_SUCCESS ) {
|
||||
if( rc == -1 ) {
|
||||
send_ldap_disconnect( conn, op, rc, errmsg );
|
||||
} else {
|
||||
send_ldap_result( conn, op, rc, NULL, errmsg, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -10,80 +10,98 @@
|
|||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
extern Backend *select_backend();
|
||||
|
||||
extern char *default_referral;
|
||||
|
||||
void
|
||||
int
|
||||
do_delete(
|
||||
Connection *conn,
|
||||
Operation *op
|
||||
)
|
||||
{
|
||||
char *dn, *odn;
|
||||
char *ndn;
|
||||
Backend *be;
|
||||
int rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "do_delete\n", 0, 0, 0 );
|
||||
|
||||
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", NULL );
|
||||
return LDAP_SASL_BIND_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the delete request. It looks like this:
|
||||
*
|
||||
* DelRequest := DistinguishedName
|
||||
*/
|
||||
|
||||
if ( ber_scanf( op->o_ber, "a", &dn ) == LBER_ERROR ) {
|
||||
if ( ber_scanf( op->o_ber, "a", &ndn ) == LBER_ERROR ) {
|
||||
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
|
||||
return;
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
return -1;
|
||||
}
|
||||
odn = strdup( dn );
|
||||
dn_normalize( dn );
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "do_delete: dn (%s)\n", dn, 0, 0 );
|
||||
if( ( rc = get_ctrls( conn, op, 1 ) ) != LDAP_SUCCESS ) {
|
||||
free( ndn );
|
||||
Debug( LDAP_DEBUG_ANY, "do_add: get_ctrls failed\n", 0, 0, 0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_STATS, "DEL dn=\"%s\"\n", dn, 0, 0 );
|
||||
Debug( LDAP_DEBUG_ARGS, "do_delete: dn (%s)\n", ndn, 0, 0 );
|
||||
|
||||
dn_normalize_case( ndn );
|
||||
|
||||
Debug( LDAP_DEBUG_STATS, "DEL dn=\"%s\"\n", ndn, 0, 0 );
|
||||
|
||||
/*
|
||||
* We could be serving multiple database backends. Select the
|
||||
* appropriate one, or send a referral to our "referral server"
|
||||
* if we don't hold it.
|
||||
*/
|
||||
if ( (be = select_backend( dn )) == NULL ) {
|
||||
free( dn );
|
||||
free( odn );
|
||||
send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
|
||||
default_referral );
|
||||
return;
|
||||
if ( (be = select_backend( ndn )) == NULL ) {
|
||||
free( ndn );
|
||||
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
|
||||
NULL, NULL, default_referral );
|
||||
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;
|
||||
* 2) this backend is master for what it holds;
|
||||
* 3) it's a replica and the dn supplied is the updatedn.
|
||||
* 3) it's a replica and the dn supplied is the update_ndn.
|
||||
*/
|
||||
if ( be->be_delete != NULL ) {
|
||||
if ( be->be_delete ) {
|
||||
/* do the update here */
|
||||
if ( be->be_updatedn == NULL || strcasecmp( be->be_updatedn,
|
||||
op->o_dn ) == 0 ) {
|
||||
if ( (*be->be_delete)( be, conn, op, dn ) == 0 ) {
|
||||
replog( be, LDAP_REQ_DELETE, odn, NULL, 0 );
|
||||
if ( be->be_update_ndn == NULL ||
|
||||
strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
|
||||
{
|
||||
if ( (*be->be_delete)( be, conn, op, ndn ) == 0 ) {
|
||||
replog( be, LDAP_REQ_DELETE, ndn, NULL, 0 );
|
||||
}
|
||||
} else {
|
||||
send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
|
||||
default_referral );
|
||||
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
|
||||
NULL, NULL, default_referral );
|
||||
}
|
||||
} else {
|
||||
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
|
||||
"Function not implemented" );
|
||||
send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
|
||||
NULL, "Function not implemented", NULL );
|
||||
}
|
||||
|
||||
free( dn );
|
||||
free( odn );
|
||||
free( ndn );
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
112
servers/slapd/extended.c
Normal file
112
servers/slapd/extended.c
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright 1999 The OpenLDAP Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted only
|
||||
* as authorized by the OpenLDAP Public License. A copy of this
|
||||
* license is available at http://www.OpenLDAP.org/license.html or
|
||||
* in file LICENSE in the top-level directory of the distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* LDAPv3 Extended Operation Request
|
||||
* ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
|
||||
* requestName [0] LDAPOID,
|
||||
* requestValue [1] OCTET STRING OPTIONAL
|
||||
* }
|
||||
*
|
||||
* LDAPv3 Extended Operation Response
|
||||
* ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
|
||||
* COMPONENTS OF LDAPResult,
|
||||
* responseName [10] LDAPOID OPTIONAL,
|
||||
* response [11] OCTET STRING OPTIONAL
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
char *supportedExtensions[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
do_extended(
|
||||
Connection *conn,
|
||||
Operation *op
|
||||
)
|
||||
{
|
||||
int rc = LDAP_SUCCESS;
|
||||
char* reqoid ;
|
||||
struct berval reqdata;
|
||||
ber_tag_t tag;
|
||||
ber_len_t len;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "do_extended\n", 0, 0, 0 );
|
||||
|
||||
reqoid = NULL;
|
||||
reqdata.bv_val = NULL;
|
||||
|
||||
if( op->o_protocol < LDAP_VERSION3 ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_extended: protocol version (%d) too low\n",
|
||||
op->o_protocol, 0 ,0 );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "requires LDAPv3" );
|
||||
rc = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( ber_scanf( op->o_ber, "a", &reqoid ) == LBER_ERROR ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_extended: ber_scanf failed\n", 0, 0 ,0 );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
rc = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
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 extended operation", NULL );
|
||||
goto done;
|
||||
}
|
||||
|
||||
tag = ber_peek_tag( op->o_ber, &len );
|
||||
|
||||
if( ber_peek_tag( op->o_ber, &len ) == LDAP_TAG_EXOP_REQ_VALUE ) {
|
||||
if( ber_scanf( op->o_ber, "o", &reqdata ) != LBER_ERROR ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_extended: ber_scanf failed\n", 0, 0 ,0 );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
rc = -1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_extended: get_ctrls failed\n", 0, 0 ,0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
done:
|
||||
if ( reqoid != NULL ) {
|
||||
free( reqoid );
|
||||
}
|
||||
if ( reqdata.bv_val != NULL ) {
|
||||
free( reqdata.bv_val );
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1,37 +1,173 @@
|
|||
/* init.c - initialize various things */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/time.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
extern pthread_mutex_t active_threads_mutex;
|
||||
extern pthread_mutex_t new_conn_mutex;
|
||||
extern pthread_mutex_t currenttime_mutex;
|
||||
extern pthread_mutex_t entry2str_mutex;
|
||||
extern pthread_mutex_t replog_mutex;
|
||||
extern pthread_mutex_t ops_mutex;
|
||||
extern pthread_mutex_t num_sent_mutex;
|
||||
#ifndef sunos5
|
||||
extern pthread_mutex_t regex_mutex;
|
||||
/*
|
||||
* read-only global variables or variables only written by the listener
|
||||
* thread (after they are initialized) - no need to protect them with a mutex.
|
||||
*/
|
||||
int slap_debug = 0;
|
||||
|
||||
#ifdef LDAP_DEBUG
|
||||
int ldap_syslog = LDAP_DEBUG_STATS;
|
||||
#else
|
||||
int ldap_syslog;
|
||||
#endif
|
||||
|
||||
init()
|
||||
{
|
||||
pthread_mutex_init( &active_threads_mutex, pthread_mutexattr_default );
|
||||
pthread_mutex_init( &new_conn_mutex, pthread_mutexattr_default );
|
||||
pthread_mutex_init( ¤ttime_mutex, pthread_mutexattr_default );
|
||||
pthread_mutex_init( &entry2str_mutex, pthread_mutexattr_default );
|
||||
pthread_mutex_init( &replog_mutex, pthread_mutexattr_default );
|
||||
pthread_mutex_init( &ops_mutex, pthread_mutexattr_default );
|
||||
pthread_mutex_init( &num_sent_mutex, pthread_mutexattr_default );
|
||||
#ifndef sunos5
|
||||
pthread_mutex_init( ®ex_mutex, pthread_mutexattr_default );
|
||||
int ldap_syslog_level = LOG_DEBUG;
|
||||
struct berval **default_referral = NULL;
|
||||
int g_argc;
|
||||
char **g_argv;
|
||||
|
||||
/*
|
||||
* global variables that need mutex protection
|
||||
*/
|
||||
int active_threads;
|
||||
ldap_pvt_thread_mutex_t active_threads_mutex;
|
||||
ldap_pvt_thread_cond_t active_threads_cond;
|
||||
|
||||
ldap_pvt_thread_mutex_t gmtime_mutex;
|
||||
#ifdef SLAPD_CRYPT
|
||||
ldap_pvt_thread_mutex_t crypt_mutex;
|
||||
#endif
|
||||
|
||||
int num_conns;
|
||||
long num_ops_initiated;
|
||||
long num_ops_completed;
|
||||
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()
|
||||
* routine since it returns a pointer to static data.
|
||||
*/
|
||||
ldap_pvt_thread_mutex_t entry2str_mutex;
|
||||
ldap_pvt_thread_mutex_t replog_mutex;
|
||||
|
||||
static char* slap_name;
|
||||
int slapMode = SLAP_UNDEFINED_MODE;
|
||||
|
||||
static ldap_pvt_thread_mutex_t currenttime_mutex;
|
||||
|
||||
int
|
||||
slap_init( int mode, char *name )
|
||||
{
|
||||
int rc;
|
||||
|
||||
if( slapMode != SLAP_UNDEFINED_MODE ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s init: init called twice (old=%d, new=%d)\n",
|
||||
name, slapMode, mode );
|
||||
return 1;
|
||||
}
|
||||
|
||||
slapMode = mode;
|
||||
|
||||
switch ( slapMode ) {
|
||||
|
||||
case SLAP_SERVER_MODE:
|
||||
case SLAP_TOOL_MODE:
|
||||
#ifdef SLAPD_BDB2
|
||||
case SLAP_TIMEDSERVER_MODE:
|
||||
case SLAP_TOOLID_MODE:
|
||||
#endif
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"%s init: initiated %s.\n",
|
||||
name, mode == SLAP_TOOL_MODE ? "tool" : "server", 0 );
|
||||
|
||||
slap_name = name;
|
||||
|
||||
(void) ldap_pvt_thread_initialize();
|
||||
|
||||
ldap_pvt_thread_mutex_init( &active_threads_mutex );
|
||||
ldap_pvt_thread_cond_init( &active_threads_cond );
|
||||
|
||||
ldap_pvt_thread_mutex_init( ¤ttime_mutex );
|
||||
ldap_pvt_thread_mutex_init( &entry2str_mutex );
|
||||
ldap_pvt_thread_mutex_init( &replog_mutex );
|
||||
ldap_pvt_thread_mutex_init( &num_ops_mutex );
|
||||
ldap_pvt_thread_mutex_init( &num_sent_mutex );
|
||||
|
||||
ldap_pvt_thread_mutex_init( &gmtime_mutex );
|
||||
#ifdef SLAPD_CRYPT
|
||||
ldap_pvt_thread_mutex_init( &crypt_mutex );
|
||||
#endif
|
||||
|
||||
rc = backend_init();
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s init: undefined mode (%d).\n", name, mode, 0 );
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int slap_startup(int dbnum)
|
||||
{
|
||||
int rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"%s startup: initiated.\n",
|
||||
slap_name, 0, 0 );
|
||||
|
||||
rc = backend_startup(dbnum);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int slap_shutdown(int dbnum)
|
||||
{
|
||||
int rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"%s shutdown: initiated\n",
|
||||
slap_name, 0, 0 );
|
||||
|
||||
/* let backends do whatever cleanup they need to do */
|
||||
rc = backend_shutdown(dbnum);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int slap_destroy(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"%s shutdown: freeing system resources.\n",
|
||||
slap_name, 0, 0 );
|
||||
|
||||
rc = backend_destroy();
|
||||
|
||||
ldap_pvt_thread_destroy();
|
||||
|
||||
/* should destory the above mutex */
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* should create a utils.c for these */
|
||||
time_t slap_get_time(void)
|
||||
{
|
||||
time_t t;
|
||||
ldap_pvt_thread_mutex_lock( ¤ttime_mutex );
|
||||
time( &t );
|
||||
ldap_pvt_thread_mutex_unlock( ¤ttime_mutex );
|
||||
return t;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,39 +10,46 @@
|
|||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/time.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
extern Backend *select_backend();
|
||||
static void modlist_free(LDAPModList *ml);
|
||||
|
||||
extern char *default_referral;
|
||||
extern time_t currenttime;
|
||||
extern pthread_mutex_t currenttime_mutex;
|
||||
extern int global_lastmod;
|
||||
|
||||
static void modlist_free();
|
||||
static void add_lastmods();
|
||||
|
||||
void
|
||||
int
|
||||
do_modify(
|
||||
Connection *conn,
|
||||
Operation *op
|
||||
)
|
||||
{
|
||||
char *dn, *odn;
|
||||
char *ndn;
|
||||
char *last;
|
||||
unsigned long tag, len;
|
||||
LDAPMod *mods, *tmp;
|
||||
LDAPMod **modtail;
|
||||
ber_tag_t tag;
|
||||
ber_len_t len;
|
||||
LDAPModList *modlist;
|
||||
LDAPModList **modtail;
|
||||
#ifdef LDAP_DEBUG
|
||||
LDAPModList *tmp;
|
||||
#endif
|
||||
Backend *be;
|
||||
int rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "do_modify\n", 0, 0, 0 );
|
||||
|
||||
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", NULL );
|
||||
return LDAP_SASL_BIND_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the modify request. It looks like this:
|
||||
*
|
||||
|
|
@ -62,198 +69,150 @@ do_modify(
|
|||
* }
|
||||
*/
|
||||
|
||||
if ( ber_scanf( op->o_ber, "{a", &dn ) == LBER_ERROR ) {
|
||||
if ( ber_scanf( op->o_ber, "{a" /*}*/, &ndn ) == LBER_ERROR ) {
|
||||
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
|
||||
return;
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
return -1;
|
||||
}
|
||||
odn = strdup( dn );
|
||||
dn_normalize( dn );
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", dn, 0, 0 );
|
||||
Debug( LDAP_DEBUG_ARGS, "do_modify: dn (%s)\n", ndn, 0, 0 );
|
||||
|
||||
(void) dn_normalize_case( ndn );
|
||||
|
||||
/* collect modifications & save for later */
|
||||
mods = NULL;
|
||||
modtail = &mods;
|
||||
modlist = NULL;
|
||||
modtail = &modlist;
|
||||
|
||||
for ( tag = ber_first_element( op->o_ber, &len, &last );
|
||||
tag != LBER_DEFAULT;
|
||||
tag = ber_next_element( op->o_ber, &len, last ) )
|
||||
{
|
||||
(*modtail) = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
|
||||
ber_int_t mop;
|
||||
|
||||
if ( ber_scanf( op->o_ber, "{i{a[V]}}", &(*modtail)->mod_op,
|
||||
&(*modtail)->mod_type, &(*modtail)->mod_bvalues )
|
||||
(*modtail) = (LDAPModList *) ch_calloc( 1, sizeof(LDAPModList) );
|
||||
|
||||
if ( ber_scanf( op->o_ber, "{i{a[V]}}", &mop,
|
||||
&(*modtail)->ml_type, &(*modtail)->ml_bvalues )
|
||||
== LBER_ERROR )
|
||||
{
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
|
||||
"decoding error" );
|
||||
free( dn );
|
||||
free( odn );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding modlist error" );
|
||||
free( ndn );
|
||||
free( *modtail );
|
||||
modlist_free( mods );
|
||||
return;
|
||||
*modtail = NULL;
|
||||
modlist_free( modlist );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( (*modtail)->mod_op != LDAP_MOD_ADD &&
|
||||
(*modtail)->mod_op != LDAP_MOD_DELETE &&
|
||||
(*modtail)->mod_op != LDAP_MOD_REPLACE )
|
||||
(*modtail)->ml_op = mop;
|
||||
|
||||
if ( (*modtail)->ml_op != LDAP_MOD_ADD &&
|
||||
(*modtail)->ml_op != LDAP_MOD_DELETE &&
|
||||
(*modtail)->ml_op != LDAP_MOD_REPLACE )
|
||||
{
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
|
||||
"unrecognized modify operation" );
|
||||
free( dn );
|
||||
free( odn );
|
||||
modlist_free( mods );
|
||||
return;
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
|
||||
NULL, "unrecognized modify operation", NULL );
|
||||
free( ndn );
|
||||
modlist_free( modlist );
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
if ( (*modtail)->mod_bvalues == NULL && (*modtail)->mod_op
|
||||
!= LDAP_MOD_DELETE ) {
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
|
||||
"no values given" );
|
||||
free( dn );
|
||||
free( odn );
|
||||
modlist_free( mods );
|
||||
return;
|
||||
if ( (*modtail)->ml_bvalues == NULL
|
||||
&& (*modtail)->ml_op != LDAP_MOD_DELETE )
|
||||
{
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR,
|
||||
NULL, "unrecognized modify operation", NULL );
|
||||
free( ndn );
|
||||
modlist_free( modlist );
|
||||
return LDAP_PROTOCOL_ERROR;
|
||||
}
|
||||
attr_normalize( (*modtail)->mod_type );
|
||||
attr_normalize( (*modtail)->ml_type );
|
||||
|
||||
modtail = &(*modtail)->mod_next;
|
||||
modtail = &(*modtail)->ml_next;
|
||||
}
|
||||
*modtail = NULL;
|
||||
|
||||
#ifdef LDAP_DEBUG
|
||||
Debug( LDAP_DEBUG_ARGS, "modifications:\n", 0, 0, 0 );
|
||||
for ( tmp = mods; tmp != NULL; tmp = tmp->mod_next ) {
|
||||
Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n", tmp->mod_op
|
||||
== LDAP_MOD_ADD ? "add" : (tmp->mod_op == LDAP_MOD_DELETE ?
|
||||
"delete" : "replace"), tmp->mod_type, 0 );
|
||||
for ( tmp = modlist; tmp != NULL; tmp = tmp->ml_next ) {
|
||||
Debug( LDAP_DEBUG_ARGS, "\t%s: %s\n",
|
||||
tmp->ml_op == LDAP_MOD_ADD
|
||||
? "add" : (tmp->ml_op == LDAP_MOD_DELETE
|
||||
? "delete" : "replace"), tmp->ml_type, 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
|
||||
free( ndn );
|
||||
modlist_free( modlist );
|
||||
Debug( LDAP_DEBUG_ANY, "do_modify: get_ctrls failed\n", 0, 0, 0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d MOD dn=\"%s\"\n",
|
||||
conn->c_connid, op->o_opid, dn, 0, 0 );
|
||||
conn->c_connid, op->o_opid, ndn, 0, 0 );
|
||||
|
||||
/*
|
||||
* We could be serving multiple database backends. Select the
|
||||
* appropriate one, or send a referral to our "referral server"
|
||||
* if we don't hold it.
|
||||
*/
|
||||
if ( (be = select_backend( dn )) == NULL ) {
|
||||
free( dn );
|
||||
free( odn );
|
||||
modlist_free( mods );
|
||||
send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
|
||||
default_referral );
|
||||
return;
|
||||
if ( (be = select_backend( ndn )) == NULL ) {
|
||||
free( ndn );
|
||||
modlist_free( modlist );
|
||||
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
|
||||
NULL, NULL, default_referral );
|
||||
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;
|
||||
* 2) this backend is master for what it holds;
|
||||
* 3) it's a replica and the dn supplied is the updatedn.
|
||||
* 3) it's a replica and the dn supplied is the update_ndn.
|
||||
*/
|
||||
if ( be->be_modify != NULL ) {
|
||||
if ( be->be_modify ) {
|
||||
/* do the update here */
|
||||
if ( be->be_updatedn == NULL || strcasecmp( be->be_updatedn,
|
||||
op->o_dn ) == 0 ) {
|
||||
if ( (be->be_lastmod == ON || be->be_lastmod == 0 &&
|
||||
global_lastmod == ON) && be->be_updatedn == NULL ) {
|
||||
add_lastmods( op, &mods );
|
||||
}
|
||||
if ( (*be->be_modify)( be, conn, op, odn, mods )
|
||||
== 0 ) {
|
||||
replog( be, LDAP_REQ_MODIFY, dn, mods, 0 );
|
||||
if ( be->be_update_ndn == NULL ||
|
||||
strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
|
||||
{
|
||||
if ( (*be->be_modify)( be, conn, op, ndn, modlist ) == 0 ) {
|
||||
replog( be, LDAP_REQ_MODIFY, ndn, modlist, 0 );
|
||||
}
|
||||
|
||||
/* send a referral */
|
||||
} else {
|
||||
send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
|
||||
default_referral );
|
||||
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
|
||||
NULL, NULL, default_referral );
|
||||
}
|
||||
} else {
|
||||
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
|
||||
"Function not implemented" );
|
||||
send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
|
||||
NULL, "Function not implemented", NULL );
|
||||
}
|
||||
|
||||
free( dn );
|
||||
free( odn );
|
||||
modlist_free( mods );
|
||||
free( ndn );
|
||||
modlist_free( modlist );
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
modlist_free(
|
||||
LDAPMod *mods
|
||||
LDAPModList *ml
|
||||
)
|
||||
{
|
||||
LDAPMod *next;
|
||||
LDAPModList *next;
|
||||
|
||||
for ( ; mods != NULL; mods = next ) {
|
||||
next = mods->mod_next;
|
||||
free( mods->mod_type );
|
||||
if ( mods->mod_bvalues != NULL )
|
||||
ber_bvecfree( mods->mod_bvalues );
|
||||
free( mods );
|
||||
for ( ; ml != NULL; ml = next ) {
|
||||
next = ml->ml_next;
|
||||
|
||||
free( ml->ml_type );
|
||||
if ( ml->ml_bvalues != NULL )
|
||||
ber_bvecfree( ml->ml_bvalues );
|
||||
|
||||
free( ml );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_lastmods( Operation *op, LDAPMod **mods )
|
||||
{
|
||||
char buf[20];
|
||||
struct berval bv;
|
||||
struct berval *bvals[2];
|
||||
LDAPMod **m;
|
||||
LDAPMod *tmp;
|
||||
struct tm *ltm;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "add_lastmods\n", 0, 0, 0 );
|
||||
|
||||
bvals[0] = &bv;
|
||||
bvals[1] = NULL;
|
||||
|
||||
/* remove any attempts by the user to modify these attrs */
|
||||
for ( m = mods; *m != NULL; m = &(*m)->mod_next ) {
|
||||
if ( strcasecmp( (*m)->mod_type, "modifytimestamp" ) == 0
|
||||
|| strcasecmp( (*m)->mod_type, "modifiersname" ) == 0 ) {
|
||||
tmp = *m;
|
||||
*m = (*m)->mod_next;
|
||||
free( tmp->mod_type );
|
||||
if ( tmp->mod_bvalues != NULL ) {
|
||||
ber_bvecfree( tmp->mod_bvalues );
|
||||
}
|
||||
free( tmp );
|
||||
}
|
||||
}
|
||||
|
||||
if ( op->o_dn == NULL || op->o_dn[0] == '\0' ) {
|
||||
bv.bv_val = "NULLDN";
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
} else {
|
||||
bv.bv_val = op->o_dn;
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
}
|
||||
tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
|
||||
tmp->mod_type = strdup( "modifiersname" );
|
||||
tmp->mod_op = LDAP_MOD_REPLACE;
|
||||
tmp->mod_bvalues = (struct berval **) ch_calloc( 1,
|
||||
2 * sizeof(struct berval *) );
|
||||
tmp->mod_bvalues[0] = ber_bvdup( &bv );
|
||||
tmp->mod_next = *mods;
|
||||
*mods = tmp;
|
||||
|
||||
pthread_mutex_lock( ¤ttime_mutex );
|
||||
ltm = localtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
|
||||
pthread_mutex_unlock( ¤ttime_mutex );
|
||||
bv.bv_val = buf;
|
||||
bv.bv_len = strlen( bv.bv_val );
|
||||
tmp = (LDAPMod *) ch_calloc( 1, sizeof(LDAPMod) );
|
||||
tmp->mod_type = strdup( "modifytimestamp" );
|
||||
tmp->mod_op = LDAP_MOD_REPLACE;
|
||||
tmp->mod_bvalues = (struct berval **) ch_calloc( 1,
|
||||
2 * sizeof(struct berval *) );
|
||||
tmp->mod_bvalues[0] = ber_bvdup( &bv );
|
||||
tmp->mod_next = *mods;
|
||||
*mods = tmp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,52 +10,167 @@
|
|||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
/*
|
||||
* LDAP v3 newSuperior support.
|
||||
*
|
||||
* Copyright 1999, Juan C. Gomez, All rights reserved.
|
||||
* This software is not subject to any license of Silicon Graphics
|
||||
* Inc. or Purdue University.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* without restriction or fee of any kind as long as this notice
|
||||
* is preserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
extern Backend *select_backend();
|
||||
|
||||
extern char *default_referral;
|
||||
|
||||
void
|
||||
int
|
||||
do_modrdn(
|
||||
Connection *conn,
|
||||
Operation *op
|
||||
)
|
||||
{
|
||||
char *dn, *odn, *newrdn;
|
||||
int deloldrdn;
|
||||
char *ndn, *newrdn;
|
||||
ber_int_t deloldrdn;
|
||||
Backend *be;
|
||||
/* Vars for LDAP v3 newSuperior support */
|
||||
char *newSuperior = NULL;
|
||||
char *nnewSuperior = NULL;
|
||||
Backend *newSuperior_be = NULL;
|
||||
ber_len_t length;
|
||||
int rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "do_modrdn\n", 0, 0, 0 );
|
||||
|
||||
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", NULL );
|
||||
return LDAP_SASL_BIND_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the modrdn request. It looks like this:
|
||||
*
|
||||
* ModifyRDNRequest := SEQUENCE {
|
||||
* entry DistinguishedName,
|
||||
* newrdn RelativeDistinguishedName
|
||||
* deleteoldrdn BOOLEAN,
|
||||
* newSuperior [0] LDAPDN OPTIONAL (v3 Only!)
|
||||
* }
|
||||
*/
|
||||
|
||||
if ( ber_scanf( op->o_ber, "{aab}", &dn, &newrdn, &deloldrdn )
|
||||
if ( ber_scanf( op->o_ber, "{aab", &ndn, &newrdn, &deloldrdn )
|
||||
== LBER_ERROR ) {
|
||||
Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 );
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
|
||||
return;
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check for newSuperior parameter, if present scan it */
|
||||
|
||||
if ( ber_peek_tag( op->o_ber, &length ) == LDAP_TAG_NEWSUPERIOR ) {
|
||||
|
||||
if ( op->o_protocol == 0 ) {
|
||||
/*
|
||||
* Promote to LDAPv3
|
||||
*/
|
||||
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
|
||||
conn->c_protocol = LDAP_VERSION3;
|
||||
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
|
||||
op->o_protocol = LDAP_VERSION3;
|
||||
|
||||
} else if ( op->o_protocol < LDAP_VERSION3 ) {
|
||||
/* Conection record indicates v2 but field
|
||||
* newSuperior is present: report error.
|
||||
*/
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"modrdn(v2): invalid field newSuperior!\n",
|
||||
0, 0, 0 );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "newSuperior requires LDAPv3" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( ber_scanf( op->o_ber, "a", &newSuperior )
|
||||
== LBER_ERROR ) {
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "ber_scanf(\"a\"}) failed\n",
|
||||
0, 0, 0 );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
odn = strdup( dn );
|
||||
dn_normalize( dn );
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS,
|
||||
"do_modrdn: dn (%s) newrdn (%s) deloldrdn (%d)\n", dn, newrdn,
|
||||
deloldrdn );
|
||||
"do_modrdn: dn (%s) newrdn (%s) newsuperior (%s)\n",
|
||||
ndn, newrdn,
|
||||
newSuperior != NULL ? newSuperior : "" );
|
||||
|
||||
if ( ber_scanf( op->o_ber, /*{*/ "}") == LBER_ERROR ) {
|
||||
free( ndn );
|
||||
free( newrdn );
|
||||
free( newSuperior );
|
||||
Debug( LDAP_DEBUG_ANY, "do_modrdn: ber_scanf failed\n", 0, 0, 0 );
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
|
||||
free( ndn );
|
||||
free( newrdn );
|
||||
free( newSuperior );
|
||||
Debug( LDAP_DEBUG_ANY, "do_modrdn: get_ctrls failed\n", 0, 0, 0 );
|
||||
return rc;
|
||||
}
|
||||
|
||||
if( newSuperior != NULL ) {
|
||||
/* GET BACKEND FOR NEW SUPERIOR */
|
||||
|
||||
nnewSuperior = strdup( newSuperior );
|
||||
dn_normalize_case( nnewSuperior );
|
||||
|
||||
if ( (newSuperior_be = select_backend( nnewSuperior ))
|
||||
== NULL ) {
|
||||
|
||||
/* We do not have a backend for newSuperior so we send
|
||||
* a referral.
|
||||
* XXX: We may need to do something else here, not sure
|
||||
* what though.
|
||||
*/
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS,
|
||||
"do_modrdn: cant find backend for=(%s)\n",
|
||||
newSuperior, 0, 0 );
|
||||
|
||||
free( ndn );
|
||||
free( newrdn );
|
||||
free( newSuperior );
|
||||
free( nnewSuperior );
|
||||
send_ldap_result( conn, op, LDAP_REFERRAL,
|
||||
NULL, NULL, default_referral );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
dn_normalize_case( ndn );
|
||||
|
||||
Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d MODRDN dn=\"%s\"\n",
|
||||
conn->c_connid, op->o_opid, dn, 0, 0 );
|
||||
conn->c_connid, op->o_opid, ndn, 0, 0 );
|
||||
|
||||
/*
|
||||
* We could be serving multiple database backends. Select the
|
||||
|
|
@ -63,40 +178,70 @@ do_modrdn(
|
|||
* if we don't hold it.
|
||||
*/
|
||||
|
||||
if ( (be = select_backend( dn )) == NULL ) {
|
||||
free( dn );
|
||||
free( odn );
|
||||
free( newrdn );
|
||||
send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
|
||||
default_referral );
|
||||
return;
|
||||
if ( (be = select_backend( ndn )) == NULL ) {
|
||||
free( ndn );
|
||||
free( newrdn );
|
||||
free( newSuperior );
|
||||
free( nnewSuperior );
|
||||
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
|
||||
NULL, NULL, default_referral );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Make sure that the entry being changed and the newSuperior are in
|
||||
* the same backend, otherwise we return an error.
|
||||
*/
|
||||
|
||||
if ( (newSuperior_be != NULL) && ( be != newSuperior_be) ) {
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "dn=(%s), newSuperior=(%s)\n", ndn,
|
||||
newSuperior, 0 );
|
||||
|
||||
free( ndn );
|
||||
free( newrdn );
|
||||
free( newSuperior );
|
||||
free( nnewSuperior );
|
||||
|
||||
send_ldap_result( conn, op, rc = LDAP_AFFECTS_MULTIPLE_DSAS,
|
||||
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;
|
||||
* 2) this backend is master for what it holds;
|
||||
* 3) it's a replica and the dn supplied is the updatedn.
|
||||
* 3) it's a replica and the dn supplied is the update_ndn.
|
||||
*/
|
||||
if ( be->be_modrdn != NULL ) {
|
||||
if ( be->be_modrdn ) {
|
||||
/* do the update here */
|
||||
if ( be->be_updatedn == NULL || strcasecmp( be->be_updatedn,
|
||||
op->o_dn ) == 0 ) {
|
||||
if ( (*be->be_modrdn)( be, conn, op, dn, newrdn,
|
||||
deloldrdn ) == 0 ) {
|
||||
replog( be, LDAP_REQ_MODRDN, odn, newrdn,
|
||||
if ( be->be_update_ndn == NULL ||
|
||||
strcmp( be->be_update_ndn, op->o_ndn ) == 0 )
|
||||
{
|
||||
if ( (*be->be_modrdn)( be, conn, op, ndn, newrdn,
|
||||
deloldrdn, newSuperior ) == 0 ) {
|
||||
/* XXX: MAY NEED TO ADD newSuperior HERE */
|
||||
replog( be, LDAP_REQ_MODRDN, ndn, newrdn,
|
||||
deloldrdn );
|
||||
}
|
||||
} else {
|
||||
send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
|
||||
default_referral );
|
||||
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
|
||||
NULL, NULL, default_referral );
|
||||
}
|
||||
} else {
|
||||
send_ldap_result( conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
|
||||
"Function not implemented" );
|
||||
send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
|
||||
NULL, "Function not implemented", NULL );
|
||||
}
|
||||
|
||||
free( dn );
|
||||
free( odn );
|
||||
free( newrdn );
|
||||
free( ndn );
|
||||
free( newrdn );
|
||||
free( newSuperior );
|
||||
free( nnewSuperior );
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,54 +10,46 @@
|
|||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/time.h>
|
||||
|
||||
#include "ldap_defaults.h"
|
||||
#include "slap.h"
|
||||
#include "ldapconfig.h"
|
||||
|
||||
#if defined( SLAPD_MONITOR_DN )
|
||||
|
||||
extern int nbackends;
|
||||
extern Backend *backends;
|
||||
extern int active_threads;
|
||||
extern int dtblsize;
|
||||
extern Connection *c;
|
||||
extern long ops_initiated;
|
||||
extern long ops_completed;
|
||||
extern long num_entries_sent;
|
||||
extern long num_bytes_sent;
|
||||
extern time_t currenttime;
|
||||
extern time_t starttime;
|
||||
extern int num_conns;
|
||||
|
||||
|
||||
extern char Versionstr[];
|
||||
|
||||
/*
|
||||
* no mutex protection in here - take our chances!
|
||||
*/
|
||||
|
||||
void
|
||||
monitor_info( Connection *conn, Operation *op )
|
||||
{
|
||||
Entry *e;
|
||||
char buf[BUFSIZ], buf2[20];
|
||||
char buf[BUFSIZ];
|
||||
struct berval val;
|
||||
struct berval *vals[2];
|
||||
int i, nconns, nwritewaiters, nreadwaiters;
|
||||
int nconns, nwritewaiters, nreadwaiters;
|
||||
struct tm *ltm;
|
||||
char *p, *tmpdn;
|
||||
char *p;
|
||||
char buf2[22];
|
||||
char buf3[22];
|
||||
Connection *c;
|
||||
int connindex;
|
||||
time_t currenttime;
|
||||
|
||||
vals[0] = &val;
|
||||
vals[1] = NULL;
|
||||
|
||||
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
|
||||
/* initialize reader/writer lock */
|
||||
e->e_attrs = NULL;
|
||||
e->e_dn = strdup( SLAPD_MONITOR_DN );
|
||||
e->e_dn = ch_strdup( SLAPD_MONITOR_DN );
|
||||
e->e_ndn = dn_normalize_case( ch_strdup(SLAPD_MONITOR_DN) );
|
||||
e->e_private = NULL;
|
||||
|
||||
val.bv_val = Versionstr;
|
||||
val.bv_val = (char *) Versionstr;
|
||||
if (( p = strchr( Versionstr, '\n' )) == NULL ) {
|
||||
val.bv_len = strlen( Versionstr );
|
||||
} else {
|
||||
|
|
@ -65,7 +57,9 @@ monitor_info( Connection *conn, Operation *op )
|
|||
}
|
||||
attr_merge( e, "version", vals );
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &active_threads_mutex );
|
||||
sprintf( buf, "%d", active_threads );
|
||||
ldap_pvt_thread_mutex_unlock( &active_threads_mutex );
|
||||
val.bv_val = buf;
|
||||
val.bv_len = strlen( buf );
|
||||
attr_merge( e, "threads", vals );
|
||||
|
|
@ -73,82 +67,165 @@ monitor_info( Connection *conn, Operation *op )
|
|||
nconns = 0;
|
||||
nwritewaiters = 0;
|
||||
nreadwaiters = 0;
|
||||
for ( i = 0; i < dtblsize; i++ ) {
|
||||
if ( c[i].c_sb.sb_sd != -1 ) {
|
||||
nconns++;
|
||||
if ( c[i].c_writewaiter ) {
|
||||
nwritewaiters++;
|
||||
}
|
||||
if ( c[i].c_gettingber ) {
|
||||
nreadwaiters++;
|
||||
}
|
||||
ltm = localtime( &c[i].c_starttime );
|
||||
strftime( buf2, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
|
||||
pthread_mutex_lock( &c[i].c_dnmutex );
|
||||
sprintf( buf, "%d : %s : %ld : %ld : %s : %s%s", i,
|
||||
buf2, c[i].c_opsinitiated, c[i].c_opscompleted,
|
||||
c[i].c_dn ? c[i].c_dn : "NULLDN",
|
||||
c[i].c_gettingber ? "r" : "",
|
||||
c[i].c_writewaiter ? "w" : "" );
|
||||
pthread_mutex_unlock( &c[i].c_dnmutex );
|
||||
val.bv_val = buf;
|
||||
val.bv_len = strlen( buf );
|
||||
attr_merge( e, "connection", vals );
|
||||
|
||||
/* loop through the connections */
|
||||
for ( c = connection_first( &connindex );
|
||||
c != NULL;
|
||||
c = connection_next( c, &connindex ))
|
||||
{
|
||||
nconns++;
|
||||
if ( c->c_writewaiter ) {
|
||||
nwritewaiters++;
|
||||
}
|
||||
if ( c->c_currentber != NULL ) {
|
||||
nreadwaiters++;
|
||||
}
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &gmtime_mutex );
|
||||
#ifndef LDAP_LOCALTIME
|
||||
ltm = gmtime( &c->c_starttime );
|
||||
strftime( buf2, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm );
|
||||
|
||||
ltm = gmtime( &c->c_activitytime );
|
||||
strftime( buf3, sizeof(buf2), "%Y%m%d%H%M%SZ", ltm );
|
||||
#else
|
||||
ltm = localtime( &c->.c_starttime );
|
||||
strftime( buf2, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
|
||||
|
||||
ltm = localtime( &c->c_activitytime );
|
||||
strftime( buf3, sizeof(buf2), "%y%m%d%H%M%SZ", ltm );
|
||||
#endif
|
||||
|
||||
ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
|
||||
|
||||
sprintf( buf,
|
||||
"%ld : %ld "
|
||||
": %ld/%ld/%ld/%ld "
|
||||
": %ld/%ld/%ld "
|
||||
": %s%s%s%s%s%s "
|
||||
": %s : %s : %s "
|
||||
": %s : %s",
|
||||
|
||||
c->c_connid,
|
||||
(long) c->c_protocol,
|
||||
|
||||
c->c_n_ops_received, c->c_n_ops_executing,
|
||||
c->c_n_ops_pending, c->c_n_ops_completed,
|
||||
|
||||
/* add low-level counters here */
|
||||
c->c_n_get, c->c_n_read, c->c_n_write,
|
||||
|
||||
c->c_currentber ? "r" : "",
|
||||
c->c_writewaiter ? "w" : "",
|
||||
c->c_ops != NULL ? "x" : "",
|
||||
c->c_pending_ops != NULL ? "p" : "",
|
||||
connection_state2str( c->c_conn_state ),
|
||||
c->c_bind_in_progress ? "S" : "",
|
||||
|
||||
c->c_cdn ? c->c_cdn : "<anonymous>",
|
||||
c->c_client_addr ? c->c_client_addr : "unknown",
|
||||
c->c_client_name ? c->c_client_name : "unknown",
|
||||
|
||||
buf2,
|
||||
buf3
|
||||
);
|
||||
|
||||
val.bv_val = buf;
|
||||
val.bv_len = strlen( buf );
|
||||
attr_merge( e, "connection", vals );
|
||||
}
|
||||
connection_done(c);
|
||||
|
||||
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, "%d", num_conns );
|
||||
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, "%d", dtblsize );
|
||||
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 );
|
||||
|
||||
sprintf( buf, "%ld", ops_initiated );
|
||||
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 );
|
||||
|
||||
sprintf( buf, "%ld", ops_completed );
|
||||
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 );
|
||||
|
||||
ltm = localtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
|
||||
currenttime = slap_get_time();
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &gmtime_mutex );
|
||||
#ifndef LDAP_LOCALTIME
|
||||
ltm = gmtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
|
||||
#else
|
||||
ltm = localtime( ¤ttime );
|
||||
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
|
||||
#endif
|
||||
val.bv_val = buf;
|
||||
val.bv_len = strlen( buf );
|
||||
attr_merge( e, "currenttime", vals );
|
||||
|
||||
ltm = localtime( &starttime );
|
||||
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
|
||||
#ifndef LDAP_LOCALTIME
|
||||
ltm = gmtime( &starttime );
|
||||
strftime( buf, sizeof(buf), "%Y%m%d%H%M%SZ", ltm );
|
||||
#else
|
||||
ltm = localtime( &starttime );
|
||||
strftime( buf, sizeof(buf), "%y%m%d%H%M%SZ", ltm );
|
||||
#endif
|
||||
ldap_pvt_thread_mutex_unlock( &gmtime_mutex );
|
||||
|
||||
val.bv_val = buf;
|
||||
val.bv_len = strlen( buf );
|
||||
attr_merge( e, "starttime", vals );
|
||||
|
|
@ -158,15 +235,15 @@ monitor_info( Connection *conn, Operation *op )
|
|||
val.bv_len = strlen( buf );
|
||||
attr_merge( e, "nbackends", vals );
|
||||
|
||||
#ifdef THREAD_SUNOS5_LWP
|
||||
sprintf( buf, "%d", thr_getconcurrency() );
|
||||
#ifdef HAVE_THREAD_CONCURRENCY
|
||||
sprintf( buf, "%d", ldap_pvt_thread_get_concurrency() );
|
||||
val.bv_val = buf;
|
||||
val.bv_len = strlen( buf );
|
||||
attr_merge( e, "concurrency", vals );
|
||||
#endif
|
||||
|
||||
send_search_entry( &backends[0], conn, op, e, NULL, 0 );
|
||||
send_ldap_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, 1 );
|
||||
send_search_entry( &backends[0], conn, op, e, NULL, 0, 1 );
|
||||
send_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, 1 );
|
||||
|
||||
entry_free( e );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,202 +1,439 @@
|
|||
#ifndef _PROTO_SLAP
|
||||
#define _PROTO_SLAP
|
||||
|
||||
#include <ldap_cdefs.h>
|
||||
|
||||
LDAP_BEGIN_DECL
|
||||
|
||||
/*
|
||||
* acl.c
|
||||
*/
|
||||
|
||||
int access_allowed( Backend *be, Connection *conn, Operation *op, Entry *e,
|
||||
char *attr, struct berval *val, char *dn, int access );
|
||||
struct acl * acl_get_applicable( Backend *be, Operation *op, Entry *e,
|
||||
char *attr );
|
||||
int acl_access_allowed( struct acl *a, Backend *be, Connection *conn, Entry *e,
|
||||
struct berval *val, Operation *op, int access );
|
||||
int acl_check_mods( Backend *be, Connection *conn, Operation *op, Entry *e,
|
||||
LDAPMod *mods );
|
||||
int access_allowed LDAP_P(( Backend *be, Connection *conn,
|
||||
Operation *op, Entry *e,
|
||||
char *attr, struct berval *val, int access ));
|
||||
|
||||
struct acl * acl_get_applicable LDAP_P(( Backend *be,
|
||||
Operation *op, Entry *e,
|
||||
char *attr, int nmatches, regmatch_t *matches ));
|
||||
|
||||
int acl_access_allowed LDAP_P(( struct acl *a, Backend *be, Connection *conn, Entry *e,
|
||||
struct berval *val, Operation *op, int access, char *edn,
|
||||
regmatch_t *matches ));
|
||||
|
||||
int acl_check_modlist LDAP_P(( Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
Entry *e,
|
||||
LDAPModList *ml ));
|
||||
|
||||
/*
|
||||
* aclparse.c
|
||||
*/
|
||||
|
||||
void parse_acl( Backend *be, char *fname, int lineno, int argc, char **argv );
|
||||
char * access2str( int access );
|
||||
int str2access( char *str );
|
||||
void parse_acl LDAP_P(( Backend *be, char *fname, int lineno, int argc, char **argv ));
|
||||
char * access2str LDAP_P(( int access ));
|
||||
int str2access LDAP_P(( char *str ));
|
||||
|
||||
/*
|
||||
* attr.c
|
||||
*/
|
||||
|
||||
void attr_free( Attribute *a );
|
||||
char * attr_normalize( char *s );
|
||||
int attr_merge_fast( Entry *e, char *type, struct berval **vals, int nvals,
|
||||
int naddvals, int *maxvals, Attribute ***a );
|
||||
int attr_merge( Entry *e, char *type, struct berval **vals );
|
||||
Attribute * attr_find( Attribute *a, char *type );
|
||||
int attr_delete( Attribute **attrs, char *type );
|
||||
int attr_syntax( char *type );
|
||||
void attr_syntax_config( char *fname, int lineno, int argc, char **argv );
|
||||
void attr_free LDAP_P(( Attribute *a ));
|
||||
char * attr_normalize LDAP_P(( char *s ));
|
||||
int attr_merge_fast LDAP_P(( Entry *e, char *type, struct berval **vals, int nvals,
|
||||
int naddvals, int *maxvals, Attribute ***a ));
|
||||
int attr_merge LDAP_P(( Entry *e, char *type, struct berval **vals ));
|
||||
Attribute * attr_find LDAP_P(( Attribute *a, char *type ));
|
||||
int attr_delete LDAP_P(( Attribute **attrs, char *type ));
|
||||
int attr_syntax LDAP_P(( char *type ));
|
||||
void attr_syntax_config LDAP_P(( char *fname, int lineno, int argc, char **argv ));
|
||||
AttributeType * at_find LDAP_P(( const char *name ));
|
||||
int at_find_in_list LDAP_P(( AttributeType *sat, AttributeType **list ));
|
||||
int at_append_to_list LDAP_P(( AttributeType *sat, AttributeType ***listp ));
|
||||
int at_delete_from_list LDAP_P(( int pos, AttributeType ***listp ));
|
||||
int at_fake_if_needed LDAP_P(( char *name ));
|
||||
int at_schema_info LDAP_P(( Entry *e ));
|
||||
int at_add LDAP_P(( LDAP_ATTRIBUTE_TYPE *at, const char **err ));
|
||||
char * at_canonical_name LDAP_P(( char * a_type ));
|
||||
|
||||
/*
|
||||
* ava.c
|
||||
*/
|
||||
|
||||
int get_ava( BerElement *ber, Ava *ava );
|
||||
void ava_free( Ava *ava, int freeit );
|
||||
int get_ava LDAP_P(( BerElement *ber, Ava *ava ));
|
||||
void ava_free LDAP_P(( Ava *ava, int freeit ));
|
||||
|
||||
/*
|
||||
* backend.c
|
||||
*/
|
||||
|
||||
Backend * new_backend( char *type );
|
||||
Backend * select_backend( char * dn );
|
||||
int be_issuffix( Backend *be, char *suffix );
|
||||
int be_isroot( Backend *be, char *dn );
|
||||
int be_isroot_pw( Backend *be, char *dn, struct berval *cred );
|
||||
void be_close();
|
||||
int backend_init LDAP_P((void));
|
||||
int backend_add LDAP_P((BackendInfo *aBackendInfo));
|
||||
int backend_startup LDAP_P((int dbnum));
|
||||
int backend_shutdown LDAP_P((int dbnum));
|
||||
int backend_destroy LDAP_P((void));
|
||||
|
||||
BackendInfo * backend_info LDAP_P(( char *type ));
|
||||
BackendDB * backend_db_init LDAP_P(( char *type ));
|
||||
|
||||
BackendDB * select_backend LDAP_P(( char * dn ));
|
||||
|
||||
int be_issuffix LDAP_P(( Backend *be, char *suffix ));
|
||||
int be_isroot LDAP_P(( Backend *be, char *ndn ));
|
||||
int be_isroot_pw LDAP_P(( Backend *be, char *ndn, struct berval *cred ));
|
||||
char* be_root_dn LDAP_P(( Backend *be ));
|
||||
int be_entry_release_rw LDAP_P(( Backend *be, Entry *e, int rw ));
|
||||
#define be_entry_release_r( be, e ) be_entry_release_rw( be, e, 0 )
|
||||
#define be_entry_release_w( be, e ) be_entry_release_rw( be, e, 1 )
|
||||
|
||||
|
||||
extern int backend_unbind LDAP_P((Connection *conn, Operation *op));
|
||||
|
||||
extern int backend_connection_init LDAP_P((Connection *conn));
|
||||
extern int backend_connection_destroy LDAP_P((Connection *conn));
|
||||
|
||||
extern int backend_group LDAP_P((Backend *be,
|
||||
Entry *target,
|
||||
char *gr_ndn, char *op_ndn,
|
||||
char *objectclassValue, char *groupattrName));
|
||||
|
||||
/*
|
||||
* ch_malloc.c
|
||||
*/
|
||||
|
||||
char * ch_malloc( unsigned long size );
|
||||
char * ch_realloc( char *block, unsigned long size );
|
||||
char * ch_calloc( unsigned long nelem, unsigned long size );
|
||||
void * ch_malloc LDAP_P(( ber_len_t size ));
|
||||
void * ch_realloc LDAP_P(( void *block, ber_len_t size ));
|
||||
void * ch_calloc LDAP_P(( ber_len_t nelem, ber_len_t size ));
|
||||
char * ch_strdup LDAP_P(( const char *string ));
|
||||
void ch_free LDAP_P(( void * ));
|
||||
#define free ch_free
|
||||
|
||||
/*
|
||||
* charray.c
|
||||
*/
|
||||
|
||||
void charray_add( char ***a, char *s );
|
||||
void charray_merge( char ***a, char **s );
|
||||
void charray_free( char **array );
|
||||
int charray_inlist( char **a, char *s );
|
||||
char ** charray_dup( char **a );
|
||||
char ** str2charray( char *str, char *brkstr );
|
||||
void charray_add LDAP_P(( char ***a, char *s ));
|
||||
void charray_merge LDAP_P(( char ***a, char **s ));
|
||||
void charray_free LDAP_P(( char **array ));
|
||||
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
|
||||
*/
|
||||
int get_ctrls LDAP_P((
|
||||
Connection *co,
|
||||
Operation *op,
|
||||
int senderrors ));
|
||||
|
||||
/*
|
||||
* config.c
|
||||
*/
|
||||
|
||||
void read_config( char *fname, Backend **bep, FILE *pfp );
|
||||
int read_config LDAP_P(( char *fname ));
|
||||
|
||||
/*
|
||||
* connection.c
|
||||
*/
|
||||
int connections_init LDAP_P((void));
|
||||
int connections_shutdown LDAP_P((void));
|
||||
int connections_destroy LDAP_P((void));
|
||||
int connections_timeout_idle LDAP_P((time_t));
|
||||
|
||||
void connection_activity( Connection *conn );
|
||||
long connection_init LDAP_P((
|
||||
ber_socket_t s,
|
||||
const char* name, const char* addr));
|
||||
|
||||
void connection_closing LDAP_P(( Connection *c ));
|
||||
int connection_state_closing LDAP_P(( Connection *c ));
|
||||
char *connection_state2str LDAP_P(( int state ));
|
||||
|
||||
int connection_write LDAP_P((ber_socket_t s));
|
||||
int connection_read LDAP_P((ber_socket_t s));
|
||||
|
||||
unsigned long connections_nextid(void);
|
||||
|
||||
Connection* connection_first LDAP_P((ber_socket_t *));
|
||||
Connection* connection_next LDAP_P((Connection *, ber_socket_t *));
|
||||
void connection_done LDAP_P((Connection *));
|
||||
|
||||
/*
|
||||
* dn.c
|
||||
*/
|
||||
|
||||
char * dn_normalize( char *dn );
|
||||
char * dn_normalize_case( char *dn );
|
||||
char * dn_parent( Backend *be, char *dn );
|
||||
int dn_issuffix( char *dn, char *suffix );
|
||||
int dn_type( char *dn );
|
||||
char * dn_upcase( char *dn );
|
||||
|
||||
char * dn_normalize LDAP_P(( char *dn ));
|
||||
char * dn_normalize_case LDAP_P(( char *dn ));
|
||||
char * dn_parent LDAP_P(( Backend *be, char *dn ));
|
||||
char * dn_rdn LDAP_P(( Backend *be, char *dn ));
|
||||
int dn_issuffix LDAP_P(( char *dn, char *suffix ));
|
||||
int dn_type LDAP_P(( char *dn ));
|
||||
char * dn_upcase LDAP_P(( char *dn ));
|
||||
char * rdn_attr_value LDAP_P(( char * rdn ));
|
||||
char * rdn_attr_type LDAP_P(( char * rdn ));
|
||||
void build_new_dn LDAP_P(( char ** new_dn, char *e_dn, char * p_dn,
|
||||
char * newrdn ));
|
||||
/*
|
||||
* entry.c
|
||||
*/
|
||||
|
||||
Entry * str2entry( char *s );
|
||||
char * entry2str( Entry *e, int *len, int printid );
|
||||
void entry_free( Entry *e );
|
||||
Entry * str2entry LDAP_P(( char *s ));
|
||||
char * entry2str LDAP_P(( Entry *e, int *len, int printid ));
|
||||
void entry_free LDAP_P(( Entry *e ));
|
||||
|
||||
int entry_cmp LDAP_P(( Entry *a, Entry *b ));
|
||||
int entry_dn_cmp LDAP_P(( Entry *a, Entry *b ));
|
||||
int entry_id_cmp LDAP_P(( Entry *a, Entry *b ));
|
||||
|
||||
/*
|
||||
* filter.c
|
||||
*/
|
||||
|
||||
int get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr );
|
||||
void filter_free( Filter *f );
|
||||
void filter_print( Filter *f );
|
||||
int get_filter LDAP_P(( Connection *conn, BerElement *ber, Filter **filt, char **fstr ));
|
||||
void filter_free LDAP_P(( Filter *f ));
|
||||
void filter_print LDAP_P(( Filter *f ));
|
||||
|
||||
/*
|
||||
* filterentry.c
|
||||
*/
|
||||
|
||||
int test_filter( Backend *be, Connection *conn, Operation *op, Entry *e,
|
||||
Filter *f );
|
||||
int test_filter LDAP_P(( Backend *be, Connection *conn, Operation *op, Entry *e,
|
||||
Filter *f ));
|
||||
|
||||
/*
|
||||
* lock.c
|
||||
*/
|
||||
|
||||
FILE * lock_fopen( char *fname, char *type, FILE **lfp );
|
||||
int lock_fclose( FILE *fp, FILE *lfp );
|
||||
FILE * lock_fopen LDAP_P(( char *fname, char *type, FILE **lfp ));
|
||||
int lock_fclose LDAP_P(( FILE *fp, FILE *lfp ));
|
||||
|
||||
/*
|
||||
* module.c
|
||||
*/
|
||||
|
||||
#ifdef SLAPD_MODULES
|
||||
int load_module LDAP_P(( const char* file_name, int argc, char *argv[] ));
|
||||
#endif /* SLAPD_MODULES */
|
||||
|
||||
/*
|
||||
* monitor.c
|
||||
*/
|
||||
extern char *supportedExtensions[];
|
||||
extern char *supportedControls[];
|
||||
extern char *supportedSASLMechanisms[];
|
||||
|
||||
void monitor_info( Connection *conn, Operation *op );
|
||||
void monitor_info LDAP_P(( Connection *conn, Operation *op ));
|
||||
|
||||
/*
|
||||
* operation.c
|
||||
*/
|
||||
|
||||
void op_free( Operation *op );
|
||||
Operation * op_add( Operation **olist, BerElement *ber, unsigned long msgid,
|
||||
unsigned long tag, char *dn, int id, int connid );
|
||||
void op_delete( Operation **olist, Operation *op );
|
||||
void slap_op_free LDAP_P(( Operation *op ));
|
||||
Operation * slap_op_alloc LDAP_P((
|
||||
BerElement *ber, ber_int_t msgid,
|
||||
ber_tag_t tag, ber_int_t id ));
|
||||
|
||||
int slap_op_add LDAP_P(( Operation **olist, Operation *op ));
|
||||
int slap_op_remove LDAP_P(( Operation **olist, Operation *op ));
|
||||
Operation * slap_op_pop LDAP_P(( Operation **olist ));
|
||||
|
||||
/*
|
||||
* phonetic.c
|
||||
*/
|
||||
|
||||
char * first_word( char *s );
|
||||
char * next_word( char *s );
|
||||
char * word_dup( char *w );
|
||||
char * phonetic( char *s );
|
||||
char * first_word LDAP_P(( char *s ));
|
||||
char * next_word LDAP_P(( char *s ));
|
||||
char * word_dup LDAP_P(( char *w ));
|
||||
char * phonetic LDAP_P(( char *s ));
|
||||
|
||||
/*
|
||||
* repl.c
|
||||
*/
|
||||
|
||||
void replog( Backend *be, int optype, char *dn, void *change, int flag );
|
||||
void replog LDAP_P(( Backend *be, int optype, char *dn, void *change, int flag ));
|
||||
|
||||
/*
|
||||
* result.c
|
||||
*/
|
||||
|
||||
void send_ldap_result( Connection *conn, Operation *op, int err, char *matched,
|
||||
char *text );
|
||||
void send_ldap_search_result( Connection *conn, Operation *op, int err,
|
||||
char *matched, char *text, int nentries );
|
||||
void close_connection( Connection *conn, int opconnid, int opid );
|
||||
void send_ldap_result LDAP_P((
|
||||
Connection *conn, Operation *op,
|
||||
int err, char *matched, char *text,
|
||||
struct berval **refs ));
|
||||
|
||||
void send_ldap_disconnect LDAP_P((
|
||||
Connection *conn, Operation *op,
|
||||
int err, char *text ));
|
||||
|
||||
void send_search_result LDAP_P((
|
||||
Connection *conn, Operation *op,
|
||||
int err, char *matched, char *text,
|
||||
struct berval **refs,
|
||||
int nentries ));
|
||||
|
||||
int send_search_reference LDAP_P((
|
||||
Backend *be, Connection *conn, Operation *op,
|
||||
Entry *e, struct berval **refs,
|
||||
struct berval ***v2refs ));
|
||||
|
||||
int send_search_entry LDAP_P((
|
||||
Backend *be, Connection *conn, Operation *op,
|
||||
Entry *e, char **attrs, int attrsonly, int opattrs ));
|
||||
|
||||
int str2result LDAP_P(( char *s,
|
||||
int *code, char **matched, char **info ));
|
||||
|
||||
/*
|
||||
* schema.c
|
||||
*/
|
||||
|
||||
int oc_schema_check( Entry *e );
|
||||
int oc_schema_check LDAP_P(( Entry *e ));
|
||||
int oc_check_operational_attr LDAP_P(( char *type ));
|
||||
int oc_check_usermod_attr LDAP_P(( char *type ));
|
||||
int oc_check_no_usermod_attr LDAP_P(( char *type ));
|
||||
ObjectClass *oc_find LDAP_P((const char *ocname));
|
||||
int oc_add LDAP_P((LDAP_OBJECT_CLASS *oc, const char **err));
|
||||
Syntax *syn_find LDAP_P((const char *synname));
|
||||
int syn_add LDAP_P((LDAP_SYNTAX *syn, slap_syntax_check_func *check, const char **err));
|
||||
MatchingRule *mr_find LDAP_P((const char *mrname));
|
||||
int mr_add LDAP_P((LDAP_MATCHING_RULE *mr, slap_mr_normalize_func *normalize, slap_mr_compare_func *compare, const char **err));
|
||||
void schema_info LDAP_P((Connection *conn, Operation *op, char **attrs, int attrsonly));
|
||||
int schema_init LDAP_P((void));
|
||||
|
||||
|
||||
/*
|
||||
* schemaparse.c
|
||||
*/
|
||||
|
||||
void parse_oc( Backend *be, char *fname, int lineno, int argc, char **argv );
|
||||
|
||||
void parse_oc_old LDAP_P(( Backend *be, char *fname, int lineno, int argc, char **argv ));
|
||||
void parse_oc LDAP_P(( char *fname, int lineno, char *line ));
|
||||
void parse_at LDAP_P(( char *fname, int lineno, char *line ));
|
||||
char *scherr2str LDAP_P((int code));
|
||||
/*
|
||||
* str2filter.c
|
||||
*/
|
||||
|
||||
Filter * str2filter( char *str );
|
||||
Filter * str2filter LDAP_P(( char *str ));
|
||||
|
||||
/*
|
||||
* value.c
|
||||
*/
|
||||
|
||||
int value_add_fast( struct berval ***vals, struct berval **addvals, int nvals,
|
||||
int naddvals, int *maxvals );
|
||||
int value_add( struct berval ***vals, struct berval **addvals );
|
||||
void value_normalize( char *s, int syntax );
|
||||
int value_cmp( struct berval *v1, struct berval *v2, int syntax,
|
||||
int normalize );
|
||||
int value_ncmp( struct berval *v1, struct berval *v2, int syntax, int len,
|
||||
int normalize );
|
||||
int value_find( struct berval **vals, struct berval *v, int syntax,
|
||||
int normalize );
|
||||
int value_add_fast LDAP_P(( struct berval ***vals, struct berval **addvals, int nvals,
|
||||
int naddvals, int *maxvals ));
|
||||
int value_add LDAP_P(( struct berval ***vals, struct berval **addvals ));
|
||||
void value_normalize LDAP_P(( char *s, int syntax ));
|
||||
int value_cmp LDAP_P(( struct berval *v1, struct berval *v2, int syntax,
|
||||
int normalize ));
|
||||
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
|
||||
*/
|
||||
#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
|
||||
void slap_init_user LDAP_P(( char *username, char *groupname ));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Other...
|
||||
*/
|
||||
|
||||
extern struct berval **default_referral;
|
||||
extern char *replogfile;
|
||||
extern const char Versionstr[];
|
||||
extern int active_threads;
|
||||
extern int defsize;
|
||||
extern int deftime;
|
||||
extern int g_argc;
|
||||
extern int global_default_access;
|
||||
extern int global_lastmod;
|
||||
extern int global_idletimeout;
|
||||
extern int global_schemacheck;
|
||||
extern char *global_realm;
|
||||
extern int lber_debug;
|
||||
extern int ldap_syslog;
|
||||
|
||||
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 long num_ops_initiated;
|
||||
|
||||
extern char *slapd_pid_file;
|
||||
extern char *slapd_args_file;
|
||||
extern char **g_argv;
|
||||
extern time_t starttime;
|
||||
|
||||
time_t slap_get_time LDAP_P((void));
|
||||
|
||||
extern ldap_pvt_thread_mutex_t active_threads_mutex;
|
||||
extern ldap_pvt_thread_cond_t active_threads_cond;
|
||||
|
||||
extern ldap_pvt_thread_mutex_t entry2str_mutex;
|
||||
extern ldap_pvt_thread_mutex_t replog_mutex;
|
||||
|
||||
#ifdef SLAPD_CRYPT
|
||||
extern ldap_pvt_thread_mutex_t crypt_mutex;
|
||||
#endif
|
||||
extern ldap_pvt_thread_mutex_t gmtime_mutex;
|
||||
|
||||
extern struct acl *global_acl;
|
||||
|
||||
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;
|
||||
|
||||
struct slapd_args {
|
||||
struct sockaddr_in *addr;
|
||||
int tcps;
|
||||
};
|
||||
|
||||
extern int slapd_daemon LDAP_P((struct slapd_args *args));
|
||||
extern int set_socket LDAP_P((struct sockaddr_in *addr));
|
||||
|
||||
extern void slapd_set_write LDAP_P((ber_socket_t s, int wake));
|
||||
extern void slapd_clr_write LDAP_P((ber_socket_t s, int wake));
|
||||
extern void slapd_set_read LDAP_P((ber_socket_t s, int wake));
|
||||
extern void slapd_clr_read LDAP_P((ber_socket_t s, int wake));
|
||||
|
||||
extern void slapd_remove LDAP_P((ber_socket_t s, int wake));
|
||||
|
||||
extern void slap_set_shutdown LDAP_P((int sig));
|
||||
extern void slap_do_nothing LDAP_P((int sig));
|
||||
|
||||
extern void config_info LDAP_P((Connection *conn, Operation *op));
|
||||
extern void root_dse_info LDAP_P((Connection *conn, Operation *op, char **attrs, int attrsonly));
|
||||
|
||||
extern int do_abandon LDAP_P((Connection *conn, Operation *op));
|
||||
extern int do_add LDAP_P((Connection *conn, Operation *op));
|
||||
extern int do_bind LDAP_P((Connection *conn, Operation *op));
|
||||
extern int do_compare LDAP_P((Connection *conn, Operation *op));
|
||||
extern int do_delete LDAP_P((Connection *conn, Operation *op));
|
||||
extern int do_modify LDAP_P((Connection *conn, Operation *op));
|
||||
extern int do_modrdn LDAP_P((Connection *conn, Operation *op));
|
||||
extern int do_search LDAP_P((Connection *conn, Operation *op));
|
||||
extern int do_unbind LDAP_P((Connection *conn, Operation *op));
|
||||
extern int do_extended LDAP_P((Connection *conn, Operation *op));
|
||||
|
||||
|
||||
extern ber_socket_t dtblsize;
|
||||
|
||||
LDAP_END_DECL
|
||||
|
||||
#endif /* _proto_slap */
|
||||
|
||||
|
|
|
|||
|
|
@ -1,105 +1,95 @@
|
|||
/* result.c - routines to send ldap results, errors, and referrals */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <ac/socket.h>
|
||||
#include <ac/errno.h>
|
||||
#include <ac/signal.h>
|
||||
#include <ac/string.h>
|
||||
#include <ac/time.h>
|
||||
#include <ac/unistd.h>
|
||||
|
||||
#include "slap.h"
|
||||
|
||||
#ifndef SYSERRLIST_IN_STDIO
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
#endif
|
||||
extern int active_threads;
|
||||
extern pthread_mutex_t active_threads_mutex;
|
||||
extern pthread_mutex_t new_conn_mutex;
|
||||
extern pthread_t listener_tid;
|
||||
extern struct acl *acl_get_applicable();
|
||||
extern long num_entries_sent;
|
||||
extern long num_bytes_sent;
|
||||
extern pthread_mutex_t num_sent_mutex;
|
||||
/* we need LBER internals */
|
||||
#include "../../libraries/liblber/lber-int.h"
|
||||
|
||||
void close_connection();
|
||||
|
||||
static void
|
||||
send_ldap_result2(
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
int err,
|
||||
char *matched,
|
||||
char *text,
|
||||
int nentries
|
||||
)
|
||||
static char *v2ref( struct berval **ref )
|
||||
{
|
||||
BerElement *ber;
|
||||
int rc, sd;
|
||||
unsigned long tag, bytes;
|
||||
size_t len, i;
|
||||
char *v2;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "send_ldap_result %d:%s:%s\n", err, matched ?
|
||||
matched : "", text ? text : "" );
|
||||
if(ref == NULL) return NULL;
|
||||
|
||||
switch ( op->o_tag ) {
|
||||
case LBER_DEFAULT:
|
||||
tag = LBER_SEQUENCE;
|
||||
break;
|
||||
len = sizeof("Referral:");
|
||||
v2 = ch_strdup("Referral:");
|
||||
|
||||
case LDAP_REQ_SEARCH:
|
||||
tag = LDAP_RES_SEARCH_RESULT;
|
||||
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;
|
||||
}
|
||||
|
||||
v2[len-1] = '\0';
|
||||
return v2;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
default:
|
||||
tag = op->o_tag + 1;
|
||||
case LDAP_REQ_ABANDON:
|
||||
case LDAP_REQ_UNBIND:
|
||||
tag = LBER_SEQUENCE;
|
||||
break;
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
#ifdef COMPAT30
|
||||
if ( (ber = ber_alloc_t( conn->c_version == 30 ? 0 : LBER_USE_DER ))
|
||||
== NULLBER ) {
|
||||
#else
|
||||
if ( (ber = der_alloc()) == NULLBER ) {
|
||||
#endif
|
||||
Debug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CLDAP
|
||||
if ( op->o_cldap ) {
|
||||
rc = ber_printf( ber, "{is{t{ess}}}", op->o_msgid, "", tag,
|
||||
err, matched ? matched : "", text ? text : "" );
|
||||
} else
|
||||
#endif
|
||||
#ifdef COMPAT30
|
||||
if ( conn->c_version == 30 ) {
|
||||
rc = ber_printf( ber, "{it{{ess}}}", op->o_msgid, tag, err,
|
||||
matched ? matched : "", text ? text : "" );
|
||||
} else
|
||||
#endif
|
||||
rc = ber_printf( ber, "{it{ess}}", op->o_msgid, tag, err,
|
||||
matched ? matched : "", text ? text : "" );
|
||||
|
||||
if ( rc == -1 ) {
|
||||
Debug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
|
||||
return;
|
||||
}
|
||||
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 */
|
||||
pthread_mutex_lock( &conn->c_pdumutex );
|
||||
ldap_pvt_thread_mutex_lock( &conn->c_write_mutex );
|
||||
|
||||
/* lock the connection */
|
||||
ldap_pvt_thread_mutex_lock( &conn->c_mutex );
|
||||
|
||||
/* write the pdu */
|
||||
bytes = ber->ber_ptr - ber->ber_buf;
|
||||
pthread_mutex_lock( &new_conn_mutex );
|
||||
while ( conn->c_connid == op->o_connid && ber_flush( &conn->c_sb, ber,
|
||||
1 ) != 0 ) {
|
||||
pthread_mutex_unlock( &new_conn_mutex );
|
||||
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 0;
|
||||
}
|
||||
|
||||
if ( ber_flush( conn->c_sb, ber, 1 ) == 0 ) {
|
||||
break;
|
||||
}
|
||||
|
||||
err = errno;
|
||||
|
||||
/*
|
||||
* we got an error. if it's ewouldblock, we need to
|
||||
* wait on the socket being writable. otherwise, figure
|
||||
|
|
@ -107,77 +97,281 @@ send_ldap_result2(
|
|||
*/
|
||||
|
||||
Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno %d msg (%s)\n",
|
||||
errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno]
|
||||
err, err > -1 && err < sys_nerr ? sys_errlist[err]
|
||||
: "unknown", 0 );
|
||||
|
||||
if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
|
||||
close_connection( conn, op->o_connid, op->o_opid );
|
||||
if ( err != EWOULDBLOCK && err != EAGAIN ) {
|
||||
connection_closing( conn );
|
||||
|
||||
pthread_mutex_unlock( &conn->c_pdumutex );
|
||||
return;
|
||||
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
|
||||
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* wait for socket to be write-ready */
|
||||
pthread_mutex_lock( &active_threads_mutex );
|
||||
active_threads--;
|
||||
conn->c_writewaiter = 1;
|
||||
pthread_kill( listener_tid, SIGUSR1 );
|
||||
pthread_cond_wait( &conn->c_wcv, &active_threads_mutex );
|
||||
pthread_mutex_unlock( &active_threads_mutex );
|
||||
slapd_set_write( ber_pvt_sb_get_desc( conn->c_sb ), 1 );
|
||||
|
||||
pthread_yield();
|
||||
pthread_mutex_lock( &new_conn_mutex );
|
||||
ldap_pvt_thread_cond_wait( &conn->c_write_cv, &conn->c_mutex );
|
||||
conn->c_writewaiter = 0;
|
||||
}
|
||||
pthread_mutex_unlock( &new_conn_mutex );
|
||||
pthread_mutex_unlock( &conn->c_pdumutex );
|
||||
|
||||
pthread_mutex_lock( &num_sent_mutex );
|
||||
ldap_pvt_thread_mutex_unlock( &conn->c_mutex );
|
||||
ldap_pvt_thread_mutex_unlock( &conn->c_write_mutex );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= send_ldap_ber\n", 0, 0, 0 );
|
||||
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
|
||||
)
|
||||
{
|
||||
BerElement *ber;
|
||||
int rc;
|
||||
long bytes;
|
||||
|
||||
ber = ber_alloc_t( LBER_USE_DER );
|
||||
|
||||
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;
|
||||
pthread_mutex_unlock( &num_sent_mutex );
|
||||
num_pdu_sent++;
|
||||
ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
send_ldap_disconnect(
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
ber_int_t err,
|
||||
char *text
|
||||
)
|
||||
{
|
||||
ber_tag_t tag;
|
||||
ber_int_t msgid;
|
||||
char *reqoid;
|
||||
|
||||
#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 ) {
|
||||
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, NULL, text, NULL,
|
||||
reqoid, NULL );
|
||||
|
||||
Statslog( LDAP_DEBUG_STATS,
|
||||
"conn=%d op=%d RESULT err=%d tag=%d nentries=%d\n", conn->c_connid,
|
||||
op->o_opid, err, tag, nentries );
|
||||
|
||||
return;
|
||||
"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_result(
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
int err,
|
||||
ber_int_t err,
|
||||
char *matched,
|
||||
char *text
|
||||
char *text,
|
||||
struct berval **ref
|
||||
)
|
||||
{
|
||||
#ifdef CLDAP
|
||||
ber_tag_t tag;
|
||||
ber_int_t msgid;
|
||||
char *tmp = NULL;
|
||||
|
||||
assert( !LDAP_API_ERROR( err ) );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "send_ldap_result %d:%s:%s\n",
|
||||
err, matched ? matched : "", text ? text : "" );
|
||||
|
||||
assert( err != LDAP_PARTIAL_RESULTS );
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LDAP_CONNECTIONLESS
|
||||
if ( op->o_cldap ) {
|
||||
SAFEMEMCPY( (char *)conn->c_sb.sb_useaddr, &op->o_clientaddr,
|
||||
sizeof( struct sockaddr ));
|
||||
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 *)
|
||||
conn->c_sb.sb_useaddr)->sin_addr ),
|
||||
((struct sockaddr_in *) conn->c_sb.sb_useaddr)->sin_port,
|
||||
&op->o_clientaddr)->sin_addr ),
|
||||
((struct sockaddr_in *) &op->o_clientaddr)->sin_port,
|
||||
0 );
|
||||
}
|
||||
#endif
|
||||
send_ldap_result2( conn, op, err, matched, text, 0 );
|
||||
|
||||
send_ldap_response( conn, op, tag, msgid,
|
||||
err, matched, text, ref,
|
||||
NULL, NULL );
|
||||
|
||||
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,
|
||||
int err,
|
||||
ber_int_t err,
|
||||
char *matched,
|
||||
char *text,
|
||||
char *text,
|
||||
struct berval **refs,
|
||||
int nentries
|
||||
)
|
||||
{
|
||||
send_ldap_result2( conn, op, err, matched, text, 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 : "" );
|
||||
|
||||
assert( err != LDAP_PARTIAL_RESULTS );
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
#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 );
|
||||
|
||||
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,
|
||||
|
|
@ -185,179 +379,247 @@ send_search_entry(
|
|||
Operation *op,
|
||||
Entry *e,
|
||||
char **attrs,
|
||||
int attrsonly
|
||||
int attrsonly,
|
||||
int opattrs
|
||||
)
|
||||
{
|
||||
BerElement *ber;
|
||||
Attribute *a;
|
||||
int i, rc, bytes, sd;
|
||||
int i, rc=-1, bytes;
|
||||
struct acl *acl;
|
||||
char *edn;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> send_search_entry (%s)\n", e->e_dn, 0, 0 );
|
||||
|
||||
if ( ! access_allowed( be, conn, op, e, "entry", NULL, op->o_dn,
|
||||
ACL_READ ) ) {
|
||||
#if defined( SLAPD_SCHEMA_DN )
|
||||
{
|
||||
/* this could be backend specific */
|
||||
struct berval val;
|
||||
val.bv_val = SLAPD_SCHEMA_DN;
|
||||
val.bv_len = strlen( val.bv_val );
|
||||
attr_merge( e, "subschemaSubentry", vals );
|
||||
ldap_memfree( val.bv_val );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( ! access_allowed( be, conn, op, e,
|
||||
"entry", NULL, ACL_READ ) )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ACL, "acl: access to entry not allowed\n",
|
||||
0, 0, 0 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
#ifdef COMPAT30
|
||||
if ( (ber = ber_alloc_t( conn->c_version == 30 ? 0 : LBER_USE_DER ))
|
||||
== NULLBER ) {
|
||||
#else
|
||||
if ( (ber = der_alloc()) == NULLBER ) {
|
||||
#endif
|
||||
edn = e->e_ndn;
|
||||
|
||||
ber = ber_alloc_t( LBER_USE_DER );
|
||||
|
||||
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" );
|
||||
return( 1 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, "allocating BER error", NULL );
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
#ifdef COMPAT30
|
||||
if ( conn->c_version == 30 ) {
|
||||
rc = ber_printf( ber, "{it{{s{", op->o_msgid,
|
||||
LDAP_RES_SEARCH_ENTRY, e->e_dn );
|
||||
} else
|
||||
#endif
|
||||
rc = ber_printf( ber, "{it{s{", op->o_msgid,
|
||||
LDAP_RES_SEARCH_ENTRY, e->e_dn );
|
||||
rc = ber_printf( ber, "{it{s{", op->o_msgid,
|
||||
LDAP_RES_SEARCH_ENTRY, e->e_dn );
|
||||
|
||||
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" );
|
||||
return( 1 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, "encoding dn error", NULL );
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
|
||||
if ( attrs != NULL && ! charray_inlist( attrs, a->a_type ) ) {
|
||||
regmatch_t matches[MAXREMATCHES];
|
||||
|
||||
if ( attrs == NULL ) {
|
||||
/* all addrs request, skip operational attributes */
|
||||
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 ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
acl = acl_get_applicable( be, op, e, a->a_type,
|
||||
MAXREMATCHES, matches );
|
||||
|
||||
if ( ! acl_access_allowed( acl, be, conn, e,
|
||||
NULL, op, ACL_READ, edn, matches ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
acl = acl_get_applicable( be, op, e, a->a_type );
|
||||
|
||||
if ( ! acl_access_allowed( acl, be, conn, e, NULL, op,
|
||||
ACL_READ ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ber_printf( ber, "{s[", a->a_type ) == -1 ) {
|
||||
if (( rc = ber_printf( ber, "{s[" /*]}*/ , a->a_type )) == -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 type" );
|
||||
return( 1 );
|
||||
NULL, "encoding type error", NULL );
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
if ( ! attrsonly ) {
|
||||
for ( i = 0; a->a_vals[i] != NULL; i++ ) {
|
||||
if ( a->a_syntax & SYNTAX_DN &&
|
||||
! acl_access_allowed( acl, be, conn, e,
|
||||
a->a_vals[i], op, ACL_READ ) )
|
||||
if ( a->a_syntax & SYNTAX_DN &&
|
||||
! acl_access_allowed( acl, be, conn, e, a->a_vals[i], op,
|
||||
ACL_READ, edn, matches) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ber_printf( ber, "o",
|
||||
a->a_vals[i]->bv_val,
|
||||
a->a_vals[i]->bv_len ) == -1 )
|
||||
{
|
||||
if (( rc = ber_printf( ber, "O", a->a_vals[i] )) == -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 value" );
|
||||
return( 1 );
|
||||
send_ldap_result( conn, op, LDAP_OPERATIONS_ERROR,
|
||||
NULL, "encoding value error", NULL );
|
||||
goto error_return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ber_printf( ber, "]}" ) == -1 ) {
|
||||
if (( rc = ber_printf( ber, /*{[*/ "]}" )) == -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 type end" );
|
||||
return( 1 );
|
||||
NULL, "encode end error", NULL );
|
||||
goto error_return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMPAT30
|
||||
if ( conn->c_version == 30 ) {
|
||||
rc = ber_printf( ber, "}}}}" );
|
||||
} else
|
||||
#endif
|
||||
rc = ber_printf( ber, "}}}" );
|
||||
rc = ber_printf( ber, /*{{{*/ "}}}" );
|
||||
|
||||
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 );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
/* write only one pdu at a time - wait til it's our turn */
|
||||
pthread_mutex_lock( &conn->c_pdumutex );
|
||||
bytes = send_ldap_ber( conn, ber );
|
||||
|
||||
bytes = ber->ber_ptr - ber->ber_buf;
|
||||
pthread_mutex_lock( &new_conn_mutex );
|
||||
while ( conn->c_connid == op->o_connid && ber_flush( &conn->c_sb, ber,
|
||||
1 ) != 0 ) {
|
||||
pthread_mutex_unlock( &new_conn_mutex );
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
Debug( LDAP_DEBUG_CONNS, "ber_flush failed errno %d msg (%s)\n",
|
||||
errno, errno > -1 && errno < sys_nerr ? sys_errlist[errno]
|
||||
: "unknown", 0 );
|
||||
|
||||
if ( errno != EWOULDBLOCK && errno != EAGAIN ) {
|
||||
close_connection( conn, op->o_connid, op->o_opid );
|
||||
|
||||
pthread_mutex_unlock( &conn->c_pdumutex );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
/* wait for socket to be write-ready */
|
||||
pthread_mutex_lock( &active_threads_mutex );
|
||||
active_threads--;
|
||||
conn->c_writewaiter = 1;
|
||||
pthread_kill( listener_tid, SIGUSR1 );
|
||||
pthread_cond_wait( &conn->c_wcv, &active_threads_mutex );
|
||||
pthread_mutex_unlock( &active_threads_mutex );
|
||||
|
||||
pthread_yield();
|
||||
pthread_mutex_lock( &new_conn_mutex );
|
||||
if ( bytes < 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"send_ldap_response: ber write failed\n",
|
||||
0, 0, 0 );
|
||||
return -1;
|
||||
}
|
||||
pthread_mutex_unlock( &new_conn_mutex );
|
||||
pthread_mutex_unlock( &conn->c_pdumutex );
|
||||
|
||||
pthread_mutex_lock( &num_sent_mutex );
|
||||
ldap_pvt_thread_mutex_lock( &num_sent_mutex );
|
||||
num_bytes_sent += bytes;
|
||||
num_entries_sent++;
|
||||
pthread_mutex_unlock( &num_sent_mutex );
|
||||
num_pdu_sent++;
|
||||
ldap_pvt_thread_mutex_unlock( &num_sent_mutex );
|
||||
|
||||
pthread_mutex_lock( &new_conn_mutex );
|
||||
if ( conn->c_connid == op->o_connid ) {
|
||||
rc = 0;
|
||||
Statslog( LDAP_DEBUG_STATS2, "conn=%d op=%d ENTRY dn=\"%s\"\n",
|
||||
conn->c_connid, op->o_opid, e->e_dn, 0, 0 );
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
pthread_mutex_unlock( &new_conn_mutex );
|
||||
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 );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
|
||||
|
||||
rc = 0;
|
||||
|
||||
error_return:;
|
||||
return( rc );
|
||||
}
|
||||
|
||||
int
|
||||
send_search_reference(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
Entry *e,
|
||||
struct berval **refs,
|
||||
struct berval ***v2refs
|
||||
)
|
||||
{
|
||||
BerElement *ber;
|
||||
int rc;
|
||||
int bytes;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "=> send_search_entry (%s)\n", e->e_dn, 0, 0 );
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ber = ber_alloc_t( LBER_USE_DER );
|
||||
|
||||
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 );
|
||||
return -1;
|
||||
}
|
||||
|
||||
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 );
|
||||
return -1;
|
||||
}
|
||||
|
||||
bytes = send_ldap_ber( conn, ber );
|
||||
|
||||
ldap_pvt_thread_mutex_lock( &num_sent_mutex );
|
||||
num_bytes_sent += bytes;
|
||||
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",
|
||||
(long) conn->c_connid, (long) op->o_opid, e->e_dn, 0, 0 );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<= send_search_entry\n", 0, 0, 0 );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
str2result(
|
||||
char *s,
|
||||
|
|
@ -411,24 +673,3 @@ str2result(
|
|||
|
||||
return( rc );
|
||||
}
|
||||
|
||||
/*
|
||||
* close_connection - close a connection. takes the connection to close,
|
||||
* the connid associated with the operation generating the close (so we
|
||||
* don't accidentally close a connection that's not ours), and the opid
|
||||
* of the operation generating the close (for logging purposes).
|
||||
*/
|
||||
void
|
||||
close_connection( Connection *conn, int opconnid, int opid )
|
||||
{
|
||||
pthread_mutex_lock( &new_conn_mutex );
|
||||
if ( conn->c_sb.sb_sd != -1 && conn->c_connid == opconnid ) {
|
||||
Statslog( LDAP_DEBUG_STATS,
|
||||
"conn=%d op=%d fd=%d closed errno=%d\n", conn->c_connid,
|
||||
opid, conn->c_sb.sb_sd, errno, 0 );
|
||||
close( conn->c_sb.sb_sd );
|
||||
conn->c_sb.sb_sd = -1;
|
||||
conn->c_version = 0;
|
||||
}
|
||||
pthread_mutex_unlock( &new_conn_mutex );
|
||||
}
|
||||
|
|
|
|||
105
servers/slapd/root_dse.c
Normal file
105
servers/slapd/root_dse.c
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/* root_dse.c - Provides the ROOT DSA-Specific Entry
|
||||
*
|
||||
* Copyright 1999 The OpenLDAP Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted only
|
||||
* as authorized by the OpenLDAP Public License. A copy of this
|
||||
* license is available at http://www.OpenLDAP.org/license.html or
|
||||
* in file LICENSE in the top-level directory of the distribution.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ldap_defaults.h"
|
||||
#include "slap.h"
|
||||
|
||||
void
|
||||
root_dse_info( Connection *conn, Operation *op, char **attrs, int attrsonly )
|
||||
{
|
||||
char buf[BUFSIZ];
|
||||
Entry *e;
|
||||
struct berval val;
|
||||
struct berval *vals[2];
|
||||
int i, j;
|
||||
|
||||
vals[0] = &val;
|
||||
vals[1] = NULL;
|
||||
|
||||
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
|
||||
|
||||
e->e_attrs = NULL;
|
||||
e->e_dn = ch_strdup( LDAP_ROOT_DSE );
|
||||
e->e_ndn = dn_normalize_case( ch_strdup( LDAP_ROOT_DSE ));
|
||||
e->e_private = NULL;
|
||||
|
||||
for ( i = 0; i < nbackends; i++ ) {
|
||||
for ( j = 0; backends[i].be_suffix[j] != NULL; j++ ) {
|
||||
val.bv_val = backends[i].be_suffix[j];
|
||||
val.bv_len = strlen( val.bv_val );
|
||||
attr_merge( e, "namingContexts", vals );
|
||||
}
|
||||
}
|
||||
|
||||
#if defined( SLAPD_MONITOR_DN )
|
||||
val.bv_val = SLAPD_MONITOR_DN;
|
||||
val.bv_len = strlen( val.bv_val );
|
||||
attr_merge( e, "namingContexts", vals );
|
||||
/* subschemasubentry is added by send_search_entry() */
|
||||
#endif
|
||||
|
||||
#if defined( SLAPD_CONFIG_DN )
|
||||
val.bv_val = SLAPD_CONFIG_DN;
|
||||
val.bv_len = strlen( val.bv_val );
|
||||
attr_merge( e, "namingContexts", vals );
|
||||
#endif
|
||||
|
||||
#if defined( SLAPD_SCHEMA_DN )
|
||||
val.bv_val = SLAPD_SCHEMA_DN;
|
||||
val.bv_len = strlen( val.bv_val );
|
||||
attr_merge( e, "namingContexts", vals );
|
||||
#endif
|
||||
|
||||
/* altServer unsupported */
|
||||
|
||||
/* supportedControl */
|
||||
for ( i=0; supportedControls[i] != NULL; i++ ) {
|
||||
val.bv_val = supportedControls[i];
|
||||
val.bv_len = strlen( val.bv_val );
|
||||
attr_merge( e, "supportedControl", vals );
|
||||
}
|
||||
|
||||
/* supportedExtension */
|
||||
for ( i=0; supportedExtensions[i] != NULL; i++ ) {
|
||||
val.bv_val = supportedExtensions[i];
|
||||
val.bv_len = strlen( val.bv_val );
|
||||
attr_merge( e, "supportedExtension", vals );
|
||||
}
|
||||
|
||||
/* supportedLDAPVersion */
|
||||
for ( i=LDAP_VERSION_MIN; i<=LDAP_VERSION_MAX; i++ ) {
|
||||
sprintf(buf,"%d",i);
|
||||
val.bv_val = buf;
|
||||
val.bv_len = strlen( val.bv_val );
|
||||
attr_merge( e, "supportedLDAPVersion", vals );
|
||||
}
|
||||
|
||||
/* supportedSASLMechanism */
|
||||
for ( i=0; supportedSASLMechanisms[i] != NULL; i++ ) {
|
||||
val.bv_val = supportedSASLMechanisms[i];
|
||||
val.bv_len = strlen( val.bv_val );
|
||||
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_search_result( conn, op, LDAP_SUCCESS, NULL, NULL, NULL, 1 );
|
||||
|
||||
entry_free( e );
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load diff
445
servers/slapd/schema/core.schema
Normal file
445
servers/slapd/schema/core.schema
Normal file
|
|
@ -0,0 +1,445 @@
|
|||
|
||||
# OpenLDAP Core schema
|
||||
# Includes "standard" schema items from RFC2251-RFC2256
|
||||
|
||||
# Standard X.501(93) Operational Attribute Types from RFC2252
|
||||
|
||||
attribute ( 2.5.18.1 NAME 'createTimestamp' EQUALITY generalizedTimeMatch
|
||||
ORDERING generalizedTimeOrderingMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
|
||||
SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
|
||||
|
||||
attribute ( 2.5.18.2 NAME 'modifyTimestamp' EQUALITY generalizedTimeMatch
|
||||
ORDERING generalizedTimeOrderingMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
|
||||
SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
|
||||
|
||||
attribute ( 2.5.18.3 NAME 'creatorsName' EQUALITY distinguishedNameMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
|
||||
SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
|
||||
|
||||
attribute ( 2.5.18.4 NAME 'modifiersName' EQUALITY distinguishedNameMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
|
||||
SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
|
||||
|
||||
attribute ( 2.5.18.10 NAME 'subschemaSubentry'
|
||||
EQUALITY distinguishedNameMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 NO-USER-MODIFICATION
|
||||
SINGLE-VALUE USAGE directoryOperation )
|
||||
|
||||
attribute ( 2.5.21.5 NAME 'attributeTypes'
|
||||
EQUALITY objectIdentifierFirstComponentMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.3 USAGE directoryOperation )
|
||||
|
||||
attribute ( 2.5.21.6 NAME 'objectClasses'
|
||||
EQUALITY objectIdentifierFirstComponentMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.37 USAGE directoryOperation )
|
||||
|
||||
attribute ( 2.5.21.4 NAME 'matchingRules'
|
||||
EQUALITY objectIdentifierFirstComponentMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.30 USAGE directoryOperation )
|
||||
|
||||
attribute ( 2.5.21.8 NAME 'matchingRuleUse'
|
||||
EQUALITY objectIdentifierFirstComponentMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.31 USAGE directoryOperation )
|
||||
|
||||
# LDAP Operational Attributes from RFC2252
|
||||
|
||||
attribute ( 1.3.6.1.4.1.1466.101.120.5 NAME 'namingContexts'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 USAGE dSAOperation )
|
||||
|
||||
attribute ( 1.3.6.1.4.1.1466.101.120.6 NAME 'altServer'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 USAGE dSAOperation )
|
||||
|
||||
attribute ( 1.3.6.1.4.1.1466.101.120.7 NAME 'supportedExtension'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )
|
||||
|
||||
attribute ( 1.3.6.1.4.1.1466.101.120.13 NAME 'supportedControl'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 USAGE dSAOperation )
|
||||
|
||||
attribute ( 1.3.6.1.4.1.1466.101.120.14 NAME 'supportedSASLMechanisms'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 USAGE dSAOperation )
|
||||
|
||||
attribute ( 1.3.6.1.4.1.1466.101.120.15 NAME 'supportedLDAPVersion'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 USAGE dSAOperation )
|
||||
|
||||
# LDAP Subschema Atrribute from RFC2252
|
||||
|
||||
attribute ( 1.3.6.1.4.1.1466.101.120.16 NAME 'ldapSyntaxes'
|
||||
EQUALITY objectIdentifierFirstComponentMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.54 USAGE directoryOperation )
|
||||
|
||||
# X.500 Subschema attributes from RFC2252
|
||||
|
||||
attribute ( 2.5.21.1 NAME 'dITStructureRules' EQUALITY integerFirstComponentMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.17 USAGE directoryOperation )
|
||||
|
||||
attribute ( 2.5.21.7 NAME 'nameForms'
|
||||
EQUALITY objectIdentifierFirstComponentMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.35 USAGE directoryOperation )
|
||||
|
||||
attribute ( 2.5.21.2 NAME 'dITContentRules'
|
||||
EQUALITY objectIdentifierFirstComponentMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.16 USAGE directoryOperation )
|
||||
|
||||
# Object Classes from RFC2252
|
||||
|
||||
# extensibleObject moved forward, since it depends on top
|
||||
# ldapSyntaxes (operational) is admissible in next:
|
||||
|
||||
objectclass ( 2.5.20.1 NAME 'subschema' AUXILIARY
|
||||
MAY ( dITStructureRules $ nameForms $ ditContentRules $
|
||||
objectClasses $ attributeTypes $ matchingRules $
|
||||
matchingRuleUse ) )
|
||||
|
||||
# Standard attribute types from RFC2256
|
||||
|
||||
attribute ( 2.5.4.0 NAME 'objectClass' EQUALITY objectIdentifierMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
|
||||
|
||||
attribute ( 2.5.4.1 NAME 'aliasedObjectName' EQUALITY distinguishedNameMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
|
||||
|
||||
# Defined, but no longer used
|
||||
|
||||
attribute ( 2.5.4.2 NAME 'knowledgeInformation' EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
|
||||
|
||||
# Place here since other attribute types derive from it
|
||||
|
||||
attribute ( 2.5.4.41 NAME 'name' EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
|
||||
|
||||
attribute ( 2.5.4.3 NAME ( 'cn' 'commonName' ) SUP name )
|
||||
|
||||
attribute ( 2.5.4.4 NAME ( 'sn' 'surname' ) SUP name )
|
||||
|
||||
attribute ( 2.5.4.5 NAME 'serialNumber' EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{64} )
|
||||
|
||||
# (2-letter code from ISO 3166)
|
||||
|
||||
attribute ( 2.5.4.6 NAME ( 'c' 'countryName' ) SUP name SINGLE-VALUE )
|
||||
|
||||
attribute ( 2.5.4.7 NAME ( 'l' 'localityName' ) SUP name )
|
||||
|
||||
attribute ( 2.5.4.8 NAME ( 'st' 'stateOrProvinceName' ) SUP name )
|
||||
|
||||
attribute ( 2.5.4.9 NAME ( 'street' 'streetAddress' ) EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
|
||||
|
||||
attribute ( 2.5.4.10 NAME ( 'o' 'organizationName' ) SUP name )
|
||||
|
||||
attribute ( 2.5.4.11 NAME ( 'ou' 'organizationalUnitName' ) SUP name )
|
||||
|
||||
attribute ( 2.5.4.12 NAME 'title' SUP name )
|
||||
|
||||
attribute ( 2.5.4.13 NAME 'description' EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )
|
||||
|
||||
# Obsoleted by enhancedSearchGuide
|
||||
|
||||
attribute ( 2.5.4.14 NAME 'searchGuide'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.25 )
|
||||
|
||||
attribute ( 2.5.4.15 NAME 'businessCategory' EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
|
||||
|
||||
# Show stopper: we don't have the definition of caseIgnoreListSubstringsMatch
|
||||
#attribute ( 2.5.4.16 NAME 'postalAddress' EQUALITY caseIgnoreListMatch
|
||||
# SUBSTR caseIgnoreListSubstringsMatch
|
||||
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
|
||||
attribute ( 2.5.4.16 NAME 'postalAddress' EQUALITY caseIgnoreListMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
|
||||
|
||||
attribute ( 2.5.4.17 NAME 'postalCode' EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} )
|
||||
|
||||
attribute ( 2.5.4.18 NAME 'postOfficeBox' EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} )
|
||||
|
||||
attribute ( 2.5.4.19 NAME 'physicalDeliveryOfficeName' EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
|
||||
|
||||
attribute ( 2.5.4.20 NAME 'telephoneNumber' EQUALITY telephoneNumberMatch
|
||||
SUBSTR telephoneNumberSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.50{32} )
|
||||
|
||||
attribute ( 2.5.4.21 NAME 'telexNumber'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.52 )
|
||||
|
||||
attribute ( 2.5.4.22 NAME 'teletexTerminalIdentifier'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.51 )
|
||||
|
||||
attribute ( 2.5.4.23 NAME ( 'facsimileTelephoneNumber' 'fax' )
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.22 )
|
||||
|
||||
attribute ( 2.5.4.24 NAME 'x121Address' EQUALITY numericStringMatch
|
||||
SUBSTR numericStringSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{15} )
|
||||
|
||||
attribute ( 2.5.4.25 NAME 'internationaliSDNNumber' EQUALITY numericStringMatch
|
||||
SUBSTR numericStringSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{16} )
|
||||
|
||||
attribute ( 2.5.4.26 NAME 'registeredAddress' SUP postalAddress
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
|
||||
|
||||
attribute ( 2.5.4.27 NAME 'destinationIndicator' EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{128} )
|
||||
|
||||
attribute ( 2.5.4.28 NAME 'preferredDeliveryMethod'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.14
|
||||
SINGLE-VALUE )
|
||||
|
||||
attribute ( 2.5.4.29 NAME 'presentationAddress'
|
||||
EQUALITY presentationAddressMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.43
|
||||
SINGLE-VALUE )
|
||||
|
||||
attribute ( 2.5.4.30 NAME 'supportedApplicationContext'
|
||||
EQUALITY objectIdentifierMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
|
||||
|
||||
# Placed here because others derive from it
|
||||
# We had a dn definition in slapd.at.conf and Netscape lists both
|
||||
# names for that OID
|
||||
|
||||
attribute ( 2.5.4.49 NAME ( 'distinguishedName' 'dn' )
|
||||
EQUALITY distinguishedNameMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
|
||||
|
||||
attribute ( 2.5.4.31 NAME 'member' SUP distinguishedName )
|
||||
|
||||
attribute ( 2.5.4.32 NAME 'owner' SUP distinguishedName )
|
||||
|
||||
attribute ( 2.5.4.33 NAME 'roleOccupant' SUP distinguishedName )
|
||||
|
||||
attribute ( 2.5.4.34 NAME 'seeAlso' SUP distinguishedName )
|
||||
|
||||
attribute ( 2.5.4.35 NAME 'userPassword' EQUALITY octetStringMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
|
||||
|
||||
# Must be stored and requested in the binary form, as
|
||||
# userCertificate;binary
|
||||
|
||||
attribute ( 2.5.4.36 NAME 'userCertificate'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
|
||||
|
||||
# As above
|
||||
|
||||
attribute ( 2.5.4.37 NAME 'cACertificate'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
|
||||
|
||||
# As above
|
||||
|
||||
attribute ( 2.5.4.38 NAME 'authorityRevocationList'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
|
||||
|
||||
# As above
|
||||
|
||||
attribute ( 2.5.4.39 NAME 'certificateRevocationList'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
|
||||
|
||||
# As above
|
||||
|
||||
attribute ( 2.5.4.40 NAME 'crossCertificatePair'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.10 )
|
||||
|
||||
# 2.5.4.41 is 'name', moved above since other attribute types derive from it
|
||||
|
||||
attribute ( 2.5.4.42 NAME 'givenName' SUP name )
|
||||
|
||||
attribute ( 2.5.4.43 NAME 'initials' SUP name )
|
||||
|
||||
attribute ( 2.5.4.45 NAME 'x500UniqueIdentifier' EQUALITY bitStringMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )
|
||||
|
||||
attribute ( 2.5.4.46 NAME 'dnQualifier' EQUALITY caseIgnoreMatch
|
||||
ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )
|
||||
|
||||
attribute ( 2.5.4.47 NAME 'enhancedSearchGuide'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.21 )
|
||||
|
||||
attribute ( 2.5.4.48 NAME 'protocolInformation'
|
||||
EQUALITY protocolInformationMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )
|
||||
|
||||
# 2.5.4.49 is distinguishedName, moved up
|
||||
|
||||
attribute ( 2.5.4.50 NAME 'uniqueMember' EQUALITY uniqueMemberMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )
|
||||
|
||||
attribute ( 2.5.4.51 NAME 'houseIdentifier' EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
|
||||
|
||||
# This attribute is to be stored and requested in the binary form, as
|
||||
# 'supportedAlgorithms;binary'.
|
||||
|
||||
attribute ( 2.5.4.52 NAME 'supportedAlgorithms'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.49 )
|
||||
|
||||
# This attribute is to be stored and requested in the binary form, as
|
||||
# 'deltaRevocationList;binary'.
|
||||
|
||||
attribute ( 2.5.4.53 NAME 'deltaRevocationList'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
|
||||
|
||||
attribute ( 2.5.4.54 NAME 'dmdName' SUP name )
|
||||
|
||||
# Standard object classes from RFC2256
|
||||
|
||||
objectclass ( 2.5.6.0 NAME 'top' ABSTRACT MUST objectClass )
|
||||
|
||||
objectclass ( 2.5.6.1 NAME 'alias' SUP top STRUCTURAL MUST aliasedObjectName )
|
||||
|
||||
objectclass ( 2.5.6.2 NAME 'country' SUP top STRUCTURAL MUST c
|
||||
MAY ( searchGuide $ description ) )
|
||||
|
||||
objectclass ( 2.5.6.3 NAME 'locality' SUP top STRUCTURAL
|
||||
MAY ( street $ seeAlso $ searchGuide $ st $ l $ description ) )
|
||||
|
||||
objectclass ( 2.5.6.4 NAME 'organization' SUP top STRUCTURAL MUST o
|
||||
MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
|
||||
x121Address $ registeredAddress $ destinationIndicator $
|
||||
preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
|
||||
telephoneNumber $ internationaliSDNNumber $
|
||||
facsimileTelephoneNumber $
|
||||
street $ postOfficeBox $ postalCode $ postalAddress $
|
||||
physicalDeliveryOfficeName $ st $ l $ description ) )
|
||||
|
||||
objectclass ( 2.5.6.5 NAME 'organizationalUnit' SUP top STRUCTURAL MUST ou
|
||||
MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
|
||||
x121Address $ registeredAddress $ destinationIndicator $
|
||||
preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
|
||||
telephoneNumber $ internationaliSDNNumber $
|
||||
facsimileTelephoneNumber $
|
||||
street $ postOfficeBox $ postalCode $ postalAddress $
|
||||
physicalDeliveryOfficeName $ st $ l $ description ) )
|
||||
|
||||
objectclass ( 2.5.6.6 NAME 'person' SUP top STRUCTURAL MUST ( sn $ cn )
|
||||
MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
|
||||
|
||||
objectclass ( 2.5.6.7 NAME 'organizationalPerson' SUP person STRUCTURAL
|
||||
MAY ( title $ x121Address $ registeredAddress $
|
||||
destinationIndicator $
|
||||
preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
|
||||
telephoneNumber $ internationaliSDNNumber $
|
||||
facsimileTelephoneNumber $
|
||||
street $ postOfficeBox $ postalCode $ postalAddress $
|
||||
physicalDeliveryOfficeName $ ou $ st $ l ) )
|
||||
|
||||
# Notice that preferredDeliveryMethod is duplicate
|
||||
|
||||
objectclass ( 2.5.6.8 NAME 'organizationalRole' SUP top STRUCTURAL MUST cn
|
||||
MAY ( x121Address $ registeredAddress $ destinationIndicator $
|
||||
preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
|
||||
telephoneNumber $ internationaliSDNNumber $
|
||||
facsimileTelephoneNumber $
|
||||
seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $
|
||||
postOfficeBox $ postalCode $ postalAddress $
|
||||
physicalDeliveryOfficeName $ ou $ st $ l $ description ) )
|
||||
|
||||
objectclass ( 2.5.6.9 NAME 'groupOfNames' SUP top STRUCTURAL MUST ( member $ cn )
|
||||
MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
|
||||
|
||||
# Notice that preferredDeliveryMethod is duplicate
|
||||
# It seems they could not agree on wheter telephoneNumber is MAY
|
||||
# in person. Probably it wasn't originally at was added as an
|
||||
# afterthought
|
||||
|
||||
objectclass ( 2.5.6.10 NAME 'residentialPerson' SUP person STRUCTURAL MUST l
|
||||
MAY ( businessCategory $ x121Address $ registeredAddress $
|
||||
destinationIndicator $ preferredDeliveryMethod $ telexNumber $
|
||||
teletexTerminalIdentifier $ telephoneNumber $
|
||||
internationaliSDNNumber $
|
||||
facsimileTelephoneNumber $ preferredDeliveryMethod $ street $
|
||||
postOfficeBox $ postalCode $ postalAddress $
|
||||
physicalDeliveryOfficeName $ st $ l ) )
|
||||
|
||||
objectclass ( 2.5.6.11 NAME 'applicationProcess' SUP top STRUCTURAL MUST cn
|
||||
MAY ( seeAlso $ ou $ l $ description ) )
|
||||
|
||||
objectclass ( 2.5.6.12 NAME 'applicationEntity' SUP top STRUCTURAL
|
||||
MUST ( presentationAddress $ cn )
|
||||
MAY ( supportedApplicationContext $ seeAlso $ ou $ o $ l $
|
||||
description ) )
|
||||
|
||||
# This one was wrong in our schema, it only allowed the aditional
|
||||
# knowledgeInformation attribute, while it is derived from
|
||||
# applicationEntity and should allow all its attributes as well.
|
||||
|
||||
objectclass ( 2.5.6.13 NAME 'dSA' SUP applicationEntity STRUCTURAL
|
||||
MAY knowledgeInformation )
|
||||
|
||||
objectclass ( 2.5.6.14 NAME 'device' SUP top STRUCTURAL MUST cn
|
||||
MAY ( serialNumber $ seeAlso $ owner $ ou $ o $ l $ description ) )
|
||||
|
||||
objectclass ( 2.5.6.15 NAME 'strongAuthenticationUser' SUP top AUXILIARY
|
||||
MUST userCertificate )
|
||||
|
||||
objectclass ( 2.5.6.16 NAME 'certificationAuthority' SUP top AUXILIARY
|
||||
MUST ( authorityRevocationList $ certificateRevocationList $
|
||||
cACertificate ) MAY crossCertificatePair )
|
||||
|
||||
# New
|
||||
|
||||
objectclass ( 2.5.6.17 NAME 'groupOfUniqueNames' SUP top STRUCTURAL
|
||||
MUST ( uniqueMember $ cn )
|
||||
MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
|
||||
|
||||
# New
|
||||
|
||||
objectclass ( 2.5.6.18 NAME 'userSecurityInformation' SUP top AUXILIARY
|
||||
MAY ( supportedAlgorithms ) )
|
||||
|
||||
# New
|
||||
|
||||
objectclass ( 2.5.6.16.2 NAME 'certificationAuthority-V2' SUP
|
||||
certificationAuthority
|
||||
AUXILIARY MAY ( deltaRevocationList ) )
|
||||
|
||||
# New
|
||||
|
||||
objectclass ( 2.5.6.19 NAME 'cRLDistributionPoint' SUP top STRUCTURAL
|
||||
MUST ( cn ) MAY ( certificateRevocationList $
|
||||
authorityRevocationList $
|
||||
deltaRevocationList ) )
|
||||
|
||||
# New
|
||||
|
||||
objectclass ( 2.5.6.20 NAME 'dmd' SUP top STRUCTURAL MUST ( dmdName )
|
||||
MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
|
||||
x121Address $ registeredAddress $ destinationIndicator $
|
||||
preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
|
||||
telephoneNumber $ internationaliSDNNumber $
|
||||
facsimileTelephoneNumber $
|
||||
street $ postOfficeBox $ postalCode $ postalAddress $
|
||||
physicalDeliveryOfficeName $ st $ l $ description ) )
|
||||
|
||||
# Next objectclass is defined in RFC2252, but has to be put after top
|
||||
|
||||
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 ) )
|
||||
|
|
@ -10,33 +10,42 @@
|
|||
* is provided ``as is'' without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <ac/string.h>
|
||||
#include <ac/socket.h>
|
||||
|
||||
#include "ldap_defaults.h"
|
||||
#include "slap.h"
|
||||
#include "ldapconfig.h"
|
||||
|
||||
extern int get_filter();
|
||||
extern Backend *select_backend();
|
||||
|
||||
extern char *default_referral;
|
||||
|
||||
void
|
||||
do_search( conn, op )
|
||||
Connection *conn; /* where to send results */
|
||||
Operation *op; /* info about the op to which we're responding */
|
||||
int
|
||||
do_search(
|
||||
Connection *conn, /* where to send results */
|
||||
Operation *op /* info about the op to which we're responding */
|
||||
)
|
||||
{
|
||||
int i, err;
|
||||
int scope, deref, attrsonly;
|
||||
int sizelimit, timelimit;
|
||||
char *base, *fstr;
|
||||
Filter *filter;
|
||||
char **attrs;
|
||||
ber_int_t scope, deref, attrsonly;
|
||||
ber_int_t sizelimit, timelimit;
|
||||
char *base = NULL, *fstr = NULL;
|
||||
Filter *filter = NULL;
|
||||
char **attrs = NULL;
|
||||
Backend *be;
|
||||
int rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
|
||||
|
||||
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", NULL );
|
||||
return LDAP_SASL_BIND_IN_PROGRESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the search request. It looks like this:
|
||||
*
|
||||
|
|
@ -62,52 +71,67 @@ do_search( conn, op )
|
|||
*/
|
||||
|
||||
/* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */
|
||||
if ( ber_scanf( op->o_ber, "{aiiiib", &base, &scope, &deref, &sizelimit,
|
||||
if ( ber_scanf( op->o_ber, "{aiiiib",
|
||||
&base, &scope, &deref, &sizelimit,
|
||||
&timelimit, &attrsonly ) == LBER_ERROR ) {
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
|
||||
return;
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
rc = -1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
|
||||
&& scope != LDAP_SCOPE_SUBTREE ) {
|
||||
free( base );
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL,
|
||||
"Unknown search scope" );
|
||||
return;
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
rc = -1;
|
||||
goto return_results;
|
||||
}
|
||||
(void) dn_normalize( base );
|
||||
|
||||
(void) dn_normalize_case( base );
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d", base, scope, deref );
|
||||
Debug( LDAP_DEBUG_ARGS, " %d %d %d\n", sizelimit, timelimit,
|
||||
attrsonly);
|
||||
|
||||
/* filter - returns a "normalized" version */
|
||||
filter = NULL;
|
||||
fstr = NULL;
|
||||
if ( (err = get_filter( conn, op->o_ber, &filter, &fstr )) != 0 ) {
|
||||
if ( fstr != NULL ) {
|
||||
free( fstr );
|
||||
if( err == -1 ) {
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decode error" );
|
||||
} else {
|
||||
send_ldap_result( conn, op, err,
|
||||
NULL, "Bad search filter", NULL );
|
||||
}
|
||||
free( base );
|
||||
send_ldap_result( conn, op, err, NULL, "Bad search filter" );
|
||||
return;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, " filter: %s\n", fstr, 0, 0 );
|
||||
|
||||
/* attributes */
|
||||
attrs = NULL;
|
||||
if ( ber_scanf( op->o_ber, "{v}}", &attrs ) == LBER_ERROR ) {
|
||||
free( base );
|
||||
free( fstr );
|
||||
send_ldap_result( conn, op, LDAP_PROTOCOL_ERROR, NULL, "" );
|
||||
return;
|
||||
if ( ber_scanf( op->o_ber, /*{*/ "{v}}", &attrs ) == LBER_ERROR ) {
|
||||
send_ldap_disconnect( conn, op,
|
||||
LDAP_PROTOCOL_ERROR, "decoding error" );
|
||||
rc = -1;
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
|
||||
Debug( LDAP_DEBUG_ANY, "do_search: get_ctrls failed\n", 0, 0, 0 );
|
||||
goto return_results;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, " attrs:", 0, 0, 0 );
|
||||
|
||||
if ( attrs != NULL ) {
|
||||
for ( i = 0; attrs[i] != NULL; i++ ) {
|
||||
attr_normalize( attrs[i] );
|
||||
Debug( LDAP_DEBUG_ARGS, " %s", attrs[i], 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
|
||||
|
||||
Statslog( LDAP_DEBUG_STATS,
|
||||
|
|
@ -117,63 +141,62 @@ do_search( conn, op )
|
|||
#if defined( SLAPD_MONITOR_DN ) || defined( SLAPD_CONFIG_DN ) || defined( SLAPD_SCHEMA_DN )
|
||||
if ( scope == LDAP_SCOPE_BASE ) {
|
||||
#if defined( SLAPD_MONITOR_DN )
|
||||
if ( strcasecmp( base, SLAPD_MONITOR_DN ) == 0 ) {
|
||||
free( base );
|
||||
free( fstr );
|
||||
if ( strcmp( base, SLAPD_MONITOR_DN ) == 0 ) {
|
||||
monitor_info( conn, op );
|
||||
return;
|
||||
goto return_results;
|
||||
}
|
||||
#endif
|
||||
#if defined( SLAPD_CONFIG_DN )
|
||||
if ( strcasecmp( base, SLAPD_CONFIG_DN ) == 0 ) {
|
||||
free( base );
|
||||
free( fstr );
|
||||
if ( strcmp( base, SLAPD_CONFIG_DN ) == 0 ) {
|
||||
config_info( conn, op );
|
||||
return;
|
||||
goto return_results;
|
||||
}
|
||||
#endif
|
||||
#if defined( SLAPD_SCHEMA_DN )
|
||||
if ( strcasecmp( base, SLAPD_SCHEMA_DN ) == 0 ) {
|
||||
free( base );
|
||||
free( fstr );
|
||||
schema_info( conn, op );
|
||||
return;
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* We could be serving multiple database backends. Select the
|
||||
* appropriate one, or send a referral to our "referral server"
|
||||
* if we don't hold it.
|
||||
*/
|
||||
if ( (be = select_backend( base )) == NULL ) {
|
||||
send_ldap_result( conn, op, LDAP_PARTIAL_RESULTS, NULL,
|
||||
default_referral );
|
||||
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
|
||||
NULL, NULL, default_referral );
|
||||
|
||||
free( base );
|
||||
free( fstr );
|
||||
filter_free( filter );
|
||||
if ( attrs != NULL ) {
|
||||
charray_free( attrs );
|
||||
}
|
||||
return;
|
||||
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 != NULL ) {
|
||||
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, LDAP_UNWILLING_TO_PERFORM, NULL,
|
||||
"Function not implemented" );
|
||||
send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
|
||||
NULL, "Function not implemented", NULL );
|
||||
}
|
||||
|
||||
free( base );
|
||||
free( fstr );
|
||||
filter_free( filter );
|
||||
return_results:;
|
||||
if( base != NULL) free( base );
|
||||
if( fstr != NULL) free( fstr );
|
||||
if( filter != NULL) filter_free( filter );
|
||||
if ( attrs != NULL ) {
|
||||
charray_free( attrs );
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
|||
167
servers/slapd/slapd.dsw
Normal file
167
servers/slapd/slapd.dsw
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
Microsoft Developer Studio Workspace File, Format Version 5.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "backldbm"=".\back-ldbm\backldbm.dsp" - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "libavl"=..\..\libraries\libavl\libavl.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "liblber"=..\..\libraries\liblber\liblber.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "libldap_r"=..\..\libraries\libldap_r\libldap_r.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name liblber
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "libldbm"=..\..\libraries\libldbm\libldbm.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "libldif"=..\..\libraries\libldif\libldif.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "liblutil"=..\..\libraries\liblutil\liblutil.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "libslapd"=.\libslapd.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "setup"=..\..\include\setup.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "slapd"=.\slapd.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name libavl
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name liblber
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name libldbm
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name libldif
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name liblutil
|
||||
End Project Dependency
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name libldap_r
|
||||
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 setup
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
64
servers/slapd/tools/mimic.c
Normal file
64
servers/slapd/tools/mimic.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Mimic unused interfaces of slapd...
|
||||
* needed for linking.
|
||||
*/
|
||||
#include "portable.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../slap.h"
|
||||
|
||||
#ifdef WIN32
|
||||
time_t starttime;
|
||||
#endif
|
||||
|
||||
/* bogus ../results.c */
|
||||
int str2result(
|
||||
char* s,
|
||||
int *code,
|
||||
char **matched,
|
||||
char **info )
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
send_ldap_result(
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
int err,
|
||||
char *matched,
|
||||
char *text
|
||||
)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void
|
||||
send_search_result(
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
int err,
|
||||
char *matched,
|
||||
char *text,
|
||||
int nentries
|
||||
)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
int
|
||||
send_search_entry(
|
||||
Backend *be,
|
||||
Connection *conn,
|
||||
Operation *op,
|
||||
Entry *e,
|
||||
char **attrs,
|
||||
int attrsonly,
|
||||
int opattrs
|
||||
)
|
||||
{
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
Loading…
Reference in a new issue