/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999-2021 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see . */
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
#include
#include
#include
struct mu_sockaddr *target_sa;
mu_acl_t acl;
void
read_rules (FILE *fp)
{
char buf[512];
int line = 0;
int wsflags = MU_WRDSF_DEFFLAGS | MU_WRDSF_COMMENT;
struct mu_wordsplit ws;
int rc;
rc = mu_acl_create (&acl);
if (rc)
{
mu_error ("cannot create acl: %s", mu_strerror (rc));
exit (1);
}
ws.ws_comment = "#";
while (fgets (buf, sizeof buf, fp))
{
struct mu_cidr cidr;
mu_acl_action_t action;
void *data = NULL;
int len = strlen (buf);
if (len == 0)
continue;
if (buf[len-1] != '\n')
{
mu_error ("%d: line too long", line);
continue;
}
buf[len-1] = 0;
line++;
if (buf[0] == '#')
continue;
if (mu_wordsplit (buf, &ws, wsflags))
{
mu_error ("cannot split line `%s': %s", buf,
mu_wordsplit_strerror (&ws));
continue;
}
wsflags |= MU_WRDSF_REUSE;
if (ws.ws_wordc < 2)
{
mu_error ("%d: invalid input", line);
continue;
}
if (strcmp (ws.ws_wordv[1], "any") == 0)
memset (&cidr, 0, sizeof (cidr));
else
{
rc = mu_cidr_from_string (&cidr, ws.ws_wordv[1]);
if (rc)
{
mu_error ("%d: invalid source CIDR: %s",
line, mu_strerror (rc));
continue;
}
}
/* accept addr
deny addr
log addr [rest ...]
exec addr [rest ...]
execif addr rest ....]
*/
if (mu_acl_string_to_action (ws.ws_wordv[0], &action))
{
mu_error ("%d: invalid command", line);
continue;
}
rc = 0;
switch (action)
{
case mu_acl_accept:
case mu_acl_deny:
break;
case mu_acl_log:
case mu_acl_exec:
case mu_acl_ifexec:
data = strdup (ws.ws_wordv[2]);
if (!data)
{
rc = ENOMEM;
mu_error ("%d: %s", line, mu_strerror (rc));
}
}
if (rc == 0)
{
rc = mu_acl_append (acl, action, data, &cidr);
if (rc)
mu_error ("%d: cannot append acl entry: %s", line,
mu_strerror (rc));
}
}
mu_wordsplit_free (&ws);
}
int
main (int argc, char **argv)
{
int rc;
FILE *file = NULL;
mu_acl_result_t result;
mu_set_program_name (argv[0]);
while ((rc = getopt (argc, argv, "Dd:a:f:")) != EOF)
{
switch (rc)
{
case 'D':
mu_debug_line_info = 1;
break;
case 'd':
mu_debug_parse_spec (optarg);
break;
case 'a':
rc = mu_sockaddr_from_node (&target_sa, optarg, NULL, NULL);
if (rc)
{
mu_error ("mu_sockaddr_from_node: %s", mu_strerror (rc));
exit (1);
}
break;
case 'f':
file = fopen (optarg, "r");
if (file == 0)
{
mu_error ("cannot open file %s: %s", optarg,
mu_strerror (errno));
exit (1);
}
break;
default:
exit (1);
}
}
argv += optind;
argc -= optind;
read_rules (file ? file : stdin);
rc = mu_acl_check_sockaddr (acl, target_sa->addr, target_sa->addrlen,
&result);
if (rc)
{
mu_error ("mu_acl_check_sockaddr failed: %s", mu_strerror (rc));
exit (1);
}
switch (result)
{
case mu_acl_result_undefined:
puts ("undefined");
break;
case mu_acl_result_accept:
puts ("accept");
break;
case mu_acl_result_deny:
puts ("deny");
break;
}
exit (0);
}