1
/* access.c - functions for access control
3
Copyright (C) 2003 Russell Kroll <rkroll@exploits.org>
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
#include <sys/types.h>
21
#include <sys/socket.h>
22
#include <netinet/in.h>
23
#include <arpa/inet.h>
29
struct acl_t *acl_head = NULL;
30
struct access_t *access_head = NULL;
32
/* see if <addr> matches the acl <aclname> */
33
int acl_check(const char *aclname, const struct sockaddr_in *addr)
40
if (!strcmp(tmp->name, aclname)) {
41
aclchk = tmp->addr & tmp->mask;
42
addrchk = ntohl(addr->sin_addr.s_addr) & tmp->mask;
44
if (aclchk == addrchk)
51
return 0; /* not found */
54
/* this is only used for simple stuff: MONITOR and BASE */
55
int access_check(const struct sockaddr_in *addr, int level)
60
/* check for insanity */
61
if (level > LEVEL_MONITOR) {
62
upslogx(LOG_ERR, "checkaccess called with level=%d", level);
63
return 0; /* failed */
69
ret = acl_check(tmp->aclname, addr);
71
upsdebugx(3, "acl_check: %s: match %d, level %d (%d)",
72
tmp->aclname, ret, tmp->level, level);
74
/* if ip matches and access line provides the right level.. */
76
if ((ret == 1) && (tmp->level >= level)) {
78
if (tmp->action == ACTION_GRANT)
79
return 1; /* allowed */
81
upsdebugx(1, "access denied");
83
} /* if (ip matches) && (level is provided) */
85
/* otherwise ip didn't match or the level was inadequate */
94
/* add to the master list of ACL names */
95
void acl_add(const char *aclname, char *ipblock)
97
struct acl_t *tmp, *last;
101
if ((!aclname) || (!ipblock))
104
/* ipblock must be in the form <addr>/<mask> */
106
mask = strchr(ipblock, '/');
108
/* 192.168.1.1/32: valid */
109
/* 192.168.1.1/255.255.255.255: valid */
110
/* 192.168.1.1: invalid */
112
if (!mask) /* no slash = broken acl declaration */
118
tmp = last = acl_head;
120
while (tmp != NULL) { /* find end */
125
tmp = xmalloc(sizeof (struct acl_t));
126
tmp->name = xstrdup(aclname);
127
tmp->addr = ntohl(inet_addr(addr));
130
if (strstr(mask, ".") == NULL) { /* must be a /nn CIDR type block */
131
if (atoi(mask) != 32)
132
tmp->mask = ((unsigned int) ((1 << atoi(mask)) - 1) <<
135
tmp->mask = 0xffffffff; /* avoid overflow from 2^32 */
138
tmp->mask = ntohl(inet_addr (mask));
140
if (last == NULL) /* first */
146
/* add to the access linked list */
147
void access_add(const char *action, const char *level, const char *aclname)
149
struct access_t *tmp, *last;
151
/* more sanity checking (null password is OK) */
152
if ((!action) || (!level) || (!aclname))
155
tmp = last = access_head;
157
while (tmp != NULL) { /* find end */
162
tmp = xmalloc(sizeof(struct access_t));
166
if (!strcasecmp(action, "grant"))
167
tmp->action = ACTION_GRANT;
168
if (!strcasecmp(action, "deny"))
169
tmp->action = ACTION_DENY;
171
/* we don't do "drop" any more - convert to deny */
172
if (!strcasecmp(action, "drop")) {
173
upslogx(LOG_WARNING, "ACCESS action of 'drop' deprecated; change to 'deny'");
174
tmp->action = ACTION_DENY;
177
if (!strcasecmp(level, "base"))
178
tmp->level = LEVEL_BASE;
179
if (!strcasecmp(level, "monitor"))
180
tmp->level = LEVEL_MONITOR;
182
/* deprecated in 1.2, removed in 1.3 */
183
if ((!strcasecmp(level, "login")) ||
184
(!strcasecmp(level, "master"))) {
186
upslogx(LOG_WARNING, "LOGIN and MASTER no longer supported "
187
" in upsd.conf - switch to upsd.users");
189
/* give them something somewhat useful */
190
tmp->level = LEVEL_MONITOR;
193
/* deprecated in 1.0, removed in 1.1 */
194
if (!strcasecmp(level, "manager")) {
195
upslogx(LOG_WARNING, "ACCESS type manager no longer supported -"
196
" switch to upsd.users");
198
/* but don't leave them totally out in the cold */
199
tmp->level = LEVEL_MONITOR;
202
if (!strcasecmp(level, "all"))
203
tmp->level = LEVEL_ALL;
205
tmp->aclname = xstrdup(aclname);
208
if (last == NULL) /* first */
216
struct acl_t *ptr, *next;
233
void access_free(void)
235
struct access_t *ptr, *next;