1 /* compare.cpp - ndb backend compare routine */ 2 /* OpenLDAP: pkg/ldap/servers/slapd/back-ndb/compare.cpp,v 1.3.2.3 2010/04/13 20:23:34 kurt Exp */ 3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 2008-2010 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 /* ACKNOWLEDGEMENTS: 17 * This work was initially developed by Howard Chu for inclusion 18 * in OpenLDAP Software. This work was sponsored by MySQL. 19 */ 20 21 #include "portable.h" 22 23 #include <stdio.h> 24 #include <ac/string.h> 25 26 #include "back-ndb.h" 27 28 int 29 ndb_back_compare( Operation *op, SlapReply *rs ) 30 { 31 struct ndb_info *ni = (struct ndb_info *) op->o_bd->be_private; 32 Entry e = {0}; 33 Attribute *a; 34 int manageDSAit = get_manageDSAit( op ); 35 36 NdbArgs NA; 37 NdbRdns rdns; 38 struct berval matched; 39 40 /* Get our NDB handle */ 41 rs->sr_err = ndb_thread_handle( op, &NA.ndb ); 42 43 rdns.nr_num = 0; 44 NA.rdns = &rdns; 45 e.e_name = op->o_req_dn; 46 e.e_nname = op->o_req_ndn; 47 NA.e = &e; 48 49 dn2entry_retry: 50 NA.txn = NA.ndb->startTransaction(); 51 rs->sr_text = NULL; 52 if( !NA.txn ) { 53 Debug( LDAP_DEBUG_TRACE, 54 LDAP_XSTRING(ndb_compare) ": startTransaction failed: %s (%d)\n", 55 NA.ndb->getNdbError().message, NA.ndb->getNdbError().code, 0 ); 56 rs->sr_err = LDAP_OTHER; 57 rs->sr_text = "internal error"; 58 goto return_results; 59 } 60 61 NA.ocs = NULL; 62 /* get entry */ 63 rs->sr_err = ndb_entry_get_info( op, &NA, 0, &matched ); 64 switch( rs->sr_err ) { 65 case 0: 66 break; 67 case LDAP_NO_SUCH_OBJECT: 68 rs->sr_matched = matched.bv_val; 69 if ( NA.ocs ) 70 ndb_check_referral( op, rs, &NA ); 71 goto return_results; 72 case LDAP_BUSY: 73 rs->sr_text = "ldap server busy"; 74 goto return_results; 75 #if 0 76 case DB_LOCK_DEADLOCK: 77 case DB_LOCK_NOTGRANTED: 78 goto dn2entry_retry; 79 #endif 80 default: 81 rs->sr_err = LDAP_OTHER; 82 rs->sr_text = "internal error"; 83 goto return_results; 84 } 85 86 rs->sr_err = ndb_entry_get_data( op, &NA, 0 ); 87 ber_bvarray_free_x( NA.ocs, op->o_tmpmemctx ); 88 if (!manageDSAit && is_entry_referral( &e ) ) { 89 /* return referral only if "disclose" is granted on the object */ 90 if ( !access_allowed( op, &e, slap_schema.si_ad_entry, 91 NULL, ACL_DISCLOSE, NULL ) ) 92 { 93 rs->sr_err = LDAP_NO_SUCH_OBJECT; 94 } else { 95 /* entry is a referral, don't allow compare */ 96 rs->sr_ref = get_entry_referrals( op, &e ); 97 rs->sr_err = LDAP_REFERRAL; 98 rs->sr_matched = e.e_name.bv_val; 99 rs->sr_flags |= REP_REF_MUSTBEFREED; 100 } 101 102 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 ); 103 goto return_results; 104 } 105 106 if ( get_assert( op ) && 107 ( test_filter( op, &e, (Filter *)get_assertion( op )) != LDAP_COMPARE_TRUE )) 108 { 109 if ( !access_allowed( op, &e, slap_schema.si_ad_entry, 110 NULL, ACL_DISCLOSE, NULL ) ) 111 { 112 rs->sr_err = LDAP_NO_SUCH_OBJECT; 113 } else { 114 rs->sr_err = LDAP_ASSERTION_FAILED; 115 } 116 goto return_results; 117 } 118 119 if ( !access_allowed( op, &e, op->oq_compare.rs_ava->aa_desc, 120 &op->oq_compare.rs_ava->aa_value, ACL_COMPARE, NULL ) ) 121 { 122 /* return error only if "disclose" 123 * is granted on the object */ 124 if ( !access_allowed( op, &e, slap_schema.si_ad_entry, 125 NULL, ACL_DISCLOSE, NULL ) ) 126 { 127 rs->sr_err = LDAP_NO_SUCH_OBJECT; 128 } else { 129 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 130 } 131 goto return_results; 132 } 133 134 rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE; 135 136 for ( a = attrs_find( e.e_attrs, op->oq_compare.rs_ava->aa_desc ); 137 a != NULL; 138 a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc ) ) 139 { 140 rs->sr_err = LDAP_COMPARE_FALSE; 141 142 if ( attr_valfind( a, 143 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | 144 SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, 145 &op->oq_compare.rs_ava->aa_value, NULL, 146 op->o_tmpmemctx ) == 0 ) 147 { 148 rs->sr_err = LDAP_COMPARE_TRUE; 149 break; 150 } 151 } 152 153 return_results: 154 NA.txn->close(); 155 if ( e.e_attrs ) { 156 attrs_free( e.e_attrs ); 157 e.e_attrs = NULL; 158 } 159 send_ldap_result( op, rs ); 160 161 switch ( rs->sr_err ) { 162 case LDAP_COMPARE_FALSE: 163 case LDAP_COMPARE_TRUE: 164 rs->sr_err = LDAP_SUCCESS; 165 break; 166 } 167 168 return rs->sr_err; 169 } 170