Back to index

openldap  2.4.31
compare.c
Go to the documentation of this file.
00001 /* compare.c - mdb 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-mdb.h"
00023 
00024 int
00025 mdb_compare( Operation *op, SlapReply *rs )
00026 {
00027        struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
00028        Entry         *e = NULL;
00029        int           manageDSAit = get_manageDSAit( op );
00030 
00031        MDB_txn              *rtxn;
00032        mdb_op_info   opinfo = {{{0}}}, *moi = &opinfo;
00033 
00034        rs->sr_err = mdb_opinfo_get(op, mdb, 1, &moi);
00035        switch(rs->sr_err) {
00036        case 0:
00037               break;
00038        default:
00039               send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
00040               return rs->sr_err;
00041        }
00042 
00043        rtxn = moi->moi_txn;
00044 
00045        /* get entry */
00046        rs->sr_err = mdb_dn2entry( op, rtxn, NULL, &op->o_req_ndn, &e, 1 );
00047        switch( rs->sr_err ) {
00048        case MDB_NOTFOUND:
00049        case 0:
00050               break;
00051        case LDAP_BUSY:
00052               rs->sr_text = "ldap server busy";
00053               goto return_results;
00054        default:
00055               rs->sr_err = LDAP_OTHER;
00056               rs->sr_text = "internal error";
00057               goto return_results;
00058        }
00059 
00060        if ( rs->sr_err == MDB_NOTFOUND ) {
00061               if ( e != NULL ) {
00062                      /* return referral only if "disclose" is granted on the object */
00063                      if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
00064                             NULL, ACL_DISCLOSE, NULL ) )
00065                      {
00066                             rs->sr_err = LDAP_NO_SUCH_OBJECT;
00067 
00068                      } else {
00069                             rs->sr_matched = ch_strdup( e->e_dn );
00070                             if ( is_entry_referral( e )) {
00071                                    BerVarray ref = get_entry_referrals( op, e );
00072                                    rs->sr_ref = referral_rewrite( ref, &e->e_name,
00073                                           &op->o_req_dn, LDAP_SCOPE_DEFAULT );
00074                                    ber_bvarray_free( ref );
00075                             } else {
00076                                    rs->sr_ref = NULL;
00077                             }
00078                             rs->sr_err = LDAP_REFERRAL;
00079                      }
00080                      mdb_entry_return( op, e );
00081                      e = NULL;
00082 
00083               } else {
00084                      rs->sr_ref = referral_rewrite( default_referral,
00085                             NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
00086                      rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
00087               }
00088 
00089               rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
00090               send_ldap_result( op, rs );
00091               goto done;
00092        }
00093 
00094        if (!manageDSAit && is_entry_referral( e ) ) {
00095               /* return referral only if "disclose" is granted on the object */
00096               if ( !access_allowed( op, e, slap_schema.si_ad_entry,
00097                      NULL, ACL_DISCLOSE, NULL ) )
00098               {
00099                      rs->sr_err = LDAP_NO_SUCH_OBJECT;
00100               } else {
00101                      /* entry is a referral, don't allow compare */
00102                      rs->sr_ref = get_entry_referrals( op, e );
00103                      rs->sr_err = LDAP_REFERRAL;
00104                      rs->sr_matched = e->e_name.bv_val;
00105               }
00106 
00107               Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 );
00108 
00109               send_ldap_result( op, rs );
00110 
00111               ber_bvarray_free( rs->sr_ref );
00112               rs->sr_ref = NULL;
00113               rs->sr_matched = NULL;
00114               goto done;
00115        }
00116 
00117        rs->sr_err = slap_compare_entry( op, e, op->orc_ava );
00118 
00119 return_results:
00120        send_ldap_result( op, rs );
00121 
00122        switch ( rs->sr_err ) {
00123        case LDAP_COMPARE_FALSE:
00124        case LDAP_COMPARE_TRUE:
00125               rs->sr_err = LDAP_SUCCESS;
00126               break;
00127        }
00128 
00129 done:
00130        if ( moi == &opinfo ) {
00131               mdb_txn_reset( moi->moi_txn );
00132               LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
00133        }
00134        /* free entry */
00135        if ( e != NULL ) {
00136               mdb_entry_return( op, e );
00137        }
00138 
00139        return rs->sr_err;
00140 }