~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to ntpd/refclock_atom.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2009-01-05 21:10:03 UTC
  • mfrom: (1.2.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20090105211003-mh6zc3um4k1uhsj7
Tags: 1:4.2.4p4+dfsg-8
It did not properly check the return value of EVP_VerifyFinal
which results in an malformed DSA signature being treated as
a good signature rather than as an error.  (CVE-2009-0021)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
1
/*
3
2
 * refclock_atom - clock driver for 1-pps signals
4
3
 */
18
17
#if defined(REFCLOCK) && defined(CLOCK_ATOM)
19
18
 
20
19
#ifdef HAVE_PPSAPI
21
 
# ifdef HAVE_TIMEPPS_H
22
 
#  include <timepps.h>
23
 
# else
24
 
#  ifdef HAVE_SYS_TIMEPPS_H
25
 
#   include <sys/timepps.h>
26
 
#  endif
27
 
# endif
 
20
# include "ppsapi_timepps.h"
28
21
#endif /* HAVE_PPSAPI */
29
22
 
30
23
/*
48
41
 * Systems, Version 1.0, RFC-2783 (PPSAPI). Implementations are
49
42
 * available for FreeBSD, Linux, SunOS, Solaris and Alpha. However, at
50
43
 * present only the Alpha implementation provides the full generality of
51
 
 * the API with multiple PPS drivers and multiple handles per driver.
 
44
 * the API with multiple PPS drivers and multiple handles per driver. If
 
45
 * the PPSAPI is normally implemented in the /usr/include/sys/timepps.h
 
46
 * header file and kernel support specific to each operating system.
 
47
 * However, this driver can operate without this interface if means are
 
48
 * proviced to call the pps_sample() routine from another driver. Please
 
49
 * note; if the PPSAPI interface is present, it must be used.
52
50
 *
53
51
 * In many configurations a single port is used for the radio timecode
54
52
 * and PPS signal. In order to provide for this configuration and others
61
59
 * configuration file.
62
60
 *
63
61
 * This driver normally uses the PLL/FLL clock discipline implemented in
64
 
 * the ntpd code. If kernel support is available, the kernel PLL/FLL
65
 
 * clock discipline is used instead. The default configuration is not to
66
 
 * use the kernel PPS discipline, if present. The kernel PPS discipline
67
 
 * can be enabled using the pps command.
 
62
 * the ntpd code. Ordinarily, this is the most accurate means, as the
 
63
 * median filter in the driver interface is much larger than in the
 
64
 * kernel. However, if the systemic clock frequency error is large (tens
 
65
 * to hundreds of PPM), it's better to used the kernel support, if
 
66
 * available.
68
67
 *
69
68
 * Fudge Factors
70
69
 *
71
 
 * There are no special fudge factors other than the generic. The fudge
72
 
 * time1 parameter can be used to compensate for miscellaneous device
73
 
 * driver and OS delays.
 
70
 * If flag2 is dim (default), the on-time epoch is the assert edge of
 
71
 * the PPS signal; if lit, the on-time epoch is the clear edge. If flag2
 
72
 * is lit, the assert edge is used; if flag3 is dim (default), the
 
73
 * kernel PPS support is disabled; if lit it is enabled. The time1
 
74
 * parameter can be used to compensate for miscellaneous device driver
 
75
 * and OS delays.
74
76
 */
75
77
/*
76
78
 * Interface definitions
84
86
#define DESCRIPTION     "PPS Clock Discipline" /* WRU */
85
87
#define NANOSECOND      1000000000 /* one second (ns) */
86
88
#define RANGEGATE       500000  /* range gate (ns) */
87
 
#define ASTAGE          8       /* filter stages */
88
89
 
89
90
static struct peer *pps_peer;   /* atom driver for PPS sources */
90
91
 
106
107
 */
107
108
static  int     atom_start      P((int, struct peer *));
108
109
static  void    atom_poll       P((int, struct peer *));
109
 
#ifdef HAVE_PPSAPI
110
110
static  void    atom_shutdown   P((int, struct peer *));
 
111
#ifdef HAVE_PPSAPI
111
112
static  void    atom_control    P((int, struct refclockstat *, struct
112
113
                                    refclockstat *, struct peer *));
113
 
static  int     atom_pps        P((struct peer *));
114
 
static  int     atom_ppsapi     P((struct peer *, int, int));
 
114
static  void    atom_timer      P((int, struct peer *));
 
115
static  int     atom_ppsapi     P((struct peer *, int));
115
116
#endif /* HAVE_PPSAPI */
116
117
 
117
118
/*
118
119
 * Transfer vector
119
120
 */
 
121
#ifdef HAVE_PPSAPI
120
122
struct  refclock refclock_atom = {
121
123
        atom_start,             /* start up driver */
122
 
#ifdef HAVE_PPSAPI
123
124
        atom_shutdown,          /* shut down driver */
124
 
#else
125
 
        noentry,                /* shut down driver */
126
 
#endif /* HAVE_PPSAPI */
127
125
        atom_poll,              /* transmit poll message */
128
 
#ifdef HAVE_PPSAPI
129
126
        atom_control,           /* fudge control */
130
 
#else
131
 
        noentry,                /* fudge control */
132
 
#endif /* HAVE_PPSAPI */
133
 
        noentry,                /* initialize driver */
134
 
        noentry,                /* not used (old atom_buginfo) */
 
127
        noentry,                /* initialize driver (not used) */
 
128
        noentry,                /* buginfo (not used) */
 
129
        atom_timer,             /* called once per second */
 
130
};
 
131
#else /* HAVE_PPSAPI */
 
132
struct  refclock refclock_atom = {
 
133
        atom_start,             /* start up driver */
 
134
        atom_shutdown,          /* shut down driver */
 
135
        atom_poll,              /* transmit poll message */
 
136
        noentry,                /* fudge control (not used) */
 
137
        noentry,                /* initialize driver (not used) */
 
138
        noentry,                /* buginfo (not used) */
135
139
        NOFLAGS                 /* not used */
136
140
};
 
141
#endif /* HAVE_PPPSAPI */
137
142
 
138
143
 
139
144
/*
148
153
        struct refclockproc *pp;
149
154
#ifdef HAVE_PPSAPI
150
155
        register struct ppsunit *up;
151
 
        char device[80];
 
156
        char    device[80];
 
157
        int     mode;
152
158
#endif /* HAVE_PPSAPI */
153
159
 
154
160
        /*
160
166
        pp->clockdesc = DESCRIPTION;
161
167
        pp->stratum = STRATUM_UNSPEC;
162
168
        memcpy((char *)&pp->refid, REFID, 4);
163
 
        peer->burst = ASTAGE;
164
169
#ifdef HAVE_PPSAPI
165
170
        up = emalloc(sizeof(struct ppsunit));
166
171
        memset(up, 0, sizeof(struct ppsunit));
167
172
        pp->unitptr = (caddr_t)up;
168
173
 
169
174
        /*
170
 
         * Open PPS device. If this fails and some driver has already
171
 
         * opened the associated radio device, fdpps has the file
172
 
         * descriptor for it.
 
175
         * Open PPS device. This can be any serial or parallel port and
 
176
         * not necessarily the port used for the associated radio.
173
177
         */
174
178
        sprintf(device, DEVICE, unit);
175
179
        up->fddev = open(device, O_RDWR, 0777);
176
 
        if (up->fddev <= 0 && fdpps > 0) {
177
 
                strcpy(device, pps_device);
178
 
                up->fddev = fdpps;
179
 
        }
180
180
        if (up->fddev <= 0) {
181
181
                msyslog(LOG_ERR,
182
182
                    "refclock_atom: %s: %m", device);
184
184
        }
185
185
 
186
186
        /*
187
 
         * Light off the PPSAPI interface. If this PPS device is shared
188
 
         * with the radio device, take the default options from the pps
189
 
         * command. This is for legacy purposes.
 
187
         * Light off the PPSAPI interface.
190
188
         */
191
189
        if (time_pps_create(up->fddev, &up->handle) < 0) {
192
190
                msyslog(LOG_ERR,
193
191
                    "refclock_atom: time_pps_create failed: %m");
194
192
                return (0);
195
193
        }
196
 
        return (atom_ppsapi(peer, 0, 0));
 
194
 
 
195
        /*
 
196
         * If the mode is nonzero, use that for the time_pps_setparams()
 
197
         * mode; otherwise, PPS_CAPTUREASSERT. Enable kernel PPS if
 
198
         * flag3 is lit.
 
199
         */
 
200
        mode = peer->ttl;
 
201
        if (mode == 0)
 
202
                mode = PPS_CAPTUREASSERT;
 
203
        return (atom_ppsapi(peer, mode));
197
204
#else /* HAVE_PPSAPI */
198
205
        return (1);
199
206
#endif /* HAVE_PPSAPI */
200
207
}
201
208
 
