Пример #1
0
/*
 * dnParent - dn's parent, in-place
 * note: the incoming dn is assumed to be normalized/prettyfied,
 * so that escaped rdn/ava separators are in '\'+hexpair form
 *
 * note: "dn" and "pdn" can point to the same berval;
 * beware that, in this case, the pointer to the original buffer
 * will get lost.
 */
void
dnParent( 
	struct berval	*dn, 
	struct berval	*pdn )
{
	char	*p;

	p = ber_bvchr( dn, ',' );

	/* one-level dn */
	if ( p == NULL ) {
		pdn->bv_val = dn->bv_val + dn->bv_len;
		pdn->bv_len = 0;
		return;
	}

	assert( DN_SEPARATOR( p[ 0 ] ) );
	p++;

	assert( ATTR_LEADCHAR( p[ 0 ] ) );
	pdn->bv_len = dn->bv_len - (p - dn->bv_val);
	pdn->bv_val = p;

	return;
}
Пример #2
0
/*
 * dnIsSuffix - tells whether suffix is a suffix of dn.
 * Both dn and suffix must be normalized.
 */
int
dnIsSuffix(
	const struct berval *dn,
	const struct berval *suffix )
{
	int	d;

	assert( dn != NULL );
	assert( suffix != NULL );

	d = dn->bv_len - suffix->bv_len;

	/* empty suffix matches any dn */
	if ( suffix->bv_len == 0 ) {
		return 1;
	}

	/* suffix longer than dn */
	if ( d < 0 ) {
		return 0;
	}

	/* no rdn separator or escaped rdn separator */
	if ( d > 1 && !DN_SEPARATOR( dn->bv_val[ d - 1 ] ) ) {
		return 0;
	}

	/* no possible match or malformed dn */
	if ( d == 1 ) {
		return 0;
	}

	/* compare */
	return( strncmp( dn->bv_val + d, suffix->bv_val, suffix->bv_len ) == 0 );
}
Пример #3
0
int
dnIsOneLevelRDN( struct berval *rdn )
{
	ber_len_t	len = rdn->bv_len;
	for ( ; len--; ) {
		if ( DN_SEPARATOR( rdn->bv_val[ len ] ) ) {
			return 0;
		}
	}

	return 1;
}
Пример #4
0
int
bdb_dn2id_matched(
	BackendDB	*be,
	DB_TXN *txn,
	struct berval	*in,
	ID *id,
	ID *id2,
	int flags )
{
	struct bdb_info *bdb = (struct bdb_info *) be->be_private;
	struct berval	rdn;
	char		*p1, *p2;
	idNode *n, *p;
	int		rc = 0;

	if (!bdb->bi_troot)
		return DB_NOTFOUND;

	p = bdb->bi_troot;
	if (be_issuffix(be, in)) {
		*id = p->i_id;
		return 0;
	}

	p1 = in->bv_val + in->bv_len - be->be_nsuffix[0].bv_len - 1;

	n = p;
	ldap_pvt_thread_rdwr_rlock(&bdb->bi_tree_rdwr);
	for (;;) {
		for (p2 = p1-1; (p2 >= in->bv_val) && !DN_SEPARATOR(*p2); p2--);
		rdn.bv_val = p2+1;
		rdn.bv_len = p1-rdn.bv_val;
		p1 = p2;

		ldap_pvt_thread_rdwr_rlock(&p->i_kids_rdwr);
		n = bdb_find_rdn_node(&rdn, p->i_kids);
		ldap_pvt_thread_rdwr_runlock(&p->i_kids_rdwr);
		if (!n || p2 < in->bv_val) break;
		p = n;
	}
	ldap_pvt_thread_rdwr_runlock(&bdb->bi_tree_rdwr);

	if (n) {
		*id = n->i_id;
	} else if (id2) {
		*id2 = p->i_id;
	} else {
		rc = DB_NOTFOUND;
	}

	return rc;
}
Пример #5
0
/*
 * dnRdn - dn's rdn, in-place
 * note: the incoming dn is assumed to be normalized/prettyfied,
 * so that escaped rdn/ava separators are in '\'+hexpair form
 */
