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