1
0

aclutil.c 37 KB

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