You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2355 lines
78 KiB

  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. /* result.c - routines to send ldap results, errors, and referrals */
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <sys/types.h>
  16. #include <sys/time.h>
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include <unistd.h>
  20. #include <errno.h>
  21. #include <signal.h>
  22. #include "slap.h"
  23. #include "pratom.h"
  24. #include "fe.h"
  25. #include "vattr_spi.h"
  26. #include "slapi-plugin.h"
  27. #include <ssl.h>
  28. static Slapi_Counter *num_entries_sent;
  29. static Slapi_Counter *num_bytes_sent;
  30. static long current_conn_count;
  31. static PRLock *current_conn_count_mutex;
  32. static int flush_ber(Slapi_PBlock *pb, Connection *conn, Operation *op, BerElement *ber, int type);
  33. static char *notes2str(unsigned int notes, char *buf, size_t buflen);
  34. static void log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries);
  35. static void log_entry(Operation *op, Slapi_Entry *e);
  36. static void log_referral(Operation *op);
  37. static int process_read_entry_controls(Slapi_PBlock *pb, char *oid);
  38. static struct berval *encode_read_entry(Slapi_PBlock *pb, Slapi_Entry *e, char **attrs, int alluserattrs, int some_named_attrs);
  39. static char *op_to_string(int tag);
  40. #define _LDAP_SEND_RESULT 0
  41. #define _LDAP_SEND_REFERRAL 1
  42. #define _LDAP_SEND_ENTRY 2
  43. #define _LDAP_SEND_INTERMED 4
  44. #define SLAPI_SEND_VATTR_FLAG_REALONLY 0x01
  45. #define SLAPI_SEND_VATTR_FLAG_VIRTUALONLY 0x02
  46. void
  47. g_set_num_entries_sent(Slapi_Counter *counter)
  48. {
  49. num_entries_sent = counter;
  50. }
  51. PRUint64
  52. g_get_num_entries_sent()
  53. {
  54. return (slapi_counter_get_value(num_entries_sent));
  55. }
  56. void
  57. g_set_num_bytes_sent(Slapi_Counter *counter)
  58. {
  59. num_bytes_sent = counter;
  60. }
  61. PRUint64
  62. g_get_num_bytes_sent()
  63. {
  64. return (slapi_counter_get_value(num_bytes_sent));
  65. }
  66. static void
  67. delete_default_referral(struct berval **referrals)
  68. {
  69. if (referrals) {
  70. int ii = 0;
  71. for (ii = 0; referrals[ii]; ++ii)
  72. ber_bvfree(referrals[ii]);
  73. slapi_ch_free((void **)&referrals);
  74. }
  75. }
  76. void
  77. g_set_default_referral(struct berval **ldap_url)
  78. {
  79. struct berval **default_referral;
  80. slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
  81. int nReferrals;
  82. /* check to see if we want to delete all referrals */
  83. if (ldap_url && ldap_url[0] &&
  84. PL_strncasecmp((char *)ldap_url[0]->bv_val, REFERRAL_REMOVE_CMD, ldap_url[0]->bv_len) == 0) {
  85. delete_default_referral(slapdFrontendConfig->defaultreferral);
  86. slapdFrontendConfig->defaultreferral = NULL;
  87. return;
  88. }
  89. /* count the number of referrals */
  90. for (nReferrals = 0; ldap_url && ldap_url[nReferrals]; nReferrals++)
  91. ;
  92. default_referral = (struct berval **)
  93. slapi_ch_malloc((nReferrals + 1) * sizeof(struct berval *));
  94. /* terminate the end, and add the referrals backwards */
  95. default_referral[nReferrals--] = NULL;
  96. while (nReferrals >= 0) {
  97. default_referral[nReferrals] = ber_bvdup(ldap_url[nReferrals]);
  98. nReferrals--;
  99. }
  100. delete_default_referral(slapdFrontendConfig->defaultreferral);
  101. slapdFrontendConfig->defaultreferral = default_referral;
  102. }
  103. struct berval **
  104. g_get_default_referral()
  105. {
  106. slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
  107. return slapdFrontendConfig->defaultreferral;
  108. }
  109. /*
  110. * routines to manage keeping track of the current number of connections
  111. * to the server. this information is used by the listener thread to
  112. * determine when to stop listening for new connections, which it does
  113. * when the total number of descriptors available minus the number of
  114. * current connections drops below the reservedescriptors mark.
  115. */
  116. void
  117. g_set_current_conn_count_mutex(PRLock *plock)
  118. {
  119. PR_ASSERT(NULL != plock);
  120. current_conn_count_mutex = plock;
  121. }
  122. PRLock *
  123. g_get_current_conn_count_mutex()
  124. {
  125. return (current_conn_count_mutex);
  126. }
  127. long
  128. g_get_current_conn_count()
  129. {
  130. long tmp;
  131. PR_ASSERT(NULL != current_conn_count_mutex);
  132. PR_Lock(current_conn_count_mutex);
  133. tmp = current_conn_count;
  134. PR_Unlock(current_conn_count_mutex);
  135. return (tmp);
  136. }
  137. void
  138. g_increment_current_conn_count()
  139. {
  140. PR_ASSERT(NULL != current_conn_count_mutex);
  141. PR_Lock(current_conn_count_mutex);
  142. current_conn_count++;
  143. PR_Unlock(current_conn_count_mutex);
  144. }
  145. void
  146. g_decrement_current_conn_count()
  147. {
  148. PR_ASSERT(NULL != current_conn_count_mutex);
  149. PR_Lock(current_conn_count_mutex);
  150. current_conn_count--;
  151. /* PR_ASSERT( current_conn_count >= 0 ); JCM BASTARD */
  152. PR_Unlock(current_conn_count_mutex);
  153. }
  154. void
  155. send_ldap_result(
  156. Slapi_PBlock *pb,
  157. int err,
  158. char *matched,
  159. char *text,
  160. int nentries,
  161. struct berval **urls)
  162. {
  163. send_ldap_result_ext(pb, err, matched, text, nentries, urls, NULL);
  164. }
  165. int
  166. send_ldap_intermediate(Slapi_PBlock *pb, LDAPControl **ectrls, char *responseName, struct berval *responseValue)
  167. {
  168. ber_tag_t tag;
  169. BerElement *ber;
  170. Slapi_Connection *connection;
  171. Slapi_Operation *operation;
  172. int rc = 0;
  173. int logit = 0;
  174. slapi_log_err(SLAPI_LOG_TRACE, "send_ldap_intermediate", "=>\n");
  175. slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
  176. slapi_pblock_get(pb, SLAPI_CONNECTION, &connection);
  177. if (operation->o_status == SLAPI_OP_STATUS_RESULT_SENT) {
  178. return (rc); /* result already sent */
  179. }
  180. tag = LDAP_RES_INTERMEDIATE;
  181. if ((ber = der_alloc()) == NULL) {
  182. slapi_log_err(SLAPI_LOG_ERR, "send_ldap_intermediate", "ber_alloc failed\n");
  183. goto log_and_return;
  184. }
  185. /* add the intermediate message */
  186. rc = ber_printf(ber, "{it{", operation->o_msgid, tag);
  187. /* print responsename */
  188. rc = ber_printf(ber, "ts", LDAP_TAG_IM_RES_OID, responseName);
  189. /* print responsevalue */
  190. rc = ber_printf(ber, "tO", LDAP_TAG_IM_RES_VALUE, responseValue);
  191. if (rc != LBER_ERROR) {
  192. rc = ber_printf(ber, "}"); /* one more } to come */
  193. }
  194. if (ectrls != NULL && connection->c_ldapversion >= LDAP_VERSION3 && write_controls(ber, ectrls) != 0) {
  195. rc = (int)LBER_ERROR;
  196. }
  197. if (rc != LBER_ERROR) { /* end the LDAPMessage sequence */
  198. rc = ber_put_seq(ber);
  199. }
  200. if (rc == LBER_ERROR) {
  201. slapi_log_err(SLAPI_LOG_ERR, "send_ldap_intermediate", "ber_printf failed 0\n");
  202. ber_free(ber, 1 /* freebuf */);
  203. goto log_and_return;
  204. }
  205. /* write only one pdu at a time - wait til it's our turn */
  206. if (flush_ber(pb, connection, operation, ber, _LDAP_SEND_INTERMED) == 0) {
  207. logit = 1;
  208. }
  209. log_and_return:
  210. /* operation->o_status = SLAPI_OP_STATUS_RESULT_SENT;
  211. * there could be multiple intermediate messages on
  212. * the same connection, unlike in send_result do not
  213. * set o_status
  214. */
  215. if (rc == LBER_ERROR) {
  216. rc = LDAP_OPERATIONS_ERROR;
  217. } else {
  218. rc = LDAP_SUCCESS;
  219. }
  220. if (logit && operation_is_flag_set(operation,
  221. OP_FLAG_ACTION_LOG_ACCESS)) {
  222. log_result(pb, operation, rc, tag, 0);
  223. }
  224. slapi_log_err(SLAPI_LOG_TRACE, "send_ldap_intermediate", "<= %d\n", rc);
  225. return rc;
  226. }
  227. static int
  228. check_and_send_extended_result(Slapi_PBlock *pb, ber_tag_t tag, BerElement *ber)
  229. {
  230. /*
  231. * if this is an LDAPv3 ExtendedResponse to an ExtendedRequest,
  232. * check to see if the optional responseName and response OCTET
  233. * STRING need to be appended.
  234. */
  235. int rc = 0;
  236. char *exop_oid;
  237. struct berval *exop_value;
  238. slapi_pblock_get(pb, SLAPI_EXT_OP_RET_OID, &exop_oid);
  239. slapi_pblock_get(pb, SLAPI_EXT_OP_RET_VALUE, &exop_value);
  240. if (LDAP_RES_EXTENDED == tag) {
  241. if (exop_oid != NULL) {
  242. rc = ber_printf(ber, "ts",
  243. LDAP_TAG_EXOP_RES_OID, exop_oid);
  244. }
  245. if (rc != LBER_ERROR && exop_value != NULL) {
  246. rc = ber_printf(ber, "to",
  247. LDAP_TAG_EXOP_RES_VALUE,
  248. exop_value->bv_val ? exop_value->bv_val : "",
  249. exop_value->bv_len);
  250. }
  251. }
  252. return rc;
  253. }
  254. static int
  255. check_and_send_SASL_response(Slapi_PBlock *pb, ber_tag_t tag, BerElement *ber, Connection *conn)
  256. {
  257. /*
  258. * if this is an LDAPv3 BindResponse, check to see if the
  259. * optional serverSaslCreds OCTET STRING is present and needs
  260. * to be appended.
  261. */
  262. int rc = 0;
  263. if (LDAP_RES_BIND == tag && conn->c_ldapversion >= LDAP_VERSION3) {
  264. struct berval *bind_ret_saslcreds; /* v3 serverSaslCreds */
  265. slapi_pblock_get(pb, SLAPI_BIND_RET_SASLCREDS, &bind_ret_saslcreds);
  266. if (bind_ret_saslcreds != NULL) {
  267. rc = ber_printf(ber, "to",
  268. LDAP_TAG_SASL_RES_CREDS,
  269. bind_ret_saslcreds->bv_val ? bind_ret_saslcreds->bv_val : "",
  270. bind_ret_saslcreds->bv_len);
  271. }
  272. }
  273. return rc;
  274. }
  275. /*
  276. * the input ber, if present, is not consumed
  277. */
  278. void
  279. send_ldap_result_ext(
  280. Slapi_PBlock *pb,
  281. int err,
  282. char *matched,
  283. char *text,
  284. int nentries,
  285. struct berval **urls,
  286. BerElement *ber)
  287. {
  288. Slapi_Operation *operation;
  289. passwdPolicy *pwpolicy = NULL;
  290. Connection *conn = NULL;
  291. Slapi_DN *sdn = NULL;
  292. const char *dn = NULL;
  293. ber_tag_t tag;
  294. int flush_ber_element = 1;
  295. ber_tag_t bind_method = 0;
  296. int internal_op;
  297. int i, rc, logit = 0;
  298. char *pbtext;
  299. slapi_pblock_get(pb, SLAPI_BIND_METHOD, &bind_method);
  300. slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
  301. slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);
  302. if (text) {
  303. pbtext = text;
  304. } else {
  305. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &pbtext);
  306. }
  307. if (operation == NULL) {
  308. slapi_log_err(SLAPI_LOG_ERR, "send_ldap_result_ext", "No operation found: slapi_search_internal_set_pb was incomplete (invalid 'base' ?)\n");
  309. return;
  310. }
  311. if (operation->o_status == SLAPI_OP_STATUS_RESULT_SENT) {
  312. return; /* result already sent */
  313. }
  314. if (ber != NULL) {
  315. flush_ber_element = 0;
  316. }
  317. if (err != LDAP_SUCCESS) {
  318. /* count the error for snmp */
  319. /* first check for security errors */
  320. if (err == LDAP_INVALID_CREDENTIALS || err == LDAP_INAPPROPRIATE_AUTH || err == LDAP_AUTH_METHOD_NOT_SUPPORTED || err == LDAP_STRONG_AUTH_NOT_SUPPORTED || err == LDAP_STRONG_AUTH_REQUIRED || err == LDAP_CONFIDENTIALITY_REQUIRED || err == LDAP_INSUFFICIENT_ACCESS || err == LDAP_AUTH_UNKNOWN) {
  321. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors);
  322. } else if (err != LDAP_REFERRAL && err != LDAP_OPT_REFERRALS && err != LDAP_PARTIAL_RESULTS) {
  323. /*madman man spec says not to count as normal errors
  324. --security errors
  325. --referrals
  326. -- partially seviced operations will not be conted as an error
  327. */
  328. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsErrors);
  329. }
  330. }
  331. slapi_log_err(SLAPI_LOG_TRACE, "send_ldap_result_ext", "=> %d:%s:%s\n", err,
  332. matched ? matched : "", text ? text : "");
  333. switch (operation->o_tag) {
  334. case LBER_DEFAULT:
  335. tag = LBER_SEQUENCE;
  336. break;
  337. case LDAP_REQ_SEARCH:
  338. tag = LDAP_RES_SEARCH_RESULT;
  339. break;
  340. case LDAP_REQ_DELETE:
  341. tag = LDAP_RES_DELETE;
  342. break;
  343. case LDAP_REFERRAL:
  344. if (conn && conn->c_ldapversion > LDAP_VERSION2) {
  345. tag = LDAP_TAG_REFERRAL;
  346. break;
  347. }
  348. /* FALLTHROUGH */
  349. default:
  350. tag = operation->o_tag + 1;
  351. break;
  352. }
  353. internal_op = operation_is_flag_set(operation, OP_FLAG_INTERNAL);
  354. if ((conn == NULL) || (internal_op)) {
  355. if (operation->o_result_handler != NULL) {
  356. operation->o_result_handler(conn, operation, err,
  357. matched, text, nentries, urls);
  358. logit = 1;
  359. }
  360. goto log_and_return;
  361. }
  362. /* invalid password. Update the password retry here */
  363. /* put this here for now. It could be a send_result pre-op plugin. */
  364. if ((err == LDAP_INVALID_CREDENTIALS) && (bind_method != LDAP_AUTH_SASL)) {
  365. slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
  366. dn = slapi_sdn_get_dn(sdn);
  367. pwpolicy = new_passwdPolicy(pb, dn);
  368. if (pwpolicy && (pwpolicy->pw_lockout == 1)) {
  369. if (update_pw_retry(pb) == LDAP_CONSTRAINT_VIOLATION && !pwpolicy->pw_is_legacy) {
  370. /*
  371. * If we are not using the legacy pw policy behavior,
  372. * convert the error 49 to 19 (constraint violation)
  373. * and log a message
  374. */
  375. err = LDAP_CONSTRAINT_VIOLATION;
  376. text = "Invalid credentials, you now have exceeded the password retry limit.";
  377. }
  378. }
  379. }
  380. if (ber == NULL) {
  381. if ((ber = der_alloc()) == NULL) {
  382. slapi_log_err(SLAPI_LOG_ERR, "send_ldap_result_ext", "ber_alloc failed\n");
  383. goto log_and_return;
  384. }
  385. }
  386. /* there is no admin limit exceeded in v2 - change to size limit XXX */
  387. if (err == LDAP_ADMINLIMIT_EXCEEDED &&
  388. conn->c_ldapversion < LDAP_VERSION3) {
  389. err = LDAP_SIZELIMIT_EXCEEDED;
  390. }
  391. if (conn->c_ldapversion < LDAP_VERSION3 || urls == NULL) {
  392. char *save, *buf = NULL;
  393. /*
  394. * if there are v2 referrals to send, construct
  395. * the v2 referral string.
  396. */
  397. if (urls != NULL) {
  398. int len;
  399. /* count the referral */
  400. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
  401. /*
  402. * figure out how much space we need
  403. */
  404. len = 10; /* strlen("Referral:") + NULL */
  405. for (i = 0; urls[i] != NULL; i++) {
  406. len += urls[i]->bv_len + 1; /* newline + ref */
  407. }
  408. if (text != NULL) {
  409. len += strlen(text) + 1; /* text + newline */
  410. }
  411. /*
  412. * allocate buffer and fill it in with the error
  413. * message plus v2-style referrals.
  414. */
  415. buf = slapi_ch_malloc(len);
  416. *buf = '\0';
  417. if (text != NULL) {
  418. strcpy(buf, text);
  419. strcat(buf, "\n");
  420. }
  421. strcat(buf, "Referral:");
  422. for (i = 0; urls[i] != NULL; i++) {
  423. strcat(buf, "\n");
  424. strcat(buf, urls[i]->bv_val);
  425. }
  426. save = text;
  427. text = buf;
  428. }
  429. if ((conn->c_ldapversion < LDAP_VERSION3 &&
  430. err == LDAP_REFERRAL) ||
  431. urls != NULL) {
  432. err = LDAP_PARTIAL_RESULTS;
  433. }
  434. rc = ber_printf(ber, "{it{ess", operation->o_msgid, tag, err,
  435. matched ? matched : "", pbtext ? pbtext : "");
  436. /*
  437. * if this is an LDAPv3 ExtendedResponse to an ExtendedRequest,
  438. * check to see if the optional responseName and response OCTET
  439. * STRING need to be appended.
  440. */
  441. if (rc != LBER_ERROR) {
  442. rc = check_and_send_extended_result(pb, tag, ber);
  443. }
  444. /*
  445. * if this is an LDAPv3 BindResponse, check to see if the
  446. * optional serverSaslCreds OCTET STRING is present and needs
  447. * to be appended.
  448. */
  449. if (rc != LBER_ERROR) {
  450. rc = check_and_send_SASL_response(pb, tag, ber, conn);
  451. /* XXXmcs: should we also check for a missing auth response control? */
  452. }
  453. if (rc != LBER_ERROR) {
  454. rc = ber_printf(ber, "}"); /* one more } to come */
  455. }
  456. if (buf != NULL) {
  457. text = save;
  458. slapi_ch_free((void **)&buf);
  459. }
  460. } else {
  461. /*
  462. * there are v3 referrals to add to the result
  463. */
  464. /* count the referral */
  465. if (!config_check_referral_mode())
  466. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
  467. rc = ber_printf(ber, "{it{esst{s", operation->o_msgid, tag, err,
  468. matched ? matched : "", text ? text : "", LDAP_TAG_REFERRAL,
  469. urls[0]->bv_val);
  470. for (i = 1; urls[i] != NULL && rc != LBER_ERROR; i++) {
  471. rc = ber_printf(ber, "s", urls[i]->bv_val);
  472. }
  473. if (rc != LBER_ERROR) {
  474. rc = ber_printf(ber, "}"); /* two more } to come */
  475. }
  476. /*
  477. * if this is an LDAPv3 ExtendedResponse to an ExtendedRequest,
  478. * check to see if the optional responseName and response OCTET
  479. * STRING need to be appended.
  480. */
  481. if (rc != LBER_ERROR) {
  482. rc = check_and_send_extended_result(pb, tag, ber);
  483. }
  484. /*
  485. * if this is an LDAPv3 BindResponse, check to see if the
  486. * optional serverSaslCreds OCTET STRING is present and needs
  487. * to be appended.
  488. */
  489. if (rc != LBER_ERROR) {
  490. rc = check_and_send_SASL_response(pb, tag, ber, conn);
  491. }
  492. if (rc != LBER_ERROR) {
  493. rc = ber_printf(ber, "}"); /* one more } to come */
  494. }
  495. }
  496. if (err == LDAP_SUCCESS) {
  497. /*
  498. * Process the Read Entry Controls (if any)
  499. */
  500. if (process_read_entry_controls(pb, LDAP_CONTROL_PRE_READ_ENTRY)) {
  501. err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  502. goto log_and_return;
  503. }
  504. if (process_read_entry_controls(pb, LDAP_CONTROL_POST_READ_ENTRY)) {
  505. err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  506. goto log_and_return;
  507. }
  508. }
  509. if (operation->o_results.result_controls != NULL && conn->c_ldapversion >= LDAP_VERSION3 && write_controls(ber, operation->o_results.result_controls) != 0) {
  510. rc = (int)LBER_ERROR;
  511. }
  512. if (rc != LBER_ERROR) { /* end the LDAPMessage sequence */
  513. rc = ber_put_seq(ber);
  514. }
  515. if (rc == LBER_ERROR) {
  516. slapi_log_err(SLAPI_LOG_ERR, "send_ldap_result_ext", "ber_printf failed 1\n");
  517. if (flush_ber_element == 1) {
  518. /* we alloced the ber */
  519. ber_free(ber, 1 /* freebuf */);
  520. }
  521. goto log_and_return;
  522. }
  523. if (flush_ber_element) {
  524. /* write only one pdu at a time - wait til it's our turn */
  525. if (flush_ber(pb, conn, operation, ber, _LDAP_SEND_RESULT) == 0) {
  526. logit = 1;
  527. }
  528. }
  529. log_and_return:
  530. operation->o_status = SLAPI_OP_STATUS_RESULT_SENT; /* in case this has not yet been set */
  531. if (logit && (operation_is_flag_set(operation, OP_FLAG_ACTION_LOG_ACCESS) ||
  532. (internal_op && config_get_plugin_logging()))) {
  533. log_result(pb, operation, err, tag, nentries);
  534. }
  535. slapi_log_err(SLAPI_LOG_TRACE, "send_ldap_result_ext", "<= %d\n", err);
  536. }
  537. /*
  538. * For RFC 4527 - Read Entry Controls
  539. *
  540. * If this is the correct operation for the control, then retrieve the
  541. * requested attributes. Then start building the ber-encoded string
  542. * value of the entry. We also need to check access control for the
  543. * requested attributes. Then an octet string containing a BER-encoded
  544. * SearchResultEntry is added to the response control.
  545. */
  546. static int
  547. process_read_entry_controls(Slapi_PBlock *pb, char *oid)
  548. {
  549. struct berval *req_value = NULL;
  550. struct berval *res_value = NULL;
  551. LDAPControl **req_ctls = NULL;
  552. Slapi_Entry *e = NULL;
  553. char **attrs = NULL;
  554. int attr_count = 0;
  555. int iscritical = 0;
  556. int all_attrs = 0;
  557. int no_attrs = 0;
  558. int rc = 0;
  559. slapi_pblock_get(pb, SLAPI_REQCONTROLS, &req_ctls);
  560. /*
  561. * Check for the PRE Read Entry Control, and return the pre-modified entry
  562. */
  563. if (slapi_control_present(req_ctls, oid, &req_value, &iscritical)) {
  564. BerElement *req_ber = NULL;
  565. Operation *op = NULL;
  566. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  567. if (op == NULL) {
  568. slapi_log_err(SLAPI_LOG_ERR, "process_read_entry_controls", "op is NULL\n");
  569. rc = -1;
  570. goto done;
  571. }
  572. if (strcmp(oid, LDAP_CONTROL_PRE_READ_ENTRY) == 0) {
  573. /* first verify this is the correct operation for a pre-read entry control */
  574. if (op->o_tag == LDAP_REQ_MODIFY || op->o_tag == LDAP_REQ_DELETE ||
  575. op->o_tag == LDAP_REQ_MODDN) {
  576. slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &e);
  577. } else {
  578. /* Ok, read control not used for this type of operation */
  579. slapi_log_err(SLAPI_LOG_ERR, "process_read_entry_controls", "Read Entry Controls "
  580. "can not be used for a %s operation.\n",
  581. op_to_string(op->o_tag));
  582. rc = -1;
  583. goto done;
  584. }
  585. } else {
  586. /* first verify this is the correct operation for a post-read entry control */
  587. if (op->o_tag == LDAP_REQ_MODIFY || op->o_tag == LDAP_REQ_ADD ||
  588. op->o_tag == LDAP_REQ_MODDN) {
  589. slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &e);
  590. } else {
  591. /* Ok, read control not used for this type of operation */
  592. slapi_log_err(SLAPI_LOG_ERR, "process_read_entry_controls", "Read Entry Controls "
  593. "can not be used for a %s operation.\n",
  594. op_to_string(op->o_tag));
  595. rc = -1;
  596. goto done;
  597. }
  598. }
  599. if (e == NULL) {
  600. slapi_log_err(SLAPI_LOG_ERR, "process_read_entry_controls", "Unable to retrieve entry\n");
  601. rc = -1;
  602. goto done;
  603. }
  604. #if !defined(DISABLE_ACL_CHECK)
  605. /* even though we can modify the entry, that doesn't mean we can read it */
  606. if (plugin_call_acl_plugin(pb, e, attrs, NULL, SLAPI_ACL_READ,
  607. ACLPLUGIN_ACCESS_READ_ON_ENTRY, NULL) != LDAP_SUCCESS) {
  608. slapi_log_err(SLAPI_LOG_ACL, "process_read_entry_controls", "Access to entry not allowed (%s)\n",
  609. slapi_entry_get_dn_const(e));
  610. rc = -1;
  611. goto done;
  612. }
  613. #endif
  614. /*
  615. * Check the ctl_value for any requested attributes
  616. */
  617. if (req_value && req_value->bv_len != 0 && req_value->bv_val) {
  618. if ((req_ber = ber_init(req_value)) == NULL) {
  619. rc = -1;
  620. goto free;
  621. }
  622. if (ber_scanf(req_ber, "{") == LBER_ERROR) {
  623. rc = -1;
  624. goto free;
  625. }
  626. /* process the attributes */
  627. while (1) {
  628. char *payload = NULL;
  629. if (ber_get_stringa(req_ber, &payload) != LBER_ERROR) {
  630. if (strcmp(payload, LDAP_ALL_USER_ATTRS) == 0) {
  631. all_attrs = 1;
  632. slapi_ch_free_string(&payload);
  633. } else if (strcmp(payload, LDAP_NO_ATTRS) == 0) {
  634. no_attrs = 1;
  635. slapi_ch_free_string(&payload);
  636. } else {
  637. charray_add(&attrs, payload);
  638. attr_count++;
  639. }
  640. } else {
  641. /* we're done */
  642. break;
  643. }
  644. }
  645. if (no_attrs && (all_attrs || attr_count)) {
  646. /* Can't have both no attrs and some attributes */
  647. slapi_log_err(SLAPI_LOG_ERR, "process_read_entry_controls", "Both no attributes \"1.1\" and "
  648. "specific attributes were requested.\n");
  649. rc = -1;
  650. goto free;
  651. }
  652. if (ber_scanf(req_ber, "}") == LBER_ERROR) {
  653. rc = -1;
  654. goto free;
  655. }
  656. } else {
  657. /* this is a problem, malformed request control value */
  658. slapi_log_err(SLAPI_LOG_ERR, "process_read_entry_controls", "Invalid control value.\n");
  659. rc = -1;
  660. goto free;
  661. }
  662. /*
  663. * Get the ber encoded string, and add it to the response control
  664. */
  665. res_value = encode_read_entry(pb, e, attrs, all_attrs, attr_count);
  666. if (res_value && res_value->bv_len > 0) {
  667. LDAPControl new_ctrl = {0};
  668. new_ctrl.ldctl_oid = oid;
  669. new_ctrl.ldctl_value = *res_value;
  670. new_ctrl.ldctl_iscritical = iscritical;
  671. slapi_pblock_set(pb, SLAPI_ADD_RESCONTROL, &new_ctrl);
  672. ber_bvfree(res_value);
  673. } else {
  674. /* failed to encode the result entry */
  675. slapi_log_err(SLAPI_LOG_ERR, "process_read_entry_controls", "Failed to process READ ENTRY"
  676. " Control (%s), error encoding result entry\n",
  677. oid);
  678. rc = -1;
  679. }
  680. free:
  681. if (NULL != req_ber) {
  682. ber_free(req_ber, 1);
  683. }
  684. if (rc != 0) {
  685. /* log an error */
  686. slapi_log_err(SLAPI_LOG_ERR, "process_read_entry_controls", "Failed to process READ ENTRY "
  687. "Control (%s) ber decoding error\n",
  688. oid);
  689. }
  690. }
  691. done:
  692. if (iscritical) {
  693. return rc;
  694. } else {
  695. return 0;
  696. }
  697. }
  698. void
  699. send_nobackend_ldap_result(Slapi_PBlock *pb)
  700. {
  701. struct berval **refurls;
  702. int err;
  703. refurls = g_get_default_referral();
  704. err = (refurls == NULL) ? LDAP_NO_SUCH_OBJECT : LDAP_REFERRAL;
  705. /* richm 20010831 - bug 556992 - the post op code needs to know what the
  706. ldap error sent to the client was - slapi_send_ldap_result sets the
  707. err in the pblock, so this function needs to also */
  708. slapi_pblock_set(pb, SLAPI_RESULT_CODE, &err);
  709. slapi_send_ldap_result(pb, err, NULL, NULL, 0, refurls);
  710. }
  711. int
  712. send_ldapv3_referral(
  713. Slapi_PBlock *pb,
  714. struct berval **urls)
  715. {
  716. Connection *conn = NULL;
  717. BerElement *ber;
  718. int i, rc, logit = 0;
  719. Slapi_Operation *operation;
  720. Slapi_Backend *pb_backend;
  721. slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
  722. slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);
  723. slapi_pblock_get(pb, SLAPI_BACKEND, &pb_backend);
  724. slapi_log_err(SLAPI_LOG_TRACE, "send_ldapv3_referral", "=>\n");
  725. if (conn == NULL) {
  726. if (operation->o_search_referral_handler != NULL) {
  727. if ((rc = (*operation->o_search_referral_handler)(
  728. pb_backend, conn, operation, urls)) == 0) {
  729. logit = 1;
  730. }
  731. goto log_and_return;
  732. }
  733. return (0);
  734. }
  735. if (urls == NULL) {
  736. return (0);
  737. }
  738. if ((ber = der_alloc()) == NULL) {
  739. slapi_log_err(SLAPI_LOG_ERR, "send_ldapv3_referral", "ber_alloc failed\n");
  740. send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
  741. "ber_alloc", 0, NULL);
  742. return (-1);
  743. }
  744. /*
  745. * send the ldapv3 SearchResultReference. it looks like this:
  746. *
  747. * SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL
  748. *
  749. * all wrapped up in an LDAPMessage sequence which looks like this:
  750. * LDAPMessage ::= SEQUENCE {
  751. * messageID MessageID,
  752. * SearchResultReference
  753. * controls [0] Controls OPTIONAL
  754. * }
  755. */
  756. for (i = 0, rc = ber_printf(ber, "{it{", operation->o_msgid,
  757. LDAP_RES_SEARCH_REFERENCE);
  758. rc != LBER_ERROR && urls[i] != NULL; i++) {
  759. rc = ber_printf(ber, "s", urls[i]->bv_val);
  760. }
  761. if (rc == LBER_ERROR) {
  762. slapi_log_err(SLAPI_LOG_ERR, "send_ldapv3_referral", "ber_printf failed 2\n");
  763. send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
  764. "ber_printf", 0, NULL);
  765. return (-1);
  766. }
  767. if (ber_printf(ber, "}}") == LBER_ERROR) {
  768. slapi_log_err(SLAPI_LOG_ERR, "send_ldapv3_referral", "ber_printf failed 3\n");
  769. send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
  770. "ber_printf", 0, NULL);
  771. return (-1);
  772. }
  773. /* write only one pdu at a time - wait til it's our turn */
  774. if ((rc = flush_ber(pb, conn, operation, ber, _LDAP_SEND_REFERRAL)) == 0) {
  775. logit = 1;
  776. }
  777. log_and_return:
  778. if (logit && operation_is_flag_set(operation,
  779. OP_FLAG_ACTION_LOG_ACCESS)) {
  780. log_referral(operation);
  781. }
  782. return (rc);
  783. }
  784. /*
  785. * send_ldap_referral - called to send a referral (SearchResultReference)
  786. * to a v3 client during a search. for v2 clients, it just adds the
  787. * referral(s) to the url list passed in the third parameter. this list
  788. * is then returned to v2 clients when it is passed to send_ldap_result().
  789. */
  790. int
  791. send_ldap_referral(
  792. Slapi_PBlock *pb,
  793. Slapi_Entry *e,
  794. struct berval **refs,
  795. struct berval ***urls)
  796. {
  797. char *refAttr = "ref";
  798. char *attrs[2] = {NULL, NULL};
  799. Connection *pb_conn;
  800. /* count the referral */
  801. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
  802. attrs[0] = refAttr;
  803. if (e != NULL &&
  804. plugin_call_acl_plugin(pb, e, attrs, NULL,
  805. SLAPI_ACL_READ, ACLPLUGIN_ACCESS_DEFAULT, NULL) != LDAP_SUCCESS) {
  806. return (0);
  807. }
  808. slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
  809. if (pb_conn && pb_conn->c_ldapversion > LDAP_VERSION2) {
  810. /*
  811. * v3 connection - send the referral(s) in a
  812. * SearchResultReference packet right now.
  813. */
  814. return (send_ldapv3_referral(pb, refs));
  815. } else {
  816. /*
  817. * v2 connection - add the referral(s) to the
  818. * list being maintained in urls. they will be
  819. * sent to the client later when send_ldap_result()
  820. * is called.
  821. */
  822. int i, need, have;
  823. if (refs == NULL && urls == NULL) {
  824. return (0);
  825. }
  826. for (have = 0; *urls != NULL && (*urls)[have] != NULL;
  827. have++) {
  828. ; /* NULL */
  829. }
  830. for (need = 0; refs != NULL && refs[need] != NULL; need++) {
  831. ; /* NULL */
  832. }
  833. *urls = (struct berval **)slapi_ch_realloc((char *)*urls,
  834. (need + have + 1) * sizeof(struct berval *));
  835. for (i = have; i < have + need; i++) {
  836. (*urls)[i] = ber_bvdup(refs[i - have]);
  837. }
  838. (*urls)[i] = NULL;
  839. }
  840. return (0);
  841. }
  842. int
  843. encode_attr_2(
  844. Slapi_PBlock *pb,
  845. BerElement *ber,
  846. Slapi_Entry *e,
  847. Slapi_ValueSet *vs,
  848. int attrsonly,
  849. const char *attribute_type,
  850. const char *returned_type)
  851. {
  852. char *attrs[2] = {NULL, NULL};
  853. Slapi_Value *v;
  854. int i = slapi_valueset_first_value(vs, &v);
  855. if (i == -1) {
  856. return (0);
  857. }
  858. attrs[0] = (char *)attribute_type;
  859. #if !defined(DISABLE_ACL_CHECK)
  860. if (plugin_call_acl_plugin(pb, e, attrs, NULL, SLAPI_ACL_READ,
  861. ACLPLUGIN_ACCESS_READ_ON_ATTR, NULL) != LDAP_SUCCESS) {
  862. return (0);
  863. }
  864. #endif
  865. if (ber_printf(ber, "{s[", returned_type ? returned_type : attribute_type) == -1) {
  866. slapi_log_err(SLAPI_LOG_ERR, "encode_attr_2", "ber_printf failed 4\n");
  867. ber_free(ber, 1);
  868. send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
  869. "ber_printf type", 0, NULL);
  870. return (-1);
  871. }
  872. if (!attrsonly) {
  873. while (i != -1) {
  874. if (ber_printf(ber, "o", v->bv.bv_val, v->bv.bv_len) == -1) {
  875. slapi_log_err(SLAPI_LOG_ERR,
  876. "encode_attr_2", "ber_printf failed 5\n");
  877. ber_free(ber, 1);
  878. send_ldap_result(pb, LDAP_OPERATIONS_ERROR,
  879. NULL, "ber_printf value", 0, NULL);
  880. return (-1);
  881. }
  882. i = slapi_valueset_next_value(vs, i, &v);
  883. }
  884. }
  885. if (ber_printf(ber, "]}") == -1) {
  886. slapi_log_err(SLAPI_LOG_ERR, "encode_attr_2", "ber_printf failed 6\n");
  887. ber_free(ber, 1);
  888. send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
  889. "ber_printf type end", 0, NULL);
  890. return (-1);
  891. }
  892. return (0);
  893. }
  894. int
  895. encode_attr(
  896. Slapi_PBlock *pb,
  897. BerElement *ber,
  898. Slapi_Entry *e,
  899. Slapi_Attr *a,
  900. int attrsonly,
  901. char *type)
  902. {
  903. return encode_attr_2(pb, ber, e, &(a->a_present_values), attrsonly, a->a_type, type);
  904. }
  905. #define LASTMODATTR(x) (strcasecmp(x, "modifytimestamp") == 0 || strcasecmp(x, "modifiersname") == 0 || strcasecmp(x, "internalmodifytimestamp") == 0 || strcasecmp(x, "internalmodifiersname") == 0 || strcasecmp(x, "createtimestamp") == 0 || strcasecmp(x, "creatorsname") == 0)
  906. /*
  907. * send_ldap_search_entry:
  908. * return 0 if OK
  909. * return 1 if this entry not sent
  910. * return -1 if error result sent or fatal error
  911. */
  912. int
  913. send_ldap_search_entry(
  914. Slapi_PBlock *pb,
  915. Slapi_Entry *e,
  916. LDAPControl **ectrls,
  917. char **attrs,
  918. int attrsonly)
  919. {
  920. return send_ldap_search_entry_ext(pb, e, ectrls, attrs, attrsonly, 0, 0, NULL);
  921. }
  922. /*
  923. * LDAPv2 attr names from RFC1274 and their LDAPv3 equivalent.
  924. *
  925. * The ;binary attrs are deliberately reversed.
  926. */
  927. static const char *idds_v2_attrt[][2] = {
  928. {"commonName", "cn"},
  929. {"surname", "sn"},
  930. {"userCertificate;binary", "userCertificate"},
  931. {"caCertificate;binary", "caCertificate"},
  932. {"countryName", "c"},
  933. {"localityName", "l"},
  934. {"stateOrProvinceName", "st"},
  935. {"streetAddress", "street"},
  936. {"organizationName", "o"},
  937. {"organizationalUnitName", "ou"},
  938. {"userid", "uid"},
  939. {"rfc822Mailbox", "mail"},
  940. {"domainComponent", "dc"},
  941. {"mobileTelephoneNumber", "mobile"},
  942. {"pagerTelephoneNumber", "pager"},
  943. {"friendlyCountryName", "co"},
  944. {NULL, NULL}};
  945. /*
  946. * Map an LDAPv3 attribute name to its LDAPv2 equivalent.
  947. */
  948. static const char *
  949. idds_map_attrt_v3(
  950. const char *atin)
  951. {
  952. int i;
  953. for (i = 0; idds_v2_attrt[i][0] != NULL; i++) {
  954. if (strcasecmp(atin, idds_v2_attrt[i][1]) == 0) {
  955. return (idds_v2_attrt[i][0]);
  956. }
  957. }
  958. return NULL;
  959. }
  960. /*
  961. * RFC: 2251 Page: 29
  962. *
  963. * attributes: A list of the attributes to be returned from each entry
  964. * which matches the search filter. There are two special values which
  965. * may be used: an empty list with no attributes, and the attribute
  966. * description string "*". Both of these signify that all user
  967. * attributes are to be returned. (The "*" allows the client to
  968. * request all user attributes in addition to specific operational
  969. * attributes).
  970. *
  971. * Attributes MUST be named at most once in the list, and are returned
  972. * at most once in an entry. If there are attribute descriptions in
  973. * the list which are not recognized, they are ignored by the server.
  974. *
  975. * If the client does not want any attributes returned, it can specify
  976. * a list containing only the attribute with OID "1.1". This OID was
  977. * chosen arbitrarily and does not correspond to any attribute in use.
  978. */
  979. /* Helper functions */
  980. static int
  981. send_all_attrs(Slapi_Entry *e, char **attrs, Slapi_Operation *op, Slapi_PBlock *pb, BerElement *ber, int attrsonly, int ldapversion, int real_attrs_only, int some_named_attrs, int alloperationalattrs, int alluserattrs)
  982. {
  983. int i = 0;
  984. int rc = 0;
  985. int typelist_flags = 0;
  986. vattr_type_thang *typelist = NULL;
  987. vattr_type_thang *current_type = NULL;
  988. char *current_type_name = NULL;
  989. int rewrite_rfc1274 = 0;
  990. int vattr_flags = 0;
  991. const char *dn = NULL;
  992. char **default_attrs = NULL;
  993. if (real_attrs_only == SLAPI_SEND_VATTR_FLAG_REALONLY)
  994. vattr_flags = SLAPI_REALATTRS_ONLY;
  995. else {
  996. vattr_flags = SLAPI_VIRTUALATTRS_REQUEST_POINTERS;
  997. if (real_attrs_only == SLAPI_SEND_VATTR_FLAG_VIRTUALONLY)
  998. vattr_flags |= SLAPI_VIRTUALATTRS_ONLY;
  999. }
  1000. if (some_named_attrs || alloperationalattrs) {
  1001. /*
  1002. * If the client listed some attribute types by name, one or
  1003. * more of the requested types MAY be operational. Inform the
  1004. * virtual attributes subsystem (certain optimizations are done
  1005. * by the vattrs code and vattr service providers if operational
  1006. * attributes are NOT requested).
  1007. */
  1008. vattr_flags |= SLAPI_VIRTUALATTRS_LIST_OPERATIONAL_ATTRS;
  1009. }
  1010. rc = slapi_vattr_list_attrs(e, &typelist, vattr_flags, &typelist_flags);
  1011. if (0 != rc) {
  1012. goto exit;
  1013. }
  1014. if (typelist_flags & SLAPI_VIRTUALATTRS_REALATTRS_ONLY) {
  1015. /*
  1016. * There is no point in consulting the vattr service providers
  1017. * for every attr if they didn't contribute to the attr list.
  1018. */
  1019. vattr_flags |= SLAPI_REALATTRS_ONLY;
  1020. }
  1021. rewrite_rfc1274 = config_get_rewrite_rfc1274();
  1022. dn = slapi_entry_get_dn_const(e);
  1023. if (dn == NULL || *dn == '\0') {
  1024. default_attrs = slapi_entry_attr_get_charray(e, CONFIG_RETURN_DEFAULT_OPATTR);
  1025. }
  1026. /* Send the attrs back to the client */
  1027. for (current_type = vattr_typethang_first(typelist); current_type; current_type = vattr_typethang_next(current_type)) {
  1028. Slapi_ValueSet **values = NULL;
  1029. int attr_free_flags = 0;
  1030. unsigned long current_type_flags = 0;
  1031. int sendit = 0;
  1032. char *name_to_return = NULL;
  1033. int *type_name_disposition = 0;
  1034. char **actual_type_name = NULL;
  1035. const char *v2name = NULL;
  1036. current_type_name = vattr_typethang_get_name(current_type);
  1037. current_type_flags = vattr_typethang_get_flags(current_type);
  1038. name_to_return = current_type_name;
  1039. /* We only return operational attributes if the client is LDAPv2 and the attribute is one of a special set,
  1040. OR if all operational attrs are requested, OR if the client also requested the attribute by name.
  1041. If it did, we use the specified name rather than the base name.
  1042. */
  1043. if (current_type_flags & SLAPI_ATTR_FLAG_OPATTR) {
  1044. if ((LDAP_VERSION2 == ldapversion && LASTMODATTR(current_type_name)) || alloperationalattrs) {
  1045. sendit = 1;
  1046. } else {
  1047. for (i = 0; attrs != NULL && attrs[i] != NULL; i++) {
  1048. if (slapi_attr_type_cmp(attrs[i], current_type_name, SLAPI_TYPE_CMP_SUBTYPE) == 0) {
  1049. sendit = 1;
  1050. name_to_return = op->o_searchattrs[i];
  1051. break;
  1052. }
  1053. }
  1054. if (!sendit && default_attrs) {
  1055. for (i = 0; default_attrs != NULL && default_attrs[i] != NULL; i++) {
  1056. if (slapi_attr_type_cmp(default_attrs[i], current_type_name, SLAPI_TYPE_CMP_SUBTYPE) == 0) {
  1057. sendit = 1;
  1058. break;
  1059. }
  1060. }
  1061. }
  1062. }
  1063. /*
  1064. * it's a user attribute. send it.
  1065. */
  1066. } else if (alluserattrs) {
  1067. sendit = 1;
  1068. }
  1069. /* Now send to the client */
  1070. if (sendit) {
  1071. /**********************************************/
  1072. int item_count = 0;
  1073. int iter = 0;
  1074. Slapi_DN *namespace_dn;
  1075. Slapi_Backend *be = 0;
  1076. vattr_context *ctx;
  1077. /* get the namespace dn */
  1078. slapi_pblock_get(pb, SLAPI_BACKEND, (void *)&be);
  1079. namespace_dn = (Slapi_DN *)slapi_be_getsuffix(be, 0);
  1080. /* Get the attribute value from the vattr service */
  1081. /* ctx will be freed by attr_context_ungrok() */
  1082. ctx = vattr_context_new(pb);
  1083. rc = slapi_vattr_namespace_values_get_sp(
  1084. ctx,
  1085. e,
  1086. namespace_dn,
  1087. current_type_name,
  1088. &values,
  1089. &type_name_disposition,
  1090. &actual_type_name,
  1091. vattr_flags | SLAPI_VIRTUALATTRS_SUPPRESS_SUBTYPES,
  1092. &attr_free_flags,
  1093. &item_count);
  1094. if ((0 == rc) && (item_count > 0)) {
  1095. for (iter = 0; iter < item_count; iter++) {
  1096. int skipit;
  1097. if (rc != 0) {
  1098. /* we hit an error - we need to free all of the stuff allocated by
  1099. slapi_vattr_namespace_values_get_sp */
  1100. slapi_vattr_values_free(&(values[iter]), &(actual_type_name[iter]), attr_free_flags);
  1101. continue;
  1102. }
  1103. if (SLAPI_VIRTUALATTRS_TYPE_NAME_MATCHED_SUBTYPE == type_name_disposition[iter]) {
  1104. name_to_return = actual_type_name[iter];
  1105. }
  1106. /* If current_type_name is in attrs, we could rely on send_specific_attrs. */
  1107. skipit = 0;
  1108. for (i = 0; attrs && attrs[i]; i++) {
  1109. if (slapi_attr_type_cmp(current_type_name, attrs[i], SLAPI_TYPE_CMP_SUBTYPE) == 0) {
  1110. skipit = 1;
  1111. break;
  1112. }
  1113. }
  1114. if (!skipit) {
  1115. rc = encode_attr_2(pb, ber, e, values[iter], attrsonly,
  1116. current_type_name, name_to_return);
  1117. if (rewrite_rfc1274 != 0) {
  1118. v2name = idds_map_attrt_v3(current_type_name);
  1119. if (v2name != NULL) {
  1120. /* also return values with RFC1274 attr name */
  1121. rc = encode_attr_2(pb, ber, e, values[iter],
  1122. attrsonly,
  1123. current_type_name,
  1124. v2name);
  1125. }
  1126. }
  1127. }
  1128. slapi_vattr_values_free(&(values[iter]), &(actual_type_name[iter]), attr_free_flags);
  1129. }
  1130. slapi_ch_free((void **)&actual_type_name);
  1131. slapi_ch_free((void **)&type_name_disposition);
  1132. slapi_ch_free((void **)&values);
  1133. if (rc != 0) {
  1134. goto exit;
  1135. }
  1136. } else {
  1137. /* if we got here, then either values is NULL or values contains no elements
  1138. either way we can free it */
  1139. slapi_ch_free((void **)&values);
  1140. slapi_ch_free((void **)&actual_type_name);
  1141. slapi_ch_free((void **)&type_name_disposition);
  1142. rc = 0;
  1143. }
  1144. }
  1145. }
  1146. exit:
  1147. if (NULL != typelist) {
  1148. slapi_vattr_attrs_free(&typelist, typelist_flags);
  1149. }
  1150. if (NULL != default_attrs) {
  1151. slapi_ch_free((void **)&default_attrs);
  1152. }
  1153. return rc;
  1154. }
  1155. /*
  1156. * attrs need to expand including the subtypes found in the entry
  1157. * e.g., if "sn" is no the attrs and 'e' has sn, sn;en, and sn;fr,
  1158. * attrs should have sn, sn;en, and sn;fr, as well.
  1159. */
  1160. int
  1161. send_specific_attrs(Slapi_Entry *e, char **attrs, Slapi_Operation *op, Slapi_PBlock *pb, BerElement *ber, int attrsonly, int ldapversion __attribute__((unused)), int real_attrs_only)
  1162. {
  1163. int i = 0;
  1164. int rc = 0;
  1165. int vattr_flags = 0;
  1166. vattr_context *ctx;
  1167. char **attrs_ext = NULL;
  1168. char **my_searchattrs = NULL;
  1169. if (real_attrs_only == SLAPI_SEND_VATTR_FLAG_REALONLY) {
  1170. vattr_flags = SLAPI_REALATTRS_ONLY;
  1171. } else {
  1172. vattr_flags = SLAPI_VIRTUALATTRS_REQUEST_POINTERS;
  1173. if (real_attrs_only == SLAPI_SEND_VATTR_FLAG_VIRTUALONLY)
  1174. vattr_flags |= SLAPI_VIRTUALATTRS_ONLY;
  1175. }
  1176. /* Create a copy of attrs with no duplicates */
  1177. if (attrs) {
  1178. for (i = 0; attrs[i]; i++) {
  1179. if (!charray_inlist(attrs_ext, attrs[i])) {
  1180. slapi_ch_array_add(&attrs_ext, slapi_ch_strdup(attrs[i]));
  1181. slapi_ch_array_add(&my_searchattrs, slapi_ch_strdup(op->o_searchattrs[i]));
  1182. }
  1183. }
  1184. }
  1185. if (attrs_ext) {
  1186. attrs = attrs_ext;
  1187. }
  1188. for (i = 0; my_searchattrs && attrs && attrs[i] != NULL; i++) {
  1189. char *current_type_name = attrs[i];
  1190. Slapi_ValueSet **values = NULL;
  1191. int attr_free_flags = 0;
  1192. char *name_to_return = NULL;
  1193. char **actual_type_name = NULL;
  1194. int *type_name_disposition = 0;
  1195. int item_count = 0;
  1196. int iter = 0;
  1197. Slapi_DN *namespace_dn;
  1198. Slapi_Backend *be = 0;
  1199. /*
  1200. * Here we call the computed attribute code to see whether
  1201. * the requested attribute is to be computed.
  1202. * The subroutine compute_attribute calls encode_attr on our behalf, in order
  1203. * to avoid the inefficiency of returning a complex structure
  1204. * which we'd have to free
  1205. */
  1206. rc = compute_attribute(attrs[i], pb, ber, e, attrsonly, my_searchattrs[i]);
  1207. if (0 == rc) {
  1208. continue; /* Means this was a computed attr and we prcessed it OK. */
  1209. }
  1210. if (-1 != rc) {
  1211. /* Means that some error happened */
  1212. return rc;
  1213. } else {
  1214. rc = 0; /* Means that we just didn't recognize this as a computed attr */
  1215. }
  1216. /* get the namespace dn */
  1217. slapi_pblock_get(pb, SLAPI_BACKEND, (void *)&be);
  1218. namespace_dn = (Slapi_DN *)slapi_be_getsuffix(be, 0);
  1219. /* Get the attribute value from the vattr service */
  1220. /* This call handles subtype, as well.
  1221. * e.g., current_type_name: cn
  1222. * ==>
  1223. * item_count: 5; actual_type_name: cn;sub0, ..., cn;sub4 */
  1224. /* ctx will be freed by attr_context_ungrok() */
  1225. ctx = vattr_context_new(pb);
  1226. rc = slapi_vattr_namespace_values_get_sp(
  1227. ctx,
  1228. e,
  1229. namespace_dn,
  1230. current_type_name,
  1231. &values,
  1232. &type_name_disposition,
  1233. &actual_type_name,
  1234. vattr_flags,
  1235. &attr_free_flags,
  1236. &item_count);
  1237. if ((0 == rc) && (item_count > 0)) {
  1238. for (iter = 0; iter < item_count; iter++) {
  1239. if (rc != 0) {
  1240. /* we hit an error - we need to free all of the stuff allocated by
  1241. slapi_vattr_namespace_values_get_sp */
  1242. slapi_vattr_values_free(&(values[iter]), &(actual_type_name[iter]), attr_free_flags);
  1243. continue;
  1244. }
  1245. if (SLAPI_VIRTUALATTRS_TYPE_NAME_MATCHED_SUBTYPE == type_name_disposition[iter]) {
  1246. name_to_return = actual_type_name[iter];
  1247. if ((iter > 0) && charray_inlist(attrs, name_to_return)) {
  1248. /* subtype retrieved by slapi_vattr_namespace_values_get_sp is
  1249. * included in the attr list. Skip the dup. */
  1250. continue;
  1251. }
  1252. } else {
  1253. name_to_return = my_searchattrs[i];
  1254. }
  1255. /* need to pass actual_type_name (e.g., sn;en to evaluate the ACL */
  1256. rc = encode_attr_2(pb, ber, e, values[iter], attrsonly,
  1257. actual_type_name[iter], name_to_return);
  1258. slapi_vattr_values_free(&(values[iter]), &(actual_type_name[iter]), attr_free_flags);
  1259. }
  1260. slapi_ch_free((void **)&actual_type_name);
  1261. slapi_ch_free((void **)&type_name_disposition);
  1262. slapi_ch_free((void **)&values);
  1263. if (rc != 0) {
  1264. goto exit;
  1265. }
  1266. } else {
  1267. /* if we got here, then either values is NULL or values contains no elements
  1268. either way we can free it */
  1269. slapi_ch_free((void **)&values);
  1270. slapi_ch_free((void **)&actual_type_name);
  1271. slapi_ch_free((void **)&type_name_disposition);
  1272. rc = 0;
  1273. }
  1274. }
  1275. exit:
  1276. slapi_ch_array_free(attrs_ext);
  1277. slapi_ch_array_free(my_searchattrs);
  1278. return rc;
  1279. }
  1280. int
  1281. send_ldap_search_entry_ext(
  1282. Slapi_PBlock *pb,
  1283. Slapi_Entry *e,
  1284. LDAPControl **ectrls,
  1285. char **attrs,
  1286. int attrsonly,
  1287. int send_result,
  1288. int nentries,
  1289. struct berval **urls)
  1290. {
  1291. Connection *conn = NULL;
  1292. BerElement *ber = NULL;
  1293. int i, rc = 0, logit = 0;
  1294. int alluserattrs;
  1295. int noattrs;
  1296. int some_named_attrs;
  1297. int alloperationalattrs;
  1298. Slapi_Operation *operation;
  1299. int real_attrs_only = 0;
  1300. LDAPControl **ctrlp = 0;
  1301. Slapi_Entry *gerentry = NULL;
  1302. Slapi_Entry *ecopy = NULL;
  1303. LDAPControl **searchctrlp = NULL;
  1304. slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);
  1305. slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
  1306. slapi_log_err(SLAPI_LOG_TRACE, "send_ldap_search_entry_ext", "=> (%s)\n",
  1307. e ? slapi_entry_get_dn_const(e) : "null");
  1308. /* set current entry */
  1309. slapi_pblock_set(pb, SLAPI_SEARCH_ENTRY_ORIG, e);
  1310. /* set controls */
  1311. slapi_pblock_set(pb, SLAPI_SEARCH_CTRLS, ectrls);
  1312. /* call pre entry fn */
  1313. rc = plugin_call_plugins(pb, SLAPI_PLUGIN_PRE_ENTRY_FN);
  1314. if (rc) {
  1315. slapi_log_err(SLAPI_LOG_ERR, "send_ldap_search_entry_ext",
  1316. "Error %d returned by pre entry plugins for entry %s\n",
  1317. rc, e ? slapi_entry_get_dn_const(e) : "null");
  1318. goto cleanup;
  1319. }
  1320. slapi_pblock_get(pb, SLAPI_SEARCH_ENTRY_COPY, &ecopy);
  1321. if (ecopy) {
  1322. e = ecopy; /* send back the altered entry */
  1323. }
  1324. slapi_pblock_get(pb, SLAPI_SEARCH_CTRLS, &searchctrlp);
  1325. if (conn == NULL && e) {
  1326. Slapi_Backend *pb_backend;
  1327. slapi_pblock_get(pb, SLAPI_BACKEND, &pb_backend);
  1328. if (operation->o_search_entry_handler != NULL) {
  1329. if ((rc = (*operation->o_search_entry_handler)(
  1330. pb_backend, conn, operation, e)) == 0) {
  1331. logit = 1;
  1332. goto log_and_return;
  1333. } else {
  1334. goto cleanup;
  1335. }
  1336. }
  1337. rc = 0;
  1338. goto cleanup;
  1339. }
  1340. #if !defined(DISABLE_ACL_CHECK)
  1341. if (e && plugin_call_acl_plugin(pb, e, attrs, NULL, SLAPI_ACL_READ, ACLPLUGIN_ACCESS_READ_ON_ENTRY, NULL) != LDAP_SUCCESS) {
  1342. slapi_log_err(SLAPI_LOG_ACL, "send_ldap_search_entry_ext", "Access to entry not allowed\n");
  1343. rc = 1;
  1344. goto cleanup;
  1345. }
  1346. #endif
  1347. if (NULL == e) {
  1348. rc = 1; /* everything is ok - don't send the result */
  1349. goto cleanup;
  1350. }
  1351. if ((ber = der_alloc()) == NULL) {
  1352. slapi_log_err(SLAPI_LOG_ERR, "send_ldap_search_entry_ext", "ber_alloc failed\n");
  1353. send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
  1354. "ber_alloc", 0, NULL);
  1355. rc = -1;
  1356. goto cleanup;
  1357. }
  1358. rc = ber_printf(ber, "{it{s{", operation->o_msgid,
  1359. LDAP_RES_SEARCH_ENTRY, slapi_entry_get_dn_const(e));
  1360. if (rc == -1) {
  1361. slapi_log_err(SLAPI_LOG_ERR, "send_ldap_search_entry_ext", "ber_printf failed 7\n");
  1362. send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
  1363. "ber_printf dn", 0, NULL);
  1364. goto cleanup;
  1365. }
  1366. /*
  1367. * in ldapv3, the special attribute "*" means all user attributes,
  1368. * NULL means all user attributes, "1.1" means no attributes, and
  1369. * "+" means all operational attributes (rfc3673)
  1370. * operational attributes are only retrieved if they are named
  1371. * specifically or when "+" is specified.
  1372. * In the case of "1.1", if there are other requested attributes
  1373. * then "1.1" should be ignored.
  1374. */
  1375. /* figure out if we want all user attributes or no attributes at all */
  1376. alluserattrs = 0;
  1377. noattrs = 0;
  1378. some_named_attrs = 0;
  1379. alloperationalattrs = 0;
  1380. if (attrs == NULL) {
  1381. alluserattrs = 1;
  1382. } else {
  1383. for (i = 0; attrs[i] != NULL; i++) {
  1384. if (strcmp(LDAP_ALL_USER_ATTRS, attrs[i]) == 0) {
  1385. alluserattrs = 1;
  1386. } else if (strcmp(LDAP_NO_ATTRS, attrs[i]) == 0) {
  1387. /* "1.1" is only valid if it's the only requested attribute */
  1388. if (i == 0 && attrs[1] == NULL) {
  1389. noattrs = 1;
  1390. }
  1391. } else if (strcmp(LDAP_ALL_OPERATIONAL_ATTRS, attrs[i]) == 0) {
  1392. alloperationalattrs = 1;
  1393. } else {
  1394. some_named_attrs = 1;
  1395. }
  1396. }
  1397. if (i > 1 && noattrs) {
  1398. /*
  1399. * user has specified the special "1.1" noattrs attr
  1400. * and some other stuff. this is not allowed, but
  1401. * what should we do? we'll allow them to keep going.
  1402. */
  1403. slapi_log_err(SLAPI_LOG_TRACE, "send_ldap_search_entry_ext",
  1404. "Accepting illegal other attributes specified with special \"1.1\" attribute\n");
  1405. }
  1406. }
  1407. /* determine whether we are to return virtual attributes */
  1408. slapi_pblock_get(pb, SLAPI_REQCONTROLS, &ctrlp);
  1409. if (slapi_control_present(ctrlp, LDAP_CONTROL_REAL_ATTRS_ONLY, NULL, NULL))
  1410. real_attrs_only = SLAPI_SEND_VATTR_FLAG_REALONLY;
  1411. if (slapi_control_present(ctrlp, LDAP_CONTROL_VIRT_ATTRS_ONLY, NULL, NULL)) {
  1412. if (real_attrs_only != SLAPI_SEND_VATTR_FLAG_REALONLY)
  1413. real_attrs_only = SLAPI_SEND_VATTR_FLAG_VIRTUALONLY;
  1414. else {
  1415. /* we cannot service a request for virtual only and real only */
  1416. send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
  1417. "Both real and virtual attributes only controls", 0, NULL);
  1418. rc = -1;
  1419. goto cleanup;
  1420. }
  1421. }
  1422. /* look through each attribute in the entry */
  1423. if (alluserattrs || alloperationalattrs) {
  1424. rc = send_all_attrs(e, attrs, operation, pb, ber, attrsonly, conn->c_ldapversion,
  1425. real_attrs_only, some_named_attrs, alloperationalattrs, alluserattrs);
  1426. }
  1427. /* if the client explicitly specified a list of attributes look through each attribute requested */
  1428. if ((rc == 0) && (attrs != NULL) && !noattrs) {
  1429. rc = send_specific_attrs(e, attrs, operation, pb, ber, attrsonly, conn->c_ldapversion, real_attrs_only);
  1430. }
  1431. /* Append effective rights to the stream of attribute list */
  1432. if (operation->o_flags & OP_FLAG_GET_EFFECTIVE_RIGHTS) {
  1433. char *gerstr;
  1434. char *entryrights;
  1435. char *attributerights;
  1436. char *p;
  1437. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &gerstr);
  1438. /* Syntax check - see acleffectiverights.c */
  1439. if (gerstr && (p = strchr(gerstr, '\n')) != NULL &&
  1440. strncasecmp(gerstr, "entryLevelRights: ",
  1441. strlen("entryLevelRights: ")) == 0 &&
  1442. strncasecmp(p + 1, "attributeLevelRights: ",
  1443. strlen("attributeLevelRights: ")) == 0) {
  1444. entryrights = gerstr + strlen("entryLevelRights: ");
  1445. *p = '\0';
  1446. attributerights = p + 1 + strlen("attributeLevelRights: ");
  1447. ber_printf(ber, "{s[o]}", "entryLevelRights", entryrights, strlen(entryrights));
  1448. ber_printf(ber, "{s[o]}", "attributeLevelRights", attributerights, strlen(attributerights));
  1449. }
  1450. }
  1451. if (rc != 0) {
  1452. goto cleanup;
  1453. }
  1454. rc = ber_printf(ber, "}}");
  1455. if (conn->c_ldapversion >= LDAP_VERSION3) {
  1456. if (searchctrlp != NULL) {
  1457. rc = write_controls(ber, searchctrlp);
  1458. }
  1459. }
  1460. if (rc != -1) {
  1461. rc = ber_printf(ber, "}");
  1462. }
  1463. if (rc == -1) {
  1464. slapi_log_err(SLAPI_LOG_ERR, "send_ldap_search_entry_ext", "ber_printf failed 8\n");
  1465. send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
  1466. "ber_printf entry end", 0, NULL);
  1467. goto cleanup;
  1468. }
  1469. if (send_result) {
  1470. send_ldap_result_ext(pb, LDAP_SUCCESS, NULL, NULL, nentries, urls, ber);
  1471. }
  1472. /* write only one pdu at a time - wait til it's our turn */
  1473. if ((rc = flush_ber(pb, conn, operation, ber, _LDAP_SEND_ENTRY)) == 0) {
  1474. logit = 1;
  1475. }
  1476. ber = NULL; /* flush_ber will always free the ber */
  1477. log_and_return:
  1478. if (logit && operation_is_flag_set(operation, OP_FLAG_ACTION_LOG_ACCESS)) {
  1479. log_entry(operation, e);
  1480. if (send_result) {
  1481. ber_tag_t tag;
  1482. switch (operation->o_tag) {
  1483. case LBER_DEFAULT:
  1484. tag = LBER_SEQUENCE;
  1485. break;
  1486. case LDAP_REQ_SEARCH:
  1487. tag = LDAP_RES_SEARCH_RESULT;
  1488. break;
  1489. case LDAP_REQ_DELETE:
  1490. tag = LDAP_RES_DELETE;
  1491. break;
  1492. case LDAP_REFERRAL:
  1493. if (conn != NULL && conn->c_ldapversion > LDAP_VERSION2) {
  1494. tag = LDAP_TAG_REFERRAL;
  1495. break;
  1496. }
  1497. /* FALLTHROUGH */
  1498. default:
  1499. tag = operation->o_tag + 1;
  1500. break;
  1501. }
  1502. log_result(pb, operation, LDAP_SUCCESS, tag, nentries);
  1503. }
  1504. }
  1505. cleanup:
  1506. slapi_entry_free(gerentry);
  1507. slapi_pblock_get(pb, SLAPI_SEARCH_ENTRY_COPY, &ecopy);
  1508. slapi_pblock_set(pb, SLAPI_SEARCH_ENTRY_COPY, NULL);
  1509. slapi_entry_free(ecopy);
  1510. slapi_pblock_get(pb, SLAPI_SEARCH_CTRLS, &searchctrlp);
  1511. slapi_pblock_set(pb, SLAPI_SEARCH_CTRLS, NULL);
  1512. if (searchctrlp != ectrls) {
  1513. ldap_controls_free(searchctrlp);
  1514. }
  1515. ber_free(ber, 1);
  1516. slapi_log_err(SLAPI_LOG_TRACE, "send_ldap_search_entry_ext", "<= %d\n", rc);
  1517. return (rc);
  1518. }
  1519. /*
  1520. * always frees the ber
  1521. */
  1522. static int
  1523. flush_ber(
  1524. Slapi_PBlock *pb,
  1525. Connection *conn,
  1526. Operation *op,
  1527. BerElement *ber,
  1528. int type)
  1529. {
  1530. ber_len_t bytes;
  1531. int rc = 0;
  1532. switch (type) {
  1533. case _LDAP_SEND_RESULT:
  1534. rc = plugin_call_plugins(pb, SLAPI_PLUGIN_PRE_RESULT_FN);
  1535. break;
  1536. case _LDAP_SEND_REFERRAL:
  1537. rc = plugin_call_plugins(pb, SLAPI_PLUGIN_PRE_REFERRAL_FN);
  1538. break;
  1539. case _LDAP_SEND_INTERMED:
  1540. break; /* not a plugin entry point */
  1541. }
  1542. if (rc != 0) {
  1543. ber_free(ber, 1);
  1544. return (rc);
  1545. }
  1546. if ((conn->c_flags & CONN_FLAG_CLOSING) || slapi_op_abandoned(pb)) {
  1547. slapi_log_err(SLAPI_LOG_CONNS, "flush_ber",
  1548. "Skipped because the connection was marked to be closed or abandoned\n");
  1549. ber_free(ber, 1);
  1550. /* One of the failure can be because the client has reset the connection ( closed )
  1551. * and the status needs to be updated to reflect it */
  1552. op->o_status = SLAPI_OP_STATUS_ABANDONED;
  1553. rc = -1;
  1554. } else {
  1555. ber_get_option(ber, LBER_OPT_BYTES_TO_WRITE, &bytes);
  1556. PR_Lock(conn->c_pdumutex);
  1557. rc = ber_flush(conn->c_sb, ber, 1);
  1558. PR_Unlock(conn->c_pdumutex);
  1559. if (rc != 0) {
  1560. int oserr = errno;
  1561. /* One of the failure can be because the client has reset the connection ( closed )
  1562. * and the status needs to be updated to reflect it */
  1563. op->o_status = SLAPI_OP_STATUS_ABANDONED;
  1564. slapi_log_err(SLAPI_LOG_CONNS, "flush_ber", "Failed, error %d (%s)\n",
  1565. oserr, slapd_system_strerror(oserr));
  1566. if (op->o_flags & OP_FLAG_PS) {
  1567. /* We need to tell disconnect_server() not to ding
  1568. * all the psearches if one if them disconnected
  1569. * But we do need to terminate all persistent searches that are using
  1570. * this connection
  1571. * op->o_flags |= OP_FLAG_PS_SEND_FAILED;
  1572. */
  1573. }
  1574. do_disconnect_server(conn, op->o_connid, op->o_opid);
  1575. ber_free(ber, 1);
  1576. } else {
  1577. PRUint64 b;
  1578. slapi_log_err(SLAPI_LOG_BER, "flush_ber",
  1579. "Wrote %lu bytes to socket %d\n", bytes, conn->c_sd);
  1580. LL_I2L(b, bytes);
  1581. slapi_counter_add(num_bytes_sent, b);
  1582. if (type == _LDAP_SEND_ENTRY) {
  1583. slapi_counter_increment(num_entries_sent);
  1584. }
  1585. if (!config_check_referral_mode())
  1586. slapi_counter_add(g_get_global_snmp_vars()->ops_tbl.dsBytesSent, bytes);
  1587. }
  1588. }
  1589. switch (type) {
  1590. case _LDAP_SEND_RESULT:
  1591. plugin_call_plugins(pb, SLAPI_PLUGIN_POST_RESULT_FN);
  1592. break;
  1593. case _LDAP_SEND_REFERRAL:
  1594. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned);
  1595. plugin_call_plugins(pb, SLAPI_PLUGIN_POST_REFERRAL_FN);
  1596. break;
  1597. case _LDAP_SEND_ENTRY:
  1598. slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned);
  1599. plugin_call_plugins(pb, SLAPI_PLUGIN_POST_ENTRY_FN);
  1600. break;
  1601. case _LDAP_SEND_INTERMED:
  1602. break; /* not a plugin entry point */
  1603. }
  1604. return (rc);
  1605. }
  1606. /*
  1607. Puts the default result handlers into the pblock.
  1608. This routine is called before any server call to a
  1609. database backend.
  1610. Returns : 0 on success, -1 on failure.
  1611. */
  1612. int
  1613. set_db_default_result_handlers(Slapi_PBlock *pb)
  1614. {
  1615. int rc = -1;
  1616. if (0 != pb) {
  1617. rc = slapi_pblock_set(pb, SLAPI_PLUGIN_DB_ENTRY_FN,
  1618. (void *)send_ldap_search_entry);
  1619. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_DB_RESULT_FN,
  1620. (void *)send_ldap_result);
  1621. rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_DB_REFERRAL_FN,
  1622. (void *)send_ldap_referral);
  1623. }
  1624. return rc;
  1625. }
  1626. struct slapi_note_map
  1627. {
  1628. unsigned int snp_noteid;
  1629. char *snp_string;
  1630. char *snp_detail;
  1631. };
  1632. static struct slapi_note_map notemap[] = {
  1633. {SLAPI_OP_NOTE_UNINDEXED, "U", "Partially Unindexed Filter"},
  1634. {SLAPI_OP_NOTE_SIMPLEPAGED, "P", "Paged Search"},
  1635. {SLAPI_OP_NOTE_FULL_UNINDEXED, "A", "Fully Unindexed Filter"},
  1636. {SLAPI_OP_NOTE_FILTER_INVALID, "F", "Filter Element Missing From Schema"},
  1637. };
  1638. #define SLAPI_NOTEMAP_COUNT (sizeof(notemap) / sizeof(struct slapi_note_map))
  1639. /*
  1640. * fill buf with a string representation of the bits present in notes.
  1641. *
  1642. * each bit is mapped to a character string (see table above).
  1643. * the result looks like "notes=U,Z" or similar.
  1644. * if no known notes are present, a zero-length string is generated.
  1645. * if buflen is too small, the output is truncated.
  1646. *
  1647. * Return value: buf itself.
  1648. */
  1649. static char *
  1650. notes2str(unsigned int notes, char *buf, size_t buflen)
  1651. {
  1652. char *p;
  1653. /* SLAPI_NOTEMAP_COUNT uses sizeof, size_t is unsigned. Was int */
  1654. uint i;
  1655. size_t len;
  1656. *buf = '\0';
  1657. --buflen;
  1658. if (buflen < 7) { /* must be room for "notes=X" at least */
  1659. return (buf);
  1660. }
  1661. p = buf;
  1662. for (i = 0; i < SLAPI_NOTEMAP_COUNT; ++i) {
  1663. /* Check if the flag is present in the operation notes */
  1664. if ((notemap[i].snp_noteid & notes) != 0) {
  1665. len = strlen(notemap[i].snp_string);
  1666. if (p > buf) {
  1667. if (buflen < (len + 1)) {
  1668. break;
  1669. }
  1670. // Check buflen
  1671. *p++ = ',';
  1672. --buflen;
  1673. } else {
  1674. if (buflen < (len + 6)) {
  1675. break;
  1676. }
  1677. // Check buflen
  1678. strcpy(p, "notes=");
  1679. p += 6;
  1680. buflen -= 6;
  1681. }
  1682. memcpy(p, notemap[i].snp_string, len);
  1683. buflen -= len;
  1684. p += len;
  1685. }
  1686. }
  1687. /* Get a pointer to the "start" of where we'll write the details. */
  1688. char *note_end = p;
  1689. /* Now add the details (if possible) */
  1690. for (i = 0; i < SLAPI_NOTEMAP_COUNT; ++i) {
  1691. if ((notemap[i].snp_noteid & notes) != 0) {
  1692. len = strlen(notemap[i].snp_detail);
  1693. if (p > note_end) {
  1694. /*
  1695. * len of detail + , + "
  1696. */
  1697. if (buflen < (len + 2)) {
  1698. break;
  1699. }
  1700. /*
  1701. * If the working pointer is past the start
  1702. * position, add a comma now before the next term.
  1703. */
  1704. *p++ = ',';
  1705. --buflen;
  1706. } else {
  1707. /*
  1708. * len of detail + details=" + "
  1709. */
  1710. if (buflen < (len + 11)) {
  1711. break;
  1712. }
  1713. /* This is the first iteration, so add " details=\"" */
  1714. strcpy(p, " details=\"");
  1715. p += 10;
  1716. buflen -= 10;
  1717. }
  1718. memcpy(p, notemap[i].snp_detail, len);
  1719. /*
  1720. * We don't account for the ", because on the next loop we may
  1721. * backtrack over it, so it doesn't count to the len calculation.
  1722. */
  1723. buflen -= len;
  1724. p += len;
  1725. /*
  1726. * Put in the end quote. If another snp_detail is append a comma
  1727. * will overwrite the quote.
  1728. */
  1729. *(p + 1) = '"';
  1730. }
  1731. }
  1732. return (buf);
  1733. }
  1734. static void
  1735. log_result(Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag, int nentries)
  1736. {
  1737. char *notes_str = NULL;
  1738. char notes_buf[256] = {0};
  1739. int internal_op;
  1740. CSN *operationcsn = NULL;
  1741. char csn_str[CSN_STRSIZE + 5];
  1742. char etime[ETIME_BUFSIZ] = {0};
  1743. int pr_idx = -1;
  1744. int pr_cookie = -1;
  1745. uint32_t operation_notes;
  1746. uint64_t connid;
  1747. int32_t op_id;
  1748. int32_t op_internal_id;
  1749. int32_t op_nested_count;
  1750. get_internal_conn_op(&connid, &op_id, &op_internal_id, &op_nested_count);
  1751. slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
  1752. slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_COOKIE, &pr_cookie);
  1753. internal_op = operation_is_flag_set(op, OP_FLAG_INTERNAL);
  1754. struct timespec o_hr_time_end;
  1755. slapi_operation_time_elapsed(op, &o_hr_time_end);
  1756. snprintf(etime, ETIME_BUFSIZ, "%" PRId64 ".%.09" PRId64 "", (int64_t)o_hr_time_end.tv_sec, (int64_t)o_hr_time_end.tv_nsec);
  1757. operation_notes = slapi_pblock_get_operation_notes(pb);
  1758. if (0 == operation_notes) {
  1759. notes_str = "";
  1760. } else {
  1761. notes_str = notes_buf;
  1762. *notes_buf = ' ';
  1763. notes2str(operation_notes, notes_buf + 1, sizeof(notes_buf) - 1);
  1764. }
  1765. csn_str[0] = '\0';
  1766. if (config_get_csnlogging() == LDAP_ON) {
  1767. operationcsn = operation_get_csn(op);
  1768. if (NULL != operationcsn) {
  1769. char tmp_csn_str[CSN_STRSIZE];
  1770. sprintf(csn_str, " csn=%s", csn_as_string(operationcsn, PR_FALSE, tmp_csn_str));
  1771. }
  1772. }
  1773. #define LOG_CONN_OP_FMT_INT_INT "conn=Internal(%" PRIu64 ") op=%d(%d)(%d) RESULT err=%d"
  1774. #define LOG_CONN_OP_FMT_EXT_INT "conn=%" PRIu64 " (Internal) op=%d(%d)(%d) RESULT err=%d"
  1775. if (op->o_tag == LDAP_REQ_BIND && err == LDAP_SASL_BIND_IN_PROGRESS) {
  1776. /*
  1777. * Not actually an error.
  1778. * Make that clear in the log.
  1779. */
  1780. if (!internal_op) {
  1781. slapi_log_access(LDAP_DEBUG_STATS,
  1782. "conn=%" PRIu64 " op=%d RESULT err=%d"
  1783. " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
  1784. ", SASL bind in progress\n",
  1785. op->o_connid,
  1786. op->o_opid,
  1787. err, tag, nentries,
  1788. etime,
  1789. notes_str, csn_str);
  1790. } else {
  1791. #define LOG_SASLMSG_FMT " tag=%" BERTAG_T " nentries=%d etime=%s%s%s, SASL bind in progress\n"
  1792. slapi_log_access(LDAP_DEBUG_ARGS,
  1793. connid == 0 ? LOG_CONN_OP_FMT_INT_INT LOG_SASLMSG_FMT :
  1794. LOG_CONN_OP_FMT_EXT_INT LOG_SASLMSG_FMT,
  1795. connid,
  1796. op_id,
  1797. op_internal_id,
  1798. op_nested_count,
  1799. err, tag, nentries,
  1800. etime,
  1801. notes_str, csn_str);
  1802. }
  1803. } else if (op->o_tag == LDAP_REQ_BIND && err == LDAP_SUCCESS) {
  1804. char *dn = NULL;
  1805. /*
  1806. * For methods other than simple, the dn in the bind request
  1807. * may be irrelevant. Log the actual authenticated dn.
  1808. */
  1809. slapi_pblock_get(pb, SLAPI_CONN_DN, &dn);
  1810. if (!internal_op) {
  1811. slapi_log_access(LDAP_DEBUG_STATS,
  1812. "conn=%" PRIu64 " op=%d RESULT err=%d"
  1813. " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
  1814. " dn=\"%s\"\n",
  1815. op->o_connid,
  1816. op->o_opid,
  1817. err, tag, nentries,
  1818. etime,
  1819. notes_str, csn_str, dn ? dn : "");
  1820. } else {
  1821. #define LOG_BINDMSG_FMT " tag=%" BERTAG_T " nentries=%d etime=%s%s%s dn=\"%s\"\n"
  1822. slapi_log_access(LDAP_DEBUG_ARGS,
  1823. connid == 0 ? LOG_CONN_OP_FMT_INT_INT LOG_BINDMSG_FMT :
  1824. LOG_CONN_OP_FMT_EXT_INT LOG_BINDMSG_FMT,
  1825. connid,
  1826. op_id,
  1827. op_internal_id,
  1828. op_nested_count,
  1829. err, tag, nentries,
  1830. etime,
  1831. notes_str, csn_str, dn ? dn : "");
  1832. }
  1833. slapi_ch_free((void **)&dn);
  1834. } else {
  1835. if (pr_idx > -1) {
  1836. if (!internal_op) {
  1837. slapi_log_access(LDAP_DEBUG_STATS,
  1838. "conn=%" PRIu64 " op=%d RESULT err=%d"
  1839. " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
  1840. " pr_idx=%d pr_cookie=%d\n",
  1841. op->o_connid,
  1842. op->o_opid,
  1843. err, tag, nentries,
  1844. etime,
  1845. notes_str, csn_str, pr_idx, pr_cookie);
  1846. } else {
  1847. #define LOG_PRMSG_FMT " tag=%" BERTAG_T " nentries=%d etime=%s%s%s pr_idx=%d pr_cookie=%d \n"
  1848. slapi_log_access(LDAP_DEBUG_ARGS,
  1849. connid == 0 ? LOG_CONN_OP_FMT_INT_INT LOG_PRMSG_FMT :
  1850. LOG_CONN_OP_FMT_EXT_INT LOG_PRMSG_FMT,
  1851. connid,
  1852. op_id,
  1853. op_internal_id,
  1854. op_nested_count,
  1855. err, tag, nentries,
  1856. etime,
  1857. notes_str, csn_str, pr_idx, pr_cookie);
  1858. }
  1859. } else if (!internal_op) {
  1860. char *pbtxt = NULL;
  1861. char *ext_str = NULL;
  1862. slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &pbtxt);
  1863. if (pbtxt) {
  1864. ext_str = slapi_ch_smprintf(" - %s", pbtxt);
  1865. } else {
  1866. ext_str = "";
  1867. }
  1868. slapi_log_access(LDAP_DEBUG_STATS,
  1869. "conn=%" PRIu64 " op=%d RESULT err=%d"
  1870. " tag=%" BERTAG_T " nentries=%d etime=%s%s%s%s\n",
  1871. op->o_connid,
  1872. op->o_opid,
  1873. err, tag, nentries,
  1874. etime,
  1875. notes_str, csn_str, ext_str);
  1876. if (pbtxt) {
  1877. /* if !pbtxt ==> ext_str == "". Don't free ext_str. */
  1878. slapi_ch_free_string(&ext_str);
  1879. }
  1880. } else {
  1881. int optype;
  1882. #define LOG_MSG_FMT " tag=%" BERTAG_T " nentries=%d etime=%s%s%s\n"
  1883. slapi_log_access(LDAP_DEBUG_ARGS,
  1884. connid == 0 ? LOG_CONN_OP_FMT_INT_INT LOG_MSG_FMT :
  1885. LOG_CONN_OP_FMT_EXT_INT LOG_MSG_FMT,
  1886. connid,
  1887. op_id,
  1888. op_internal_id,
  1889. op_nested_count,
  1890. err, tag, nentries,
  1891. etime,
  1892. notes_str, csn_str);
  1893. /*
  1894. * If this is an unindexed search we should log it in the error log if
  1895. * we didn't log it in the access log.
  1896. */
  1897. slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &optype);
  1898. if (optype == SLAPI_OPERATION_SEARCH && /* search, */
  1899. strcmp(notes_str, "") && /* that's unindexed, */
  1900. !(config_get_accesslog_level() & LDAP_DEBUG_ARGS) && /* and not logged in access log */
  1901. !(op->o_flags & SLAPI_OP_FLAG_IGNORE_UNINDEXED)) /* and not ignoring unindexed search */
  1902. {
  1903. struct slapdplugin *plugin = NULL;
  1904. struct slapi_componentid *cid = NULL;
  1905. char *filter_str;
  1906. char *plugin_dn;
  1907. char *base_dn;
  1908. slapi_pblock_get(pb, SLAPI_SEARCH_STRFILTER, &filter_str);
  1909. slapi_pblock_get(pb, SLAPI_TARGET_DN, &base_dn);
  1910. slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &cid);
  1911. if (cid) {
  1912. plugin = (struct slapdplugin *)cid->sci_plugin;
  1913. } else {
  1914. slapi_pblock_get(pb, SLAPI_PLUGIN, &plugin);
  1915. }
  1916. plugin_dn = plugin_get_dn(plugin);
  1917. slapi_log_err(SLAPI_LOG_ERR, "log_result", "Internal unindexed search: source (%s) "
  1918. "search base=\"%s\" filter=\"%s\" etime=%s nentries=%d %s\n",
  1919. plugin_dn, base_dn, filter_str, etime, nentries, notes_str);
  1920. slapi_ch_free_string(&plugin_dn);
  1921. }
  1922. }
  1923. }
  1924. }
  1925. static void
  1926. log_entry(Operation *op, Slapi_Entry *e)
  1927. {
  1928. int internal_op;
  1929. internal_op = operation_is_flag_set(op, OP_FLAG_INTERNAL);
  1930. if (!internal_op) {
  1931. slapi_log_access(LDAP_DEBUG_STATS2, "conn=%" PRIu64 " op=%d ENTRY dn=\"%s\"\n",
  1932. op->o_connid, op->o_opid,
  1933. slapi_entry_get_dn_const(e));
  1934. } else {
  1935. if (config_get_accesslog_level() & LDAP_DEBUG_STATS2) {
  1936. uint64_t connid;
  1937. int32_t op_id;
  1938. int32_t op_internal_id;
  1939. int32_t op_nested_count;
  1940. get_internal_conn_op(&connid, &op_id, &op_internal_id, &op_nested_count);
  1941. slapi_log_access(LDAP_DEBUG_ARGS,
  1942. connid == 0 ? "conn=Internal(%" PRIu64 ") op=%d(%d)(%d) ENTRY dn=\"%s\"\n" :
  1943. "conn=%" PRIu64 " (Internal) op=%d(%d)(%d) ENTRY dn=\"%s\"\n",
  1944. connid,
  1945. op_id,
  1946. op_internal_id,
  1947. op_nested_count,
  1948. slapi_entry_get_dn_const(e));
  1949. }
  1950. }
  1951. }
  1952. static void
  1953. log_referral(Operation *op)
  1954. {
  1955. int internal_op;
  1956. internal_op = operation_is_flag_set(op, OP_FLAG_INTERNAL);
  1957. if (!internal_op) {
  1958. slapi_log_access(LDAP_DEBUG_STATS2, "conn=%" PRIu64 " op=%d REFERRAL\n",
  1959. op->o_connid, op->o_opid);
  1960. } else {
  1961. if (config_get_accesslog_level() & LDAP_DEBUG_STATS2) {
  1962. uint64_t connid;
  1963. int32_t op_id;
  1964. int32_t op_internal_id;
  1965. int32_t op_nested_count;
  1966. get_internal_conn_op(&connid, &op_id, &op_internal_id, &op_nested_count);
  1967. slapi_log_access(LDAP_DEBUG_ARGS,
  1968. connid == 0 ? "conn=Internal(%" PRIu64 ") op=%d(%d)(%d) REFERRAL\n" :
  1969. "conn=%" PRIu64 " (Internal) op=%d(%d)(%d) REFERRAL\n",
  1970. connid, op_id, op_internal_id, op_nested_count);
  1971. }
  1972. }
  1973. }
  1974. /*
  1975. * Generate a octet string ber-encoded searchResultEntry for
  1976. * pre & post Read Entry Controls
  1977. */
  1978. static struct berval *
  1979. encode_read_entry(Slapi_PBlock *pb, Slapi_Entry *e, char **attrs, int alluserattrs, int attr_count)
  1980. {
  1981. Slapi_Operation *op = NULL;
  1982. Connection *conn = NULL;
  1983. LDAPControl **ctrlp = NULL;
  1984. struct berval *bv = NULL;
  1985. BerElement *ber = NULL;
  1986. int real_attrs_only = 0;
  1987. int rc = 0;
  1988. if ((ber = der_alloc()) == NULL) {
  1989. rc = -1;
  1990. goto cleanup;
  1991. }
  1992. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  1993. slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);
  1994. if (conn == NULL || op == NULL) {
  1995. slapi_log_err(SLAPI_LOG_ERR, "encode_read_entry",
  1996. "NULL param error: conn (0x%p) op (0x%p)\n", conn, op);
  1997. rc = -1;
  1998. goto cleanup;
  1999. }
  2000. /* Start the ber encoding with the DN */
  2001. rc = ber_printf(ber, "t{s{", LDAP_RES_SEARCH_ENTRY, slapi_entry_get_dn_const(e));
  2002. if (rc == -1) {
  2003. rc = -1;
  2004. goto cleanup;
  2005. }
  2006. /* determine whether we are to return virtual attributes */
  2007. slapi_pblock_get(pb, SLAPI_REQCONTROLS, &ctrlp);
  2008. if (slapi_control_present(ctrlp, LDAP_CONTROL_REAL_ATTRS_ONLY, NULL, NULL)) {
  2009. real_attrs_only = SLAPI_SEND_VATTR_FLAG_REALONLY;
  2010. }
  2011. if (slapi_control_present(ctrlp, LDAP_CONTROL_VIRT_ATTRS_ONLY, NULL, NULL)) {
  2012. if (real_attrs_only != SLAPI_SEND_VATTR_FLAG_REALONLY) {
  2013. real_attrs_only = SLAPI_SEND_VATTR_FLAG_VIRTUALONLY;
  2014. } else {
  2015. /* we cannot service a request for virtual only and real only */
  2016. slapi_log_err(SLAPI_LOG_ERR, "encode_read_entry",
  2017. "Both real and virtual attributes only controls requested.\n");
  2018. rc = -1;
  2019. goto cleanup;
  2020. }
  2021. }
  2022. /*
  2023. * We maintain a flag array so that we can remove requests
  2024. * for duplicate attributes. We also need to set o_searchattrs
  2025. * for the attribute processing, as modify op's don't have search attrs.
  2026. */
  2027. op->o_searchattrs = attrs;
  2028. /* Send all the attributes */
  2029. if (alluserattrs) {
  2030. rc = send_all_attrs(e, attrs, op, pb, ber, 0, conn->c_ldapversion,
  2031. real_attrs_only, attr_count, 0, 1);
  2032. if (rc) {
  2033. goto cleanup;
  2034. }
  2035. }
  2036. /* Send a specified list of attributes */
  2037. if (attrs != NULL) {
  2038. rc = send_specific_attrs(e, attrs, op, pb, ber, 0, conn->c_ldapversion, real_attrs_only);
  2039. if (rc) {
  2040. goto cleanup;
  2041. }
  2042. }
  2043. /* wrap up the ber encoding */
  2044. rc = ber_printf(ber, "}}");
  2045. if (rc != -1) {
  2046. /* generate our string encoded value */
  2047. rc = ber_flatten(ber, &bv);
  2048. }
  2049. cleanup:
  2050. ber_free(ber, 1);
  2051. if (rc != 0) {
  2052. return NULL;
  2053. } else {
  2054. return bv;
  2055. }
  2056. }
  2057. static char *
  2058. op_to_string(int tag)
  2059. {
  2060. char *op = NULL;
  2061. if (tag == LDAP_REQ_BIND) {
  2062. op = "BIND";
  2063. } else if (tag == LDAP_REQ_UNBIND) {
  2064. op = "UNBIND";
  2065. } else if (tag == LDAP_REQ_SEARCH) {
  2066. op = "SEARCH";
  2067. } else if (tag == LDAP_REQ_ADD) {
  2068. op = "ADD";
  2069. } else if (tag == LDAP_REQ_DELETE) {
  2070. op = "DELETE";
  2071. } else if (tag == LDAP_REQ_RENAME) {
  2072. op = "RENAME";
  2073. } else if (tag == LDAP_REQ_COMPARE) {
  2074. op = "COMPARE";
  2075. } else if (tag == LDAP_REQ_ABANDON) {
  2076. op = "ABANDON";
  2077. } else if (tag == LDAP_REQ_EXTENDED) {
  2078. op = "EXTENDED";
  2079. }
  2080. return op;
  2081. }