Asterisk - The Open Source Telephony Project GIT-master-7e7a603
test_acl.c
Go to the documentation of this file.
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/*!
20 * \file
21 * \brief ACL unit tests
22 *
23 * \author Mark Michelson <mmichelson@digium.com>
24 *
25 */
26
27/*** MODULEINFO
28 <depend>TEST_FRAMEWORK</depend>
29 <support_level>core</support_level>
30 ***/
31
32#include "asterisk.h"
33
34#include "asterisk/test.h"
35#include "asterisk/acl.h"
36#include "asterisk/module.h"
37#include "asterisk/netsock2.h"
38#include "asterisk/config.h"
39
40AST_TEST_DEFINE(invalid_acl)
41{
42 const char * invalid_acls[] = {
43 /* Negative netmask */
44 "1.3.3.7/-1",
45 /* Netmask too large */
46 "1.3.3.7/33",
47 /* Netmask waaaay too large */
48 "1.3.3.7/92342348927389492307420",
49 /* Netmask non-numeric */
50 "1.3.3.7/California",
51 /* Too many octets in Netmask */
52 "1.3.3.7/255.255.255.255.255",
53 /* Octets in IP address exceed 255 */
54 "57.60.278.900/31",
55 /* Octets in IP address exceed 255 and are negative */
56 "400.32.201029.-6/24",
57 /* Invalidly formatted IP address */
58 "EGGSOFDEATH/4000",
59 /* Too many octets in IP address */
60 "33.4.7.8.3/300030",
61 /* Too many octets in Netmask */
62 "1.2.3.4/6.7.8.9.0",
63 /* Too many octets in IP address */
64 "3.1.4.1.5.9/3",
65 /* IPv6 address has multiple double colons */
66 "ff::ff::ff/3",
67 /* IPv6 address is too long */
68 "1234:5678:90ab:cdef:1234:5678:90ab:cdef:1234/56",
69 /* IPv6 netmask is too large */
70 "::ffff/129",
71 /* IPv4-mapped IPv6 address has too few octets */
72 "::ffff:255.255.255/128",
73 /* Leading and trailing colons for IPv6 address */
74 ":1234:/15",
75 /* IPv6 address and IPv4 netmask */
76 "fe80::1234/255.255.255.0",
77 };
78
80 struct ast_ha *ha = NULL;
81 int i;
82
83 switch (cmd) {
84 case TEST_INIT:
85 info->name = "invalid_acl";
86 info->category = "/main/acl/";
87 info->summary = "Invalid ACL unit test";
88 info->description =
89 "Ensures that garbage ACL values are not accepted";
90 return AST_TEST_NOT_RUN;
91 case TEST_EXECUTE:
92 break;
93 }
94
95 for (i = 0; i < ARRAY_LEN(invalid_acls); ++i) {
96 int err = 0;
97 ha = ast_append_ha("permit", invalid_acls[i], ha, &err);
98 if (ha || !err) {
99 ast_test_status_update(test, "ACL %s accepted even though it is total garbage.\n",
100 invalid_acls[i]);
101 if (ha) {
102 ast_free_ha(ha);
103 }
104 res = AST_TEST_FAIL;
105 }
106 }
107
108 return res;
109}
110
111struct acl {
112 const char *host;
113 const char *access;
114};
115
116/* These constants are defined for the sole purpose of being shorter
117 * than their real names. It makes lines in this test quite a bit shorter
118 */
119
120#define TACL_A AST_SENSE_ALLOW
121#define TACL_D AST_SENSE_DENY
122
123static 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)
124{
125 size_t i;
126
127 for (i = 0; i < len; ++i) {
128 if (!(*ha = ast_append_ha(acl[i].access, acl[i].host, *ha, err))) {
129 ast_test_status_update(test, "Failed to add rule %s with access %s to %s\n",
130 acl[i].host, acl[i].access, acl_name);
131 *res = AST_TEST_FAIL;
132 return -1;
133 }
134 }
135
136 return 0;
137}
138
140{
141 struct acl permitallv4 = { "0.0.0.0/0", "permit" };
142 struct acl denyallv4 = { "0.0.0.0/0", "deny" };
143 struct acl permitallv6 = { "::/0", "permit" };
144 struct acl denyallv6 = { "::/0", "deny" };
145
146 struct acl acl1[] = {
147 { "0.0.0.0/0.0.0.0", "deny" },
148 { "10.0.0.0/255.0.0.0", "permit" },
149 { "192.168.0.0/255.255.255.0", "permit" },
150 };
151
152 struct acl acl2[] = {
153 { "10.0.0.0/8", "deny" },
154 { "10.0.0.0/8", "permit" },
155 { "10.0.0.0/16", "deny" },
156 { "10.0.0.0/24", "permit" },
157 };
158
159 struct acl acl3[] = {
160 { "::/0", "deny" },
161 { "fe80::/64", "permit" },
162 };
163
164 struct acl acl4[] = {
165 { "::/0", "deny" },
166 { "fe80::/64", "permit" },
167 { "fe80::ffff:0:0:0/80", "deny" },
168 { "fe80::ffff:0:ffff:0/112", "permit" },
169 };
170
171 struct acl acl5[] = {
172 { "0.0.0.0/0.0.0.0", "deny" },
173 { "10.0.0.0/255.0.0.0,192.168.0.0/255.255.255.0", "permit" },
174 };
175
176 struct acl acl6[] = {
177 { "10.0.0.0/8", "deny" },
178 { "10.0.0.0/8", "permit" },
179 { "10.0.0.0/16,!10.0.0.0/24", "deny" },
180 };
181
182 struct acl acl7[] = {
183 { "::/0,!fe80::/64", "deny" },
184 { "fe80::ffff:0:0:0/80", "deny" },
185 { "fe80::ffff:0:ffff:0/112", "permit" },
186 };
187
188 struct {
189 const char *test_address;
190 int v4_permitall_result;
191 int v4_denyall_result;
192 int v6_permitall_result;
193 int v6_denyall_result;
194 int acl1_result;
195 int acl2_result;
196 int acl3_result;
197 int acl4_result;
198 int acl5_result;
199 int acl6_result;
200 int acl7_result;
201 } acl_tests[] = {
203 { "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 },
204 { "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 },
206 { "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 },
207 { "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 },
208 { "fe80::1234", TACL_A, TACL_A, TACL_A, TACL_D, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A, TACL_A },
209 { "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 },
210 { "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 },
211 };
212
213 struct ast_ha *permit_hav4 = NULL;
214 struct ast_ha *deny_hav4 = NULL;
215 struct ast_ha *permit_hav6 = NULL;
216 struct ast_ha *deny_hav6 = NULL;
217 struct ast_ha *ha1 = NULL;
218 struct ast_ha *ha2 = NULL;
219 struct ast_ha *ha3 = NULL;
220 struct ast_ha *ha4 = NULL;
221 struct ast_ha *ha5 = NULL;
222 struct ast_ha *ha6 = NULL;
223 struct ast_ha *ha7 = NULL;
225 int err = 0;
226 int i;
227
228
229 switch (cmd) {
230 case TEST_INIT:
231 info->name = "acl";
232 info->category = "/main/acl/";
233 info->summary = "ACL unit test";
234 info->description =
235 "Tests that hosts are properly permitted or denied";
236 return AST_TEST_NOT_RUN;
237 case TEST_EXECUTE:
238 break;
239 }
240
241 if (!(permit_hav4 = ast_append_ha(permitallv4.access, permitallv4.host, permit_hav4, &err))) {
242 ast_test_status_update(test, "Failed to create permit_all ACL\n");
243 res = AST_TEST_FAIL;
244 goto acl_cleanup;
245 }
246
247 if (!(deny_hav4 = ast_append_ha(denyallv4.access, denyallv4.host, deny_hav4, &err))) {
248 ast_test_status_update(test, "Failed to create deny_all ACL\n");
249 res = AST_TEST_FAIL;
250 goto acl_cleanup;
251 }
252
253 if (!(permit_hav6 = ast_append_ha(permitallv6.access, permitallv6.host, permit_hav6, &err))) {
254 ast_test_status_update(test, "Failed to create permit_all ACL\n");
255 res = AST_TEST_FAIL;
256 goto acl_cleanup;
257 }
258
259 if (!(deny_hav6 = ast_append_ha(denyallv6.access, denyallv6.host, deny_hav6, &err))) {
260 ast_test_status_update(test, "Failed to create deny_all ACL\n");
261 res = AST_TEST_FAIL;
262 goto acl_cleanup;
263 }
264
265 if (build_ha(acl1, ARRAY_LEN(acl1), &ha1, "ha1", &err, test, &res) != 0) {
266 goto acl_cleanup;
267 }
268
269 if (build_ha(acl2, ARRAY_LEN(acl2), &ha2, "ha2", &err, test, &res) != 0) {
270 goto acl_cleanup;
271 }
272
273 if (build_ha(acl3, ARRAY_LEN(acl3), &ha3, "ha3", &err, test, &res) != 0) {
274 goto acl_cleanup;
275 }
276
277 if (build_ha(acl4, ARRAY_LEN(acl4), &ha4, "ha4", &err, test, &res) != 0) {
278 goto acl_cleanup;
279 }
280
281 if (build_ha(acl5, ARRAY_LEN(acl5), &ha5, "ha5", &err, test, &res) != 0) {
282 goto acl_cleanup;
283 }
284
285 if (build_ha(acl6, ARRAY_LEN(acl6), &ha6, "ha6", &err, test, &res) != 0) {
286 goto acl_cleanup;
287 }
288
289 if (build_ha(acl7, ARRAY_LEN(acl7), &ha7, "ha7", &err, test, &res) != 0) {
290 goto acl_cleanup;
291 }
292
293 for (i = 0; i < ARRAY_LEN(acl_tests); ++i) {
294 struct ast_sockaddr addr;
295 int permit_resv4;
296 int permit_resv6;
297 int deny_resv4;
298 int deny_resv6;
299 int acl1_res;
300 int acl2_res;
301 int acl3_res;
302 int acl4_res;
303 int acl5_res;
304 int acl6_res;
305 int acl7_res;
306
307 ast_sockaddr_parse(&addr, acl_tests[i].test_address, PARSE_PORT_FORBID);
308
309 permit_resv4 = ast_apply_ha(permit_hav4, &addr);
310 deny_resv4 = ast_apply_ha(deny_hav4, &addr);
311 permit_resv6 = ast_apply_ha(permit_hav6, &addr);
312 deny_resv6 = ast_apply_ha(deny_hav6, &addr);
313 acl1_res = ast_apply_ha(ha1, &addr);
314 acl2_res = ast_apply_ha(ha2, &addr);
315 acl3_res = ast_apply_ha(ha3, &addr);
316 acl4_res = ast_apply_ha(ha4, &addr);
317 acl5_res = ast_apply_ha(ha5, &addr);
318 acl6_res = ast_apply_ha(ha6, &addr);
319 acl7_res = ast_apply_ha(ha7, &addr);
320
321 if (permit_resv4 != acl_tests[i].v4_permitall_result) {
322 ast_test_status_update(test, "Access not as expected to %s on permitallv4. Expected %d but "
323 "got %d instead\n", acl_tests[i].test_address, acl_tests[i].v4_permitall_result, permit_resv4);
324 res = AST_TEST_FAIL;
325 goto acl_cleanup;
326 }
327
328 if (deny_resv4 != acl_tests[i].v4_denyall_result) {
329 ast_test_status_update(test, "Access not as expected to %s on denyallv4. Expected %d but "
330 "got %d instead\n", acl_tests[i].test_address, acl_tests[i].v4_denyall_result, deny_resv4);
331 res = AST_TEST_FAIL;
332 goto acl_cleanup;
333 }
334
335 if (permit_resv6 != acl_tests[i].v6_permitall_result) {
336 ast_test_status_update(test, "Access not as expected to %s on permitallv6. Expected %d but "
337 "got %d instead\n", acl_tests[i].test_address, acl_tests[i].v6_permitall_result, permit_resv6);
338 res = AST_TEST_FAIL;
339 goto acl_cleanup;
340 }
341
342 if (deny_resv6 != acl_tests[i].v6_denyall_result) {
343 ast_test_status_update(test, "Access not as expected to %s on denyallv6. Expected %d but "
344 "got %d instead\n", acl_tests[i].test_address, acl_tests[i].v6_denyall_result, deny_resv6);
345 res = AST_TEST_FAIL;
346 goto acl_cleanup;
347 }
348
349 if (acl1_res != acl_tests[i].acl1_result) {
350 ast_test_status_update(test, "Access not as expected to %s on acl1. Expected %d but "
351 "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl1_result, acl1_res);
352 res = AST_TEST_FAIL;
353 goto acl_cleanup;
354 }
355
356 if (acl2_res != acl_tests[i].acl2_result) {
357 ast_test_status_update(test, "Access not as expected to %s on acl2. Expected %d but "
358 "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl2_result, acl2_res);
359 res = AST_TEST_FAIL;
360 goto acl_cleanup;
361 }
362
363 if (acl3_res != acl_tests[i].acl3_result) {
364 ast_test_status_update(test, "Access not as expected to %s on acl3. Expected %d but "
365 "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl3_result, acl3_res);
366 res = AST_TEST_FAIL;
367 goto acl_cleanup;
368 }
369
370 if (acl4_res != acl_tests[i].acl4_result) {
371 ast_test_status_update(test, "Access not as expected to %s on acl4. Expected %d but "
372 "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl4_result, acl4_res);
373 res = AST_TEST_FAIL;
374 goto acl_cleanup;
375 }
376
377 if (acl5_res != acl_tests[i].acl5_result) {
378 ast_test_status_update(test, "Access not as expected to %s on acl5. Expected %d but "
379 "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl5_result, acl5_res);
380 res = AST_TEST_FAIL;
381 goto acl_cleanup;
382 }
383
384 if (acl6_res != acl_tests[i].acl6_result) {
385 ast_test_status_update(test, "Access not as expected to %s on acl6. Expected %d but "
386 "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl6_result, acl6_res);
387 res = AST_TEST_FAIL;
388 goto acl_cleanup;
389 }
390
391 if (acl7_res != acl_tests[i].acl7_result) {
392 ast_test_status_update(test, "Access not as expected to %s on acl7. Expected %d but "
393 "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl7_result, acl7_res);
394 res = AST_TEST_FAIL;
395 goto acl_cleanup;
396 }
397 }
398
399acl_cleanup:
400 if (permit_hav4) {
401 ast_free_ha(permit_hav4);
402 }
403 if (deny_hav4) {
404 ast_free_ha(deny_hav4);
405 }
406 if (permit_hav6) {
407 ast_free_ha(permit_hav6);
408 }
409 if (deny_hav6) {
410 ast_free_ha(deny_hav6);
411 }
412 if (ha1) {
413 ast_free_ha(ha1);
414 }
415 if (ha2) {
416 ast_free_ha(ha2);
417 }
418 if (ha3) {
419 ast_free_ha(ha3);
420 }
421 if (ha4) {
422 ast_free_ha(ha4);
423 }
424 if (ha5) {
425 ast_free_ha(ha5);
426 }
427 if (ha6) {
428 ast_free_ha(ha6);
429 }
430 if (ha7) {
431 ast_free_ha(ha7);
432 }
433 return res;
434}
435
436static int unload_module(void)
437{
438 AST_TEST_UNREGISTER(invalid_acl);
440 return 0;
441}
442
443static int load_module(void)
444{
445 AST_TEST_REGISTER(invalid_acl);
448}
449
Access Control of various sorts.
void ast_free_ha(struct ast_ha *ha)
Free a list of HAs.
Definition: acl.c:222
enum ast_acl_sense ast_apply_ha(const struct ast_ha *ha, const struct ast_sockaddr *addr)
Apply a set of rules to a given IP address.
Definition: acl.c:807
struct ast_ha * ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
Add a new rule to a list of HAs.
Definition: acl.c:712
Asterisk main include file. File version handling, generic pbx functions.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Configuration File Parser.
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
Network socket handling.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
#define NULL
Definition: resample.c:96
Definition: test_acl.c:111
const char * access
Definition: test_acl.c:113
const char * host
Definition: test_acl.c:112
internal representation of ACL entries In principle user applications would have no need for this,...
Definition: acl.h:51
Socket address structure.
Definition: netsock2.h:97
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
ast_test_result_state
Definition: test.h:193
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
AST_TEST_DEFINE(invalid_acl)
Definition: test_acl.c:40
#define TACL_A
Definition: test_acl.c:120
static int load_module(void)
Definition: test_acl.c:443
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)
Definition: test_acl.c:123
static int unload_module(void)
Definition: test_acl.c:436
#define TACL_D
Definition: test_acl.c:121
#define ARRAY_LEN(a)
Definition: utils.h:666