Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

acl.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- A telephony toolkit for Linux.
00003  *
00004  * Various sorts of access control
00005  * 
00006  * Copyright (C) 1999, Mark Spencer
00007  *
00008  * Mark Spencer <markster@linux-support.net>
00009  *
00010  * This program is free software, distributed under the terms of
00011  * the GNU General Public License
00012  */
00013 
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <pthread.h>
00017 #include <string.h>
00018 #include <sys/time.h>
00019 #include <signal.h>
00020 #include <errno.h>
00021 #include <unistd.h>
00022 #include <asterisk/acl.h>
00023 #include <asterisk/logger.h>
00024 #include <arpa/inet.h>
00025 #include <sys/socket.h>
00026 #include <netdb.h>
00027 #include <net/if.h>
00028 #include <netinet/in_systm.h>
00029 #include <netinet/ip.h>
00030 #include <sys/ioctl.h>
00031 
00032 #define AST_SENSE_DENY        0
00033 #define AST_SENSE_ALLOW       1
00034 
00035 struct ast_ha {
00036    /* Host access rule */
00037    struct in_addr netaddr;
00038    struct in_addr netmask;
00039    int sense;
00040    struct ast_ha *next;
00041 };
00042 
00043 /* Default IP - if not otherwise set, don't breathe garbage */
00044 static struct in_addr __ourip = { 0x00000000 };
00045 
00046 struct my_ifreq {
00047    char ifrn_name[IFNAMSIZ];  /* Interface name, e.g. "eth0", "ppp0", etc.  */
00048    struct sockaddr_in ifru_addr;
00049 };
00050 
00051 void ast_free_ha(struct ast_ha *ha)
00052 {
00053    struct ast_ha *hal;
00054    while(ha) {
00055       hal = ha;
00056       ha = ha->next;
00057       free(hal);
00058    }
00059 }
00060 
00061 struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
00062 {
00063    struct ast_ha *ha = malloc(sizeof(struct ast_ha));
00064    char *nm;
00065    struct ast_ha *prev = NULL;
00066    struct ast_ha *ret;
00067    ret = path;
00068    while(path) {
00069       prev = path;
00070       path = path->next;
00071    }
00072    if (ha) {
00073       char *stringp=NULL;
00074       stringp=stuff;
00075       strsep(&stringp, "/");
00076       nm = strsep(&stringp, "/");
00077       if (!nm)
00078          nm = "255.255.255.255";
00079       if (!inet_aton(stuff, &ha->netaddr)) {
00080          ast_log(LOG_WARNING, "%s not a valid IP\n", stuff);
00081          free(ha);
00082          return NULL;
00083       }
00084       if (!inet_aton(nm, &ha->netmask)) {
00085          ast_log(LOG_WARNING, "%s not a valid netmask\n", nm);
00086          free(ha);
00087          return NULL;
00088       }
00089       ha->netaddr.s_addr &= ha->netmask.s_addr;
00090       if (!strncasecmp(sense, "p", 1)) {
00091          ha->sense = AST_SENSE_ALLOW;
00092       } else {
00093          ha->sense = AST_SENSE_DENY;
00094       }
00095       ha->next = NULL;
00096       if (prev)
00097          prev->next = ha;
00098       else
00099          ret = ha;
00100    }
00101    return ret;
00102 }
00103 
00104 int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
00105 {
00106    /* Start optimistic */
00107    int res = AST_SENSE_ALLOW;
00108    while(ha) {
00109       /* For each rule, if this address and the netmask = the net address
00110          apply the current rule */
00111       if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == (ha->netaddr.s_addr))
00112          res = ha->sense;
00113       ha = ha->next;
00114    }
00115    return res;
00116 }
00117 
00118 int ast_get_ip(struct sockaddr_in *sin, char *value)
00119 {
00120    struct hostent *hp;
00121    hp = gethostbyname(value);
00122    if (hp) {
00123       memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
00124    } else {
00125       ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value);
00126       return -1;
00127    }
00128    return 0;
00129 }
00130 
00131 int inaddrcmp(struct sockaddr_in *sin1, struct sockaddr_in *sin2)
00132 {
00133    return ((sin1->sin_addr.s_addr != sin2->sin_addr.s_addr )
00134          || (sin1->sin_port != sin2->sin_port));
00135 }
00136 
00137 /* iface is the interface (e.g. eth0); address is the return value */
00138 int ast_lookup_iface(char *iface, struct in_addr *address) {
00139    int mysock, res = 0;
00140    struct my_ifreq ifreq;
00141 
00142    memset(&ifreq, 0, sizeof(ifreq));
00143    strncpy(ifreq.ifrn_name,iface,sizeof(ifreq.ifrn_name) - 1);
00144 
00145    mysock = socket(PF_INET,SOCK_DGRAM,IPPROTO_IP);
00146    res = ioctl(mysock,SIOCGIFADDR,&ifreq);
00147 
00148    close(mysock);
00149    if (res < 0) {
00150       ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
00151       memcpy((char *)address,(char *)&__ourip,sizeof(__ourip));
00152       return -1;
00153    } else {
00154       memcpy((char *)address,(char *)&ifreq.ifru_addr.sin_addr,sizeof(ifreq.ifru_addr.sin_addr));
00155       return 0;
00156    }
00157 }
00158 
00159 int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
00160 {
00161    FILE *PROC;
00162    unsigned int remote_ip;
00163    int res = 1;
00164    char line[256];
00165    remote_ip = them->s_addr;
00166    
00167    PROC = fopen("/proc/net/route","r");
00168    if (!PROC) {
00169       bzero(us,sizeof(struct in_addr));
00170       return -1;
00171    }
00172    /* First line contains headers */
00173    fgets(line,sizeof(line),PROC);
00174 
00175    while (!feof(PROC)) {
00176       char iface[8];
00177       unsigned int dest, gateway, mask;
00178       int i,fieldnum;
00179       char *fields[40];
00180 
00181       fgets(line,sizeof(line),PROC);
00182 
00183       fieldnum = 0;
00184       for (i=0;i<sizeof(line);i++) {
00185          char *offset;
00186 
00187          fields[fieldnum++] = line + i;
00188          offset = strchr(line + i,'\t');
00189          if (offset == NULL) {
00190             /* Exit loop */
00191             break;
00192          } else if (fieldnum >= 9) {
00193             /* Short-circuit: can't break at 8, since the end of field 7 is figured when fieldnum=8 */
00194             break;
00195          } else {
00196             *offset = '\0';
00197             i = offset - line;
00198          }
00199       }
00200 
00201       sscanf(fields[0],"%s",iface);
00202       sscanf(fields[1],"%x",&dest);
00203       sscanf(fields[2],"%x",&gateway);
00204       sscanf(fields[7],"%x",&mask);
00205 #if 0
00206       printf("Addr: %s %08x Dest: %08x Mask: %08x\n", inet_ntoa(*them), remote_ip, dest, mask);
00207 #endif      
00208       /* Looks simple, but here is the magic */
00209       if (((remote_ip & mask) ^ dest) == 0) {
00210          res = ast_lookup_iface(iface,us);
00211          break;
00212       }
00213    }
00214    fclose(PROC);
00215    if (res == 1) {
00216       ast_log(LOG_WARNING, "Yikes!  No default route?!!\n");
00217       bzero(us,sizeof(struct in_addr));
00218       return -2;
00219    } else if (res) {
00220       /* We've already warned in subroutine */
00221       return -1;
00222    }
00223    return 0;
00224 }
00225 
00226 

Generated on Fri Oct 31 07:05:04 2003 for Asterisk by doxygen 1.3.4