1 /* $NetBSD: search.c,v 1.1.1.4 2014/05/28 09:58:50 tron 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-2014 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 void 36 monitor_find_children( 37 Operation *op, 38 SlapReply *rs, 39 Entry *e_parent, 40 Entry **nonv, 41 Entry **vol 42 ) 43 { 44 monitor_entry_t *mp; 45 46 mp = ( monitor_entry_t * )e_parent->e_private; 47 *nonv = mp->mp_children; 48 49 if ( MONITOR_HAS_VOLATILE_CH( mp ) ) { 50 monitor_entry_create( op, rs, NULL, e_parent, vol ); 51 } 52 } 53 54 static int 55 monitor_send_children( 56 Operation *op, 57 SlapReply *rs, 58 Entry *e_nonvolatile, 59 Entry *e_ch, 60 int sub ) 61 { 62 monitor_info_t *mi = ( monitor_info_t * )op->o_bd->be_private; 63 Entry *e, 64 *e_tmp; 65 monitor_entry_t *mp; 66 int rc, 67 nonvolatile = 0; 68 69 e = e_nonvolatile; 70 71 /* no volatile entries? */ 72 if ( e_ch == NULL ) { 73 /* no persistent entries? return */ 74 if ( e == NULL ) { 75 return LDAP_SUCCESS; 76 } 77 78 /* volatile entries */ 79 } else { 80 /* if no persistent, return only volatile */ 81 if ( e == NULL ) { 82 e = e_ch; 83 84 /* else append persistent to volatile */ 85 } else { 86 e_tmp = e_ch; 87 do { 88 mp = ( monitor_entry_t * )e_tmp->e_private; 89 e_tmp = mp->mp_next; 90 91 if ( e_tmp == NULL ) { 92 mp->mp_next = e; 93 break; 94 } 95 } while ( e_tmp ); 96 e = e_ch; 97 } 98 } 99 100 /* return entries */ 101 for ( ; e != NULL; e = e_tmp ) { 102 Entry *sub_nv = NULL, *sub_ch = NULL; 103 104 monitor_cache_lock( e ); 105 monitor_entry_update( op, rs, e ); 106 107 if ( e == e_nonvolatile ) 108 nonvolatile = 1; 109 110 mp = ( monitor_entry_t * )e->e_private; 111 e_tmp = mp->mp_next; 112 113 if ( op->o_abandon ) { 114 monitor_cache_release( mi, e ); 115 rc = SLAPD_ABANDON; 116 goto freeout; 117 } 118 119 if ( sub ) 120 monitor_find_children( op, rs, e, &sub_nv, &sub_ch ); 121 122 rc = test_filter( op, e, op->oq_search.rs_filter ); 123 if ( rc == LDAP_COMPARE_TRUE ) { 124 rs->sr_entry = e; 125 rs->sr_flags = REP_ENTRY_MUSTRELEASE; 126 rc = send_search_entry( op, rs ); 127 if ( rc ) { 128 for ( e = sub_ch; e != NULL; e = sub_nv ) { 129 mp = ( monitor_entry_t * )e->e_private; 130 sub_nv = mp->mp_next; 131 monitor_cache_lock( e ); 132 monitor_cache_release( mi, e ); 133 } 134 goto freeout; 135 } 136 } else { 137 monitor_cache_release( mi, e ); 138 } 139 140 if ( sub ) { 141 rc = monitor_send_children( op, rs, sub_nv, sub_ch, sub ); 142 if ( rc ) { 143 freeout: 144 if ( nonvolatile == 0 ) { 145 for ( ; e_tmp != NULL; ) { 146 mp = ( monitor_entry_t * )e_tmp->e_private; 147 e = e_tmp; 148 e_tmp = mp->mp_next; 149 monitor_cache_lock( e ); 150 monitor_cache_release( mi, e ); 151 152 if ( e_tmp == e_nonvolatile ) { 153 break; 154 } 155 } 156 } 157 158 return( rc ); 159 } 160 } 161 } 162 163 return LDAP_SUCCESS; 164 } 165 166 int 167 monitor_back_search( Operation *op, SlapReply *rs ) 168 { 169 monitor_info_t *mi = ( monitor_info_t * )op->o_bd->be_private; 170 int rc = LDAP_SUCCESS; 171 Entry *e = NULL, *matched = NULL; 172 Entry *e_nv = NULL, *e_ch = NULL; 173 slap_mask_t mask; 174 175 Debug( LDAP_DEBUG_TRACE, "=> monitor_back_search\n", 0, 0, 0 ); 176 177 178 /* get entry with reader lock */ 179 monitor_cache_dn2entry( op, rs, &op->o_req_ndn, &e, &matched ); 180 if ( e == NULL ) { 181 rs->sr_err = LDAP_NO_SUCH_OBJECT; 182 if ( matched ) { 183 if ( !access_allowed_mask( op, matched, 184 slap_schema.si_ad_entry, 185 NULL, ACL_DISCLOSE, NULL, NULL ) ) 186 { 187 /* do nothing */ ; 188 } else { 189 rs->sr_matched = matched->e_dn; 190 } 191 } 192 193 send_ldap_result( op, rs ); 194 if ( matched ) { 195 monitor_cache_release( mi, matched ); 196 rs->sr_matched = NULL; 197 } 198 199 return rs->sr_err; 200 } 201 202 /* NOTE: __NEW__ "search" access is required 203 * on searchBase object */ 204 if ( !access_allowed_mask( op, e, slap_schema.si_ad_entry, 205 NULL, ACL_SEARCH, NULL, &mask ) ) 206 { 207 monitor_cache_release( mi, e ); 208 209 if ( !ACL_GRANT( mask, ACL_DISCLOSE ) ) { 210 rs->sr_err = LDAP_NO_SUCH_OBJECT; 211 } else { 212 rs->sr_err = LDAP_INSUFFICIENT_ACCESS; 213 } 214 215 send_ldap_result( op, rs ); 216 217 return rs->sr_err; 218 } 219 220 rs->sr_attrs = op->oq_search.rs_attrs; 221 switch ( op->oq_search.rs_scope ) { 222 case LDAP_SCOPE_BASE: 223 monitor_entry_update( op, rs, e ); 224 rc = test_filter( op, e, op->oq_search.rs_filter ); 225 if ( rc == LDAP_COMPARE_TRUE ) { 226 rs->sr_entry = e; 227 rs->sr_flags = REP_ENTRY_MUSTRELEASE; 228 send_search_entry( op, rs ); 229 rs->sr_entry = NULL; 230 } else { 231 monitor_cache_release( mi, e ); 232 } 233 rc = LDAP_SUCCESS; 234 break; 235 236 case LDAP_SCOPE_ONELEVEL: 237 case LDAP_SCOPE_SUBORDINATE: 238 monitor_find_children( op, rs, e, &e_nv, &e_ch ); 239 monitor_cache_release( mi, e ); 240 rc = monitor_send_children( op, rs, e_nv, e_ch, 241 op->oq_search.rs_scope == LDAP_SCOPE_SUBORDINATE ); 242 break; 243 244 case LDAP_SCOPE_SUBTREE: 245 monitor_entry_update( op, rs, e ); 246 monitor_find_children( op, rs, e, &e_nv, &e_ch ); 247 rc = test_filter( op, e, op->oq_search.rs_filter ); 248 if ( rc == LDAP_COMPARE_TRUE ) { 249 rs->sr_entry = e; 250 rs->sr_flags = REP_ENTRY_MUSTRELEASE; 251 send_search_entry( op, rs ); 252 rs->sr_entry = NULL; 253 } else { 254 monitor_cache_release( mi, e ); 255 } 256 257 rc = monitor_send_children( op, rs, e_nv, e_ch, 1 ); 258 break; 259 260 default: 261 rc = LDAP_UNWILLING_TO_PERFORM; 262 monitor_cache_release( mi, e ); 263 } 264 265 rs->sr_attrs = NULL; 266 rs->sr_err = rc; 267 if ( rs->sr_err != SLAPD_ABANDON ) { 268 send_ldap_result( op, rs ); 269 } 270 271 return rs->sr_err; 272 } 273 274