void
dnRdn( 
	struct berval	*dn, 
	struct berval	*rdn )
{
	char	*p;

	*rdn = *dn;
	p = ber_bvchr( dn, ',' );

	/* one-level dn */
	if ( p == NULL ) {
		return;
	}

	assert( DN_SEPARATOR( p[ 0 ] ) );
	assert( ATTR_LEADCHAR( p[ 1 ] ) );
	rdn->bv_len = p - dn->bv_val;

	return;
}
Пример #6
0
/*
 * ldap_back_dn_massage
 * 
 * Aliases the suffix; based on suffix_alias (servers/slapd/suffixalias.c).
 */
int
ldap_back_dn_massage(
	dncookie *dc,
	struct berval *odn,
	struct berval *res
)
{
	int     i, src, dst;
	struct berval pretty = {0,NULL}, *dn = odn;

	assert( res != NULL );

	if ( dn == NULL ) {
		res->bv_val = NULL;
		res->bv_len = 0;
		return 0;
	}
	if ( dc->target->mt_rwmap.rwm_suffix_massage == NULL ) {
		*res = *dn;
		return 0;
	}

	if ( dc->tofrom ) {
		src = 0 + dc->normalized;
		dst = 2 + dc->normalized;
	} else {
		src = 2 + dc->normalized;
		dst = 0 + dc->normalized;
		/* DN from remote server may be in arbitrary form.
		 * Pretty it so we can parse reliably.
		 */
		dnPretty( NULL, dn, &pretty, NULL );
		if (pretty.bv_val) dn = &pretty;
	}

	for ( i = 0;
		dc->target->mt_rwmap.rwm_suffix_massage[i].bv_val != NULL;
		i += 4 ) {
		int aliasLength = dc->target->mt_rwmap.rwm_suffix_massage[i+src].bv_len;
		int diff = dn->bv_len - aliasLength;

		if ( diff < 0 ) {
			/* alias is longer than dn */
			continue;
		} else if ( diff > 0 && ( !DN_SEPARATOR(dn->bv_val[diff-1]))) {
			/* boundary is not at a DN separator */
			continue;
			/* At a DN Separator */
		}

		if ( !strcmp( dc->target->mt_rwmap.rwm_suffix_massage[i+src].bv_val, &dn->bv_val[diff] ) ) {
			res->bv_len = diff + dc->target->mt_rwmap.rwm_suffix_massage[i+dst].bv_len;
			res->bv_val = ch_malloc( res->bv_len + 1 );
			strncpy( res->bv_val, dn->bv_val, diff );
			strcpy( &res->bv_val[diff], dc->target->mt_rwmap.rwm_suffix_massage[i+dst].bv_val );
			Debug( LDAP_DEBUG_ARGS,
				"ldap_back_dn_massage:"
				" converted \"%s\" to \"%s\"\n",
				BER_BVISNULL( dn ) ? "" : dn->bv_val,
				BER_BVISNULL( res ) ? "" : res->bv_val, 0 );
			break;
		}
	}
	if (pretty.bv_val) {
		ch_free(pretty.bv_val);
		dn = odn;
	}
	/* Nothing matched, just return the original DN */
	if (res->bv_val == NULL) {
		*res = *dn;
	}

	return 0;
}
Пример #7
0
static int
limits_get( 
	Operation		*op,
	struct slap_limits_set 	**limit
)
{
	static struct berval empty_dn = BER_BVC( "" );
	struct slap_limits **lm;
	struct berval		*ndns[2];

	assert( op != NULL );
	assert( limit != NULL );

	ndns[0] = &op->o_ndn;
	ndns[1] = &op->o_req_ndn;

	Debug( LDAP_DEBUG_TRACE, "==> limits_get: %s self=\"%s\" this=\"%s\"\n",
			op->o_log_prefix,
			BER_BVISNULL( ndns[0] ) ? "[anonymous]" : ndns[0]->bv_val,
			BER_BVISNULL( ndns[1] ) ? "" : ndns[1]->bv_val );
	/*
	 * default values
	 */
	*limit = &op->o_bd->be_def_limit;

	if ( op->o_bd->be_limits == NULL ) {
		return( 0 );
	}

	for ( lm = op->o_bd->be_limits; lm[0] != NULL; lm++ ) {
		unsigned	style = lm[0]->lm_flags & SLAP_LIMITS_MASK;
		unsigned	type = lm[0]->lm_flags & SLAP_LIMITS_TYPE_MASK;
		unsigned	isthis = type == SLAP_LIMITS_TYPE_THIS;
		struct berval *ndn = ndns[isthis];

		if ( style == SLAP_LIMITS_ANY )
			goto found_any;

		if ( BER_BVISEMPTY( ndn ) ) {
			if ( style == SLAP_LIMITS_ANONYMOUS )
				goto found_nodn;
			if ( !isthis )
				continue;
			ndn = &empty_dn;
		}

		switch ( style ) {
		case SLAP_LIMITS_EXACT:
			if ( type == SLAP_LIMITS_TYPE_GROUP ) {
				int	rc = backend_group( op, NULL,
						&lm[0]->lm_pat, ndn,
						lm[0]->lm_group_oc,
						lm[0]->lm_group_ad );
				if ( rc == 0 ) {
					goto found_group;
				}
			} else {
				if ( dn_match( &lm[0]->lm_pat, ndn ) ) {
					goto found_dn;
				}
			}
			break;

		case SLAP_LIMITS_ONE:
		case SLAP_LIMITS_SUBTREE:
		case SLAP_LIMITS_CHILDREN: {
			ber_len_t d;
			
			/* ndn shorter than lm_pat */
			if ( ndn->bv_len < lm[0]->lm_pat.bv_len ) {
				break;
			}
			d = ndn->bv_len - lm[0]->lm_pat.bv_len;

			if ( d == 0 ) {
				/* allow exact match for SUBTREE only */
				if ( style != SLAP_LIMITS_SUBTREE ) {
					break;
				}
			} else {
				/* check for unescaped rdn separator */
				if ( !DN_SEPARATOR( ndn->bv_val[d - 1] ) ) {
					break;
				}
			}

			/* check that ndn ends with lm_pat */
			if ( strcmp( lm[0]->lm_pat.bv_val, &ndn->bv_val[d] ) != 0 ) {
				break;
			}

			/* in case of ONE, require exactly one rdn below lm_pat */
			if ( style == SLAP_LIMITS_ONE ) {
				if ( dn_rdnlen( NULL, ndn ) != d - 1 ) {
					break;
				}
			}

			goto found_dn;
		}

		case SLAP_LIMITS_REGEX:
			if ( regexec( &lm[0]->lm_regex, ndn->bv_val, 0, NULL, 0 ) == 0 ) {
				goto found_dn;
			}
			break;

		case SLAP_LIMITS_ANONYMOUS:
			break;

		case SLAP_LIMITS_USERS:
		found_nodn:
			Debug( LDAP_DEBUG_TRACE, "<== limits_get: type=%s match=%s\n",
				dn_source[isthis], limits2str( style ), 0 );
		found_any:
			*limit = &lm[0]->lm_limits;
			return( 0 );

		found_dn:
			Debug( LDAP_DEBUG_TRACE,
				"<== limits_get: type=%s match=%s dn=\"%s\"\n",
				dn_source[isthis], limits2str( style ), lm[0]->lm_pat.bv_val );
			*limit = &lm[0]->lm_limits;
			return( 0 );

		found_group:
			Debug( LDAP_DEBUG_TRACE, "<== limits_get: type=GROUP match=EXACT "
				"dn=\"%s\" oc=\"%s\" ad=\"%s\"\n",
				lm[0]->lm_pat.bv_val,
				lm[0]->lm_group_oc->soc_cname.bv_val,
				lm[0]->lm_group_ad->ad_cname.bv_val );
			*limit = &lm[0]->lm_limits;
			return( 0 );

		default:
			assert( 0 );	/* unreachable */
			return( -1 );
		}
	}

	return( 0 );
}
Пример #8
0
/* return IDs from root to parent of DN */
int
mdb_dn2sups(
	Operation	*op,
	MDB_txn *txn,
	struct berval	*in,
	ID	*ids )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	MDB_cursor *cursor;
	MDB_dbi dbi = mdb->mi_dn2id;
	MDB_val		key, data;
	int		rc = 0, nrlen;
	diskNode *d;
	char	*ptr;
	ID pid, nid;
	struct berval tmp;

	Debug( LDAP_DEBUG_TRACE, "=> mdb_dn2sups(\"%s\")\n", in->bv_val );

	if ( !in->bv_len ) {
		goto done;
	}

	tmp = *in;

	nrlen = tmp.bv_len - op->o_bd->be_nsuffix[0].bv_len;
	tmp.bv_val += nrlen;
	tmp.bv_len = op->o_bd->be_nsuffix[0].bv_len;
	nid = 0;
	key.mv_size = sizeof(ID);

	rc = mdb_cursor_open( txn, dbi, &cursor );
	if ( rc ) goto done;

	for (;;) {
		key.mv_data = &pid;
		pid = nid;

		data.mv_size = sizeof(diskNode) + tmp.bv_len;
		d = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
		d->nrdnlen[1] = tmp.bv_len & 0xff;
		d->nrdnlen[0] = (tmp.bv_len >> 8) | 0x80;
		ptr = lutil_strncopy( d->nrdn, tmp.bv_val, tmp.bv_len );
		*ptr = '\0';
		data.mv_data = d;
		rc = mdb_cursor_get( cursor, &key, &data, MDB_GET_BOTH );
		op->o_tmpfree( d, op->o_tmpmemctx );
		if ( rc ) {
			mdb_cursor_close( cursor );
			break;
		}
		ptr = (char *) data.mv_data + data.mv_size - 2*sizeof(ID);
		memcpy( &nid, ptr, sizeof(ID));

		if ( pid )
			mdb_idl_insert( ids, pid );

		if ( tmp.bv_val > in->bv_val ) {
			for (ptr = tmp.bv_val - 2; ptr > in->bv_val &&
				!DN_SEPARATOR(*ptr); ptr--)	/* empty */;
			if ( ptr >= in->bv_val ) {
				if (DN_SEPARATOR(*ptr)) ptr++;
				tmp.bv_len = tmp.bv_val - ptr - 1;
				tmp.bv_val = ptr;
			}
		} else {
			break;
		}
	}

