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