1 /* $NetBSD: compare.c,v 1.1.1.1 2014/05/28 09:58:49 tron Exp $ */ 2 3 /* compare.c - mdb backend compare routine */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2000-2014 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 19 #include "portable.h" 20 21 #include <stdio.h> 22 #include <ac/string.h> 23 24 #include "back-mdb.h" 25 26 int 27 mdb_compare( Operation *op, SlapReply *rs ) 28 { 29 struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; 30 Entry *e = NULL; 31 int manageDSAit = get_manageDSAit( op ); 32 33 MDB_txn *rtxn; 34 mdb_op_info opinfo = {{{0}}}, *moi = &opinfo; 35 36 rs->sr_err = mdb_opinfo_get(op, mdb, 1, &moi); 37 switch(rs->sr_err) { 38 case 0: 39 break; 40 default: 41 send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); 42 return rs->sr_err; 43 } 44 45 rtxn = moi->moi_txn; 46 47 /* get entry */ 48 rs->sr_err = mdb_dn2entry( op, rtxn, NULL, &op->o_req_ndn, &e, NULL, 1 ); 49 switch( rs->sr_err ) { 50 case MDB_NOTFOUND: 51 case 0: 52 break; 53 case LDAP_BUSY: 54 rs->sr_text = "ldap server busy"; 55 goto return_results; 56 default: 57 rs->sr_err = LDAP_OTHER; 58 rs->sr_text = "internal error"; 59 goto return_results; 60 } 61 62 if ( rs->sr_err == MDB_NOTFOUND ) { 63 if ( e != NULL ) { 64 /* return referral only if "disclose" is granted on the object */ 65 if ( ! access_allowed( op, e, slap_schema.si_ad_entry, 66 NULL, ACL_DISCLOSE, NULL ) ) 67 { 68 rs->sr_err = LDAP_NO_SUCH_OBJECT; 69 70 } else { 71 rs->sr_matched = ch_strdup( e->e_dn ); 72 if ( is_entry_referral( e )) { 73 BerVarray ref = get_entry_referrals( op, e ); 74 rs->sr_ref = referral_rewrite( ref, &e->e_name, 75 &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 76 ber_bvarray_free( ref ); 77 } else { 78 rs->sr_ref = NULL; 79 } 80 rs->sr_err = LDAP_REFERRAL; 81 } 82 mdb_entry_return( op, e ); 83 e = NULL; 84 85 } else { 86 rs->sr_ref = referral_rewrite( default_referral, 87 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 88 rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT; 89 } 90 91 rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; 92 send_ldap_result( op, rs ); 93 goto done; 94 } 95 96 if (!manageDSAit && is_entry_referral( e ) ) { 97 /* return referral only if "disclose" is granted on the object */ 98 if ( !access_allowed( op, e, slap_schema.si_ad_entry, 99 NULL, ACL_DISCLOSE, NULL ) ) 100 { 101 rs->sr_err = LDAP_NO_SUCH_OBJECT; 102 } else { 103 /* entry is a referral, don't allow compare */ 104 rs->sr_ref = get_entry_referrals( op, e ); 105 rs->sr_err = LDAP_REFERRAL; 106 rs->sr_matched = e->e_name.bv_val; 107 } 108 109 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); 110 111 send_ldap_result( op, rs ); 112 113 ber_bvarray_free( rs->sr_ref ); 114 rs->sr_ref = NULL; 115 rs->sr_matched = NULL; 116 goto done; 117 } 118 119 rs->sr_err = slap_compare_entry( op, e, op->orc_ava ); 120 121 return_results: 122 send_ldap_result( op, rs ); 123 124 switch ( rs->sr_err ) { 125 case LDAP_COMPARE_FALSE: 126 case LDAP_COMPARE_TRUE: 127 rs->sr_err = LDAP_SUCCESS; 128 break; 129 } 130 131 done: 132 if ( moi == &opinfo ) { 133 mdb_txn_reset( moi->moi_txn ); 134 LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next ); 135 } else { 136 moi->moi_ref--; 137 } 138 /* free entry */ 139 if ( e != NULL ) { 140 mdb_entry_return( op, e ); 141 } 142 143 return rs->sr_err; 144 } 145