done:
	if( rc != 0 ) {
		Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2sups: get failed: %s (%d)\n",
			mdb_strerror( rc ), rc );
	}

	return rc;
}
Пример #9
0
/* return last found ID in *id if no match
 * If mc is provided, it will be left pointing to the RDN's
 * record under the parent's ID. If nsubs is provided, return
 * the number of entries in this entry's subtree.
 */
int
mdb_dn2id(
	Operation	*op,
	MDB_txn *txn,
	MDB_cursor	*mc,
	struct berval	*in,
	ID	*id,
	ID	*nsubs,
	struct berval	*matched,
	struct berval	*nmatched )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	MDB_cursor *cursor;
	MDB_dbi dbi = mdb->mi_dn2id;
	MDB_val		key, data;
	int		rc = 0, nrlen;
	diskNode *d;
	char	*ptr;
	char dn[SLAP_LDAPDN_MAXLEN];
	ID pid, nid;
	struct berval tmp;

	Debug( LDAP_DEBUG_TRACE, "=> mdb_dn2id(\"%s\")\n", in->bv_val ? in->bv_val : "" );

	if ( matched ) {
		matched->bv_val = dn + sizeof(dn) - 1;
		matched->bv_len = 0;
		*matched->bv_val-- = '\0';
	}
	if ( nmatched ) {
		nmatched->bv_len = 0;
		nmatched->bv_val = 0;
	}

	if ( !in->bv_len ) {
		*id = 0;
		nid = 0;
		goto done;
	}

	tmp = *in;

	if ( op->o_bd->be_nsuffix[0].bv_len ) {
		nrlen = tmp.bv_len - op->o_bd->be_nsuffix[0].bv_len;
		tmp.bv_val += nrlen;
		tmp.bv_len = op->o_bd->be_nsuffix[0].bv_len;
	} else {
		for ( ptr = tmp.bv_val + tmp.bv_len - 1; ptr >= tmp.bv_val; ptr-- )
			if (DN_SEPARATOR(*ptr))
				break;
		ptr++;
		tmp.bv_len -= ptr - tmp.bv_val;
		tmp.bv_val = ptr;
	}
	nid = 0;
	key.mv_size = sizeof(ID);

	if ( mc ) {
		cursor = mc;
	} else {
		rc = mdb_cursor_open( txn, dbi, &cursor );
		if ( rc ) goto done;
	}

	for (;;) {
		key.mv_data = &pid;
		pid = nid;

		data.mv_size = sizeof(diskNode) + tmp.bv_len;
		d = op->o_tmpalloc( data.mv_size, op->o_tmpmemctx );
		d->nrdnlen[1] = tmp.bv_len & 0xff;
		d->nrdnlen[0] = (tmp.bv_len >> 8) | 0x80;
		ptr = lutil_strncopy( d->nrdn, tmp.bv_val, tmp.bv_len );
		*ptr = '\0';
		data.mv_data = d;
		rc = mdb_cursor_get( cursor, &key, &data, MDB_GET_BOTH );
		op->o_tmpfree( d, op->o_tmpmemctx );
		if ( rc )
			break;
		ptr = (char *) data.mv_data + data.mv_size - 2*sizeof(ID);
		memcpy( &nid, ptr, sizeof(ID));

		/* grab the non-normalized RDN */
		if ( matched ) {
			int rlen;
			d = data.mv_data;
			rlen = data.mv_size - sizeof(diskNode) - tmp.bv_len - sizeof(ID);
			matched->bv_len += rlen;
			matched->bv_val -= rlen + 1;
			ptr = lutil_strcopy( matched->bv_val, d->rdn + tmp.bv_len );
			if ( pid ) {
				*ptr = ',';
				matched->bv_len++;
			}
		}
		if ( nmatched ) {
			nmatched->bv_val = tmp.bv_val;
		}

		if ( tmp.bv_val > in->bv_val ) {
			for (ptr = tmp.bv_val - 2; ptr > in->bv_val &&
				!DN_SEPARATOR(*ptr); ptr--)	/* empty */;
			if ( ptr >= in->bv_val ) {
				if (DN_SEPARATOR(*ptr)) ptr++;
				tmp.bv_len = tmp.bv_val - ptr - 1;
				tmp.bv_val = ptr;
			}
		} else {
			break;
		}
	}
	*id = nid;
	/* return subtree count if requested */
	if ( !rc && nsubs ) {
		ptr = (char *)data.mv_data + data.mv_size - sizeof(ID);
		memcpy( nsubs, ptr, sizeof( ID ));
	}
	if ( !mc )
		mdb_cursor_close( cursor );