202
209
 
 
210
/*
 
211
 * atom_shutdown - shut down the clock
 
212
 */
 
213
static void
 
214
atom_shutdown(
 
215
        int unit,               /* unit number (not used) */
 
216
        struct peer *peer       /* peer structure pointer */
 
217
        )
 
218
{
 
219
        struct refclockproc *pp;
 
220
        register struct ppsunit *up;
 
221
 
 
222
        pp = peer->procptr;
 
223
        up = (struct ppsunit *)pp->unitptr;
 
224
#ifdef HAVE_PPSAPI
 
225
        if (up->fddev > 0)
 
226
                close(up->fddev);
 
227
        if (up->handle != 0)
 
228
                time_pps_destroy(up->handle);
 
229
#endif /* HAVE_PPSAPI */
 
230
        if (pps_peer == peer)
 
231
                pps_peer = NULL;
 
232
        free(up);
 
233
}
 
234
 
 
235
 
203
236
#ifdef HAVE_PPSAPI
204
237
/*
205
238
 * atom_control - fudge control
213
246
        )
214
247
{
215
248
        struct refclockproc *pp;
 
249
        int     mode;
216
250
 
217
251
        pp = peer->procptr;
218
 
        atom_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2,
219
 
            pp->sloppyclockflag & CLK_FLAG3);
 
252
        if (peer->ttl != 0)     /* all legal modes must be nonzero */
 
