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