done:
	if ( matched ) {
		if ( matched->bv_len ) {
			ptr = op->o_tmpalloc( matched->bv_len+1, op->o_tmpmemctx );
			strcpy( ptr, matched->bv_val );
			matched->bv_val = ptr;
		} else {
			if ( BER_BVISEMPTY( &op->o_bd->be_nsuffix[0] ) && !nid ) {
				ber_dupbv( matched, (struct berval *)&slap_empty_bv );
			} else {
				matched->bv_val = NULL;
			}
		}
	}
	if ( nmatched ) {
		if ( nmatched->bv_val ) {
			nmatched->bv_len = in->bv_len - (nmatched->bv_val - in->bv_val);
		} else {
			*nmatched = slap_empty_bv;
		}
	}

	if( rc != 0 ) {
		Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2id: get failed: %s (%d)\n",
			mdb_strerror( rc ), rc );
	} else {
		Debug( LDAP_DEBUG_TRACE, "<= mdb_dn2id: got id=0x%lx\n", nid );
	}

	return rc;
}
Пример #10
0
/* Find the EntryInfo for the requested DN. If the DN cannot be found, return
 * the info for its closest ancestor. *res should be NULL to process a
 * complete DN starting from the tree root. Otherwise *res must be the
 * immediate parent of the requested DN, and only the RDN will be searched.
 * The EntryInfo is locked upon return and must be unlocked by the caller.
 */
int
bdb_cache_find_ndn(
	Operation	*op,
	DB_TXN		*txn,
	struct berval	*ndn,
	EntryInfo	**res )
{
	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
	EntryInfo	ei, *eip, *ei2;
	int rc = 0;
	char *ptr;

	/* this function is always called with normalized DN */
	if ( *res ) {
		/* we're doing a onelevel search for an RDN */
		ei.bei_nrdn.bv_val = ndn->bv_val;
		ei.bei_nrdn.bv_len = dn_rdnlen( op->o_bd, ndn );
		eip = *res;
	} else {
		/* we're searching a full DN from the root */
		ptr = ndn->bv_val + ndn->bv_len - op->o_bd->be_nsuffix[0].bv_len;
		ei.bei_nrdn.bv_val = ptr;
		ei.bei_nrdn.bv_len = op->o_bd->be_nsuffix[0].bv_len;
		/* Skip to next rdn if suffix is empty */
		if ( ei.bei_nrdn.bv_len == 0 ) {
			for (ptr = ei.bei_nrdn.bv_val - 2; ptr > ndn->bv_val
				&& !DN_SEPARATOR(*ptr); ptr--) /* empty */;
			if ( ptr >= ndn->bv_val ) {
				if (DN_SEPARATOR(*ptr)) ptr++;
				ei.bei_nrdn.bv_len = ei.bei_nrdn.bv_val - ptr;
				ei.bei_nrdn.bv_val = ptr;
			}
		}
		eip = &bdb->bi_cache.c_dntree;
	}
	
	for ( bdb_cache_entryinfo_lock( eip ); eip; ) {
		eip->bei_state |= CACHE_ENTRY_REFERENCED;
		ei.bei_parent = eip;
		ei2 = (EntryInfo *)avl_find( eip->bei_kids, &ei, bdb_rdn_cmp );
		if ( !ei2 ) {
			DBC *cursor;
			int len = ei.bei_nrdn.bv_len;
				
			if ( BER_BVISEMPTY( ndn )) {
				*res = eip;
				return LDAP_SUCCESS;
			}

			ei.bei_nrdn.bv_len = ndn->bv_len -
				(ei.bei_nrdn.bv_val - ndn->bv_val);
			eip->bei_finders++;
			bdb_cache_entryinfo_unlock( eip );

			BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Reading %s",
				ei.bei_nrdn.bv_val );

			cursor = NULL;
			rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, txn, &cursor );
			if (rc) {
				bdb_cache_entryinfo_lock( eip );
				eip->bei_finders--;
				if ( cursor ) cursor->c_close( cursor );
				*res = eip;
				return rc;
			}

			BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Read got %s(%d)",
				ei.bei_nrdn.bv_val, ei.bei_id );

			/* DN exists but needs to be added to cache */
			ei.bei_nrdn.bv_len = len;
			rc = bdb_entryinfo_add_internal( bdb, &ei, &ei2 );
			/* add_internal left eip and c_rwlock locked */
			eip->bei_finders--;
			ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
			if ( cursor ) cursor->c_close( cursor );
			if ( rc ) {
				*res = eip;
				return rc;
			}
		}
		bdb_cache_entryinfo_lock( ei2 );
		if ( ei2->bei_state & CACHE_ENTRY_DELETED ) {
			/* In the midst of deleting? Give it a chance to
			 * complete.
			 */
			bdb_cache_entryinfo_unlock( ei2 );
			bdb_cache_entryinfo_unlock( eip );
			ldap_pvt_thread_yield();
			bdb_cache_entryinfo_lock( eip );
			*res = eip;
			return DB_NOTFOUND;
		}
		bdb_cache_entryinfo_unlock( eip );

		eip = ei2;

		/* Advance to next lower RDN */
		for (ptr = ei.bei_nrdn.bv_val - 2; ptr > ndn->bv_val
			&& !DN_SEPARATOR(*ptr); ptr--) /* empty */;
		if ( ptr >= ndn->bv_val ) {
			if (DN_SEPARATOR(*ptr)) ptr++;
			ei.bei_nrdn.bv_len = ei.bei_nrdn.bv_val - ptr - 1;
			ei.bei_nrdn.bv_val = ptr;
		}
		if ( ptr < ndn->bv_val ) {
			*res = eip;
			break;
		}
	}

	return rc;
}
Пример #11
0
/*
 * dnRelativeMatch routine
 */
