aclutil.c 36 KB

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