1
0

cb_search.c 23 KB

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