Example #1
0
static int
slapi_op_search_callback( Operation *op, SlapReply *rs, int prc )
{
    Slapi_PBlock		*pb = SLAPI_OPERATION_PBLOCK( op );
    Filter *f = op->ors_filter;

    /* check preoperation result code */
    if ( prc < 0 ) {
        return rs->sr_err;
    }

    rs->sr_err = LDAP_SUCCESS;

    if ( pb->pb_intop == 0 &&
            slapi_int_call_plugins( op->o_bd, SLAPI_PLUGIN_COMPUTE_SEARCH_REWRITER_FN, pb ) == 0 ) {
        /*
         * The plugin can set the SLAPI_SEARCH_FILTER.
         * SLAPI_SEARCH_STRFILER is not normative.
         */
        if (f != op->ors_filter) {
            op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
            filter2bv_x( op, op->ors_filter, &op->ors_filterstr );
        }
    }

    return LDAP_SUCCESS;
}
Example #2
0
int
do_search(
    Operation	*op,	/* info about the op to which we're responding */
    SlapReply	*rs	/* all the response data we'll send */ )
{
	struct berval base = BER_BVNULL;
	ber_len_t	siz, off, i;

	Debug( LDAP_DEBUG_TRACE, "%s do_search\n",
		op->o_log_prefix, 0, 0 );
	/*
	 * Parse the search request.  It looks like this:
	 *
	 *	SearchRequest := [APPLICATION 3] SEQUENCE {
	 *		baseObject	DistinguishedName,
	 *		scope		ENUMERATED {
	 *			baseObject	(0),
	 *			singleLevel	(1),
	 *			wholeSubtree (2),
	 *          subordinate (3)  -- OpenLDAP extension
	 *		},
	 *		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, "{miiiib" /*}*/,
		&base, &op->ors_scope, &op->ors_deref, &op->ors_slimit,
	    &op->ors_tlimit, &op->ors_attrsonly ) == LBER_ERROR )
	{
		send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding error" );
		rs->sr_err = SLAPD_DISCONNECT;
		goto return_results;
	}

	if ( op->ors_tlimit < 0 || op->ors_tlimit > SLAP_MAX_LIMIT ) {
		send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid time limit" );
		goto return_results;
	}

	if ( op->ors_slimit < 0 || op->ors_slimit > SLAP_MAX_LIMIT ) {
		send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid size limit" );
		goto return_results;
	}

	switch( op->ors_scope ) {
	case LDAP_SCOPE_BASE:
	case LDAP_SCOPE_ONELEVEL:
	case LDAP_SCOPE_SUBTREE:
	case LDAP_SCOPE_SUBORDINATE:
		break;
	default:
		send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid scope" );
		goto return_results;
	}

	switch( op->ors_deref ) {
	case LDAP_DEREF_NEVER:
	case LDAP_DEREF_FINDING:
	case LDAP_DEREF_SEARCHING:
	case LDAP_DEREF_ALWAYS:
		break;
	default:
		send_ldap_error( op, rs, LDAP_PROTOCOL_ERROR, "invalid deref" );
		goto return_results;
	}

	rs->sr_err = dnPrettyNormal( NULL, &base, &op->o_req_dn, &op->o_req_ndn, op->o_tmpmemctx );
	if( rs->sr_err != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_ANY, "%s do_search: invalid dn: \"%s\"\n",
			op->o_log_prefix, base.bv_val, 0 );
		send_ldap_error( op, rs, LDAP_INVALID_DN_SYNTAX, "invalid DN" );
		goto return_results;
	}

	Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d",
		base.bv_val, op->ors_scope, op->ors_deref );
	Debug( LDAP_DEBUG_ARGS, "    %d %d %d\n",
		op->ors_slimit, op->ors_tlimit, op->ors_attrsonly);

	/* filter - returns a "normalized" version */
	rs->sr_err = get_filter( op, op->o_ber, &op->ors_filter, &rs->sr_text );
	if( rs->sr_err != LDAP_SUCCESS ) {
		if( rs->sr_err == SLAPD_DISCONNECT ) {
			rs->sr_err = LDAP_PROTOCOL_ERROR;
			send_ldap_disconnect( op, rs );
			rs->sr_err = SLAPD_DISCONNECT;
		} else {
			send_ldap_result( op, rs );
		}
		goto return_results;
	}
	filter2bv_x( op, op->ors_filter, &op->ors_filterstr );
	
	Debug( LDAP_DEBUG_ARGS, "    filter: %s\n",
		!BER_BVISEMPTY( &op->ors_filterstr ) ? op->ors_filterstr.bv_val : "empty", 0, 0 );

	/* attributes */
	siz = sizeof(AttributeName);
	off = offsetof(AttributeName,an_name);
	if ( ber_scanf( op->o_ber, "{M}}", &op->ors_attrs, &siz, off ) == LBER_ERROR ) {
		send_ldap_discon( op, rs, LDAP_PROTOCOL_ERROR, "decoding attrs error" );
		rs->sr_err = SLAPD_DISCONNECT;
		goto return_results;
	}
	for ( i=0; i<siz; i++ ) {
		const char *dummy;	/* ignore msgs from bv2ad */
		op->ors_attrs[i].an_desc = NULL;
		op->ors_attrs[i].an_oc = NULL;
		op->ors_attrs[i].an_flags = 0;
		if ( slap_bv2ad( &op->ors_attrs[i].an_name,
			&op->ors_attrs[i].an_desc, &dummy ) != LDAP_SUCCESS )
		{
			if ( slap_bv2undef_ad( &op->ors_attrs[i].an_name,
				&op->ors_attrs[i].an_desc, &dummy,
				SLAP_AD_PROXIED|SLAP_AD_NOINSERT ) )
			{
				struct berval *bv = &op->ors_attrs[i].an_name;

				/* RFC 4511 LDAPv3: All User Attributes */
				if ( bvmatch( bv, slap_bv_all_user_attrs ) ) {
					continue;
				}

				/* RFC 3673 LDAPv3: All Operational Attributes */
				if ( bvmatch( bv, slap_bv_all_operational_attrs ) ) {
					continue;
				}

				/* RFC 4529 LDAP: Requesting Attributes by Object Class */
				if ( bv->bv_len > 1 && bv->bv_val[0] == '@' ) {
					/* FIXME: check if remaining is valid oc name? */
					continue;
				}

				/* add more "exceptions" to RFC 4511 4.5.1.8. */

				/* invalid attribute description? remove */
				if ( ad_keystring( bv ) ) {
					/* NOTE: parsed in-place, don't modify;
					 * rather add "1.1", which must be ignored */
					BER_BVSTR( &op->ors_attrs[i].an_name, LDAP_NO_ATTRS );
				}

				/* otherwise leave in place... */
			}
		}
	}

	if( get_ctrls( op, rs, 1 ) != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_ANY, "%s do_search: get_ctrls failed\n",
			op->o_log_prefix, 0, 0 );
		goto return_results;
	}

	Debug( LDAP_DEBUG_ARGS, "    attrs:", 0, 0, 0 );

	if ( siz != 0 ) {
		for ( i = 0; i<siz; i++ ) {
			Debug( LDAP_DEBUG_ARGS, " %s", op->ors_attrs[i].an_name.bv_val, 0, 0 );
		}
	}

	Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );

	if ( StatslogTest( LDAP_DEBUG_STATS ) ) {
		char abuf[BUFSIZ/2], *ptr = abuf;
		unsigned len = 0, alen;

		sprintf(abuf, "scope=%d deref=%d", op->ors_scope, op->ors_deref);
		Statslog( LDAP_DEBUG_STATS,
		        "%s SRCH base=\"%s\" %s filter=\"%s\"\n",
		        op->o_log_prefix, op->o_req_dn.bv_val, abuf,
		        op->ors_filterstr.bv_val, 0 );

		for ( i = 0; i<siz; i++ ) {
			alen = op->ors_attrs[i].an_name.bv_len;
			if (alen >= sizeof(abuf)) {
				alen = sizeof(abuf)-1;
			}
			if (len && (len + 1 + alen >= sizeof(abuf))) {
				Statslog( LDAP_DEBUG_STATS, "%s SRCH attr=%s\n",
				    op->o_log_prefix, abuf, 0, 0, 0 );
				len = 0;
				ptr = abuf;
			}
			if (len) {
				*ptr++ = ' ';
				len++;
			}
			ptr = lutil_strncopy(ptr, op->ors_attrs[i].an_name.bv_val, alen);
			len += alen;
			*ptr = '\0';
		}
		if (len) {
			Statslog( LDAP_DEBUG_STATS, "%s SRCH attr=%s\n",
	    			op->o_log_prefix, abuf, 0, 0, 0 );
		}
	}

	op->o_bd = frontendDB;
	rs->sr_err = frontendDB->be_search( op, rs );