253
                return;
 
254
 
 
255
        if (pp->sloppyclockflag & CLK_FLAG2)
 
256
                mode = PPS_CAPTURECLEAR;
 
257
        else
 
258
                mode = PPS_CAPTUREASSERT;
 
259
        atom_ppsapi(peer, mode);
220
260
}
221
261
 
222
262
 
226
266
int
227
267
atom_ppsapi(
228
268
        struct peer *peer,      /* peer structure pointer */
229
 
        int enb_clear,          /* clear enable */
230
 
        int enb_hardpps         /* hardpps enable */
 
269
        int mode                /* mode */
231
270
        )
232
271
{
233
272
        struct refclockproc *pp;
236
275
 
237
276
        pp = peer->procptr;
238
277
        up = (struct ppsunit *)pp->unitptr;
 
278
        if (up->handle == 0)
 
279
                return (0);
 
280
 
239
281
        if (time_pps_getcap(up->handle, &capability) < 0) {
240
282
                msyslog(LOG_ERR,
241
283
                    "refclock_atom: time_pps_getcap failed: %m");
242
284
                return (0);
243
285
        }
244
286
        memset(&up->pps_params, 0, sizeof(pps_params_t));
245
 
        if (enb_clear)
246
 
                up->pps_params.mode = capability & PPS_CAPTURECLEAR;
247
 
        else
248
 
                up->pps_params.mode = capability & PPS_CAPTUREASSERT;
249
 
        if (!up->pps_params.mode) {
250
 
                msyslog(LOG_ERR,
251
 
                    "refclock_atom: invalid capture edge %d",
252
 
                    enb_clear);
253
 
                return (0);
254
 
        }
255
 
        up->pps_params.mode |= PPS_TSFMT_TSPEC;
 
287
        up->pps_params.api_version = PPS_API_VERS_1;
 
288
        up->pps_params.mode = mode | PPS_TSFMT_TSPEC;
256
289
        if (time_pps_setparams(up->handle, &up->pps_params) < 0) {
257
290
                msyslog(LOG_ERR,
258
291
                    "refclock_atom: time_pps_setparams failed: %m");
259
292
                return (0);
260
293
        }
261
 
        if (enb_hardpps) {
 
294
        if (pp->sloppyclockflag & CLK_FLAG3) {
262
295
                if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS,
263
296
                    up->pps_params.mode & ~PPS_TSFMT_TSPEC,
264
297
                    PPS_TSFMT_TSPEC) < 0) {
272
305
        if (debug) {
273
306
                time_pps_getparams(up->handle, &up->pps_params);
274
307
                printf(
275
 
                    "refclock_ppsapi: fd %d capability 0x%x version %d mode 0x%x kern %d\n",
 
308
                    "refclock_ppsapi: fd %d capability 0x%x version %d mode 0x%x\n",
276
309
                    up->fddev, capability, up->pps_params.api_version,
277
 
                    up->pps_params.mode, enb_hardpps);
 
310
                    up->pps_params.mode);
278
311
        }
279
312
#endif
280
313
        return (1);
282
315
 
283
316
 
284
317
/*
285
 
 * atom_shutdown - shut down the clock
286
 
 */
287
 
static void
288
 
atom_shutdown(
289
 
        int unit,               /* unit number (not used) */
290
 
        struct peer *peer       /* peer structure pointer */
291
 
        )
292
 
{
293
 
        struct refclockproc *pp;
294
 
        register struct ppsunit *up;
295
 
 
296
 
        pp = peer->procptr;
297
 
        up = (struct ppsunit *)pp->unitptr;
298
 
        if (up->fddev > 0)
299
 
                close(up->fddev);
300
 
        if (up->handle != 0)
301
 
                time_pps_destroy(up->handle);
302
 
        if (pps_peer == peer)
303
 
                pps_peer = 0;
304
 
        free(up);
305
 
}
306
 
 
307
 
 
308
 
/*
309
 
 * atom_pps - receive data from the PPSAPI interface
 
318
 * atom_timer - called once per second
310
319
 *
311
320
 * This routine is called once per second when the PPSAPI interface is
312
321
 * present. It snatches the PPS timestamp from the kernel and saves the
313
322
 * sign-extended fraction in a circular buffer for processing at the
314
323
 * next poll event.
315
324
 */
316
 
static int
317
 
atom_pps(
 
325
static void
 
326
atom_timer(
 
327
        int     unit,           /* unit number (not used) */
318
328
        struct peer *peer       /* peer structure pointer */
319
329
        )
320
330
{
322
332
        struct refclockproc *pp;
323
333
        pps_info_t pps_info;
324
334
        struct timespec timeout, ts;
325
 
        double dtemp;
 
335
        long    sec, nsec;
 
336
        double  dtemp;
 
337
        char    tbuf[80];       /* monitor buffer */
326
338
 
327
339
        /*
328
340
         * Convert the timespec nanoseconds field to signed double and
334
346
        pp = peer->procptr;
335
347
        up = (struct ppsunit *)pp->unitptr;
336
348
        if (up->handle == 0)
337
 
                return (-1);
 
349
                return;
 
350
 
338
351
        timeout.tv_sec = 0;
339
352
        timeout.tv_nsec = 0;
340
353
        memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t));
341
354
        if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info,
342
 
            &timeout) < 0)
343
 
                return (-1);
 
355
            &timeout) < 0) {
 
356
                refclock_report(peer, CEVNT_FAULT);
 
357
                return;
 
358
        }
344
359
        if (up->pps_params.mode & PPS_CAPTUREASSERT) {
345
 
                if (pps_info.assert_sequence ==
346
 
                    up->pps_info.assert_sequence)
347
 
                        return (1);
348
360
                ts = up->pps_info.assert_timestamp;
349
361
        } else if (up->pps_params.mode & PPS_CAPTURECLEAR) {
350
 
                if (pps_info.clear_sequence ==
351
 
                    up->pps_info.clear_sequence)
352
 
                        return (1);
353
362
                ts = up->pps_info.clear_timestamp;
354
363
        } else {
355
 
                return (-1);
356
 
        }
357
 
        if (!((ts.tv_sec == up->ts.tv_sec && ts.tv_nsec -
358
 
            up->ts.tv_nsec > NANOSECOND - RANGEGATE) ||
359
 
            (ts.tv_sec - up->ts.tv_sec == 1 && ts.tv_nsec -
360
 
            up->ts.tv_nsec < RANGEGATE))) {
361
 
                up->ts = ts;
362
 
                return (1);
363
 
        }
 
364
                refclock_report(peer, CEVNT_FAULT);
 
365
                return;
 
366
        }
 
367
 
 
368
        /*
 
369
         * There can be zero, one or two PPS seconds between polls. If
 
370
         * zero, either the poll clock is slightly faster than the PPS
 
371
         * clock or the PPS clock has died. If the PPS clock advanced
 
372
         * once between polls, we make sure the fraction time difference
 
373
         * since the last sample is within the range gate of 5 ms (500
 
374
         * PPM). If the PPS clock advanced twice since the last poll,
 
375
         * the poll bracketed more than one second and the first second
 
376
         * was lost to a slip. Since the interval since the last sample
 
377
         * found is now two seconds, just widen the range gate. If the
 
378
         * PPS clock advanced three or more times, either the signal has
 
379
         * failed for a number of seconds or we have runts, in which
 
380
         * case just ignore them.
 
381
         *
 
382
         * If flag4 is lit, record each second offset to clockstats.
 
383
         * That's so we can make awesome Allan deviation plots.
 
384
         */
 
385
        sec = ts.tv_sec - up->ts.tv_sec;
 
386
        nsec = ts.tv_nsec - up->ts.tv_nsec;
364
387
        up->ts = ts;
 
388
        if (nsec < 0) {
 
389
                sec --;
 
390
                nsec += NANOSECOND;
 
391
        } else if (nsec >= NANOSECOND) {
 
392
                sec++;
 
393
                nsec -= NANOSECOND;
 
394
        }
 
395
        if (sec * NANOSECOND + nsec > NANOSECOND + RANGEGATE)
 
396
                return;
 
397
 
 
398
        else if (sec * NANOSECOND + nsec < NANOSECOND - RANGEGATE)
 
399
                return;
 
400
 
365
401
        pp->lastrec.l_ui = ts.tv_sec + JAN_1970;
366
402
        dtemp = ts.tv_nsec * FRAC / 1e9;
367
403
        if (dtemp >= FRAC)
371
407
                ts.tv_nsec -= NANOSECOND;
372
408
        dtemp = -(double)ts.tv_nsec / NANOSECOND;
373
409
        SAMPLE(dtemp + pp->fudgetime1);
 
410
        if (pp->sloppyclockflag & CLK_FLAG4){
 
411
                sprintf(tbuf, "%.9f", dtemp);
 
412
                record_clock_stats(&peer->srcadr, tbuf);
 
413
        }
374
414
#ifdef DEBUG
375
415
        if (debug > 1)
376
 
                printf("atom_pps %f %f\n", dtemp, pp->fudgetime1);
 
416
                printf("atom_timer: %lu %f %f\n", current_time,
 
417
                    dtemp, pp->fudgetime1);
377
418
#endif
378
 
        return (0);
 
419
        return;
379
420
}
380
421
#endif /* HAVE_PPSAPI */
381
422
 
387
428
 * processes PPS information. It processes the PPS timestamp and saves
388
429
 * the sign-extended fraction in a circular buffer for processing at the
389
430
 * next poll event. This works only for a single PPS device.
 
431
 *
 
432
 * The routine should be used by another configured driver ONLY when
 
433
 * this driver is configured as well and the PPSAPI is NOT in use.
390
434
 */
391
435
int
392
436
pps_sample(
399
443
        double doffset;
400
444
 
401
445
        peer = pps_peer;
402
 
        if (peer == 0)          /* nobody home */
 
446
        if (peer == NULL)
403
447
                return (1);
 
448
 
404
449
        pp = peer->procptr;
405
450
 
406
451
        /*
417
462
        return (0);
418
463
}
419
464
 
 
465
 
420
466
/*
421
467
 * atom_poll - called by the transmit procedure
422
 
 *
423
 
 * This routine is called once per second when in burst mode to save PPS
424
 
 * sample offsets in the median filter. At the end of the burst period
425
 
 * the samples are processed as a heap and the clock filter updated.
426
468
 */
427
469
static void
428
470
atom_poll(
431
473
        )
432
474
{
433
475
        struct refclockproc *pp;
434
 
#ifdef HAVE_PPSAPI
435
 
        int err;
436
 
#endif /* HAVE_PPSAPI */
437
 
 
438
 
        /*
439
 
         * Accumulate samples in the median filter. If a noise sample,
440
 
         * return with no prejudice; if a protocol error, get mean;
441
 
         * otherwise, cool. At the end of each poll interval, do a
442
 
         * little bookeeping and process the surviving samples.
443
 
         */
444
476
        pp = peer->procptr;
445
477
        pp->polls++;
446
 
#ifdef HAVE_PPSAPI
447
 
        err = atom_pps(peer);
448
 
        if (err < 0) {
449
 
                refclock_report(peer, CEVNT_FAULT);
450
 
                return;
451
 
        }
452
 
#endif /* HAVE_PPSAPI */
453
478
 
454
479
        /*
455
480
         * Valid time is returned only if the prefer peer has survived
456
 
         * the intersection algorithm and within clock_max of local time
 
481
         * the intersection algorithm and within 0.4 s of local time
457
482
         * and not too long ago. This ensures the PPS time is within
458
 
         * +-0.5 s of the local time and the seconds numbering is
459
 
         * unambiguous. Note that the leap bits are set no-warning on
460
 
         * the first valid update and the stratum is set at the prefer
461
 
         * peer, unless overriden by a fudge command.
 
483
         * 0.5 s of the local time and the seconds numbering is
 
484
         * unambiguous. Note that the leap bits, stratum and refid are
 
485
         * set from the prefer peer, unless overriden by a fudge
 
486
         * command.
462
487
         */
463
 
        if (peer->burst > 0)
464
 
                return;
465
 
        peer->leap = LEAP_NOTINSYNC;
466
488
        if (pp->codeproc == pp->coderecv) {
467
489
                refclock_report(peer, CEVNT_TIMEOUT);
468
 
                peer->burst = ASTAGE;
469
490
                return;
470
491
 
471
492
        } else if (sys_prefer == NULL) {
472
493
                pp->codeproc = pp->coderecv;
473
 
                peer->burst = ASTAGE;
474
494
                return;
475
495
 
476
 
        } else if (fabs(sys_prefer->offset) > clock_max) {
 
496
        } else if (fabs(sys_prefer->offset) >= 0.4) {
477
497
                pp->codeproc = pp->coderecv;
478
 
                peer->burst = ASTAGE;
479
498
                return;
480
499
        }
481
 
        pp->leap = LEAP_NOWARNING;
 
500
        pp->leap = sys_prefer->leap;
482
501
        if (pp->stratum >= STRATUM_UNSPEC)
483
502
                peer->stratum = sys_prefer->stratum;
484
503
        else
485
504
                peer->stratum = pp->stratum;
486
 
        if (peer->stratum == STRATUM_REFCLOCK || peer->stratum ==
487
 
            STRATUM_UNSPEC)
488
 
                peer->refid = pp->refid;
489
 
        else
490
 
                peer->refid = addr2refid(&sys_prefer->srcadr);
491
505
        pp->lastref = pp->lastrec;
492
506
        refclock_receive(peer);
493
 
        peer->burst = ASTAGE;
494
507
}
495
508
#else
496
509
int refclock_atom_bs;
499
512
           l_fp *offset         /* PPS offset */
500
513
           )
501
514
{
502
 
        return 1;
 
515
        return (1);
503
516
}
504
517
#endif /* REFCLOCK */