int
dnRelativeMatch(
	int *matchp,
	slap_mask_t flags,
	Syntax *syntax,
	MatchingRule *mr,
	struct berval *value,
	void *assertedValue )
{
	int match;
	struct berval *asserted = (struct berval *) assertedValue;

	assert( matchp != NULL );
	assert( value != NULL );
	assert( assertedValue != NULL );
	assert( !BER_BVISNULL( value ) );
	assert( !BER_BVISNULL( asserted ) );

	if( mr == slap_schema.si_mr_dnSubtreeMatch ) {
		if( asserted->bv_len > value->bv_len ) {
			match = -1;
		} else if ( asserted->bv_len == value->bv_len ) {
			match = memcmp( value->bv_val, asserted->bv_val, 
				value->bv_len );
		} else {
			if( DN_SEPARATOR(
				value->bv_val[value->bv_len - asserted->bv_len - 1] ))
			{
				match = memcmp(
					&value->bv_val[value->bv_len - asserted->bv_len],
					asserted->bv_val, 
					asserted->bv_len );
			} else {
				match = 1;
			}
		}

		*matchp = match;
		return LDAP_SUCCESS;
	}

	if( mr == slap_schema.si_mr_dnSuperiorMatch ) {
		asserted = value;
		value = (struct berval *) assertedValue;
		mr = slap_schema.si_mr_dnSubordinateMatch;
	}

	if( mr == slap_schema.si_mr_dnSubordinateMatch ) {
		if( asserted->bv_len >= value->bv_len ) {
			match = -1;
		} else {
			if( DN_SEPARATOR(
				value->bv_val[value->bv_len - asserted->bv_len - 1] ))
			{
				match = memcmp(
					&value->bv_val[value->bv_len - asserted->bv_len],
					asserted->bv_val, 
					asserted->bv_len );
			} else {
				match = 1;
			}
		}

		*matchp = match;
		return LDAP_SUCCESS;
	}

	if( mr == slap_schema.si_mr_dnOneLevelMatch ) {
		if( asserted->bv_len >= value->bv_len ) {
			match = -1;
		} else {
			if( DN_SEPARATOR(
				value->bv_val[value->bv_len - asserted->bv_len - 1] ))
			{
				match = memcmp(
					&value->bv_val[value->bv_len - asserted->bv_len],
					asserted->bv_val, 
					asserted->bv_len );

				if( !match ) {
					struct berval rdn;
					rdn.bv_val = value->bv_val;
					rdn.bv_len = value->bv_len - asserted->bv_len - 1;
					match = dnIsOneLevelRDN( &rdn ) ? 0 : 1;
				}
			} else {
				match = 1;
			}
		}

		*matchp = match;
		return LDAP_SUCCESS;
	}

	/* should not be reachable */
	assert( 0 );
	return LDAP_OTHER;
}