aclanom.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. #include "acl.h"
  42. /************************************************************************
  43. Anonymous profile
  44. **************************************************************************/
  45. struct anom_targetacl {
  46. int anom_type; /* defines for anom types same as aci_type */
  47. int anom_access;
  48. Slapi_DN *anom_target; /* target of the ACL */
  49. Slapi_Filter *anom_filter; /* targetfilter part */
  50. char **anom_targetAttrs; /* list of attrs */
  51. };
  52. struct anom_profile {
  53. short anom_signature;
  54. short anom_numacls;
  55. struct anom_targetacl anom_targetinfo[ACL_ANOM_MAX_ACL];
  56. };
  57. static struct anom_profile *acl_anom_profile = NULL;
  58. static Slapi_RWLock *anom_rwlock = NULL;
  59. #define ANOM_LOCK_READ() slapi_rwlock_rdlock (anom_rwlock )
  60. #define ANOM_UNLOCK_READ() slapi_rwlock_unlock (anom_rwlock )
  61. #define ANOM_LOCK_WRITE() slapi_rwlock_wrlock (anom_rwlock )
  62. #define ANOM_UNLOCK_WRITE() slapi_rwlock_unlock (anom_rwlock )
  63. /*
  64. * aclanom_init ();
  65. * Generate a profile for the anonymous user. We can use this profile
  66. * later to determine what resources the client is allowed to.
  67. *
  68. * Dependency:
  69. * Before calling this, it is assumed that all the ACLs have been read
  70. * and parsed.
  71. *
  72. * We will go thru all the ACL and pick the ANYONE ACL and generate the anom
  73. * profile.
  74. *
  75. */
  76. int
  77. aclanom_init ()
  78. {
  79. acl_anom_profile = (struct anom_profile * )
  80. slapi_ch_calloc (1, sizeof ( struct anom_profile ) );
  81. if (( anom_rwlock = slapi_new_rwlock()) == NULL ) {
  82. slapi_log_error( SLAPI_LOG_FATAL, plugin_name,
  83. "Failed in getting the ANOM rwlock\n" );
  84. return 1;
  85. }
  86. return 0;
  87. }
  88. /*
  89. * Depending on the context, this routine may need to take the
  90. * acicache read lock.
  91. */
  92. void
  93. aclanom_gen_anomProfile (acl_lock_flag_t lock_flag)
  94. {
  95. aci_t *aci = NULL;
  96. int i;
  97. Targetattr **srcattrArray;
  98. Targetattr *attr;
  99. struct anom_profile *a_profile;
  100. PRUint32 cookie;
  101. PR_ASSERT( lock_flag == DO_TAKE_ACLCACHE_READLOCK ||
  102. lock_flag == DONT_TAKE_ACLCACHE_READLOCK);
  103. /*
  104. * This routine requires two locks:
  105. * the one for the global cache in acllist_acicache_READ_LOCK() and
  106. * the one for the anom profile.
  107. * They _must_ be taken in the order presented here or there
  108. * is a deadlock scenario with acllist_remove_aci_needsLock() which
  109. * takes them is this order.
  110. */
  111. if ( lock_flag == DO_TAKE_ACLCACHE_READLOCK ) {
  112. acllist_acicache_READ_LOCK();
  113. }
  114. ANOM_LOCK_WRITE ();
  115. a_profile = acl_anom_profile;
  116. if ( (!acl_get_aclsignature()) || ( !a_profile) ||
  117. (a_profile->anom_signature == acl_get_aclsignature()) ) {
  118. ANOM_UNLOCK_WRITE ();
  119. if ( lock_flag == DO_TAKE_ACLCACHE_READLOCK ) {
  120. acllist_acicache_READ_UNLOCK();
  121. }
  122. return;
  123. }
  124. /* D0 we have one already. If we do, then clean it up */
  125. aclanom__del_profile(0);
  126. /* We have a new signature now */
  127. a_profile->anom_signature = acl_get_aclsignature();
  128. slapi_log_error(SLAPI_LOG_ACL, plugin_name, "GENERATING ANOM USER PROFILE\n");
  129. /*
  130. ** Go thru the ACL list and find all the ACLs which apply to the
  131. ** anonymous user i.e anyone. we can generate a profile for that.
  132. ** We will llok at the simple case i.e it matches
  133. ** cases not handled:
  134. ** 1) When there is a mix if rule types ( allows & denies )
  135. **
  136. */
  137. aci = acllist_get_first_aci ( NULL, &cookie );
  138. while ( aci ) {
  139. int a_numacl;
  140. struct slapi_filter *f;
  141. char **destattrArray;
  142. /*
  143. * We must not have a rule like: deny ( all ) userdn != "xyz"
  144. * or groupdn !=
  145. */
  146. if ( (aci->aci_type & ACI_HAS_DENY_RULE) &&
  147. ( (aci->aci_type & ACI_CONTAIN_NOT_USERDN ) ||
  148. (aci->aci_type & ACI_CONTAIN_NOT_GROUPDN) ||
  149. (aci->aci_type & ACI_CONTAIN_NOT_ROLEDN)) ){
  150. slapi_log_error(SLAPI_LOG_ACL, plugin_name,
  151. "CANCELLING ANOM USER PROFILE BECAUSE OF DENY RULE\n");
  152. goto cleanup;
  153. }
  154. /* Must be a anyone rule */
  155. if ( aci->aci_elevel != ACI_ELEVEL_USERDN_ANYONE ) {
  156. aci = acllist_get_next_aci ( NULL, aci, &cookie);
  157. continue;
  158. }
  159. if (! (aci->aci_access & ( SLAPI_ACL_READ | SLAPI_ACL_SEARCH)) ) {
  160. aci = acllist_get_next_aci ( NULL, aci, &cookie);
  161. continue;
  162. }
  163. /* If the rule has anything other than userdn = "ldap:///anyone"
  164. ** let's not consider complex rules - let's make this lean.
  165. */
  166. if ( aci->aci_ruleType & ~ACI_USERDN_RULE ){
  167. slapi_log_error(SLAPI_LOG_ACL, plugin_name,
  168. "CANCELLING ANOM USER PROFILE BECAUSE OF COMPLEX RULE\n");
  169. goto cleanup;
  170. }
  171. /* Must not be a or have a
  172. ** 1 ) DENY RULE 2) targetfilter
  173. ** 3) no target pattern ( skip monitor acl )
  174. */
  175. if ( aci->aci_type & ( ACI_HAS_DENY_RULE | ACI_TARGET_PATTERN |
  176. ACI_TARGET_NOT | ACI_TARGET_FILTER_NOT )) {
  177. const char *dn = slapi_sdn_get_dn ( aci->aci_sdn );
  178. /* see if this is a monitor acl */
  179. if (( strcasecmp ( dn, "cn=monitor") == 0 ) ||
  180. /* cn=monitor,cn=ldbm: No such object */
  181. ( strcasecmp ( dn, "cn=monitor,cn=ldbm") == 0 )) {
  182. aci = acllist_get_next_aci ( NULL, aci, &cookie);
  183. continue;
  184. } else {
  185. /* clean up before leaving */
  186. slapi_log_error(SLAPI_LOG_ACL, plugin_name,
  187. "CANCELLING ANOM USER PROFILE 1\n");
  188. goto cleanup;
  189. }
  190. }
  191. /* Now we have an ALLOW ACL which applies to anyone */
  192. a_numacl = a_profile->anom_numacls++;
  193. if ( a_profile->anom_numacls == ACL_ANOM_MAX_ACL ) {
  194. slapi_log_error(SLAPI_LOG_ACL, plugin_name, "CANCELLING ANOM USER PROFILE 2\n");
  195. goto cleanup;
  196. }
  197. if ( (f = aci->target) != NULL ) {
  198. char *avaType;
  199. struct berval *avaValue;
  200. slapi_filter_get_ava ( f, &avaType, &avaValue );
  201. a_profile->anom_targetinfo[a_numacl].anom_target =
  202. slapi_sdn_new_dn_byval ( avaValue->bv_val );
  203. } else {
  204. a_profile->anom_targetinfo[a_numacl].anom_target =
  205. slapi_sdn_dup ( aci->aci_sdn );
  206. }
  207. a_profile->anom_targetinfo[a_numacl].anom_filter = NULL;
  208. if ( aci->targetFilterStr ) {
  209. a_profile->anom_targetinfo[a_numacl].anom_filter = slapi_str2filter ( aci->targetFilterStr );
  210. if (NULL == a_profile->anom_targetinfo[a_numacl].anom_filter) {
  211. const char *dn = slapi_sdn_get_dn ( aci->aci_sdn );
  212. slapi_log_error(SLAPI_LOG_FATAL, plugin_name,
  213. "Error: invalid filter [%s] in anonymous aci in entry [%s]\n",
  214. aci->targetFilterStr, dn);
  215. goto cleanup;
  216. }
  217. }
  218. i = 0;
  219. srcattrArray = aci->targetAttr;
  220. while ( srcattrArray[i])
  221. i++;
  222. a_profile->anom_targetinfo[a_numacl].anom_targetAttrs =
  223. (char **) slapi_ch_calloc ( 1, (i+1) * sizeof(char *));
  224. srcattrArray = aci->targetAttr;
  225. destattrArray = a_profile->anom_targetinfo[a_numacl].anom_targetAttrs;
  226. i = 0;
  227. while ( srcattrArray[i] ) {
  228. attr = srcattrArray[i];
  229. if ( attr->attr_type & ACL_ATTR_FILTER ) {
  230. /* Do'nt want to support these kind now */
  231. destattrArray[i] = NULL;
  232. /* clean up before leaving */
  233. aclanom__del_profile (0);
  234. slapi_log_error(SLAPI_LOG_ACL, plugin_name,
  235. "CANCELLING ANOM USER PROFILE 3\n");
  236. goto cleanup;
  237. }
  238. destattrArray[i] = slapi_ch_strdup ( attr->u.attr_str );
  239. i++;
  240. }
  241. destattrArray[i] = NULL;
  242. aclutil_print_aci ( aci, "anom" );
  243. /* Here we are storing att the info from the acls. However
  244. ** we are only interested in a few things like ACI_TARGETATTR_NOT.
  245. */
  246. a_profile->anom_targetinfo[a_numacl].anom_type = aci->aci_type;
  247. a_profile->anom_targetinfo[a_numacl].anom_access = aci->aci_access;
  248. aci = acllist_get_next_aci ( NULL, aci, &cookie);
  249. }
  250. ANOM_UNLOCK_WRITE ();
  251. if ( lock_flag == DO_TAKE_ACLCACHE_READLOCK ) {
  252. acllist_acicache_READ_UNLOCK();
  253. }
  254. return;
  255. cleanup:
  256. aclanom__del_profile (0);
  257. ANOM_UNLOCK_WRITE ();
  258. if ( lock_flag == DO_TAKE_ACLCACHE_READLOCK ) {
  259. acllist_acicache_READ_UNLOCK();
  260. }
  261. }
  262. void
  263. aclanom_invalidateProfile ()
  264. {
  265. ANOM_LOCK_WRITE();
  266. if ( acl_anom_profile && acl_anom_profile->anom_numacls )
  267. acl_anom_profile->anom_signature = 0;
  268. ANOM_UNLOCK_WRITE();
  269. }
  270. /*
  271. * __aclanom_del_profile
  272. *
  273. * Cleanup the anonymous user's profile we have.
  274. *
  275. * ASSUMPTION: A WRITE LOCK HAS BEEN OBTAINED
  276. *
  277. */
  278. void
  279. aclanom__del_profile (int closing)
  280. {
  281. int i;
  282. struct anom_profile *a_profile;
  283. if ( (a_profile = acl_anom_profile) == NULL ) {
  284. return;
  285. }
  286. for ( i=0; i < a_profile->anom_numacls; i++ ) {
  287. int j = 0;
  288. char **destArray = a_profile->anom_targetinfo[i].anom_targetAttrs;
  289. /* Deallocate target */
  290. slapi_sdn_free ( &a_profile->anom_targetinfo[i].anom_target );
  291. /* Deallocate filter */
  292. if ( a_profile->anom_targetinfo[i].anom_filter )
  293. slapi_filter_free ( a_profile->anom_targetinfo[i].anom_filter, 1 );
  294. /* Deallocate attrs */
  295. if ( destArray ) {
  296. while ( destArray[j] ) {
  297. slapi_ch_free ( (void **) &destArray[j] );
  298. j++;
  299. }
  300. slapi_ch_free ( (void **) &destArray );
  301. }
  302. a_profile->anom_targetinfo[i].anom_targetAttrs = NULL;
  303. a_profile->anom_targetinfo[i].anom_type = 0;
  304. a_profile->anom_targetinfo[i].anom_access = 0;
  305. }
  306. a_profile->anom_numacls = 0;
  307. if(closing){
  308. slapi_destroy_rwlock(anom_rwlock);
  309. anom_rwlock = NULL;
  310. slapi_ch_free((void **)&acl_anom_profile);
  311. }
  312. /* Don't clean the signatue */
  313. }
  314. /*
  315. * This routine sets up a "context" for evaluation of access control
  316. * on a given entry for an anonymous user.
  317. * It just factors out the scope and targetfilter info into a list
  318. * of indices of the global anom profile list, that apply to this
  319. * entry, and stores them in the aclpb.
  320. * It's use relies on the way that access control is checked in the mailine search
  321. * code in the core server, namely: check filter, check entry, then check each
  322. * attribute. So, we call this in acl_access_allowed() before calling
  323. * aclanom_match_profile()--therafter, aclanom_match_profile() uses the
  324. * context to evaluate access to the entry and attributes.
  325. *
  326. * If there are no anom profiles, or the anom profiles get cancelled
  327. * due to complex anon acis, then that's OK, aclanom_match_profile()
  328. * returns -1 and the mainline acl code kicks in.
  329. *
  330. * The lifetime of this context info is the time it takes to check
  331. * access control for all parts of this entry (filter, entry, attributes).
  332. * So, if for an example an entry changes and a given anom profile entry
  333. * no longer applies, we will not notice until the next round of access
  334. * control checking on the entry--this is acceptable.
  335. *
  336. * The gain on doing this factoring in the following type of search
  337. * was approx 6%:
  338. * anon bind, 20 threads, exact match, ~20 attributes returned,
  339. * (searchrate & DirectoryMark).
  340. *
  341. */
  342. void
  343. aclanom_get_suffix_info(Slapi_Entry *e,
  344. struct acl_pblock *aclpb ) {
  345. int i;
  346. char *ndn = NULL;
  347. Slapi_DN *e_sdn;
  348. const char *aci_ndn;
  349. struct scoped_entry_anominfo *s_e_anominfo =
  350. &aclpb->aclpb_scoped_entry_anominfo;
  351. ANOM_LOCK_READ ();
  352. s_e_anominfo->anom_e_nummatched=0;
  353. ndn = slapi_entry_get_ndn ( e ) ;
  354. e_sdn= slapi_entry_get_sdn ( e ) ;
  355. for (i=acl_anom_profile->anom_numacls-1; i >= 0; i-- ) {
  356. aci_ndn = slapi_sdn_get_ndn (acl_anom_profile->anom_targetinfo[i].anom_target);
  357. if (!slapi_sdn_issuffix(e_sdn,acl_anom_profile->anom_targetinfo[i].anom_target)
  358. || (!slapi_is_rootdse(ndn) && slapi_is_rootdse(aci_ndn)))
  359. continue;
  360. if ( acl_anom_profile->anom_targetinfo[i].anom_filter ) {
  361. if ( slapi_vattr_filter_test( aclpb->aclpb_pblock, e,
  362. acl_anom_profile->anom_targetinfo[i].anom_filter,
  363. 0 /*don't do acess chk*/) != 0)
  364. continue;
  365. }
  366. s_e_anominfo->anom_e_targetInfo[s_e_anominfo->anom_e_nummatched]=i;
  367. s_e_anominfo->anom_e_nummatched++;
  368. }
  369. ANOM_UNLOCK_READ ();
  370. }
  371. /*
  372. * aclanom_match_profile
  373. * Look at the anonymous profile and see if we can use it or not.
  374. *
  375. *
  376. * Inputs:
  377. * Slapi_Pblock - The Pblock
  378. * Slapi_Entry *e - The entry for which we are asking permission.
  379. * char *attr - Attribute name
  380. * int access - access type
  381. *
  382. * Return:
  383. * LDAP_SUCCESS ( 0 ) - acess is allowed.
  384. * LDAP_INSUFFICIENT_ACCESS (50 ) - access denied.
  385. * -1 - didn't match the targets
  386. *
  387. * Assumptions:
  388. * The caller of this module has to make sure that the client is
  389. * an anonymous client.
  390. */
  391. int
  392. aclanom_match_profile (Slapi_PBlock *pb, struct acl_pblock *aclpb, Slapi_Entry *e,
  393. char *attr, int access )
  394. {
  395. struct anom_profile *a_profile;
  396. int result, i, k;
  397. char **destArray;
  398. int tmatched = 0;
  399. int loglevel;
  400. struct scoped_entry_anominfo *s_e_anominfo =
  401. &aclpb->aclpb_scoped_entry_anominfo;
  402. loglevel = slapi_is_loglevel_set(SLAPI_LOG_ACL) ? SLAPI_LOG_ACL : SLAPI_LOG_ACLSUMMARY;
  403. /* WE are only interested for READ/SEARCH */
  404. if ( !(access & ( SLAPI_ACL_SEARCH | SLAPI_ACL_READ)) )
  405. return -1;
  406. /* If we are here means, the client is doing a anonymous read/search */
  407. if ((a_profile = acl_anom_profile) == NULL ) {
  408. return -1;
  409. }
  410. ANOM_LOCK_READ ();
  411. /* Check the signature first */
  412. if ( a_profile->anom_signature != acl_get_aclsignature () ) {
  413. /* Need to regenrate the signature.
  414. * Need a WRITE lock to generate the anom profile -
  415. * which is obtained in acl__gen_anom_user_profile (). Since
  416. * I don't have upgrade lock -- I have to do this way.
  417. */
  418. ANOM_UNLOCK_READ ();
  419. aclanom_gen_anomProfile (DO_TAKE_ACLCACHE_READLOCK);
  420. aclanom_get_suffix_info(e, aclpb );
  421. ANOM_LOCK_READ ();
  422. }
  423. /* doing this early saves use a malloc/free/normalize cost */
  424. if ( !a_profile->anom_numacls ) {
  425. ANOM_UNLOCK_READ ();
  426. return -1;
  427. }
  428. result = LDAP_INSUFFICIENT_ACCESS;
  429. for ( k=0; k<s_e_anominfo->anom_e_nummatched; k++ ) {
  430. short matched = 0;
  431. short j = 0;
  432. i = s_e_anominfo->anom_e_targetInfo[k];
  433. /* Check for right */
  434. if ( !(a_profile->anom_targetinfo[i].anom_access & access) )
  435. continue;
  436. /*
  437. * XXX rbyrne Don't really understand the role of this
  438. * but not causing any obvious bugs...get back to it.
  439. */
  440. tmatched++;
  441. if ( attr == NULL ) {
  442. result = LDAP_SUCCESS;
  443. break;
  444. }
  445. destArray = a_profile->anom_targetinfo[i].anom_targetAttrs;
  446. while ( destArray[j] ) {
  447. if ( strcasecmp ( destArray[j], "*") == 0 ||
  448. slapi_attr_type_cmp ( attr, destArray[j], 1 ) == 0 ) {
  449. matched = 1;
  450. break;
  451. }
  452. j++;
  453. }
  454. if ( a_profile->anom_targetinfo[i].anom_type & ACI_TARGET_ATTR_NOT )
  455. result = matched ? LDAP_INSUFFICIENT_ACCESS : LDAP_SUCCESS;
  456. else
  457. result = matched ? LDAP_SUCCESS : LDAP_INSUFFICIENT_ACCESS;
  458. if ( result == LDAP_SUCCESS )
  459. break;
  460. } /* for */
  461. if ( slapi_is_loglevel_set(loglevel) ) {
  462. char *ndn = NULL;
  463. Slapi_Operation *op = NULL;
  464. PRUint64 o_connid = 0xffffffffffffffff; /* no op */
  465. int o_opid = -1; /* no op */
  466. ndn = slapi_entry_get_ndn ( e ) ;
  467. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  468. if (op) {
  469. o_connid = op->o_connid;
  470. o_opid = op->o_opid;
  471. }
  472. if ( result == LDAP_SUCCESS) {
  473. const char *aci_ndn;
  474. aci_ndn = slapi_sdn_get_ndn (acl_anom_profile->anom_targetinfo[i].anom_target);
  475. if (access & SLAPI_ACL_MODDN) {
  476. slapi_log_error(loglevel, plugin_name,
  477. "conn=%" NSPRIu64 " op=%d: Allow access on entry(%s).attr(%s) (from %s) to anonymous: acidn=\"%s\"\n",
  478. o_connid, o_opid,
  479. ndn,
  480. attr ? attr:"NULL",
  481. aclpb->aclpb_moddn_source_sdn ? slapi_sdn_get_dn(aclpb->aclpb_moddn_source_sdn) : "NULL",
  482. aci_ndn);
  483. } else {
  484. slapi_log_error(loglevel, plugin_name,
  485. "conn=%" NSPRIu64 " op=%d: Allow access on entry(%s).attr(%s) to anonymous: acidn=\"%s\"\n",
  486. o_connid, o_opid,
  487. ndn,
  488. attr ? attr:"NULL",
  489. aci_ndn);
  490. }
  491. } else {
  492. if (access & SLAPI_ACL_MODDN) {
  493. slapi_log_error(loglevel, plugin_name,
  494. "conn=%" NSPRIu64 " op=%d: Deny access on entry(%s).attr(%s) (from %s) to anonymous\n",
  495. o_connid, o_opid,
  496. ndn, attr ? attr:"NULL" ,
  497. aclpb->aclpb_moddn_source_sdn ? slapi_sdn_get_dn(aclpb->aclpb_moddn_source_sdn) : "NULL");
  498. } else {
  499. slapi_log_error(loglevel, plugin_name,
  500. "conn=%" NSPRIu64 " op=%d: Deny access on entry(%s).attr(%s) to anonymous\n",
  501. o_connid, o_opid,
  502. ndn, attr ? attr:"NULL" );
  503. }
  504. }
  505. }
  506. ANOM_UNLOCK_READ ();
  507. if ( tmatched == 0)
  508. return -1;
  509. else
  510. return result;
  511. }
  512. int
  513. aclanom_is_client_anonymous ( Slapi_PBlock *pb )
  514. {
  515. char *clientDn;
  516. slapi_pblock_get ( pb, SLAPI_REQUESTOR_DN, &clientDn );
  517. if (acl_anom_profile->anom_numacls &&
  518. acl_anom_profile->anom_signature &&
  519. (( NULL == clientDn) || (clientDn && *clientDn == '\0')) )
  520. return 1;
  521. return 0;
  522. }