⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 search.c

📁 ldap服务器源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* search.c - ldap backend search function *//* $OpenLDAP: pkg/ldap/servers/slapd/back-ldap/search.c,v 1.148.2.36 2007/01/27 23:56:43 ando Exp $ *//* This work is part of OpenLDAP Software <http://www.openldap.org/>. * * Copyright 1999-2007 The OpenLDAP Foundation. * Portions Copyright 1999-2003 Howard Chu. * Portions Copyright 2000-2003 Pierangelo Masarati. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * <http://www.OpenLDAP.org/license.html>. *//* ACKNOWLEDGEMENTS: * This work was initially developed by the Howard Chu for inclusion * in OpenLDAP Software and subsequently enhanced by Pierangelo * Masarati. */#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"#undef ldap_debug	/* silence a warning in ldap-int.h */#include "../../../libraries/libldap/ldap-int.h"#include "lutil.h"static intldap_build_entry( Operation *op, LDAPMessage *e, Entry *ent,	 struct berval *bdn );/* * Quick'n'dirty rewrite of filter in case of error, to deal with * <draft-zeilenga-ldap-t-f>. */static intldap_back_munge_filter(	Operation	*op,	struct berval	*filter ){	ldapinfo_t	*li = (ldapinfo_t *) op->o_bd->be_private;	char		*ptr;	int		gotit = 0;	Debug( LDAP_DEBUG_ARGS, "=> ldap_back_munge_filter \"%s\"\n",			filter->bv_val, 0, 0 );	for ( ptr = strstr( filter->bv_val, "(?=" ); 			ptr;			ptr = strstr( ptr, "(?=" ) )	{		static struct berval			bv_true = BER_BVC( "(?=true)" ),			bv_false = BER_BVC( "(?=false)" ),			bv_undefined = BER_BVC( "(?=undefined)" ),			bv_t = BER_BVC( "(&)" ),			bv_f = BER_BVC( "(|)" ),			bv_T = BER_BVC( "(objectClass=*)" ),			bv_F = BER_BVC( "(!(objectClass=*))" );		struct berval	*oldbv = NULL,				*newbv = NULL,				oldfilter = BER_BVNULL;		if ( strncmp( ptr, bv_true.bv_val, bv_true.bv_len ) == 0 ) {			oldbv = &bv_true;			if ( LDAP_BACK_T_F( li ) ) {				newbv = &bv_t;			} else {				newbv = &bv_T;			}		} else if ( strncmp( ptr, bv_false.bv_val, bv_false.bv_len ) == 0 )		{			oldbv = &bv_false;			if ( LDAP_BACK_T_F( li ) ) {				newbv = &bv_f;			} else {				newbv = &bv_F;			}		} else if ( strncmp( ptr, bv_undefined.bv_val, bv_undefined.bv_len ) == 0 )		{			oldbv = &bv_undefined;			newbv = &bv_F;		} else {			gotit = 0;			goto done;		}		oldfilter = *filter;		if ( newbv->bv_len > oldbv->bv_len ) {			filter->bv_len += newbv->bv_len - oldbv->bv_len;			if ( filter->bv_val == op->ors_filterstr.bv_val ) {				filter->bv_val = op->o_tmpalloc( filter->bv_len + 1,						op->o_tmpmemctx );				AC_MEMCPY( filter->bv_val, op->ors_filterstr.bv_val,						op->ors_filterstr.bv_len + 1 );			} else {				filter->bv_val = op->o_tmprealloc( filter->bv_val,						filter->bv_len + 1, op->o_tmpmemctx );			}			ptr = filter->bv_val + ( ptr - oldfilter.bv_val );		}		AC_MEMCPY( &ptr[ newbv->bv_len ],				&ptr[ oldbv->bv_len ], 				oldfilter.bv_len - ( ptr - filter->bv_val ) - oldbv->bv_len + 1 );		AC_MEMCPY( ptr, newbv->bv_val, newbv->bv_len );		ptr += newbv->bv_len;		gotit = 1;	}done:;	Debug( LDAP_DEBUG_ARGS, "<= ldap_back_munge_filter \"%s\" (%d)\n",			filter->bv_val, gotit, 0 );	return gotit;}intldap_back_search(		Operation	*op,		SlapReply	*rs ){	ldapinfo_t	*li = (ldapinfo_t *) op->o_bd->be_private;	ldapconn_t	*lc = NULL;	struct timeval	tv;	time_t		stoptime = (time_t)(-1);	LDAPMessage	*res,			*e;	int		rc = 0,			msgid; 	struct berval	match = BER_BVNULL,			filter = BER_BVNULL;	int		free_filter = 0;	int		i;	char		**attrs = NULL;	int		freetext = 0;	int		do_retry = 1, dont_retry = 0;	LDAPControl	**ctrls = NULL;	/* FIXME: shouldn't this be null? */	const char	*save_matched = rs->sr_matched;	if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {		return rs->sr_err;	}	/*	 * FIXME: in case of values return filter, we might want	 * to map attrs and maybe rewrite value	 */	/* should we check return values? */	if ( op->ors_deref != -1 ) {		ldap_set_option( lc->lc_ld, LDAP_OPT_DEREF,				(void *)&op->ors_deref );	}	if ( op->ors_tlimit != SLAP_NO_LIMIT ) {		tv.tv_sec = op->ors_tlimit;		tv.tv_usec = 0;		stoptime = op->o_time + op->ors_tlimit;	} else {		LDAP_BACK_TV_SET( &tv );	}	if ( op->ors_attrs ) {		for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ )			/* just count attrs */ ;		attrs = ch_malloc( ( i + 1 )*sizeof( char * ) );		if ( attrs == NULL ) {			rs->sr_err = LDAP_NO_MEMORY;			rc = -1;			goto finish;		}			for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ ) {			attrs[ i ] = op->ors_attrs[i].an_name.bv_val;		}		attrs[ i ] = NULL;	}	ctrls = op->o_ctrls;	rc = ldap_back_proxy_authz_ctrl( &lc->lc_bound_ndn,		li->li_version, &li->li_idassert, op, rs, &ctrls );	if ( rc != LDAP_SUCCESS ) {		goto finish;	}	/* deal with <draft-zeilenga-ldap-t-f> filters */	filter = op->ors_filterstr;retry:	rs->sr_err = ldap_search_ext( lc->lc_ld, op->o_req_dn.bv_val,			op->ors_scope, filter.bv_val,			attrs, op->ors_attrsonly, ctrls, NULL,			tv.tv_sec ? &tv : NULL,			op->ors_slimit, &msgid );	if ( rs->sr_err != LDAP_SUCCESS ) {		switch ( rs->sr_err ) {		case LDAP_SERVER_DOWN:			if ( do_retry ) {				do_retry = 0;				if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) {					goto retry;				}			}			if ( lc == NULL ) {				/* reset by ldap_back_retry ... */				rs->sr_err = slap_map_api2result( rs );			} else {				rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_DONTSEND );			}							goto finish;		case LDAP_FILTER_ERROR:			if ( ldap_back_munge_filter( op, &filter ) ) {				free_filter = 1;				goto retry;			}			/* invalid filters return success with no data */			rs->sr_err = LDAP_SUCCESS;			rs->sr_text = NULL;			goto finish;				default:			rs->sr_err = slap_map_api2result( rs );			rs->sr_text = NULL;			goto finish;		}	}	/* if needed, initialize timeout */	if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {		if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) {			tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ];			tv.tv_usec = 0;		}	}	/* 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 ( rc = -2; rc != -1; rc = ldap_result( lc->lc_ld, msgid, LDAP_MSG_ONE, &tv, &res ) )	{		/* check for abandon */		if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( lc ) ) {			if ( rc > 0 ) {				ldap_msgfree( res );			}			(void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );			rc = SLAPD_ABANDON;			goto finish;		}		if ( rc == 0 || rc == -2 ) {			ldap_pvt_thread_yield();			/* check timeout */			if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {				if ( rc == 0 ) {					(void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );					rs->sr_text = "Operation timed out";					rc = rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?						LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;					goto finish;				}			} else {				LDAP_BACK_TV_SET( &tv );			}			/* check time limit */			if ( op->ors_tlimit != SLAP_NO_LIMIT					&& slap_get_time() > stoptime )			{				(void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );				rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;				goto finish;			}			continue;		} else {			/* only touch when activity actually took place... */			if ( li->li_idle_timeout && lc ) {				lc->lc_time = op->o_time;			}			/* don't retry any more */			dont_retry = 1;		}		if ( rc == LDAP_RES_SEARCH_ENTRY ) {			Entry		ent = { 0 };			struct berval	bdn = BER_BVNULL;			do_retry = 0;			e = ldap_first_entry( lc->lc_ld, res );			rc = ldap_build_entry( op, e, &ent, &bdn );			if ( rc == LDAP_SUCCESS ) {				rs->sr_entry = &ent;				rs->sr_attrs = op->ors_attrs;				rs->sr_operational_attrs = NULL;				rs->sr_flags = 0;				rs->sr_err = LDAP_SUCCESS;				rc = rs->sr_err = send_search_entry( op, rs );				if ( !BER_BVISNULL( &ent.e_name ) ) {					assert( ent.e_name.bv_val != bdn.bv_val );					op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx );					BER_BVZERO( &ent.e_name );				}				if ( !BER_BVISNULL( &ent.e_nname ) ) {					op->o_tmpfree( ent.e_nname.bv_val, op->o_tmpmemctx );					BER_BVZERO( &ent.e_nname );				}				entry_clean( &ent );			}			ldap_msgfree( res );			if ( rc != LDAP_SUCCESS ) {				if ( rc == LDAP_UNAVAILABLE ) {					rc = rs->sr_err = LDAP_OTHER;				} else {					(void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );				}				goto finish;			}		} else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {			char		**references = NULL;			do_retry = 0;			rc = ldap_parse_reference( lc->lc_ld, res,					&references, &rs->sr_ctrls, 1 );			if ( rc != LDAP_SUCCESS ) {				continue;			}			/* FIXME: there MUST be at least one */			if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) {				int		cnt;				for ( cnt = 0; references[ cnt ]; cnt++ )					/* NO OP */ ;				/* FIXME: there MUST be at least one */				rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),					op->o_tmpmemctx );				for ( cnt = 0; references[ cnt ]; cnt++ ) {					ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );				}				BER_BVZERO( &rs->sr_ref[ cnt ] );				/* ignore return value by now */				( void )send_search_reference( op, rs );			} else {				Debug( LDAP_DEBUG_ANY,					"%s ldap_back_search: "					"got SEARCH_REFERENCE "					"with no referrals\n",					op->o_log_prefix, 0, 0 );			}			/* cleanup */			if ( references ) {				ber_memvfree( (void **)references );				op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );				rs->sr_ref = NULL;			}			if ( rs->sr_ctrls ) {				ldap_controls_free( rs->sr_ctrls );				rs->sr_ctrls = NULL;			}		} else {			char		**references = NULL, *err = NULL;			rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,					&match.bv_val, &err,					&references, &rs->sr_ctrls, 1 );			if ( rc != LDAP_SUCCESS ) {				rs->sr_err = rc;			}			rs->sr_err = slap_map_api2result( rs );			if ( err ) {				rs->sr_text = err;				freetext = 1;			}			if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) {				int	cnt;				if ( rs->sr_err != LDAP_REFERRAL ) {					/* FIXME: error */					Debug( LDAP_DEBUG_ANY,						"%s ldap_back_search: "						"got referrals with %d\n",						op->o_log_prefix,						rs->sr_err, 0 );					rs->sr_err = LDAP_REFERRAL;				}				for ( cnt = 0; references[ cnt ]; cnt++ )					/* NO OP */ ;				

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -