X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fcompare.c;h=87a88e4886c107b8e3a295d79660b60db3cec6c9;hb=ad0858dea49bd3155d4ba210ee3afd923179f217;hp=544b7ca1cd8c5b8350a7de4e112d806963ac04d0;hpb=175ace59c8906d27639d5ee72cfaa3e4de2b2c02;p=openldap diff --git a/servers/slapd/compare.c b/servers/slapd/compare.c index 544b7ca1cd..87a88e4886 100644 --- a/servers/slapd/compare.c +++ b/servers/slapd/compare.c @@ -1,3 +1,8 @@ +/* $OpenLDAP$ */ +/* + * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved. + * COPYING RESTRICTIONS APPLY, see COPYRIGHT file + */ /* * Copyright (c) 1995 Regents of the University of Michigan. * All rights reserved. @@ -13,32 +18,43 @@ #include "portable.h" #include - #include +#include "ldap_pvt.h" #include "slap.h" +static int compare_entry( + Connection *conn, + Operation *op, + Entry *e, + AttributeAssertion *ava ); + int do_compare( Connection *conn, Operation *op ) { - char *ndn; - Ava ava; + Entry *entry = NULL; + struct berval dn = { 0, NULL }; + struct berval pdn = { 0, NULL }; + struct berval ndn = { 0, NULL }; + struct berval desc = { 0, NULL }; + struct berval value = { 0, NULL }; + AttributeAssertion ava = { 0 }; Backend *be; int rc = LDAP_SUCCESS; + const char *text = NULL; + int manageDSAit; - Debug( LDAP_DEBUG_TRACE, "do_compare\n", 0, 0, 0 ); - - if( op->o_bind_in_progress ) { - Debug( LDAP_DEBUG_ANY, "do_compare: SASL bind in progress.\n", - 0, 0, 0 ); - send_ldap_result( conn, op, LDAP_SASL_BIND_IN_PROGRESS, NULL, - "SASL bind in progress" ); - return LDAP_SASL_BIND_IN_PROGRESS; - } + ava.aa_desc = NULL; +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY, + "do_compare: conn %d\n", conn->c_connid )); +#else + Debug( LDAP_DEBUG_TRACE, "do_compare\n", 0, 0, 0 ); +#endif /* * Parse the compare request. It looks like this: * @@ -51,58 +67,247 @@ do_compare( * } */ - if ( ber_scanf( op->o_ber, "{a{ao}}", &ndn, &ava.ava_type, - &ava.ava_value ) == LBER_ERROR ) { + if ( ber_scanf( op->o_ber, "{m" /*}*/, &dn ) == LBER_ERROR ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ERR, + "do_compare: conn %d ber_scanf failed\n", conn->c_connid )); +#else Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 ); - send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR, NULL, "" ); - return rc; +#endif + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + return SLAPD_DISCONNECT; + } + + if ( ber_scanf( op->o_ber, "{mm}", &desc, &value ) == LBER_ERROR ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ERR, + "do_compare: conn %d get ava failed\n", conn->c_connid )); +#else + Debug( LDAP_DEBUG_ANY, "do_compare: get ava failed\n", 0, 0, 0 ); +#endif + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + rc = SLAPD_DISCONNECT; + goto cleanup; + } + + if ( ber_scanf( op->o_ber, /*{*/ "}" ) == LBER_ERROR ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ERR, + "do_compare: conn %d ber_scanf failed\n", conn->c_connid )); +#else + Debug( LDAP_DEBUG_ANY, "ber_scanf failed\n", 0, 0, 0 ); +#endif + send_ldap_disconnect( conn, op, + LDAP_PROTOCOL_ERROR, "decoding error" ); + rc = SLAPD_DISCONNECT; + goto cleanup; } -#ifdef GET_CTRLS if( ( rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) { - free( ndn ); - ava_free( &ava, 0 ); +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, + "do_compare: conn %d get_ctrls failed\n", conn->c_connid )); +#else Debug( LDAP_DEBUG_ANY, "do_compare: get_ctrls failed\n", 0, 0, 0 ); - return rc; +#endif + goto cleanup; } + + rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn ); + if( rc != LDAP_SUCCESS ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_INFO, + "do_compare: conn %d invalid dn (%s)\n", + conn->c_connid, dn.bv_val )); +#else + Debug( LDAP_DEBUG_ANY, + "do_compare: invalid dn (%s)\n", dn.bv_val, 0, 0 ); #endif + send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL, + "invalid DN", NULL, NULL ); + goto cleanup; + } - value_normalize( ava.ava_value.bv_val, attr_syntax( ava.ava_type ) ); + rc = slap_bv2ad( &desc, &ava.aa_desc, &text ); + if( rc != LDAP_SUCCESS ) { + send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); + goto cleanup; + } - Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n", - ndn, ava.ava_type, ava.ava_value.bv_val ); + rc = value_validate_normalize( ava.aa_desc, SLAP_MR_EQUALITY, + &value, &ava.aa_value, &text ); + if( rc != LDAP_SUCCESS ) { + send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); + goto cleanup; + } + + if( strcasecmp( ndn.bv_val, LDAP_ROOT_DSE ) == 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ARGS, + "do_compare: conn %d dn (%s) attr(%s) value (%s)\n", + conn->c_connid, pdn.bv_val, + ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val )); +#else + Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n", + pdn.bv_val, ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val ); +#endif + + Statslog( LDAP_DEBUG_STATS, + "conn=%ld op=%d CMP dn=\"%s\" attr=\"%s\"\n", + op->o_connid, op->o_opid, pdn.bv_val, + ava.aa_desc->ad_cname.bv_val, 0 ); + + rc = backend_check_restrictions( NULL, conn, op, NULL, &text ) ; + if( rc != LDAP_SUCCESS ) { + send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); + goto cleanup; + } + + rc = root_dse_info( conn, &entry, &text ); + if( rc != LDAP_SUCCESS ) { + send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); + goto cleanup; + } + + } else if ( strcasecmp( ndn.bv_val, SLAPD_SCHEMA_DN ) == 0 ) { +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ARGS, + "do_compare: conn %d dn (%s) attr(%s) value (%s)\n", + conn->c_connid, pdn.bv_val, ava.aa_desc->ad_cname.bv_val, + ava.aa_value.bv_val )); +#else + Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n", + pdn.bv_val, ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val ); +#endif + + Statslog( LDAP_DEBUG_STATS, + "conn=%ld op=%d CMP dn=\"%s\" attr=\"%s\"\n", + op->o_connid, op->o_opid, pdn.bv_val, + ava.aa_desc->ad_cname.bv_val, 0 ); + + rc = backend_check_restrictions( NULL, conn, op, NULL, &text ) ; + if( rc != LDAP_SUCCESS ) { + send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); + rc = 0; + goto cleanup; + } + + rc = schema_info( &entry, &text ); + if( rc != LDAP_SUCCESS ) { + send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); + rc = 0; + goto cleanup; + } + } + + if( entry ) { + rc = compare_entry( conn, op, entry, &ava ); + entry_free( entry ); - ndn = dn_normalize_case( ndn ); + send_ldap_result( conn, op, rc, NULL, text, NULL, NULL ); - Statslog( LDAP_DEBUG_STATS, "conn=%d op=%d CMP dn=\"%s\" attr=\"%s\"\n", - conn->c_connid, op->o_opid, ndn, ava.ava_type, 0 ); + if( rc == LDAP_COMPARE_TRUE || rc == LDAP_COMPARE_FALSE ) { + rc = 0; + } + + goto cleanup; + } + + manageDSAit = get_manageDSAit( op ); /* * 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( ndn )) == NULL ) { - free( ndn ); - ava_free( &ava, 0 ); + if ( (be = select_backend( &ndn, manageDSAit, 0 )) == NULL ) { + BerVarray ref = referral_rewrite( default_referral, + NULL, &pdn, LDAP_SCOPE_DEFAULT ); + + send_ldap_result( conn, op, rc = LDAP_REFERRAL, + NULL, NULL, ref ? ref : default_referral, NULL ); - send_ldap_result( conn, op, rc = LDAP_PARTIAL_RESULTS, NULL, - default_referral ); - return 1; + ber_bvarray_free( ref ); + rc = 0; + goto cleanup; } - /* alias suffix if approp */ - ndn = suffixAlias( ndn, op, be ); + /* 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 cleanup; + } + + /* check for referrals */ + rc = backend_check_referrals( be, conn, op, &pdn, &ndn ); + if ( rc != LDAP_SUCCESS ) { + goto cleanup; + } + +#ifdef NEW_LOGGING + LDAP_LOG(( "operation", LDAP_LEVEL_ARGS, + "do_compare: conn %d dn (%s) attr(%s) value (%s)\n", + conn->c_connid, pdn.bv_val, ava.aa_desc->ad_cname.bv_val, + ava.aa_value.bv_val )); +#else + Debug( LDAP_DEBUG_ARGS, "do_compare: dn (%s) attr (%s) value (%s)\n", + pdn.bv_val, ava.aa_desc->ad_cname.bv_val, ava.aa_value.bv_val ); +#endif + + Statslog( LDAP_DEBUG_STATS, "conn=%ld op=%d CMP dn=\"%s\" attr=\"%s\"\n", + op->o_connid, op->o_opid, pdn.bv_val, + ava.aa_desc->ad_cname.bv_val, 0 ); + + + /* deref suffix alias if appropriate */ + suffix_alias( be, &ndn ); if ( be->be_compare ) { - (*be->be_compare)( be, conn, op, ndn, &ava ); + (*be->be_compare)( be, conn, op, &pdn, &ndn, &ava ); } else { - send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, NULL, - "Function not implemented" ); + send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM, + NULL, "operation not supported within namingContext", + NULL, NULL ); + } + +cleanup: + free( pdn.bv_val ); + free( ndn.bv_val ); + if ( ava.aa_value.bv_val ) free( ava.aa_value.bv_val ); + + return rc; +} + +static int compare_entry( + Connection *conn, + Operation *op, + Entry *e, + AttributeAssertion *ava ) +{ + int rc = LDAP_NO_SUCH_ATTRIBUTE; + Attribute *a; + + if ( ! access_allowed( NULL, conn, op, e, + ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) ) + { + return LDAP_INSUFFICIENT_ACCESS; } - free( ndn ); - ava_free( &ava, 0 ); + for(a = attrs_find( e->e_attrs, ava->aa_desc ); + a != NULL; + a = attrs_find( a->a_next, ava->aa_desc )) + { + rc = LDAP_COMPARE_FALSE; + + if ( value_find( ava->aa_desc, a->a_vals, &ava->aa_value ) == 0 ) { + rc = LDAP_COMPARE_TRUE; + break; + } + } return rc; }