1
0

lasip.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2021 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. if (!curptr) {
  241. return LAS_EVAL_INVALID;
  242. }
  243. delimiter = strcspn(curptr, ", \t");
  244. delimiter = (delimiter <= strlen(curptr)) ? delimiter : strlen(curptr);
  245. if (delimiter >= sizeof(token2)) {
  246. return LAS_EVAL_INVALID;
  247. }
  248. strncpy(token2, curptr, delimiter);
  249. token2[delimiter] = '\0';
  250. retcode = dotdecimal(token, token2, &ip, &netmask);
  251. if (retcode)
  252. return (retcode);
  253. curptr = strpbrk((++curptr), "1234567890+.*");
  254. } else {
  255. retcode = dotdecimal(token, "255.255.255.255", &ip, &netmask);
  256. if (retcode)
  257. return (retcode);
  258. }
  259. } else {
  260. /* token is the IP addr string in both cases */
  261. *plusptr ='\0'; /* truncate the string */
  262. retcode =dotdecimal(token, ++plusptr, &ip, &netmask);
  263. if (retcode)
  264. return (retcode);
  265. }
  266. if (LASIpAddPattern(errp, netmask, ip, &context->treetop) != 0)
  267. return LAS_EVAL_INVALID;
  268. } else {
  269. /*
  270. * IPv6
  271. */
  272. PRIPv6Addr ipv6;
  273. plusptr = strchr(token, '/');
  274. if (plusptr == NULL) {
  275. if (curptr && (*curptr == '/')) {
  276. /* There was a space before (and possibly after) the plus sign */
  277. curptr = strpbrk((++curptr), "1234567890.*:ABCDEFabcdef");
  278. if (!curptr) {
  279. return LAS_EVAL_INVALID;
  280. }
  281. delimiter = strcspn(curptr, ", \t");
  282. delimiter = (delimiter <= strlen(curptr)) ? delimiter : strlen(curptr);
  283. strncpy(token2, curptr, delimiter);
  284. token2[delimiter] = '\0';
  285. retcode = colonhex_ipv6(token, token2, &ipv6, &netmask);
  286. if (retcode)
  287. return (retcode);
  288. curptr = strpbrk((++curptr), "1234567890+.:ABCDEFabcdef*");
  289. } else {
  290. retcode = colonhex_ipv6(token, "128", &ipv6, &netmask);
  291. if (retcode)
  292. return (retcode);
  293. }
  294. } else {
  295. /* token is the IP addr string in both cases */
  296. *plusptr ='\0'; /* truncate the string */
  297. retcode = colonhex_ipv6(token, ++plusptr, &ipv6, &netmask);
  298. if (retcode)
  299. return (retcode);
  300. }
  301. if (LASIpAddPatternIPv6(errp, netmask, &ipv6, &context->treetop_ipv6) != 0) {
  302. return LAS_EVAL_INVALID;
  303. }
  304. }
  305. } while ((curptr != NULL) && (delimiter != 0));
  306. return 0;
  307. }
  308. /* LASIpAddPattern
  309. * Takes a netmask and IP address and a pointer to an existing IP
  310. * tree and adds nodes as appropriate to recognize the new pattern.
  311. * INPUT
  312. * netmask e.g. 0xffffff00
  313. * pattern IP address in 4 bytes
  314. * *treetop An existing IP tree or 0 if a new tree
  315. * RETURNS
  316. * ret code NULL on success, ACL_RES_ERROR on failure
  317. * **treetop If this is a new tree, the head of the tree.
  318. */
  319. static int
  320. LASIpAddPattern(NSErr_t *errp, int netmask, int pattern, LASIpTree_t **treetop)
  321. {
  322. int stopbit; /* Don't care after this point */
  323. int curbit; /* current bit we're working on */
  324. int curval; /* value of pattern[curbit] */
  325. LASIpTree_t *curptr = NULL; /* pointer to the current node */
  326. LASIpTree_t *newptr;
  327. if (NULL == treetop) {
  328. return ACL_RES_ERROR;
  329. }
  330. /* stop at the first 1 in the netmask from low to high */
  331. for (stopbit=0; stopbit<32; stopbit++) {
  332. if ((netmask&(1<<stopbit)) != 0)
  333. break;
  334. }
  335. /* Special case if there's no tree. Allocate the first node */
  336. if (*treetop == (LASIpTree_t *)NULL) { /* No tree at all */
  337. curptr = LASIpTreeAllocNode(errp);
  338. if (curptr == NULL) {
  339. nserrGenerate(errp, ACLERRFAIL, ACLERR5100, ACL_Program, 1,
  340. XP_GetAdminStr(DBT_ipLasUnableToAllocateTreeNodeN_));
  341. return ACL_RES_ERROR;
  342. }
  343. *treetop = curptr;
  344. }
  345. /*
  346. * Special case if the netmask is 0.
  347. */
  348. if (stopbit > 31) {
  349. (*treetop)->action[0] = (LASIpTree_t *)LAS_EVAL_TRUE;
  350. (*treetop)->action[1] = (LASIpTree_t *)LAS_EVAL_TRUE;
  351. return 0;
  352. }
  353. /* follow the tree down the pattern path bit by bit until the
  354. * end of the tree is reached (i.e. a constant).
  355. */
  356. for (curbit=31,curptr=*treetop; curbit >= 0; curbit--) {
  357. /* Is the current bit ON? If so set curval to 1 else 0 */
  358. curval = (pattern & (1<<curbit)) ? 1 : 0;
  359. /* Are we done, if so remove the rest of the tree */
  360. if (curbit == stopbit) {
  361. LASIpTreeDealloc(curptr->action[curval]);
  362. curptr->action[curval] = (LASIpTree_t *)LAS_EVAL_TRUE;
  363. /* This is the normal exit point. Most other exits must be due to errors. */
  364. return 0;
  365. }
  366. /* Oops reached the end - must allocate */
  367. if (LAS_IP_IS_CONSTANT(curptr->action[curval])) {
  368. newptr = LASIpTreeAllocNode(errp);
  369. if (newptr == NULL) {
  370. LASIpTreeDealloc(*treetop);
  371. nserrGenerate(errp, ACLERRFAIL, ACLERR5110, ACL_Program, 1,
  372. XP_GetAdminStr(DBT_ipLasUnableToAllocateTreeNodeN_1));
  373. return ACL_RES_ERROR;
  374. }
  375. curptr->action[curval] = newptr;
  376. }
  377. /* Keep going down the tree */
  378. curptr = curptr->action[curval];
  379. }
  380. return ACL_RES_ERROR;
  381. }
  382. /* LASIpFlush
  383. * Deallocates any memory previously allocated by the LAS
  384. */
  385. void
  386. LASIpFlush(void **las_cookie)
  387. {
  388. if (*las_cookie == NULL)
  389. return;
  390. LASIpTreeDealloc(((LASIpContext_t *)*las_cookie)->treetop);
  391. LASIpTreeDealloc(((LASIpContext_t *)*las_cookie)->treetop_ipv6);
  392. PERM_FREE(*las_cookie);
  393. *las_cookie = NULL;
  394. return;
  395. }
  396. /*
  397. * LASIpEval
  398. * INPUT
  399. * attr_name The string "ip" - in lower case.
  400. * comparator CMP_OP_EQ or CMP_OP_NE only
  401. * attr_pattern A comma-separated list of IP addresses and netmasks
  402. * in dotted-decimal form. Netmasks are optionally
  403. * prepended to the IP address using a plus sign. E.g.
  404. * 255.255.255.0+123.45.67.89. Any byte in the IP address
  405. * (but not the netmask) can be wildcarded using "*"
  406. * *cachable Always set to ACL_INDEF_CACHABLE
  407. * subject Subject property list
  408. * resource Resource property list
  409. * auth_info The authentication info if any
  410. * RETURNS
  411. * ret code The usual LAS return codes.
  412. */
  413. int LASIpEval(NSErr_t *errp, char *attr_name, CmpOp_t comparator,
  414. char *attr_pattern, ACLCachable_t *cachable, void **LAS_cookie,
  415. PList_t subject, PList_t resource, PList_t auth_info,
  416. PList_t global_auth)
  417. {
  418. LASIpContext_t *context = NULL;
  419. IPAddr_t ip;
  420. PRNetAddr *client_addr = NULL;
  421. struct in_addr client_inaddr;
  422. char ip_str[124];
  423. int retcode;
  424. int bit;
  425. int rc = LAS_EVAL_INVALID;
  426. int rv;
  427. *cachable = ACL_INDEF_CACHABLE;
  428. if (strcmp(attr_name, "ip") != 0) {
  429. nserrGenerate(errp, ACLERRINVAL, ACLERR5200, ACL_Program, 2,
  430. XP_GetAdminStr(DBT_lasIpBuildReceivedRequestForAttr_), attr_name);
  431. return LAS_EVAL_INVALID;
  432. }
  433. if ((comparator != CMP_OP_EQ) && (comparator != CMP_OP_NE)) {
  434. nserrGenerate(errp, ACLERRINVAL, ACLERR5210, ACL_Program, 2,
  435. XP_GetAdminStr(DBT_lasipevalIllegalComparatorDN_), comparator_string(comparator));
  436. return LAS_EVAL_INVALID;
  437. }
  438. /*
  439. * Get the IP addr from the session context, and store it in "client_addr
  440. */
  441. #ifndef UTEST
  442. rv = ACL_GetAttribute(errp, ACL_ATTR_IP, (void **)&client_addr, subject, resource, auth_info, global_auth);
  443. if (rv != LAS_EVAL_TRUE) {
  444. if (subject || resource) {
  445. /* Don't ereport if called from ACL_CachableAclList */
  446. char rv_str[16];
  447. sprintf(rv_str, "%d", rv);
  448. nserrGenerate(errp, ACLERRINVAL, ACLERR5220, ACL_Program, 2,
  449. XP_GetAdminStr(DBT_lasipevalUnableToGetSessionAddre_), rv_str);
  450. }
  451. return LAS_EVAL_FAIL;
  452. }
  453. #else
  454. ip = (IPAddr_t)LASIpGetIp();
  455. #endif
  456. /*
  457. * If this is the first time through, build the pattern tree first.
  458. */
  459. if (*LAS_cookie == NULL) {
  460. if (strcspn(attr_pattern, "0123456789.*,+ \tABCDEFabcdef:/")) {
  461. return LAS_EVAL_INVALID;
  462. }
  463. ACL_CritEnter();
  464. if (*LAS_cookie == NULL) { /* must check again */
  465. *LAS_cookie = context =
  466. (LASIpContext_t *)PERM_MALLOC(sizeof(LASIpContext_t));
  467. if (context == NULL) {
  468. nserrGenerate(errp, ACLERRNOMEM, ACLERR5230, ACL_Program, 1,
  469. XP_GetAdminStr(DBT_lasipevalUnableToAllocateContext_));
  470. ACL_CritExit();
  471. return LAS_EVAL_FAIL;
  472. }
  473. context->treetop = NULL;
  474. context->treetop_ipv6 = NULL;
  475. retcode = LASIpBuild(errp, attr_name, comparator, attr_pattern, context);
  476. if (retcode) {
  477. ACL_CritExit();
  478. return (retcode);
  479. }
  480. } else {
  481. context = (LASIpContext *) *LAS_cookie;
  482. }
  483. ACL_CritExit();
  484. } else {
  485. ACL_CritEnter();
  486. context = (LASIpContext *) *LAS_cookie;
  487. ACL_CritExit();
  488. }
  489. /*
  490. * Check if IP is ipv4/ipv6
  491. */
  492. if ( PR_IsNetAddrType( client_addr, PR_IpAddrV4Mapped) || client_addr->raw.family == PR_AF_INET ) {
  493. /*
  494. * IPv4
  495. */
  496. /* Set the appropriate s_addr for ipv4 or ipv4 mapped to ipv6 */
  497. if (client_addr->raw.family == PR_AF_INET) {
  498. client_inaddr.s_addr = client_addr->inet.ip;
  499. } else {
  500. client_inaddr.s_addr = client_addr->ipv6.ip._S6_un._S6_u32[3];
  501. }
  502. LASIpTree_t *node = context->treetop;
  503. ip = (IPAddr_t)PR_ntohl( client_inaddr.s_addr );
  504. if(node == NULL){
  505. rc = (comparator == CMP_OP_EQ ? LAS_EVAL_FALSE : LAS_EVAL_TRUE);
  506. } else {
  507. for (bit = 31; bit >= 0; bit--) {
  508. int value = (ip & (IPAddr_t) (1 << bit)) ? 1 : 0;
  509. if (LAS_IP_IS_CONSTANT(node->action[value])){
  510. /* Reached a result, so return it */
  511. if (comparator == CMP_OP_EQ){
  512. rc = (int)(PRSize)node->action[value];
  513. break;
  514. } else {
  515. rc = ((int)(PRSize)node->action[value] == LAS_EVAL_TRUE) ? LAS_EVAL_FALSE : LAS_EVAL_TRUE;
  516. break;
  517. }
  518. } else {
  519. /* Move on to the next bit */
  520. node = node->action[value];
  521. }
  522. }
  523. }
  524. if(rc == LAS_EVAL_INVALID){
  525. sprintf(ip_str, "%x", (unsigned int)ip);
  526. nserrGenerate(errp, ACLERRINTERNAL, ACLERR5240, ACL_Program, 2,
  527. XP_GetAdminStr(DBT_lasipevalReach32BitsWithoutConcl_), ip_str);
  528. }
  529. } else {
  530. /*
  531. * IPv6
  532. */
  533. PRIPv6Addr *ipv6 = &(client_addr->ipv6.ip);
  534. LASIpTree_t *node;
  535. int bit_position = 15;
  536. int field = 0;
  537. int addr = 0;
  538. node = context->treetop_ipv6;
  539. if ( node == NULL ) {
  540. rc = (comparator == CMP_OP_EQ ? LAS_EVAL_FALSE : LAS_EVAL_TRUE);
  541. } else {
  542. addr = PR_ntohs( ipv6->_S6_un._S6_u16[field]);
  543. for (bit = 127; bit >= 0 ; bit--, bit_position--) {
  544. int value = (addr & (1 << bit_position)) ? 1 : 0;
  545. if (LAS_IP_IS_CONSTANT(node->action[value])) {
  546. /* Reached a result, so return it */
  547. if (comparator == CMP_OP_EQ){
  548. return(int)(long)node->action[value];
  549. } else {
  550. return(((int)(long)node->action[value] == LAS_EVAL_TRUE) ? LAS_EVAL_FALSE : LAS_EVAL_TRUE);
  551. }
  552. } else {
  553. node = node->action[value];
  554. if ( bit % 16 == 0) {
  555. /* Ok, move to the next field in the IPv6 addr: f:f:next:f:f:f:f:f */
  556. field++;
  557. addr = PR_ntohs( ipv6->_S6_un._S6_u16[field]);
  558. bit_position = 15;
  559. }
  560. }
  561. }
  562. rc = LAS_EVAL_INVALID;
  563. }
  564. }
  565. return rc;
  566. }
  567. /*
  568. * The ipv6 version of LASIpAddPattern
  569. */
  570. static int
  571. LASIpAddPatternIPv6(NSErr_t *errp, int netmask, PRIPv6Addr *ipv6, LASIpTree_t **treetop)
  572. {
  573. LASIpTree_t *curptr;
  574. LASIpTree_t *newptr;
  575. int stopbit;
  576. int curbit;
  577. int curval;
  578. int field = 0; /* (8) 16 bit fields in a IPv6 address: x:x:x:x:x:x:x:x */
  579. int addr = 0;
  580. int curbit_position = 15; /* 16 bits: 0-15 */
  581. /* stop at the first 1 in the netmask from low to high */
  582. stopbit = 128 - netmask;
  583. /* Special case if there's no tree. Allocate the first node */
  584. if (*treetop == (LASIpTree_t *)NULL) { /* No tree at all */
  585. curptr = LASIpTreeAllocNode(errp);
  586. if (curptr == NULL) {
  587. nserrGenerate(errp, ACLERRFAIL, ACLERR5100, ACL_Program, 1,
  588. XP_GetAdminStr(DBT_ipLasUnableToAllocateTreeNodeN_));
  589. return ACL_RES_ERROR;
  590. }
  591. *treetop = curptr;
  592. }
  593. addr = PR_ntohs(ipv6->_S6_un._S6_u16[field]);
  594. for (curbit = 127, curptr = *treetop; curbit >= 0; curbit--, curbit_position--){
  595. /* Is the current bit ON? If so set curval to 1 else 0 */
  596. curval = (addr & (1 << curbit_position)) ? 1 : 0;
  597. /* Are we done, if so remove the rest of the tree */
  598. if (curbit == stopbit) {
  599. LASIpTreeDealloc(curptr->action[curval]);
  600. curptr->action[curval] = (LASIpTree_t *)LAS_EVAL_TRUE;
  601. /* This is the normal exit point. Most other exits must be due to errors. */
  602. return 0;
  603. }
  604. /* Oops reached the end - must allocate */
  605. if (LAS_IP_IS_CONSTANT(curptr->action[curval])) {
  606. newptr = LASIpTreeAllocNode(errp);
  607. if (newptr == NULL) {
  608. LASIpTreeDealloc(*treetop);
  609. nserrGenerate(errp, ACLERRFAIL, ACLERR5110, ACL_Program, 1,
  610. XP_GetAdminStr(DBT_ipLasUnableToAllocateTreeNodeN_1));
  611. return ACL_RES_ERROR;
  612. }
  613. curptr->action[curval] = newptr;
  614. }
  615. /* Keep going down the tree */
  616. curptr = curptr->action[curval];
  617. if ( curbit % 16 == 0) {
  618. /* Ok, move to the next field in the addr */
  619. field++;
  620. addr = PR_ntohs(ipv6->_S6_un._S6_u16[field]);
  621. curbit_position = 15;
  622. }
  623. }
  624. return ACL_RES_ERROR;
  625. }
  626. /*
  627. * This is very similar to dotdecimal(), but for ipv6 addresses
  628. */
  629. static int
  630. colonhex_ipv6(char *ipstr, const char *netmaskstr, PRIPv6Addr *ipv6, int *netmask)
  631. {
  632. PRNetAddr addr;
  633. /*
  634. * Validate netmaskstr - can only be digits
  635. */
  636. if (strcspn(netmaskstr, "0123456789")){
  637. return LAS_EVAL_INVALID;
  638. }
  639. /*
  640. * Validate ipstr - can only have digits, colons, hex chars, and dots
  641. */
  642. if(strcspn(ipstr, "0123456789:ABCDEFabcdef.")){
  643. return LAS_EVAL_INVALID;
  644. }
  645. /*
  646. * validate the netmask - must be between 1 and 128
  647. */
  648. *netmask = atoi(netmaskstr);
  649. if(*netmask < 1 || *netmask > 128){
  650. return LAS_EVAL_INVALID;
  651. }
  652. /*
  653. * Get the net addr
  654. */
  655. if (PR_StringToNetAddr(ipstr, &addr) != PR_SUCCESS){
  656. return LAS_EVAL_INVALID;
  657. }
  658. /*
  659. * Set the ipv6 addr
  660. */
  661. *ipv6 = addr.ipv6.ip;
  662. return 0;
  663. }