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