search.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. /*
  39. * File: search.c
  40. *
  41. * Functions:
  42. *
  43. * ldif_back_search() - ldif backend search function
  44. *
  45. */
  46. #include "back-ldif.h"
  47. /*
  48. * Function: ldif_back_search
  49. *
  50. * Returns: returns 0 if good, -1 else.
  51. *
  52. * Description: Searches the database for entries satisfying the
  53. * user's criteria
  54. */
  55. int
  56. ldif_back_search( Slapi_PBlock *pb )
  57. {
  58. LDIF *db; /*The database*/
  59. char *base; /*Base of the search*/
  60. int scope; /*Scope of the search*/
  61. int deref; /*Should we dereference aliases?*/
  62. int slimit; /*Size limit of the search*/
  63. int tlimit; /*Time limit of the search*/
  64. Slapi_Filter *filter; /*The filter*/
  65. time_t dummy=0; /*Used for time()*/
  66. char **attrs; /*Attributes*/
  67. int attrsonly; /*Should we just return the attributes found?*/
  68. time_t optime; /*Time the operation started*/
  69. int nentries; /*Number of entries found thus far*/
  70. ldif_Entry *cur; /*Used for traversing the list of entries*/
  71. int hitflag=0; /*Used to test if we found the entry in the db*/
  72. char *freeme; /*Tmp storage for monitordn*/
  73. time_t currtime; /*The current time*/
  74. LDAPDebug( LDAP_DEBUG_TRACE, "=> ldif_back_search\n", 0, 0, 0 );
  75. /*
  76. * Get private information created in the init routine.
  77. * Also get the parameters of the search operation. These come
  78. * more or less directly from the client.
  79. */
  80. if (slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &db ) < 0 ||
  81. slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &base ) < 0 ||
  82. slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope ) < 0 ||
  83. slapi_pblock_get( pb, SLAPI_SEARCH_DEREF, &deref ) < 0 ||
  84. slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &slimit ) < 0 ||
  85. slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit ) < 0 ||
  86. slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter ) < 0 ||
  87. slapi_pblock_get( pb, SLAPI_SEARCH_ATTRS, &attrs ) < 0 ||
  88. slapi_pblock_get( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly ) <0 ||
  89. slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime ) < 0){
  90. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL );
  91. return(-1);
  92. }
  93. /*
  94. * If we get a search request for the backend monitor dn,
  95. * call ldif_back_monitor_info(), which packages up the
  96. * backend database analysis info and sends it back to the
  97. * client
  98. */
  99. if ( scope == LDAP_SCOPE_BASE ) {
  100. /*Get the backend's monitor dn*/
  101. freeme = (char *) get_monitordn(pb);
  102. if (freeme != NULL){
  103. /*
  104. * Compare the monitor dn with the base,
  105. * if they match, call monitor_info, which
  106. * will return all the relevant info to the client
  107. */
  108. if ( strcasecmp( base, freeme) == 0 ) {
  109. ldif_back_monitor_info( pb, db );
  110. free ((void *) freeme);
  111. return(-1);
  112. }
  113. free ((void *) freeme);
  114. }
  115. }
  116. /*
  117. * First we lock the whole database (clumsy, inefficient and
  118. * inelegant, but simple)
  119. */
  120. PR_Lock( db->ldif_lock );
  121. /*Increase the number of accesses*/
  122. db->ldif_tries++;
  123. /*
  124. * Look through each entry in the ldif file and see if it matches
  125. * the filter and scope of the search. Do this by calling the
  126. * slapi_filter_test() routine.
  127. */
  128. nentries = 0;
  129. for (cur=db->ldif_entries; cur != NULL; cur = cur->next ) {
  130. /*Make sure we're not exceeding our time limit...*/
  131. currtime = time(&dummy);
  132. if ((tlimit > 0) && ((currtime - optime) > (time_t)tlimit)){
  133. slapi_send_ldap_result( pb, LDAP_TIMELIMIT_EXCEEDED, NULL, NULL, nentries, NULL);
  134. /*We "hit" the cache*/
  135. if (hitflag)
  136. {
  137. db->ldif_hits++;
  138. }
  139. PR_Unlock( db->ldif_lock );
  140. return(-1);
  141. }
  142. /*...or that we haven't been abandoned*/
  143. if ( slapi_op_abandoned( pb ) ) {
  144. /*We "hit" the cache*/
  145. if (hitflag)
  146. {
  147. db->ldif_hits++;
  148. }
  149. PR_Unlock( db->ldif_lock );
  150. return( -1 );
  151. }
  152. /*Test for exceedence of size limit*/
  153. if ((slimit > -1) && (nentries >= slimit)){
  154. slapi_send_ldap_result( pb, LDAP_SIZELIMIT_EXCEEDED, NULL, NULL, nentries, NULL);
  155. /*We hit the "cache"*/
  156. if (hitflag)
  157. {
  158. db->ldif_hits++;
  159. }
  160. PR_Unlock( db->ldif_lock );
  161. return(-1);
  162. }
  163. /*Test if this entry matches the filter*/
  164. if ( slapi_vattr_filter_test( pb, cur->lde_e, filter, 1 /* verify access */ ) == 0 ) {
  165. /* Entry matches - send it */
  166. hitflag = 1;
  167. switch ( slapi_send_ldap_search_entry( pb, cur->lde_e, NULL, attrs,
  168. attrsonly ) ) {
  169. case 0: /* Entry sent ok */
  170. nentries++;
  171. break;
  172. case 1: /* Entry not sent - because of acl, etc. */
  173. break;
  174. case -1:/* Connection closed */
  175. /* Clean up and return */
  176. /*We "hit" the cache*/
  177. if (hitflag)
  178. {
  179. db->ldif_hits++;
  180. }
  181. PR_Unlock( db->ldif_lock );
  182. return( -1 );
  183. }
  184. }
  185. }
  186. /*If we succeeded, we should update the ldif_hits entry of db*/
  187. if (hitflag)
  188. {
  189. db->ldif_hits++;
  190. }
  191. /* Search is done, send LDAP_SUCCESS */
  192. slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, NULL, nentries, NULL );
  193. PR_Unlock( db->ldif_lock );
  194. LDAPDebug( LDAP_DEBUG_TRACE, "<= ldif_back_search\n", 0, 0, 0 );
  195. return( -1 );
  196. }