lasip.cpp 24 KB

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