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