1 /*
2 Copyright (C) 2002-2008 Thomas Ries <tries@gmx.net>
3
4 This file is part of Siproxd.
5
6 Siproxd is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 Siproxd is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Siproxd; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <netinet/in.h>
28
29 #include <osipparser2/osip_parser.h>
30
31 #include "siproxd.h"
32 #include "log.h"
33
34 static char const ident[]="$Id: accessctl.c 521 2015-09-13 08:43:04Z hb9xar $";
35
36 /* configuration storage */
37 extern struct siproxd_config configuration;
38
39
40 /*
41 * verifies the from address agains the access lists
42 * defined in the configuration file.
43 *
44 * returns a bitmask with ACCESSCTL_SIP, ACCESSCTL_REG
45 */
accesslist_check(struct sockaddr_in from)46 int accesslist_check (struct sockaddr_in from) {
47 int access = 0;
48
49 DEBUGC(DBCLASS_ACCESS,"deny list (SIP):%s",
50 configuration.hosts_deny_sip? configuration.hosts_deny_sip : "*NULL*");
51 DEBUGC(DBCLASS_ACCESS,"allow list (SIP):%s",
52 configuration.hosts_allow_sip? configuration.hosts_allow_sip : "*NULL*");
53 DEBUGC(DBCLASS_ACCESS,"allow list (REG):%s",
54 configuration.hosts_allow_reg? configuration.hosts_allow_reg : "*NULL*");
55
56 /*
57 * check DENY list
58 */
59 if ( (configuration.hosts_deny_sip !=NULL) &&
60 (strcmp(configuration.hosts_deny_sip,"")!=0) ) {
61 /* non-empty list -> check agains it */
62 if (process_aclist(configuration.hosts_deny_sip, from)== STS_SUCCESS) {
63 /* yup - this one is blacklisted */
64 DEBUGC(DBCLASS_ACCESS,"caught by deny list");
65 return 0;
66 }
67 }
68
69 /*
70 * check SIP allow list
71 */
72 if ( (configuration.hosts_allow_sip !=NULL) &&
73 (strcmp(configuration.hosts_allow_sip,"")!=0) ) {
74 /* non-empty list -> check agains it */
75 if (process_aclist(configuration.hosts_allow_sip, from)==STS_SUCCESS) {
76 /* SIP access granted */
77 DEBUGC(DBCLASS_ACCESS,"granted SIP access");
78 access |= ACCESSCTL_SIP;
79 }
80 } else {
81 access |= ACCESSCTL_SIP;
82 }
83
84 /*
85 * check SIP registration allow list
86 */
87 if ( (configuration.hosts_allow_reg !=NULL) &&
88 (strcmp(configuration.hosts_allow_reg,"")!=0) ) {
89 /* non-empty list -> check against it */
90 if (process_aclist(configuration.hosts_allow_reg, from)==STS_SUCCESS) {
91 /* SIP registration access granted */
92 DEBUGC(DBCLASS_ACCESS,"granted REG/SIP access");
93 access |= ACCESSCTL_REG | ACCESSCTL_SIP;
94 }
95 } else {
96 access |= ACCESSCTL_REG;
97 }
98
99 DEBUGC(DBCLASS_ACCESS,"access check =%i", access);
100 return access;
101 }
102
103
104 /*
105 * checks for a match of the 'from' address with the supplied
106 * access list.
107 *
108 * RETURNS
109 * STS_SUCCESS for a match
110 * STS_FAILURE for no match
111 */
process_aclist(char * aclist,struct sockaddr_in from)112 int process_aclist (char *aclist, struct sockaddr_in from) {
113 int i, sts;
114 int lastentry;
115 char *p1, *p2;
116 char address[HOSTNAME_SIZE+1]; /* dotted decimal IP - max 15 chars */
117 /* or hostname*/
118 char mask[8]; /* mask - max 2 digits */
119 int mask_int;
120 struct in_addr inaddr;
121 unsigned int bitmask;
122
123
124 for (i=0, p1=aclist, lastentry=0;
125 !lastentry; i++) {
126
127 /*
128 * extract one entry from the access list
129 */
130 /* address */
131 p2=strchr(p1,'/');
132 if (!p2) {
133 ERROR("CONFIG: accesslist [%s]- no mask separator found", aclist);
134 return STS_FAILURE;
135 }
136 memset(address,0,sizeof(address));
137 memcpy(address,p1,p2-p1);
138
139 /* mask */
140 p1=p2+1;
141 p2=strchr(p1,',');
142 if (!p2) { /* then this must be the last entry in the list */
143 p2=strchr(p1,'\0');
144 lastentry=1;
145 }
146 memset(mask,0,sizeof(mask));
147 memcpy(mask,p1,p2-p1);
148 p1=p2+1;
149
150 DEBUGC(DBCLASS_ACCESS,"[%i] extracted address=%s", i, address);
151 DEBUGC(DBCLASS_ACCESS,"[%i] extracted mask =%s", i, mask);
152
153 /*
154 * check for a match
155 */
156 sts=get_ip_by_host(address, &inaddr);
157 if (sts == STS_FAILURE) {
158 DEBUGC(DBCLASS_ACCESS, "process_aclist: cannot resolve address [%s]",
159 address);
160 return STS_FAILURE;
161 }
162
163 mask_int=atoi(mask);
164 if ((mask_int < 0) || (mask_int > 32)) mask_int=32;
165 bitmask= (mask_int)? (0xffffffff<<(32-mask_int)) : 0;
166
167 DEBUGC(DBCLASS_ACCESS,"check match: entry=%i, filter=%lx, from=%lx", i,
168 (long)ntohl(inaddr.s_addr) & bitmask,
169 (long)ntohl(from.sin_addr.s_addr) & bitmask);
170
171 if ( (ntohl(inaddr.s_addr) & bitmask) ==
172 (ntohl(from.sin_addr.s_addr) & bitmask) ) {
173 DEBUGC(DBCLASS_ACCESS, "process_aclist: MATCH");
174 return STS_SUCCESS;
175 }
176 }
177
178 DEBUGC(DBCLASS_ACCESS, "process_aclist: no match");
179 return STS_FAILURE;
180 }
181