aclutil.c 36 KB

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