mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
82fad7d0c8
Includes rewriting of URLs where the DN of the referral object and the DN of the ref attribute attribute are not the same. Also, always returns explicit DN and scope. Currently, back-ldbm only. Needs to be ported to back-bdb.
318 lines
7.9 KiB
C
318 lines
7.9 KiB
C
/* $OpenLDAP$ */
|
|
/*
|
|
* Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
|
|
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
|
|
*/
|
|
/* Portions
|
|
* Copyright (c) 1995 Regents of the University of Michigan.
|
|
* 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 the University of Michigan at Ann Arbor. The name of the University
|
|
* 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 "ldap_pvt.h"
|
|
#include "slap.h"
|
|
|
|
int
|
|
do_search(
|
|
Connection *conn, /* where to send results */
|
|
Operation *op /* info about the op to which we're responding */
|
|
) {
|
|
int i;
|
|
ber_int_t scope, deref, attrsonly;
|
|
ber_int_t sizelimit, timelimit;
|
|
char *base = NULL, *nbase = NULL, *fstr = NULL;
|
|
Filter *filter = NULL;
|
|
char **attrs = NULL;
|
|
Backend *be;
|
|
int rc;
|
|
const char *text;
|
|
int manageDSAit;
|
|
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
|
|
"do_search: conn %d\n", conn->c_connid ));
|
|
#else
|
|
Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
|
|
#endif
|
|
|
|
/*
|
|
* Parse the search request. It looks like this:
|
|
*
|
|
* SearchRequest := [APPLICATION 3] SEQUENCE {
|
|
* baseObject DistinguishedName,
|
|
* scope ENUMERATED {
|
|
* baseObject (0),
|
|
* singleLevel (1),
|
|
* wholeSubtree (2)
|
|
* },
|
|
* derefAliases ENUMERATED {
|
|
* neverDerefaliases (0),
|
|
* derefInSearching (1),
|
|
* derefFindingBaseObj (2),
|
|
* alwaysDerefAliases (3)
|
|
* },
|
|
* sizelimit INTEGER (0 .. 65535),
|
|
* timelimit INTEGER (0 .. 65535),
|
|
* attrsOnly BOOLEAN,
|
|
* filter Filter,
|
|
* attributes SEQUENCE OF AttributeType
|
|
* }
|
|
*/
|
|
|
|
/* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */
|
|
if ( ber_scanf( op->o_ber, "{aiiiib" /*}*/,
|
|
&base, &scope, &deref, &sizelimit,
|
|
&timelimit, &attrsonly ) == LBER_ERROR ) {
|
|
send_ldap_disconnect( conn, op,
|
|
LDAP_PROTOCOL_ERROR, "decoding error" );
|
|
rc = SLAPD_DISCONNECT;
|
|
goto return_results;
|
|
}
|
|
|
|
switch( scope ) {
|
|
case LDAP_SCOPE_BASE:
|
|
case LDAP_SCOPE_ONELEVEL:
|
|
case LDAP_SCOPE_SUBTREE:
|
|
break;
|
|
default:
|
|
send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
|
|
NULL, "invalid scope", NULL, NULL );
|
|
goto return_results;
|
|
}
|
|
|
|
switch( deref ) {
|
|
case LDAP_DEREF_NEVER:
|
|
case LDAP_DEREF_FINDING:
|
|
case LDAP_DEREF_SEARCHING:
|
|
case LDAP_DEREF_ALWAYS:
|
|
break;
|
|
default:
|
|
send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
|
|
NULL, "invalid deref", NULL, NULL );
|
|
goto return_results;
|
|
}
|
|
|
|
nbase = ch_strdup( base );
|
|
|
|
if( dn_normalize( nbase ) == NULL ) {
|
|
send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX,
|
|
NULL, "invalid DN", NULL, NULL );
|
|
goto return_results;
|
|
}
|
|
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG(( "operation", LDAP_LEVEL_ARGS,
|
|
"do_search \"%s\" %d %d %d %d %d\n", base, scope,
|
|
deref, sizelimit, timelimit, attrsonly ));
|
|
#else
|
|
Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d", base, scope, deref );
|
|
Debug( LDAP_DEBUG_ARGS, " %d %d %d\n", sizelimit, timelimit,
|
|
attrsonly);
|
|
#endif
|
|
|
|
/* filter - returns a "normalized" version */
|
|
rc = get_filter( conn, op->o_ber, &filter, &fstr, &text );
|
|
if( rc != LDAP_SUCCESS ) {
|
|
if( rc == SLAPD_DISCONNECT ) {
|
|
send_ldap_disconnect( conn, op,
|
|
LDAP_PROTOCOL_ERROR, text );
|
|
} else {
|
|
send_ldap_result( conn, op, rc,
|
|
NULL, text, NULL, NULL );
|
|
}
|
|
goto return_results;
|
|
}
|
|
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG(( "operation", LDAP_LEVEL_ARGS,
|
|
"do_search: conn %d filter: %s\n", conn->c_connid, fstr ));
|
|
#else
|
|
Debug( LDAP_DEBUG_ARGS, " filter: %s\n", fstr, 0, 0 );
|
|
#endif
|
|
|
|
|
|
/* attributes */
|
|
if ( ber_scanf( op->o_ber, /*{*/ "{v}}", &attrs ) == LBER_ERROR ) {
|
|
send_ldap_disconnect( conn, op,
|
|
LDAP_PROTOCOL_ERROR, "decoding attrs error" );
|
|
rc = SLAPD_DISCONNECT;
|
|
goto return_results;
|
|
}
|
|
|
|
if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
|
|
"do_search: conn %d get_ctrls failed (%d)\n",
|
|
conn->c_connid, rc ));
|
|
#else
|
|
Debug( LDAP_DEBUG_ANY, "do_search: get_ctrls failed\n", 0, 0, 0 );
|
|
#endif
|
|
|
|
goto return_results;
|
|
}
|
|
|
|
rc = LDAP_SUCCESS;
|
|
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG(( "operation", LDAP_LEVEL_ARGS,
|
|
"do_search: conn %d attrs:", conn->c_connid ));
|
|
#else
|
|
Debug( LDAP_DEBUG_ARGS, " attrs:", 0, 0, 0 );
|
|
#endif
|
|
|
|
|
|
if ( attrs != NULL ) {
|
|
for ( i = 0; attrs[i] != NULL; i++ ) {
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG(( "operation", LDAP_LEVEL_ARGS,
|
|
"do_search: %s", attrs[i] ));
|
|
#else
|
|
Debug( LDAP_DEBUG_ARGS, " %s", attrs[i], 0, 0 );
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG(( "operation", LDAP_LEVEL_ARGS, "\n" ));
|
|
#else
|
|
Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
|
|
#endif
|
|
|
|
Statslog( LDAP_DEBUG_STATS,
|
|
"conn=%ld op=%d SRCH base=\"%s\" scope=%d filter=\"%s\"\n",
|
|
op->o_connid, op->o_opid, base, scope, fstr );
|
|
|
|
manageDSAit = get_manageDSAit( op );
|
|
|
|
if ( scope == LDAP_SCOPE_BASE ) {
|
|
Entry *entry = NULL;
|
|
|
|
if ( strcasecmp( nbase, LDAP_ROOT_DSE ) == 0 ) {
|
|
#ifdef LDAP_CONNECTIONLESS
|
|
/* Ignore LDAPv2 CLDAP DSE queries */
|
|
if (op->o_protocol==LDAP_VERSION2 && conn->c_is_udp) {
|
|
goto return_results;
|
|
}
|
|
#endif
|
|
/* check restrictions */
|
|
rc = backend_check_restrictions( NULL, conn, op, NULL, &text ) ;
|
|
if( rc != LDAP_SUCCESS ) {
|
|
send_ldap_result( conn, op, rc,
|
|
NULL, text, NULL, NULL );
|
|
goto return_results;
|
|
}
|
|
|
|
rc = root_dse_info( conn, &entry, &text );
|
|
}
|
|
|
|
#if defined( SLAPD_SCHEMA_DN )
|
|
else if ( strcasecmp( nbase, SLAPD_SCHEMA_DN ) == 0 ) {
|
|
/* check restrictions */
|
|
rc = backend_check_restrictions( NULL, conn, op, NULL, &text ) ;
|
|
if( rc != LDAP_SUCCESS ) {
|
|
send_ldap_result( conn, op, rc,
|
|
NULL, text, NULL, NULL );
|
|
goto return_results;
|
|
}
|
|
|
|
rc = schema_info( &entry, &text );
|
|
}
|
|
#endif
|
|
|
|
if( rc != LDAP_SUCCESS ) {
|
|
send_ldap_result( conn, op, rc,
|
|
NULL, text, NULL, NULL );
|
|
goto return_results;
|
|
|
|
} else if ( entry != NULL ) {
|
|
rc = test_filter( NULL, conn, op,
|
|
entry, filter );
|
|
|
|
if( rc == LDAP_COMPARE_TRUE ) {
|
|
send_search_entry( &backends[0], conn, op,
|
|
entry, attrs, attrsonly, NULL );
|
|
}
|
|
entry_free( entry );
|
|
|
|
send_ldap_result( conn, op, LDAP_SUCCESS,
|
|
NULL, NULL, NULL, NULL );
|
|
|
|
goto return_results;
|
|
}
|
|
}
|
|
|
|
if( nbase[0] == '\0' && default_search_nbase != NULL ) {
|
|
ch_free( base );
|
|
ch_free( nbase );
|
|
base = ch_strdup( default_search_base );
|
|
nbase = ch_strdup( default_search_nbase );
|
|
}
|
|
|
|
/*
|
|
* 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( nbase, manageDSAit )) == NULL ) {
|
|
struct berval **ref = referral_rewrite( default_referral,
|
|
NULL, base, scope );
|
|
|
|
send_ldap_result( conn, op, rc = LDAP_REFERRAL,
|
|
NULL, NULL, ref ? ref : default_referral, NULL );
|
|
|
|
ber_bvecfree( ref );
|
|
goto return_results;
|
|
}
|
|
|
|
/* check restrictions */
|
|
rc = backend_check_restrictions( be, conn, op, NULL, &text ) ;
|
|
if( rc != LDAP_SUCCESS ) {
|
|
send_ldap_result( conn, op, rc,
|
|
NULL, text, NULL, NULL );
|
|
goto return_results;
|
|
}
|
|
|
|
/* check for referrals */
|
|
rc = backend_check_referrals( be, conn, op, base, nbase );
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
goto return_results;
|
|
}
|
|
|
|
/* deref the base if needed */
|
|
nbase = suffix_alias( be, nbase );
|
|
|
|
/* actually do the search and send the result(s) */
|
|
if ( be->be_search ) {
|
|
(*be->be_search)( be, conn, op, base, nbase, scope, deref, sizelimit,
|
|
timelimit, filter, fstr, attrs, attrsonly );
|
|
} else {
|
|
send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
|
|
NULL, "operation not supported within namingContext", NULL, NULL );
|
|
}
|
|
|
|
return_results:;
|
|
if( base != NULL) free( base );
|
|
if( nbase != NULL) free( nbase );
|
|
if( fstr != NULL) free( fstr );
|
|
if( filter != NULL) filter_free( filter );
|
|
if ( attrs != NULL ) {
|
|
charray_free( attrs );
|
|
}
|
|
|
|
return rc;
|
|
}
|