~ubuntu-branches/ubuntu/saucy/nut/saucy

« back to all changes in this revision

Viewing changes to server/access.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Quette
  • Date: 2004-05-28 13:10:01 UTC
  • mto: (16.1.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20040528131001-yj2m9qcez4ya2w14
Tags: upstream-1.4.2
ImportĀ upstreamĀ versionĀ 1.4.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* access.c - functions for access control
 
2
 
 
3
   Copyright (C) 2003  Russell Kroll <rkroll@exploits.org>
 
4
 
 
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.
 
9
 
 
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.
 
14
 
 
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
 
18
*/
 
19
 
 
20
#include <sys/types.h>
 
21
#include <sys/socket.h>
 
22
#include <netinet/in.h>
 
23
#include <arpa/inet.h>
 
24
 
 
25
#include "common.h"
 
26
#include "access.h"
 
27
#include "levels.h"
 
28
 
 
29
        struct  acl_t   *acl_head = NULL;
 
30
        struct  access_t        *access_head = NULL;
 
31
 
 
32
/* see if <addr> matches the acl <aclname> */
 
33
int acl_check(const char *aclname, const struct sockaddr_in *addr)
 
34
{
 
35
        struct  acl_t   *tmp;
 
36
        int     aclchk, addrchk;
 
37
 
 
38
        tmp = acl_head;
 
39
        while (tmp != NULL) {
 
40
                if (!strcmp(tmp->name, aclname)) {
 
41
                        aclchk = tmp->addr & tmp->mask;
 
42
                        addrchk = ntohl(addr->sin_addr.s_addr) & tmp->mask;
 
43
 
 
44
                        if (aclchk == addrchk) 
 
45
                                return 1;       /* match */
 
46
                }
 
47
 
 
48
                tmp = tmp->next;
 
49
        }
 
50
 
 
51
        return 0;       /* not found */
 
52
}
 
53
 
 
54
/* this is only used for simple stuff: MONITOR and BASE */
 
55
int access_check(const struct sockaddr_in *addr, int level)
 
56
{
 
57
        struct  access_t        *tmp;
 
58
        int     ret;
 
59
 
 
60
        /* check for insanity */
 
61
        if (level > LEVEL_MONITOR) {
 
62
                upslogx(LOG_ERR, "checkaccess called with level=%d", level);
 
63
                return 0;       /* failed */
 
64
        }
 
65
 
 
66
        tmp = access_head;
 
67
 
 
68
        while (tmp != NULL) {
 
69
                ret = acl_check(tmp->aclname, addr);
 
70
 
 
71
                upsdebugx(3, "acl_check: %s: match %d, level %d (%d)", 
 
72
                        tmp->aclname, ret, tmp->level, level);
 
73
 
 
74
                /* if ip matches and access line provides the right level.. */
 
75
 
 
76
                if ((ret == 1) && (tmp->level >= level)) {
 
77
 
 
78
                        if (tmp->action == ACTION_GRANT)
 
79
                                return 1;       /* allowed */
 
80
 
 
81
                        upsdebugx(1, "access denied");
 
82
                        return 0;
 
83
                }       /* if (ip matches) && (level is provided) */
 
84
 
 
85
                /* otherwise ip didn't match or the level was inadequate */
 
86
 
 
87
                tmp = tmp->next;
 
88
        }
 
89
 
 
90
        /* default = deny */
 
91
        return 0;
 
92
}
 
93
 
 
94
/* add to the master list of ACL names */
 
95
void acl_add(const char *aclname, char *ipblock)
 
96
{
 
97
        struct  acl_t   *tmp, *last;
 
98
        char    *addr, *mask;
 
99
 
 
100
        /* are we sane? */
 
101
        if ((!aclname) || (!ipblock))
 
102
                return;
 
103
 
 
104
        /* ipblock must be in the form <addr>/<mask>    */
 
105
 
 
106
        mask = strchr(ipblock, '/');
 
107
 
 
108
        /* 192.168.1.1/32: valid */
 
109
        /* 192.168.1.1/255.255.255.255: valid */
 
110
        /* 192.168.1.1: invalid */
 
111
 
 
112
        if (!mask)      /* no slash = broken acl declaration */
 
113
                return;
 
114
 
 
115
        *mask++ = '\0';
 
116
        addr = ipblock;
 
117
 
 
118
        tmp = last = acl_head;
 
119
 
 
120
        while (tmp != NULL) {   /* find end */
 
121
                last = tmp;
 
122
                tmp = tmp->next;
 
123
        }
 
124
 
 
125
        tmp = xmalloc(sizeof (struct acl_t));
 
126
        tmp->name = xstrdup(aclname);
 
127
        tmp->addr = ntohl(inet_addr(addr));
 
128
        tmp->next = NULL;
 
129
 
 
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) << 
 
133
                                    (32 - atoi(mask)));
 
