lasip.cpp 26 KB

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