Deleted Added
full compact
hosts_access.c (51495) hosts_access.c (56977)
1 /*
2 * This module implements a simple access control language that is based on
3 * host (or domain) names, NIS (host) netgroup names, IP addresses (or
4 * network numbers) and daemon process names. When a match is found the
5 * search is terminated, and depending on whether PROCESS_OPTIONS is defined,
6 * a list of options is executed or an optional shell command is executed.
7 *
8 * Host and user names are looked up on demand, provided that suitable endpoint
9 * information is available as sockaddr_in structures or TLI netbufs. As a
10 * side effect, the pattern matching process may change the contents of
11 * request structure fields.
12 *
13 * Diagnostics are reported through syslog(3).
14 *
15 * Compile with -DNETGROUP if your library provides support for netgroups.
16 *
17 * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
18 *
1 /*
2 * This module implements a simple access control language that is based on
3 * host (or domain) names, NIS (host) netgroup names, IP addresses (or
4 * network numbers) and daemon process names. When a match is found the
5 * search is terminated, and depending on whether PROCESS_OPTIONS is defined,
6 * a list of options is executed or an optional shell command is executed.
7 *
8 * Host and user names are looked up on demand, provided that suitable endpoint
9 * information is available as sockaddr_in structures or TLI netbufs. As a
10 * side effect, the pattern matching process may change the contents of
11 * request structure fields.
12 *
13 * Diagnostics are reported through syslog(3).
14 *
15 * Compile with -DNETGROUP if your library provides support for netgroups.
16 *
17 * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
18 *
19 * $FreeBSD: head/contrib/tcp_wrappers/hosts_access.c 51495 1999-09-21 09:09:57Z sheldonh $
19 * $FreeBSD: head/contrib/tcp_wrappers/hosts_access.c 56977 2000-02-03 10:27:03Z shin $
20 */
21
22#ifndef lint
23static char sccsid[] = "@(#) hosts_access.c 1.21 97/02/12 02:13:22";
24#endif
25
26/* System libraries. */
27
28#include <sys/types.h>
20 */
21
22#ifndef lint
23static char sccsid[] = "@(#) hosts_access.c 1.21 97/02/12 02:13:22";
24#endif
25
26/* System libraries. */
27
28#include <sys/types.h>
29#ifdef INT32_T
30 typedef uint32_t u_int32_t;
31#endif
29#include <sys/param.h>
32#include <sys/param.h>
33#ifdef INET6
34#include <sys/socket.h>
35#endif
30#include <netinet/in.h>
31#include <arpa/inet.h>
32#include <stdio.h>
33#include <syslog.h>
34#include <ctype.h>
35#include <errno.h>
36#include <setjmp.h>
37#include <string.h>

--- 41 unchanged lines hidden (view full) ---

79
80static int table_match();
81static int list_match();
82static int server_match();
83static int client_match();
84static int host_match();
85static int string_match();
86static int masked_match();
36#include <netinet/in.h>
37#include <arpa/inet.h>
38#include <stdio.h>
39#include <syslog.h>
40#include <ctype.h>
41#include <errno.h>
42#include <setjmp.h>
43#include <string.h>

--- 41 unchanged lines hidden (view full) ---

85
86static int table_match();
87static int list_match();
88static int server_match();
89static int client_match();
90static int host_match();
91static int string_match();
92static int masked_match();
93#ifdef INET6
94static int masked_match4();
95static int masked_match6();
96#endif
87
88/* Size of logical line buffer. */
89
90#define BUFLEN 2048
91
92/* hosts_access - host access control facility */
93
94int hosts_access(request)

--- 213 unchanged lines hidden (view full) ---

