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