1
0

acleffectiverights.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2005 Red Hat, Inc.
  35. * All rights reserved.
  36. * END COPYRIGHT BLOCK **/
  37. #include "acl.h"
  38. /* safer than doing strcat unprotected */
  39. /* news2 is optional, provided as a convenience */
  40. /* capacity is the capacity of the gerstr, size is the current length */
  41. static void
  42. _append_gerstr(char **gerstr, size_t *capacity, size_t *size, const char *news, const char *news2)
  43. {
  44. size_t len;
  45. size_t increment = 128;
  46. size_t fornull;
  47. if (!news) {
  48. return;
  49. }
  50. /* find out how much space we need */
  51. len = strlen(news);
  52. fornull = 1;
  53. if (news2) {
  54. len += strlen(news2);
  55. fornull++;
  56. }
  57. /* increase space if needed */
  58. while ((*size + len + fornull) > *capacity) {
  59. if ((len + fornull) > increment) {
  60. *capacity += len + fornull; /* just go ahead and grow the string enough */
  61. } else {
  62. *capacity += increment; /* rather than having lots of small increments */
  63. }
  64. }
  65. if (!*gerstr) {
  66. *gerstr = slapi_ch_malloc(*capacity);
  67. **gerstr = 0;
  68. } else {
  69. *gerstr = slapi_ch_realloc(*gerstr, *capacity);
  70. }
  71. strcat(*gerstr, news);
  72. if (news2) {
  73. strcat(*gerstr, news2);
  74. }
  75. *size += len;
  76. return;
  77. }
  78. static int
  79. _ger_g_permission_granted ( Slapi_PBlock *pb, Slapi_Entry *e, char **errbuf )
  80. {
  81. char *proxydn = NULL;
  82. Slapi_DN *requestor_sdn, *entry_sdn;
  83. char *errtext = NULL;
  84. int isroot;
  85. int rc;
  86. /*
  87. * Theorically, we should check if the entry has "g"
  88. * permission granted to the requestor. If granted,
  89. * allows the effective rights on that entry and its
  90. * attributes within the entry to be returned for
  91. * ANY subject.
  92. *
  93. * "G" permission granting has not been implemented yet,
  94. * the current release assumes that "g" permission be
  95. * granted to root and owner of any entry.
  96. */
  97. /*
  98. * The requestor may be either the bind dn or a proxy dn
  99. */
  100. acl_get_proxyauth_dn ( pb, &proxydn, &errtext );
  101. if ( proxydn != NULL )
  102. {
  103. requestor_sdn = slapi_sdn_new_dn_passin ( proxydn );
  104. }
  105. else
  106. {
  107. requestor_sdn = &(pb->pb_op->o_sdn);
  108. }
  109. if ( slapi_sdn_get_dn (requestor_sdn) == NULL )
  110. {
  111. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  112. "_ger_g_permission_granted: anonymous has no g permission\n" );
  113. rc = LDAP_INSUFFICIENT_ACCESS;
  114. goto bailout;
  115. }
  116. isroot = slapi_dn_isroot ( slapi_sdn_get_dn (requestor_sdn) );
  117. if ( isroot )
  118. {
  119. /* Root has "g" permission on any entry */
  120. rc = LDAP_SUCCESS;
  121. goto bailout;
  122. }
  123. entry_sdn = slapi_entry_get_sdn ( e );
  124. if ( entry_sdn == NULL || slapi_sdn_get_dn (entry_sdn) == NULL )
  125. {
  126. rc = LDAP_SUCCESS;
  127. goto bailout;
  128. }
  129. if ( slapi_sdn_compare ( requestor_sdn, entry_sdn ) == 0 )
  130. {
  131. /* Owner has "g" permission on his own entry */
  132. rc = LDAP_SUCCESS;
  133. goto bailout;
  134. }
  135. aclutil_str_appened ( errbuf, "get-effective-rights: requestor has no g permission on the entry" );
  136. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  137. "_ger_g_permission_granted: %s\n", *errbuf);
  138. rc = LDAP_INSUFFICIENT_ACCESS;
  139. bailout:
  140. if ( proxydn )
  141. {
  142. /* The ownership of proxydn has passed to requestor_sdn */
  143. slapi_sdn_free ( &requestor_sdn );
  144. }
  145. return rc;
  146. }
  147. static int
  148. _ger_parse_control ( Slapi_PBlock *pb, char **subjectndn, int *iscritical, char **errbuf )
  149. {
  150. LDAPControl **requestcontrols;
  151. struct berval *subjectber;
  152. BerElement *ber;
  153. if (NULL == subjectndn)
  154. {
  155. return LDAP_OPERATIONS_ERROR;
  156. }
  157. *subjectndn = NULL;
  158. /*
  159. * Get the control
  160. */
  161. slapi_pblock_get ( pb, SLAPI_REQCONTROLS, (void *) &requestcontrols );
  162. slapi_control_present ( requestcontrols,
  163. LDAP_CONTROL_GET_EFFECTIVE_RIGHTS,
  164. &subjectber,
  165. iscritical );
  166. if ( subjectber == NULL || subjectber->bv_val == NULL ||
  167. subjectber->bv_len == 0 )
  168. {
  169. aclutil_str_appened ( errbuf, "get-effective-rights: missing subject" );
  170. slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
  171. return LDAP_INVALID_SYNTAX;
  172. }
  173. if ( strncasecmp ( "dn:", subjectber->bv_val, 3 ) == 0 )
  174. {
  175. /*
  176. * This is a non-standard support to allow the subject being a plain
  177. * or base64 encoding string. Hence users using -J option in
  178. * ldapsearch don't have to do BER encoding for the subject.
  179. */
  180. *subjectndn = slapi_ch_malloc ( subjectber->bv_len + 1 );
  181. strncpy ( *subjectndn, subjectber->bv_val, subjectber->bv_len );
  182. *(*subjectndn + subjectber->bv_len) = '\0';
  183. }
  184. else
  185. {
  186. ber = ber_init (subjectber);
  187. if ( ber == NULL )
  188. {
  189. aclutil_str_appened ( errbuf, "get-effective-rights: ber_init failed for the subject" );
  190. slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
  191. return LDAP_OPERATIONS_ERROR;
  192. }
  193. /* "a" means to allocate storage as needed for octet string */
  194. if ( ber_scanf (ber, "a", subjectndn) == LBER_ERROR )
  195. {
  196. aclutil_str_appened ( errbuf, "get-effective-rights: invalid ber tag in the subject" );
  197. slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
  198. ber_free ( ber, 1 );
  199. return LDAP_INVALID_SYNTAX;
  200. }
  201. ber_free ( ber, 1 );
  202. }
  203. /*
  204. * The current implementation limits the subject to authorization ID
  205. * (see section 9 of RFC 2829) only. It also only supports the "dnAuthzId"
  206. * flavor, which looks like "dn:<DN>" where null <DN> is for anonymous.
  207. */
  208. if ( NULL == *subjectndn || strlen (*subjectndn) < 3 ||
  209. strncasecmp ( "dn:", *subjectndn, 3 ) != 0 )
  210. {
  211. aclutil_str_appened ( errbuf, "get-effective-rights: subject is not dnAuthzId" );
  212. slapi_log_error (SLAPI_LOG_FATAL, plugin_name, "%s\n", *errbuf );
  213. return LDAP_INVALID_SYNTAX;
  214. }
  215. strcpy ( *subjectndn, *subjectndn + 3 );
  216. slapi_dn_normalize ( *subjectndn );
  217. return LDAP_SUCCESS;
  218. }
  219. static void
  220. _ger_release_gerpb (
  221. Slapi_PBlock **gerpb,
  222. void **aclcb, /* original aclcb */
  223. Slapi_PBlock *pb /* original pb */
  224. )
  225. {
  226. if ( *gerpb )
  227. {
  228. /* Return conn to pb */
  229. slapi_pblock_set ( *gerpb, SLAPI_CONNECTION, NULL );
  230. slapi_pblock_destroy ( *gerpb );
  231. *gerpb = NULL;
  232. }
  233. /* Put the original aclcb back to pb */
  234. if ( *aclcb )
  235. {
  236. Connection *conn = NULL;
  237. slapi_pblock_get ( pb, SLAPI_CONNECTION, &conn );
  238. if (conn)
  239. {
  240. struct aclcb *geraclcb;
  241. geraclcb = (struct aclcb *) acl_get_ext ( ACL_EXT_CONNECTION, conn );
  242. acl_conn_ext_destructor ( geraclcb, NULL, NULL );
  243. acl_set_ext ( ACL_EXT_CONNECTION, conn, *aclcb );
  244. *aclcb = NULL;
  245. }
  246. }
  247. }
  248. static int
  249. _ger_new_gerpb (
  250. Slapi_PBlock *pb,
  251. Slapi_Entry *e,
  252. const char *subjectndn,
  253. Slapi_PBlock **gerpb,
  254. void **aclcb, /* original aclcb */
  255. char **errbuf
  256. )
  257. {
  258. Connection *conn;
  259. struct acl_cblock *geraclcb;
  260. Acl_PBlock *geraclpb;
  261. Operation *gerop;
  262. int rc = LDAP_SUCCESS;
  263. *aclcb = NULL;
  264. *gerpb = slapi_pblock_new ();
  265. if ( *gerpb == NULL )
  266. {
  267. rc = LDAP_NO_MEMORY;
  268. goto bailout;
  269. }
  270. {
  271. /* aclpb initialization needs the backend */
  272. Slapi_Backend *be;
  273. slapi_pblock_get ( pb, SLAPI_BACKEND, &be );
  274. slapi_pblock_set ( *gerpb, SLAPI_BACKEND, be );
  275. }
  276. {
  277. int isroot = slapi_dn_isroot ( subjectndn );
  278. slapi_pblock_set ( *gerpb, SLAPI_REQUESTOR_ISROOT, &isroot );
  279. }
  280. /* Save requestor's aclcb and set subjectdn's one */
  281. {
  282. slapi_pblock_get ( pb, SLAPI_CONNECTION, &conn );
  283. slapi_pblock_set ( *gerpb, SLAPI_CONNECTION, conn );
  284. /* Can't share the conn->aclcb because of different context */
  285. geraclcb = (struct acl_cblock *) acl_conn_ext_constructor ( NULL, NULL);
  286. if ( geraclcb == NULL )
  287. {
  288. rc = LDAP_NO_MEMORY;
  289. goto bailout;
  290. }
  291. slapi_sdn_set_ndn_byval ( geraclcb->aclcb_sdn, subjectndn );
  292. *aclcb = acl_get_ext ( ACL_EXT_CONNECTION, conn );
  293. acl_set_ext ( ACL_EXT_CONNECTION, conn, (void *) geraclcb );
  294. }
  295. {
  296. gerop = operation_new ( OP_FLAG_INTERNAL );
  297. if ( gerop == NULL )
  298. {
  299. rc = LDAP_NO_MEMORY;
  300. goto bailout;
  301. }
  302. /*
  303. * conn is a no-use parameter in the functions
  304. * chained down from factory_create_extension
  305. */
  306. gerop->o_extension = factory_create_extension ( get_operation_object_type(), (void *)gerop, (void *)conn );
  307. slapi_pblock_set ( *gerpb, SLAPI_OPERATION, gerop );
  308. slapi_sdn_set_dn_byval ( &gerop->o_sdn, subjectndn );
  309. geraclpb = acl_get_ext ( ACL_EXT_OPERATION, (void *)gerop);
  310. acl_init_aclpb ( *gerpb, geraclpb, subjectndn, 0 );
  311. geraclpb->aclpb_res_type |= ACLPB_EFFECTIVE_RIGHTS;
  312. }
  313. bailout:
  314. if ( rc != LDAP_SUCCESS )
  315. {
  316. _ger_release_gerpb ( gerpb, aclcb, pb );
  317. }
  318. return rc;
  319. }
  320. /*
  321. * Callers should have already allocated *gerstr to hold at least
  322. * "entryLevelRights: adnvxxx\n".
  323. */
  324. unsigned long
  325. _ger_get_entry_rights (
  326. Slapi_PBlock *gerpb,
  327. Slapi_Entry *e,
  328. const char *subjectndn,
  329. char **gerstr,
  330. size_t *gerstrsize,
  331. size_t *gerstrcap,
  332. char **errbuf
  333. )
  334. {
  335. unsigned long entryrights = 0;
  336. Slapi_RDN *rdn = NULL;
  337. char *rdntype = NULL;
  338. char *rdnvalue = NULL;
  339. _append_gerstr(gerstr, gerstrsize, gerstrcap, "entryLevelRights: ", NULL);
  340. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  341. "_ger_get_entry_rights: SLAPI_ACL_READ\n" );
  342. if (acl_access_allowed(gerpb, e, "*", NULL, SLAPI_ACL_READ) == LDAP_SUCCESS)
  343. {
  344. /* v - view e */
  345. entryrights |= SLAPI_ACL_READ;
  346. _append_gerstr(gerstr, gerstrsize, gerstrcap, "v", NULL);
  347. }
  348. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  349. "_ger_get_entry_rights: SLAPI_ACL_ADD\n" );
  350. if (acl_access_allowed(gerpb, e, NULL, NULL, SLAPI_ACL_ADD) == LDAP_SUCCESS)
  351. {
  352. /* a - add child entry below e */
  353. entryrights |= SLAPI_ACL_ADD;
  354. _append_gerstr(gerstr, gerstrsize, gerstrcap, "a", NULL);
  355. }
  356. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  357. "_ger_get_entry_rights: SLAPI_ACL_DELETE\n" );
  358. if (acl_access_allowed(gerpb, e, NULL, NULL, SLAPI_ACL_DELETE) == LDAP_SUCCESS)
  359. {
  360. /* d - delete e */
  361. entryrights |= SLAPI_ACL_DELETE;
  362. _append_gerstr(gerstr, gerstrsize, gerstrcap, "d", NULL);
  363. }
  364. /*
  365. * Some limitation/simplification applied here:
  366. * - The modrdn right requires the rights to delete the old rdn and
  367. * the new one. However we have no knowledge of what the new rdn
  368. * is going to be.
  369. * - In multi-valued RDN case, we check the right on
  370. * the first rdn type only for now.
  371. */
  372. rdn = slapi_rdn_new_dn ( slapi_entry_get_ndn (e) );
  373. slapi_rdn_get_first(rdn, &rdntype, &rdnvalue);
  374. if ( NULL != rdntype ) {
  375. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  376. "_ger_get_entry_rights: SLAPI_ACL_WRITE_DEL & _ADD %s\n", rdntype );
  377. if (acl_access_allowed(gerpb, e, rdntype, NULL,
  378. ACLPB_SLAPI_ACL_WRITE_DEL) == LDAP_SUCCESS &&
  379. acl_access_allowed(gerpb, e, rdntype, NULL,
  380. ACLPB_SLAPI_ACL_WRITE_ADD) == LDAP_SUCCESS)
  381. {
  382. /* n - rename e */
  383. entryrights |= SLAPI_ACL_WRITE;
  384. _append_gerstr(gerstr, gerstrsize, gerstrcap, "n", NULL);
  385. }
  386. }
  387. slapi_rdn_free ( &rdn );
  388. if ( entryrights == 0 )
  389. {
  390. _append_gerstr(gerstr, gerstrsize, gerstrcap, "none", NULL);
  391. }
  392. _append_gerstr(gerstr, gerstrsize, gerstrcap, "\n", NULL);
  393. return entryrights;
  394. }
  395. /*
  396. * *gerstr should point to a heap buffer since it may need
  397. * to expand dynamically.
  398. */
  399. unsigned long
  400. _ger_get_attr_rights (
  401. Slapi_PBlock *gerpb,
  402. Slapi_Entry *e,
  403. const char *subjectndn,
  404. char *type,
  405. char **gerstr,
  406. size_t *gerstrsize,
  407. size_t *gerstrcap,
  408. int isfirstattr,
  409. char **errbuf
  410. )
  411. {
  412. unsigned long attrrights = 0;
  413. if (!isfirstattr)
  414. {
  415. _append_gerstr(gerstr, gerstrsize, gerstrcap, ", ", NULL);
  416. }
  417. _append_gerstr(gerstr, gerstrsize, gerstrcap, type, ":");
  418. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  419. "_ger_get_attr_rights: SLAPI_ACL_READ %s\n", type );
  420. if (acl_access_allowed(gerpb, e, type, NULL, SLAPI_ACL_READ) == LDAP_SUCCESS)
  421. {
  422. /* r - read the values of type */
  423. attrrights |= SLAPI_ACL_READ;
  424. _append_gerstr(gerstr, gerstrsize, gerstrcap, "r", NULL);
  425. }
  426. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  427. "_ger_get_attr_rights: SLAPI_ACL_SEARCH %s\n", type );
  428. if (acl_access_allowed(gerpb, e, type, NULL, SLAPI_ACL_SEARCH) == LDAP_SUCCESS)
  429. {
  430. /* s - search the values of type */
  431. attrrights |= SLAPI_ACL_SEARCH;
  432. _append_gerstr(gerstr, gerstrsize, gerstrcap, "s", NULL);
  433. }
  434. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  435. "_ger_get_attr_rights: SLAPI_ACL_COMPARE %s\n", type );
  436. if (acl_access_allowed(gerpb, e, type, NULL, SLAPI_ACL_COMPARE) == LDAP_SUCCESS)
  437. {
  438. /* c - compare the values of type */
  439. attrrights |= SLAPI_ACL_COMPARE;
  440. _append_gerstr(gerstr, gerstrsize, gerstrcap, "c", NULL);
  441. }
  442. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  443. "_ger_get_attr_rights: SLAPI_ACL_WRITE_ADD %s\n", type );
  444. if (acl_access_allowed(gerpb, e, type, NULL, ACLPB_SLAPI_ACL_WRITE_ADD) == LDAP_SUCCESS)
  445. {
  446. /* w - add the values of type */
  447. attrrights |= ACLPB_SLAPI_ACL_WRITE_ADD;
  448. _append_gerstr(gerstr, gerstrsize, gerstrcap, "w", NULL);
  449. }
  450. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  451. "_ger_get_attr_rights: SLAPI_ACL_WRITE_DEL %s\n", type );
  452. if (acl_access_allowed(gerpb, e, type, NULL, ACLPB_SLAPI_ACL_WRITE_DEL) == LDAP_SUCCESS)
  453. {
  454. /* o - delete the values of type */
  455. attrrights |= ACLPB_SLAPI_ACL_WRITE_DEL;
  456. _append_gerstr(gerstr, gerstrsize, gerstrcap, "o", NULL);
  457. }
  458. /* If subjectdn has no general write right, check for self write */
  459. if ( 0 == (attrrights & (ACLPB_SLAPI_ACL_WRITE_DEL | ACLPB_SLAPI_ACL_WRITE_ADD)) )
  460. {
  461. struct berval val;
  462. val.bv_val = (char *)subjectndn;
  463. val.bv_len = strlen (subjectndn);
  464. if (acl_access_allowed(gerpb, e, type, &val, ACLPB_SLAPI_ACL_WRITE_ADD) == LDAP_SUCCESS)
  465. {
  466. /* W - add self to the attribute */
  467. attrrights |= ACLPB_SLAPI_ACL_WRITE_ADD;
  468. _append_gerstr(gerstr, gerstrsize, gerstrcap, "W", NULL);
  469. }
  470. if (acl_access_allowed(gerpb, e, type, &val, ACLPB_SLAPI_ACL_WRITE_DEL) == LDAP_SUCCESS)
  471. {
  472. /* O - delete self from the attribute */
  473. attrrights |= ACLPB_SLAPI_ACL_WRITE_DEL;
  474. _append_gerstr(gerstr, gerstrsize, gerstrcap, "O", NULL);
  475. }
  476. }
  477. if ( attrrights == 0 )
  478. {
  479. _append_gerstr(gerstr, gerstrsize, gerstrcap, "none", NULL);
  480. }
  481. return attrrights;
  482. }
  483. void
  484. _ger_get_attrs_rights (
  485. Slapi_PBlock *gerpb,
  486. Slapi_Entry *e,
  487. const char *subjectndn,
  488. char **attrs,
  489. char **gerstr,
  490. size_t *gerstrsize,
  491. size_t *gerstrcap,
  492. char **errbuf
  493. )
  494. {
  495. int isfirstattr = 1;
  496. /* gerstr was initially allocated with enough space for one more line */
  497. _append_gerstr(gerstr, gerstrsize, gerstrcap, "attributeLevelRights: ", NULL);
  498. if (attrs && *attrs)
  499. {
  500. int i;
  501. for ( i = 0; attrs[i]; i++ )
  502. {
  503. _ger_get_attr_rights ( gerpb, e, subjectndn, attrs[i], gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf );
  504. isfirstattr = 0;
  505. }
  506. }
  507. else
  508. {
  509. Slapi_Attr *prevattr = NULL, *attr;
  510. char *type;
  511. while ( slapi_entry_next_attr ( e, prevattr, &attr ) == 0 )
  512. {
  513. if ( ! slapi_attr_flag_is_set (attr, SLAPI_ATTR_FLAG_OPATTR) )
  514. {
  515. slapi_attr_get_type ( attr, &type );
  516. _ger_get_attr_rights ( gerpb, e, subjectndn, type, gerstr, gerstrsize, gerstrcap, isfirstattr, errbuf );
  517. isfirstattr = 0;
  518. }
  519. prevattr = attr;
  520. }
  521. }
  522. if ( isfirstattr )
  523. {
  524. /* not a single attribute was retrived or specified */
  525. _append_gerstr(gerstr, gerstrsize, gerstrcap, "*:none", NULL);
  526. }
  527. return;
  528. }
  529. /*
  530. * controlType = LDAP_CONTROL_GET_EFFECTIVE_RIGHTS;
  531. * criticality = n/a;
  532. * controlValue = OCTET STRING of BER encoding of the SEQUENCE of
  533. * ENUMERATED LDAP code
  534. */
  535. void
  536. _ger_set_response_control (
  537. Slapi_PBlock *pb,
  538. int iscritical,
  539. int rc
  540. )
  541. {
  542. LDAPControl **resultctrls = NULL;
  543. LDAPControl gerrespctrl;
  544. BerElement *ber = NULL;
  545. struct berval *berval = NULL;
  546. int found = 0;
  547. int i;
  548. if ( (ber = der_alloc ()) == NULL )
  549. {
  550. goto bailout;
  551. }
  552. /* begin sequence, enumeration, end sequence */
  553. ber_printf ( ber, "{e}", rc );
  554. if ( ber_flatten ( ber, &berval ) != LDAP_SUCCESS )
  555. {
  556. goto bailout;
  557. }
  558. gerrespctrl.ldctl_oid = LDAP_CONTROL_GET_EFFECTIVE_RIGHTS;
  559. gerrespctrl.ldctl_iscritical = iscritical;
  560. gerrespctrl.ldctl_value.bv_val = berval->bv_val;
  561. gerrespctrl.ldctl_value.bv_len = berval->bv_len;
  562. slapi_pblock_get ( pb, SLAPI_RESCONTROLS, &resultctrls );
  563. for (i = 0; resultctrls && resultctrls[i]; i++)
  564. {
  565. if (strcmp(resultctrls[i]->ldctl_oid, LDAP_CONTROL_GET_EFFECTIVE_RIGHTS) == 0)
  566. {
  567. /*
  568. * We get here if search returns more than one entry
  569. * and this is not the first entry.
  570. */
  571. ldap_control_free ( resultctrls[i] );
  572. resultctrls[i] = slapi_dup_control (&gerrespctrl);
  573. found = 1;
  574. break;
  575. }
  576. }
  577. if ( !found )
  578. {
  579. /* slapi_pblock_set() will dup the control */
  580. slapi_pblock_set ( pb, SLAPI_ADD_RESCONTROL, &gerrespctrl );
  581. }
  582. bailout:
  583. ber_free ( ber, 1 ); /* ber_free() checks for NULL param */
  584. ber_bvfree ( berval ); /* ber_bvfree() checks for NULL param */
  585. }
  586. int
  587. acl_get_effective_rights (
  588. Slapi_PBlock *pb,
  589. Slapi_Entry *e, /* target entry */
  590. char **attrs, /* Attribute of the entry */
  591. struct berval *val, /* value of attr. NOT USED */
  592. int access, /* requested access rights */
  593. char **errbuf
  594. )
  595. {
  596. Slapi_PBlock *gerpb = NULL;
  597. void *aclcb = NULL;
  598. char *subjectndn = NULL;
  599. char *gerstr = NULL;
  600. size_t gerstrsize = 0;
  601. size_t gerstrcap = 0;
  602. unsigned long entryrights;
  603. int iscritical = 1;
  604. int rc;
  605. *errbuf = '\0';
  606. /*
  607. * Get the subject
  608. */
  609. rc = _ger_parse_control (pb, &subjectndn, &iscritical, errbuf );
  610. if ( rc != LDAP_SUCCESS )
  611. {
  612. goto bailout;
  613. }
  614. /*
  615. * The requestor should have g permission on the entry
  616. * to get the effective rights.
  617. */
  618. rc = _ger_g_permission_granted (pb, e, errbuf);
  619. if ( rc != LDAP_SUCCESS )
  620. {
  621. goto bailout;
  622. }
  623. /*
  624. * Construct a new pb
  625. */
  626. rc = _ger_new_gerpb ( pb, e, subjectndn, &gerpb, &aclcb, errbuf );
  627. if ( rc != LDAP_SUCCESS )
  628. {
  629. goto bailout;
  630. }
  631. /* Get entry level effective rights */
  632. entryrights = _ger_get_entry_rights ( gerpb, e, subjectndn, &gerstr, &gerstrsize, &gerstrcap, errbuf );
  633. /*
  634. * Attribute level effective rights may not be NULL
  635. * even if entry level's is.
  636. */
  637. _ger_get_attrs_rights ( gerpb, e, subjectndn, attrs, &gerstr, &gerstrsize, &gerstrcap, errbuf );
  638. bailout:
  639. /*
  640. * Now construct the response control
  641. */
  642. _ger_set_response_control ( pb, iscritical, rc );
  643. if ( rc != LDAP_SUCCESS )
  644. {
  645. gerstr = slapi_ch_smprintf("entryLevelRights: %d\nattributeLevelRights: *:%d", rc, rc );
  646. }
  647. slapi_log_error (SLAPI_LOG_ACLSUMMARY, plugin_name,
  648. "###### Effective Rights on Entry (%s) for Subject (%s) ######\n",
  649. slapi_entry_get_ndn (e), subjectndn);
  650. slapi_log_error (SLAPI_LOG_ACLSUMMARY, plugin_name, "%s\n", gerstr);
  651. /* Restore pb */
  652. _ger_release_gerpb ( &gerpb, &aclcb, pb );
  653. /*
  654. * General plugin uses SLAPI_RESULT_TEXT for error text. Here
  655. * SLAPI_PB_RESULT_TEXT is exclusively shared with add, dse and schema.
  656. * slapi_pblock_set() will free any previous data, and
  657. * pblock_done() will free SLAPI_PB_RESULT_TEXT.
  658. */
  659. slapi_pblock_set (pb, SLAPI_PB_RESULT_TEXT, gerstr);
  660. if ( !iscritical )
  661. {
  662. /*
  663. * If return code is not LDAP_SUCCESS, the server would
  664. * abort sending the data of the entry to the client.
  665. */
  666. rc = LDAP_SUCCESS;
  667. }
  668. slapi_ch_free ( (void **) &subjectndn );
  669. slapi_ch_free ( (void **) &gerstr );
  670. return rc;
  671. }