aclutil.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377
  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. * END COPYRIGHT BLOCK **/
  6. #include "acl.h"
  7. /**************************************************************************
  8. * Defines and usefuls stuff
  9. ****************************************************************************/
  10. /*************************************************************************
  11. * Prototypes
  12. *************************************************************************/
  13. static void aclutil__typestr (int type , char str[]);
  14. static void aclutil__Ruletypestr (int type , char str[]);
  15. static char* __aclutil_extract_dn_component ( char **e_dns, int position,
  16. char *attrName );
  17. static int acl_find_comp_start(char * s, int pos );
  18. static PRIntn acl_ht_free_entry_and_value(PLHashEntry *he, PRIntn i,
  19. void *arg);
  20. static PLHashNumber acl_ht_hash( const void *key);
  21. static PRIntn acl_ht_display_entry(PLHashEntry *he, PRIntn i, void *arg);
  22. /***************************************************************************/
  23. /* UTILITY FUNCTIONS */
  24. /***************************************************************************/
  25. int
  26. aclutil_str_appened(char **str1, const char *str2)
  27. {
  28. int new_len;
  29. if ( str1 == NULL || str2 == NULL )
  30. return(0);
  31. if ( *str1 == NULL ) {
  32. new_len = strlen(str2) + 1;
  33. *str1 = (char *)slapi_ch_malloc(new_len);
  34. *str1[0] = 0;
  35. } else {
  36. new_len = strlen(*str1) + strlen(str2) + 1;
  37. *str1 = (char *)slapi_ch_realloc(*str1, new_len);
  38. }
  39. if ( *str1 == NULL )
  40. return(-1);
  41. strcat(*str1, str2);
  42. return(0);
  43. }
  44. /***************************************************************************/
  45. /* Print routines */
  46. /***************************************************************************/
  47. /* print eroror message returned from the ACL Library */
  48. #define ACLUTIL_ACLLIB_MSGBUF_LEN 200
  49. void
  50. acl_print_acllib_err (NSErr_t *errp , char * str)
  51. {
  52. char msgbuf[ ACLUTIL_ACLLIB_MSGBUF_LEN ];
  53. if ((NULL == errp ) || !slapi_is_loglevel_set ( SLAPI_LOG_ACL ) )
  54. return;
  55. aclErrorFmt(errp, msgbuf, ACLUTIL_ACLLIB_MSGBUF_LEN, 1);
  56. msgbuf[ACLUTIL_ACLLIB_MSGBUF_LEN-1] = '\0';
  57. if (msgbuf)
  58. slapi_log_error(SLAPI_LOG_ACL, plugin_name,"ACL LIB ERR:(%s)(%s)\n",
  59. msgbuf, str ? str: "NULL",0);
  60. }
  61. void
  62. aclutil_print_aci (aci_t *aci_item, char *type)
  63. {
  64. char str[BUFSIZ];
  65. const char *dn;
  66. if ( ! slapi_is_loglevel_set ( SLAPI_LOG_ACL ) )
  67. return;
  68. if (!aci_item) {
  69. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  70. "acl__print_aci: Null item\n",0,0,0);
  71. return;
  72. }
  73. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  74. "***BEGIN ACL INFO[ Name:%s]***\n", aci_item->aclName);
  75. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  76. "ACL Index:%d ACL_ELEVEL:%d\n", aci_item->aci_index, aci_item->aci_elevel );
  77. aclutil__access_str (aci_item->aci_access, str);
  78. aclutil__typestr (aci_item->aci_type, &str[strlen(str)]);
  79. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  80. "ACI type:(%s)\n", str);
  81. aclutil__Ruletypestr (aci_item->aci_ruleType, str);
  82. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  83. "ACI RULE type:(%s)\n",str);
  84. dn = slapi_sdn_get_dn ( aci_item->aci_sdn );
  85. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  86. "Slapi_Entry DN:%s\n", escape_string_with_punctuation (dn, str));
  87. slapi_log_error (SLAPI_LOG_ACL, plugin_name,
  88. "***END ACL INFO*****************************\n");
  89. }
  90. void
  91. aclutil_print_err (int rv , const Slapi_DN *sdn, const struct berval* val,
  92. char **errbuf)
  93. {
  94. char ebuf [BUFSIZ];
  95. /*
  96. * The maximum size of line is ebuf_size + the log message
  97. * itself (less than 200 characters for all but potentially ACL_INVALID_TARGET)
  98. */
  99. char line [BUFSIZ + 200];
  100. char str [1024];
  101. const char *dn;
  102. char *lineptr = line;
  103. char *newline = NULL;
  104. if ( rv >= 0)
  105. return;
  106. if (val->bv_len > 0 && val->bv_val != NULL) {
  107. PR_snprintf (str, sizeof(str), "%.1023s", val->bv_val);
  108. } else {
  109. str[0] = '\0';
  110. }
  111. dn = slapi_sdn_get_dn ( sdn );
  112. if (dn && (rv == ACL_INVALID_TARGET) && ((strlen(dn) + strlen(str)) > BUFSIZ)) {
  113. /*
  114. * if (str_length + dn_length + 200 char message) > (BUFSIZ + 200) line
  115. * we have to make space for a bigger line...
  116. */
  117. newline = slapi_ch_malloc(strlen(dn) + strlen(str) + 200);
  118. lineptr = newline;
  119. }
  120. switch (rv) {
  121. case ACL_TARGET_FILTER_ERR:
  122. sprintf (line, "ACL Internal Error(%d): "
  123. "Error in generating the target filter for the ACL(%s)\n",
  124. rv, escape_string_with_punctuation (str, ebuf));
  125. break;
  126. case ACL_TARGETATTR_FILTER_ERR:
  127. sprintf (line, "ACL Internal Error(%d): "
  128. "Error in generating the targetattr filter for the ACL(%s)\n",
  129. rv, escape_string_with_punctuation (str, ebuf));
  130. break;
  131. case ACL_TARGETFILTER_ERR:
  132. sprintf (line, "ACL Internal Error(%d): "
  133. "Error in generating the targetfilter filter for the ACL(%s)\n",
  134. rv, escape_string_with_punctuation (str, ebuf));
  135. break;
  136. case ACL_SYNTAX_ERR:
  137. sprintf (line, "ACL Syntax Error(%d):%s\n",
  138. rv, escape_string_with_punctuation (str, ebuf));
  139. break;
  140. case ACL_ONEACL_TEXT_ERR:
  141. sprintf (line, "ACL Syntax Error in the Bind Rules(%d):%s\n",
  142. rv, escape_string_with_punctuation (str, ebuf));
  143. break;
  144. case ACL_ERR_CONCAT_HANDLES:
  145. sprintf (line, "ACL Internal Error(%d): "
  146. "Error in Concatenating List handles\n",
  147. rv);
  148. break;
  149. case ACL_INVALID_TARGET:
  150. sprintf (lineptr, "ACL Invalid Target Error(%d): "
  151. "Target is beyond the scope of the ACL(SCOPE:%s)",
  152. rv, dn ? escape_string_with_punctuation (dn, ebuf) : "NULL");
  153. sprintf (lineptr + strlen(lineptr), " %s\n", escape_string_with_punctuation (str, ebuf));
  154. break;
  155. case ACL_INVALID_AUTHMETHOD:
  156. sprintf (line, "ACL Multiple auth method Error(%d):"
  157. "Multiple Authentication Metod in the ACL(%s)\n",
  158. rv, escape_string_with_punctuation (str, ebuf));
  159. break;
  160. case ACL_INVALID_AUTHORIZATION:
  161. sprintf (line, "ACL Syntax Error(%d):"
  162. "Invalid Authorization statement in the ACL(%s)\n",
  163. rv, escape_string_with_punctuation (str, ebuf));
  164. break;
  165. case ACL_INCORRECT_ACI_VERSION:
  166. sprintf (line, "ACL Syntax Error(%d):"
  167. "Incorrect version Number in the ACL(%s)\n",
  168. rv, escape_string_with_punctuation (str, ebuf));
  169. break;
  170. default:
  171. sprintf (line, "ACL Internal Error(%d):"
  172. "ACL generic error (%s)\n",
  173. rv, escape_string_with_punctuation (str, ebuf));
  174. break;
  175. }
  176. if (errbuf) {
  177. /* If a buffer is provided, then copy the error */
  178. aclutil_str_appened(errbuf, lineptr );
  179. }
  180. slapi_log_error( SLAPI_LOG_FATAL, plugin_name, "%s", lineptr);
  181. if (newline) slapi_ch_free((void **) &newline);
  182. }
  183. /***************************************************************************
  184. * Convert access to str
  185. ***************************************************************************/
  186. char*
  187. aclutil__access_str (int type , char str[])
  188. {
  189. char *p;
  190. str[0] = '\0';
  191. p = str;
  192. if (type & SLAPI_ACL_COMPARE) {
  193. strcpy (p, "compare ");
  194. p = strchr (p, '\0');
  195. }
  196. if (type & SLAPI_ACL_SEARCH) {
  197. strcpy (p, "search ");
  198. p = strchr (p, '\0');
  199. }
  200. if (type & SLAPI_ACL_READ) {
  201. strcpy (p, "read ");
  202. p = strchr (p, '\0');
  203. }
  204. if (type & SLAPI_ACL_WRITE) {
  205. strcpy (p, "write ");
  206. p = strchr (p, '\0');
  207. }
  208. if (type & SLAPI_ACL_DELETE) {
  209. strcpy (p, "delete ");
  210. p = strchr (p, '\0');
  211. }
  212. if (type & SLAPI_ACL_ADD) {
  213. strcpy (p, "add ");
  214. p = strchr (p, '\0');
  215. }
  216. if (type & SLAPI_ACL_SELF) {
  217. strcpy (p, "self ");
  218. p = strchr (p, '\0');
  219. }
  220. if (type & SLAPI_ACL_PROXY) {
  221. strcpy (p, "proxy ");
  222. }
  223. return str;
  224. }
  225. /***************************************************************************
  226. * Convert type to str
  227. ***************************************************************************/
  228. static void
  229. aclutil__typestr (int type , char str[])
  230. {
  231. char *p;
  232. /* Start copying in at whatever location is passed in */
  233. p = str;
  234. if (type & ACI_TARGET_DN) {
  235. strcpy (p, "target_DN ");
  236. p = strchr (p, '\0');
  237. }
  238. if (type & ACI_TARGET_ATTR) {
  239. strcpy (p, "target_attr ");
  240. p = strchr (p, '\0');
  241. }
  242. if (type & ACI_TARGET_PATTERN) {
  243. strcpy (p, "target_patt ");
  244. p = strchr (p, '\0');
  245. }
  246. if ((type & ACI_TARGET_ATTR_ADD_FILTERS) | (type & ACI_TARGET_ATTR_DEL_FILTERS)) {
  247. strcpy (p, "targetattrfilters ");
  248. p = strchr (p, '\0');
  249. }
  250. if (type & ACI_TARGET_FILTER) {
  251. strcpy (p, "target_filter ");
  252. p = strchr (p, '\0');
  253. }
  254. if (type & ACI_ACLTXT) {
  255. strcpy (p, "acltxt ");
  256. p = strchr (p, '\0');
  257. }
  258. if (type & ACI_TARGET_NOT) {
  259. strcpy (p, "target_not ");
  260. p = strchr (p, '\0');
  261. }
  262. if (type & ACI_TARGET_ATTR_NOT) {
  263. strcpy (p, "target_attr_not ");
  264. p = strchr (p, '\0');
  265. }
  266. if (type & ACI_TARGET_FILTER_NOT) {
  267. strcpy (p, "target_filter_not ");
  268. p = strchr (p, '\0');
  269. }
  270. if (type & ACI_HAS_ALLOW_RULE) {
  271. strcpy (p, "allow_rule ");
  272. p = strchr (p, '\0');
  273. }
  274. if (type & ACI_HAS_DENY_RULE) {
  275. strcpy (p, "deny_rule ");
  276. p = strchr (p, '\0');
  277. }
  278. }
  279. static void
  280. aclutil__Ruletypestr (int type , char str[])
  281. {
  282. char *p;
  283. str[0] = '\0';
  284. p = str;
  285. if ( type & ACI_USERDN_RULE) {
  286. strcpy (p, "userdn ");
  287. p = strchr (p, '\0');
  288. }
  289. if ( type & ACI_USERDNATTR_RULE) {
  290. strcpy (p, "userdnattr ");
  291. p = strchr (p, '\0');
  292. }
  293. if ( type & ACI_USERATTR_RULE) {
  294. strcpy (p, "userattr ");
  295. p = strchr (p, '\0');
  296. }
  297. if ( type & ACI_GROUPDN_RULE) {
  298. strcpy (p, "groupdn ");
  299. p = strchr (p, '\0');
  300. }
  301. if ( type & ACI_GROUPDNATTR_RULE) {
  302. strcpy (p, "groupdnattr ");
  303. p = strchr (p, '\0');
  304. }
  305. if ( type & ACI_ROLEDN_RULE) {
  306. strcpy (p, "roledn ");
  307. p = strchr (p, '\0');
  308. }
  309. if ( type & ACI_IP_RULE) {
  310. strcpy (p, "ip ");
  311. p = strchr (p, '\0');
  312. }
  313. if ( type & ACI_DNS_RULE) {
  314. strcpy (p, "dns ");
  315. p = strchr (p, '\0');
  316. }
  317. if ( type & ACI_TIMEOFDAY_RULE) {
  318. strcpy (p, "timeofday ");
  319. p = strchr (p, '\0');
  320. }
  321. if ( type & ACI_DAYOFWEEK_RULE) {
  322. strcpy (p, "dayofweek ");
  323. p = strchr (p, '\0');
  324. }
  325. if ( type & ACI_AUTHMETHOD_RULE) {
  326. strcpy (p, "authmethod ");
  327. p = strchr (p, '\0');
  328. }
  329. if ( type & ACI_PARAM_DNRULE) {
  330. strcpy (p, "paramdn ");
  331. p = strchr (p, '\0');
  332. }
  333. if ( type & ACI_PARAM_ATTRRULE) {
  334. strcpy (p, "paramAttr ");
  335. p = strchr (p, '\0');
  336. }
  337. }
  338. /*
  339. ** acl_gen_err_msg
  340. ** This function is called by backend to generate the error message
  341. ** if access is denied.
  342. */
  343. void
  344. acl_gen_err_msg(int access, char *edn, char *attr, char **errbuf)
  345. {
  346. char *line = NULL;
  347. if (access & SLAPI_ACL_WRITE) {
  348. line = PR_smprintf(
  349. "Insufficient 'write' privilege to the '%s' attribute of entry '%s'.\n",
  350. attr ? attr: "NULL", edn);
  351. } else if ( access & SLAPI_ACL_ADD ) {
  352. line = PR_smprintf(
  353. "Insufficient 'add' privilege to add the entry '%s'.\n",edn);
  354. } else if ( access & SLAPI_ACL_DELETE ) {
  355. line = PR_smprintf(
  356. "Insufficient 'delete' privilege to delete the entry '%s'.\n",edn);
  357. }
  358. aclutil_str_appened(errbuf, line );
  359. if (line) {
  360. PR_smprintf_free(line);
  361. line = NULL;
  362. }
  363. }
  364. short
  365. aclutil_gen_signature ( short c_signature )
  366. {
  367. short o_signature;
  368. o_signature = c_signature ^ (slapi_rand() % 32768);
  369. if (!o_signature)
  370. o_signature = c_signature ^ (slapi_rand() % 32768);
  371. return o_signature;
  372. }
  373. void
  374. aclutil_print_resource( struct acl_pblock *aclpb, char *right , char *attr, char *clientdn )
  375. {
  376. char str[BUFSIZ];
  377. const char *dn;
  378. if ( aclpb == NULL) return;
  379. if ( ! slapi_is_loglevel_set ( SLAPI_LOG_ACL ) )
  380. return;
  381. slapi_log_error (SLAPI_LOG_ACL, plugin_name, " ************ RESOURCE INFO STARTS *********\n",0,0,0);
  382. slapi_log_error (SLAPI_LOG_ACL, plugin_name, " Client DN: %s\n",
  383. clientdn ? escape_string_with_punctuation (clientdn, str) : "NULL", 0,0);
  384. aclutil__access_str (aclpb->aclpb_access, str);
  385. aclutil__typestr (aclpb->aclpb_res_type, &str[strlen(str)]);
  386. slapi_log_error (SLAPI_LOG_ACL, plugin_name, " resource type:%d(%s)\n",
  387. aclpb->aclpb_res_type, str, 0);
  388. dn = slapi_sdn_get_dn ( aclpb->aclpb_curr_entry_sdn );
  389. slapi_log_error (SLAPI_LOG_ACL, plugin_name, " Slapi_Entry DN: %s\n",
  390. dn ? escape_string_with_punctuation ( dn , str) : "NULL",0,0);
  391. slapi_log_error (SLAPI_LOG_ACL, plugin_name, " ATTR: %s\n", attr ? attr : "NULL",0,0);
  392. slapi_log_error (SLAPI_LOG_ACL, plugin_name, " rights:%s\n", right ? right: "NULL",0,0);
  393. slapi_log_error (SLAPI_LOG_ACL, plugin_name, " ************ RESOURCE INFO ENDS *********\n",0,0,0);
  394. }
  395. /*
  396. * The input string contains a rule like
  397. * "cn=helpdesk, ou=$attr.deptName, o=$dn.o, o=ISP"
  398. *
  399. * Where $attr -- means look into the attribute list for values
  400. * $dn -- means look into the entry's dn
  401. *
  402. * We extract the values from the entry and returned a string
  403. * with the values added.
  404. * For "$attr" rule - if we find multiple values then it is
  405. * the pattern is not expanded.
  406. * For "$dn" rule, if we find multiple of them, we use the relative
  407. * position.
  408. * NOTE: The caller is responsible in freeing the memory.
  409. */
  410. char *
  411. aclutil_expand_paramString ( char *str, Slapi_Entry *e )
  412. {
  413. char **e_dns;
  414. char **a_dns;
  415. char *attrName;
  416. char *s, *p;
  417. char *attrVal;
  418. int i, len;
  419. int ncomponents, type;
  420. int rc = -1;
  421. char *buf = NULL;
  422. e_dns = ldap_explode_dn ( slapi_entry_get_ndn ( e ), 0 );
  423. a_dns = ldap_explode_dn ( str, 0 );
  424. i = 0;
  425. ncomponents = 0;
  426. while ( a_dns[ncomponents] )
  427. ncomponents++;
  428. for (i=0; i < ncomponents; i++ ) {
  429. /* Look for"$" char */
  430. if ( (s = strchr ( a_dns[i], '$') ) != NULL) {
  431. p = s;
  432. s++;
  433. if ( strncasecmp (s, "dn", 2) == 0 )
  434. type = 1;
  435. else if ( strncasecmp (s, "attr", 4) == 0 )
  436. type = 2;
  437. else {
  438. /* error */
  439. goto cleanup;
  440. }
  441. *p = '\0';
  442. aclutil_str_appened ( &buf,a_dns[i]);
  443. if ( type == 1 ) {
  444. /* xyz = $dn.o */
  445. s +=3;
  446. attrName = s;
  447. attrVal = __aclutil_extract_dn_component (e_dns,
  448. ncomponents-i, attrName);
  449. if ( NULL == attrVal ) /*error*/
  450. goto cleanup;
  451. } else {
  452. Slapi_Attr *attr;
  453. const struct berval *attrValue;
  454. int kk;
  455. Slapi_Value *sval, *t_sval;
  456. /* The pattern is x=$attr.o" */
  457. s +=5;
  458. attrName = s;
  459. slapi_entry_attr_find ( e, attrName, &attr );
  460. if ( NULL == attr )
  461. goto cleanup;
  462. kk= slapi_attr_first_value ( attr, &sval );
  463. if ( kk != -1 ) {
  464. t_sval = sval;
  465. kk= slapi_attr_next_value( attr, kk, &sval );
  466. if ( kk != -1 ) /* can't handle multiple --error */
  467. goto cleanup;
  468. }
  469. attrValue = slapi_value_get_berval ( t_sval );
  470. attrVal = attrValue->bv_val;
  471. }
  472. } else {
  473. attrVal = a_dns[i];
  474. }
  475. aclutil_str_appened ( &buf, attrVal);
  476. aclutil_str_appened ( &buf, ",");
  477. }
  478. rc = 0; /* everything is okay*/
  479. /* remove the last comma */
  480. if (buf) {
  481. len = strlen ( buf);
  482. buf[len-1] = '\0';
  483. }
  484. cleanup:
  485. ldap_value_free ( a_dns );
  486. ldap_value_free ( e_dns );
  487. if ( 0 != rc ) /* error */ {
  488. slapi_ch_free ( (void **) &buf );
  489. buf = NULL;
  490. }
  491. return buf;
  492. }
  493. static char *
  494. __aclutil_extract_dn_component ( char **e_dns, int position, char *attrName )
  495. {
  496. int i, matched, len;
  497. char *s;
  498. int matchedPosition;
  499. len = strlen ( attrName );
  500. /* First check if there thare are multiple of these */
  501. i = matched = 0;
  502. while ( e_dns[i] ) {
  503. if (0 == strncasecmp (e_dns[i], attrName, len) ) {
  504. matched++;
  505. matchedPosition = i;
  506. }
  507. i++;
  508. }
  509. if (!matched )
  510. return NULL;
  511. if ( matched > 1 ) {
  512. matchedPosition = i - position;
  513. }
  514. if ( NULL == e_dns[matchedPosition])
  515. return NULL;
  516. s = strstr ( e_dns[matchedPosition], "=");
  517. if ( NULL == s)
  518. return NULL;
  519. else
  520. return s+1;
  521. }
  522. /*
  523. * Does the first component of ndn match the first component of match_this ?
  524. */
  525. int
  526. acl_dn_component_match( const char *ndn, char *match_this, int component_number) {
  527. return(1);
  528. }
  529. /*
  530. * Here, ndn is a resource dn and match_this is a dn, containing a macro, ($dn).
  531. *
  532. * eg. ndn is cn=fred,ou=groups,ou=people,ou=icnc,o=ISP and
  533. * match_this is "ou=Groups,($dn),o=ISP" or
  534. * "cn=*,ou=Groups,($dn),o=ISP".
  535. *
  536. * They match if:
  537. * match_this is a suffix of ndn
  538. *
  539. * It returns NULL, if they do not match.
  540. * Otherwise it returns a copy of the substring of ndn that matches the ($dn).
  541. *
  542. * eg. in the above example, "ou=people,ou=icnc"
  543. */
  544. char *
  545. acl_match_macro_in_target( const char *ndn, char * match_this,
  546. char *macro_ptr) {
  547. char *macro_prefix = NULL;
  548. int macro_prefix_len = 0;
  549. char *macro_suffix = NULL;
  550. char *tmp_ptr = NULL;
  551. char *matched_val = NULL;
  552. char *ndn_suffix_start = NULL;
  553. char *ret_val = NULL;
  554. int ndn_len = 0;
  555. int macro_suffix_len = 0;
  556. int ndn_prefix_len = 0;
  557. int ndn_prefix_end = 0;
  558. int matched_val_len = 0;
  559. /*
  560. * First, grab the macro_suffix--the bit after the ($dn)
  561. *
  562. */
  563. if (strlen(macro_ptr) == strlen(ACL_TARGET_MACRO_DN_KEY)) {
  564. macro_suffix = NULL; /* just ($dn) */
  565. } else {
  566. if ( macro_ptr[strlen(ACL_TARGET_MACRO_DN_KEY)] == ',') {
  567. macro_suffix = &macro_ptr[strlen(ACL_TARGET_MACRO_DN_KEY) + 1];
  568. } else {
  569. macro_suffix = &macro_ptr[strlen(ACL_TARGET_MACRO_DN_KEY)];
  570. }
  571. }
  572. /*
  573. * First ensure that the suffix of match_this is
  574. * a suffix of ndn.
  575. */
  576. ndn_len = strlen(ndn);
  577. if ( macro_suffix != NULL) {
  578. macro_suffix_len = strlen(macro_suffix);
  579. if( macro_suffix_len >= ndn_len ) {
  580. /*
  581. * eg ndn: o=icnc,o=sun.com
  582. * match_this: ($dn),o=icnc,o=sun.com
  583. */
  584. return(NULL); /* ($dn) must match something. */
  585. } else {
  586. /*
  587. * eg ndn: ou=People,o=icnc,o=sun.com
  588. * match_this: ($dn),o=icnc,o=sun.com
  589. *
  590. * we can do a direct strncmp() because we know that
  591. * there can be no "*" after the ($dn)...by definition.
  592. */
  593. if (strncasecmp( macro_suffix, &ndn[ndn_len-macro_suffix_len],
  594. macro_suffix_len) != 0) {
  595. return(NULL); /* suffix must match */
  596. }
  597. }
  598. }
  599. /* Start of the suffix in ndn...and it matched. */
  600. ndn_suffix_start = (char*)&ndn[ndn_len-macro_suffix_len];
  601. /* Here, macro_suffix is a suffix of ndn.
  602. *
  603. *
  604. * Now, look at macro_prefix, if it is NULL, then ($dn) matches
  605. * ndn[0..ndn_len-macro_suffix_len].
  606. * (eg, ndn: cn=fred,ou=People,o=sun.com
  607. * match_this: ($dn),o=sun.com.
  608. *
  609. */
  610. macro_prefix = slapi_ch_strdup(match_this);
  611. /* we know it's got a $(dn) */
  612. tmp_ptr = strstr(macro_prefix, ACL_TARGET_MACRO_DN_KEY);
  613. *tmp_ptr = '\0';
  614. /* There may be a NULL prefix eg. match_this: ($dn),o=sun.com */
  615. macro_prefix_len = strlen(macro_prefix);
  616. if (macro_prefix_len == 0) {
  617. slapi_ch_free((void **) &macro_prefix);
  618. macro_prefix = NULL;
  619. }
  620. if (macro_prefix == NULL ) {
  621. /*
  622. * ($dn) matches ndn[0..ndn_len-macro_suffix_len]
  623. */
  624. int matched_val_len = 0;
  625. matched_val_len = ndn_len-macro_suffix_len;
  626. matched_val = (char *)slapi_ch_malloc(matched_val_len + 1);
  627. strncpy(matched_val, ndn, ndn_len-macro_suffix_len);
  628. /*
  629. * Null terminate matched_val, removing trailing "," if there is
  630. * one.
  631. */
  632. if (matched_val_len > 1) {
  633. if (matched_val[matched_val_len-1] == ',' ) {
  634. matched_val[matched_val_len-1] = '\0';
  635. } else {
  636. matched_val[matched_val_len] = '\0';
  637. }
  638. }
  639. ret_val = matched_val;
  640. } else {
  641. /*
  642. * If it is not NULL, then if macro_prefix contains a * then
  643. * it needs to be an exact prefix of ndn (modulo the * component
  644. * which matches anything) becuase that's the semantics
  645. * of target patterns containing *'s, except that we just
  646. * make it match one component.
  647. * If it is such a prefix then ($dn) matches that portion of ndn
  648. * from the end of the prefix, &ndn[ndn_prefix_end] to
  649. * ndn_suffix_start.
  650. * If ndn_prefix_len > ndn_len-macro_suffix_len then return(NULL),
  651. * otherwise $(dn) matches ndn[ndn_prefix_len..ndn_len-macro_suffix_len].
  652. *
  653. *
  654. * eg. ndn: cn=fred,ou=P,o=sun.com
  655. * match_this: cn=*,($dn),o=sun.com
  656. */
  657. if ( strstr(macro_prefix, "=*") != NULL ) {
  658. int exact_match = 0;
  659. ndn_prefix_len = acl_match_prefix( macro_prefix, ndn, &exact_match);
  660. if ( ndn_prefix_len != -1 ) {
  661. /*
  662. * ndn[0..ndn_prefix_len] is the prefix in ndn.
  663. * ndn[ndn_prefix_len..ndn_len-macro_suffix_len] is the
  664. * matched string.
  665. */
  666. if (ndn_prefix_len >= ndn_len-macro_suffix_len) {
  667. /*
  668. * eg ndn: cn=fred,ou=People,o=icnc,o=sun.com
  669. * cn=*,ou=People,o=icnc,($dn),o=icnc,o=sun.com
  670. */
  671. ret_val = NULL; /* matched string is empty */
  672. } else {
  673. /*
  674. * eg ndn: cn=fred,ou=People,o=icnc,o=sun.com
  675. * cn=*,ou=People,($dn),o=sun.com
  676. */
  677. matched_val_len = ndn_len-macro_suffix_len-ndn_prefix_len;
  678. matched_val = (char *)slapi_ch_malloc(matched_val_len + 1);
  679. strncpy(matched_val, &ndn[ndn_prefix_len], matched_val_len);
  680. if (matched_val_len > 1) {
  681. if (matched_val[matched_val_len-1] == ',' ) {
  682. matched_val[matched_val_len-1] = '\0';
  683. } else {
  684. matched_val[matched_val_len] = '\0';
  685. }
  686. }
  687. matched_val[matched_val_len] = '\0';
  688. ret_val = matched_val;
  689. }
  690. } else {
  691. /* Was not a prefix so not a match */
  692. ret_val = NULL;
  693. }
  694. } else {
  695. /*
  696. *
  697. * If macro_prefix is not NULL and it does not
  698. * contain a =* then
  699. * we need to ensure that macro_prefix is a substring
  700. * ndn.
  701. * If it is and the position of the character after it's end in
  702. * ndn is
  703. * ndn_prefix_end then ($dn) matches
  704. * ndn[ndn_prefix_end..ndn_len-macro_suffix_len].
  705. *
  706. *
  707. * One important principal is that ($dn) matches a maximal
  708. * chunk--this way it will serve to make the link
  709. * between resources and users at each level of the structure.
  710. *
  711. * eg. ndn: ou=Groups,ou=Groups,ou=Groups,c=fr
  712. * macro_prefix: ou=Groups,($dn),c=fr
  713. *
  714. * then ($dn) matches ou=Groups,ou=Groups.
  715. *
  716. *
  717. *
  718. * If it is not a substring, then there is no match.
  719. * If it is a substring and
  720. * ndn[ndn_prefix_end..ndn_len-macro_suffix_len] is empty then
  721. * it's also not a match as we demand that ($dn) match a non-empty
  722. * string.
  723. *
  724. *
  725. *
  726. * (eg. ndn: cn=fred,o=icnc,ou=People,o=sun.com
  727. * match_this: o=icnc,($dn),o=sun.com.)
  728. *
  729. *
  730. * (eg. ndn: cn=fred,o=menlo park,ou=People,o=icnc,o=sun.com
  731. * match_this: o=menlo park,ou=People,($dn),o=sun.com
  732. *
  733. */
  734. ndn_prefix_end = acl_strstr((char *)ndn, macro_prefix);
  735. if ( ndn_prefix_end == -1) {
  736. ret_val = NULL;
  737. } else {
  738. /* Is a substring */
  739. ndn_prefix_end += macro_prefix_len;
  740. /*
  741. * make sure the matching part is non-empty:
  742. *
  743. * ndn[ndn_prefix_end..mndn_len-macro_suffix_len].
  744. */
  745. if ( ndn_prefix_end >= ndn_len-macro_suffix_len) {
  746. ret_val = NULL;
  747. } else {
  748. /*
  749. * ($dn) matches the non-empty string segment
  750. * ndn[ndn_prefix_end..mndn_len-macro_suffix_len]
  751. * the -1 is because macro_suffix_eln does not include
  752. * the coma before the suffix.
  753. */
  754. matched_val_len = ndn_len-macro_suffix_len-
  755. ndn_prefix_end - 1;
  756. matched_val = (char *)slapi_ch_malloc(matched_val_len + 1);
  757. strncpy(matched_val, &ndn[ndn_prefix_end],
  758. matched_val_len);
  759. matched_val[matched_val_len] = '\0';
  760. ret_val = matched_val;
  761. }
  762. }
  763. }/* contains an =* */
  764. slapi_ch_free((void **) &macro_prefix);
  765. }/* macro_prefix != NULL */
  766. return(ret_val);
  767. }
  768. /*
  769. * Checks to see if macro_prefix is an exact prefix of ndn.
  770. * macro_prefix may contain a * component.
  771. *
  772. * The length of the matched prefix in ndn is returned.
  773. * If it was not a match, a negative int is returned.
  774. * Also, if the string matched exactly,
  775. * exact_match is set to 1, other wise it was a proper prefix.
  776. *
  777. */
  778. int
  779. acl_match_prefix( char *macro_prefix, const char *ndn, int *exact_match) {
  780. int ret_code = -1;
  781. int macro_prefix_len = 0;
  782. int ndn_len = 0;
  783. int i = 0;
  784. int j = 0;
  785. int done = 0;
  786. int t = 0;
  787. char * tmp_str = NULL;
  788. int k,l = 0;
  789. *exact_match = 0; /* default to not an exact match */
  790. /* The NULL prefix matches everthing*/
  791. if (macro_prefix == NULL) {
  792. if ( ndn == NULL ) {
  793. *exact_match = 1;
  794. }
  795. return(0);
  796. } else {
  797. /* macro_prefix is not null, so if ndn is NULL, it's not a match. */
  798. if ( ndn == NULL) {
  799. return(-1);
  800. }
  801. }
  802. /*
  803. * Here, neither macro_prefix nor ndn are NULL.
  804. *
  805. * eg. macro_prefix: cn=*,ou=people,o=sun.com
  806. * ndn : cn=fred,ou=people,o=sun.com
  807. */
  808. /*
  809. * Here, there is a component with a * (eg. cn=* ) so
  810. * we need to step through the macro_prefix, and where there is
  811. * such a * match on that component,
  812. * when we run out of * componenets, jsut do a straight match.
  813. *
  814. * Out of interest, the following extended regular expression
  815. * will match just one ou rdn value from a string:
  816. * "^uid=admin,ou=\([^,]*\\\,\)*[^,]*,o=sun.com$"
  817. *
  818. *
  819. * eg. cn=fred,ou=People,o=sun.com
  820. *
  821. *
  822. * s points to the = of the component.
  823. */
  824. macro_prefix_len = strlen(macro_prefix);
  825. ndn_len = strlen(ndn);
  826. i = 0;
  827. j = 0;
  828. done = 0;
  829. while ( !done ) {
  830. /* Here ndn[0..i] has matched macro_prefix[0..j] && j<= i
  831. * i<=ndn_len j<=macro_prefix_len */
  832. if ( (t = acl_strstr(&macro_prefix[j], "=*")) < 0 ) {
  833. /*
  834. * No more *'s, do a straight match on
  835. * macro_prefix[j..macro_prefix_len] and
  836. * ndn[i..macro_prefix_len]
  837. */
  838. if( macro_prefix_len-j > ndn_len-i) {
  839. /* Not a prefix, nor a match */
  840. *exact_match = 0;
  841. ret_code = -1;
  842. done = 1;
  843. } else {
  844. /*
  845. * ndn_len-i >= macro_prefix_len - j
  846. * if macro_prefix_len-j is 0, then
  847. * it's a null prefix, so it matches.
  848. * If in addition ndn_len-i is 0 then it's
  849. * an exact match.
  850. * Otherwise, do the cmp.
  851. */
  852. if ( macro_prefix_len-j == 0) {
  853. done = 1;
  854. ret_code = i;
  855. if ( ndn_len-i == 0) {
  856. *exact_match = 1;
  857. }
  858. }else {
  859. if (strncasecmp(&macro_prefix[j], &ndn[i],
  860. macro_prefix_len-j) == 0) {
  861. *exact_match = (macro_prefix_len-j == ndn_len-i);
  862. ret_code = i + macro_prefix_len -j;
  863. done = 1;
  864. } else {
  865. /* not a prefix not a match */
  866. *exact_match = 0;
  867. ret_code = -1;
  868. done = 1;
  869. }
  870. }
  871. }
  872. }else {
  873. /*
  874. * Is another * component, so:
  875. * 1. match that component in macro_prefix (at pos k say)
  876. * with the corresponding compoent (at pos l say ) in ndn
  877. *
  878. * 2. match the intervening string ndn[i..l] and
  879. * macro_prefix[j..k].
  880. */
  881. /* First, find the start of the component in macro_prefix. */
  882. t++; /* move to the--this way we will look for "ou=" in ndn */
  883. k = acl_find_comp_start(macro_prefix, t);
  884. /* Now identify that component in ndn--if it's not there no match */
  885. tmp_str = slapi_ch_malloc(t-k+1);
  886. strncpy(tmp_str, &macro_prefix[k], t-k);
  887. tmp_str[t-k] = '\0';
  888. l = acl_strstr((char*)&ndn[i], tmp_str);
  889. if (l == -1) {
  890. *exact_match = 0;
  891. ret_code = -1;
  892. done = 1;
  893. } else {
  894. /*
  895. * Found the comp in ndn, so the comp matches.
  896. * Now test the intervening string segments:
  897. * ndn[i..l] and macro_prefix[j..k]
  898. */
  899. if ( k-j != l-i ) {
  900. *exact_match = 0;
  901. ret_code = -1;
  902. done = 1;
  903. } else{
  904. if (strncasecmp(&macro_prefix[j], &ndn[i], k-j) != 0) {
  905. *exact_match = 0;
  906. ret_code = -1;
  907. done = 1;
  908. } else {
  909. /* Matched, so bump i and j and keep going.*/
  910. i += acl_find_comp_end((char*)&ndn[l]);
  911. j += acl_find_comp_end((char*)&macro_prefix[k]);
  912. }
  913. }
  914. }
  915. slapi_ch_free((void **)&tmp_str);
  916. }
  917. }/* while */
  918. return(ret_code);
  919. }
  920. /*
  921. * returns the index in s of where the component at position
  922. * s[pos] starts.
  923. * This is the index of the character after the first unescaped comma
  924. * moving backwards in s from pos.
  925. * If this is not found then return 0, ie. the start of the string.
  926. * If the index returned is > strlen(s) then could not find it.
  927. * only such case is if you pass ",", in which case there is no component start.
  928. */
  929. static int
  930. acl_find_comp_start(char * s, int pos ) {
  931. int i =0;
  932. int comp_start = 0;
  933. i = pos;
  934. while( i > 0 && (s[i] != ',' ||
  935. s[i-1] == '\\')) {
  936. i--;
  937. }
  938. /*
  939. * i == 0 || (s[i] == ',' && s[i-1] != '\\')
  940. */
  941. if (i==0) {
  942. /* Got all the way with no unescaped comma */
  943. if (s[i] == ',') {
  944. comp_start = i+1;
  945. } else {
  946. comp_start = i;
  947. }
  948. } else { /* Found an unescaped comma */
  949. comp_start = i + 1;
  950. }
  951. return( comp_start);
  952. }
  953. /*
  954. * returns the index in s of the first character after the
  955. * first unescaped comma.
  956. * If ther is no such character, returns strlen(s);
  957. */
  958. int
  959. acl_find_comp_end( char * s) {
  960. int i = 0;
  961. int s_len = 0;
  962. s_len = strlen(s);
  963. if ( s_len == 0 || s_len == 1) {
  964. return(s_len);
  965. }
  966. /* inv: i+1<s_len && (s[i] == '\\' || s[i+1] != ',')*/
  967. i = 0;
  968. while( i+1 < s_len && (s[i] == '\\' ||
  969. s[i+1] != ',')) {
  970. i++;
  971. }
  972. if ( i + 1 == s_len) {
  973. return(s_len);
  974. } else {
  975. return(i+2);
  976. }
  977. }
  978. /*
  979. * return the index in s where substr occurs, if none
  980. * returns -1.
  981. */
  982. int
  983. acl_strstr(char * s, char *substr) {
  984. char *t = NULL;
  985. char *tmp_str = NULL;
  986. tmp_str = slapi_ch_strdup(s);
  987. if ( (t = strstr(tmp_str, substr)) == NULL ) {
  988. slapi_ch_free((void **)&tmp_str);
  989. return(-1);
  990. } else {
  991. int l = 0;
  992. *t = '\0';
  993. l = strlen(tmp_str);
  994. slapi_ch_free((void **)&tmp_str);
  995. return(l);
  996. }
  997. }
  998. /*
  999. * replace all occurences of substr in s with replace_str.
  1000. *
  1001. * returns a malloced version of the patched string.
  1002. */
  1003. char *
  1004. acl_replace_str(char * s, char *substr, char* replace_with_str) {
  1005. char *str = NULL;
  1006. char *working_s, *suffix, *prefix, *patched;
  1007. int replace_with_len, substr_len, prefix_len, suffix_len;
  1008. if ( (str = strstr(s, substr)) == NULL) {
  1009. return(slapi_ch_strdup(s));
  1010. } else {
  1011. replace_with_len = strlen(replace_with_str);
  1012. substr_len = strlen(substr);
  1013. working_s = slapi_ch_strdup(s);
  1014. prefix = working_s;
  1015. str = strstr(prefix, substr);
  1016. while (str != NULL) {
  1017. /*
  1018. * working_s is a copy of the string to be patched
  1019. * str points to a substr to be patched
  1020. * prefix points to working_s
  1021. */
  1022. *str = '\0';
  1023. suffix = &str[substr_len];
  1024. prefix_len = strlen(prefix);
  1025. suffix_len = strlen(suffix);
  1026. patched = (char *)slapi_ch_malloc(prefix_len +
  1027. replace_with_len +
  1028. suffix_len +1 );
  1029. strcpy(patched, prefix);
  1030. strcat(patched, replace_with_str);
  1031. strcat(patched, suffix);
  1032. slapi_ch_free((void **)&working_s);
  1033. working_s = patched;
  1034. prefix = working_s;
  1035. str = strstr(prefix, substr);
  1036. }
  1037. return(working_s);
  1038. }
  1039. }
  1040. /*
  1041. * Start at index and return a malloced string that is the
  1042. * next component in dn (eg. "ou=People"),
  1043. * or NULL if couldn't find the next one.
  1044. */
  1045. char *
  1046. get_next_component(char *dn, int *index) {
  1047. int dn_len = strlen(dn);
  1048. int start_next = -1;
  1049. int i = 0;
  1050. char *ret_comp;
  1051. if (*index>= dn_len) {
  1052. return(NULL);
  1053. }
  1054. start_next = acl_find_comp_end( &dn[*index]);
  1055. if ( start_next >= dn_len ) {
  1056. *index = start_next;
  1057. return(NULL); /* no next comp */
  1058. }
  1059. /*
  1060. *Here, start_next should be the start of the next
  1061. * component--so far have not run off the end.
  1062. */
  1063. i = acl_find_comp_end( &dn[start_next]);
  1064. /*
  1065. * Here, the matched string is all from start_next to i.
  1066. */
  1067. ret_comp = (char *)slapi_ch_malloc(i - start_next +1);
  1068. memcpy( ret_comp, &dn[start_next], i-start_next);
  1069. ret_comp[i-start_next] = '\0';
  1070. return(ret_comp);
  1071. }
  1072. char *
  1073. get_this_component(char *dn, int *index) {
  1074. int dn_len = strlen(dn);
  1075. int i = 0;
  1076. char *ret_comp;
  1077. if (*index>= dn_len) {
  1078. return(NULL);
  1079. }
  1080. if (dn_len == *index + 1) {
  1081. /* Just return a copy of the string. */
  1082. return(slapi_ch_strdup(dn));
  1083. }else {
  1084. /* *index + 1 < dn_len */
  1085. i = *index+1;
  1086. while( (dn[i] != '\0') && dn[i] != ',' && dn[i-1] != '\\') {
  1087. i += 1;
  1088. }
  1089. /*
  1090. * Here, the matched string is all from *index to i.
  1091. */
  1092. ret_comp = (char *)slapi_ch_malloc(i - *index +1);
  1093. memcpy( ret_comp, &dn[*index], i - *index);
  1094. ret_comp[i-*index] = '\0';
  1095. if (i < dn_len) {
  1096. /* Found a comma before the end */
  1097. *index = i + 1; /* skip it */
  1098. }
  1099. return(ret_comp);
  1100. }
  1101. }
  1102. /* acl hash table funcs */
  1103. /*
  1104. * Add the key adn value to the ht.
  1105. * If it already exists then remove the old one and free
  1106. * the value.
  1107. */
  1108. void acl_ht_add_and_freeOld(acl_ht_t * acl_ht,
  1109. PLHashNumber key,
  1110. char *value){
  1111. char *old_value = NULL;
  1112. if ( (old_value = (char *)acl_ht_lookup( acl_ht, key)) != NULL ) {
  1113. acl_ht_remove( acl_ht, key);
  1114. slapi_ch_free((void **)&old_value);
  1115. }
  1116. PL_HashTableAdd( acl_ht, (const void *)key, value);
  1117. }
  1118. /*
  1119. * Return a new acl_ht_t *
  1120. */
  1121. acl_ht_t *acl_ht_new(void) {
  1122. return(PL_NewHashTable(30, acl_ht_hash, /* key hasher */
  1123. PL_CompareValues, /* keyCompare */
  1124. PL_CompareStrings, 0, 0)); /* value compare */
  1125. }
  1126. static PLHashNumber acl_ht_hash( const void *key) {
  1127. return( (PLHashNumber)key );
  1128. }
  1129. /* Free all the values in the ht */
  1130. void acl_ht_free_all_entries_and_values( acl_ht_t *acl_ht) {
  1131. PL_HashTableEnumerateEntries( acl_ht, acl_ht_free_entry_and_value,
  1132. NULL);
  1133. }
  1134. static PRIntn
  1135. acl_ht_free_entry_and_value(PLHashEntry *he, PRIntn i, void *arg)
  1136. {
  1137. slapi_ch_free((void **)&he->value); /* free value */
  1138. /* Free this entry anfd go on to next one */
  1139. return ( HT_ENUMERATE_NEXT | HT_ENUMERATE_REMOVE);
  1140. }
  1141. /* Free all the values in the ht */
  1142. void acl_ht_display_ht( acl_ht_t *acl_ht) {
  1143. #ifdef DEBUG
  1144. PL_HashTableEnumerateEntries( acl_ht, acl_ht_display_entry, NULL);
  1145. #endif
  1146. }
  1147. static PRIntn
  1148. acl_ht_display_entry(PLHashEntry *he, PRIntn i, void *arg)
  1149. {
  1150. PLHashNumber aci_index = (PLHashNumber)he->key;
  1151. char *matched_val = (char *)he->value;
  1152. LDAPDebug(LDAP_DEBUG_ACL,"macro ht entry: key='%d' matched_val='%s'"
  1153. "keyhash='%d'\n",
  1154. aci_index, (matched_val ? matched_val: "NULL"),
  1155. (PLHashNumber)he->keyHash);
  1156. return HT_ENUMERATE_NEXT;
  1157. }
  1158. /* remove this entry from the ht--doesn't free the value.*/
  1159. void acl_ht_remove( acl_ht_t *acl_ht, PLHashNumber key) {
  1160. PL_HashTableRemove( acl_ht, (const void *)key);
  1161. }
  1162. /* Retrieve a pointer to the value of the entry with key */
  1163. void *acl_ht_lookup( acl_ht_t *acl_ht,
  1164. PLHashNumber key) {
  1165. return( PL_HashTableLookup( acl_ht, (const void *)key) );
  1166. }
  1167. /***************************************************************************/
  1168. /* E N D */
  1169. /***************************************************************************/