xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-monitor/search.c (revision 413d532bcc3f62d122e56d92e13ac64825a40baf)
1 /*	$NetBSD: search.c,v 1.1.1.3 2010/12/12 15:23:16 adam Exp $	*/
2 
3 /* search.c - monitor backend search function */
4 /* OpenLDAP: pkg/ldap/servers/slapd/back-monitor/search.c,v 1.39.2.7 2010/04/13 20:23:33 kurt Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2001-2010 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 "portable.h"
25 
26 #include <stdio.h>
27 
28 #include <ac/string.h>
29 #include <ac/socket.h>
30 
31 #include "slap.h"
32 #include "back-monitor.h"
33 #include "proto-back-monitor.h"
34 
35 static int
36 monitor_send_children(
37 	Operation	*op,
38 	SlapReply	*rs,
39 	Entry		*e_parent,
40 	int		sub )
41 {
42 	monitor_info_t	*mi = ( monitor_info_t * )op->o_bd->be_private;
43 	Entry 			*e,
44 				*e_tmp,
45 				*e_ch = NULL,
46 				*e_nonvolatile = NULL;
47 	monitor_entry_t *mp;
48 	int			rc,
49 				nonvolatile = 0;
50 
51 	mp = ( monitor_entry_t * )e_parent->e_private;
52 	e_nonvolatile = e = mp->mp_children;
53 
54 	if ( MONITOR_HAS_VOLATILE_CH( mp ) ) {
55 		monitor_entry_create( op, rs, NULL, e_parent, &e_ch );
56 	}
57 	monitor_cache_release( mi, e_parent );
58 
59 	/* no volatile entries? */
60 	if ( e_ch == NULL ) {
61 		/* no persistent entries? return */
62 		if ( e == NULL ) {
63 			return LDAP_SUCCESS;
64 		}
65 
66 	/* volatile entries */
67 	} else {
68 		/* if no persistent, return only volatile */
69 		if ( e == NULL ) {
70 			e = e_ch;
71 
72 		/* else append persistent to volatile */
73 		} else {
74 			e_tmp = e_ch;
75 			do {
76 				mp = ( monitor_entry_t * )e_tmp->e_private;
77 				e_tmp = mp->mp_next;
78 
79 				if ( e_tmp == NULL ) {
80 					mp->mp_next = e;
81 					break;
82 				}
83 			} while ( e_tmp );
84 			e = e_ch;
85 		}
86 	}
87 
88 	/* return entries */
89 	for ( monitor_cache_lock( e ); e != NULL; ) {
90 		monitor_entry_update( op, rs, e );
91 
92 		if ( op->o_abandon ) {
93 			/* FIXME: may leak generated children */
94 			if ( nonvolatile == 0 ) {
95 				for ( e_tmp = e; e_tmp != NULL; ) {
96 					mp = ( monitor_entry_t * )e_tmp->e_private;
97 					e = e_tmp;
98 					e_tmp = mp->mp_next;
99 					monitor_cache_release( mi, e );
100 
101 					if ( e_tmp == e_nonvolatile ) {
102 						break;
103 					}
104 				}
105 
106 			} else {
107 				monitor_cache_release( mi, e );
108 			}
109 
110 			return SLAPD_ABANDON;
111 		}
112 
113 		rc = test_filter( op, e, op->oq_search.rs_filter );
114 		if ( rc == LDAP_COMPARE_TRUE ) {
115 			rs->sr_entry = e;
116 			rs->sr_flags = 0;
117 			rc = send_search_entry( op, rs );
118 			rs->sr_entry = NULL;
119 		}
120 
121 		mp = ( monitor_entry_t * )e->e_private;
122 		e_tmp = mp->mp_next;
123 
124 		if ( sub ) {
125 			rc = monitor_send_children( op, rs, e, sub );
126 			if ( rc ) {
127 				/* FIXME: may leak generated children */
128 				if ( nonvolatile == 0 ) {
129 					for ( ; e_tmp != NULL; ) {
130 						mp = ( monitor_entry_t * )e_tmp->e_private;
131 						e = e_tmp;
132 						e_tmp = mp->mp_next;
133 						monitor_cache_release( mi, e );
134 
135 						if ( e_tmp == e_nonvolatile ) {
136 							break;
137 						}
138 					}
139 				}
140 
141 				return( rc );
142 			}
143 		}
144 
145 		if ( e_tmp != NULL ) {
146 			monitor_cache_lock( e_tmp );
147 		}
148 
149 		if ( !sub ) {
150 			/* otherwise the recursive call already released */
151 			monitor_cache_release( mi, e );
152 		}
153 
154 		e = e_tmp;
155 		if ( e == e_nonvolatile ) {
156 			nonvolatile = 1;
157 		}
158 	}
159 
160 	return LDAP_SUCCESS;
161 }
162 
163 int
164 monitor_back_search( Operation *op, SlapReply *rs )
165 {
166 	monitor_info_t	*mi = ( monitor_info_t * )op->o_bd->be_private;
167 	int		rc = LDAP_SUCCESS;
168 	Entry		*e = NULL, *matched = NULL;
169 	slap_mask_t	mask;
170 
171 	Debug( LDAP_DEBUG_TRACE, "=> monitor_back_search\n", 0, 0, 0 );
172 
173 
174 	/* get entry with reader lock */
175 	monitor_cache_dn2entry( op, rs, &op->o_req_ndn, &e, &matched );
176 	if ( e == NULL ) {
177 		rs->sr_err = LDAP_NO_SUCH_OBJECT;
178 		if ( matched ) {
179 			if ( !access_allowed_mask( op, matched,
180 					slap_schema.si_ad_entry,
181 					NULL, ACL_DISCLOSE, NULL, NULL ) )
182 			{
183 				/* do nothing */ ;
184 			} else {
185 				rs->sr_matched = matched->e_dn;
186 			}
187 		}
188 
189 		send_ldap_result( op, rs );
190 		if ( matched ) {
191 			monitor_cache_release( mi, matched );
192 			rs->sr_matched = NULL;
193 		}
194 
195 		return rs->sr_err;
196 	}
197 
198 	/* NOTE: __NEW__ "search" access is required
199 	 * on searchBase object */
200 	if ( !access_allowed_mask( op, e, slap_schema.si_ad_entry,
201 				NULL, ACL_SEARCH, NULL, &mask ) )
202 	{
203 		monitor_cache_release( mi, e );
204 
205 		if ( !ACL_GRANT( mask, ACL_DISCLOSE ) ) {
206 			rs->sr_err = LDAP_NO_SUCH_OBJECT;
207 		} else {
208 			rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
209 		}
210 
211 		send_ldap_result( op, rs );
212 
213 		return rs->sr_err;
214 	}
215 
216 	rs->sr_attrs = op->oq_search.rs_attrs;
217 	switch ( op->oq_search.rs_scope ) {
218 	case LDAP_SCOPE_BASE:
219 		monitor_entry_update( op, rs, e );
220 		rc = test_filter( op, e, op->oq_search.rs_filter );
221  		if ( rc == LDAP_COMPARE_TRUE ) {
222 			rs->sr_entry = e;
223 			rs->sr_flags = 0;
224 			send_search_entry( op, rs );
225 			rs->sr_entry = NULL;
226 		}
227 		rc = LDAP_SUCCESS;
228 		monitor_cache_release( mi, e );
229 		break;
230 
231 	case LDAP_SCOPE_ONELEVEL:
232 	case LDAP_SCOPE_SUBORDINATE:
233 		rc = monitor_send_children( op, rs, e,
234 			op->oq_search.rs_scope == LDAP_SCOPE_SUBORDINATE );
235 		break;
236 
237 	case LDAP_SCOPE_SUBTREE:
238 		monitor_entry_update( op, rs, e );
239 		rc = test_filter( op, e, op->oq_search.rs_filter );
240 		if ( rc == LDAP_COMPARE_TRUE ) {
241 			rs->sr_entry = e;
242 			rs->sr_flags = 0;
243 			send_search_entry( op, rs );
244 			rs->sr_entry = NULL;
245 		}
246 
247 		rc = monitor_send_children( op, rs, e, 1 );
248 		break;
249 
250 	default:
251 		rc = LDAP_UNWILLING_TO_PERFORM;
252 		monitor_cache_release( mi, e );
253 	}
254 
255 	rs->sr_attrs = NULL;
256 	rs->sr_err = rc;
257 	if ( rs->sr_err != SLAPD_ABANDON ) {
258 		send_ldap_result( op, rs );
259 	}
260 
261 	return rs->sr_err;
262 }
263 
264