![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
acl.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2006, Digium, Inc. 00005 * 00006 * Mark Spencer <markster@digium.com> 00007 * 00008 * See http://www.asterisk.org for more information about 00009 * the Asterisk project. Please do not directly contact 00010 * any of the maintainers of this project for assistance; 00011 * the project provides a web site, mailing lists and IRC 00012 * channels for your use. 00013 * 00014 * This program is free software, distributed under the terms of 00015 * the GNU General Public License Version 2. See the LICENSE file 00016 * at the top of the source tree. 00017 */ 00018 00019 /*! \file 00020 * 00021 * \brief Various sorts of access control 00022 * 00023 * \author Mark Spencer <markster@digium.com> 00024 */ 00025 00026 #include "asterisk.h" 00027 00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 49116 $") 00029 00030 #include <stdio.h> 00031 #include <stdlib.h> 00032 #include <string.h> 00033 #include <sys/time.h> 00034 #include <signal.h> 00035 #include <errno.h> 00036 #include <unistd.h> 00037 #include <netinet/in.h> 00038 #include <arpa/inet.h> 00039 #include <sys/socket.h> 00040 #include <netdb.h> 00041 #include <net/if.h> 00042 #include <netinet/in.h> 00043 #include <netinet/in_systm.h> 00044 #include <netinet/ip.h> 00045 #include <sys/ioctl.h> 00046 00047 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) 00048 #include <fcntl.h> 00049 #include <net/route.h> 00050 #endif 00051 00052 #if defined(SOLARIS) 00053 #include <sys/sockio.h> 00054 #endif 00055 00056 /* netinet/ip.h may not define the following (See RFCs 791 and 1349) */ 00057 #if !defined(IPTOS_LOWCOST) 00058 #define IPTOS_LOWCOST 0x02 00059 #endif 00060 00061 #if !defined(IPTOS_MINCOST) 00062 #define IPTOS_MINCOST IPTOS_LOWCOST 00063 #endif 00064 00065 #include "asterisk/acl.h" 00066 #include "asterisk/logger.h" 00067 #include "asterisk/channel.h" 00068 #include "asterisk/options.h" 00069 #include "asterisk/utils.h" 00070 #include "asterisk/lock.h" 00071 #include "asterisk/srv.h" 00072 00073 struct ast_ha { 00074 /* Host access rule */ 00075 struct in_addr netaddr; 00076 struct in_addr netmask; 00077 int sense; 00078 struct ast_ha *next; 00079 }; 00080 00081 struct my_ifreq { 00082 char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "eth0", "ppp0", etc. */ 00083 struct sockaddr_in ifru_addr; 00084 }; 00085 00086 /* Free HA structure */ 00087 void ast_free_ha(struct ast_ha *ha) 00088 { 00089 struct ast_ha *hal; 00090 while (ha) { 00091 hal = ha; 00092 ha = ha->next; 00093 free(hal); 00094 } 00095 } 00096 00097 /* Copy HA structure */ 00098 static void ast_copy_ha(struct ast_ha *from, struct ast_ha *to) 00099 { 00100 memcpy(&to->netaddr, &from->netaddr, sizeof(from->netaddr)); 00101 memcpy(&to->netmask, &from->netmask, sizeof(from->netmask)); 00102 to->sense = from->sense; 00103 } 00104 00105 /* Create duplicate of ha structure */ 00106 static struct ast_ha *ast_duplicate_ha(struct ast_ha *original) 00107 { 00108 struct ast_ha *new_ha; 00109 00110 if ((new_ha = ast_malloc(sizeof(*new_ha)))) { 00111 /* Copy from original to new object */ 00112 ast_copy_ha(original, new_ha); 00113 } 00114 00115 return new_ha; 00116 } 00117 00118 /* Create duplicate HA link list */ 00119 /* Used in chan_sip2 templates */ 00120 struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original) 00121 { 00122 struct ast_ha *start = original; 00123 struct ast_ha *ret = NULL; 00124 struct ast_ha *link, *prev = NULL; 00125 00126 while (start) { 00127 link = ast_duplicate_ha(start); /* Create copy of this object */ 00128 if (prev) 00129 prev->next = link; /* Link previous to this object */ 00130 00131 if (!ret) 00132 ret = link; /* Save starting point */ 00133 00134 start = start->next; /* Go to next object */ 00135 prev = link; /* Save pointer to this object */ 00136 } 00137 return ret; /* Return start of list */ 00138 } 00139 00140 struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path, int *error) 00141 { 00142 struct ast_ha *ha; 00143 char *nm = "255.255.255.255"; 00144 char tmp[256]; 00145 struct ast_ha *prev = NULL; 00146 struct ast_ha *ret; 00147 int x, z; 00148 unsigned int y; 00149 00150 ret = path; 00151 while (path) { 00152 prev = path; 00153 path = path->next; 00154 } 00155 if ((ha = ast_malloc(sizeof(*ha)))) { 00156 ast_copy_string(tmp, stuff, sizeof(tmp)); 00157 nm = strchr(tmp, '/'); 00158 if (!nm) { 00159 nm = "255.255.255.255"; 00160 } else { 00161 *nm = '\0'; 00162 nm++; 00163 } 00164 if (!strchr(nm, '.')) { 00165 if ((sscanf(nm, "%d", &x) == 1) && (x >= 0) && (x <= 32)) { 00166 y = 0; 00167 for (z = 0; z < x; z++) { 00168 y >>= 1; 00169 y |= 0x80000000; 00170 } 00171 ha->netmask.s_addr = htonl(y); 00172 } 00173 } else if (!inet_aton(nm, &ha->netmask)) { 00174 ast_log(LOG_WARNING, "%s is not a valid netmask\n", nm); 00175 if (error) 00176 *error = 1; 00177 free(ha); 00178 return ret; 00179 } 00180 if (!inet_aton(tmp, &ha->netaddr)) { 00181 ast_log(LOG_WARNING, "%s is not a valid IP\n", tmp); 00182 if (error) 00183 *error = 1; 00184 free(ha); 00185 return ret; 00186 } 00187 ha->netaddr.s_addr &= ha->netmask.s_addr; 00188 if (!strncasecmp(sense, "p", 1)) { 00189 ha->sense = AST_SENSE_ALLOW; 00190 } else { 00191 ha->sense = AST_SENSE_DENY; 00192 } 00193 ha->next = NULL; 00194 if (prev) { 00195 prev->next = ha; 00196 } else { 00197 ret = ha; 00198 } 00199 } 00200 if (option_debug) 00201 ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n", stuff, nm); 00202 return ret; 00203 } 00204 00205 int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin) 00206 { 00207 /* Start optimistic */ 00208 int res = AST_SENSE_ALLOW; 00209 while (ha) { 00210 char iabuf[INET_ADDRSTRLEN]; 00211 char iabuf2[INET_ADDRSTRLEN]; 00212 /* DEBUG */ 00213 ast_copy_string(iabuf, ast_inet_ntoa(sin->sin_addr), sizeof(iabuf)); 00214 ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2)); 00215 ast_log(LOG_DEBUG, "##### Testing %s with %s\n", iabuf, iabuf2); 00216 /* For each rule, if this address and the netmask = the net address 00217 apply the current rule */ 00218 if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == ha->netaddr.s_addr) 00219 res = ha->sense; 00220 ha = ha->next; 00221 } 00222 return res; 00223 } 00224 00225 int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service) 00226 { 00227 struct hostent *hp; 00228 struct ast_hostent ahp; 00229 char srv[256]; 00230 char host[256]; 00231 int tportno = ntohs(sin->sin_port); 00232 if (inet_aton(value, &sin->sin_addr)) 00233 return 0; 00234 if (service) { 00235 snprintf(srv, sizeof(srv), "%s.%s", service, value); 00236 if (ast_get_srv(NULL, host, sizeof(host), &tportno, srv) > 0) { 00237 sin->sin_port = htons(tportno); 00238 value = host; 00239 } 00240 } 00241 hp = ast_gethostbyname(value, &ahp); 00242 if (hp) { 00243 memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); 00244 } else { 00245 ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value); 00246 return -1; 00247 } 00248 return 0; 00249 } 00250 00251 struct dscp_codepoint { 00252 char *name; 00253 unsigned int space; 00254 }; 00255 00256 /* IANA registered DSCP codepoints */ 00257 00258 static const struct dscp_codepoint dscp_pool1[] = { 00259 { "CS0", 0x00 }, 00260 { "CS1", 0x08 }, 00261 { "CS2", 0x10 }, 00262 { "CS3", 0x18 }, 00263 { "CS4", 0x20 }, 00264 { "CS5", 0x28 }, 00265 { "CS6", 0x30 }, 00266 { "CS7", 0x38 }, 00267 { "AF11", 0x0A }, 00268 { "AF12", 0x0C }, 00269 { "AF13", 0x0E }, 00270 { "AF21", 0x12 }, 00271 { "AF22", 0x14 }, 00272 { "AF23", 0x16 }, 00273 { "AF31", 0x1A }, 00274 { "AF32", 0x1C }, 00275 { "AF33", 0x1E }, 00276 { "AF41", 0x22 }, 00277 { "AF42", 0x24 }, 00278 { "AF43", 0x26 }, 00279 { "EF", 0x2E }, 00280 }; 00281 00282 int ast_str2tos(const char *value, unsigned int *tos) 00283 { 00284 int fval; 00285 unsigned int x; 00286 00287 if (sscanf(value, "%i", &fval) == 1) { 00288 *tos = fval & 0xFF; 00289 return 0; 00290 } 00291 00292 for (x = 0; x < sizeof(dscp_pool1) / sizeof(dscp_pool1[0]); x++) { 00293 if (!strcasecmp(value, dscp_pool1[x].name)) { 00294 *tos = dscp_pool1[x].space << 2; 00295 return 0; 00296 } 00297 } 00298 00299 return -1; 00300 } 00301 00302 const char *ast_tos2str(unsigned int tos) 00303 { 00304 unsigned int x; 00305 00306 for (x = 0; x < sizeof(dscp_pool1) / sizeof(dscp_pool1[0]); x++) { 00307 if (dscp_pool1[x].space == (tos >> 2)) 00308 return dscp_pool1[x].name; 00309 } 00310 00311 return "unknown"; 00312 } 00313 00314 int ast_get_ip(struct sockaddr_in *sin, const char *value) 00315 { 00316 return ast_get_ip_or_srv(sin, value, NULL); 00317 } 00318 00319 int ast_ouraddrfor(struct in_addr *them, struct in_addr *us) 00320 { 00321 int s; 00322 struct sockaddr_in sin; 00323 socklen_t slen; 00324 00325 s = socket(PF_INET, SOCK_DGRAM, 0); 00326 if (s < 0) { 00327 ast_log(LOG_WARNING, "Cannot create socket\n"); 00328 return -1; 00329 } 00330 sin.sin_family = AF_INET; 00331 sin.sin_port = 5060; 00332 sin.sin_addr = *them; 00333 if (connect(s, (struct sockaddr *)&sin, sizeof(sin))) { 00334 ast_log(LOG_WARNING, "Cannot connect\n"); 00335 close(s); 00336 return -1; 00337 } 00338 slen = sizeof(sin); 00339 if (getsockname(s, (struct sockaddr *)&sin, &slen)) { 00340 ast_log(LOG_WARNING, "Cannot get socket name\n"); 00341 close(s); 00342 return -1; 00343 } 00344 close(s); 00345 *us = sin.sin_addr; 00346 return 0; 00347 } 00348 00349 int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr) 00350 { 00351 char ourhost[MAXHOSTNAMELEN] = ""; 00352 struct ast_hostent ahp; 00353 struct hostent *hp; 00354 struct in_addr saddr; 00355 00356 /* just use the bind address if it is nonzero */ 00357 if (ntohl(bindaddr.sin_addr.s_addr)) { 00358 memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip)); 00359 return 0; 00360 } 00361 /* try to use our hostname */ 00362 if (gethostname(ourhost, sizeof(ourhost) - 1)) { 00363 ast_log(LOG_WARNING, "Unable to get hostname\n"); 00364 } else { 00365 hp = ast_gethostbyname(ourhost, &ahp); 00366 if (hp) { 00367 memcpy(ourip, hp->h_addr, sizeof(*ourip)); 00368 return 0; 00369 } 00370 } 00371 /* A.ROOT-SERVERS.NET. */ 00372 if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip)) 00373 return 0; 00374 return -1; 00375 } 00376