xref: /freebsd/contrib/ntp/ntpd/ntp_restrict.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
1 /*
2  * ntp_restrict.c - find out what restrictions this host is running under
3  */
4 #ifdef HAVE_CONFIG_H
5 #include <config.h>
6 #endif
7 
8 #include <stdio.h>
9 #include <sys/types.h>
10 
11 #include "ntpd.h"
12 #include "ntp_if.h"
13 #include "ntp_stdlib.h"
14 
15 /*
16  * This code keeps a simple address-and-mask list of hosts we want
17  * to place restrictions on (or remove them from).  The restrictions
18  * are implemented as a set of flags which tell you what the host
19  * can't do.  There is a subroutine entry to return the flags.  The
20  * list is kept sorted to reduce the average number of comparisons
21  * and make sure you get the set of restrictions most specific to
22  * the address.
23  *
24  * The algorithm is that, when looking up a host, it is first assumed
25  * that the default set of restrictions will apply.  It then searches
26  * down through the list.  Whenever it finds a match it adopts the match's
27  * flags instead.  When you hit the point where the sorted address is
28  * greater than the target, you return with the last set of flags you
29  * found.  Because of the ordering of the list, the most specific match
30  * will provide the final set of flags.
31  *
32  * This was originally intended to restrict you from sync'ing to your
33  * own broadcasts when you are doing that, by restricting yourself
34  * from your own interfaces.  It was also thought it would sometimes
35  * be useful to keep a misbehaving host or two from abusing your primary
36  * clock.  It has been expanded, however, to suit the needs of those
37  * with more restrictive access policies.
38  */
39 
40 /*
41  * Memory allocation parameters.  We allocate INITRESLIST entries
42  * initially, and add INCRESLIST entries to the free list whenever
43  * we run out.
44  */
45 #define	INITRESLIST	10
46 #define	INCRESLIST	5
47 
48 /*
49  * The restriction list
50  */
51 struct restrictlist *restrictlist;
52 static	int restrictcount;	/* count of entries in the restriction list */
53 
54 /*
55  * The free list and associated counters.  Also some uninteresting
56  * stat counters.
57  */
58 static	struct restrictlist *resfree;
59 static	int numresfree;		/* number of structures on free list */
60 
61 static	u_long res_calls;
62 static	u_long res_found;
63 static	u_long res_not_found;
64 /* static	u_long res_timereset; */
65 
66 /*
67  * Parameters of the RES_LIMITED restriction option.
68  * client_limit is the number of hosts allowed per source net
69  * client_limit_period is the number of seconds after which an entry
70  * is no longer considered for client limit determination
71  */
72 u_long client_limit;
73 u_long client_limit_period;
74 /*
75  * count number of restriction entries referring to RES_LIMITED
76  * controls activation/deactivation of monitoring
77  * (with respect to RES_LIMITED control)
78  */
79 static	u_long res_limited_refcnt;
80 
81 /*
82  * Our initial allocation of list entries.
83  */
84 static	struct restrictlist resinit[INITRESLIST];
85 
86 /*
87  * init_restrict - initialize the restriction data structures
88  */
89 void
90 init_restrict(void)
91 {
92 	register int i;
93 	char bp[80];
94 
95 	/*
96 	 * Zero the list and put all but one on the free list
97 	 */
98 	resfree = 0;
99 	memset((char *)resinit, 0, sizeof resinit);
100 
101 	for (i = 1; i < INITRESLIST; i++) {
102 		resinit[i].next = resfree;
103 		resfree = &resinit[i];
104 	}
105 
106 	numresfree = INITRESLIST-1;
107 
108 	/*
109 	 * Put the remaining item at the head of the
110 	 * list as our default entry.  Everything in here
111 	 * should be zero for now.
112 	 */
113 	resinit[0].addr = htonl(INADDR_ANY);
114 	resinit[0].mask = 0;
115 	restrictlist = &resinit[0];
116 	restrictcount = 1;
117 
118 
119 	/*
120 	 * fix up stat counters
121 	 */
122 	res_calls = 0;
123 	res_found = 0;
124 	res_not_found = 0;
125 	/* res_timereset = 0; */
126 
127 	/*
128 	 * set default values for RES_LIMIT functionality
129 	 */
130 	client_limit = 3;
131 	client_limit_period = 3600;
132 	res_limited_refcnt = 0;
133 
134 	sprintf(bp, "client_limit=%ld", client_limit);
135 	set_sys_var(bp, strlen(bp)+1, RO);
136 	sprintf(bp, "client_limit_period=%ld", client_limit_period);
137 	set_sys_var(bp, strlen(bp)+1, RO);
138 }
139 
140 
141 /*
142  * restrictions - return restrictions for this host
143  */
144 int
145 restrictions(
146 	struct sockaddr_in *srcadr
147 	)
148 {
149 	register struct restrictlist *rl;
150 	register struct restrictlist *match;
151 	register u_int32 hostaddr;
152 	register int isntpport;
153 
154 	res_calls++;
155 	/*
156 	 * We need the host address in host order.  Also need to know
157 	 * whether this is from the ntp port or not.
158 	 */
159 	hostaddr = SRCADR(srcadr);
160 	isntpport = (SRCPORT(srcadr) == NTP_PORT);
161 
162 	/*
163 	 * Ignore any packets with a multicast source address
164 	 * (this should be done early in the receive process, later!)
165 	 */
166 	if (IN_CLASSD(ntohl(srcadr->sin_addr.s_addr)))
167 	    return (int)RES_IGNORE;
168 
169 	/*
170 	 * Set match to first entry, which is default entry.  Work our
171 	 * way down from there.
172 	 */
173 	match = restrictlist;
174 
175 	for (rl = match->next; rl != 0 && rl->addr <= hostaddr; rl = rl->next)
176 	    if ((hostaddr & rl->mask) == rl->addr) {
177 		    if ((rl->mflags & RESM_NTPONLY) && !isntpport)
178 			continue;
179 		    match = rl;
180 	    }
181 
182 	match->count++;
183 	if (match == restrictlist)
184 	    res_not_found++;
185 	else
186 	    res_found++;
187 
188 	/*
189 	 * The following implements limiting the number of clients
190 	 * accepted from a given network. The notion of "same network"
191 	 * is determined by the mask and addr fields of the restrict
192 	 * list entry. The monitor mechanism has to be enabled for
193 	 * collecting info on current clients.
194 	 *
195 	 * The policy is as follows:
196 	 *	- take the list of clients recorded
197 	 *        from the given "network" seen within the last
198 	 *        client_limit_period seconds
199 	 *      - if there are at most client_limit entries:
200 	 *        --> access allowed
201 	 *      - otherwise sort by time first seen
202 	 *      - current client among the first client_limit seen
203 	 *        hosts?
204 	 *        if yes: access allowed
205 	 *        else:   eccess denied
206 	 */
207 	if (match->flags & RES_LIMITED) {
208 		int lcnt;
209 		struct mon_data *md, *this_client;
210 
211 #ifdef DEBUG
212 		if (debug > 2)
213 		    printf("limited clients check: %ld clients, period %ld seconds, net is 0x%lX\n",
214 			   client_limit, client_limit_period,
215 			   (u_long)netof(hostaddr));
216 #endif /*DEBUG*/
217 		if (mon_enabled == MON_OFF) {
218 #ifdef DEBUG
219 			if (debug > 4)
220 			    printf("no limit - monitoring is off\n");
221 #endif
222 			return (int)(match->flags & ~RES_LIMITED);
223 		}
224 
225 		/*
226 		 * How nice, MRU list provides our current client as the
227 		 * first entry in the list.
228 		 * Monitoring was verified to be active above, thus we
229 		 * know an entry for our client must exist, or some
230 		 * brain dead set the memory limit for mon entries to ZERO!!!
231 		 */
232 		this_client = mon_mru_list.mru_next;
233 
234 		for (md = mon_fifo_list.fifo_next,lcnt = 0;
235 		     md != &mon_fifo_list;
236 		     md = md->fifo_next) {
237 			if ((current_time - md->lasttime)
238 			    > client_limit_period) {
239 #ifdef DEBUG
240 				if (debug > 5)
241 				    printf("checking: %s: ignore: too old: %ld\n",
242 					   numtoa(md->rmtadr),
243 					   current_time - md->lasttime);
244 #endif
245 				continue;
246 			}
247 			if (md->mode == MODE_BROADCAST ||
248 			    md->mode == MODE_CONTROL ||
249 			    md->mode == MODE_PRIVATE) {
250 #ifdef DEBUG
251 				if (debug > 5)
252 				    printf("checking: %s: ignore mode %d\n",
253 					   numtoa(md->rmtadr),
254 					   md->mode);
255 #endif
256 				continue;
257 			}
258 			if (netof(md->rmtadr) !=
259 			    netof(hostaddr)) {
260 #ifdef DEBUG
261 				if (debug > 5)
262 				    printf("checking: %s: different net 0x%lX\n",
263 					   numtoa(md->rmtadr),
264 					   (u_long)netof(md->rmtadr));
265 #endif
266 				continue;
267 			}
268 			lcnt++;
269 			if (lcnt >  (int) client_limit ||
270 			    md->rmtadr == hostaddr) {
271 #ifdef DEBUG
272 				if (debug > 5)
273 				    printf("considering %s: found host\n",
274 					   numtoa(md->rmtadr));
275 #endif
276 				break;
277 			}
278 #ifdef DEBUG
279 			else {
280 				if (debug > 5)
281 				    printf("considering %s: same net\n",
282 					   numtoa(md->rmtadr));
283 			}
284 #endif
285 
286 		}
287 #ifdef DEBUG
288 		if (debug > 4)
289 		    printf("this one is rank %d in list, limit is %lu: %s\n",
290 			   lcnt, client_limit,
291 			   (lcnt <= (int) client_limit) ? "ALLOW" : "REJECT");
292 #endif
293 		if (lcnt <= (int) client_limit) {
294 			this_client->lastdrop = 0;
295 			return (int)(match->flags & ~RES_LIMITED);
296 		} else {
297 			this_client->lastdrop = current_time;
298 		}
299 	}
300 	return (int)match->flags;
301 }
302 
303 
304 /*
305  * hack_restrict - add/subtract/manipulate entries on the restrict list
306  */
307 void
308 hack_restrict(
309 	int op,
310 	struct sockaddr_in *resaddr,
311 	struct sockaddr_in *resmask,
312 	int mflags,
313 	int flags
314 	)
315 {
316 	register u_int32 addr;
317 	register u_int32 mask;
318 	register struct restrictlist *rl;
319 	register struct restrictlist *rlprev;
320 	int i;
321 
322 	/*
323 	 * Get address and mask in host byte order
324 	 */
325 	addr = SRCADR(resaddr);
326 	mask = SRCADR(resmask);
327 	addr &= mask;		/* make sure low bits are zero */
328 
329 	/*
330 	 * If this is the default address, point at first on list.  Else
331 	 * go searching for it.
332 	 */
333 	if (addr == htonl(INADDR_ANY)) {
334 		rlprev = 0;
335 		rl = restrictlist;
336 	} else {
337 		rlprev = restrictlist;
338 		rl = rlprev->next;
339 		while (rl != 0) {
340 			if (rl->addr > addr) {
341 				rl = 0;
342 				break;
343 			} else if (rl->addr == addr) {
344 				if (rl->mask == mask) {
345 					if ((mflags & RESM_NTPONLY)
346 					    == (rl->mflags & RESM_NTPONLY))
347 					    break;	/* exact match */
348 					if (!(mflags & RESM_NTPONLY)) {
349 						/*
350 						 * No flag fits before flag
351 						 */
352 						rl = 0;
353 						break;
354 					}
355 					/* continue on */
356 				} else if (rl->mask > mask) {
357 					rl = 0;
358 					break;
359 				}
360 			}
361 			rlprev = rl;
362 			rl = rl->next;
363 		}
364 	}
365 	/*
366 	 * In case the above wasn't clear :-), either rl now points
367 	 * at the entry this call refers to, or rl is zero and rlprev
368 	 * points to the entry prior to where this one should go in
369 	 * the sort.
370 	 */
371 
372 	/*
373 	 * Switch based on operation
374 	 */
375 	switch (op) {
376 	    case RESTRICT_FLAGS:
377 		/*
378 		 * Here we add bits to the flags.  If this is a new
379 		 * restriction add it.
380 		 */
381 		if (rl == 0) {
382 			if (numresfree == 0) {
383 				rl = (struct restrictlist *) emalloc(
384 					INCRESLIST*sizeof(struct restrictlist));
385 				memset((char *)rl, 0,
386 				       INCRESLIST*sizeof(struct restrictlist));
387 
388 				for (i = 0; i < INCRESLIST; i++) {
389 					rl->next = resfree;
390 					resfree = rl;
391 					rl++;
392 				}
393 				numresfree = INCRESLIST;
394 			}
395 
396 			rl = resfree;
397 			resfree = rl->next;
398 			numresfree--;
399 
400 			rl->addr = addr;
401 			rl->mask = mask;
402 			rl->mflags = (u_short)mflags;
403 
404 			rl->next = rlprev->next;
405 			rlprev->next = rl;
406 			restrictcount++;
407 		}
408 		if ((rl->flags ^ (u_short)flags) & RES_LIMITED) {
409 			res_limited_refcnt++;
410 			mon_start(MON_RES); /* ensure data gets collected */
411 		}
412 		rl->flags |= (u_short)flags;
413 		break;
414 
415 	    case RESTRICT_UNFLAG:
416 		/*
417 		 * Remove some bits from the flags.  If we didn't
418 		 * find this one, just return.
419 		 */
420 		if (rl != 0) {
421 			if ((rl->flags ^ (u_short)flags) & RES_LIMITED) {
422 				res_limited_refcnt--;
423 				if (res_limited_refcnt == 0)
424 				    mon_stop(MON_RES);
425 			}
426 			rl->flags &= (u_short)~flags;
427 		}
428 		break;
429 
430 	    case RESTRICT_REMOVE:
431 		/*
432 		 * Remove an entry from the table entirely if we found one.
433 		 * Don't remove the default entry and don't remove an
434 		 * interface entry.
435 		 */
436 		if (rl != 0
437 		    && rl->addr != htonl(INADDR_ANY)
438 		    && !(rl->mflags & RESM_INTERFACE)) {
439 			rlprev->next = rl->next;
440 			restrictcount--;
441 			if (rl->flags & RES_LIMITED) {
442 				res_limited_refcnt--;
443 				if (res_limited_refcnt == 0)
444 				    mon_stop(MON_RES);
445 			}
446 			memset((char *)rl, 0, sizeof(struct restrictlist));
447 
448 			rl->next = resfree;
449 			resfree = rl;
450 			numresfree++;
451 		}
452 		break;
453 
454 	    default:
455 		/* Oh, well */
456 		break;
457 	}
458 
459 	/* done! */
460 }
461