acl.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /*
  2. * Asterisk -- A telephony toolkit for Linux.
  3. *
  4. * Various sorts of access control
  5. *
  6. * Copyright (C) 1999, Mark Spencer
  7. *
  8. * Mark Spencer <markster@linux-support.net>
  9. *
  10. * This program is free software, distributed under the terms of
  11. * the GNU General Public License
  12. */
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <sys/time.h>
  17. #include <signal.h>
  18. #include <errno.h>
  19. #include <unistd.h>
  20. #include <asterisk/acl.h>
  21. #include <asterisk/logger.h>
  22. #include <asterisk/channel.h>
  23. #include <asterisk/utils.h>
  24. #include <asterisk/lock.h>
  25. #include <arpa/inet.h>
  26. #include <sys/socket.h>
  27. #include <netdb.h>
  28. #include <net/if.h>
  29. #include <netinet/in_systm.h>
  30. #include <netinet/ip.h>
  31. #include <sys/ioctl.h>
  32. #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
  33. #include <fcntl.h>
  34. #include <net/route.h>
  35. AST_MUTEX_DEFINE_STATIC(routeseq_lock);
  36. #endif
  37. struct ast_ha {
  38. /* Host access rule */
  39. struct in_addr netaddr;
  40. struct in_addr netmask;
  41. int sense;
  42. struct ast_ha *next;
  43. };
  44. /* Default IP - if not otherwise set, don't breathe garbage */
  45. static struct in_addr __ourip = { 0x00000000 };
  46. struct my_ifreq {
  47. char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "eth0", "ppp0", etc. */
  48. struct sockaddr_in ifru_addr;
  49. };
  50. /* Free HA structure */
  51. void ast_free_ha(struct ast_ha *ha)
  52. {
  53. struct ast_ha *hal;
  54. while(ha) {
  55. hal = ha;
  56. ha = ha->next;
  57. free(hal);
  58. }
  59. }
  60. /* Copy HA structure */
  61. static void ast_copy_ha(struct ast_ha *from, struct ast_ha *to)
  62. {
  63. memcpy(&to->netaddr, &from->netaddr, sizeof(from->netaddr));
  64. memcpy(&to->netmask, &from->netmask, sizeof(from->netmask));
  65. to->sense = from->sense;
  66. }
  67. /* Create duplicate of ha structure */
  68. static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
  69. {
  70. struct ast_ha *new_ha = malloc(sizeof(struct ast_ha));
  71. /* Copy from original to new object */
  72. ast_copy_ha(original, new_ha);
  73. return(new_ha);
  74. }
  75. /* Create duplicate HA link list */
  76. /* Used in chan_sip2 templates */
  77. struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
  78. {
  79. struct ast_ha *start=original;
  80. struct ast_ha *ret = NULL;
  81. struct ast_ha *link,*prev=NULL;
  82. while(start) {
  83. link = ast_duplicate_ha(start); /* Create copy of this object */
  84. if (prev)
  85. prev->next = link; /* Link previous to this object */
  86. if (!ret)
  87. ret = link; /* Save starting point */
  88. start = start->next; /* Go to next object */
  89. prev = link; /* Save pointer to this object */
  90. }
  91. return (ret); /* Return start of list */
  92. }
  93. struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
  94. {
  95. struct ast_ha *ha = malloc(sizeof(struct ast_ha));
  96. char *nm="255.255.255.255";
  97. char tmp[256] = "";
  98. struct ast_ha *prev = NULL;
  99. struct ast_ha *ret;
  100. int x,z;
  101. unsigned int y;
  102. ret = path;
  103. while(path) {
  104. prev = path;
  105. path = path->next;
  106. }
  107. if (ha) {
  108. strncpy(tmp, stuff, sizeof(tmp) - 1);
  109. nm = strchr(tmp, '/');
  110. if (!nm)
  111. nm = "255.255.255.255";
  112. else {
  113. *nm = '\0';
  114. nm++;
  115. }
  116. if (!strchr(nm, '.')) {
  117. if ((sscanf(nm, "%i", &x) == 1) && (x >= 0) && (x <= 32)) {
  118. y = 0;
  119. for (z=0;z<x;z++) {
  120. y >>= 1;
  121. y |= 0x80000000;
  122. }
  123. ha->netmask.s_addr = htonl(y);
  124. }
  125. } else if (!inet_aton(nm, &ha->netmask)) {
  126. ast_log(LOG_WARNING, "%s not a valid netmask\n", nm);
  127. free(ha);
  128. return path;
  129. }
  130. if (!inet_aton(tmp, &ha->netaddr)) {
  131. ast_log(LOG_WARNING, "%s not a valid IP\n", tmp);
  132. free(ha);
  133. return path;
  134. }
  135. ha->netaddr.s_addr &= ha->netmask.s_addr;
  136. if (!strncasecmp(sense, "p", 1)) {
  137. ha->sense = AST_SENSE_ALLOW;
  138. } else {
  139. ha->sense = AST_SENSE_DENY;
  140. }
  141. ha->next = NULL;
  142. if (prev)
  143. prev->next = ha;
  144. else
  145. ret = ha;
  146. }
  147. ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n",stuff, nm);
  148. return ret;
  149. }
  150. int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
  151. {
  152. /* Start optimistic */
  153. int res = AST_SENSE_ALLOW;
  154. while(ha) {
  155. char iabuf[INET_ADDRSTRLEN];
  156. char iabuf2[INET_ADDRSTRLEN];
  157. /* DEBUG */
  158. ast_log(LOG_DEBUG,
  159. "##### Testing %s with %s\n",
  160. ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr),
  161. ast_inet_ntoa(iabuf2, sizeof(iabuf2), ha->netaddr));
  162. /* For each rule, if this address and the netmask = the net address
  163. apply the current rule */
  164. if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == (ha->netaddr.s_addr))
  165. res = ha->sense;
  166. ha = ha->next;
  167. }
  168. return res;
  169. }
  170. int ast_get_ip(struct sockaddr_in *sin, char *value)
  171. {
  172. struct hostent *hp;
  173. struct ast_hostent ahp;
  174. hp = ast_gethostbyname(value, &ahp);
  175. if (hp) {
  176. memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
  177. } else {
  178. ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value);
  179. return -1;
  180. }
  181. return 0;
  182. }
  183. /* iface is the interface (e.g. eth0); address is the return value */
  184. int ast_lookup_iface(char *iface, struct in_addr *address) {
  185. int mysock, res = 0;
  186. struct my_ifreq ifreq;
  187. memset(&ifreq, 0, sizeof(ifreq));
  188. strncpy(ifreq.ifrn_name,iface,sizeof(ifreq.ifrn_name) - 1);
  189. mysock = socket(PF_INET,SOCK_DGRAM,IPPROTO_IP);
  190. res = ioctl(mysock,SIOCGIFADDR,&ifreq);
  191. close(mysock);
  192. if (res < 0) {
  193. ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
  194. memcpy((char *)address,(char *)&__ourip,sizeof(__ourip));
  195. return -1;
  196. } else {
  197. memcpy((char *)address,(char *)&ifreq.ifru_addr.sin_addr,sizeof(ifreq.ifru_addr.sin_addr));
  198. return 0;
  199. }
  200. }
  201. int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
  202. {
  203. #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
  204. struct sockaddr_in *sin;
  205. struct sockaddr *sa;
  206. struct {
  207. struct rt_msghdr m_rtm;
  208. char m_space[512];
  209. } m_rtmsg;
  210. char iabuf[INET_ADDRSTRLEN];
  211. char *cp, *p;
  212. int i, l, s, seq, flags;
  213. pid_t pid = getpid();
  214. static int routeseq; /* Protected by "routeseq_lock" mutex */
  215. p = ast_strdupa(ast_inet_ntoa(iabuf, sizeof(iabuf), *them));
  216. memset(us, 0, sizeof(struct in_addr));
  217. memset(&m_rtmsg, 0, sizeof(m_rtmsg));
  218. m_rtmsg.m_rtm.rtm_type = RTM_GET;
  219. m_rtmsg.m_rtm.rtm_version = RTM_VERSION;
  220. ast_mutex_lock(&routeseq_lock);
  221. seq = ++routeseq;
  222. ast_mutex_unlock(&routeseq_lock);
  223. m_rtmsg.m_rtm.rtm_seq = seq;
  224. m_rtmsg.m_rtm.rtm_addrs = RTA_DST | RTA_IFA;
  225. m_rtmsg.m_rtm.rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
  226. sin = (struct sockaddr_in *)m_rtmsg.m_space;
  227. sin->sin_family = AF_INET;
  228. sin->sin_len = sizeof(struct sockaddr_in);
  229. sin->sin_addr = *them;
  230. if ((s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) < 0) {
  231. ast_log(LOG_ERROR, "Error opening routing socket\n");
  232. return -1;
  233. }
  234. flags = fcntl(s, F_GETFL);
  235. fcntl(s, F_SETFL, flags | O_NONBLOCK);
  236. if (write(s, (char *)&m_rtmsg, m_rtmsg.m_rtm.rtm_msglen) < 0) {
  237. ast_log(LOG_ERROR, "Error writing to routing socket: %s\n", strerror(errno));
  238. close(s);
  239. return -1;
  240. }
  241. do {
  242. l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
  243. } while (l > 0 && (m_rtmsg.m_rtm.rtm_seq != seq || m_rtmsg.m_rtm.rtm_pid != pid));
  244. if (l < 0) {
  245. if (errno != EAGAIN)
  246. ast_log(LOG_ERROR, "Error reading from routing socket\n");
  247. close(s);
  248. return -1;
  249. }
  250. close(s);
  251. if (m_rtmsg.m_rtm.rtm_version != RTM_VERSION) {
  252. ast_log(LOG_ERROR, "Unsupported route socket protocol version\n");
  253. return -1;
  254. }
  255. if (m_rtmsg.m_rtm.rtm_msglen != l)
  256. ast_log(LOG_WARNING, "Message length mismatch, in packet %d, returned %d\n",
  257. m_rtmsg.m_rtm.rtm_msglen, l);
  258. if (m_rtmsg.m_rtm.rtm_errno) {
  259. ast_log(LOG_ERROR, "RTM_GET got %s (%d)\n",
  260. strerror(m_rtmsg.m_rtm.rtm_errno), m_rtmsg.m_rtm.rtm_errno);
  261. return -1;
  262. }
  263. cp = (char *)m_rtmsg.m_space;
  264. if (m_rtmsg.m_rtm.rtm_addrs)
  265. for (i = 1; i; i <<= 1)
  266. if (m_rtmsg.m_rtm.rtm_addrs & i) {
  267. sa = (struct sockaddr *)cp;
  268. if (i == RTA_IFA && sa->sa_family == AF_INET) {
  269. sin = (struct sockaddr_in *)sa;
  270. *us = sin->sin_addr;
  271. ast_log(LOG_DEBUG, "Found route to %s, output from our address %s.\n", p, ast_inet_ntoa(iabuf, sizeof(iabuf), *us));
  272. return 0;
  273. }
  274. cp += sa->sa_len > 0 ?
  275. (1 + ((sa->sa_len - 1) | (sizeof(long) - 1))) :
  276. sizeof(long);
  277. }
  278. ast_log(LOG_DEBUG, "No route found for address %s!\n", p);
  279. return -1;
  280. #else
  281. FILE *PROC;
  282. unsigned int remote_ip;
  283. int res = 1;
  284. char line[256];
  285. remote_ip = them->s_addr;
  286. PROC = fopen("/proc/net/route","r");
  287. if (!PROC) {
  288. bzero(us,sizeof(struct in_addr));
  289. return -1;
  290. }
  291. /* First line contains headers */
  292. fgets(line,sizeof(line),PROC);
  293. while (!feof(PROC)) {
  294. char iface[256];
  295. unsigned int dest, gateway, mask;
  296. int i,fieldnum;
  297. char *fields[40];
  298. fgets(line,sizeof(line),PROC);
  299. fieldnum = 0;
  300. for (i=0;i<sizeof(line);i++) {
  301. char *offset;
  302. fields[fieldnum++] = line + i;
  303. offset = strchr(line + i,'\t');
  304. if (offset == NULL) {
  305. /* Exit loop */
  306. break;
  307. } else if (fieldnum >= 9) {
  308. /* Short-circuit: can't break at 8, since the end of field 7 is figured when fieldnum=8 */
  309. break;
  310. } else {
  311. *offset = '\0';
  312. i = offset - line;
  313. }
  314. }
  315. if (fieldnum >= 8) {
  316. sscanf(fields[0],"%s",iface);
  317. sscanf(fields[1],"%x",&dest);
  318. sscanf(fields[2],"%x",&gateway);
  319. sscanf(fields[7],"%x",&mask);
  320. #if 0
  321. { char iabuf[INET_ADDRSTRLEN];
  322. printf("Addr: %s %08x Dest: %08x Mask: %08x\n", ast_inet_ntoa(iabuf, sizeof(iabuf), *them), remote_ip, dest, mask); }
  323. #endif
  324. /* Looks simple, but here is the magic */
  325. if (((remote_ip & mask) ^ dest) == 0) {
  326. res = ast_lookup_iface(iface,us);
  327. break;
  328. }
  329. }
  330. }
  331. fclose(PROC);
  332. if (res == 1) {
  333. ast_log(LOG_WARNING, "Yikes! No default route?!!\n");
  334. bzero(us,sizeof(struct in_addr));
  335. return -2;
  336. } else if (res) {
  337. /* We've already warned in subroutine */
  338. return -1;
  339. }
  340. return 0;
  341. #endif
  342. }
  343. int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
  344. {
  345. char ourhost[MAXHOSTNAMELEN]="";
  346. struct ast_hostent ahp;
  347. struct hostent *hp;
  348. struct in_addr saddr;
  349. /* just use the bind address if it is nonzero */
  350. if (ntohl(bindaddr.sin_addr.s_addr)) {
  351. memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip));
  352. return 0;
  353. }
  354. /* try to use our hostname */
  355. if (gethostname(ourhost, sizeof(ourhost)-1)) {
  356. ast_log(LOG_WARNING, "Unable to get hostname\n");
  357. } else {
  358. hp = ast_gethostbyname(ourhost, &ahp);
  359. if (hp) {
  360. memcpy(ourip, hp->h_addr, sizeof(*ourip));
  361. return 0;
  362. }
  363. }
  364. /* A.ROOT-SERVERS.NET. */
  365. if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip))
  366. return 0;
  367. return -1;
  368. }