cb_search.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  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. #include "cb.h"
  39. /*
  40. * Build a candidate list for this backentry and scope.
  41. * Could be a BASE, ONELEVEL, or SUBTREE search.
  42. *
  43. * Returns:
  44. * 0 - success
  45. * <0 - fail
  46. *
  47. */
  48. int
  49. chainingdb_build_candidate_list ( Slapi_PBlock *pb )
  50. {
  51. Slapi_Backend * be;
  52. Slapi_Operation * op;
  53. char *target, *filter;
  54. int scope,attrsonly,sizelimit,timelimit,rc,searchreferral;
  55. char **attrs=NULL;
  56. LDAPControl **controls=NULL;
  57. LDAPControl **ctrls=NULL;
  58. LDAP *ld=NULL;
  59. cb_backend_instance *cb = NULL;
  60. cb_searchContext *ctx=NULL;
  61. struct timeval timeout;
  62. time_t optime;
  63. int doit,parse_rc;
  64. LDAPMessage *res=NULL;
  65. char *matched_msg,*error_msg;
  66. LDAPControl **serverctrls=NULL;
  67. char **referrals=NULL;
  68. char *cnxerrbuf=NULL;
  69. time_t endbefore=0;
  70. time_t endtime;
  71. cb_outgoing_conn *cnx;
  72. slapi_pblock_get( pb, SLAPI_BACKEND, &be );
  73. cb = cb_get_instance(be);
  74. slapi_pblock_get( pb, SLAPI_OPERATION, &op );
  75. slapi_pblock_get( pb, SLAPI_SEARCH_STRFILTER, &filter );
  76. slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope );
  77. slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime );
  78. slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &target );
  79. if ( LDAP_SUCCESS != (parse_rc=cb_forward_operation(pb) )) {
  80. /* Don't return errors */
  81. if (cb_debug_on()) {
  82. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  83. "local search: base:<%s> scope:<%s> filter:<%s>\n",target,
  84. scope==LDAP_SCOPE_SUBTREE?"SUBTREE":scope==LDAP_SCOPE_ONELEVEL ? "ONE-LEVEL" : "BASE" , filter);
  85. }
  86. ctx = (cb_searchContext *)slapi_ch_calloc(1,sizeof(cb_searchContext));
  87. ctx->type = CB_SEARCHCONTEXT_ENTRY;
  88. ctx->data=NULL;
  89. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,ctx);
  90. return 0;
  91. }
  92. cb_update_monitor_info(pb,cb,SLAPI_OPERATION_SEARCH);
  93. /* Check wether the chaining BE is available or not */
  94. if ( cb_check_availability( cb, pb ) == FARMSERVER_UNAVAILABLE ){
  95. return -1;
  96. }
  97. if (cb_debug_on()) {
  98. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  99. "chained search: base:<%s> scope:<%s> filter:<%s>\n",target,
  100. scope==LDAP_SCOPE_SUBTREE?"SUBTREE":scope==LDAP_SCOPE_ONELEVEL ? "ONE-LEVEL" : "BASE" , filter);
  101. }
  102. slapi_pblock_get( pb, SLAPI_SEARCH_ATTRS, &attrs );
  103. slapi_pblock_get( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
  104. slapi_pblock_get( pb, SLAPI_REQCONTROLS, &controls );
  105. slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &timelimit );
  106. slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &sizelimit );
  107. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
  108. if ((scope != LDAP_SCOPE_BASE) && (scope != LDAP_SCOPE_ONELEVEL) && (scope != LDAP_SCOPE_SUBTREE)) {
  109. cb_send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "Bad scope", 0, NULL );
  110. return 1;
  111. }
  112. searchreferral=cb->searchreferral;
  113. if (( scope != LDAP_SCOPE_BASE ) && ( searchreferral )) {
  114. int i;
  115. struct berval bv,*bvals[2];
  116. Slapi_Entry ** aciArray=(Slapi_Entry **) slapi_ch_malloc(2*sizeof(Slapi_Entry *));
  117. Slapi_Entry *anEntry = slapi_entry_alloc();
  118. slapi_entry_set_dn(anEntry,slapi_ch_strdup(target));
  119. bvals[1]=NULL;
  120. bvals[0]=&bv;
  121. bv.bv_val="referral";
  122. bv.bv_len=strlen(bv.bv_val);
  123. slapi_entry_add_values( anEntry, "objectclass", bvals);
  124. PR_RWLock_Rlock(cb->rwl_config_lock);
  125. for (i=0; cb->url_array && cb->url_array[i]; i++) {
  126. char * anUrl = slapi_ch_smprintf("%s%s",cb->url_array[i],target);
  127. bv.bv_val=anUrl;
  128. bv.bv_len=strlen(bv.bv_val);
  129. slapi_entry_attr_merge( anEntry, "ref", bvals);
  130. slapi_ch_free((void **)&anUrl);
  131. }
  132. PR_RWLock_Unlock(cb->rwl_config_lock);
  133. aciArray[0]=anEntry;
  134. aciArray[1]=NULL;
  135. ctx = (cb_searchContext *)slapi_ch_calloc(1,sizeof(cb_searchContext));
  136. ctx->type = CB_SEARCHCONTEXT_ENTRY;
  137. ctx->data=aciArray;
  138. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,ctx);
  139. return 0;
  140. }
  141. /*
  142. ** Time limit management.
  143. ** Make sure the operation has not expired
  144. */
  145. if ( timelimit == -1 ) {
  146. timeout.tv_sec = timeout.tv_usec = 0;
  147. } else {
  148. time_t now=current_time();
  149. endbefore=optime + timelimit;
  150. if (now >= endbefore) {
  151. cb_send_ldap_result( pb, LDAP_TIMELIMIT_EXCEEDED, NULL,NULL, 0, NULL);
  152. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
  153. return 1;
  154. }
  155. timeout.tv_sec=(time_t)timelimit-(now-optime);
  156. timeout.tv_usec=0;
  157. }
  158. /* Operational attribute support for internal searches: */
  159. /* The front-end relies on the fact that operational attributes */
  160. /* are returned along with standard attrs when the attr list is */
  161. /* NULL. To make it work, we need to explicitly request for all*/
  162. /* possible operational attrs. Too bad. */
  163. if ( (attrs == NULL) && operation_is_flag_set(op, OP_FLAG_INTERNAL) ) {
  164. attrs = cb->every_attribute;
  165. }
  166. else
  167. {
  168. int i;
  169. if ( attrs != NULL )
  170. {
  171. for ( i = 0; attrs[i] != NULL; i++ ) {
  172. if ( strcasecmp( "nsrole", attrs[i] ) == 0 )
  173. {
  174. attrs = cb->every_attribute;
  175. break;
  176. }
  177. }
  178. }
  179. }
  180. /* Grab a connection handle */
  181. if ( LDAP_SUCCESS != (rc = cb_get_connection(cb->pool,&ld,&cnx,&timeout,&cnxerrbuf))) {
  182. if (rc == LDAP_TIMELIMIT_EXCEEDED)
  183. cb_send_ldap_result( pb, rc, NULL,cnxerrbuf, 0, NULL);
  184. else
  185. cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,cnxerrbuf, 0, NULL);
  186. if (cnxerrbuf) {
  187. PR_smprintf_free(cnxerrbuf);
  188. }
  189. /* ping the farm. If the farm is unreachable, we increment the counter */
  190. cb_ping_farm(cb,NULL,0);
  191. return 1;
  192. }
  193. /*
  194. * Control management
  195. */
  196. if ( LDAP_SUCCESS != (rc = cb_update_controls( pb,ld,&ctrls,CB_UPDATE_CONTROLS_ADDAUTH ))) {
  197. cb_send_ldap_result( pb, rc, NULL,NULL, 0, NULL);
  198. cb_release_op_connection(cb->pool,ld,0);
  199. return 1;
  200. }
  201. if ( slapi_op_abandoned( pb )) {
  202. cb_release_op_connection(cb->pool,ld,0);
  203. if ( NULL != ctrls)
  204. ldap_controls_free(ctrls);
  205. return 1;
  206. }
  207. ctx = (cb_searchContext *) slapi_ch_calloc(1,sizeof(cb_searchContext));
  208. /*
  209. ** We need to store the connection handle in the search context
  210. ** to make sure we reuse it in the next_entry iteration
  211. ** Indeed, if another thread on this connection detects a problem
  212. ** on this connection, it may reallocate a new connection and
  213. ** a call to get_connection may return a new cnx. Too bad.
  214. */
  215. ctx->ld=ld;
  216. ctx->cnx=cnx;
  217. /* for some reasons, it is an error to pass in a zero'd timeval */
  218. /* to ldap_search_ext() */
  219. if ((timeout.tv_sec==0) && (timeout.tv_usec==0))
  220. timeout.tv_sec=timeout.tv_usec=-1;
  221. /* heart-beat management */
  222. if (cb->max_idle_time>0)
  223. endtime=current_time() + cb->max_idle_time;
  224. rc=ldap_search_ext(ld ,target,scope,filter,attrs,attrsonly,
  225. ctrls, NULL, &timeout,sizelimit, &(ctx->msgid) );
  226. if ( NULL != ctrls)
  227. ldap_controls_free(ctrls);
  228. if ( LDAP_SUCCESS != rc ) {
  229. cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, ldap_err2string(rc), 0, NULL);
  230. cb_release_op_connection(cb->pool,ld,CB_LDAP_CONN_ERROR(rc));
  231. slapi_ch_free((void **) &ctx);
  232. return 1;
  233. }
  234. /*
  235. ** Need to get the very first result to handle
  236. ** errors properly, especially no search base.
  237. */
  238. doit=1;
  239. while (doit) {
  240. if (cb_check_forward_abandon(cb,pb,ctx->ld,ctx->msgid)) {
  241. slapi_ch_free((void **) &ctx);
  242. return 1;
  243. }
  244. rc=ldap_result(ld,ctx->msgid,LDAP_MSG_ONE,&cb->abandon_timeout,&res);
  245. switch ( rc ) {
  246. case -1:
  247. /* An error occurred. return now */
  248. rc = ldap_get_lderrno(ld,NULL,NULL);
  249. /* tuck away some errors in a OPERATION_ERROR */
  250. if (CB_LDAP_CONN_ERROR(rc)) {
  251. cb_send_ldap_result(pb,LDAP_OPERATIONS_ERROR, NULL,
  252. ldap_err2string( rc ), 0, NULL);
  253. } else {
  254. cb_send_ldap_result(pb,rc, NULL, NULL,0,NULL);
  255. }
  256. cb_release_op_connection(cb->pool,ld,CB_LDAP_CONN_ERROR(rc));
  257. if (res)
  258. ldap_msgfree(res);
  259. slapi_ch_free((void **)&ctx);
  260. return 1;
  261. case 0:
  262. /* Local timeout management */
  263. if (timelimit != -1) {
  264. if (current_time() > endbefore) {
  265. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  266. "Local timeout expiration\n");
  267. cb_send_ldap_result(pb,LDAP_TIMELIMIT_EXCEEDED,
  268. NULL,NULL, 0, NULL);
  269. /* Force connection close */
  270. cb_release_op_connection(cb->pool,ld,1);
  271. if (res)
  272. ldap_msgfree(res);
  273. slapi_ch_free((void **)&ctx);
  274. return 1;
  275. }
  276. }
  277. /* heart-beat management */
  278. if ((rc=cb_ping_farm(cb,cnx,endtime)) != LDAP_SUCCESS) {
  279. cb_send_ldap_result(pb,LDAP_OPERATIONS_ERROR, NULL,
  280. ldap_err2string(rc), 0, NULL);
  281. cb_release_op_connection(cb->pool,ld,CB_LDAP_CONN_ERROR(rc));
  282. if (res)
  283. ldap_msgfree(res);
  284. slapi_ch_free((void **)&ctx);
  285. return 1;
  286. }
  287. #ifdef CB_YIELD
  288. DS_Sleep(PR_INTERVAL_NO_WAIT);
  289. #endif
  290. break;
  291. case LDAP_RES_SEARCH_ENTRY:
  292. case LDAP_RES_SEARCH_REFERENCE:
  293. /* Some results received */
  294. /* don't parse result here */
  295. ctx->pending_result=res;
  296. ctx->pending_result_type=rc;
  297. doit=0;
  298. break;
  299. case LDAP_RES_SEARCH_RESULT:
  300. matched_msg=NULL;
  301. error_msg=NULL;
  302. referrals=NULL;
  303. serverctrls=NULL;
  304. parse_rc=ldap_parse_result(ld,res,&rc,&matched_msg,
  305. &error_msg,&referrals, &serverctrls, 0 );
  306. if ( parse_rc != LDAP_SUCCESS ) {
  307. cb_send_ldap_result(pb,parse_rc,
  308. matched_msg,error_msg,0,NULL);
  309. rc=-1;
  310. } else
  311. if ( rc != LDAP_SUCCESS ) {
  312. ldap_get_lderrno( ctx->ld, &matched_msg, &error_msg );
  313. cb_send_ldap_result( pb, rc, matched_msg,
  314. error_msg,0,NULL);
  315. /* BEWARE: matched_msg and error_msg points */
  316. /* to ld fields. */
  317. matched_msg=NULL;
  318. error_msg=NULL;
  319. rc=-1;
  320. }
  321. slapi_ch_free((void **)&matched_msg);
  322. slapi_ch_free((void **)&error_msg);
  323. if (serverctrls)
  324. ldap_controls_free(serverctrls);
  325. if (referrals)
  326. charray_free(referrals);
  327. if (rc!=LDAP_SUCCESS) {
  328. cb_release_op_connection(cb->pool,ld,
  329. CB_LDAP_CONN_ERROR(rc));
  330. ldap_msgfree(res);
  331. slapi_ch_free((void **)&ctx);
  332. return -1;
  333. }
  334. /* Store the msg in the ctx */
  335. /* Parsed in iterate. */
  336. ctx->pending_result=res;
  337. ctx->pending_result_type=LDAP_RES_SEARCH_RESULT;
  338. doit=0;
  339. }
  340. }
  341. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,ctx);
  342. return 0;
  343. }
  344. /*
  345. * Return the next entry in the result set. The entry is returned
  346. * in the pblock.
  347. * Returns 0 normally. If -1 is returned, it means that some
  348. * exceptional condition, e.g. timelimit exceeded has occurred,
  349. * and this routine has sent a result to the client. If zero
  350. * is returned and no entry is available in the PBlock, then
  351. * we've iterated through all the entries.
  352. */
  353. int
  354. chainingdb_next_search_entry ( Slapi_PBlock *pb )
  355. {
  356. char *target;
  357. int sizelimit, timelimit;
  358. int rc, parse_rc, retcode;
  359. int i, attrsonly;
  360. time_t optime;
  361. LDAPMessage *res=NULL;
  362. char *matched_msg,*error_msg;
  363. cb_searchContext *ctx=NULL;
  364. Slapi_Entry *entry;
  365. LDAPControl **serverctrls=NULL;
  366. char **referrals=NULL;
  367. cb_backend_instance * cb=NULL;
  368. Slapi_Backend * be;
  369. time_t endtime;
  370. matched_msg=error_msg=NULL;
  371. slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &ctx );
  372. slapi_pblock_get( pb, SLAPI_BACKEND, &be );
  373. slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &timelimit );
  374. slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &sizelimit );
  375. slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &target );
  376. slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime );
  377. slapi_pblock_get( pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly );
  378. cb = cb_get_instance(be);
  379. if ( NULL == ctx ) {
  380. /* End of local search */
  381. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
  382. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
  383. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  384. "Unexpected NULL ctx in chainingdb_next_search_entry\n");
  385. return 0;
  386. }
  387. if ( NULL != ctx->tobefreed ) {
  388. slapi_entry_free(ctx->tobefreed);
  389. ctx->tobefreed=NULL;
  390. }
  391. if ( ctx->type == CB_SEARCHCONTEXT_ENTRY ) {
  392. int n;
  393. Slapi_Entry ** ptr;
  394. if ( (timelimit != -1) && (timelimit != 0)) {
  395. time_t now=current_time();
  396. if (now > (optime + timelimit)) {
  397. cb_send_ldap_result( pb, LDAP_TIMELIMIT_EXCEEDED, NULL,NULL, 0, NULL);
  398. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL );
  399. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
  400. for ( n = 0, ptr=(Slapi_Entry **)ctx->data; ptr != NULL && ptr[n] != NULL; n++ ) {
  401. slapi_entry_free(ptr[n]);
  402. }
  403. if (ctx->data)
  404. slapi_ch_free((void **)&ctx->data);
  405. slapi_ch_free((void **)&ctx);
  406. return -1;
  407. }
  408. }
  409. /*
  410. ** Return the Slapi_Entry of the result set one
  411. ** by one
  412. */
  413. for ( n = 0, ptr=(Slapi_Entry **)ctx->data; ptr != NULL && ptr[n] != NULL; n++ );
  414. if ( n != 0) {
  415. Slapi_Entry * anEntry=ptr[n-1];
  416. ptr[n-1]=NULL;
  417. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,anEntry);
  418. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,ctx);
  419. cb_set_acl_policy(pb);
  420. ctx->tobefreed=anEntry;
  421. } else {
  422. slapi_ch_free((void **) &ctx);
  423. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL );
  424. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
  425. }
  426. return 0;
  427. }
  428. /*
  429. * Grab a connection handle. Should be the same as the one
  430. * used in the build_candidate list. To be certain of that, grab it from
  431. * the context.
  432. */
  433. /* Poll the server for the results of the search operation.
  434. * Passing LDAP_MSG_ONE indicates that you want to receive
  435. * the entries one at a time, as they come in. If the next
  436. * entry that you retrieve is NULL, there are no more entries.
  437. */
  438. /* heart-beat management */
  439. if (cb->max_idle_time>0)
  440. endtime=current_time() + cb->max_idle_time;
  441. while (1) {
  442. if (cb_check_forward_abandon(cb,pb,ctx->ld,ctx->msgid)) {
  443. /* cnx handle released */
  444. if (ctx->pending_result)
  445. ldap_msgfree(ctx->pending_result);
  446. slapi_ch_free((void **) &ctx);
  447. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL );
  448. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
  449. return -1;
  450. }
  451. /* Check for time limit done by the remote farm server */
  452. /* Check for size limit done by the remote farm server */
  453. /* Use pending msg if one is available */
  454. if (ctx->pending_result) {
  455. res=ctx->pending_result;
  456. rc=ctx->pending_result_type;
  457. ctx->pending_result=NULL;
  458. } else {
  459. rc=ldap_result(ctx->ld,ctx->msgid,
  460. LDAP_MSG_ONE, &cb->abandon_timeout, &res );
  461. }
  462. /* The server can return three types of results back to the client,
  463. * and the return value of ldap_result() indicates the result type:
  464. * LDAP_RES_SEARCH_ENTRY identifies an entry found by the search,
  465. * LDAP_RES_SEARCH_REFERENCE identifies a search reference returned
  466. * by the server, and LDAP_RES_SEARCH_RESULT is the last result
  467. * sent from the server to the client after the operation completes.
  468. * We need to check for each of these types of results.
  469. */
  470. switch ( rc ) {
  471. case -1:
  472. /* An error occurred. */
  473. rc = ldap_get_lderrno( ctx->ld, NULL, NULL );
  474. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
  475. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
  476. cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, ldap_err2string( rc ), 0, NULL);
  477. if (res)
  478. ldap_msgfree(res);
  479. cb_release_op_connection(cb->pool,ctx->ld,CB_LDAP_CONN_ERROR(rc));
  480. slapi_ch_free((void **)&ctx);
  481. return -1;
  482. case 0:
  483. /* heart-beat management */
  484. if ((rc=cb_ping_farm(cb,ctx->cnx,endtime)) != LDAP_SUCCESS) {
  485. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
  486. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
  487. cb_send_ldap_result(pb,LDAP_OPERATIONS_ERROR, NULL,
  488. ldap_err2string(rc), 0, NULL);
  489. if (res)
  490. ldap_msgfree(res);
  491. cb_release_op_connection(cb->pool,ctx->ld,CB_LDAP_CONN_ERROR(rc));
  492. slapi_ch_free((void **)&ctx);
  493. return -1;
  494. }
  495. #ifdef CB_YIELD
  496. DS_Sleep(PR_INTERVAL_NO_WAIT);
  497. #endif
  498. break;
  499. case LDAP_RES_SEARCH_ENTRY:
  500. /* heart-beat management */
  501. if (cb->max_idle_time>0)
  502. endtime=current_time() + cb->max_idle_time;
  503. /* The server sent one of the entries found by the search */
  504. if ((entry = cb_LDAPMessage2Entry(ctx->ld,res,attrsonly)) == NULL) {
  505. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,"Invalid entry received.\n");
  506. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
  507. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
  508. cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL , 0, NULL);
  509. ldap_msgfree(res);
  510. cb_release_op_connection(cb->pool,ctx->ld,0);
  511. slapi_ch_free((void **)&ctx);
  512. return -1;
  513. }
  514. ctx->tobefreed=entry;
  515. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,ctx);
  516. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,entry);
  517. cb_set_acl_policy(pb);
  518. ldap_msgfree(res);
  519. return 0;
  520. case LDAP_RES_SEARCH_REFERENCE:
  521. /* The server sent a search reference encountered during the
  522. * search operation.
  523. */
  524. /* heart-beat management */
  525. if (cb->max_idle_time>0)
  526. endtime=current_time() + cb->max_idle_time;
  527. parse_rc = ldap_parse_reference( ctx->ld, res, &referrals, NULL, 1 );
  528. if ( parse_rc != LDAP_SUCCESS ) {
  529. cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,
  530. ldap_err2string( parse_rc ), 0, NULL);
  531. cb_release_op_connection(cb->pool,ctx->ld,CB_LDAP_CONN_ERROR(parse_rc));
  532. slapi_ch_free((void **)&ctx);
  533. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
  534. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
  535. return -1;
  536. }
  537. /*
  538. ** build a dummy entry on the fly with a ref attribute
  539. */
  540. {
  541. struct berval bv;
  542. int i;
  543. struct berval *bvals[2];
  544. Slapi_Entry *anEntry = slapi_entry_alloc();
  545. slapi_entry_set_dn(anEntry,slapi_ch_strdup(target));
  546. bvals[1]=NULL;
  547. bvals[0]=&bv;
  548. bv.bv_val="referral";
  549. bv.bv_len=strlen(bv.bv_val);
  550. slapi_entry_add_values( anEntry, "objectclass", bvals);
  551. for (i=0;referrals[i] != NULL; i++) {
  552. bv.bv_val=referrals[i];
  553. bv.bv_len=strlen(bv.bv_val);
  554. slapi_entry_add_values( anEntry, "ref", bvals);
  555. }
  556. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,ctx);
  557. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,anEntry);
  558. cb_set_acl_policy(pb);
  559. }
  560. if (referrals != NULL) {
  561. ldap_value_free( referrals );
  562. }
  563. return 0;
  564. case LDAP_RES_SEARCH_RESULT:
  565. /* Parse the final result received from the server. Note the last
  566. * argument is a non-zero value, which indicates that the
  567. * LDAPMessage structure will be freed when done.
  568. */
  569. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET,NULL);
  570. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY,NULL);
  571. parse_rc = ldap_parse_result( ctx->ld, res,
  572. &rc,&matched_msg,&error_msg, &referrals, &serverctrls, 1 );
  573. if ( parse_rc != LDAP_SUCCESS ) {
  574. cb_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, matched_msg,
  575. ldap_err2string( parse_rc ), 0, NULL);
  576. retcode=-1;
  577. } else
  578. if ( rc != LDAP_SUCCESS ) {
  579. ldap_get_lderrno( ctx->ld, &matched_msg, &error_msg );
  580. cb_send_ldap_result( pb, rc, matched_msg, NULL, 0, NULL);
  581. /* BEWARE: Don't free matched_msg && error_msg */
  582. /* Points to the ld fields */
  583. matched_msg=NULL;
  584. error_msg=NULL;
  585. retcode=-1;
  586. } else {
  587. /* Add control response sent by the farm server */
  588. for (i=0; serverctrls && serverctrls[i];i++)
  589. slapi_pblock_set( pb, SLAPI_ADD_RESCONTROL, serverctrls[i]);
  590. retcode=0;
  591. }
  592. if (serverctrls)
  593. ldap_controls_free(serverctrls);
  594. slapi_ch_free((void **)&matched_msg);
  595. slapi_ch_free((void **)&error_msg);
  596. if (referrals)
  597. charray_free(referrals);
  598. cb_release_op_connection(cb->pool,ctx->ld,0);
  599. slapi_ch_free((void **)&ctx);
  600. return retcode;
  601. default:
  602. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM,
  603. "chainingdb_next_search_entry:default case.\n");
  604. }
  605. }
  606. /* Not reached */
  607. /* return 0; */
  608. }
  609. int
  610. chaining_back_entry_release ( Slapi_PBlock *pb ) {
  611. slapi_log_error( SLAPI_LOG_PLUGIN, CB_PLUGIN_SUBSYSTEM, "chaining_back_entry_release\n");
  612. return 0;
  613. }