lasip.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /* aclip.c
  13. * This file contains the IP LAS code.
  14. */
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <netsite.h>
  18. #include <base/plist.h>
  19. #include <libaccess/nserror.h>
  20. #include <libaccess/nsauth.h>
  21. #include <libaccess/acl.h>
  22. #include "aclpriv.h"
  23. #include <libaccess/aclproto.h>
  24. #include <libaccess/las.h>
  25. #include "lasip.h"
  26. #include "aclutil.h"
  27. #include "aclcache.h"
  28. #include <libaccess/dbtlibaccess.h>
  29. #include <libaccess/aclerror.h>
  30. #include <prio.h>
  31. #include "nspr.h"
  32. #define LAS_IP_IS_CONSTANT(x) (((x) == (LASIpTree_t *)LAS_EVAL_TRUE) || ((x) == (LASIpTree_t *)LAS_EVAL_FALSE))
  33. #ifdef UTEST
  34. extern int LASIpGetIp();
  35. #endif
  36. static int colonhex_ipv6(char *ipstr, const char *netmaskstr, PRIPv6Addr *ipv6, int *netmask);
  37. static int LASIpAddPattern(NSErr_t *errp, int netmask, int pattern, LASIpTree_t **treetop);
  38. static int LASIpAddPatternIPv6(NSErr_t *errp, int netmask, PRIPv6Addr *ipv6, LASIpTree_t **treetop);
  39. /* dotdecimal
  40. * Takes netmask and ip strings and returns the numeric values,
  41. * accounting for wildards in the ip specification. Wildcards in the
  42. * ip override the netmask where they conflict.
  43. * INPUT
  44. * ipstr e.g. "123.45.67.89"
  45. * netmaskstr e.g. "255.255.255.0"
  46. * RETURNS
  47. * *ip
  48. * *netmask e.g. 0xffffff00
  49. * result NULL on success or else one of the LAS_EVAL_* codes.
  50. */
  51. int
  52. dotdecimal(char *ipstr, const char *netmaskstr, int *ip, int *netmask)
  53. {
  54. int i;
  55. char token[64];
  56. char *dotptr; /* location of the "." */
  57. int dotidx; /* index of the period char */
  58. /* Sanity check the patterns */
  59. /* Netmask can only have digits and periods. */
  60. if (strcspn(netmaskstr, "0123456789."))
  61. return LAS_EVAL_INVALID;
  62. /* IP can only have digits, periods and "*" */
  63. if (strcspn(ipstr, "0123456789.*")) {
  64. return LAS_EVAL_INVALID;
  65. }
  66. if (strlen(netmaskstr) >= sizeof(token)) {
  67. return LAS_EVAL_INVALID;
  68. }
  69. if (strlen(ipstr) >= sizeof(token)) {
  70. return LAS_EVAL_INVALID;
  71. }
  72. *netmask = *ip = 0; /* Start with "don't care" */
  73. for (i=0; i<4; i++) {
  74. dotptr = strchr((char*)netmaskstr, '.');
  75. /* copy out the token, then point beyond it */
  76. if (dotptr == NULL)
  77. strcpy(token, netmaskstr);
  78. else {
  79. dotidx = dotptr-netmaskstr;
  80. strncpy(token, netmaskstr, dotidx);
  81. token[dotidx] = '\0';
  82. netmaskstr = ++dotptr; /* skip the period */
  83. }
  84. /* Turn into a number and shift left as appropriate */
  85. *netmask += (atoi(token))<<(8*(4-i-1));
  86. if (dotptr == NULL)
  87. break;
  88. }
  89. for (i=0; i<4; i++) {
  90. dotptr = strchr(ipstr, '.');
  91. /* copy out the token, then point beyond it */
  92. if (dotptr == NULL)
  93. strcpy(token, ipstr);
  94. else {
  95. dotidx = dotptr-ipstr;
  96. strncpy(token, ipstr, dotidx);
  97. token[dotidx] = '\0';
  98. ipstr = ++dotptr;
  99. }
  100. /* check for wildcard */
  101. if (strcmp(token, "*") == 0) {
  102. switch(i) {
  103. case 0:
  104. if (dotptr == NULL)
  105. *netmask &= 0x00000000;
  106. else
  107. *netmask &= 0x00ffffff;
  108. break;
  109. case 1:
  110. if (dotptr == NULL)
  111. *netmask &= 0xff000000;
  112. else
  113. *netmask &= 0xff00ffff;
  114. break;
  115. case 2:
  116. if (dotptr == NULL)
  117. *netmask &= 0xffff0000;
  118. else
  119. *netmask &= 0xffff00ff;
  120. break;
  121. case 3:
  122. *netmask &= 0xffffff00;
  123. break;
  124. }
  125. continue;
  126. } else {
  127. /* Turn into a number and shift left as appropriate */
  128. *ip += (atoi(token))<<(8*(4-i-1));
  129. }
  130. /* check for end of string */
  131. if (dotptr == NULL) {
  132. switch(i) {
  133. case 0:
  134. *netmask &= 0xff000000;
  135. break;
  136. case 1:
  137. *netmask &= 0xffff0000;
  138. break;
  139. case 2:
  140. *netmask &= 0xffffff00;
  141. break;
  142. }
  143. break;
  144. }
  145. }
  146. return 0;
  147. }
  148. /* LASIpTreeAlloc
  149. * Malloc a node and set the actions to LAS_EVAL_FALSE
  150. */
  151. static LASIpTree_t *
  152. LASIpTreeAllocNode(NSErr_t *errp)
  153. {
  154. LASIpTree_t *newnode;
  155. newnode = (LASIpTree_t *)PERM_MALLOC(sizeof(LASIpTree_t));
  156. if (newnode == NULL) {
  157. nserrGenerate(errp, ACLERRNOMEM, ACLERR5000, ACL_Program, 1, XP_GetAdminStr(DBT_lasiptreeallocNoMemoryN_));
  158. return NULL;
  159. }
  160. newnode->action[0] = (LASIpTree_t *)LAS_EVAL_FALSE;
  161. newnode->action[1] = (LASIpTree_t *)LAS_EVAL_FALSE;
  162. return newnode;
  163. }
  164. /* LASIpTreeDealloc
  165. * Deallocates a Tree starting from a given node down.
  166. * INPUT
  167. * startnode Starting node to remove. Could be a constant in
  168. * which case, just return success.
  169. * OUTPUT
  170. * N/A
  171. */
  172. static void
  173. LASIpTreeDealloc(LASIpTree_t *startnode)
  174. {
  175. int i;
  176. if (startnode == NULL)
  177. return;
  178. /* If this is just a constant then we're done */
  179. if (LAS_IP_IS_CONSTANT(startnode))
  180. return;
  181. /* Else recursively call ourself for each branch down */
  182. for (i=0; i<2; i++) {
  183. if (!(LAS_IP_IS_CONSTANT(startnode->action[i])))
  184. LASIpTreeDealloc(startnode->action[i]);
  185. }
  186. /* Now deallocate the local node */
  187. PERM_FREE(startnode);
  188. }
  189. /*
  190. * LASIpBuild
  191. * INPUT
  192. * attr_name The string "ip" - in lower case.
  193. * comparator CmpOpEQ or CmpOpNE only
  194. * attr_pattern A comma-separated list of IP addresses and netmasks
  195. * in dotted-decimal form. Netmasks are optionally
  196. * prepended to the IP address using a plus sign. E.g.
  197. * 255.255.255.0+123.45.67.89. Any byte in the IP address
  198. * (but not the netmask) can be wildcarded using "*"
  199. * context A pointer to the IP LAS context structure.
  200. * RETURNS
  201. * ret code The usual LAS return codes.
  202. */
  203. static int
  204. LASIpBuild(NSErr_t *errp, char *attr_name, CmpOp_t comparator, char *attr_pattern, LASIpContext_t *context)
  205. {
  206. unsigned int delimiter; /* length of valid token */
  207. char token[64], token2[64]; /* a single ip[+netmask] */
  208. char *curptr; /* current place in attr_pattern */
  209. int netmask = 0;
  210. int ip = 0;
  211. char *plusptr;
  212. int retcode;
  213. if (NULL == context) {
  214. return ACL_RES_ERROR;
  215. }
  216. /*
  217. * IP address can be delimited by space, tab, comma, or carriage return only.
  218. */
  219. curptr = attr_pattern;
  220. do {
  221. delimiter = strcspn(curptr, ", \t");
  222. delimiter = (delimiter <= strlen(curptr)) ? delimiter : strlen(curptr);
  223. strncpy(token, curptr, delimiter);
  224. if (delimiter >= sizeof(token)) {
  225. return LAS_EVAL_INVALID;
  226. }
  227. token[delimiter] = '\0';
  228. /* skip all the white space after the token */
  229. curptr = strpbrk((curptr+delimiter), "1234567890+.*ABCDEFabcdef:/");
  230. /*
  231. * IPv4 addresses do not have ":"
  232. */
  233. if( strstr(token,":") == NULL ){
  234. /* Is there a netmask? */
  235. plusptr = strchr(token, '+');
  236. if (plusptr == NULL) {
  237. if (curptr && (*curptr == '+')) {
  238. /* There was a space before (and possibly after) the plus sign*/
  239. curptr = strpbrk((++curptr), "1234567890.*");
  240. delimiter = strcspn(curptr, ", \t");
  241. delimiter = (delimiter <= strlen(curptr)) ? delimiter : strlen(curptr);
  242. if (delimiter >= sizeof(token2)) {
  243. return LAS_EVAL_INVALID;
  244. }
  245. strncpy(token2, curptr, delimiter);
  246. token2[delimiter] = '\0';
  247. retcode = dotdecimal(token, token2, &ip, &netmask);
  248. if (retcode)
  249. return (retcode);
  250. curptr = strpbrk((++curptr), "1234567890+.*");
  251. } else {
  252. retcode = dotdecimal(token, "255.255.255.255", &ip, &netmask);
  253. if (retcode)
  254. return (retcode);
  255. }
  256. } else {
  257. /* token is the IP addr string in both cases */
  258. *plusptr ='\0'; /* truncate the string */
  259. retcode =dotdecimal(token, ++plusptr, &ip, &netmask);
  260. if (retcode)
  261. return (retcode);
  262. }
  263. if (LASIpAddPattern(errp, netmask, ip, &context->treetop) != 0)
  264. return LAS_EVAL_INVALID;
  265. } else {
  266. /*
  267. * IPv6
  268. */
  269. PRIPv6Addr ipv6;
  270. plusptr = strchr(token, '/');
  271. if (plusptr == NULL) {
  272. if (curptr && (*curptr == '/')) {
  273. /* There was a space before (and possibly after) the plus sign */
  274. curptr = strpbrk((++curptr), "1234567890.*:ABCDEFabcdef");
  275. delimiter = strcspn(curptr, ", \t");
  276. delimiter = (delimiter <= strlen(curptr)) ? delimiter : strlen(curptr);
  277. strncpy(token2, curptr, delimiter);
  278. token2[delimiter] = '\0';
  279. retcode = colonhex_ipv6(token, token2, &ipv6, &netmask);
  280. if (retcode)
  281. return (retcode);
  282. curptr = strpbrk((++curptr), "1234567890+.:ABCDEFabcdef*");
  283. } else {
  284. retcode = colonhex_ipv6(token, "128", &ipv6, &netmask);
  285. if (retcode)
  286. return (retcode);
  287. }
  288. } else {
  289. /* token is the IP addr string in both cases */
  290. *plusptr ='\0'; /* truncate the string */
  291. retcode = colonhex_ipv6(token, ++plusptr, &ipv6, &netmask);
  292. if (retcode)
  293. return (retcode);
  294. }
  295. if (LASIpAddPatternIPv6(errp, netmask, &ipv6, &context->treetop_ipv6) != (int)NULL) {
  296. return LAS_EVAL_INVALID;
  297. }
  298. }
  299. } while ((curptr != NULL) && (delimiter != 0));
  300. return 0;
  301. }
  302. /* LASIpAddPattern
  303. * Takes a netmask and IP address and a pointer to an existing IP
  304. * tree and adds nodes as appropriate to recognize the new pattern.
  305. * INPUT
  306. * netmask e.g. 0xffffff00
  307. * pattern IP address in 4 bytes
  308. * *treetop An existing IP tree or 0 if a new tree
  309. * RETURNS
  310. * ret code NULL on success, ACL_RES_ERROR on failure
  311. * **treetop If this is a new tree, the head of the tree.
  312. */
  313. static int
  314. LASIpAddPattern(NSErr_t *errp, int netmask, int pattern, LASIpTree_t **treetop)
  315. {
  316. int stopbit; /* Don't care after this point */
  317. int curbit; /* current bit we're working on */
  318. int curval; /* value of pattern[curbit] */
  319. LASIpTree_t *curptr = NULL; /* pointer to the current node */
  320. LASIpTree_t *newptr;
  321. if (NULL == treetop) {
  322. return ACL_RES_ERROR;
  323. }
  324. /* stop at the first 1 in the netmask from low to high */
  325. for (stopbit=0; stopbit<32; stopbit++) {
  326. if ((netmask&(1<<stopbit)) != 0)
  327. break;
  328. }
  329. /* Special case if there's no tree. Allocate the first node */
  330. if (*treetop == (LASIpTree_t *)NULL) { /* No tree at all */
  331. curptr = LASIpTreeAllocNode(errp);
  332. if (curptr == NULL) {
  333. nserrGenerate(errp, ACLERRFAIL, ACLERR5100, ACL_Program, 1,
  334. XP_GetAdminStr(DBT_ipLasUnableToAllocateTreeNodeN_));
  335. return ACL_RES_ERROR;
  336. }
  337. *treetop = curptr;
  338. }
  339. /*
  340. * Special case if the netmask is 0.
  341. */
  342. if (stopbit > 31) {
  343. (*treetop)->action[0] = (LASIpTree_t *)LAS_EVAL_TRUE;
  344. (*treetop)->action[1] = (LASIpTree_t *)LAS_EVAL_TRUE;
  345. return 0;
  346. }
  347. /* follow the tree down the pattern path bit by bit until the
  348. * end of the tree is reached (i.e. a constant).
  349. */
  350. for (curbit=31,curptr=*treetop; curbit >= 0; curbit--) {
  351. /* Is the current bit ON? If so set curval to 1 else 0 */
  352. curval = (pattern & (1<<curbit)) ? 1 : 0;
  353. /* Are we done, if so remove the rest of the tree */
  354. if (curbit == stopbit) {
  355. LASIpTreeDealloc(curptr->action[curval]);
  356. curptr->action[curval] = (LASIpTree_t *)LAS_EVAL_TRUE;
  357. /* This is the normal exit point. Most other exits must be due to errors. */
  358. return 0;
  359. }
  360. /* Oops reached the end - must allocate */
  361. if (LAS_IP_IS_CONSTANT(curptr->action[curval])) {
  362. newptr = LASIpTreeAllocNode(errp);
  363. if (newptr == NULL) {
  364. LASIpTreeDealloc(*treetop);
  365. nserrGenerate(errp, ACLERRFAIL, ACLERR5110, ACL_Program, 1,
  366. XP_GetAdminStr(DBT_ipLasUnableToAllocateTreeNodeN_1));
  367. return ACL_RES_ERROR;
  368. }
  369. curptr->action[curval] = newptr;
  370. }
  371. /* Keep going down the tree */
  372. curptr = curptr->action[curval];
  373. }
  374. return ACL_RES_ERROR;
  375. }
  376. /* LASIpFlush
  377. * Deallocates any memory previously allocated by the LAS
  378. */
  379. void
  380. LASIpFlush(void **las_cookie)
  381. {
  382. if (*las_cookie == NULL)
  383. return;
  384. LASIpTreeDealloc(((LASIpContext_t *)*las_cookie)->treetop);
  385. PERM_FREE(*las_cookie);
  386. *las_cookie = NULL;
  387. return;
  388. }
  389. /*
  390. * LASIpEval
  391. * INPUT
  392. * attr_name The string "ip" - in lower case.
  393. * comparator CMP_OP_EQ or CMP_OP_NE only
  394. * attr_pattern A comma-separated list of IP addresses and netmasks
  395. * in dotted-decimal form. Netmasks are optionally
  396. * prepended to the IP address using a plus sign. E.g.
  397. * 255.255.255.0+123.45.67.89. Any byte in the IP address
  398. * (but not the netmask) can be wildcarded using "*"
  399. * *cachable Always set to ACL_INDEF_CACHABLE
  400. * subject Subject property list
  401. * resource Resource property list
  402. * auth_info The authentication info if any
  403. * RETURNS
  404. * ret code The usual LAS return codes.
  405. */
  406. int LASIpEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
  407. char *attr_pattern, ACLCachable_t *cachable, void **LAS_cookie,
  408. PList_t subject, PList_t resource, PList_t auth_info,
  409. PList_t global_auth)
  410. {
  411. LASIpContext_t *context = NULL;
  412. LASIpTree_t *node = NULL;
  413. IPAddr_t ip;
  414. PRNetAddr *client_addr = NULL;
  415. struct in_addr client_inaddr;
  416. char ip_str[124];
  417. int retcode;
  418. int value;
  419. int bit;
  420. int rc = LAS_EVAL_INVALID;
  421. int rv;
  422. *cachable = ACL_INDEF_CACHABLE;
  423. if (strcmp(attr_name, "ip") != 0) {
  424. nserrGenerate(errp, ACLERRINVAL, ACLERR5200, ACL_Program, 2,
  425. XP_GetAdminStr(DBT_lasIpBuildReceivedRequestForAttr_), attr_name);
  426. return LAS_EVAL_INVALID;
  427. }
  428. if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) {
  429. nserrGenerate(errp, ACLERRINVAL, ACLERR5210, ACL_Program, 2,
  430. XP_GetAdminStr(DBT_lasipevalIllegalComparatorDN_), comparator_string(comparator));
  431. return LAS_EVAL_INVALID;
  432. }
  433. /*
  434. * Get the IP addr from the session context, and store it in "client_addr
  435. */
  436. #ifndef UTEST
  437. rv = ACL_GetAttribute(errp, ACL_ATTR_IP, (void **)&client_addr, subject, resource, auth_info, global_auth);
  438. if (rv != LAS_EVAL_TRUE) {
  439. if (subject || resource) {
  440. /* Don't ereport if called from ACL_CachableAclList */
  441. char rv_str[16];
  442. sprintf(rv_str, "%d", rv);
  443. nserrGenerate(errp, ACLERRINVAL, ACLERR5220, ACL_Program, 2,
  444. XP_GetAdminStr(DBT_lasipevalUnableToGetSessionAddre_), rv_str);
  445. }
  446. return LAS_EVAL_FAIL;
  447. }
  448. #else
  449. ip = (IPAddr_t)LASIpGetIp();
  450. #endif
  451. /*
  452. * If this is the first time through, build the pattern tree first.
  453. */
  454. if (*LAS_cookie == NULL) {
  455. if (strcspn(attr_pattern, "0123456789.*,+ \tABCDEFabcdef:/")) {
  456. return LAS_EVAL_INVALID;
  457. }
  458. ACL_CritEnter();
  459. if (*LAS_cookie == NULL) { /* must check again */
  460. *LAS_cookie = context =
  461. (LASIpContext_t *)PERM_MALLOC(sizeof(LASIpContext_t));
  462. if (context == NULL) {
  463. nserrGenerate(errp, ACLERRNOMEM, ACLERR5230, ACL_Program, 1,
  464. XP_GetAdminStr(DBT_lasipevalUnableToAllocateContext_));
  465. ACL_CritExit();
  466. return LAS_EVAL_FAIL;
  467. }
  468. context->treetop = NULL;
  469. context->treetop_ipv6 = NULL;
  470. retcode = LASIpBuild(errp, attr_name, comparator, attr_pattern, context);
  471. if (retcode) {
  472. ACL_CritExit();
  473. return (retcode);
  474. }
  475. } else {
  476. context = (LASIpContext *) *LAS_cookie;
  477. }
  478. ACL_CritExit();
  479. } else {
  480. ACL_CritEnter();
  481. context = (LASIpContext *) *LAS_cookie;
  482. ACL_CritExit();
  483. }
  484. /*
  485. * Check if IP is ipv4/ipv6
  486. */
  487. if ( PR_IsNetAddrType( client_addr, PR_IpAddrV4Mapped) || client_addr->raw.family == PR_AF_INET ) {
  488. /*
  489. * IPv4
  490. */
  491. /* Set the appropriate s_addr for ipv4 or ipv4 mapped to ipv6 */
  492. if (client_addr->raw.family == PR_AF_INET) {
  493. client_inaddr.s_addr = client_addr->inet.ip;
  494. } else {
  495. client_inaddr.s_addr = client_addr->ipv6.ip._S6_un._S6_u32[3];
  496. }
  497. node = context->treetop;
  498. ip = (IPAddr_t)PR_ntohl( client_inaddr.s_addr );
  499. if(node == NULL){
  500. rc = (comparator == CMP_OP_EQ ? LAS_EVAL_FALSE : LAS_EVAL_TRUE);
  501. } else {
  502. for (bit = 31; bit >= 0; bit--) {
  503. value = (ip & (IPAddr_t) (1 << bit)) ? 1 : 0;
  504. if (LAS_IP_IS_CONSTANT(node->action[value])){
  505. /* Reached a result, so return it */
  506. if (comparator == CMP_OP_EQ){
  507. rc = (int)(PRSize)node->action[value];
  508. break;
  509. } else {
  510. rc = ((int)(PRSize)node->action[value] == LAS_EVAL_TRUE) ? LAS_EVAL_FALSE : LAS_EVAL_TRUE;
  511. break;
  512. }
  513. } else {
  514. /* Move on to the next bit */
  515. node = node->action[value];
  516. }
  517. }
  518. }
  519. if(rc == LAS_EVAL_INVALID){
  520. sprintf(ip_str, "%x", (unsigned int)ip);
  521. nserrGenerate(errp, ACLERRINTERNAL, ACLERR5240, ACL_Program, 2,
  522. XP_GetAdminStr(DBT_lasipevalReach32BitsWithoutConcl_), ip_str);
  523. }
  524. } else {
  525. /*
  526. * IPv6
  527. */
  528. PRIPv6Addr *ipv6 = &(client_addr->ipv6.ip);
  529. LASIpTree_t *node;
  530. int bit_position = 15;
  531. int field = 0;
  532. int addr = 0;
  533. int value;
  534. node = context->treetop_ipv6;
  535. if ( node == NULL ) {
  536. retcode = (comparator == CMP_OP_EQ ? LAS_EVAL_FALSE : LAS_EVAL_TRUE);
  537. } else {
  538. addr = PR_ntohs( ipv6->_S6_un._S6_u16[field]);
  539. for (bit = 127; bit >= 0 ; bit--, bit_position--) {
  540. value = (addr & (1 << bit_position)) ? 1 : 0;
  541. if (LAS_IP_IS_CONSTANT(node->action[value])) {
  542. /* Reached a result, so return it */
  543. if (comparator == CMP_OP_EQ){
  544. return(int)(long)node->action[value];
  545. } else {
  546. return(((int)(long)node->action[value] == LAS_EVAL_TRUE) ? LAS_EVAL_FALSE : LAS_EVAL_TRUE);
  547. }
  548. } else {
  549. node = node->action[value];
  550. if ( bit % 16 == 0) {
  551. /* Ok, move to the next field in the IPv6 addr: f:f:next:f:f:f:f:f */
  552. field++;
  553. addr = PR_ntohs( ipv6->_S6_un._S6_u16[field]);
  554. bit_position = 15;
  555. }
  556. }
  557. }
  558. rc = LAS_EVAL_INVALID;
  559. }
  560. }
  561. return rc;
  562. }
  563. /*
  564. * The ipv6 version of LASIpAddPattern
  565. */
  566. static int
  567. LASIpAddPatternIPv6(NSErr_t *errp, int netmask, PRIPv6Addr *ipv6, LASIpTree_t **treetop)
  568. {
  569. LASIpTree_t *curptr;
  570. LASIpTree_t *newptr;
  571. int stopbit;
  572. int curbit;
  573. int curval;
  574. int field = 0; /* (8) 16 bit fields in a IPv6 address: x:x:x:x:x:x:x:x */
  575. int addr = 0;
  576. int curbit_position = 15; /* 16 bits: 0-15 */
  577. /* stop at the first 1 in the netmask from low to high */
  578. stopbit = 128 - netmask;
  579. /* Special case if there's no tree. Allocate the first node */
  580. if (*treetop == (LASIpTree_t *)NULL) { /* No tree at all */
  581. curptr = LASIpTreeAllocNode(errp);
  582. if (curptr == NULL) {
  583. nserrGenerate(errp, ACLERRFAIL, ACLERR5100, ACL_Program, 1,
  584. XP_GetAdminStr(DBT_ipLasUnableToAllocateTreeNodeN_));
  585. return ACL_RES_ERROR;
  586. }
  587. *treetop = curptr;
  588. }
  589. addr = PR_ntohs(ipv6->_S6_un._S6_u16[field]);
  590. for (curbit = 127, curptr = *treetop; curbit >= 0; curbit--, curbit_position--){
  591. /* Is the current bit ON? If so set curval to 1 else 0 */
  592. curval = (addr & (1 << curbit_position)) ? 1 : 0;
  593. /* Are we done, if so remove the rest of the tree */
  594. if (curbit == stopbit) {
  595. LASIpTreeDealloc(curptr->action[curval]);
  596. curptr->action[curval] = (LASIpTree_t *)LAS_EVAL_TRUE;
  597. /* This is the normal exit point. Most other exits must be due to errors. */
  598. return 0;
  599. }
  600. /* Oops reached the end - must allocate */
  601. if (LAS_IP_IS_CONSTANT(curptr->action[curval])) {
  602. newptr = LASIpTreeAllocNode(errp);
  603. if (newptr == NULL) {
  604. LASIpTreeDealloc(*treetop);
  605. nserrGenerate(errp, ACLERRFAIL, ACLERR5110, ACL_Program, 1,
  606. XP_GetAdminStr(DBT_ipLasUnableToAllocateTreeNodeN_1));
  607. return ACL_RES_ERROR;
  608. }
  609. curptr->action[curval] = newptr;
  610. }
  611. /* Keep going down the tree */
  612. curptr = curptr->action[curval];
  613. if ( curbit % 16 == 0) {
  614. /* Ok, move to the next field in the addr */
  615. field++;
  616. addr = PR_ntohs(ipv6->_S6_un._S6_u16[field]);
  617. curbit_position = 15;
  618. }
  619. }
  620. return ACL_RES_ERROR;
  621. }
  622. /*
  623. * This is very similar to dotdecimal(), but for ipv6 addresses
  624. */
  625. static int
  626. colonhex_ipv6(char *ipstr, const char *netmaskstr, PRIPv6Addr *ipv6, int *netmask)
  627. {
  628. PRNetAddr addr;
  629. /*
  630. * Validate netmaskstr - can only be digits
  631. */
  632. if (strcspn(netmaskstr, "0123456789")){
  633. return LAS_EVAL_INVALID;
  634. }
  635. /*
  636. * Validate ipstr - can only have digits, colons, hex chars, and dots
  637. */
  638. if(strcspn(ipstr, "0123456789:ABCDEFabcdef.")){
  639. return LAS_EVAL_INVALID;
  640. }
  641. /*
  642. * validate the netmask - must be between 1 and 128
  643. */
  644. *netmask = atoi(netmaskstr);
  645. if(*netmask < 1 || *netmask > 128){
  646. return LAS_EVAL_INVALID;
  647. }
  648. /*
  649. * Get the net addr
  650. */
  651. if (PR_StringToNetAddr(ipstr, &addr) != PR_SUCCESS){
  652. return LAS_EVAL_INVALID;
  653. }
  654. /*
  655. * Set the ipv6 addr
  656. */
  657. *ipv6 = addr.ipv6.ip;
  658. return 0;
  659. }