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

📄 search.c

📁 OpenLdap是LDAP的开源项目
💻 C
📖 第 1 页 / 共 4 页
字号:
		for ( i = 0; i < mi->mi_ntargets; i++ ) {			if ( META_IS_CANDIDATE( &candidates[ i ] )					&& candidates[ i ].sr_matched != NULL )			{				struct berval	bv, pbv;				int		rc;				/* if we got success, and this target				 * returned noSuchObject, and its suffix				 * is a superior of the searchBase,				 * ignore the matchedDN */				if ( sres == LDAP_SUCCESS					&& candidates[ i ].sr_err == LDAP_NO_SUCH_OBJECT					&& op->o_req_ndn.bv_len > mi->mi_targets[ i ]->mt_nsuffix.bv_len )				{					free( (char *)candidates[ i ].sr_matched );					candidates[ i ].sr_matched = NULL;					continue;				}				ber_str2bv( candidates[ i ].sr_matched, 0, 0, &bv );				rc = dnPretty( NULL, &bv, &pbv, op->o_tmpmemctx );				if ( rc == LDAP_SUCCESS ) {					/* NOTE: if they all are superiors					 * of the baseDN, the shorter is also 					 * superior of the longer... */					if ( pbv.bv_len > pmatched.bv_len ) {						if ( !BER_BVISNULL( &pmatched ) ) {							op->o_tmpfree( pmatched.bv_val, op->o_tmpmemctx );						}						pmatched = pbv;						op->o_private = (void *)i;					} else {						op->o_tmpfree( pbv.bv_val, op->o_tmpmemctx );					}				}				if ( candidates[ i ].sr_matched != NULL ) {					free( (char *)candidates[ i ].sr_matched );					candidates[ i ].sr_matched = NULL;				}			}		}		if ( !BER_BVISNULL( &pmatched ) ) {			matched = pmatched.bv_val;		}	} else if ( sres == LDAP_NO_SUCH_OBJECT ) {		matched = op->o_bd->be_suffix[ 0 ].bv_val;	}	/*	 * In case we returned at least one entry, we return LDAP_SUCCESS	 * otherwise, the latter error code we got	 */	if ( sres == LDAP_SUCCESS ) {		if ( rs->sr_v2ref ) {			sres = LDAP_REFERRAL;		}		if ( META_BACK_ONERR_REPORT( mi ) ) {			/*			 * Report errors, if any			 *			 * FIXME: we should handle error codes and return the more 			 * important/reasonable			 */			for ( i = 0; i < mi->mi_ntargets; i++ ) {				if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {					continue;				}				if ( candidates[ i ].sr_err != LDAP_SUCCESS					&& candidates[ i ].sr_err != LDAP_NO_SUCH_OBJECT )				{					sres = candidates[ i ].sr_err;					break;				}			}		}	}	rs->sr_err = sres;	rs->sr_matched = matched;	rs->sr_ref = ( sres == LDAP_REFERRAL ? rs->sr_v2ref : NULL );	send_ldap_result( op, rs );	op->o_private = savepriv;	rs->sr_matched = NULL;	rs->sr_ref = NULL;finish:;	if ( matched && matched != op->o_bd->be_suffix[ 0 ].bv_val ) {		op->o_tmpfree( matched, op->o_tmpmemctx );	}	if ( rs->sr_v2ref ) {		ber_bvarray_free( rs->sr_v2ref );	}	for ( i = 0; i < mi->mi_ntargets; i++ ) {		if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {			continue;		}		if ( mc && META_IS_BINDING( &candidates[ i ] ) ) {			ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );			if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) {				assert( candidates[ i ].sr_msgid >= 0 );				assert( mc->mc_conns[ i ].msc_ld != NULL );#ifdef DEBUG_205				Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(cleanup) "					"ldap_unbind_ext[%ld] ld=%p\n",					op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld );#endif /* DEBUG_205 */				/* if still binding, destroy */				meta_clear_one_candidate( op, mc, i );			}			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );			META_BINDING_CLEAR( &candidates[ i ] );		}		if ( candidates[ i ].sr_matched ) {			free( (char *)candidates[ i ].sr_matched );			candidates[ i ].sr_matched = NULL;		}		if ( candidates[ i ].sr_text ) {			ldap_memfree( (char *)candidates[ i ].sr_text );			candidates[ i ].sr_text = NULL;		}		if ( candidates[ i ].sr_ref ) {			ber_bvarray_free( candidates[ i ].sr_ref );			candidates[ i ].sr_ref = NULL;		}		if ( candidates[ i ].sr_ctrls ) {			ldap_controls_free( candidates[ i ].sr_ctrls );			candidates[ i ].sr_ctrls = NULL;		}		if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ i ] ) ) {			meta_back_quarantine( op, &candidates[ i ], i );		}		/* only in case of timelimit exceeded, if the timelimit exceeded because		 * one contacted target never responded, invalidate the connection		 * NOTE: should we quarantine the target as well?  right now, the connection		 * is invalidated; the next time it will be recreated and the target		 * will be quarantined if it cannot be contacted */		if ( mi->mi_idle_timeout != 0			&& rs->sr_err == LDAP_TIMELIMIT_EXCEEDED			&& op->o_time > mc->mc_conns[ i ].msc_time )		{			/* don't let anyone else use this expired connection */			LDAP_BACK_CONN_TAINTED_SET( mc );		}	}	if ( mc ) {		meta_back_release_conn( mi, mc );	}	return rs->sr_err;}static intmeta_send_entry(	Operation 	*op,	SlapReply	*rs,	metaconn_t	*mc,	int 		target,	LDAPMessage 	*e ){	metainfo_t 		*mi = ( metainfo_t * )op->o_bd->be_private;	struct berval		a, mapped;	int			check_duplicate_attrs = 0;	Entry 			ent = { 0 };	BerElement 		ber = *e->lm_ber;	Attribute 		*attr, **attrp;	struct berval 		bdn,				dn = BER_BVNULL;	const char 		*text;	dncookie		dc;	int			rc;	if ( ber_scanf( &ber, "{m{", &bdn ) == LBER_ERROR ) {		return LDAP_DECODING_ERROR;	}	/*	 * Rewrite the dn of the result, if needed	 */	dc.target = mi->mi_targets[ target ];	dc.conn = op->o_conn;	dc.rs = rs;	dc.ctx = "searchResult";	rs->sr_err = ldap_back_dn_massage( &dc, &bdn, &dn );	if ( rs->sr_err != LDAP_SUCCESS) {		return rs->sr_err;	}	/*	 * Note: this may fail if the target host(s) schema differs	 * from the one known to the meta, and a DN with unknown	 * attributes is returned.	 * 	 * FIXME: should we log anything, or delegate to dnNormalize?	 */	rc = dnPrettyNormal( NULL, &dn, &ent.e_name, &ent.e_nname,		op->o_tmpmemctx );	if ( dn.bv_val != bdn.bv_val ) {		free( dn.bv_val );	}	BER_BVZERO( &dn );	if ( rc != LDAP_SUCCESS ) {		return LDAP_INVALID_DN_SYNTAX;	}	/*	 * cache dn	 */	if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) {		( void )meta_dncache_update_entry( &mi->mi_cache,				&ent.e_nname, target );	}	attrp = &ent.e_attrs;	dc.ctx = "searchAttrDN";	while ( ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) {		int				last = 0;		slap_syntax_validate_func	*validate;		slap_syntax_transform_func	*pretty;		ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_at, 				&a, &mapped, BACKLDAP_REMAP );		if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0' ) {			( void )ber_scanf( &ber, "x" /* [W] */ );			continue;		}		if ( mapped.bv_val != a.bv_val ) {			/* will need to check for duplicate attrs */			check_duplicate_attrs++;		}		attr = ( Attribute * )ch_calloc( 1, sizeof( Attribute ) );		if ( attr == NULL ) {			continue;		}		if ( slap_bv2ad( &mapped, &attr->a_desc, &text )				!= LDAP_SUCCESS) {			if ( slap_bv2undef_ad( &mapped, &attr->a_desc, &text,				SLAP_AD_PROXIED ) != LDAP_SUCCESS )			{				char	buf[ SLAP_TEXT_BUFLEN ];				snprintf( buf, sizeof( buf ),					"%s meta_send_entry(\"%s\"): "					"slap_bv2undef_ad(%s): %s\n",					op->o_log_prefix, ent.e_name.bv_val,					mapped.bv_val, text );				Debug( LDAP_DEBUG_ANY, "%s", buf, 0, 0 );				ch_free( attr );				continue;			}		}		/* no subschemaSubentry */		if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry			|| attr->a_desc == slap_schema.si_ad_entryDN )		{			/* 			 * We eat target's subschemaSubentry because			 * a search for this value is likely not			 * to resolve to the appropriate backend;			 * later, the local subschemaSubentry is			 * added.			 *			 * We also eat entryDN because the frontend			 * will reattach it without checking if already			 * present...			 */			( void )ber_scanf( &ber, "x" /* [W] */ );			ch_free(attr);			continue;		}		if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR 				|| attr->a_vals == NULL )		{			attr->a_vals = (struct berval *)&slap_dummy_bv;		} else {			for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); ++last )				;		}		validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;		pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty;		if ( !validate && !pretty ) {			attr_free( attr );			goto next_attr;		}		if ( attr->a_desc == slap_schema.si_ad_objectClass				|| attr->a_desc == slap_schema.si_ad_structuralObjectClass )		{			struct berval 	*bv;			for ( bv = attr->a_vals; !BER_BVISNULL( bv ); bv++ ) {				ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_oc,						bv, &mapped, BACKLDAP_REMAP );				if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0') {remove_oc:;					free( bv->bv_val );					BER_BVZERO( bv );					if ( --last < 0 ) {						break;					}					*bv = attr->a_vals[ last ];					BER_BVZERO( &attr->a_vals[ last ] );					bv--;				} else if ( mapped.bv_val != bv->bv_val ) {					int	i;					for ( i = 0; !BER_BVISNULL( &attr->a_vals[ i ] ); i++ ) {						if ( &attr->a_vals[ i ] == bv ) {							continue;						}						if ( ber_bvstrcasecmp( &mapped, &attr->a_vals[ i ] ) == 0 ) {							break;						}					}					if ( !BER_BVISNULL( &attr->a_vals[ i ] ) ) {						goto remove_oc;					}					ber_bvreplace( bv, &mapped );				}			}		/*		 * It is necessary to try to rewrite attributes with		 * dn syntax because they might be used in ACLs as		 * members of groups; since ACLs are applied to the		 * rewritten stuff, no dn-based subecj clause could		 * be used at the ldap backend side (see		 * http://www.OpenLDAP.org/faq/data/cache/452.html)		 * The problem can be overcome by moving the dn-based		 * ACLs to the target directory server, and letting		 * everything pass thru the ldap backend.		 */		} else {			int	i;			if ( attr->a_desc->ad_type->sat_syntax ==				slap_schema.si_syn_distinguishedName )			{				ldap_dnattr_result_rewrite( &dc, attr->a_vals );			} else if ( attr->a_desc == slap_schema.si_ad_ref ) {				ldap_back_referral_result_rewrite( &dc, attr->a_vals );			}			for ( i = 0; i < last; i++ ) {				struct berval	pval;				int		rc;				if ( pretty ) {					rc = pretty( attr->a_desc->ad_type->sat_syntax,						&attr->a_vals[i], &pval, NULL );				} else {					rc = validate( attr->a_desc->ad_type->sat_syntax,						&attr->a_vals[i] );				}				if ( rc ) {					LBER_FREE( attr->a_vals[i].bv_val );					if ( --last == i ) {						BER_BVZERO( &attr->a_vals[ i ] );						break;					}					attr->a_vals[i] = attr->a_vals[last];					BER_BVZERO( &attr->a_vals[last] );					i--;					continue;				}				if ( pretty ) {					LBER_FREE( attr->a_vals[i].bv_val );					attr->a_vals[i] = pval;				}			}			if ( last == 0 && attr->a_vals != &slap_dummy_bv ) {				attr_free( attr );				goto next_attr;			}		}		if ( last && attr->a_desc->ad_type->sat_equality &&			attr->a_desc->ad_type->sat_equality->smr_normalize )		{			int i;			attr->a_nvals = ch_malloc( ( last + 1 ) * sizeof( struct berval ) );			for ( i = 0; i<last; i++ ) {				attr->a_desc->ad_type->sat_equality->smr_normalize(					SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,					attr->a_desc->ad_type->sat_syntax,					attr->a_desc->ad_type->sat_equality,					&attr->a_vals[i], &attr->a_nvals[i],					NULL );			}			BER_BVZERO( &attr->a_nvals[i] );		} else {			attr->a_nvals = attr->a_vals;		}		*attrp = attr;		attrp = &attr->a_next;next_attr:;	}	/* only check if some mapping occurred */	if ( check_duplicate_attrs ) {		Attribute	**ap;		for ( ap = &ent.e_attrs; *ap != NULL; ap = &(*ap)->a_next ) {			Attribute	**tap;			for ( tap = &(*ap)->a_next; *tap != NULL; ) {				if ( (*tap)->a_desc == (*ap)->a_desc ) {					Entry		e = { 0 };					Modification	mod = { 0 };					const char	*text = NULL;					char		textbuf[ SLAP_TEXT_BUFLEN ];					Attribute	*next = (*tap)->a_next;					BER_BVSTR( &e.e_name, "" );					BER_BVSTR( &e.e_nname, "" );					e.e_attrs = *ap;					mod.sm_op = LDAP_MOD_ADD;					mod.sm_desc = (*ap)->a_desc;					mod.sm_type = mod.sm_desc->ad_cname;					mod.sm_values = (*tap)->a_vals;					mod.sm_nvalues = (*tap)->a_nvals;					(void)modify_add_values( &e, &mod,						/* permissive */ 1,						&text, textbuf, sizeof( textbuf ) );					/* should not insert new attrs! */					assert( e.e_attrs == *ap );					attr_free( *tap );					*tap = next;				} else {					tap = &(*tap)->a_next;				}			}		}	}	rs->sr_entry = &ent;	rs->sr_attrs = op->ors_attrs;	rs->sr_flags = 0;	rs->sr_err = LDAP_SUCCESS;	rc = send_search_entry( op, rs );	switch ( rc ) {	case LDAP_UNAVAILABLE:		rc = LDAP_OTHER;		break;	}	rs->sr_entry = NULL;	rs->sr_attrs = NULL;		if ( !BER_BVISNULL( &ent.e_name ) ) {		free( ent.e_name.bv_val );		BER_BVZERO( &ent.e_name );	}	if ( !BER_BVISNULL( &ent.e_nname ) ) {		free( ent.e_nname.bv_val );		BER_BVZERO( &ent.e_nname );	}	entry_clean( &ent );	return rc;}

⌨️ 快捷键说明

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