aclutil.c 35 KB

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