1 /* $NetBSD: compare.c,v 1.1.1.3 2018/02/06 01:53:17 christos 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-2017 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 <sys/cdefs.h> 20 __RCSID("$NetBSD: compare.c,v 1.1.1.3 2018/02/06 01:53:17 christos Exp $"); 21 22 #include "portable.h" 23 24 #include <stdio.h> 25 #include <ac/string.h> 26 27 #include "back-mdb.h" 28 29 int 30 mdb_compare( Operation *op, SlapReply *rs ) 31 { 32 struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private; 33 Entry *e = NULL; 34 int manageDSAit = get_manageDSAit( op ); 35 36 MDB_txn *rtxn; 37 mdb_op_info opinfo = {{{0}}}, *moi = &opinfo; 38 39 rs->sr_err = mdb_opinfo_get(op, mdb, 1, &moi); 40 switch(rs->sr_err) { 41 case 0: 42 break; 43 default: 44 send_ldap_error( op, rs, LDAP_OTHER, "internal error" ); 45 return rs->sr_err; 46 } 47 48 rtxn = moi->moi_txn; 49 50 /* get entry */ 51 rs->sr_err = mdb_dn2entry( op, rtxn, NULL, &op->o_req_ndn, &e, NULL, 1 ); 52 switch( rs->sr_err ) { 53 case MDB_NOTFOUND: 54 case 0: 55 break; 56 case LDAP_BUSY: 57 rs->sr_text = "ldap server busy"; 58 goto return_results; 59 default: 60 rs->sr_err = LDAP_OTHER; 61 rs->sr_text = "internal error"; 62 goto return_results; 63 } 64 65 if ( rs->sr_err == MDB_NOTFOUND ) { 66 if ( e != NULL ) { 67 /* return referral only if "disclose" is granted on the object */ 68 if ( ! access_allowed( op, e, slap_schema.si_ad_entry, 69 NULL, ACL_DISCLOSE, NULL ) ) 70 { 71 rs->sr_err = LDAP_NO_SUCH_OBJECT; 72 73 } else { 74 rs->sr_matched = ch_strdup( e->e_dn ); 75 if ( is_entry_referral( e )) { 76 BerVarray ref = get_entry_referrals( op, e ); 77 rs->sr_ref = referral_rewrite( ref, &e->e_name, 78 &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 79 ber_bvarray_free( ref ); 80 } else { 81 rs->sr_ref = NULL; 82 } 83 rs->sr_err = LDAP_REFERRAL; 84 } 85 mdb_entry_return( op, e ); 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 rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED; 95 send_ldap_result( op, rs ); 96 goto done; 97 } 98 99 if (!manageDSAit && is_entry_referral( e ) ) { 100 /* return referral only if "disclose" is granted on the object */ 101 if ( !access_allowed( op, e, slap_schema.si_ad_entry, 102 NULL, ACL_DISCLOSE, NULL ) ) 103 { 104 rs->sr_err = LDAP_NO_SUCH_OBJECT; 105 } else { 106 /* entry is a referral, don't allow compare */ 107 rs->sr_ref = get_entry_referrals( op, e ); 108 rs->sr_err = LDAP_REFERRAL; 109 rs->sr_matched = e->e_name.bv_val; 110 } 111 112 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); 113 114 send_ldap_result( op, rs ); 115 116 ber_bvarray_free( rs->sr_ref ); 117 rs->sr_ref = NULL; 118 rs->sr_matched = NULL; 119 goto done; 120 } 121 122 rs->sr_err = slap_compare_entry( op, e, op->orc_ava ); 123 124 return_results: 125 send_ldap_result( op, rs ); 126 127 switch ( rs->sr_err ) { 128 case LDAP_COMPARE_FALSE: 129 case LDAP_COMPARE_TRUE: 130 rs->sr_err = LDAP_SUCCESS; 131 break; 132 } 133 134 done: 135 if ( moi == &opinfo ) { 136 mdb_txn_reset( moi->moi_txn ); 137 LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next ); 138 } else { 139 moi->moi_ref--; 140 } 141 /* free entry */ 142 if ( e != NULL ) { 143 mdb_entry_return( op, e ); 144 } 145 146 return rs->sr_err; 147 } 148