]> git.sur5r.net Git - openldap/blob - servers/slapd/back-mdb/compare.c
More porting
[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-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-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
33         rs->sr_err = mdb_reader_get(op, mdb->mi_dbenv, &rtxn);
34         switch(rs->sr_err) {
35         case 0:
36                 break;
37         default:
38                 send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
39                 return rs->sr_err;
40         }
41
42         /* get entry */
43         rs->sr_err = mdb_dn2entry( op, rtxn, &op->o_req_ndn, &e, 1 );
44         switch( rs->sr_err ) {
45         case MDB_NOTFOUND:
46         case 0:
47                 break;
48         case LDAP_BUSY:
49                 rs->sr_text = "ldap server busy";
50                 goto return_results;
51         default:
52                 rs->sr_err = LDAP_OTHER;
53                 rs->sr_text = "internal error";
54                 goto return_results;
55         }
56
57         if ( rs->sr_err == MDB_NOTFOUND ) {
58                 if ( e != NULL ) {
59                         /* return referral only if "disclose" is granted on the object */
60                         if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
61                                 NULL, ACL_DISCLOSE, NULL ) )
62                         {
63                                 rs->sr_err = LDAP_NO_SUCH_OBJECT;
64
65                         } else {
66                                 rs->sr_matched = ch_strdup( e->e_dn );
67                                 rs->sr_ref = is_entry_referral( e )
68                                         ? get_entry_referrals( op, e )
69                                         : NULL;
70                                 rs->sr_err = LDAP_REFERRAL;
71                         }
72
73                         mdb_entry_return( e );
74                         e = NULL;
75
76                 } else {
77                         rs->sr_ref = referral_rewrite( default_referral,
78                                 NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
79                         rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
80                 }
81
82                 rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
83                 send_ldap_result( op, rs );
84                 goto done;
85         }
86
87         if (!manageDSAit && is_entry_referral( e ) ) {
88                 /* return referral only if "disclose" is granted on the object */
89                 if ( !access_allowed( op, e, slap_schema.si_ad_entry,
90                         NULL, ACL_DISCLOSE, NULL ) )
91                 {
92                         rs->sr_err = LDAP_NO_SUCH_OBJECT;
93                 } else {
94                         /* entry is a referral, don't allow compare */
95                         rs->sr_ref = get_entry_referrals( op, e );
96                         rs->sr_err = LDAP_REFERRAL;
97                         rs->sr_matched = e->e_name.bv_val;
98                 }
99
100                 Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 );
101
102                 send_ldap_result( op, rs );
103
104                 ber_bvarray_free( rs->sr_ref );
105                 rs->sr_ref = NULL;
106                 rs->sr_matched = NULL;
107                 goto done;
108         }
109
110         rs->sr_err = slap_compare_entry( op, e, op->orc_ava );
111
112 return_results:
113         send_ldap_result( op, rs );
114
115         switch ( rs->sr_err ) {
116         case LDAP_COMPARE_FALSE:
117         case LDAP_COMPARE_TRUE:
118                 rs->sr_err = LDAP_SUCCESS;
119                 break;
120         }
121
122 done:
123         /* free entry */
124         if ( e != NULL ) {
125                 mdb_entry_return( e );
126         }
127
128         return rs->sr_err;
129 }