xref: /freebsd/contrib/ntp/ntpd/ntp_restrict.c (revision 41059135ce931c0f1014a999ffabc6bc470ce856)
1 /*
2  * ntp_restrict.c - determine host restrictions
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_lists.h"
14 #include "ntp_stdlib.h"
15 #include "ntp_assert.h"
16 
17 /*
18  * This code keeps a simple address-and-mask list of hosts we want
19  * to place restrictions on (or remove them from). The restrictions
20  * are implemented as a set of flags which tell you what the host
21  * can't do. There is a subroutine entry to return the flags. The
22  * list is kept sorted to reduce the average number of comparisons
23  * and make sure you get the set of restrictions most specific to
24  * the address.
25  *
26  * The algorithm is that, when looking up a host, it is first assumed
27  * that the default set of restrictions will apply. It then searches
28  * down through the list. Whenever it finds a match it adopts the
29  * match's flags instead. When you hit the point where the sorted
30  * address is greater than the target, you return with the last set of
31  * flags you found. Because of the ordering of the list, the most
32  * specific match will provide the final set of flags.
33  *
34  * This was originally intended to restrict you from sync'ing to your
35  * own broadcasts when you are doing that, by restricting yourself from
36  * your own interfaces. It was also thought it would sometimes be useful
37  * to keep a misbehaving host or two from abusing your primary clock. It
38  * has been expanded, however, to suit the needs of those with more
39  * restrictive access policies.
40  */
41 /*
42  * We will use two lists, one for IPv4 addresses and one for IPv6
43  * addresses. This is not protocol-independant but for now I can't
44  * find a way to respect this. We'll check this later... JFB 07/2001
45  */
46 #define MASK_IPV6_ADDR(dst, src, msk)					\
47 	do {								\
48 		int idx;						\
49 		for (idx = 0; idx < (int)COUNTOF((dst)->s6_addr); idx++) { \
50 			(dst)->s6_addr[idx] = (src)->s6_addr[idx]	\
51 					      & (msk)->s6_addr[idx];	\
52 		}							\
53 	} while (0)
54 
55 /*
56  * We allocate INC_RESLIST{4|6} entries to the free list whenever empty.
57  * Auto-tune these to be just less than 1KB (leaving at least 16 bytes
58  * for allocator overhead).
59  */
60 #define	INC_RESLIST4	((1024 - 16) / V4_SIZEOF_RESTRICT_U)
61 #define	INC_RESLIST6	((1024 - 16) / V6_SIZEOF_RESTRICT_U)
62 
63 /*
64  * The restriction list
65  */
66 restrict_u *restrictlist4;
67 restrict_u *restrictlist6;
68 static int restrictcount;	/* count in the restrict lists */
69 
70 /*
71  * The free list and associated counters.  Also some uninteresting
72  * stat counters.
73  */
74 static restrict_u *resfree4;	/* available entries (free list) */
75 static restrict_u *resfree6;
76 
77 static u_long res_calls;
78 static u_long res_found;
79 static u_long res_not_found;
80 
81 /*
82  * Count number of restriction entries referring to RES_LIMITED, to
83  * control implicit activation/deactivation of the MRU monlist.
84  */
85 static	u_long res_limited_refcnt;
86 
87 /*
88  * Our default entries.
89  */
90 static	restrict_u	restrict_def4;
91 static	restrict_u	restrict_def6;
92 
93 /*
94  * "restrict source ..." enabled knob and restriction bits.
95  */
96 static	int		restrict_source_enabled;
97 static	u_short		restrict_source_flags;
98 static	u_short		restrict_source_mflags;
99 
100 /*
101  * private functions
102  */
103 static restrict_u *	alloc_res4(void);
104 static restrict_u *	alloc_res6(void);
105 static void		free_res(restrict_u *, int);
106 static void		inc_res_limited(void);
107 static void		dec_res_limited(void);
108 static restrict_u *	match_restrict4_addr(u_int32, u_short);
109 static restrict_u *	match_restrict6_addr(const struct in6_addr *,
110 					     u_short);
111 static restrict_u *	match_restrict_entry(const restrict_u *, int);
112 static int		res_sorts_before4(restrict_u *, restrict_u *);
113 static int		res_sorts_before6(restrict_u *, restrict_u *);
114 
115 
116 /*
117  * init_restrict - initialize the restriction data structures
118  */
119 void
120 init_restrict(void)
121 {
122 	/*
123 	 * The restriction lists begin with a default entry with address
124 	 * and mask 0, which will match any entry.  The lists are kept
125 	 * sorted by descending address followed by descending mask:
126 	 *
127 	 *   address	  mask
128 	 * 192.168.0.0	255.255.255.0	kod limited noquery nopeer
129 	 * 192.168.0.0	255.255.0.0	kod limited
130 	 * 0.0.0.0	0.0.0.0		kod limited noquery
131 	 *
132 	 * The first entry which matches an address is used.  With the
133 	 * example restrictions above, 192.168.0.0/24 matches the first
134 	 * entry, the rest of 192.168.0.0/16 matches the second, and
135 	 * everything else matches the third (default).
136 	 *
137 	 * Note this achieves the same result a little more efficiently
138 	 * than the documented behavior, which is to keep the lists
139 	 * sorted by ascending address followed by ascending mask, with
140 	 * the _last_ matching entry used.
141 	 *
142 	 * An additional wrinkle is we may have multiple entries with
143 	 * the same address and mask but differing match flags (mflags).
144 	 * At present there is only one, RESM_NTPONLY.  Entries with
145 	 * RESM_NTPONLY are sorted earlier so they take precedence over
146 	 * any otherwise similar entry without.  Again, this is the same
147 	 * behavior as but reversed implementation compared to the docs.
148 	 *
149 	 */
150 	LINK_SLIST(restrictlist4, &restrict_def4, link);
151 	LINK_SLIST(restrictlist6, &restrict_def6, link);
152 	restrictcount = 2;
153 }
154 
155 
156 static restrict_u *
157 alloc_res4(void)
158 {
159 	const size_t	cb = V4_SIZEOF_RESTRICT_U;
160 	const size_t	count = INC_RESLIST4;
161 	restrict_u *	rl;
162 	restrict_u *	res;
163 	size_t		i;
164 
165 	UNLINK_HEAD_SLIST(res, resfree4, link);
166 	if (res != NULL)
167 		return res;
168 
169 	rl = eallocarray(count, cb);
170 	/* link all but the first onto free list */
171 	res = (void *)((char *)rl + (count - 1) * cb);
172 	for (i = count - 1; i > 0; i--) {
173 		LINK_SLIST(resfree4, res, link);
174 		res = (void *)((char *)res - cb);
175 	}
176 	INSIST(rl == res);
177 	/* allocate the first */
178 	return res;
179 }
180 
181 
182 static restrict_u *
183 alloc_res6(void)
184 {
185 	const size_t	cb = V6_SIZEOF_RESTRICT_U;
186 	const size_t	count = INC_RESLIST6;
187 	restrict_u *	rl;
188 	restrict_u *	res;
189 	size_t		i;
190 
191 	UNLINK_HEAD_SLIST(res, resfree6, link);
192 	if (res != NULL)
193 		return res;
194 
195 	rl = eallocarray(count, cb);
196 	/* link all but the first onto free list */
197 	res = (void *)((char *)rl + (count - 1) * cb);
198 	for (i = count - 1; i > 0; i--) {
199 		LINK_SLIST(resfree6, res, link);
200 		res = (void *)((char *)res - cb);
201 	}
202 	INSIST(rl == res);
203 	/* allocate the first */
204 	return res;
205 }
206 
207 
208 static void
209 free_res(
210 	restrict_u *	res,
211 	int		v6
212 	)
213 {
214 	restrict_u **	plisthead;
215 	restrict_u *	unlinked;
216 
217 	restrictcount--;
218 	if (RES_LIMITED & res->flags)
219 		dec_res_limited();
220 
221 	if (v6)
222 		plisthead = &restrictlist6;
223 	else
224 		plisthead = &restrictlist4;
225 	UNLINK_SLIST(unlinked, *plisthead, res, link, restrict_u);
226 	INSIST(unlinked == res);
227 
228 	if (v6) {
229 		zero_mem(res, V6_SIZEOF_RESTRICT_U);
230 		plisthead = &resfree6;
231 	} else {
232 		zero_mem(res, V4_SIZEOF_RESTRICT_U);
233 		plisthead = &resfree4;
234 	}
235 	LINK_SLIST(*plisthead, res, link);
236 }
237 
238 
239 static void
240 inc_res_limited(void)
241 {
242 	if (!res_limited_refcnt)
243 		mon_start(MON_RES);
244 	res_limited_refcnt++;
245 }
246 
247 
248 static void
249 dec_res_limited(void)
250 {
251 	res_limited_refcnt--;
252 	if (!res_limited_refcnt)
253 		mon_stop(MON_RES);
254 }
255 
256 
257 static restrict_u *
258 match_restrict4_addr(
259 	u_int32	addr,
260 	u_short	port
261 	)
262 {
263 	const int	v6 = 0;
264 	restrict_u *	res;
265 	restrict_u *	next;
266 
267 	for (res = restrictlist4; res != NULL; res = next) {
268 		next = res->link;
269 		if (res->expire &&
270 		    res->expire <= current_time)
271 			free_res(res, v6);
272 		if (res->u.v4.addr == (addr & res->u.v4.mask)
273 		    && (!(RESM_NTPONLY & res->mflags)
274 			|| NTP_PORT == port))
275 			break;
276 	}
277 	return res;
278 }
279 
280 
281 static restrict_u *
282 match_restrict6_addr(
283 	const struct in6_addr *	addr,
284 	u_short			port
285 	)
286 {
287 	const int	v6 = 1;
288 	restrict_u *	res;
289 	restrict_u *	next;
290 	struct in6_addr	masked;
291 
292 	for (res = restrictlist6; res != NULL; res = next) {
293 		next = res->link;
294 		INSIST(next != res);
295 		if (res->expire &&
296 		    res->expire <= current_time)
297 			free_res(res, v6);
298 		MASK_IPV6_ADDR(&masked, addr, &res->u.v6.mask);
299 		if (ADDR6_EQ(&masked, &res->u.v6.addr)
300 		    && (!(RESM_NTPONLY & res->mflags)
301 			|| NTP_PORT == (int)port))
302 			break;
303 	}
304 	return res;
305 }
306 
307 
308 /*
309  * match_restrict_entry - find an exact match on a restrict list.
310  *
311  * Exact match is addr, mask, and mflags all equal.
312  * In order to use more common code for IPv4 and IPv6, this routine
313  * requires the caller to populate a restrict_u with mflags and either
314  * the v4 or v6 address and mask as appropriate.  Other fields in the
315  * input restrict_u are ignored.
316  */
317 static restrict_u *
318 match_restrict_entry(
319 	const restrict_u *	pmatch,
320 	int			v6
321 	)
322 {
323 	restrict_u *res;
324 	restrict_u *rlist;
325 	size_t cb;
326 
327 	if (v6) {
328 		rlist = restrictlist6;
329 		cb = sizeof(pmatch->u.v6);
330 	} else {
331 		rlist = restrictlist4;
332 		cb = sizeof(pmatch->u.v4);
333 	}
334 
335 	for (res = rlist; res != NULL; res = res->link)
336 		if (res->mflags == pmatch->mflags &&
337 		    !memcmp(&res->u, &pmatch->u, cb))
338 			break;
339 	return res;
340 }
341 
342 
343 /*
344  * res_sorts_before4 - compare two restrict4 entries
345  *
346  * Returns nonzero if r1 sorts before r2.  We sort by descending
347  * address, then descending mask, then descending mflags, so sorting
348  * before means having a higher value.
349  */
350 static int
351 res_sorts_before4(
352 	restrict_u *r1,
353 	restrict_u *r2
354 	)
355 {
356 	int r1_before_r2;
357 
358 	if (r1->u.v4.addr > r2->u.v4.addr)
359 		r1_before_r2 = 1;
360 	else if (r1->u.v4.addr < r2->u.v4.addr)
361 		r1_before_r2 = 0;
362 	else if (r1->u.v4.mask > r2->u.v4.mask)
363 		r1_before_r2 = 1;
364 	else if (r1->u.v4.mask < r2->u.v4.mask)
365 		r1_before_r2 = 0;
366 	else if (r1->mflags > r2->mflags)
367 		r1_before_r2 = 1;
368 	else
369 		r1_before_r2 = 0;
370 
371 	return r1_before_r2;
372 }
373 
374 
375 /*
376  * res_sorts_before6 - compare two restrict6 entries
377  *
378  * Returns nonzero if r1 sorts before r2.  We sort by descending
379  * address, then descending mask, then descending mflags, so sorting
380  * before means having a higher value.
381  */
382 static int
383 res_sorts_before6(
384 	restrict_u *r1,
385 	restrict_u *r2
386 	)
387 {
388 	int r1_before_r2;
389 	int cmp;
390 
391 	cmp = ADDR6_CMP(&r1->u.v6.addr, &r2->u.v6.addr);
392 	if (cmp > 0)		/* r1->addr > r2->addr */
393 		r1_before_r2 = 1;
394 	else if (cmp < 0)	/* r2->addr > r1->addr */
395 		r1_before_r2 = 0;
396 	else {
397 		cmp = ADDR6_CMP(&r1->u.v6.mask, &r2->u.v6.mask);
398 		if (cmp > 0)		/* r1->mask > r2->mask*/
399 			r1_before_r2 = 1;
400 		else if (cmp < 0)	/* r2->mask > r1->mask */
401 			r1_before_r2 = 0;
402 		else if (r1->mflags > r2->mflags)
403 			r1_before_r2 = 1;
404 		else
405 			r1_before_r2 = 0;
406 	}
407 
408 	return r1_before_r2;
409 }
410 
411 
412 /*
413  * restrictions - return restrictions for this host
414  */
415 u_short
416 restrictions(
417 	sockaddr_u *srcadr
418 	)
419 {
420 	restrict_u *match;
421 	struct in6_addr *pin6;
422 	u_short flags;
423 
424 	res_calls++;
425 	flags = 0;
426 	/* IPv4 source address */
427 	if (IS_IPV4(srcadr)) {
428 		/*
429 		 * Ignore any packets with a multicast source address
430 		 * (this should be done early in the receive process,
431 		 * not later!)
432 		 */
433 		if (IN_CLASSD(SRCADR(srcadr)))
434 			return (int)RES_IGNORE;
435 
436 		match = match_restrict4_addr(SRCADR(srcadr),
437 					     SRCPORT(srcadr));
438 
439 		INSIST(match != NULL);
440 
441 		match->count++;
442 		/*
443 		 * res_not_found counts only use of the final default
444 		 * entry, not any "restrict default ntpport ...", which
445 		 * would be just before the final default.
446 		 */
447 		if (&restrict_def4 == match)
448 			res_not_found++;
449 		else
450 			res_found++;
451 		flags = match->flags;
452 	}
453 
454 	/* IPv6 source address */
455 	if (IS_IPV6(srcadr)) {
456 		pin6 = PSOCK_ADDR6(srcadr);
457 
458 		/*
459 		 * Ignore any packets with a multicast source address
460 		 * (this should be done early in the receive process,
461 		 * not later!)
462 		 */
463 		if (IN6_IS_ADDR_MULTICAST(pin6))
464 			return (int)RES_IGNORE;
465 
466 		match = match_restrict6_addr(pin6, SRCPORT(srcadr));
467 		INSIST(match != NULL);
468 		match->count++;
469 		if (&restrict_def6 == match)
470 			res_not_found++;
471 		else
472 			res_found++;
473 		flags = match->flags;
474 	}
475 	return (flags);
476 }
477 
478 
479 /*
480  * hack_restrict - add/subtract/manipulate entries on the restrict list
481  */
482 void
483 hack_restrict(
484 	int		op,
485 	sockaddr_u *	resaddr,
486 	sockaddr_u *	resmask,
487 	u_short		mflags,
488 	u_short		flags,
489 	u_long		expire
490 	)
491 {
492 	int		v6;
493 	restrict_u	match;
494 	restrict_u *	res;
495 	restrict_u **	plisthead;
496 
497 	DPRINTF(1, ("restrict: op %d addr %s mask %s mflags %08x flags %08x\n",
498 		    op, stoa(resaddr), stoa(resmask), mflags, flags));
499 
500 	if (NULL == resaddr) {
501 		REQUIRE(NULL == resmask);
502 		REQUIRE(RESTRICT_FLAGS == op);
503 		restrict_source_flags = flags;
504 		restrict_source_mflags = mflags;
505 		restrict_source_enabled = 1;
506 		return;
507 	}
508 
509 	ZERO(match);
510 
511 #if 0
512 	/* silence VC9 potentially uninit warnings */
513 	// HMS: let's use a compiler-specific "enable" for this.
514 	res = NULL;
515 	v6 = 0;
516 #endif
517 
518 	if (IS_IPV4(resaddr)) {
519 		v6 = 0;
520 		/*
521 		 * Get address and mask in host byte order for easy
522 		 * comparison as u_int32
523 		 */
524 		match.u.v4.addr = SRCADR(resaddr);
525 		match.u.v4.mask = SRCADR(resmask);
526 		match.u.v4.addr &= match.u.v4.mask;
527 
528 	} else if (IS_IPV6(resaddr)) {
529 		v6 = 1;
530 		/*
531 		 * Get address and mask in network byte order for easy
532 		 * comparison as byte sequences (e.g. memcmp())
533 		 */
534 		match.u.v6.mask = SOCK_ADDR6(resmask);
535 		MASK_IPV6_ADDR(&match.u.v6.addr, PSOCK_ADDR6(resaddr),
536 			       &match.u.v6.mask);
537 
538 	} else	/* not IPv4 nor IPv6 */
539 		REQUIRE(0);
540 
541 	match.flags = flags;
542 	match.mflags = mflags;
543 	match.expire = expire;
544 	res = match_restrict_entry(&match, v6);
545 
546 	switch (op) {
547 
548 	case RESTRICT_FLAGS:
549 		/*
550 		 * Here we add bits to the flags. If this is a
551 		 * new restriction add it.
552 		 */
553 		if (NULL == res) {
554 			if (v6) {
555 				res = alloc_res6();
556 				memcpy(res, &match,
557 				       V6_SIZEOF_RESTRICT_U);
558 				plisthead = &restrictlist6;
559 			} else {
560 				res = alloc_res4();
561 				memcpy(res, &match,
562 				       V4_SIZEOF_RESTRICT_U);
563 				plisthead = &restrictlist4;
564 			}
565 			LINK_SORT_SLIST(
566 				*plisthead, res,
567 				(v6)
568 				  ? res_sorts_before6(res, L_S_S_CUR())
569 				  : res_sorts_before4(res, L_S_S_CUR()),
570 				link, restrict_u);
571 			restrictcount++;
572 			if (RES_LIMITED & flags)
573 				inc_res_limited();
574 		} else {
575 			if ((RES_LIMITED & flags) &&
576 			    !(RES_LIMITED & res->flags))
577 				inc_res_limited();
578 			res->flags |= flags;
579 		}
580 		break;
581 
582 	case RESTRICT_UNFLAG:
583 		/*
584 		 * Remove some bits from the flags. If we didn't
585 		 * find this one, just return.
586 		 */
587 		if (res != NULL) {
588 			if ((RES_LIMITED & res->flags)
589 			    && (RES_LIMITED & flags))
590 				dec_res_limited();
591 			res->flags &= ~flags;
592 		}
593 		break;
594 
595 	case RESTRICT_REMOVE:
596 	case RESTRICT_REMOVEIF:
597 		/*
598 		 * Remove an entry from the table entirely if we
599 		 * found one. Don't remove the default entry and
600 		 * don't remove an interface entry.
601 		 */
602 		if (res != NULL
603 		    && (RESTRICT_REMOVEIF == op
604 			|| !(RESM_INTERFACE & res->mflags))
605 		    && res != &restrict_def4
606 		    && res != &restrict_def6)
607 			free_res(res, v6);
608 		break;
609 
610 	default:	/* unknown op */
611 		INSIST(0);
612 		break;
613 	}
614 
615 }
616 
617 
618 /*
619  * restrict_source - maintains dynamic "restrict source ..." entries as
620  *		     peers come and go.
621  */
622 void
623 restrict_source(
624 	sockaddr_u *	addr,
625 	int		farewell,	/* 0 to add, 1 to remove */
626 	u_long		expire		/* 0 is infinite, valid until */
627 	)
628 {
629 	sockaddr_u	onesmask;
630 	restrict_u *	res;
631 	int		found_specific;
632 
633 	if (!restrict_source_enabled || SOCK_UNSPEC(addr) ||
634 	    IS_MCAST(addr) || ISREFCLOCKADR(addr))
635 		return;
636 
637 	REQUIRE(AF_INET == AF(addr) || AF_INET6 == AF(addr));
638 
639 	SET_HOSTMASK(&onesmask, AF(addr));
640 	if (farewell) {
641 		hack_restrict(RESTRICT_REMOVE, addr, &onesmask,
642 			      0, 0, 0);
643 		DPRINTF(1, ("restrict_source: %s removed", stoa(addr)));
644 		return;
645 	}
646 
647 	/*
648 	 * If there is a specific entry for this address, hands
649 	 * off, as it is condidered more specific than "restrict
650 	 * server ...".
651 	 * However, if the specific entry found is a fleeting one
652 	 * added by pool_xmit() before soliciting, replace it
653 	 * immediately regardless of the expire value to make way
654 	 * for the more persistent entry.
655 	 */
656 	if (IS_IPV4(addr)) {
657 		res = match_restrict4_addr(SRCADR(addr), SRCPORT(addr));
658 		INSIST(res != NULL);
659 		found_specific = (SRCADR(&onesmask) == res->u.v4.mask);
660 	} else {
661 		res = match_restrict6_addr(&SOCK_ADDR6(addr),
662 					   SRCPORT(addr));
663 		INSIST(res != NULL);
664 		found_specific = ADDR6_EQ(&res->u.v6.mask,
665 					  &SOCK_ADDR6(&onesmask));
666 	}
667 	if (!expire && found_specific && res->expire) {
668 		found_specific = 0;
669 		free_res(res, IS_IPV6(addr));
670 	}
671 	if (found_specific)
672 		return;
673 
674 	hack_restrict(RESTRICT_FLAGS, addr, &onesmask,
675 		      restrict_source_mflags, restrict_source_flags,
676 		      expire);
677 	DPRINTF(1, ("restrict_source: %s host restriction added\n",
678 		    stoa(addr)));
679 }
680