1/* $NetBSD: compare.c,v 1.1.1.3 2010/12/12 15:22:54 adam Exp $ */ 2 3/* compare.c - bdb backend compare routine */ 4/* OpenLDAP: pkg/ldap/servers/slapd/back-bdb/compare.c,v 1.51.2.8 2010/04/13 20:23:23 kurt Exp */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2000-2010 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-bdb.h" 25 26int 27bdb_compare( Operation *op, SlapReply *rs ) 28{ 29 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; 30 Entry *e = NULL; 31 EntryInfo *ei; 32 Attribute *a; 33 int manageDSAit = get_manageDSAit( op ); 34 35 DB_TXN *rtxn; 36 DB_LOCK lock; 37 38 rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn); 39 switch(rs->sr_err) { 40 case 0: 41 break; 42 default: 43 send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); 44 return rs->sr_err; 45 } 46 47dn2entry_retry: 48 /* get entry */ 49 rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1, 50 &lock ); 51 52 switch( rs->sr_err ) { 53 case DB_NOTFOUND: 54 case 0: 55 break; 56 case LDAP_BUSY: 57 rs->sr_text = "ldap server busy"; 58 goto return_results; 59 case DB_LOCK_DEADLOCK: 60 case DB_LOCK_NOTGRANTED: 61 goto dn2entry_retry; 62 default: 63 rs->sr_err = LDAP_OTHER; 64 rs->sr_text = "internal error"; 65 goto return_results; 66 } 67 68 e = ei->bei_e; 69 if ( rs->sr_err == DB_NOTFOUND ) { 70 if ( e != NULL ) { 71 /* return referral only if "disclose" is granted on the object */ 72 if ( ! access_allowed( op, e, slap_schema.si_ad_entry, 73 NULL, ACL_DISCLOSE, NULL ) ) 74 { 75 rs->sr_err = LDAP_NO_SUCH_OBJECT; 76 77 } else { 78 rs->sr_matched = ch_strdup( e->e_dn ); 79 rs->sr_ref = is_entry_referral( e ) 80 ? get_entry_referrals( op, e ) 81 : NULL; 82 rs->sr_err = LDAP_REFERRAL; 83 } 84 85 bdb_cache_return_entry_r( bdb, e, &lock ); 86 e = NULL; 87 88 } else { 89 rs->sr_ref = referral_rewrite( default_referral, 90 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 91 rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT; 92 } 93 94 send_ldap_result( op, rs ); 95 96 ber_bvarray_free( rs->sr_ref ); 97 free( (char *)rs->sr_matched ); 98 rs->sr_ref = NULL; 99 rs->sr_matched = NULL; 100 101 goto done; 102 } 103 104 if (!manageDSAit && is_entry_referral( e ) ) { 105 /* return referral only if "disclose" is granted on the object */ 106 if ( !access_allowed( op, e, slap_schema.si_ad_entry, 107 NULL, ACL_DISCLOSE, NULL ) ) 108 { 109 rs->sr_err = LDAP_NO_SUCH_OBJECT; 110 } else { 111 /* entry is a referral, don't allow compare */ 112 rs->sr_ref = get_entry_referrals( op, e ); 113 rs->sr_err = LDAP_REFERRAL; 114 rs->sr_matched = e->e_name.bv_val; 115 } 116 117 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); 118 119 send_ldap_result( op, rs ); 120 121 ber_bvarray_free( rs->sr_ref ); 122 rs->sr_ref = NULL; 123 rs->sr_matched = NULL; 124 goto done; 125 } 126 127 if ( get_assert( op ) && 128 ( test_filter( op, e, get_assertion( op )) != LDAP_COMPARE_TRUE )) 129 { 130 if ( !access_allowed( op, e, slap_schema.si_ad_entry, 131 NULL, ACL_DISCLOSE, NULL ) ) 132 { 133 rs->sr_err = LDAP_NO_SUCH_OBJECT; 134 } else { 135 rs->sr_err = LDAP_ASSERTION_FAILED; 136 } 137 goto return_results; 138 } 139 140 if ( !access_allowed( op, e, op->oq_compare.rs_ava->aa_desc, 141 &op->oq_compare.rs_ava->aa_value, ACL_COMPARE, NULL ) ) 142 { 143 /* return error only if "disclose" 144 * is granted on the object */ 145 if ( !access_allowed( op, e, slap_schema.si_ad_entry, 146 NULL, ACL_DISCLOSE, NULL ) ) 147 { 148 rs->sr_err = LDAP_NO_SUCH_OBJECT; 149 } else { 150 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 151 } 152 goto return_results; 153 } 154 155 rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE; 156 157 for ( a = attrs_find( e->e_attrs, op->oq_compare.rs_ava->aa_desc ); 158 a != NULL; 159 a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc ) ) 160 { 161 rs->sr_err = LDAP_COMPARE_FALSE; 162 163 if ( attr_valfind( a, 164 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | 165 SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, 166 &op->oq_compare.rs_ava->aa_value, NULL, 167 op->o_tmpmemctx ) == 0 ) 168 { 169 rs->sr_err = LDAP_COMPARE_TRUE; 170 break; 171 } 172 } 173 174return_results: 175 send_ldap_result( op, rs ); 176 177 switch ( rs->sr_err ) { 178 case LDAP_COMPARE_FALSE: 179 case LDAP_COMPARE_TRUE: 180 rs->sr_err = LDAP_SUCCESS; 181 break; 182 } 183 184done: 185 /* free entry */ 186 if ( e != NULL ) { 187 bdb_cache_return_entry_r( bdb, e, &lock ); 188 } 189 190 return rs->sr_err; 191} 192