And the automerge property.
[asterisk/asterisk.git] / tests / test_acl.c
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  ***/
30
31 #include "asterisk.h"
32
33 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34
35 #include "asterisk/test.h"
36 #include "asterisk/acl.h"
37 #include "asterisk/module.h"
38
39 AST_TEST_DEFINE(invalid_acl)
40 {
41         const char * invalid_acls[] = {
42                 "1.3.3.7/-1",
43                 "1.3.3.7/33",
44                 "1.3.3.7/92342348927389492307420",
45                 "1.3.3.7/California",
46                 "1.3.3.7/255.255.255.255.255",
47                 "57.60.278.900/31",
48                 "400.32.201029.-6/24",
49                 "EGGSOFDEATH/4000",
50                 "33.4.7.8.3/300030",
51                 "1.2.3.4/6.7.8.9.0",
52                 "3.1.4.1.5.9/3",
53         };
54
55         enum ast_test_result_state res = AST_TEST_PASS;
56         struct ast_ha *ha = NULL;
57         int i;
58
59         switch (cmd) {
60         case TEST_INIT:
61                 info->name = "invalid_acl";
62                 info->category = "main/acl/";
63                 info->summary = "Invalid ACL unit test";
64                 info->description =
65                         "Ensures that garbage ACL values are not accepted";
66                 return AST_TEST_NOT_RUN;
67         case TEST_EXECUTE:
68                 break;
69         }
70
71         for (i = 0; i < ARRAY_LEN(invalid_acls); ++i) {
72                 int err = 0;
73                 ha = ast_append_ha("permit", invalid_acls[i], ha, &err);
74                 if (ha || !err) {
75                         ast_test_status_update(test, "ACL %s accepted even though it is total garbage.\n",
76                                         invalid_acls[i]);
77                         if (ha) {
78                                 ast_free_ha(ha);
79                         }
80                         res = AST_TEST_FAIL;
81                 }
82         }
83
84         return res;
85 }
86
87 struct acl {
88         const char *host;
89         const char *access;
90 };
91
92 AST_TEST_DEFINE(acl)
93 {
94         struct acl permitall = { "0.0.0.0/0", "permit" };
95         struct acl denyall = { "0.0.0.0/0", "deny" };
96         struct acl acl1[] = {
97                 { "0.0.0.0/0.0.0.0", "deny" },
98                 { "10.0.0.0/255.0.0.0", "permit" },
99                 { "192.168.0.0/255.255.255.0", "permit" },
100         };
101         struct acl acl2[] = {
102                 { "10.0.0.0/8", "deny" },
103                 { "10.0.0.0/8", "permit" },
104                 { "10.0.0.0/16", "deny" },
105                 { "10.0.0.0/24", "permit" },
106         };
107
108         struct {
109                 const char *test_address;
110                 int acl1_result;
111                 int acl2_result;
112         } acl_tests[] = {
113                 { "10.1.1.5", AST_SENSE_ALLOW, AST_SENSE_ALLOW },
114                 { "192.168.0.5", AST_SENSE_ALLOW, AST_SENSE_ALLOW },
115                 { "192.168.1.5", AST_SENSE_DENY, AST_SENSE_ALLOW },
116                 { "10.0.0.1", AST_SENSE_ALLOW, AST_SENSE_ALLOW },
117                 { "10.0.10.10", AST_SENSE_ALLOW, AST_SENSE_DENY },
118                 { "172.16.0.1", AST_SENSE_DENY, AST_SENSE_ALLOW },
119         };
120
121         struct ast_ha *permit_ha = NULL;
122         struct ast_ha *deny_ha = NULL;
123         struct ast_ha *ha1 = NULL;
124         struct ast_ha *ha2 = NULL;
125         enum ast_test_result_state res = AST_TEST_PASS;
126         int err = 0;
127         int i;
128
129         switch (cmd) {
130         case TEST_INIT:
131                 info->name = "acl";
132                 info->category = "main/acl/";
133                 info->summary = "ACL unit test";
134                 info->description =
135                         "Tests that hosts are properly permitted or denied";
136                 return AST_TEST_NOT_RUN;
137         case TEST_EXECUTE:
138                 break;
139         }
140
141         if (!(permit_ha = ast_append_ha(permitall.access, permitall.host, permit_ha, &err))) {
142                 ast_test_status_update(test, "Failed to create permit_all ACL\n");
143                 res = AST_TEST_FAIL;
144                 goto acl_cleanup;
145         }
146
147         if (!(deny_ha = ast_append_ha(denyall.access, denyall.host, deny_ha, &err))) {
148                 ast_test_status_update(test, "Failed to create deny_all ACL\n");
149                 res = AST_TEST_FAIL;
150                 goto acl_cleanup;
151         }
152
153         for (i = 0; i < ARRAY_LEN(acl1); ++i) {
154                 if (!(ha1 = ast_append_ha(acl1[i].access, acl1[i].host, ha1, &err))) {
155                         ast_test_status_update(test, "Failed to add rule %s with access %s to ha1\n",
156                                         acl1[i].host, acl1[i].access);
157                         res = AST_TEST_FAIL;
158                         goto acl_cleanup;
159                 }
160         }
161
162         for (i = 0; i < ARRAY_LEN(acl2); ++i) {
163                 if (!(ha2 = ast_append_ha(acl2[i].access, acl2[i].host, ha2, &err))) {
164                         ast_test_status_update(test, "Failed to add rule %s with access %s to ha2\n",
165                                         acl2[i].host, acl2[i].access);
166                         res = AST_TEST_FAIL;
167                         goto acl_cleanup;
168                 }
169         }
170
171         for (i = 0; i < ARRAY_LEN(acl_tests); ++i) {
172                 struct sockaddr_in sin;
173                 int permit_res;
174                 int deny_res;
175                 int acl1_res;
176                 int acl2_res;
177
178                 inet_aton(acl_tests[i].test_address, &sin.sin_addr);
179
180                 permit_res = ast_apply_ha(permit_ha, &sin);
181                 deny_res = ast_apply_ha(deny_ha, &sin);
182                 acl1_res = ast_apply_ha(ha1, &sin);
183                 acl2_res = ast_apply_ha(ha2, &sin);
184
185                 if (permit_res != AST_SENSE_ALLOW) {
186                         ast_test_status_update(test, "Access denied to %s on permit_all ACL\n",
187                                         acl_tests[i].test_address);
188                         res = AST_TEST_FAIL;
189                         goto acl_cleanup;
190                 }
191
192                 if (deny_res != AST_SENSE_DENY) {
193                         ast_test_status_update(test, "Access allowed to %s on deny_all ACL\n",
194                                         acl_tests[i].test_address);
195                         res = AST_TEST_FAIL;
196                         goto acl_cleanup;
197                 }
198
199                 if (acl1_res != acl_tests[i].acl1_result) {
200                         ast_test_status_update(test, "Access not as expected to %s on acl1. Expected %d but"
201                                         "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl1_result, acl1_res);
202                         res = AST_TEST_FAIL;
203                         goto acl_cleanup;
204                 }
205
206                 if (acl2_res != acl_tests[i].acl2_result) {
207                         ast_test_status_update(test, "Access not as expected to %s on acl2. Expected %d but"
208                                         "got %d instead\n", acl_tests[i].test_address, acl_tests[i].acl2_result, acl2_res);
209                         res = AST_TEST_FAIL;
210                         goto acl_cleanup;
211                 }
212         }
213
214 acl_cleanup:
215         if (permit_ha) {
216                 ast_free_ha(permit_ha);
217         }
218         if (deny_ha) {
219                 ast_free_ha(deny_ha);
220         }
221         if (ha1) {
222                 ast_free_ha(ha1);
223         }
224         if (ha1) {
225                 ast_free_ha(ha2);
226         }
227         return res;
228 }
229
230 static int unload_module(void)
231 {
232         AST_TEST_UNREGISTER(invalid_acl);
233         AST_TEST_UNREGISTER(acl);
234         return 0;
235 }
236
237 static int load_module(void)
238 {
239         AST_TEST_REGISTER(invalid_acl);
240         AST_TEST_REGISTER(acl);
241         return AST_MODULE_LOAD_SUCCESS;
242 }
243
244 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "ACL test module");