]> git.saurik.com Git - apple/network_cmds.git/blame - ypserv.tproj/acl.c
network_cmds-245.1.3.tar.gz
[apple/network_cmds.git] / ypserv.tproj / acl.c
CommitLineData
b7080c8e
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
ffda1f4a
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
b7080c8e
A
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
ffda1f4a
A
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
b7080c8e
A
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/* $OpenBSD: acl.c,v 1.5 1997/08/05 09:26:55 maja Exp $ */
24
25/*
26 * Copyright (c) 1994 Mats O Jansson <moj@stacken.kth.se>
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by Mats O Jansson
40 * 4. The name of the author may not be used to endorse or promote products
41 * derived from this software without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
44 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
47 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 */
55
56#ifndef LINT
57static char rcsid[] = "$OpenBSD: acl.c,v 1.5 1997/08/05 09:26:55 maja Exp $";
58#endif
59
60#include <sys/types.h>
61#include <sys/socket.h>
62#include <netinet/in.h>
63#include <arpa/inet.h>
64#include <stdio.h>
65#include <stdlib.h>
66#include <ctype.h>
67#include <netdb.h>
68#include "acl.h"
69
70#define TRUE 1
71#define FALSE 0
72
73static struct aclent *acl_root = NULL;
74
75static int acl_read_line(fp, buf, size)
76FILE *fp;
77char *buf;
78int size;
79{
80 int len = 0;
81 char *c,*p,l;
82
83 /* Read a line, and remove any comment, trim space */
84
85 do {
86 while (fgets(buf, size, fp)) {
87 c = buf;
88 while(*c != '\0') {
89 if ((*c == '#') || (*c == '\n')) {
90 *c = '\0';
91 } else {
92 c++;
93 }
94 }
95
96 c = p = buf; l = ' ';
97 while(*c != '\0') {
98 if ((isspace(l) != 0) && (isspace(*c) != 0)) {
99 c++;
100 } else {
101 l = *c++; *p = l; p++;
102 }
103 }
104 *p = '\0';
105
106 if (p != buf) {
107 --p;
108 if (isspace(*p) != 0) {
109 *p = '\0';
110 }
111 }
112
113 len = strlen(buf);
114 return len + 1;
115 }
116 } while (size > 0 && !feof(fp));
117
118 return len;
119}
120
121int
2b484d24 122yp_acl_check_host(addr)
b7080c8e
A
123struct in_addr *addr;
124{
125 struct aclent *p;
126
127 p = acl_root;
128 while (p != NULL) {
129 if ((addr->s_addr & p->s_mask) == p->s_addr) {
130 return(p->allow);
131 }
132 p = p->next;
133 }
134 return(TRUE);
135}
136
137void
138acl_add_net(allow,addr,mask)
139int allow;
140struct in_addr *addr,*mask;
141{
142
143 struct aclent *acl,*p;
144
145 acl = (struct aclent *) malloc((unsigned) sizeof(struct aclent));
146
147 acl->next = NULL;
148 acl->allow = allow;
149 acl->s_addr = addr->s_addr;
150 acl->s_mask = mask->s_addr;
151
152 if (acl_root == NULL) {
153 acl_root = acl;
154 } else {
155 p = acl_root;
156 while (p->next != NULL)
157 p = p->next;
158 p->next = acl;
159 }
160
161}
162
163void
164acl_add_host(allow,addr)
165int allow;
166struct in_addr *addr;
167{
168 struct in_addr mask;
169
170 mask.s_addr = htonl(0xffffffff);
171
172 acl_add_net(allow,addr,&mask);
173}
174
175int
2b484d24 176yp_acl_init(file)
b7080c8e
A
177char *file;
178{
179 char data_line[1024];
180 int line_no = 0;
181 int len,i;
182 int allow = TRUE;
183 int error_cnt = 0;
184 char *p,*k;
185 int state;
186 struct in_addr addr,mask,*host_addr;
187 struct hostent *host;
188 struct netent *net;
189 FILE *data_file = NULL;
190
191 if (file != NULL) {
192 data_file = fopen(file,"r");
193 };
194
195 while ((data_file != NULL) &&
196 (acl_read_line(data_file,data_line,sizeof(data_line)))) {
197
198 line_no++;
199
200 len = strlen(data_line);
201 if (len == 0) {
202 continue;
203 }
204
205 p = (char *) &data_line;
206
207 /* State 1: Initial State */
208
209 state = ACLS_INIT;
210 addr.s_addr = mask.s_addr = 0;
211
212 k = p; i = 0; /* save start of verb */
213 while ((*p != '\0') &&
214 (!isspace(*p = tolower(*p)))) {
215 p++; i++;
216 };
217
218 if (*p != '\0') {
219 *p++ = '\0';
220 }
221
222 if (strcmp(k,"allow") == 0) {
223 allow = TRUE;
224 state = ACLS_ALLOW;
225 }
226
227 if (strcmp(k,"deny") == 0) {
228 allow = FALSE;
229 state = ACLS_DENY;
230 }
231
232 if (state == ACLS_INIT) {
233 state = ACLE_UVERB;
234 }
235
236 /* State 2: allow row */
237 /* State 3: deny row */
238
239 if ((*p != '\0') &&
240 ((state == ACLS_ALLOW) || (state == ACLS_DENY))) {
241
242 k = p; i = 0; /* save start of verb */
243 while ((*p != '\0') &&
244 (!isspace(*p = tolower(*p)))) {
245 p++; i++;
246 };
247
248 if (*p != '\0') {
249 *p++ = '\0';
250 }
251
252 if (strcmp(k,"all") == 0) {
253 state = state + ACLD_ALL;
254 }
255
256 if (strcmp(k,"host") == 0) {
257 state = state + ACLD_HOST;
258 }
259
260 if (strcmp(k,"net") == 0) {
261 state = state + ACLD_NET;
262 }
263
264 if ((state == ACLS_ALLOW) || (state == ACLS_DENY)) {
265 state = ACLE_U2VERB;
266 }
267
268 }
269
270 if ((state == ACLS_ALLOW) || (state == ACLS_DENY)) {
271 state = ACLE_UEOL;
272 }
273
274 /* State 4 & 5: all state, remove any comment */
275
276 if ((*p == '\0') &&
277 ((state == ACLS_ALLOW_ALL) || (state == ACLS_DENY_ALL))) {
278 acl_add_net(allow,&addr,&mask);
279 state = ACLE_OK;
280 }
281
282 /* State 6 & 7: host line */
283 /* State 8 & 9: net line */
284
285 if ((*p != '\0') &&
286 (state >= ACLS_ALLOW_HOST) && (state <= ACLS_DENY_NET)) {
287
288 k = p; i = 0; /* save start of verb */
289 while ((*p != '\0') &&
290 (!isspace(*p = tolower(*p)))) {
291 p++; i++;
292 };
293
294 if (*p != '\0') {
295 *p++ = '\0';
296 }
297
298 if ((state == ACLS_ALLOW_HOST) || (state == ACLS_DENY_HOST)) {
299 if ((*k >= '0') && (*k <= '9')) {
300 (void)inet_aton(k,&addr);
301 acl_add_host(allow,&addr);
302 state = state + ACLD_HOST_DONE;
303 } else {
304 host = gethostbyname(k);
305 if (host == NULL) {
306 state = ACLE_NOHOST;
307 } else {
308 if (host->h_addrtype == AF_INET) {
309 while ((host_addr = (struct in_addr *) *host->h_addr_list++)
310 != NULL)
311 acl_add_host(allow,host_addr);
312 }
313 state = state + ACLD_HOST_DONE;
314 }
315 }
316 }
317
318 if ((state == ACLS_ALLOW_NET) || (state == ACLS_DENY_NET)) {
319 if ((*k >= '0') && (*k <= '9')) {
320 (void)inet_aton(k,&addr);
321 state = state + ACLD_NET_DONE;
322 } else {
323 net = getnetbyname(k);
324 if (net == NULL) {
325 state = ACLE_NONET;
326 } else {
327 addr.s_addr = ntohl(net->n_net);
328 state = state + ACLD_NET_DONE;
329 }
330 }
331 }
332
333 }
334
335 if ((state >= ACLS_ALLOW_HOST) && (state <= ACLS_DENY_NET)) {
336 state = ACLE_UEOL;
337 }
338
339 /* State 10 & 11: allow/deny host line */
340
341 if ((*p == '\0') &&
342 ((state == ACLS_ALLOW_HOST_DONE) || (state == ACLS_DENY_HOST_DONE))) {
343 state = ACLE_OK;
344 }
345
346 /* State 12 & 13: allow/deny net line */
347
348 if ((*p == '\0') &&
349 ((state == ACLS_ALLOW_NET_DONE) || (state == ACLS_DENY_NET_DONE))) {
350 mask.s_addr = htonl(0xffffff00);
351 if (ntohl(addr.s_addr) < 0xc0000000) {
352 mask.s_addr = htonl(0xffff0000);
353 }
354 if (ntohl(addr.s_addr) < 0x80000000) {
355 mask.s_addr = htonl(0xff000000);
356 }
357 acl_add_net(allow,&addr,&mask);
358 state = ACLE_OK;
359 }
360
361 if ((*p != '\0') &&
362 ((state == ACLS_ALLOW_NET_DONE) || (state == ACLS_DENY_NET_DONE))) {
363
364 k = p; i = 0; /* save start of verb */
365 while ((*p != '\0') &&
366 (!isspace(*p = tolower(*p)))) {
367 p++; i++;
368 };
369
370 if (*p != '\0') {
371 *p++ = '\0';
372 }
373
374 if (strcmp(k,"netmask") == 0) {
375 state = state + ACLD_NET_MASK;
376 }
377
378 if ((state == ACLS_ALLOW_NET_DONE) || (state == ACLS_DENY_NET_DONE)) {
379 state = ACLE_NONETMASK;
380 }
381
382 }
383
384 /* State 14 & 15: allow/deny net netmask line */
385
386 if ((*p != '\0') &&
387 ((state == ACLS_ALLOW_NET_MASK) || (state == ACLS_DENY_NET_MASK))) {
388
389 k = p; i = 0; /* save start of verb */
390 while ((*p != '\0') &&
391 (!isspace(*p = tolower(*p)))) {
392 p++; i++;
393 };
394
395 if (*p != '\0') {
396 *p++ = '\0';
397 }
398
399 if ((state == ACLS_ALLOW_NET_MASK) || (state == ACLS_DENY_NET_MASK)) {
400 if ((*k >= '0') && (*k <= '9')) {
401 (void)inet_aton(k,&mask);
402 state = state + ACLD_NET_EOL;
403 } else {
404 net = getnetbyname(k);
405 if (net == NULL) {
406 state = ACLE_NONET;
407 } else {
408 mask.s_addr = ntohl(net->n_net);
409 state = state + ACLD_NET_EOL;
410 }
411 }
412 }
413
414 }
415
416 if ((state == ACLS_ALLOW_NET_MASK) || (state == ACLS_DENY_NET_MASK)) {
417 state = ACLE_UEOL;
418 }
419
420 /* State 16 & 17: allow/deny host line */
421
422 if ((*p == '\0') &&
423 ((state == ACLS_ALLOW_NET_EOL) || (state == ACLS_DENY_NET_EOL))) {
424 acl_add_net(allow,&addr,&mask);
425 state = ACLE_OK;
426 }
427
428 switch (state) {
429 case ACLE_NONETMASK:
430 fprintf(stderr,"acl: excpected \"netmask\" missing at line %d\n",line_no);
431 break;
432 case ACLE_NONET:
433 error_cnt++;
434 fprintf(stderr,"acl: unknown network at line %d\n",line_no);
435 break;
436 case ACLE_NOHOST:
437 error_cnt++;
438 fprintf(stderr,"acl: unknown host at line %d\n",line_no);
439 break;
440 case ACLE_UVERB:
441 error_cnt++;
442 fprintf(stderr,"acl: unknown verb at line %d\n",line_no);
443 break;
444 case ACLE_U2VERB:
445 error_cnt++;
446 fprintf(stderr,"acl: unknown secondary verb at line %d\n",line_no);
447 break;
448 case ACLE_UEOL:
449 error_cnt++;
450 fprintf(stderr,"acl: unexpected end of line at line %d\n",line_no);
451 break;
452 case ACLE_OK:
453 break;
454 default:
455 error_cnt++;
456 fprintf(stderr,"acl: unexpected state %d %s\n",state,k);
457 }
458
459 }
460
461 if (data_file != NULL) {
462 (void)fflush(stderr);
463 (void)fclose(data_file);
464 }
465
466 /* Always add a last allow all if file don't exists or */
467 /* the file doesn't cover all cases. */
468
469 addr.s_addr = mask.s_addr = 0;
470 allow = TRUE;
471 acl_add_net(allow,&addr,&mask);
472
473 return(error_cnt);
474
475}
476
477int
2b484d24 478yp_acl_securenet(file)
b7080c8e
A
479char *file;
480{
481 char data_line[1024];
482 int line_no = 0;
483 int len,i;
484 int allow = TRUE;
485 int error_cnt = 0;
486 char *p,*k;
487 int state;
488 struct in_addr addr,mask;
489 struct netent *net;
490 FILE *data_file = NULL;
491
492 if (file != NULL) {
493 data_file = fopen(file,"r");
494 };
495
496 /* Always add a localhost allow first, to be compatable with sun */
497
498 addr.s_addr = htonl(0x7f000001);
499 mask.s_addr = htonl(0xffffffff);
500 allow = TRUE;
501 acl_add_net(allow,&addr,&mask);
502
503 while ((data_file != NULL) &&
504 (acl_read_line(data_file,data_line,sizeof(data_line)))) {
505
506 line_no++;
507
508 len = strlen(data_line);
509 if (len == 0) {
510 continue;
511 }
512
513 p = (char *) &data_line;
514
515 /* State 1: Initial State */
516
517 state = ACLS_INIT;
518 addr.s_addr = mask.s_addr = 0;
519
520 k = p; i = 0; /* save start of verb */
521 while ((*p != '\0') &&
522 (!isspace(*p = tolower(*p)))) {
523 p++; i++;
524 };
525
526 if (*p != '\0') {
527 *p++ = '\0';
528 state = ACLS_ALLOW_NET_MASK;
529 }
530
531 if (state == ACLS_INIT) {
532 state = ACLE_UEOL;
533 }
534
535 if (state == ACLS_ALLOW_NET_MASK) {
536
537 if ((*k >= '0') && (*k <= '9')) {
538 (void)inet_aton(k,&mask);
539 state = ACLS_ALLOW_NET;
540 } else {
541 net = getnetbyname(k);
542 if (net == NULL) {
543 state = ACLE_NONET;
544 } else {
545 mask.s_addr = ntohl(net->n_net);
546 state = ACLS_ALLOW_NET;
547 }
548 }
549
550 k = p; i = 0; /* save start of verb */
551 while ((*p != '\0') &&
552 (!isspace(*p = tolower(*p)))) {
553 p++; i++;
554 };
555
556 if (*p != '\0') {
557 *p++ = '\0';
558 }
559 }
560
561 if ((state == ACLS_ALLOW_NET_MASK)) {
562 state = ACLE_UEOL;
563 }
564
565 if (state == ACLS_ALLOW_NET) {
566
567 if ((*k >= '0') && (*k <= '9')) {
568 (void)inet_aton(k,&addr);
569 state = ACLS_ALLOW_NET_EOL;
570 } else {
571 net = getnetbyname(k);
572 if (net == NULL) {
573 state = ACLE_NONET;
574 } else {
575 addr.s_addr = ntohl(net->n_net);
576 state = ACLS_ALLOW_NET_EOL;
577 }
578 }
579 }
580
581 if ((state == ACLS_ALLOW_NET)) {
582 state = ACLE_UEOL;
583 }
584
585 if ((*p == '\0') && (state == ACLS_ALLOW_NET_EOL)) {
586 acl_add_net(allow,&addr,&mask);
587 state = ACLE_OK;
588 }
589
590 switch (state) {
591 case ACLE_NONET:
592 error_cnt++;
593 fprintf(stderr,"securenet: unknown network at line %d\n",line_no);
594 break;
595 case ACLE_UEOL:
596 error_cnt++;
597 fprintf(stderr,"securenet: unexpected end of line at line %d\n",line_no);
598 break;
599 case ACLE_OK:
600 break;
601 default:
602 error_cnt++;
603 fprintf(stderr,"securenet: unexpected state %d %s\n",state,k);
604 }
605
606 }
607
608 if (data_file != NULL) {
609 (void)fflush(stderr);
610 (void)fclose(data_file);
611
612 /* Always add a last deny all if file exists */
613
614 addr.s_addr = mask.s_addr = 0;
615 allow = FALSE;
616 acl_add_net(allow,&addr,&mask);
617
618 }
619
620 /* Always add a last allow all if file don't exists */
621
622 addr.s_addr = mask.s_addr = 0;
623 allow = TRUE;
624 acl_add_net(allow,&addr,&mask);
625
626 return(error_cnt);
627
628}
629
630void
2b484d24 631yp_acl_reset()
b7080c8e
A
632{
633 struct aclent *p;
634
635 while (acl_root != NULL) {
636 p = acl_root->next;
637 free(acl_root);
638 acl_root = p;
639 }
640}