/
ntp_proto.c
4531 lines (4180 loc) · 125 KB
/
ntp_proto.c
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* ntp_proto.c - NTP version 4 protocol machinery
*
* ATTENTION: Get approval from Dave Mills on all changes to this file!
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "ntpd.h"
#include "ntp_stdlib.h"
#include "ntp_unixtime.h"
#include "ntp_control.h"
#include "ntp_string.h"
#include "ntp_leapsec.h"
#include "refidsmear.h"
#include "lib_strbuf.h"
#include <stdio.h>
#ifdef HAVE_LIBSCF_H
#include <libscf.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
/*
* This macro defines the authentication state. If x is 1 authentication
* is required; othewise it is optional.
*/
#define AUTH(x, y) ((x) ? (y) == AUTH_OK \
: (y) == AUTH_OK || (y) == AUTH_NONE)
#define AUTH_NONE 0 /* authentication not required */
#define AUTH_OK 1 /* authentication OK */
#define AUTH_ERROR 2 /* authentication error */
#define AUTH_CRYPTO 3 /* crypto_NAK */
/*
* Set up Kiss Code values
*/
enum kiss_codes {
NOKISS, /* No Kiss Code */
RATEKISS, /* Rate limit Kiss Code */
DENYKISS, /* Deny Kiss */
RSTRKISS, /* Restricted Kiss */
XKISS, /* Experimental Kiss */
UNKNOWNKISS /* Unknown Kiss Code */
};
/*
* traffic shaping parameters
*/
#define NTP_IBURST 6 /* packets in iburst */
#define RESP_DELAY 1 /* refclock burst delay (s) */
/*
* pool soliciting restriction duration (s)
*/
#define POOL_SOLICIT_WINDOW 8
/*
* peer_select groups statistics for a peer used by clock_select() and
* clock_cluster().
*/
typedef struct peer_select_tag {
struct peer * peer;
double synch; /* sync distance */
double error; /* jitter */
double seljit; /* selection jitter */
} peer_select;
/*
* System variables are declared here. Unless specified otherwise, all
* times are in seconds.
*/
u_char sys_leap; /* system leap indicator, use set_sys_leap() to change this */
u_char xmt_leap; /* leap indicator sent in client requests, set up by set_sys_leap() */
u_char sys_stratum; /* system stratum */
s_char sys_precision; /* local clock precision (log2 s) */
double sys_rootdelay; /* roundtrip delay to primary source */
double sys_rootdisp; /* dispersion to primary source */
u_int32 sys_refid; /* reference id (network byte order) */
l_fp sys_reftime; /* last update time */
struct peer *sys_peer; /* current peer */
#ifdef LEAP_SMEAR
struct leap_smear_info leap_smear;
#endif
int leap_sec_in_progress;
/*
* Rate controls. Leaky buckets are used to throttle the packet
* transmission rates in order to protect busy servers such as at NIST
* and USNO. There is a counter for each association and another for KoD
* packets. The association counter decrements each second, but not
* below zero. Each time a packet is sent the counter is incremented by
* a configurable value representing the average interval between
* packets. A packet is delayed as long as the counter is greater than
* zero. Note this does not affect the time value computations.
*/
/*
* Nonspecified system state variables
*/
int sys_bclient; /* broadcast client enable */
double sys_bdelay; /* broadcast client default delay */
int sys_authenticate; /* requre authentication for config */
l_fp sys_authdelay; /* authentication delay */
double sys_offset; /* current local clock offset */
double sys_mindisp = MINDISPERSE; /* minimum distance (s) */
double sys_maxdist = MAXDISTANCE; /* selection threshold */
double sys_jitter; /* system jitter */
u_long sys_epoch; /* last clock update time */
static double sys_clockhop; /* clockhop threshold */
static int leap_vote_ins; /* leap consensus for insert */
static int leap_vote_del; /* leap consensus for delete */
keyid_t sys_private; /* private value for session seed */
int sys_manycastserver; /* respond to manycast client pkts */
int ntp_mode7; /* respond to ntpdc (mode7) */
int peer_ntpdate; /* active peers in ntpdate mode */
int sys_survivors; /* truest of the truechimers */
char *sys_ident = NULL; /* identity scheme */
/*
* TOS and multicast mapping stuff
*/
int sys_floor = 0; /* cluster stratum floor */
int sys_ceiling = STRATUM_UNSPEC - 1; /* cluster stratum ceiling */
int sys_minsane = 1; /* minimum candidates */
int sys_minclock = NTP_MINCLOCK; /* minimum candidates */
int sys_maxclock = NTP_MAXCLOCK; /* maximum candidates */
int sys_cohort = 0; /* cohort switch */
int sys_orphan = STRATUM_UNSPEC + 1; /* orphan stratum */
int sys_orphwait = NTP_ORPHWAIT; /* orphan wait */
int sys_beacon = BEACON; /* manycast beacon interval */
int sys_ttlmax; /* max ttl mapping vector index */
u_char sys_ttl[MAX_TTL]; /* ttl mapping vector */
/*
* Statistics counters - first the good, then the bad
*/
u_long sys_stattime; /* elapsed time */
u_long sys_received; /* packets received */
u_long sys_processed; /* packets for this host */
u_long sys_newversion; /* current version */
u_long sys_oldversion; /* old version */
u_long sys_restricted; /* access denied */
u_long sys_badlength; /* bad length or format */
u_long sys_badauth; /* bad authentication */
u_long sys_declined; /* declined */
u_long sys_limitrejected; /* rate exceeded */
u_long sys_kodsent; /* KoD sent */
/*
* Mechanism knobs: how soon do we unpeer()?
*
* The default way is "on-receipt". If this was a packet from a
* well-behaved source, on-receipt will offer the fastest recovery.
* If this was from a DoS attack, the default way makes it easier
* for a bad-guy to DoS us. So look and see what bites you harder
* and choose according to your environment.
*/
int unpeer_crypto_early = 1; /* bad crypto (TEST9) */
int unpeer_crypto_nak_early = 1; /* crypto_NAK (TEST5) */
int unpeer_digest_early = 1; /* bad digest (TEST5) */
static int kiss_code_check(u_char hisleap, u_char hisstratum, u_char hismode, u_int32 refid);
static double root_distance (struct peer *);
static void clock_combine (peer_select *, int, int);
static void peer_xmit (struct peer *);
static void fast_xmit (struct recvbuf *, int, keyid_t, int);
static void pool_xmit (struct peer *);
static void clock_update (struct peer *);
static void measure_precision(void);
static double measure_tick_fuzz(void);
static int local_refid (struct peer *);
static int peer_unfit (struct peer *);
#ifdef AUTOKEY
static int group_test (char *, char *);
#endif /* AUTOKEY */
#ifdef WORKER
void pool_name_resolved (int, int, void *, const char *,
const char *, const struct addrinfo *,
const struct addrinfo *);
#endif /* WORKER */
const char * amtoa (int am);
void
set_sys_leap(
u_char new_sys_leap
)
{
sys_leap = new_sys_leap;
xmt_leap = sys_leap;
/*
* Under certain conditions we send faked leap bits to clients, so
* eventually change xmt_leap below, but never change LEAP_NOTINSYNC.
*/
if (xmt_leap != LEAP_NOTINSYNC) {
if (leap_sec_in_progress) {
/* always send "not sync" */
xmt_leap = LEAP_NOTINSYNC;
}
#ifdef LEAP_SMEAR
else {
/*
* If leap smear is enabled in general we must
* never send a leap second warning to clients,
* so make sure we only send "in sync".
*/
if (leap_smear.enabled)
xmt_leap = LEAP_NOWARNING;
}
#endif /* LEAP_SMEAR */
}
}
/*
* Kiss Code check
*/
int
kiss_code_check(
u_char hisleap,
u_char hisstratum,
u_char hismode,
u_int32 refid
)
{
if ( hismode == MODE_SERVER
&& hisleap == LEAP_NOTINSYNC
&& hisstratum == STRATUM_UNSPEC) {
if(memcmp(&refid,"RATE", 4) == 0) {
return (RATEKISS);
} else if(memcmp(&refid,"DENY", 4) == 0) {
return (DENYKISS);
} else if(memcmp(&refid,"RSTR", 4) == 0) {
return (RSTRKISS);
} else if(memcmp(&refid,"X", 1) == 0) {
return (XKISS);
} else {
return (UNKNOWNKISS);
}
} else {
return (NOKISS);
}
}
/*
* transmit - transmit procedure called by poll timeout
*/
void
transmit(
struct peer *peer /* peer structure pointer */
)
{
u_char hpoll;
/*
* The polling state machine. There are two kinds of machines,
* those that never expect a reply (broadcast and manycast
* server modes) and those that do (all other modes). The dance
* is intricate...
*/
hpoll = peer->hpoll;
/*
* In broadcast mode the poll interval is never changed from
* minpoll.
*/
if (peer->cast_flags & (MDF_BCAST | MDF_MCAST)) {
peer->outdate = current_time;
if (sys_leap != LEAP_NOTINSYNC)
peer_xmit(peer);
poll_update(peer, hpoll);
return;
}
/*
* In manycast mode we start with unity ttl. The ttl is
* increased by one for each poll until either sys_maxclock
* servers have been found or the maximum ttl is reached. When
* sys_maxclock servers are found we stop polling until one or
* more servers have timed out or until less than sys_minclock
* associations turn up. In this case additional better servers
* are dragged in and preempt the existing ones. Once every
* sys_beacon seconds we are to transmit unconditionally, but
* this code is not quite right -- peer->unreach counts polls
* and is being compared with sys_beacon, so the beacons happen
* every sys_beacon polls.
*/
if (peer->cast_flags & MDF_ACAST) {
peer->outdate = current_time;
if (peer->unreach > sys_beacon) {
peer->unreach = 0;
peer->ttl = 0;
peer_xmit(peer);
} else if ( sys_survivors < sys_minclock
|| peer_associations < sys_maxclock) {
if (peer->ttl < (u_int32)sys_ttlmax)
peer->ttl++;
peer_xmit(peer);
}
peer->unreach++;
poll_update(peer, hpoll);
return;
}
/*
* Pool associations transmit unicast solicitations when there
* are less than a hard limit of 2 * sys_maxclock associations,
* and either less than sys_minclock survivors or less than
* sys_maxclock associations. The hard limit prevents unbounded
* growth in associations if the system clock or network quality
* result in survivor count dipping below sys_minclock often.
* This was observed testing with pool, where sys_maxclock == 12
* resulted in 60 associations without the hard limit. A
* similar hard limit on manycastclient ephemeral associations
* may be appropriate.
*/
if (peer->cast_flags & MDF_POOL) {
peer->outdate = current_time;
if ( (peer_associations <= 2 * sys_maxclock)
&& ( peer_associations < sys_maxclock
|| sys_survivors < sys_minclock))
pool_xmit(peer);
poll_update(peer, hpoll);
return;
}
/*
* In unicast modes the dance is much more intricate. It is
* designed to back off whenever possible to minimize network
* traffic.
*/
if (peer->burst == 0) {
u_char oreach;
/*
* Update the reachability status. If not heard for
* three consecutive polls, stuff infinity in the clock
* filter.
*/
oreach = peer->reach;
peer->outdate = current_time;
peer->unreach++;
peer->reach <<= 1;
if (!peer->reach) {
/*
* Here the peer is unreachable. If it was
* previously reachable raise a trap. Send a
* burst if enabled.
*/
clock_filter(peer, 0., 0., MAXDISPERSE);
if (oreach) {
peer_unfit(peer);
report_event(PEVNT_UNREACH, peer, NULL);
}
if ( (peer->flags & FLAG_IBURST)
&& peer->retry == 0)
peer->retry = NTP_RETRY;
} else {
/*
* Here the peer is reachable. Send a burst if
* enabled and the peer is fit. Reset unreach
* for persistent and ephemeral associations.
* Unreach is also reset for survivors in
* clock_select().
*/
hpoll = sys_poll;
if (!(peer->flags & FLAG_PREEMPT))
peer->unreach = 0;
if ( (peer->flags & FLAG_BURST)
&& peer->retry == 0
&& !peer_unfit(peer))
peer->retry = NTP_RETRY;
}
/*
* Watch for timeout. If ephemeral, toss the rascal;
* otherwise, bump the poll interval. Note the
* poll_update() routine will clamp it to maxpoll.
* If preemptible and we have more peers than maxclock,
* and this peer has the minimum score of preemptibles,
* demobilize.
*/
if (peer->unreach >= NTP_UNREACH) {
hpoll++;
/* ephemeral: no FLAG_CONFIG nor FLAG_PREEMPT */
if (!(peer->flags & (FLAG_CONFIG | FLAG_PREEMPT))) {
report_event(PEVNT_RESTART, peer, "timeout");
peer_clear(peer, "TIME");
unpeer(peer);
return;
}
if ( (peer->flags & FLAG_PREEMPT)
&& (peer_associations > sys_maxclock)
&& score_all(peer)) {
report_event(PEVNT_RESTART, peer, "timeout");
peer_clear(peer, "TIME");
unpeer(peer);
return;
}
}
} else {
peer->burst--;
if (peer->burst == 0) {
/*
* If ntpdate mode and the clock has not been
* set and all peers have completed the burst,
* we declare a successful failure.
*/
if (mode_ntpdate) {
peer_ntpdate--;
if (peer_ntpdate == 0) {
msyslog(LOG_NOTICE,
"ntpd: no servers found");
if (!msyslog_term)
printf(
"ntpd: no servers found\n");
exit (0);
}
}
}
}
if (peer->retry > 0)
peer->retry--;
/*
* Do not transmit if in broadcast client mode.
*/
if (peer->hmode != MODE_BCLIENT)
peer_xmit(peer);
poll_update(peer, hpoll);
return;
}
const char *
amtoa(
int am
)
{
char *bp;
switch(am) {
case AM_ERR: return "AM_ERR";
case AM_NOMATCH: return "AM_NOMATCH";
case AM_PROCPKT: return "AM_PROCPKT";
case AM_BCST: return "AM_BCST";
case AM_FXMIT: return "AM_FXMIT";
case AM_MANYCAST: return "AM_MANYCAST";
case AM_NEWPASS: return "AM_NEWPASS";
case AM_NEWBCL: return "AM_NEWBCL";
case AM_POSSBCL: return "AM_POSSBCL";
default:
LIB_GETBUF(bp);
snprintf(bp, LIB_BUFLENGTH, "AM_#%d", am);
return bp;
}
}
/*
* receive - receive procedure called for each packet received
*/
void
receive(
struct recvbuf *rbufp
)
{
register struct peer *peer; /* peer structure pointer */
register struct pkt *pkt; /* receive packet pointer */
u_char hisversion; /* packet version */
u_char hisleap; /* packet leap indicator */
u_char hismode; /* packet mode */
u_char hisstratum; /* packet stratum */
u_short restrict_mask; /* restrict bits */
const char *hm_str; /* hismode string */
const char *am_str; /* association match string */
int kissCode = NOKISS; /* Kiss Code */
int has_mac; /* length of MAC field */
int authlen; /* offset of MAC field */
int is_authentic = 0; /* cryptosum ok */
int retcode = AM_NOMATCH; /* match code */
keyid_t skeyid = 0; /* key IDs */
u_int32 opcode = 0; /* extension field opcode */
sockaddr_u *dstadr_sin; /* active runway */
struct peer *peer2; /* aux peer structure pointer */
endpt *match_ep; /* newpeer() local address */
l_fp p_org; /* origin timestamp */
l_fp p_rec; /* receive timestamp */
l_fp p_xmt; /* transmit timestamp */
#ifdef AUTOKEY
char hostname[NTP_MAXSTRLEN + 1];
char *groupname = NULL;
struct autokey *ap; /* autokey structure pointer */
int rval; /* cookie snatcher */
keyid_t pkeyid = 0, tkeyid = 0; /* key IDs */
#endif /* AUTOKEY */
#ifdef HAVE_NTP_SIGND
static unsigned char zero_key[16];
#endif /* HAVE_NTP_SIGND */
/*
* Monitor the packet and get restrictions. Note that the packet
* length for control and private mode packets must be checked
* by the service routines. Some restrictions have to be handled
* later in order to generate a kiss-o'-death packet.
*/
/*
* Bogus port check is before anything, since it probably
* reveals a clogging attack.
*/
sys_received++;
if (0 == SRCPORT(&rbufp->recv_srcadr)) {
sys_badlength++;
return; /* bogus port */
}
restrict_mask = restrictions(&rbufp->recv_srcadr);
pkt = &rbufp->recv_pkt;
DPRINTF(2, ("receive: at %ld %s<-%s flags %x restrict %03x org %#010x.%08x xmt %#010x.%08x\n",
current_time, stoa(&rbufp->dstadr->sin),
stoa(&rbufp->recv_srcadr), rbufp->dstadr->flags,
restrict_mask, ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf),
ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf)));
hisversion = PKT_VERSION(pkt->li_vn_mode);
hisleap = PKT_LEAP(pkt->li_vn_mode);
hismode = (int)PKT_MODE(pkt->li_vn_mode);
hisstratum = PKT_TO_STRATUM(pkt->stratum);
if (restrict_mask & RES_IGNORE) {
sys_restricted++;
return; /* ignore everything */
}
if (hismode == MODE_PRIVATE) {
if (!ntp_mode7 || (restrict_mask & RES_NOQUERY)) {
sys_restricted++;
return; /* no query private */
}
process_private(rbufp, ((restrict_mask &
RES_NOMODIFY) == 0));
return;
}
if (hismode == MODE_CONTROL) {
if (restrict_mask & RES_NOQUERY) {
sys_restricted++;
return; /* no query control */
}
process_control(rbufp, restrict_mask);
return;
}
if (restrict_mask & RES_DONTSERVE) {
sys_restricted++;
return; /* no time serve */
}
/*
* This is for testing. If restricted drop ten percent of
* surviving packets.
*/
if (restrict_mask & RES_FLAKE) {
if ((double)ntp_random() / 0x7fffffff < .1) {
sys_restricted++;
return; /* no flakeway */
}
}
/*
* Version check must be after the query packets, since they
* intentionally use an early version.
*/
if (hisversion == NTP_VERSION) {
sys_newversion++; /* new version */
} else if ( !(restrict_mask & RES_VERSION)
&& hisversion >= NTP_OLDVERSION) {
sys_oldversion++; /* previous version */
} else {
sys_badlength++;
return; /* old version */
}
/*
* Figure out his mode and validate the packet. This has some
* legacy raunch that probably should be removed. In very early
* NTP versions mode 0 was equivalent to what later versions
* would interpret as client mode.
*/
if (hismode == MODE_UNSPEC) {
if (hisversion == NTP_OLDVERSION) {
hismode = MODE_CLIENT;
} else {
sys_badlength++;
return; /* invalid mode */
}
}
/*
* Parse the extension field if present. We figure out whether
* an extension field is present by measuring the MAC size. If
* the number of words following the packet header is 0, no MAC
* is present and the packet is not authenticated. If 1, the
* packet is a crypto-NAK; if 3, the packet is authenticated
* with DES; if 5, the packet is authenticated with MD5; if 6,
* the packet is authenticated with SHA. If 2 or * 4, the packet
* is a runt and discarded forthwith. If greater than 6, an
* extension field is present, so we subtract the length of the
* field and go around again.
*/
authlen = LEN_PKT_NOMAC;
has_mac = rbufp->recv_length - authlen;
while (has_mac > 0) {
u_int32 len;
#ifdef AUTOKEY
u_int32 hostlen;
struct exten *ep;
#endif /*AUTOKEY */
if (has_mac % 4 != 0 || has_mac < (int)MIN_MAC_LEN) {
sys_badlength++;
return; /* bad length */
}
if (has_mac <= (int)MAX_MAC_LEN) {
skeyid = ntohl(((u_int32 *)pkt)[authlen / 4]);
break;
} else {
opcode = ntohl(((u_int32 *)pkt)[authlen / 4]);
len = opcode & 0xffff;
if ( len % 4 != 0
|| len < 4
|| (int)len + authlen > rbufp->recv_length) {
sys_badlength++;
return; /* bad length */
}
#ifdef AUTOKEY
/*
* Extract calling group name for later. If
* sys_groupname is non-NULL, there must be
* a group name provided to elicit a response.
*/
if ( (opcode & 0x3fff0000) == CRYPTO_ASSOC
&& sys_groupname != NULL) {
ep = (struct exten *)&((u_int32 *)pkt)[authlen / 4];
hostlen = ntohl(ep->vallen);
if ( hostlen >= sizeof(hostname)
|| hostlen > len -
offsetof(struct exten, pkt)) {
sys_badlength++;
return; /* bad length */
}
memcpy(hostname, &ep->pkt, hostlen);
hostname[hostlen] = '\0';
groupname = strchr(hostname, '@');
if (groupname == NULL) {
sys_declined++;
return;
}
groupname++;
}
#endif /* AUTOKEY */
authlen += len;
has_mac -= len;
}
}
/*
* If has_mac is < 0 we had a malformed packet.
*/
if (has_mac < 0) {
sys_badlength++;
return; /* bad length */
}
/*
* If authentication required, a MAC must be present.
*/
if (restrict_mask & RES_DONTTRUST && has_mac == 0) {
sys_restricted++;
return; /* access denied */
}
/*
* Update the MRU list and finger the cloggers. It can be a
* little expensive, so turn it off for production use.
* RES_LIMITED and RES_KOD will be cleared in the returned
* restrict_mask unless one or both actions are warranted.
*/
restrict_mask = ntp_monitor(rbufp, restrict_mask);
if (restrict_mask & RES_LIMITED) {
sys_limitrejected++;
if ( !(restrict_mask & RES_KOD)
|| MODE_BROADCAST == hismode
|| MODE_SERVER == hismode) {
if (MODE_SERVER == hismode)
DPRINTF(1, ("Possibly self-induced rate limiting of MODE_SERVER from %s\n",
stoa(&rbufp->recv_srcadr)));
return; /* rate exceeded */
}
if (hismode == MODE_CLIENT)
fast_xmit(rbufp, MODE_SERVER, skeyid,
restrict_mask);
else
fast_xmit(rbufp, MODE_ACTIVE, skeyid,
restrict_mask);
return; /* rate exceeded */
}
restrict_mask &= ~RES_KOD;
/*
* We have tossed out as many buggy packets as possible early in
* the game to reduce the exposure to a clogging attack. Now we
* have to burn some cycles to find the association and
* authenticate the packet if required. Note that we burn only
* digest cycles, again to reduce exposure. There may be no
* matching association and that's okay.
*
* More on the autokey mambo. Normally the local interface is
* found when the association was mobilized with respect to a
* designated remote address. We assume packets arriving from
* the remote address arrive via this interface and the local
* address used to construct the autokey is the unicast address
* of the interface. However, if the sender is a broadcaster,
* the interface broadcast address is used instead.
* Notwithstanding this technobabble, if the sender is a
* multicaster, the broadcast address is null, so we use the
* unicast address anyway. Don't ask.
*/
peer = findpeer(rbufp, hismode, &retcode);
dstadr_sin = &rbufp->dstadr->sin;
NTOHL_FP(&pkt->org, &p_org);
NTOHL_FP(&pkt->rec, &p_rec);
NTOHL_FP(&pkt->xmt, &p_xmt);
hm_str = modetoa(hismode);
am_str = amtoa(retcode);
/*
* Authentication is conditioned by three switches:
*
* NOPEER (RES_NOPEER) do not mobilize an association unless
* authenticated
* NOTRUST (RES_DONTTRUST) do not allow access unless
* authenticated (implies NOPEER)
* enable (sys_authenticate) master NOPEER switch, by default
* on
*
* The NOPEER and NOTRUST can be specified on a per-client basis
* using the restrict command. The enable switch if on implies
* NOPEER for all clients. There are four outcomes:
*
* NONE The packet has no MAC.
* OK the packet has a MAC and authentication succeeds
* ERROR the packet has a MAC and authentication fails
* CRYPTO crypto-NAK. The MAC has four octets only.
*
* Note: The AUTH(x, y) macro is used to filter outcomes. If x
* is zero, acceptable outcomes of y are NONE and OK. If x is
* one, the only acceptable outcome of y is OK.
*/
if (has_mac == 0) {
restrict_mask &= ~RES_MSSNTP;
is_authentic = AUTH_NONE; /* not required */
DPRINTF(2, ("receive: at %ld %s<-%s mode %d/%s:%s len %d org %#010x.%08x xmt %#010x.%08x NOMAC\n",
current_time, stoa(dstadr_sin),
stoa(&rbufp->recv_srcadr), hismode, hm_str, am_str,
authlen,
ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf),
ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf)));
} else if (has_mac == 4) {
restrict_mask &= ~RES_MSSNTP;
is_authentic = AUTH_CRYPTO; /* crypto-NAK */
DPRINTF(2, ("receive: at %ld %s<-%s mode %d/%s:%s keyid %08x len %d auth %d org %#010x.%08x xmt %#010x.%08x MAC4\n",
current_time, stoa(dstadr_sin),
stoa(&rbufp->recv_srcadr), hismode, hm_str, am_str,
skeyid, authlen + has_mac, is_authentic,
ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf),
ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf)));
#ifdef HAVE_NTP_SIGND
/*
* If the signature is 20 bytes long, the last 16 of
* which are zero, then this is a Microsoft client
* wanting AD-style authentication of the server's
* reply.
*
* This is described in Microsoft's WSPP docs, in MS-SNTP:
* http://msdn.microsoft.com/en-us/library/cc212930.aspx
*/
} else if ( has_mac == MAX_MD5_LEN
&& (restrict_mask & RES_MSSNTP)
&& (retcode == AM_FXMIT || retcode == AM_NEWPASS)
&& (memcmp(zero_key, (char *)pkt + authlen + 4,
MAX_MD5_LEN - 4) == 0)) {
is_authentic = AUTH_NONE;
#endif /* HAVE_NTP_SIGND */
} else {
restrict_mask &= ~RES_MSSNTP;
#ifdef AUTOKEY
/*
* For autokey modes, generate the session key
* and install in the key cache. Use the socket
* broadcast or unicast address as appropriate.
*/
if (crypto_flags && skeyid > NTP_MAXKEY) {
/*
* More on the autokey dance (AKD). A cookie is
* constructed from public and private values.
* For broadcast packets, the cookie is public
* (zero). For packets that match no
* association, the cookie is hashed from the
* addresses and private value. For server
* packets, the cookie was previously obtained
* from the server. For symmetric modes, the
* cookie was previously constructed using an
* agreement protocol; however, should PKI be
* unavailable, we construct a fake agreement as
* the EXOR of the peer and host cookies.
*
* hismode ephemeral persistent
* =======================================
* active 0 cookie#
* passive 0% cookie#
* client sys cookie 0%
* server 0% sys cookie
* broadcast 0 0
*
* # if unsync, 0
* % can't happen
*/
if (has_mac < (int)MAX_MD5_LEN) {
sys_badauth++;
return;
}
if (hismode == MODE_BROADCAST) {
/*
* For broadcaster, use the interface
* broadcast address when available;
* otherwise, use the unicast address
* found when the association was
* mobilized. However, if this is from
* the wildcard interface, game over.
*/
if ( crypto_flags
&& rbufp->dstadr ==
ANY_INTERFACE_CHOOSE(&rbufp->recv_srcadr)) {
sys_restricted++;
return; /* no wildcard */
}
pkeyid = 0;
if (!SOCK_UNSPEC(&rbufp->dstadr->bcast))
dstadr_sin =
&rbufp->dstadr->bcast;
} else if (peer == NULL) {
pkeyid = session_key(
&rbufp->recv_srcadr, dstadr_sin, 0,
sys_private, 0);
} else {
pkeyid = peer->pcookie;
}
/*
* The session key includes both the public
* values and cookie. In case of an extension
* field, the cookie used for authentication
* purposes is zero. Note the hash is saved for
* use later in the autokey mambo.
*/
if (authlen > (int)LEN_PKT_NOMAC && pkeyid != 0) {
session_key(&rbufp->recv_srcadr,
dstadr_sin, skeyid, 0, 2);
tkeyid = session_key(
&rbufp->recv_srcadr, dstadr_sin,
skeyid, pkeyid, 0);
} else {
tkeyid = session_key(
&rbufp->recv_srcadr, dstadr_sin,
skeyid, pkeyid, 2);
}
}
#endif /* AUTOKEY */
/*
* Compute the cryptosum. Note a clogging attack may
* succeed in bloating the key cache. If an autokey,
* purge it immediately, since we won't be needing it
* again. If the packet is authentic, it can mobilize an
* association. Note that there is no key zero.
*/
if (!authdecrypt(skeyid, (u_int32 *)pkt, authlen,
has_mac))
is_authentic = AUTH_ERROR;
else
is_authentic = AUTH_OK;
#ifdef AUTOKEY
if (crypto_flags && skeyid > NTP_MAXKEY)
authtrust(skeyid, 0);
#endif /* AUTOKEY */
DPRINTF(2, ("receive: at %ld %s<-%s mode %d/%s:%s keyid %08x len %d auth %d org %#010x.%08x xmt %#010x.%08x\n",
current_time, stoa(dstadr_sin),
stoa(&rbufp->recv_srcadr), hismode, hm_str, am_str,
skeyid, authlen + has_mac, is_authentic,
ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf),
ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf)));
}
/*
* The association matching rules are implemented by a set of
* routines and an association table. A packet matching an
* association is processed by the peer process for that
* association. If there are no errors, an ephemeral association
* is mobilized: a broadcast packet mobilizes a broadcast client
* aassociation; a manycast server packet mobilizes a manycast
* client association; a symmetric active packet mobilizes a
* symmetric passive association.
*/
switch (retcode) {
/*
* This is a client mode packet not matching any association. If
* an ordinary client, simply toss a server mode packet back
* over the fence. If a manycast client, we have to work a
* little harder.
*/
case AM_FXMIT:
/*
* If authentication OK, send a server reply; otherwise,
* send a crypto-NAK.
*/
if (!(rbufp->dstadr->flags & INT_MCASTOPEN)) {
if (AUTH(restrict_mask & RES_DONTTRUST,
is_authentic)) {
fast_xmit(rbufp, MODE_SERVER, skeyid,
restrict_mask);
} else if (is_authentic == AUTH_ERROR) {
fast_xmit(rbufp, MODE_SERVER, 0,
restrict_mask);
sys_badauth++;
} else {
sys_restricted++;
}
return; /* hooray */
}
/*
* This must be manycast. Do not respond if not
* configured as a manycast server.
*/
if (!sys_manycastserver) {
sys_restricted++;
return; /* not enabled */
}
#ifdef AUTOKEY
/*
* Do not respond if not the same group.
*/
if (group_test(groupname, NULL)) {
sys_declined++;
return;
}
#endif /* AUTOKEY */
/*
* Do not respond if we are not synchronized or our
* stratum is greater than the manycaster or the
* manycaster has already synchronized to us.
*/
if ( sys_leap == LEAP_NOTINSYNC
|| sys_stratum >= hisstratum
|| (!sys_cohort && sys_stratum == hisstratum + 1)
|| rbufp->dstadr->addr_refid == pkt->refid) {
sys_declined++;
return; /* no help */
}
/*
* Respond only if authentication succeeds. Don't do a
* crypto-NAK, as that would not be useful.
*/
if (AUTH(restrict_mask & RES_DONTTRUST, is_authentic))
fast_xmit(rbufp, MODE_SERVER, skeyid,
restrict_mask);
return; /* hooray */