1
0

aclutil.c 37 KB

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