Back to index

openldap  2.4.31
compare.c
Go to the documentation of this file.
00001 /* compare.c - bdb backend compare routine */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2000-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 
00017 #include "portable.h"
00018 
00019 #include <stdio.h>
00020 #include <ac/string.h>
00021 
00022 #include "back-bdb.h"
00023 
00024 int
00025 bdb_compare( Operation *op, SlapReply *rs )
00026 {
00027        struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
00028        Entry         *e = NULL;
00029        EntryInfo     *ei;
00030        int           manageDSAit = get_manageDSAit( op );
00031 
00032        DB_TXN        *rtxn;
00033        DB_LOCK              lock;
00034 
00035        rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
00036        switch(rs->sr_err) {
00037        case 0:
00038               break;
00039        default:
00040               send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
00041               return rs->sr_err;
00042        }
00043 
00044 dn2entry_retry:
00045        /* get entry */
00046        rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1,
00047               &lock );
00048 
00049        switch( rs->sr_err ) {
00050        case DB_NOTFOUND:
00051        case 0:
00052               break;
00053        case LDAP_BUSY:
00054               rs->sr_text = "ldap server busy";
00055               goto return_results;
00056        case DB_LOCK_DEADLOCK:
00057        case DB_LOCK_NOTGRANTED:
00058               goto dn2entry_retry;
00059        default:
00060               rs->sr_err = LDAP_OTHER;
00061               rs->sr_text = "internal error";
00062               goto return_results;
00063        }
00064 
00065        e = ei->bei_e;
00066        if ( rs->sr_err == DB_NOTFOUND ) {
00067               if ( e != NULL ) {
00068                      /* return referral only if "disclose" is granted on the object */
00069                      if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
00070                             NULL, ACL_DISCLOSE, NULL ) )
00071                      {
00072                             rs->sr_err = LDAP_NO_SUCH_OBJECT;
00073 
00074                      } else {
00075                             rs->sr_matched = ch_strdup( e->e_dn );
00076                             rs->sr_ref = is_entry_referral( e )
00077                                    ? get_entry_referrals( op, e )
00078                                    : NULL;
00079                             rs->sr_err = LDAP_REFERRAL;
00080                      }
00081 
00082                      bdb_cache_return_entry_r( bdb, e, &lock );
00083                      e = NULL;
00084 
00085               } else {
00086                      rs->sr_ref = referral_rewrite( default_referral,
00087                             NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
00088                      rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
00089               }
00090 
00091               send_ldap_result( op, rs );
00092 
00093               ber_bvarray_free( rs->sr_ref );
00094               free( (char *)rs->sr_matched );
00095               rs->sr_ref = NULL;
00096               rs->sr_matched = NULL;
00097 
00098               goto done;
00099        }
00100 
00101        if (!manageDSAit && is_entry_referral( e ) ) {
00102               /* return referral only if "disclose" is granted on the object */
00103               if ( !access_allowed( op, e, slap_schema.si_ad_entry,
00104                      NULL, ACL_DISCLOSE, NULL ) )
00105               {
00106                      rs->sr_err = LDAP_NO_SUCH_OBJECT;
00107               } else {
00108                      /* entry is a referral, don't allow compare */
00109                      rs->sr_ref = get_entry_referrals( op, e );
00110                      rs->sr_err = LDAP_REFERRAL;
00111                      rs->sr_matched = e->e_name.bv_val;
00112               }
00113 
00114               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 );
00115 
00116               send_ldap_result( op, rs );
00117 
00118               ber_bvarray_free( rs->sr_ref );
00119               rs->sr_ref = NULL;
00120               rs->sr_matched = NULL;
00121               goto done;
00122        }
00123 
00124        rs->sr_err = slap_compare_entry( op, e, op->orc_ava );
00125 
00126 return_results:
00127        send_ldap_result( op, rs );
00128 
00129        switch ( rs->sr_err ) {
00130        case LDAP_COMPARE_FALSE:
00131        case LDAP_COMPARE_TRUE:
00132               rs->sr_err = LDAP_SUCCESS;
00133               break;
00134        }
00135 
00136 done:
00137        /* free entry */
00138        if ( e != NULL ) {
00139               bdb_cache_return_entry_r( bdb, e, &lock );
00140        }
00141 
00142        return rs->sr_err;
00143 }