PageRenderTime 25ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/user/blkfin-apps/inetutils/inetutils-1.6/talkd/acl.c

https://bitbucket.org/thelearninglabs/uclinux-distro-tll-public
C | 331 lines | 268 code | 43 blank | 20 comment | 56 complexity | a00fed714cc72f8d6d17246b24099133 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-3.0, Unlicense, GPL-2.0, GPL-3.0, CC-BY-SA-3.0, AGPL-1.0, ISC, MIT, 0BSD, LGPL-2.0
  1. /* Copyright (C) 1998,2001,2007 Free Software Foundation, Inc.
  2. This file is part of GNU Inetutils.
  3. GNU Inetutils is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3, or (at your option)
  6. any later version.
  7. GNU Inetutils is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with GNU Inetutils; see the file COPYING. If not, write
  13. to the Free Software Foundation, Inc., 51 Franklin Street,
  14. Fifth Floor, Boston, MA 02110-1301 USA. */
  15. #include <intalkd.h>
  16. #include <pwd.h>
  17. #include <regex.h>
  18. #include <ctype.h>
  19. #include "argcv.h"
  20. typedef struct netdef netdef_t;
  21. struct netdef
  22. {
  23. netdef_t *next;
  24. unsigned int ipaddr;
  25. unsigned int netmask;
  26. };
  27. #define ACT_ALLOW 0
  28. #define ACT_DENY 1
  29. typedef struct acl acl_t;
  30. struct acl
  31. {
  32. acl_t *next;
  33. regex_t re;
  34. netdef_t *netlist;
  35. int action;
  36. };
  37. acl_t *acl_head, *acl_tail;
  38. #define DOTTED_QUAD_LEN 16
  39. static int
  40. read_address (char **line_ptr, char *ptr)
  41. {
  42. char *startp = *line_ptr;
  43. char *endp;
  44. int dotcount = 0;
  45. for (endp = startp; *endp; endp++, ptr++)
  46. if (!(isdigit (*endp) || *endp == '.'))
  47. break;
  48. else if (endp < startp + DOTTED_QUAD_LEN)
  49. {
  50. if (*endp == '.')
  51. dotcount++;
  52. *ptr = *endp;
  53. }
  54. else
  55. break;
  56. *line_ptr = endp;
  57. *ptr = 0;
  58. return dotcount;
  59. }
  60. static netdef_t *
  61. netdef_parse (char *str)
  62. {
  63. unsigned int ipaddr, netmask;
  64. netdef_t *netdef;
  65. char ipbuf[DOTTED_QUAD_LEN + 1];
  66. if (strcmp (str, "any") == 0)
  67. {
  68. ipaddr = 0;
  69. netmask = 0;
  70. }
  71. else
  72. {
  73. read_address (&str, ipbuf);
  74. ipaddr = inet_addr (ipbuf);
  75. if (ipaddr == INADDR_NONE)
  76. return NULL;
  77. if (*str == 0)
  78. netmask = 0xfffffffful;
  79. else if (*str != '/')
  80. return NULL;
  81. else
  82. {
  83. str++;
  84. if (read_address (&str, ipbuf) == 0)
  85. {
  86. /* netmask length */
  87. unsigned int len = strtoul (ipbuf, NULL, 0);
  88. if (len > 32)
  89. return NULL;
  90. netmask = 0xfffffffful >> (32 - len);
  91. netmask <<= (32 - len);
  92. /*FIXME: hostorder? */
  93. }
  94. else
  95. netmask = inet_network (ipbuf);
  96. netmask = htonl (netmask);
  97. }
  98. }
  99. netdef = malloc (sizeof *netdef);
  100. if (!netdef)
  101. {
  102. syslog (LOG_ERR, "out of memory");
  103. exit (1);
  104. }
  105. netdef->next = NULL;
  106. netdef->ipaddr = ipaddr;
  107. netdef->netmask = netmask;
  108. return netdef;
  109. }
  110. void
  111. read_acl (char *config_file)
  112. {
  113. FILE *fp;
  114. int line;
  115. char buf[128];
  116. char *ptr;
  117. if (!config_file)
  118. return;
  119. fp = fopen (config_file, "r");
  120. if (!fp)
  121. {
  122. syslog (LOG_ERR, "can't open config file %s: %m", config_file);
  123. return;
  124. }
  125. line = 0;
  126. while ((ptr = fgets (buf, sizeof buf, fp)))
  127. {
  128. int len, i;
  129. int argc;
  130. char **argv;
  131. int action;
  132. regex_t re;
  133. netdef_t *head, *tail;
  134. acl_t *acl;
  135. line++;
  136. len = strlen (ptr);
  137. if (len > 0 && ptr[len - 1] == '\n')
  138. ptr[--len] = 0;
  139. while (*ptr && isspace (*ptr))
  140. ptr++;
  141. if (!*ptr || *ptr == '#')
  142. continue;
  143. argcv_get (ptr, "", &argc, &argv);
  144. if (argc < 2)
  145. {
  146. syslog (LOG_ERR, "%s:%d: too few fields", config_file, line);
  147. argcv_free (argc, argv);
  148. continue;
  149. }
  150. if (strcmp (argv[0], "allow") == 0)
  151. action = ACT_ALLOW;
  152. else if (strcmp (argv[0], "deny") == 0)
  153. action = ACT_DENY;
  154. else
  155. {
  156. syslog (LOG_ERR, "%s:%d: unknown keyword", config_file, line);
  157. argcv_free (argc, argv);
  158. continue;
  159. }
  160. if (regcomp (&re, argv[1], 0) != 0)
  161. {
  162. syslog (LOG_ERR, "%s:%d: bad regexp", config_file, line);
  163. argcv_free (argc, argv);
  164. continue;
  165. }
  166. head = tail = NULL;
  167. for (i = 2; i < argc; i++)
  168. {
  169. netdef_t *cur = netdef_parse (argv[i]);
  170. if (!cur)
  171. {
  172. syslog (LOG_ERR, "%s:%d: can't parse netdef: %s",
  173. config_file, line, argv[i]);
  174. continue;
  175. }
  176. if (!tail)
  177. head = cur;
  178. else
  179. tail->next = cur;
  180. tail = cur;
  181. }
  182. argcv_free (argc, argv);
  183. acl = malloc (sizeof *acl);
  184. if (!acl)
  185. {
  186. syslog (LOG_CRIT, "out of memory");
  187. exit (1);
  188. }
  189. acl->next = NULL;
  190. acl->action = action;
  191. acl->netlist = head;
  192. acl->re = re;
  193. if (!acl_tail)
  194. acl_head = acl;
  195. else
  196. acl_tail->next = acl;
  197. acl_tail = acl;
  198. }
  199. fclose (fp);
  200. }
  201. static acl_t *
  202. open_users_acl (char *name)
  203. {
  204. char *filename;
  205. struct passwd *pw;
  206. acl_t *mark;
  207. pw = getpwnam (name);
  208. if (!pw)
  209. return NULL;
  210. filename =
  211. malloc (strlen (pw->pw_dir) + sizeof (USER_ACL_NAME) +
  212. 2 /* Null and separator. */ );
  213. if (!filename)
  214. {
  215. syslog (LOG_ERR, "out of memory");
  216. return NULL;
  217. }
  218. sprintf (filename, "%s/%s", pw->pw_dir, USER_ACL_NAME);
  219. mark = acl_tail;
  220. read_acl (filename);
  221. free (filename);
  222. return mark;
  223. }
  224. static void
  225. netdef_free (netdef_t * netdef)
  226. {
  227. netdef_t *next;
  228. while (netdef)
  229. {
  230. next = netdef->next;
  231. free (netdef);
  232. netdef = next;
  233. }
  234. }
  235. static void
  236. acl_free (acl_t * acl)
  237. {
  238. acl_t *next;
  239. while (acl)
  240. {
  241. next = acl->next;
  242. regfree (&acl->re);
  243. netdef_free (acl->netlist);
  244. free (acl);
  245. acl = next;
  246. }
  247. }
  248. static void
  249. discard_acl (acl_t * mark)
  250. {
  251. if (mark)
  252. {
  253. acl_free (mark->next);
  254. acl_tail = mark;
  255. acl_tail->next = NULL;
  256. }
  257. else
  258. acl_head = acl_tail = NULL;
  259. }
  260. int
  261. acl_match (CTL_MSG * msg, struct sockaddr_in *sa_in)
  262. {
  263. acl_t *acl, *mark;
  264. unsigned int ip;
  265. mark = open_users_acl (msg->r_name);
  266. ip = sa_in->sin_addr.s_addr;
  267. for (acl = acl_head; acl; acl = acl->next)
  268. {
  269. netdef_t *net;
  270. for (net = acl->netlist; net; net = net->next)
  271. {
  272. if (net->ipaddr == (ip & net->netmask))
  273. {
  274. if (regexec (&acl->re, msg->l_name, 0, NULL, 0) == 0)
  275. {
  276. discard_acl (mark);
  277. return acl->action;
  278. }
  279. }
  280. }
  281. }
  282. discard_acl (mark);
  283. return ACT_ALLOW;
  284. }