test_acl.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2010, Digium, Inc.
  5. *
  6. * Mark Michelson <mmichelson@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*!
  19. * \file
  20. * \brief ACL unit tests
  21. *
  22. * \author Mark Michelson <mmichelson@digium.com>
  23. *
  24. */
  25. /*** MODULEINFO
  26. <depend>TEST_FRAMEWORK</depend>
  27. <support_level>core</support_level>
  28. ***/
  29. #include "asterisk.h"
  30. #include "asterisk/test.h"
  31. #include "asterisk/acl.h"
  32. #include "asterisk/module.h"
  33. #include "asterisk/netsock2.h"
  34. #include "asterisk/config.h"
  35. AST_TEST_DEFINE(invalid_acl)
  36. {
  37. const char * invalid_acls[] = {
  38. /* Negative netmask */
  39. "1.3.3.7/-1",
  40. /* Netmask too large */
  41. "1.3.3.7/33",
  42. /* Netmask waaaay too large */
  43. "1.3.3.7/92342348927389492307420",
  44. /* Netmask non-numeric */
  45. "1.3.3.7/California",
  46. /* Too many octets in Netmask */
  47. "1.3.3.7/255.255.255.255.255",
  48. /* Octets in IP address exceed 255 */
  49. "57.60.278.900/31",
  50. /* Octets in IP address exceed 255 and are negative */
  51. "400.32.201029.-6/24",
  52. /* Invalidly formatted IP address */
  53. "EGGSOFDEATH/4000",
  54. /* Too many octets in IP address */
  55. "33.4.7.8.3/300030",
  56. /* Too many octets in Netmask */
  57. "1.2.3.4/6.7.8.9.0",
  58. /* Too many octets in IP address */
  59. "3.1.4.1.5.9/3",
  60. /* IPv6 address has multiple double colons */
  61. "ff::ff::ff/3",
  62. /* IPv6 address is too long */
  63. "1234:5678:90ab:cdef:1234:5678:90ab:cdef:1234/56",
  64. /* IPv6 netmask is too large */
  65. "::ffff/129",
  66. /* IPv4-mapped IPv6 address has too few octets */
  67. "::ffff:255.255.255/128",
  68. /* Leading and trailing colons for IPv6 address */
  69. ":1234:/15",
  70. /* IPv6 address and IPv4 netmask */
  71. "fe80::1234/255.255.255.0",
  72. };
  73. enum ast_test_result_state res = AST_TEST_PASS;
  74. struct ast_ha *ha = NULL;
  75. int i;
  76. switch (cmd) {
  77. case TEST_INIT:
  78. info->name = "invalid_acl";
  79. info->category = "/main/acl/";
  80. info->summary = "Invalid ACL unit test";
  81. info->description =
  82. "Ensures that garbage ACL values are not accepted";
  83. return AST_TEST_NOT_RUN;
  84. case TEST_EXECUTE:
  85. break;
  86. }
  87. for (i = 0; i < ARRAY_LEN(invalid_acls); ++i) {
  88. int err = 0;
  89. ha = ast_append_ha("permit", invalid_acls[i], ha, &err);
  90. if (ha || !err) {
  91. ast_test_status_update(test, "ACL %s accepted even though it is total garbage.\n",
  92. invalid_acls[i]);
  93. if (ha) {
  94. ast_free_ha(ha);
  95. }
  96. res = AST_TEST_FAIL;
  97. }
  98. }
  99. return res;
  100. }
  101. struct acl {
  102. const char *host;
  103. const char *access;
  104. };
  105. /* These constants are defined for the sole purpose of being shorter
  106. * than their real names. It makes lines in this test quite a bit shorter
  107. */
  108. #define TACL_A AST_SENSE_ALLOW
  109. #define TACL_D AST_SENSE_DENY
  110. static int build_ha(const struct acl *acl, size_t len, struct ast_ha **ha, const char *acl_name, int *err, struct ast_test *test, enum ast_test_result_state *res)
  111. {
  112. size_t i;
  113. for (i = 0; i < len; ++i) {
  114. if (!(*ha = ast_append_ha(acl[i].access, acl[i].host, *ha, err))) {
  115. ast_test_status_update(test, "Failed to add rule %s with access %s to %s\n",
  116. acl[i].host, acl[i].access, acl_name);
  117. *res = AST_TEST_FAIL;
  118. return -1;
  119. }
  120. }
  121. return 0;
  122. }
  123. AST_TEST_DEFINE(acl)
  124. {
  125. struct acl permitallv4 = { "0.0.0.0/0", "permit" };
  126. struct acl denyallv4 = { "0.0.0.0/0", "deny" };
  127. struct acl permitallv6 = { "::/0", "permit" };
  128. struct acl denyallv6 = { "::/0", "deny" };
  129. struct acl acl1[] = {
  130. { "0.0.0.0/0.0.0.0", "deny" },
  131. { "10.0.0.0/255.0.0.0", "permit" },
  132. { "192.168.0.0/255.255.255.0", "permit" },
  133. };
  134. struct acl acl2[] = {
  135. { "10.0.0.0/8", "deny" },
  136. { "10.0.0.0/8", "permit" },
  137. { "10.0.0.0/16", "deny" },
  138. { "10.0.0.0/24", "permit" },
  139. };
  140. struct acl acl3[] = {
  141. { "::/0", "deny" },
  142. { "fe80::/64", "permit" },
  143. };
  144. struct acl acl4[] = {
  145. { "::/0", "deny" },
  146. { "fe80::/64", "permit" },
  147. { "fe80::ffff:0:0:0/80", "deny" },
  148. { "fe80::ffff:0:ffff:0/112", "permit" },
  149. };
  150. struct acl acl5[] = {
  151. { "0.0.0.0/0.0.0.0", "deny" },
  152. { "10.0.0.0/255.0.0.0,192.168.0.0/255.255.255.0", "permit" },
  153. };
  154. struct acl acl6[] = {
  155. { "10.0.0.0/8", "deny" },
  156. { "10.0.0.0/8", "permit" },
  157. { "10.0.0.0/16,!10.0.0.0/24", "deny" },
  158. };
  159. struct acl acl7[] = {
  160. { "::/0,!fe80::/64", "deny" },
  161. { "fe80::ffff:0:0:0/80", "deny" },
  162. { "fe80::ffff:0:ffff:0/112", "permit" },
  163. };
  164. struct {
  165. const char *test_address;
  166. int v4_permitall_result;
  167. int v4_denyall_result;
  168. int v6_permitall_result;
  169. int v6_denyall_result;
  170. int acl1_result;
  171. int acl2_result;
  172. int acl3_result;
  173. int acl4_result;
  174. int acl5_result;
  175. int acl6_result;
  176. int acl7_result;
  177. } acl_tests[] = {
  178. { "10.1.1.5", TACL_A, TACL_D, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A },
  179. { "192.168.0.5", TACL_A, TACL_D, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A },
  180. { "192.168.1.5", TACL_A, TACL_D, TACL_A, TACL_A, TACL_D, TACL_A, TACL_A, TACL_A, TACL_D, TACL_A, TACL_A },
  181. { "10.0.0.1", TACL_A, TACL_D, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A },
  182. { "10.0.10.10", TACL_A, TACL_D, TACL_A, TACL_A, TACL_A, TACL_D, TACL_A, TACL_A, TACL_A, TACL_D, TACL_A },
  183. { "172.16.0.1", TACL_A, TACL_D, TACL_A, TACL_A, TACL_D, TACL_A, TACL_A, TACL_A, TACL_D, TACL_A, TACL_A },
  184. { "fe80::1234", TACL_A, TACL_A, TACL_A, TACL_D, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A },
  185. { "fe80::ffff:1213:dead:beef", TACL_A, TACL_A, TACL_A, TACL_D, TACL_A, TACL_A, TACL_A, TACL_D, TACL_A, TACL_A, TACL_D },
  186. { "fe80::ffff:0:ffff:ABCD", TACL_A, TACL_A, TACL_A, TACL_D, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A },
  187. };
  188. struct ast_ha *permit_hav4 = NULL;
  189. struct ast_ha *deny_hav4 = NULL;
  190. struct ast_ha *permit_hav6 = NULL;
  191. struct ast_ha *deny_hav6 = NULL;
  192. struct ast_ha *ha1 = NULL;
  193. struct ast_ha *ha2 = NULL;
  194. struct ast_ha *ha3 = NULL;
  195. struct ast_ha *ha4 = NULL;
  196. struct ast_ha *ha5 = NULL;
  197. struct ast_ha *ha6 = NULL;
  198. struct ast_ha *ha7 = NULL;
  199. enum ast_test_result_state res = AST_TEST_PASS;
  200. int err = 0;
  201. int i;
  202. switch (cmd) {
  203. case TEST_INIT:
  204. info->name = "acl";
  205. info->category = "/main/acl/";
  206. info->summary = "ACL unit test";
  207. info->description =
  208. "Tests that hosts are properly permitted or denied";
  209. return AST_TEST_NOT_RUN;
  210. case TEST_EXECUTE:
  211. break;
  212. }
  213. if (!(permit_hav4 = ast_append_ha(permitallv4.access, permitallv4.host, permit_hav4, &err))) {
  214. ast_test_status_update(test, "Failed to create permit_all ACL\n");
  215. res = AST_TEST_FAIL;
  216. goto acl_cleanup;
  217. }
  218. if (!(deny_hav4 = ast_append_ha(denyallv4.access, denyallv4.host, deny_hav4, &err))) {
  219. ast_test_status_update(test, "Failed to create deny_all ACL\n");
  220. res = AST_TEST_FAIL;
  221. goto acl_cleanup;
  222. }
  223. if (!(permit_hav6 = ast_append_ha(permitallv6.access, permitallv6.host, permit_hav6, &err))) {
  224. ast_test_status_update(test, "Failed to create permit_all ACL\n");
  225. res = AST_TEST_FAIL;
  226. goto acl_cleanup;
  227. }
  228. if (!(deny_hav6 = ast_append_ha(denyallv6.access, denyallv6.host, deny_hav6, &err))) {
  229. ast_test_status_update(test, "Failed to create deny_all ACL\n");
  230. res = AST_TEST_FAIL;
  231. goto acl_cleanup;
  232. }
  233. if (build_ha(acl1, ARRAY_LEN(acl1), &ha1, "ha1", &err, test, &res) != 0) {
  234. goto acl_cleanup;
  235. }
  236. if (build_ha(acl2, ARRAY_LEN(acl2), &ha2, "ha2", &err, test, &res) != 0) {
  237. goto acl_cleanup;
  238. }
  239. if (build_ha(acl3, ARRAY_LEN(acl3), &ha3, "ha3", &err, test, &res) != 0) {
  240. goto acl_cleanup;
  241. }
  242. if (build_ha(acl4, ARRAY_LEN(acl4), &ha4, "ha4", &err, test, &res) != 0) {
  243. goto acl_cleanup;
  244. }
  245. if (build_ha(acl5, ARRAY_LEN(acl5), &ha5, "ha5", &err, test, &res) != 0) {
  246. goto acl_cleanup;
  247. }
  248. if (build_ha(acl6, ARRAY_LEN(acl6), &ha6, "ha6", &err, test, &res) != 0) {
  249. goto acl_cleanup;
  250. }
  251. if (build_ha(acl7, ARRAY_LEN(acl7), &ha7, "ha7", &err, test, &res) != 0) {
  252. goto acl_cleanup;
  253. }
  254. for (i = 0; i < ARRAY_LEN(acl_tests); ++i) {
  255. struct ast_sockaddr addr;
  256. int permit_resv4;
  257. int permit_resv6;
  258. int deny_resv4;
  259. int deny_resv6;
  260. int acl1_res;
  261. int acl2_res;
  262. int acl3_res;
  263. int acl4_res;
  264. int acl5_res;
  265. int acl6_res;
  266. int acl7_res;
  267. ast_sockaddr_parse(&addr, acl_tests[i].test_address, PARSE_PORT_FORBID);
  268. permit_resv4 = ast_apply_ha(permit_hav4, &addr);
  269. deny_resv4 = ast_apply_ha(deny_hav4, &addr);
  270. permit_resv6 = ast_apply_ha(permit_hav6, &addr);
  271. deny_resv6 = ast_apply_ha(deny_hav6, &addr);
  272. acl1_res = ast_apply_ha(ha1, &addr);
  273. acl2_res = ast_apply_ha(ha2, &addr);
  274. acl3_res = ast_apply_ha(ha3, &addr);
  275. acl4_res = ast_apply_ha(ha4, &addr);
  276. acl5_res = ast_apply_ha(ha5, &addr);
  277. acl6_res = ast_apply_ha(ha6, &addr);
  278. acl7_res = ast_apply_ha(ha7, &addr);
  279. if (permit_resv4 != acl_tests[i].v4_permitall_result) {
  280. ast_test_status_update(test, "Access not as expected to %s on permitallv4. Expected %d but "
  281. "got %d instead\n", acl_tests[i].test_address, acl_tests[i].v4_permitall_result, permit_resv4);
  282. res = AST_TEST_FAIL;
  283. goto acl_cleanup;
  284. }
  285. if (deny_resv4 != acl_tests[i].v4_denyall_result) {
  286. ast_test_status_update(test, "Access not as expected to %s on denyallv4. Expected %d but "
  287. "got %d instead\n", acl_tests[i].test_address, acl_tests[i].v4_denyall_result, deny_resv4);
  288. res = AST_TEST_FAIL;
  289. goto acl_cleanup;
  290. }
  291. if (permit_resv6 != acl_tests[i].v6_permitall_result) {
  292. ast_test_status_update(test, "Access not as expected to %s on permitallv6. Expected %d but "
  293. "got %d instead\n", acl_tests[i].test_address, acl_tests[i].v6_permitall_result, permit_resv6);
  294. res = AST_TEST_FAIL;
  295. goto acl_cleanup;
  296. }
  297. if (deny_resv6 != acl_tests[i].v6_denyall_result) {
  298. ast_test_status_update(test, "Access not as expected to %s on denyallv6. Expected %d but "
  299. "got %d instead\n", acl_tests[i].test_address, acl_tests[i].v6_denyall_result, deny_resv6);
  300. res = AST_TEST_FAIL;
  301. goto acl_cleanup;
  302. }
  303. if (acl1_res != acl_tests[i].acl1_result) {
  304. ast_test_status_update(test, "Access not as expected to %s on acl1. Expected %d but "
  305. "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl1_result, acl1_res);
  306. res = AST_TEST_FAIL;
  307. goto acl_cleanup;
  308. }
  309. if (acl2_res != acl_tests[i].acl2_result) {
  310. ast_test_status_update(test, "Access not as expected to %s on acl2. Expected %d but "
  311. "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl2_result, acl2_res);
  312. res = AST_TEST_FAIL;
  313. goto acl_cleanup;
  314. }
  315. if (acl3_res != acl_tests[i].acl3_result) {
  316. ast_test_status_update(test, "Access not as expected to %s on acl3. Expected %d but "
  317. "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl3_result, acl3_res);
  318. res = AST_TEST_FAIL;
  319. goto acl_cleanup;
  320. }
  321. if (acl4_res != acl_tests[i].acl4_result) {
  322. ast_test_status_update(test, "Access not as expected to %s on acl4. Expected %d but "
  323. "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl4_result, acl4_res);
  324. res = AST_TEST_FAIL;
  325. goto acl_cleanup;
  326. }
  327. if (acl5_res != acl_tests[i].acl5_result) {
  328. ast_test_status_update(test, "Access not as expected to %s on acl5. Expected %d but "
  329. "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl5_result, acl5_res);
  330. res = AST_TEST_FAIL;
  331. goto acl_cleanup;
  332. }
  333. if (acl6_res != acl_tests[i].acl6_result) {
  334. ast_test_status_update(test, "Access not as expected to %s on acl6. Expected %d but "
  335. "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl6_result, acl6_res);
  336. res = AST_TEST_FAIL;
  337. goto acl_cleanup;
  338. }
  339. if (acl7_res != acl_tests[i].acl7_result) {
  340. ast_test_status_update(test, "Access not as expected to %s on acl7. Expected %d but "
  341. "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl7_result, acl7_res);
  342. res = AST_TEST_FAIL;
  343. goto acl_cleanup;
  344. }
  345. }
  346. acl_cleanup:
  347. if (permit_hav4) {
  348. ast_free_ha(permit_hav4);
  349. }
  350. if (deny_hav4) {
  351. ast_free_ha(deny_hav4);
  352. }
  353. if (permit_hav6) {
  354. ast_free_ha(permit_hav6);
  355. }
  356. if (deny_hav6) {
  357. ast_free_ha(deny_hav6);
  358. }
  359. if (ha1) {
  360. ast_free_ha(ha1);
  361. }
  362. if (ha2) {
  363. ast_free_ha(ha2);
  364. }
  365. if (ha3) {
  366. ast_free_ha(ha3);
  367. }
  368. if (ha4) {
  369. ast_free_ha(ha4);
  370. }
  371. if (ha5) {
  372. ast_free_ha(ha5);
  373. }
  374. if (ha6) {
  375. ast_free_ha(ha6);
  376. }
  377. if (ha7) {
  378. ast_free_ha(ha7);
  379. }
  380. return res;
  381. }
  382. static int unload_module(void)
  383. {
  384. AST_TEST_UNREGISTER(invalid_acl);
  385. AST_TEST_UNREGISTER(acl);
  386. return 0;
  387. }
  388. static int load_module(void)
  389. {
  390. AST_TEST_REGISTER(invalid_acl);
  391. AST_TEST_REGISTER(acl);
  392. return AST_MODULE_LOAD_SUCCESS;
  393. }
  394. AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ACL test module");