File: haccess.c

package info (click to toggle)
netstd 3.07-7slink.3
  • links: PTS
  • area: main
  • in suites: slink
  • size: 6,312 kB
  • ctags: 9,027
  • sloc: ansic: 72,107; cpp: 6,144; makefile: 1,650; yacc: 1,614; sh: 1,164; perl: 308; awk: 46
file content (118 lines) | stat: -rw-r--r-- 2,454 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
 * haccess.c
 *
 * Check a client against /etc/hosts.{allow,deny}
 *
 * Copyright (C) 1995-1997, Olaf Kirch <okir@monad.swb.de>
 */

#include "site.h"

#ifdef HOSTS_ACCESS
#include "system.h"
#include "haccess.h"
#include <rpc/rpc.h>
#include "logging.h"
#ifdef HAVE_LIBWRAP_BUG
#include <syslog.h>
#endif

/* This is from libwrap.a */
extern int		hosts_ctl(char *, char *, char *, char *);

#define IP_HASH_MASK	0xF
#define IP_HASH(a)	((((a)>>24)^((a)>>16)^((a)>>8)^(a))&IP_HASH_MASK)

typedef struct clnt_host {
	struct clnt_host	*next;
	struct in_addr		clnt_addr;
	char			status;
} clnt_host;

#define HACS_MAXHOSTS		256
#define HACS_INTERVAL		3600		/* one hour */

static clnt_host		*clients[IP_HASH_MASK+1];
static unsigned int		nrhosts = 0;
static time_t			lastflush = 0;


/*
 * libwrap.a from tcp_wrappers-7.2 references these variables when built
 * with OPTIONS support, but does not define them.
 */
#ifdef HAVE_LIBWRAP_BUG
int	deny_severity = LOG_WARNING;
int	allow_severity = LOG_INFO;
#endif


int
client_checkaccess(char *rpcprog, struct sockaddr_in *sin, int checkport)
{
	struct in_addr	   addr = sin->sin_addr;
	struct clnt_host   *hp;
	int		   hash;
	time_t		   now;

	if (checkport
	 && (ntohs(sin->sin_port) >= IPPORT_RESERVED
	  || ntohs(sin->sin_port) < IPPORT_RESERVED/2)) {
		Dprintf(L_ERROR,
			"client %s called from illegal port %d\n",
				inet_ntoa(addr), ntohs(sin->sin_port));
		return 0;
	}

	/* Flush once per hour */
	if ((now = time(NULL)) - lastflush > HACS_INTERVAL)
		client_flushaccess();

	hash = IP_HASH(addr.s_addr);
	for (hp = clients[hash]; hp != NULL; hp = hp->next) 
		if (hp->clnt_addr.s_addr == addr.s_addr) break;

	if (hp == NULL) {
		if (nrhosts >= HACS_MAXHOSTS)
			client_flushaccess();

		hp = (clnt_host *) xmalloc(sizeof(*hp));
		hp->next = clients[hash];
		clients[hash] = hp;

		hp->clnt_addr = addr;
		hp->status = hosts_ctl(rpcprog, "unknown",
					inet_ntoa(addr), "root");
		nrhosts++;
	}

	if (!hp->status)
		Dprintf(L_ERROR, "access from host %s rejected\n",
					inet_ntoa(addr));

	return hp->status;
}

void
client_flushaccess(void)
{
	static int	flushing = 0;
	clnt_host	*hp;
	int		i;

	if (flushing)
		return;
	flushing = 1;

	Dprintf(D_AUTH, "flushed host access cache\n");
	for (i = 0; i < IP_HASH_MASK+1; i++) {
		while ((hp = clients[i]) != NULL) {
			clients[i] = hp->next;
			free (hp);
		}
	}
	nrhosts = 0;
	flushing = 0;
	lastflush = time(NULL);
}
#endif /* HOSTS_ACCESS */