308/* string_match - match string against pattern */
309
310static int string_match(tok, string)
311char *tok;
312char *string;
313{
314 int n;
315
97
98/* Size of logical line buffer. */
99
100#define BUFLEN 2048
101
102/* hosts_access - host access control facility */
103
104int hosts_access(request)

--- 213 unchanged lines hidden (view full) ---

318/* string_match - match string against pattern */
319
320static int string_match(tok, string)
321char *tok;
322char *string;
323{
324 int n;
325
326#ifdef INET6
327 /* convert IPv4 mapped IPv6 address to IPv4 address */
328 if (STRN_EQ(string, "::ffff:", 7)
329 && dot_quad_addr(string + 7) != INADDR_NONE) {
330 string += 7;
331 }
332#endif
316 if (tok[0] == '.') { /* suffix */
317 n = strlen(string) - strlen(tok);
318 return (n > 0 && STR_EQ(tok, string + n));
319 } else if (STR_EQ(tok, "ALL")) { /* all: match any */
320 return (YES);
321 } else if (STR_EQ(tok, "KNOWN")) { /* not unknown */
322 return (STR_NE(string, unknown));
323 } else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */
324 return (STRN_EQ(tok, string, n));
325 } else { /* exact match */
333 if (tok[0] == '.') { /* suffix */
334 n = strlen(string) - strlen(tok);
335 return (n > 0 && STR_EQ(tok, string + n));
336 } else if (STR_EQ(tok, "ALL")) { /* all: match any */
337 return (YES);
338 } else if (STR_EQ(tok, "KNOWN")) { /* not unknown */
339 return (STR_NE(string, unknown));
340 } else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */
341 return (STRN_EQ(tok, string, n));
342 } else { /* exact match */
343#ifdef INET6
344 struct in6_addr pat, addr;
345 int len, ret;
346 char ch;
347
348 len = strlen(tok);
349 if (*tok == '[' && tok[len - 1] == ']') {
350 ch = tok[len - 1];
351 tok[len - 1] = '\0';
352 ret = inet_pton(AF_INET6, tok + 1, pat.s6_addr);
353 tok[len - 1] = ch;
354 if (ret != 1 || inet_pton(AF_INET6, string, addr.s6_addr) != 1)
355 return NO;
356 return (!memcmp(&pat, &addr, sizeof(struct in6_addr)));
357 }
358#endif
326 return (STR_EQ(tok, string));
327 }
328}
329
330/* masked_match - match address against netnumber/netmask */
331
359 return (STR_EQ(tok, string));
360 }
361}
362
363/* masked_match - match address against netnumber/netmask */
364
365#ifdef INET6
332static int masked_match(net_tok, mask_tok, string)
333char *net_tok;
334char *mask_tok;
335char *string;
336{
366static int masked_match(net_tok, mask_tok, string)
367char *net_tok;
368char *mask_tok;
369char *string;
370{
371 return (masked_match4(net_tok, mask_tok, string) ||
372 masked_match6(net_tok, mask_tok, string));
373}
374
375static int masked_match4(net_tok, mask_tok, string)
376#else
377static int masked_match(net_tok, mask_tok, string)
378#endif
379char *net_tok;
380char *mask_tok;
381char *string;
382{
383#ifdef INET6
384 u_int32_t net;
385 u_int32_t mask;
386 u_int32_t addr;
387#else
337 unsigned long net;
338 unsigned long mask;
339 unsigned long addr;
388 unsigned long net;
389 unsigned long mask;
390 unsigned long addr;
391#endif
340
341 /*
342 * Disallow forms other than dotted quad: the treatment that inet_addr()
343 * gives to forms with less than four components is inconsistent with the
344 * access control language. John P. Rouillard <rouilj@cs.umb.edu>.
345 */
346
347 if ((addr = dot_quad_addr(string)) == INADDR_NONE)
348 return (NO);
349 if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
350 || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) {
392
393 /*
394 * Disallow forms other than dotted quad: the treatment that inet_addr()
395 * gives to forms with less than four components is inconsistent with the
396 * access control language. John P. Rouillard <rouilj@cs.umb.edu>.
397 */
398
399 if ((addr = dot_quad_addr(string)) == INADDR_NONE)
400 return (NO);
401 if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
402 || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) {
403#ifndef INET6
351 tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
404 tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
405#endif
352 return (NO); /* not tcpd_jump() */
353 }
354 return ((addr & mask) == net);
355}
406 return (NO); /* not tcpd_jump() */
407 }
408 return ((addr & mask) == net);
409}
410
411#ifdef INET6
412static int masked_match6(net_tok, mask_tok, string)
413char *net_tok;
414char *mask_tok;
415char *string;
416{
417 struct in6_addr net, addr;
418 u_int32_t mask;
419 int len, mask_len, i = 0;
420 char ch;
421
422 if (inet_pton(AF_INET6, string, addr.s6_addr) != 1)
423 return NO;
424
425 if (IN6_IS_ADDR_V4MAPPED(&addr)) {
426 if ((*(u_int32_t *)&net.s6_addr[12] = dot_quad_addr(net_tok)) == INADDR_NONE
427 || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE)
428 return (NO);
429 return ((*(u_int32_t *)&addr.s6_addr[12] & mask) == *(u_int32_t *)&net.s6_addr[12]);
430 }
431
432 /* match IPv6 address against netnumber/prefixlen */
433 len = strlen(net_tok);
434 if (*net_tok != '[' || net_tok[len - 1] != ']')
435 return NO;
436 ch = net_tok[len - 1];
437 net_tok[len - 1] = '\0';
438 if (inet_pton(AF_INET6, net_tok + 1, net.s6_addr) != 1) {
439 net_tok[len - 1] = ch;
440 return NO;
441 }
442 net_tok[len - 1] = ch;
443 if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128)
444 return NO;
445
446 while (mask_len > 0) {
447 if (mask_len < 32) {
448 mask = htonl(~(0xffffffff >> mask_len));
449 if ((*(u_int32_t *)&addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.s6_addr[i] & mask))
450 return NO;
451 break;
452 }
453 if (*(u_int32_t *)&addr.s6_addr[i] != *(u_int32_t *)&net.s6_addr[i])
454 return NO;
455 i += 4;
456 mask_len -= 32;
457 }
458 return YES;
459}
460#endif /* INET6 */