return_results:;
	if ( !BER_BVISNULL( &op->o_req_dn ) ) {
		slap_sl_free( op->o_req_dn.bv_val, op->o_tmpmemctx );
	}
	if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
		slap_sl_free( op->o_req_ndn.bv_val, op->o_tmpmemctx );
	}
	if ( !BER_BVISNULL( &op->ors_filterstr ) ) {
		op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
	}
	if ( op->ors_filter != NULL) {
		filter_free_x( op, op->ors_filter, 1 );
	}
	if ( op->ors_attrs != NULL ) {
		op->o_tmpfree( op->ors_attrs, op->o_tmpmemctx );
	}

	return rs->sr_err;
}
Example #3
0
static int translucent_search(Operation *op, SlapReply *rs) {
	slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
	translucent_info *ov = on->on_bi.bi_private;
	slap_callback cb = { NULL, NULL, NULL, NULL };
	trans_ctx tc;
	Filter *fl, *fr;
	struct berval fbv;
	int rc = 0;

	if ( op->o_managedsait > SLAP_CONTROL_IGNORED )
		return SLAP_CB_CONTINUE;

	Debug(LDAP_DEBUG_TRACE, "==> translucent_search: <%s> %s\n",
		op->o_req_dn.bv_val, op->ors_filterstr.bv_val, 0);

	if(ov->defer_db_open) {
		send_ldap_error(op, rs, LDAP_UNAVAILABLE,
			"remote DB not available");
		return(rs->sr_err);
	}

	fr = ov->remote ? trans_filter_dup( op, op->ors_filter, ov->remote ) : NULL;
	fl = ov->local ? trans_filter_dup( op, op->ors_filter, ov->local ) : NULL;
	cb.sc_response = (slap_response *) translucent_search_cb;
	cb.sc_private = &tc;
	cb.sc_next = op->o_callback;

	ov->db.be_acl = op->o_bd->be_acl;
	tc.db = op->o_bd;
	tc.on = on;
	tc.orig = op->ors_filter;
	tc.list = NULL;
	tc.step = 0;
	tc.slimit = op->ors_slimit;
	tc.attrs = NULL;
	fbv = op->ors_filterstr;

	op->o_callback = &cb;

	if ( fr || !fl ) {
		tc.attrs = op->ors_attrs;
		op->ors_slimit = SLAP_NO_LIMIT;
		op->ors_attrs = slap_anlist_all_attributes;
		op->o_bd = &ov->db;
		tc.step |= RMT_SIDE;
		if ( fl ) {
			tc.step |= USE_LIST;
			op->ors_filter = fr;
			filter2bv_x( op, fr, &op->ors_filterstr );
		}
		rc = ov->db.bd_info->bi_op_search(op, rs);
		if ( op->ors_attrs == slap_anlist_all_attributes )
			op->ors_attrs = tc.attrs;
		op->o_bd = tc.db;
		if ( fl ) {
			op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
		}
	}
	if ( fl && !rc ) {
		tc.step |= LCL_SIDE;
		op->ors_filter = fl;
		filter2bv_x( op, fl, &op->ors_filterstr );
		rc = overlay_op_walk( op, rs, op_search, on->on_info, on->on_next );
		op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
	}
	op->ors_filterstr = fbv;
	op->ors_filter = tc.orig;
	op->o_callback = cb.sc_next;
	rs->sr_attrs = op->ors_attrs;
	rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs );

	/* Send out anything remaining on the list and finish */
	if ( tc.step & USE_LIST ) {
		if ( tc.list ) {
			Avlnode *av;

			av = tavl_end( tc.list, TAVL_DIR_LEFT );
			while ( av ) {
				rs->sr_entry = av->avl_data;
				if ( rc == LDAP_SUCCESS && LDAP_COMPARE_TRUE ==
					test_filter( op, rs->sr_entry, op->ors_filter ))
				{
					rs->sr_flags = REP_ENTRY_MUSTBEFREED;
					rc = send_search_entry( op, rs );
				} else {
					entry_free( rs->sr_entry );
				}
				av = tavl_next( av, TAVL_DIR_RIGHT );
			}
			tavl_free( tc.list, NULL );
			rs->sr_flags = 0;
			rs->sr_entry = NULL;
		}
		send_ldap_result( op, rs );
	}

	op->ors_slimit = tc.slimit;

	/* Free in reverse order */
	if ( fl )
		trans_filter_free( op, fl );
	if ( fr )
		trans_filter_free( op, fr );

	return rc;
}
Example #4
0
static adremap_dnv *adremap_filter(
	Operation *op,
	adremap_info *ai
)
{
	slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
	Filter *f = op->ors_filter, *fn = NULL;
	adremap_dnv *ad = NULL;
	struct berval bv;
	int fextra = 0;

	/* Do we need to munge the filter? First see if it's of
	 * the form (objectClass=<mapgrp>)
	 * or form (&(objectClass=<mapgrp>)...)
	 * or form (&(&(objectClass=<mapgrp>)...)...)
	 */
	if (f->f_choice == LDAP_FILTER_AND && f->f_and) {
		fextra = 1;
		f = f->f_and;
		fn = f->f_next;
	}
	if (f->f_choice == LDAP_FILTER_AND && f->f_and) {
		fextra = 2;
		f = f->f_and;
	}
	if (f->f_choice == LDAP_FILTER_EQUALITY &&
		f->f_av_desc == slap_schema.si_ad_objectClass) {
		struct berval bv = f->f_av_value;

		for (ad = ai->ai_dnv; ad; ad = ad->ad_next) {
			if (!ber_bvstrcasecmp( &bv, &ad->ad_mapgrp->soc_cname )) {
			/* Now check to see if next element is (<newattr>=foo) */
				Filter *fnew;
				if (fn && fn->f_choice == LDAP_FILTER_EQUALITY &&
					fn->f_av_desc == ad->ad_newattr) {
					Filter fr[3];
					AttributeAssertion aa[2] = {0};
					Operation op2;
					slap_callback cb = {0};
					SlapReply rs = {REP_RESULT};
					struct berval dn = BER_BVNULL;

					/* It's a match, setup a search with filter
					 * (&(objectclass=<refgrp>)(<deref>=foo))
					 */
					fr[0].f_choice = LDAP_FILTER_AND;
					fr[0].f_and = &fr[1];
					fr[0].f_next = NULL;

					fr[1].f_choice = LDAP_FILTER_EQUALITY;
					fr[1].f_ava = &aa[0];
					fr[1].f_av_desc = slap_schema.si_ad_objectClass;
					fr[1].f_av_value = ad->ad_refgrp->soc_cname;
					fr[1].f_next = &fr[2];

					fr[2].f_choice = LDAP_FILTER_EQUALITY;
					fr[2].f_ava = &aa[1];
					fr[2].f_av_desc = ad->ad_deref;
					fr[2].f_av_value = fn->f_av_value;
					fr[2].f_next = NULL;

					/* Search with this filter to retrieve target DN */
					op2 = *op;
					op2.o_callback = &cb;
					cb.sc_response = adremap_refsearch;
					cb.sc_private = &dn;
					op2.o_req_dn = ad->ad_refbase;
					op2.o_req_ndn = ad->ad_refbase;
					op2.ors_filter = fr;
					filter2bv_x(op, fr, &op2.ors_filterstr);
					op2.ors_deref = LDAP_DEREF_NEVER;
					op2.ors_slimit = 1;
					op2.ors_tlimit = SLAP_NO_LIMIT;
					op2.ors_attrs = slap_anlist_no_attrs;
					op2.ors_attrsonly = 1;
					op2.o_no_schema_check = 1;
					op2.o_bd->bd_info = (BackendInfo *)on->on_info;
					op2.o_bd->be_search(&op2, &rs);
					op2.o_bd->bd_info = (BackendInfo *)on;
					op->o_tmpfree(op2.ors_filterstr.bv_val, op->o_tmpmemctx);

					if (!dn.bv_len) {	/* no match was found */
						ad = NULL;
						break;
					}

					if (rs.sr_err) {	/* sizelimit exceeded, etc.: invalid name */
						op->o_tmpfree(dn.bv_val, op->o_tmpmemctx);
						ad = NULL;
						break;
					}

					/* Build a new filter of form
					 * (&(objectclass=<group>)(<dnattr>=foo-DN)...)
					 */
					f = op->o_tmpalloc(sizeof(Filter), op->o_tmpmemctx);
					f->f_choice = LDAP_FILTER_AND;
					fnew = f;
					f->f_next = NULL;

					f->f_and = op->o_tmpalloc(sizeof(Filter), op->o_tmpmemctx);
					f = f->f_and;
					f->f_choice = LDAP_FILTER_EQUALITY;
					f->f_ava = op->o_tmpcalloc(1, sizeof(AttributeAssertion), op->o_tmpmemctx);
					f->f_av_desc = slap_schema.si_ad_objectClass;
					ber_dupbv_x(&f->f_av_value, &ad->ad_group->soc_cname, op->o_tmpmemctx);

					f->f_next = op->o_tmpalloc(sizeof(Filter), op->o_tmpmemctx);
					f = f->f_next;
					f->f_choice = LDAP_FILTER_EQUALITY;
					f->f_ava = op->o_tmpcalloc(1, sizeof(AttributeAssertion), op->o_tmpmemctx);
					f->f_av_desc = ad->ad_dnattr;
					f->f_av_value = dn;

					f->f_next = fn->f_next;
					fn->f_next = NULL;
				} else {
					/* Build a new filter of form
					 * (objectclass=<group>)
					 */
					f->f_next = NULL;	/* disconnect old chain */

					f = op->o_tmpalloc(sizeof(Filter), op->o_tmpmemctx);
					f->f_choice = LDAP_FILTER_EQUALITY;
					f->f_ava = op->o_tmpcalloc(1, sizeof(AttributeAssertion), op->o_tmpmemctx);
					f->f_av_desc = slap_schema.si_ad_objectClass;
					ber_dupbv_x(&f->f_av_value, &ad->ad_group->soc_cname, op->o_tmpmemctx);

					/* If there was a wrapping (&), attach it. */
					if (fextra) {
						fnew = op->o_tmpalloc(sizeof(Filter), op->o_tmpmemctx);
						fnew->f_choice = LDAP_FILTER_AND;
						fnew->f_and = f;
						fnew->f_next = NULL;
						f->f_next = fn;
					} else {
						fnew = f;
						f->f_next = NULL;
					}
				}
				if (fextra > 1) {
					f = op->o_tmpalloc(sizeof(Filter), op->o_tmpmemctx);
					f->f_choice = LDAP_FILTER_AND;
					f->f_and = fnew->f_and;
					f->f_next = f->f_and->f_next;
					f->f_and->f_next = op->ors_filter->f_and->f_and->f_next;
					op->ors_filter->f_and->f_and->f_next = NULL;
					fnew->f_and = f;
				}
				filter_free_x(op, op->ors_filter, 1);
				op->o_tmpfree(op->ors_filterstr.bv_val, op->o_tmpmemctx);
				op->ors_filter = fnew;
				filter2bv_x(op, op->ors_filter, &op->ors_filterstr);
				break;
			}
		}
	}
	return ad;
}