134
                else
 
135
                        tmp->mask = 0xffffffff; /* avoid overflow from 2^32 */
 
136
        }
 
137
        else
 
138
                tmp->mask = ntohl(inet_addr (mask));
 
139
 
 
140
        if (last == NULL)       /* first */
 
141
                acl_head = tmp;
 
142
        else
 
143
                last->next = tmp;
 
144
}
 
145
 
 
146
/* add to the access linked list */
 
147
void access_add(const char *action, const char *level, const char *aclname)
 
148
{
 
149
        struct  access_t        *tmp, *last;
 
150
 
 
151
        /* more sanity checking (null password is OK) */
 
152
        if ((!action) || (!level) || (!aclname))
 
153
                return;
 
154
 
 
155
        tmp = last = access_head;
 
156
 
 
157
        while (tmp != NULL) {   /* find end */
 
158
                last = tmp;
 
159
                tmp = tmp->next;
 
160
        }
 
161
 
 
162
        tmp = xmalloc(sizeof(struct access_t));
 
163
        tmp->action = 0;
 
164
        tmp->level = 0;
 
165
 
 
166
        if (!strcasecmp(action, "grant"))
 
167
                tmp->action = ACTION_GRANT;
 
168
        if (!strcasecmp(action, "deny"))
 
169
                tmp->action = ACTION_DENY;
 
170
 
 
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;
 
175
        }
 
176
 
 
177
        if (!strcasecmp(level, "base"))
 
178
                tmp->level = LEVEL_BASE;
 
179
        if (!strcasecmp(level, "monitor"))
 
180
                tmp->level = LEVEL_MONITOR;
 
181
 
 
182
        /* deprecated in 1.2, removed in 1.3 */
 
183
        if ((!strcasecmp(level, "login")) ||
 
184
           (!strcasecmp(level, "master"))) {
 
185
 
 
186
                upslogx(LOG_WARNING, "LOGIN and MASTER no longer supported "
 
187
                        " in upsd.conf - switch to upsd.users");
 
188
 
 
189
                /* give them something somewhat useful */
 
190
                tmp->level = LEVEL_MONITOR;
 
191
        }
 
192
 
 
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");
 
197
 
 
198
                /* but don't leave them totally out in the cold */
 
199
                tmp->level = LEVEL_MONITOR;
 
200
        }
 
201
 
 
202
        if (!strcasecmp(level, "all"))
 
203
                tmp->level = LEVEL_ALL;
 
204
 
 
205
        tmp->aclname = xstrdup(aclname);
 
206
        tmp->next = NULL;
 
207
 
 
208
        if (last == NULL)       /* first */
 
209
                access_head = tmp;
 
210
        else
 
211
                last->next = tmp;       
 
212
}
 
213
 
 
214
void acl_free(void)
 
215
{
 
216
        struct  acl_t   *ptr, *next;
 
217
 
 
218
        ptr = acl_head;
 
219
 
 
220
        while (ptr) {
 
221
                next = ptr->next;
 
222
                
 
223
                if (ptr->name)
 
224
                        free(ptr->name);
 
225
                free(ptr);
 
226
 
 
227
                ptr = next;
 
228
        }
 
229
 
 
230
        acl_head = NULL;
 
231
}
 
232
 
 
233
void access_free(void)
 
234
{
 
235
        struct  access_t        *ptr, *next;
 
236
 
 
237
        ptr = access_head;
 
238
 
 
239
        while (ptr) {
 
240
                next = ptr->next;
 
241
 
 
242
                if (ptr->aclname)
 
243
                        free(ptr->aclname);
 
244
                free(ptr);
 
245
 
 
246
                ptr = next;
 
247
        }
 
248
 
 
249
        access_head = NULL;
 
250
}