]> git.sur5r.net Git - openldap/blob - servers/slapd/back-mdb/compare.c
905b5d01d41c0a2e7d8d3ccdd64a37f990f6b4c1
[openldap] / servers / slapd / back-mdb / compare.c
1 /* compare.c - mdb backend compare routine */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2000-2017 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-mdb.h"
23
24 int
25 mdb_compare( Operation *op, SlapReply *rs )
26 {
27         struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
28         Entry           *e = NULL;
29         int             manageDSAit = get_manageDSAit( op );
30
31         MDB_txn         *rtxn;
32         mdb_op_info     opinfo = {{{0}}}, *moi = &opinfo;
33
34         rs->sr_err = mdb_opinfo_get(op, mdb, 1, &moi);
35         switch(rs->sr_err) {
36         case 0:
37                 break;
38         default:
39                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
40                 return rs->sr_err;
41         }
42
43         rtxn = moi->moi_txn;
44
45         /* get entry */
46         rs->sr_err = mdb_dn2entry( op, rtxn, NULL, &op->o_req_ndn, &e, NULL, 1 );
47         switch( rs->sr_err ) {
48         case MDB_NOTFOUND:
49         case 0:
50                 break;
51         case LDAP_BUSY:
52                 rs->sr_text = "ldap server busy";
53                 goto return_results;
54         default:
55                 rs->sr_err = LDAP_OTHER;
56                 rs->sr_text = "internal error";
57                 goto return_results;
58         }
59
60         if ( rs->sr_err == MDB_NOTFOUND ) {
61                 if ( e != NULL ) {
62                         /* return referral only if "disclose" is granted on the object */
63                         if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
64                                 NULL, ACL_DISCLOSE, NULL ) )
65                         {
66                                 rs->sr_err = LDAP_NO_SUCH_OBJECT;
67
68                         } else {
69                                 rs->sr_matched = ch_strdup( e->e_dn );
70                                 if ( is_entry_referral( e )) {
71                                         BerVarray ref = get_entry_referrals( op, e );
72                                         rs->sr_ref = referral_rewrite( ref, &e->e_name,
73                                                 &op->o_req_dn, LDAP_SCOPE_DEFAULT );
74                                         ber_bvarray_free( ref );
75                                 } else {
76                                         rs->sr_ref = NULL;
77                                 }
78                                 rs->sr_err = LDAP_REFERRAL;
79                         }
80                         mdb_entry_return( op, e );
81                         e = NULL;
82
83                 } else {
84                         rs->sr_ref = referral_rewrite( default_referral,
85                                 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
86                         rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
87                 }
88
89                 rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
90                 send_ldap_result( op, rs );
91                 goto done;
92         }
93
94         if (!manageDSAit && is_entry_referral( e ) ) {
95                 /* return referral only if "disclose" is granted on the object */
96                 if ( !access_allowed( op, e, slap_schema.si_ad_entry,
97                         NULL, ACL_DISCLOSE, NULL ) )
98                 {
99                         rs->sr_err = LDAP_NO_SUCH_OBJECT;
100                 } else {
101                         /* entry is a referral, don't allow compare */
102                         rs->sr_ref = get_entry_referrals( op, e );
103                         rs->sr_err = LDAP_REFERRAL;
104                         rs->sr_matched = e->e_name.bv_val;
105                 }
106
107                 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 );
108
109                 send_ldap_result( op, rs );
110
111                 ber_bvarray_free( rs->sr_ref );
112                 rs->sr_ref = NULL;
113                 rs->sr_matched = NULL;
114                 goto done;
115         }
116
117         rs->sr_err = slap_compare_entry( op, e, op->orc_ava );
118
119 return_results:
120         send_ldap_result( op, rs );
121
122         switch ( rs->sr_err ) {
123         case LDAP_COMPARE_FALSE:
124         case LDAP_COMPARE_TRUE:
125                 rs->sr_err = LDAP_SUCCESS;
126                 break;
127         }
128
129 done:
130         if ( moi == &opinfo ) {
131                 mdb_txn_reset( moi->moi_txn );
132                 LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
133         } else {
134                 moi->moi_ref--;
135         }
136         /* free entry */
137         if ( e != NULL ) {
138                 mdb_entry_return( op, e );
139         }
140
141         return rs->sr_err;
142 }