1 /* $NetBSD: search.c,v 1.3 2021/08/14 16:15:00 christos Exp $ */
2
3 /* search.c - monitor backend search function */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 2001-2021 The OpenLDAP Foundation.
8 * Portions Copyright 2001-2003 Pierangelo Masarati.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted only as authorized by the OpenLDAP
13 * Public License.
14 *
15 * A copy of this license is available in file LICENSE in the
16 * top-level directory of the distribution or, alternatively, at
17 * <http://www.OpenLDAP.org/license.html>.
18 */
19 /* ACKNOWLEDGEMENTS:
20 * This work was initially developed by Pierangelo Masarati for inclusion
21 * in OpenLDAP Software.
22 */
23
24 #include <sys/cdefs.h>
25 __RCSID("$NetBSD: search.c,v 1.3 2021/08/14 16:15:00 christos Exp $");
26
27 #include "portable.h"
28
29 #include <stdio.h>
30
31 #include <ac/string.h>
32 #include <ac/socket.h>
33
34 #include "slap.h"
35 #include "back-monitor.h"
36 #include "proto-back-monitor.h"
37
38 static void
monitor_find_children(Operation * op,SlapReply * rs,Entry * e_parent,Entry ** nonv,Entry ** vol)39 monitor_find_children(
40 Operation *op,
41 SlapReply *rs,
42 Entry *e_parent,
43 Entry **nonv,
44 Entry **vol
45 )
46 {
47 monitor_entry_t *mp;
48
49 mp = ( monitor_entry_t * )e_parent->e_private;
50 *nonv = mp->mp_children;
51
52 if ( MONITOR_HAS_VOLATILE_CH( mp ) ) {
53 monitor_entry_create( op, rs, NULL, e_parent, vol );
54 }
55 }
56
57 static int
monitor_send_children(Operation * op,SlapReply * rs,Entry * e_nonvolatile,Entry * e_ch,int sub)58 monitor_send_children(
59 Operation *op,
60 SlapReply *rs,
61 Entry *e_nonvolatile,
62 Entry *e_ch,
63 int sub )
64 {
65 monitor_info_t *mi = ( monitor_info_t * )op->o_bd->be_private;
66 Entry *e,
67 *e_tmp;
68 monitor_entry_t *mp;
69 int rc,
70 nonvolatile = 0;
71
72 e = e_nonvolatile;
73
74 /* no volatile entries? */
75 if ( e_ch == NULL ) {
76 /* no persistent entries? return */
77 if ( e == NULL ) {
78 return LDAP_SUCCESS;
79 }
80
81 /* volatile entries */
82 } else {
83 /* if no persistent, return only volatile */
84 if ( e == NULL ) {
85 e = e_ch;
86
87 /* else append persistent to volatile */
88 } else {
89 e_tmp = e_ch;
90 do {
91 mp = ( monitor_entry_t * )e_tmp->e_private;
92 e_tmp = mp->mp_next;
93
94 if ( e_tmp == NULL ) {
95 mp->mp_next = e;
96 break;
97 }
98 } while ( e_tmp );
99 e = e_ch;
100 }
101 }
102
103 /* return entries */
104 for ( ; e != NULL; e = e_tmp ) {
105 Entry *sub_nv = NULL, *sub_ch = NULL;
106
107 monitor_cache_lock( e );
108 monitor_entry_update( op, rs, e );
109
110 if ( e == e_nonvolatile )
111 nonvolatile = 1;
112
113 mp = ( monitor_entry_t * )e->e_private;
114 e_tmp = mp->mp_next;
115
116 if ( op->o_abandon ) {
117 monitor_cache_release( mi, e );
118 rc = SLAPD_ABANDON;
119 goto freeout;
120 }
121
122 if ( sub )
123 monitor_find_children( op, rs, e, &sub_nv, &sub_ch );
124
125 rc = test_filter( op, e, op->oq_search.rs_filter );
126 if ( rc == LDAP_COMPARE_TRUE ) {
127 rs->sr_entry = e;
128 rs->sr_flags = REP_ENTRY_MUSTRELEASE;
129 rc = send_search_entry( op, rs );
130 if ( rc ) {
131 for ( e = sub_ch; e != NULL; e = sub_nv ) {
132 mp = ( monitor_entry_t * )e->e_private;
133 sub_nv = mp->mp_next;
134 monitor_cache_lock( e );
135 monitor_cache_release( mi, e );
136 }
137 goto freeout;
138 }
139 } else {
140 monitor_cache_release( mi, e );
141 }
142
143 if ( sub ) {
144 rc = monitor_send_children( op, rs, sub_nv, sub_ch, sub );
145 if ( rc ) {
146 freeout:
147 if ( nonvolatile == 0 ) {
148 for ( ; e_tmp != NULL; ) {
149 mp = ( monitor_entry_t * )e_tmp->e_private;
150 e = e_tmp;
151 e_tmp = mp->mp_next;
152 monitor_cache_lock( e );
153 monitor_cache_release( mi, e );
154
155 if ( e_tmp == e_nonvolatile ) {
156 break;
157 }
158 }
159 }
160
161 return( rc );
162 }
163 }
164 }
165
166 return LDAP_SUCCESS;
167 }
168
169 int
monitor_back_search(Operation * op,SlapReply * rs)170 monitor_back_search( Operation *op, SlapReply *rs )
171 {
172 monitor_info_t *mi = ( monitor_info_t * )op->o_bd->be_private;
173 int rc = LDAP_SUCCESS;
174 Entry *e = NULL, *matched = NULL;
175 Entry *e_nv = NULL, *e_ch = NULL;
176 slap_mask_t mask;
177
178 Debug( LDAP_DEBUG_TRACE, "=> monitor_back_search\n" );
179
180
181 /* get entry with reader lock */
182 monitor_cache_dn2entry( op, rs, &op->o_req_ndn, &e, &matched );
183 if ( e == NULL ) {
184 rs->sr_err = LDAP_NO_SUCH_OBJECT;
185 if ( matched ) {
186 if ( !access_allowed_mask( op, matched,
187 slap_schema.si_ad_entry,
188 NULL, ACL_DISCLOSE, NULL, NULL ) )
189 {
190 /* do nothing */ ;
191 } else {
192 rs->sr_matched = matched->e_dn;
193 }
194 }
195
196 send_ldap_result( op, rs );
197 if ( matched ) {
198 monitor_cache_release( mi, matched );
199 rs->sr_matched = NULL;
200 }
201
202 return rs->sr_err;
203 }
204
205 /* NOTE: __NEW__ "search" access is required
206 * on searchBase object */
207 if ( !access_allowed_mask( op, e, slap_schema.si_ad_entry,
208 NULL, ACL_SEARCH, NULL, &mask ) )
209 {
210 monitor_cache_release( mi, e );
211
212 if ( !ACL_GRANT( mask, ACL_DISCLOSE ) ) {
213 rs->sr_err = LDAP_NO_SUCH_OBJECT;
214 } else {
215 rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
216 }
217
218 send_ldap_result( op, rs );
219
220 return rs->sr_err;
221 }
222
223 rs->sr_attrs = op->oq_search.rs_attrs;
224 switch ( op->oq_search.rs_scope ) {
225 case LDAP_SCOPE_BASE:
226 monitor_entry_update( op, rs, e );
227 rc = test_filter( op, e, op->oq_search.rs_filter );
228 if ( rc == LDAP_COMPARE_TRUE ) {
229 rs->sr_entry = e;
230 rs->sr_flags = REP_ENTRY_MUSTRELEASE;
231 send_search_entry( op, rs );
232 rs->sr_entry = NULL;
233 } else {
234 monitor_cache_release( mi, e );
235 }
236 rc = LDAP_SUCCESS;
237 break;
238
239 case LDAP_SCOPE_ONELEVEL:
240 case LDAP_SCOPE_SUBORDINATE:
241 monitor_find_children( op, rs, e, &e_nv, &e_ch );
242 monitor_cache_release( mi, e );
243 rc = monitor_send_children( op, rs, e_nv, e_ch,
244 op->oq_search.rs_scope == LDAP_SCOPE_SUBORDINATE );
245 break;
246
247 case LDAP_SCOPE_SUBTREE:
248 monitor_entry_update( op, rs, e );
249 monitor_find_children( op, rs, e, &e_nv, &e_ch );
250 rc = test_filter( op, e, op->oq_search.rs_filter );
251 if ( rc == LDAP_COMPARE_TRUE ) {
252 rs->sr_entry = e;
253 rs->sr_flags = REP_ENTRY_MUSTRELEASE;
254 send_search_entry( op, rs );
255 rs->sr_entry = NULL;
256 } else {
257 monitor_cache_release( mi, e );
258 }
259
260 rc = monitor_send_children( op, rs, e_nv, e_ch, 1 );
261 break;
262
263 default:
264 rc = LDAP_UNWILLING_TO_PERFORM;
265 monitor_cache_release( mi, e );
266 }
267
268 rs->sr_attrs = NULL;
269 rs->sr_err = rc;
270 if ( rs->sr_err != SLAPD_ABANDON ) {
271 send_ldap_result( op, rs );
272 }
273
274 return rs->sr_err;
275 }
276
277