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

« back to all changes in this revision

Viewing changes to util/ntp-genkeys.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-10-11 16:10:27 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041011161027-icyjbji8ujym633o
Tags: 1:4.2.0a-10ubuntu2
Use ntp.ubuntulinux.org instead of pool.ntp.org

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Program to generate MD5 and RSA keys for NTP clients and servers
3
 
 */
4
 
 
5
 
#ifdef HAVE_CONFIG_H
6
 
# include <config.h>
7
 
#endif
8
 
 
9
 
#ifdef HAVE_NETINFO
10
 
#include <netinfo/ni.h>
11
 
#endif
12
 
 
13
 
#include "ntpd.h"
14
 
#include "ntp_stdlib.h"
15
 
#include "ntp_string.h"
16
 
#include "ntp_filegen.h"
17
 
#include "ntp_unixtime.h"
18
 
#include "ntp_config.h"
19
 
#include "ntp_cmdargs.h"
20
 
 
21
 
#include <stdio.h>
22
 
#include <unistd.h>
23
 
#include <limits.h>             /* PATH_MAX */
24
 
#include <sys/stat.h>
25
 
 
26
 
#ifdef PUBKEY
27
 
# include "ntp_crypto.h"
28
 
#endif
29
 
 
30
 
#ifndef PATH_MAX
31
 
# ifdef _POSIX_PATH_MAX
32
 
#  define PATH_MAX _POSIX_PATH_MAX
33
 
# else
34
 
#  define PATH_MAX 255
35
 
# endif
36
 
#endif
37
 
 
38
 
/*
39
 
 * Cryptodefines
40
 
 */
41
 
#define MAXKEYLEN       1024    /* maximum encoded key length */
42
 
#define MODULUSLEN      512     /* length of RSA modulus */
43
 
#define PRIMELEN        512     /* length of D_H prime, generator */
44
 
 
45
 
/*
46
 
 * This program generates (up to) four files:
47
 
 *
48
 
 *      ntp.keys    containing the DES/MD5 private keys,
49
 
 *      ntpkey      containing the RSA private key,
50
 
 *      ntpkey_HOST containing the RSA public key
51
 
 *                   where HOST is the DNS name of the generating machine,
52
 
 *      ntpkey_dh   containing the parameters for the Diffie-Hellman
53
 
 *                  key-agreement algorithm.
54
 
 *
55
 
 * The files contain cryptographic values generated by the algorithms of
56
 
 * the rsaref20 package and are in printable ASCII format.  Since the
57
 
 * algorythms are seeded by the system clock, each run of this program
58
 
 * will produce a different outcome.  There are no options or frills of
59
 
 * any sort, although a number of options would seem to be appropriate.
60
 
 * Waving this program in the breeze will no doubt bring a cast of
61
 
 * thousands to wiggle the options this way and that for various useful
62
 
 * purposes.
63
 
 *
64
 
 * The names of all files begin with "ntp" and end with an extension
65
 
 * consisting of the seconds value of the current NTP timestamp, which
66
 
 * appears in the form ".*".  This provides a way to distinguish between
67
 
 * key generations, since the host name and timestamp can be fetched by
68
 
 * a client during operation.
69
 
 *
70
 
 * The ntp.keys.* file contains 16 MD5 keys.  Each key consists of 16
71
 
 * characters randomized over the ASCII 95-character printing subset.
72
 
 * The file is read by the daemon at the location specified by the keys
73
 
 * configuration file command and made visible only to root.  An
74
 
 * additional key consisting of a easily remembered password should be
75
 
 * added by hand for use with the ntpdc program.  The file must be
76
 
 * distributed by secure means to other servers and clients sharing the
77
 
 * same security compartment.
78
 
 *
79
 
 * The key identifiers for MD5 and DES keys must be less than 65536,
80
 
 * although this program uses only the identifiers from 1 to 16.  The key
81
 
 * identifier for each association is specified as the key argument in
82
 
 * the server or peer configuration file command.
83
 
 *
84
 
 * The ntpkey.* file contains the RSA private key.  It is read by the
85
 
 * daemon at the location specified by the private argument of the
86
 
 * crypto configuration file command and made visible only to root.
87
 
 * This file is useful only to the machine that generated it and never
88
 
 * shared with any other daemon or application program.
89
 
 *
90
 
 * The ntpkey_host.* file contains the RSA public key, where host is the
91
 
 * DNS name of the host that generated it.  The file is read by the
92
 
 * daemon at the location specified by the public argument to the server
93
 
 * or peer configuration file command.  This file can be widely
94
 
 * distributed and stored without using secure means, since the data are
95
 
 * public values.
96
 
 *
97
 
 * The ntp_dh.* file contains two Diffie-Hellman parameters, the prime
98
 
 * modulus and the generator.  The file is read by the daemon at the
99
 
 * location specified by the dhparams argument of the crypto
100
 
 * configuration file command.  This file can be widely distributed and
101
 
 * stored without using secure means, since the data are public values.
102
 
 *
103
 
 * The file formats all begin with two lines.  The first line contains
104
 
 * the file name and decimal timestamp, while the second contains the
105
 
 * readable datestamp.  Lines beginning with # are considered comments
106
 
 * and ignored by the daemon.  In the ntp.keys.* file, the next 16 lines
107
 
 * contain the MD5 keys in order.  In the ntpkey.* and ntpkey_host.*
108
 
 * files, the next line contains the modulus length in bits followed by
109
 
 * the key as a PEM encoded string.  In the ntpkey_dh.* file, the next
110
 
 * line contains the prime length in bytes followed by the prime as a
111
 
 * PEM encoded string, and the next and final line contains the
112
 
 * generator length in bytes followed by the generator as a PEM encoded
113
 
 * string.
114
 
 *
115
 
 * Note: See the file ./source/rsaref.h in the rsaref20 package for
116
 
 * explanation of return values, if necessary.
117
 
 */
118
 
 
119
 
 
120
 
extern char *config_file;
121
 
 
122
 
#ifdef HAVE_NETINFO
123
 
extern struct netinfo_config_state *config_netinfo;
124
 
extern int check_netinfo;
125
 
#endif /* HAVE_NETINFO */
126
 
 
127
 
#ifdef SYS_WINNT
128
 
char *alt_config_file;
129
 
LPTSTR temp;
130
 
char config_file_storage[PATH_MAX];
131
 
char alt_config_file_storage[PATH_MAX];
132
 
#endif /* SYS_WINNT */
133
 
 
134
 
int make_dh = 0;                /* Make D-H parameter file? */
135
 
int make_md5 = 0;               /* Make MD5 keyfile? */
136
 
int make_rsa = 0;               /* Make RSA pair? */
137
 
int force = 0;                  /* Force the installation? */
138
 
int here = 0;                   /* Put the files here (curdir)? */
139
 
int nosymlinks = 0;             /* Just create the (timestamped) files? */
140
 
int memorex = 0;                /* Are we live? */
141
 
int trash = 0;                  /* Trash old files? */
142
 
int errflag = 0;
143
 
 
144
 
char *f1_keysdir = NTP_KEYSDIR;
145
 
 
146
 
char *f1_keys;                  /* Visible MD5 key file name */
147
 
char *f2_keys;                  /* timestamped */
148
 
char *f3_keys;                  /* previous filename */
149
 
 
150
 
char *f1_publickey;
151
 
char *f2_publickey;
152
 
char *f3_publickey;
153
 
 
154
 
char *f1_privatekey;
155
 
char *f2_privatekey;
156
 
char *f3_privatekey;
157
 
 
158
 
char *f1_dhparms;
159
 
char *f2_dhparms;
160
 
char *f3_dhparms;
161
 
 
162
 
 
163
 
/* Stubs and hacks so we can link with ntp_config.o */
164
 
u_long  sys_automax;            /* maximum session key lifetime */
165
 
int     sys_bclient;            /* we set our time to broadcasts */
166
 
int     sys_manycastserver;     /* 1 => respond to manycast client pkts */
167
 
u_long  client_limit_period;
168
 
char *  req_file;               /* name of the file with configuration info */
169
 
keyid_t ctl_auth_keyid;         /* keyid used for authenticating write requests */
170
 
struct interface *any_interface;        /* default interface */
171
 
keyid_t info_auth_keyid;        /* keyid used to authenticate requests */
172
 
u_long  current_time;           /* current time (s) */
173
 
const char *Version = "";       /* version declaration */
174
 
keyid_t req_keyid;              /* request keyid */
175
 
u_long  client_limit;
176
 
u_long  client_limit_period;
177
 
l_fp    sys_revoketime;
178
 
u_long  sys_revoke;             /* keys revoke timeout */
179
 
volatile int debug = 0;         /* debugging flag */
180
 
u_char  sys_minpoll;            /* min poll interval (log2 s) */
181
 
 
182
 
void snifflink P((const char *, char **));
183
 
int filep P((const char *));
184
 
FILE *newfile P((const char *, const char *, mode_t, const char *));
185
 
void cleanlinks P((const char *, const char *, const char *));
186
 
 
187
 
struct peer *
188
 
peer_config(
189
 
        struct sockaddr_in *srcadr,
190
 
        struct interface *dstadr,
191
 
        int hmode,
192
 
        int version,
193
 
        int minpoll,
194
 
        int maxpoll,
195
 
        u_int flags,
196
 
        int ttl,
197
 
        keyid_t key,
198
 
        u_char *keystr
199
 
        )
200
 
{
201
 
        if (debug > 1) printf("peer_config...\n");
202
 
        return 0;
203
 
}
204
 
 
205
 
 
206
 
void
207
 
set_sys_var(
208
 
        char *data,
209
 
        u_long size,
210
 
        int def
211
 
        )
212
 
{
213
 
        if (debug > 1) printf("set_sys_var...\n");
214
 
        return;
215
 
}
216
 
 
217
 
 
218
 
void
219
 
ntp_intres (void)
220
 
{
221
 
        if (debug > 1) printf("ntp_intres...\n");
222
 
        return;
223
 
}
224
 
 
225
 
 
226
 
int
227
 
ctlsettrap(
228
 
        struct sockaddr_in *raddr,
229
 
        struct interface *linter,
230
 
        int traptype,
231
 
        int version
232
 
        )
233
 
{
234
 
        if (debug > 1) printf("ctlsettrap...\n");
235
 
        return 0;
236
 
}
237
 
 
238
 
 
239
 
#ifdef PUBKEY
240
 
void
241
 
crypto_config(
242
 
        int item,               /* configuration item */
243
 
        char *cp                /* file name */
244
 
        )
245
 
{
246
 
        switch (item) {
247
 
            case CRYPTO_CONF_DH:
248
 
                if (debug > 0) printf("crypto_config: DH/<%d> <%s>\n", item, cp);
249
 
                f1_dhparms = strdup(cp);
250
 
                break;
251
 
            case CRYPTO_CONF_PRIV:
252
 
                if (debug > 0) printf("crypto_config: PRIVATEKEY/<%d> <%s>\n", item, cp);
253
 
                f1_privatekey = strdup(cp);
254
 
                break;
255
 
            case CRYPTO_CONF_PUBL:
256
 
                if (debug > 0) printf("crypto_config: PUBLICKEY/<%d> <%s>\n", item, cp);
257
 
                f1_publickey = strdup(cp);
258
 
                break;
259
 
            default:
260
 
                if (debug > 1) printf("crypto_config: <%d> <%s>\n", item, cp);
261
 
                break;
262
 
        }
263
 
        return;
264
 
}
265
 
#endif
266
 
 
267
 
 
268
 
struct interface *
269
 
findinterface(
270
 
        struct sockaddr_in *addr
271
 
        )
272
 
{
273
 
        if (debug > 1) printf("findinterface...\n");
274
 
        return 0;
275
 
}
276
 
 
277
 
 
278
 
void
279
 
refclock_control(
280
 
        struct sockaddr_in *srcadr,
281
 
        struct refclockstat *in,
282
 
        struct refclockstat *out
283
 
        )
284
 
{
285
 
        if (debug > 1) printf("refclock_control...\n");
286
 
        return;
287
 
}
288
 
 
289
 
 
290
 
void
291
 
loop_config(
292
 
        int item,
293
 
        double freq
294
 
        )
295
 
{
296
 
        if (debug > 1) printf("loop_config...\n");
297
 
        return;
298
 
}
299
 
 
300
 
 
301
 
void
302
 
filegen_config(
303
 
        FILEGEN *gen,
304
 
        char    *basename,
305
 
        u_int   type,
306
 
        u_int   flag
307
 
        )
308
 
{
309
 
        if (debug > 1) printf("filegen_config...\n");
310
 
        return;
311
 
}
312
 
 
313
 
 
314
 
void
315
 
stats_config(
316
 
        int item,
317
 
        char *invalue   /* only one type so far */
318
 
        )
319
 
{
320
 
        if (debug > 1) printf("stats_config...\n");
321
 
        return;
322
 
}
323
 
 
324
 
 
325
 
void
326
 
hack_restrict(
327
 
        int op,
328
 
        struct sockaddr_in *resaddr,
329
 
        struct sockaddr_in *resmask,
330
 
        int mflags,
331
 
        int flags
332
 
        )
333
 
{
334
 
        if (debug > 1) printf("hack_restrict...\n");
335
 
        return;
336
 
}
337
 
 
338
 
 
339
 
void
340
 
kill_asyncio (void)
341
 
{
342
 
        if (debug > 1) printf("kill_asyncio...\n");
343
 
        return;
344
 
}
345
 
 
346
 
 
347
 
void
348
 
proto_config(
349
 
        int item,
350
 
        u_long value,
351
 
        double dvalue
352
 
        )
353
 
{
354
 
        if (debug > 1) printf("proto_config...\n");
355
 
        return;
356
 
}
357
 
 
358
 
void
359
 
getauthkeys(
360
 
        char *keyfile
361
 
        )
362
 
{
363
 
        if (debug > 0) printf("getauthkeys: got <%s>\n", keyfile);
364
 
        f1_keys = strdup(keyfile);
365
 
        return;
366
 
}
367
 
 
368
 
 
369
 
FILEGEN *
370
 
filegen_get(
371
 
        char *name
372
 
        )
373
 
{
374
 
        if (debug > 1) printf("filegen_get...\n");
375
 
        return 0;
376
 
}
377
 
 
378
 
 
379
 
/* End of stubs and hacks */
380
 
 
381
 
 
382
 
static void
383
 
usage(
384
 
        void
385
 
        )
386
 
{
387
 
        printf("Usage: %s [ -c ntp.conf ] [ -g {d,m,r} ] [ -k key_file ]\n",
388
 
               progname);
389
 
        printf("       [ -d ] [ -f ] [ -h ] [ -l ] [ -n ] [ -t ]\n");
390
 
        printf(" where:\n");
391
 
        printf("  -c /etc/ntp.conf   Location of ntp.conf file\n");
392
 
        printf("  -d     enable debug messages (can be used multiple times)\n");
393
 
        printf("  -f     force installation of generated keys.\n");
394
 
        printf("  -g d   Generate D-H parameter file\n");
395
 
        printf("  -g m   Generate MD5 key file\n");
396
 
        printf("  -g r   Generate RSA keys\n");
397
 
        printf("  -g dmr (Can be combined)\n");
398
 
        printf("  -h     Build keys here (current directory). Implies -l\n");
399
 
        printf("  -k key_file        Location of key file\n");
400
 
        printf("  -l     Don't make the symlinks\n");
401
 
        printf("  -n     Don't actually do anything, just say what would be done\n");
402
 
        printf("  -t     Trash the (old) files at the end of symlink\n");
403
 
 
404
 
        exit(1);
405
 
}
406
 
 
407
 
 
408
 
void
409
 
getCmdOpts (
410
 
        int argc,
411
 
        char *argv[]
412
 
        )
413
 
{
414
 
        int i;
415
 
 
416
 
        while ((i = ntp_getopt(argc, argv, "c:dfg:hlnt")) != EOF)
417
 
                switch (i) {
418
 
                    case 'c':
419
 
                        config_file = ntp_optarg;
420
 
#ifdef HAVE_NETINFO
421
 
                        check_netinfo = 0;
422
 
#endif
423
 
                        break;
424
 
                    case 'd':
425
 
                        ++debug;
426
 
                        break;
427
 
                    case 'f':
428
 
                        ++force;
429
 
                        break;
430
 
                    case 'g':
431
 
                        while (*ntp_optarg) {
432
 
                                switch (*ntp_optarg) {
433
 
                                    case 'd':
434
 
                                        ++make_dh;
435
 
                                        break;
436
 
                                    case 'm':
437
 
                                        ++make_md5;
438
 
                                        break;
439
 
                                    case 'r':
440
 
                                        ++make_rsa;
441
 
                                        break;
442
 
                                    default:
443
 
                                        ++errflag;
444
 
                                        break;
445
 
                                }
446
 
                                ++ntp_optarg;
447
 
                        }
448
 
                        break;
449
 
                    case 'h':
450
 
                        ++here;
451
 
                        ++nosymlinks;
452
 
                        break;
453
 
                    case 'l':
454
 
                        ++nosymlinks;
455
 
                        break;
456
 
                    case 'n':
457
 
                        ++memorex;
458
 
                        break;
459
 
                    case 't':
460
 
                        ++trash;
461
 
                        break;
462
 
                    case '?':
463
 
                        ++errflag;
464
 
                        break;
465
 
                }
466
 
 
467
 
        if (errflag)
468
 
                usage();
469
 
 
470
 
        /* If no file type was specified, make them all. */
471
 
        if (!(make_dh | make_md5 | make_rsa)) {
472
 
                ++make_dh;
473
 
                ++make_md5;
474
 
                ++make_rsa;
475
 
        }
476
 
}
477
 
 
478
 
 
479
 
void
480
 
snifflink(
481
 
        const char *file,
482
 
        char **linkdata
483
 
        )
484
 
{
485
 
#ifdef HAVE_READLINK
486
 
        char buf[PATH_MAX];
487
 
        int rc;
488
 
 
489
 
        if (!file)
490
 
                return;
491
 
 
492
 
        rc = readlink(file, buf, sizeof buf);
493
 
        if (-1 == rc) {
494
 
                switch (errno) {
495
 
                    case EINVAL:        /* Fall thru */
496
 
                    case ENOENT:
497
 
                        return;
498
 
                }
499
 
                fprintf(stderr, "%s: readlink(%s) failed: (%d) %s\n",
500
 
                        progname, file, errno, strerror(errno));
501
 
                exit(1);
502
 
        }
503
 
        buf[rc] = '\0';
504
 
        *linkdata = strdup(buf);
505
 
        /* XXX: make sure linkdata is not 0... */
506
 
#endif /* not HAVE_READLINK */
507
 
        return;
508
 
}
509
 
 
510
 
 
511
 
int
512
 
filep(
513
 
        const char *fn
514
 
        )
515
 
{
516
 
        struct stat sb;
517
 
 
518
 
        if (-1 == stat(fn, &sb)) {
519
 
                if (ENOENT == errno)
520
 
                        return 0;
521
 
                fprintf(stderr, "stat(%s) failed: %s\n",
522
 
                        fn, strerror(errno));
523
 
                exit(1);
524
 
        }
525
 
        return 1;
526
 
}
527
 
 
528
 
 
529
 
FILE *
530
 
newfile(
531
 
        const char *f1,         /* Visible file */
532
 
        const char *f2,         /* New timestamped file name */
533
 
        mode_t fmask,           /* umask for new timestamped file */
534
 
        const char *f3          /* Previous symlink target */
535
 
        )
536
 
{
537
 
        FILE *fp;
538
 
        char fb[PATH_MAX];
539
 
        char *cp;
540
 
 
541
 
        if (debug > 1) printf("newfile(%s,%s,%0o,%s)\n", f1, f2,
542
 
                              (unsigned)fmask, f3 ? f3 : "NULL");
543
 
        /*
544
 
           If:
545
 
           - no symlink support, or
546
 
           - there is no old symlink (!f3)
547
 
           - - file = dirname(f1) / f2
548
 
           Otherwise:
549
 
           - If ('/' == *f3)
550
 
           - - file = dirname(f3) / f2
551
 
           - else
552
 
           - - file = dirname(f1) / dirname(f3) / f2
553
 
           fopen(file)
554
 
           print any error message/bail
555
 
           return FILE
556
 
        */
557
 
 
558
 
        if (here)
559
 
                snprintf(fb, sizeof fb, "%s", f2);
560
 
        else {
561
 
                if (
562
 
#ifdef HAVE_READLINK
563
 
                    !f3
564
 
#else
565
 
                    1
566
 
#endif
567
 
                   ) {
568
 
                        /* file = dirname(f1) / f2 */
569
 
                        snprintf(fb, sizeof fb, "%s", f1);
570
 
                        cp = strrchr(fb, '/');
571
 
                        if (cp) {
572
 
                                *cp = 0;
573
 
                        }
574
 
                        snprintf(fb, sizeof fb, "%s/%s", fb, f2);
575
 
                        if (debug > 1) printf("case 1: file is <%s>\n", fb);
576
 
                } else {
577
 
                        /*
578
 
                          - If ('/' == *f3)
579
 
                          - - file = dirname(f3) / f2
580
 
                          - else
581
 
                          - - file = dirname(f1) / dirname(f3) / f2
582
 
                        */
583
 
                        if ('/' != *f3) {
584
 
                                snprintf(fb, sizeof fb, "%s", f1);
585
 
                                cp = strrchr(fb, '/');
586
 
                                if (cp) {
587
 
                                        ++cp;
588
 
                                        *cp = 0;
589
 
                                }
590
 
                                if (debug > 1)
591
 
                                        printf("case 2: file is <%s>\n", fb);
592
 
                        } else {
593
 
                                *fb = 0;
594
 
                        }
595
 
                        snprintf(fb, sizeof fb, "%s%s", fb, f3);
596
 
                        cp = strrchr(fb, '/');
597
 
                        if (cp) {
598
 
                                *cp = 0;
599
 
                        }
600
 
                        snprintf(fb, sizeof fb, "%s/%s", fb, f2);
601
 
                        if (debug > 1) printf("case 3: file is <%s>\n", fb);
602
 
                }
603
 
        }
604
 
 
605
 
        /*
606
 
          fopen(file)
607
 
          print any error message/bail
608
 
          return FILE
609
 
        */
610
 
        if (memorex) {
611
 
                printf("Would write file <%s>\n", fb);
612
 
                fp = NULL;
613
 
        } else {
614
 
                mode_t omask;
615
 
 
616
 
                omask = umask(fmask);
617
 
                fp = fopen(fb, "w");
618
 
                (void) umask(omask);
619
 
                if (fp == NULL) {
620
 
                        perror(fb);
621
 
                        exit(1);
622
 
                }
623
 
        }
624
 
        return fp;
625
 
}
626
 
 
627
 
void
628
 
cleanlinks(
629
 
        const char *f1,         /* Visible file */
630
 
        const char *f2,         /* New timestamped file name */
631
 
        const char *f3          /* Previous symlink target */
632
 
        )
633
 
{
634
 
#ifdef HAVE_READLINK
635
 
        char *cp;
636
 
        char fb[PATH_MAX];
637
 
 
638
 
        /*
639
 
          Just return if nosymlinks.
640
 
          unlink f1
641
 
          file = dirname(f3) / f2
642
 
          symlink file, f1
643
 
          If trash:
644
 
          - if f3 begins with a /, unlink it
645
 
          - else, unlink dirname(f1) / f3
646
 
        */
647
 
#endif /* HAVE_READLINK */
648
 
 
649
 
        if (nosymlinks)
650
 
                return;
651
 
 
652
 
        if (memorex)
653
 
                printf("Would unlink(%s)\n", f1);
654
 
        else if (unlink(f1)) {
655
 
                if (errno != ENOENT) {
656
 
                        fprintf(stderr, "unlink(%s) failed: %s\n", f1,
657
 
                                strerror(errno));
658
 
                        return;
659
 
                }
660
 
        }
661
 
        /* file = dirname(f3) / f2 */
662
 
        if (f3) {
663
 
                snprintf(fb, sizeof fb, "%s", f3);
664
 
                cp = strrchr(fb, '/');
665
 
                if (cp) {
666
 
                        ++cp;
667
 
                        *cp = 0;
668
 
                } else {
669
 
                        *fb = 0;
670
 
                }
671
 
        } else {
672
 
                *fb = 0;
673
 
        }
674
 
        snprintf(fb, sizeof fb, "%s%s", fb, f2);
675
 
        if (debug > 1) printf("cleanlinks 1: file is <%s>\n", fb);
676
 
 
677
 
        if (memorex)
678
 
                printf("Would symlink <%s> -> <%s>\n", f1, fb);
679
 
        else if (symlink(fb, f1)) {
680
 
                fprintf(stderr, "symlink(%s,%s) failed: %s\n", fb, f1,
681
 
                        strerror(errno));
682
 
                return;
683
 
        }
684
 
 
685
 
        /*
686
 
          If trash:
687
 
          - if f3 begins with a /, unlink it
688
 
          - else, unlink dirname(f1) / f3
689
 
        */
690
 
        if (trash && f3) {
691
 
                if ('/' == *f3) {
692
 
                        if (memorex)
693
 
                                printf("Would unlink(%s)\n", f3);
694
 
                        else if (unlink(f3)) {
695
 
                                if (errno != ENOENT) {
696
 
                                        fprintf(stderr, "unlink(%s) failed: %s\n", f3,
697
 
                                                strerror(errno));
698
 
                                        return;
699
 
                                }
700
 
                        }
701
 
                } else {
702
 
                        snprintf(fb, sizeof fb, "%s", f1);
703
 
                        cp = strrchr(fb, '/');
704
 
                        if (cp) {
705
 
                                *cp = 0;
706
 
                        }
707
 
                        snprintf(fb, sizeof fb, "%s/%s", fb, f3);
708
 
                        if (debug > 1)
709
 
                                printf("cleanlinks 2: file is <%s>\n", fb);
710
 
                        if (memorex)
711
 
                                printf("Would unlink(%s)\n", fb);
712
 
                        else if (unlink(fb)) {
713
 
                                if (errno != ENOENT) {
714
 
                                        fprintf(stderr, "unlink(%s) failed: %s\n", fb,
715
 
                                                strerror(errno));
716
 
                                        return;
717
 
                                }
718
 
                        }
719
 
                }
720
 
        }
721
 
 
722
 
        return;
723
 
}
724
 
 
725
 
 
726
 
int
727
 
main(
728
 
        int argc,
729
 
        char *argv[]
730
 
        )
731
 
{
732
 
#ifdef PUBKEY
733
 
        R_RSA_PRIVATE_KEY rsaref_private; /* RSA private key */
734
 
        R_RSA_PUBLIC_KEY rsaref_public; /* RSA public key */
735
 
        R_RSA_PROTO_KEY protokey;       /* RSA prototype key */
736
 
        R_DH_PARAMS dh_params;          /* Diffie-Hellman parameters */
737
 
        R_RANDOM_STRUCT randomstr;      /* random structure */
738
 
        int rval;                       /* return value */
739
 
        u_char encoded_key[MAXKEYLEN];  /* encoded PEM string buffer */
740
 
        u_int modulus;                  /* modulus length */
741
 
        u_int len;
742
 
#endif /* PUBKEY */
743
 
        struct timeval tv;              /* initialization vector */
744
 
        u_long ntptime;                 /* NTP timestamp */
745
 
        char hostname[256];             /* DNS host name */
746
 
        u_char md5key[17];              /* generated MD5 key */ 
747
 
        FILE *str;                      /* file handle */
748
 
        u_int temp;
749
 
        int i, j;
750
 
        mode_t std_mask;        /* Standard mask */
751
 
        mode_t sec_mask = 077;  /* Secure mask */
752
 
        char pathbuf[PATH_MAX];
753
 
 
754
 
        gethostname(hostname, sizeof(hostname));
755
 
        gettimeofday(&tv, 0);
756
 
        ntptime = tv.tv_sec + JAN_1970;
757
 
 
758
 
        /* Initialize config_file */
759
 
        getconfig(argc, argv);  /* ntpd/ntp_config.c */
760
 
 
761
 
        if (!f1_keysdir) {
762
 
                /* Shouldn't happen... */
763
 
                f1_keysdir = "PATH_KEYSDIR";
764
 
        }
765
 
        if (*f1_keysdir != '/') {
766
 
                fprintf(stderr,
767
 
                        "%s: keysdir path <%s> doesn't begin with a /\n",
768
 
                        progname, f1_keysdir);
769
 
                exit(1);
770
 
        }
771
 
 
772
 
        if (!f2_keys) {
773
 
                snprintf(pathbuf, sizeof pathbuf, "ntp.keys.%lu",
774
 
                         ntptime);
775
 
                f2_keys = strdup(pathbuf);
776
 
        }
777
 
        if (!f1_keys) {
778
 
                snprintf(pathbuf, sizeof pathbuf, "%s/ntp.keys",
779
 
                         f1_keysdir);
780
 
                f1_keys = strdup(pathbuf);
781
 
        }
782
 
        if (*f1_keys != '/') {
783
 
                fprintf(stderr,
784
 
                        "%s: keys path <%s> doesn't begin with a /\n",
785
 
                        progname, f1_keys);
786
 
                exit(1);
787
 
        }
788
 
        snifflink(f1_keys, &f3_keys);
789
 
 
790
 
        if (!f2_publickey) {
791
 
                snprintf(pathbuf, sizeof pathbuf, "ntpkey_%s.%lu",
792
 
                         hostname, ntptime);
793
 
                f2_publickey = strdup(pathbuf);
794
 
        }
795
 
        if (!f1_publickey) {
796
 
                snprintf(pathbuf, sizeof pathbuf, "%s/ntpkey_%s",
797
 
                         f1_keysdir, hostname);
798
 
                f1_publickey = strdup(pathbuf);
799
 
        }
800
 
        if (*f1_publickey != '/') {
801
 
                fprintf(stderr,
802
 
                        "%s: publickey path <%s> doesn't begin with a /\n",
803
 
                        progname, f1_publickey);
804
 
                exit(1);
805
 
        }
806
 
        snifflink(f1_publickey, &f3_publickey);
807
 
 
808
 
        if (!f2_privatekey) {
809
 
                snprintf(pathbuf, sizeof pathbuf, "ntpkey.%lu",
810
 
                         ntptime);
811
 
                f2_privatekey = strdup(pathbuf);
812
 
        }
813
 
        if (!f1_privatekey) {
814
 
                snprintf(pathbuf, sizeof pathbuf, "%s/ntpkey",
815
 
                         f1_keysdir);
816
 
                f1_privatekey = strdup(pathbuf);
817
 
        }
818
 
        if (*f1_privatekey != '/') {
819
 
                fprintf(stderr,
820
 
                        "%s: privatekey path <%s> doesn't begin with a /\n",
821
 
                        progname, f1_privatekey);
822
 
                exit(1);
823
 
        }
824
 
        snifflink(f1_privatekey, &f3_privatekey);
825
 
 
826
 
        if (!f2_dhparms) {
827
 
                snprintf(pathbuf, sizeof pathbuf, "ntpkey_dh.%lu",
828
 
                         ntptime);
829
 
                f2_dhparms = strdup(pathbuf);
830
 
        }
831
 
        if (!f1_dhparms) {
832
 
                snprintf(pathbuf, sizeof pathbuf, "%s/ntpkey_dh",
833
 
                         f1_keysdir);
834
 
                f1_dhparms = strdup(pathbuf);
835
 
        }
836
 
        if (*f1_dhparms != '/') {
837
 
                fprintf(stderr,
838
 
                        "%s: dhparms path <%s> doesn't begin with a /\n",
839
 
                        progname, f1_dhparms);
840
 
                exit(1);
841
 
        }
842
 
        snifflink(f1_dhparms, &f3_dhparms);
843
 
 
844
 
        if (debug > 1) {
845
 
                printf("After config:\n");
846
 
                printf("keysdir    = <%s>\n", f1_keysdir? f1_keysdir: "");
847
 
                printf("keys       = <%s> -> <%s>\n"
848
 
                       , f1_keys? f1_keys: ""
849
 
                       , f2_keys? f2_keys: ""
850
 
                      );
851
 
                printf("       old = <%s>\n", f3_keys? f3_keys: "");
852
 
                printf("publickey  = <%s> -> <%s>\n"
853
 
                       , f1_publickey? f1_publickey: ""
854
 
                       , f2_publickey? f2_publickey: ""
855
 
                      );
856
 
                printf("       old = <%s>\n", f3_publickey? f3_publickey: "");
857
 
                printf("privatekey = <%s> -> <%s>\n"
858
 
                       , f1_privatekey? f1_privatekey: ""
859
 
                       , f2_privatekey? f2_privatekey: ""
860
 
                      );
861
 
                printf("       old = <%s>\n", f3_privatekey? f3_privatekey: "");
862
 
                printf("dhparms    = <%s> -> <%s>\n"
863
 
                       , f1_dhparms? f1_dhparms: ""
864
 
                       , f2_dhparms? f2_dhparms: ""
865
 
                      );
866
 
                printf("       old = <%s>\n", f3_dhparms? f3_dhparms: "");
867
 
        }
868
 
 
869
 
        /*
870
 
          for each file we're going to install:
871
 
          - make the new timestamped file
872
 
          - if (!nosymlinks)
873
 
          - - remove any old link
874
 
          - - make the link
875
 
          - - if (trash)
876
 
          - - - remove the old file
877
 
        */
878
 
 
879
 
        std_mask = umask(sec_mask); /* Get the standard mask */
880
 
        (void) umask(std_mask);
881
 
 
882
 
        if (make_md5 && (force || !filep(f1_keys))) {
883
 
                /*
884
 
                 * Generate 16 random MD5 keys.
885
 
                 */
886
 
                printf("Generating MD5 key file...\n");
887
 
                str = newfile(f1_keys, f2_keys, sec_mask, f3_keys);
888
 
                if (!memorex) {
889
 
                        srandom((u_int)tv.tv_usec);
890
 
                        fprintf(str, "# MD5 key file %s\n# %s", f2_keys,
891
 
                                ctime((const time_t *) &tv.tv_sec));
892
 
                        for (i = 1; i <= 16; i++) {
893
 
                                for (j = 0; j < 16; j++) {
894
 
                                        while (1) {
895
 
                                                temp = random() & 0xff;
896
 
                                                /*
897
 
                                                ** Harlan says Karnaugh maps
898
 
                                                ** are not his friend, and
899
 
                                                ** compilers can optimize
900
 
                                                ** this most easily.
901
 
                                                */
902
 
                                                if (temp == '#')
903
 
                                                        continue;
904
 
                                                if (temp > 0x20 && temp < 0x7f)
905
 
                                                        break;
906
 
                                        }
907
 
                                        md5key[j] = (u_char)temp;
908
 
                                }
909
 
                                md5key[16] = 0;
910
 
                                fprintf(str, "%2d M %16s        # MD5 key\n",
911
 
                                        i, md5key);
912
 
                        }
913
 
                }
914
 
                if (str) fclose(str);
915
 
                cleanlinks(f1_keys, f2_keys, f3_keys);
916
 
        }
917
 
 
918
 
#ifdef PUBKEY
919
 
        if (make_rsa && (force || !filep(f1_publickey)
920
 
                         || !filep(f1_privatekey))) {
921
 
                /*
922
 
                 * Roll the RSA public/private key pair.
923
 
                 */
924
 
                printf("Generating RSA public/private key pair (%d bits)...\n",
925
 
                       MODULUSLEN);
926
 
                if (!memorex) {
927
 
                        protokey.bits = MODULUSLEN;
928
 
                        protokey.useFermat4 = 1;
929
 
                        R_RandomInit(&randomstr);
930
 
                        R_GetRandomBytesNeeded(&len, &randomstr);
931
 
                        for (i = 0; i < len; i++) {
932
 
                                temp = random();
933
 
                                R_RandomUpdate(&randomstr, (u_char *)&temp, 1);
934
 
                        }
935
 
                        rval = R_GeneratePEMKeys(&rsaref_public,
936
 
                                                 &rsaref_private, &protokey,
937
 
                                                 &randomstr);
938
 
                        if (rval) {
939
 
                                printf("R_GeneratePEMKeys error %x\n", rval);
940
 
                                return (-1);
941
 
                        }
942
 
                }
943
 
 
944
 
                /*
945
 
                 * Generate the file "ntpkey.*" containing the RSA
946
 
                 * private key in printable ASCII format.
947
 
                 */
948
 
                str = newfile(f1_privatekey, f2_privatekey, sec_mask,
949
 
                              f3_privatekey);
950
 
                if (!memorex) {
951
 
                        len = sizeof(rsaref_private)
952
 
                            - sizeof(rsaref_private.bits);
953
 
                        modulus = (u_int32)rsaref_private.bits;
954
 
                        fprintf(str, "# RSA private key file %s\n# %s",
955
 
                                f2_privatekey,  ctime(&tv.tv_sec));
956
 
                        R_EncodePEMBlock(encoded_key, &temp,
957
 
                                         (u_char *)rsaref_private.modulus,
958
 
                                         len);
959
 
                        encoded_key[temp] = '\0';
960
 
                        fprintf(str, "%d %s\n", modulus, encoded_key);
961
 
                }
962
 
                if (str) fclose(str);
963
 
                cleanlinks(f1_privatekey, f2_privatekey, f3_privatekey);
964
 
 
965
 
                /*
966
 
                 * Generate the file "ntpkey_host.*" containing the RSA
967
 
                 * public key in printable ASCII format.
968
 
                 */
969
 
                str = newfile(f1_publickey, f2_publickey, std_mask,
970
 
                              f3_publickey);
971
 
                if (!memorex) {
972
 
                        len = sizeof(rsaref_public)
973
 
                            - sizeof(rsaref_public.bits);
974
 
                        modulus = (u_int32)rsaref_public.bits;
975
 
                        fprintf(str, "# RSA public key file %s\n# %s",
976
 
                                f2_publickey, ctime(&tv.tv_sec));
977
 
                        R_EncodePEMBlock(encoded_key, &temp,
978
 
                                         (u_char *)rsaref_public.modulus, len);
979
 
                        encoded_key[temp] = '\0';
980
 
                        fprintf(str, "%d %s\n", modulus, encoded_key);
981
 
                }
982
 
                if (str) fclose(str);
983
 
                cleanlinks(f1_publickey, f2_publickey, f3_publickey);
984
 
        }
985
 
#endif /* PUBKEY */
986
 
 
987
 
#ifdef PUBKEY
988
 
        if (make_dh && (force || !filep(f1_dhparms))) {
989
 
                /*
990
 
                 * Roll the prime and generator for the Diffie-Hellman key
991
 
                 * agreement algorithm.
992
 
                 */
993
 
                printf("Generating Diffie-Hellman parameters (%d bits)...\n",
994
 
                       PRIMELEN);
995
 
                str = newfile(f1_dhparms, f2_dhparms, std_mask, f3_dhparms);
996
 
 
997
 
                if (!memorex) {
998
 
                        R_RandomInit(&randomstr);
999
 
                        R_GetRandomBytesNeeded(&len, &randomstr);
1000
 
                        for (i = 0; i < len; i++) {
1001
 
                                temp = random();
1002
 
                                R_RandomUpdate(&randomstr, (u_char *)&temp, 1);
1003
 
                        }
1004
 
 
1005
 
                        /*
1006
 
                         * Generate the file "ntpkey_dh.*" containing the
1007
 
                         * Diffie-Hellman prime and generator in printable
1008
 
                         * ASCII format.
1009
 
                         */
1010
 
                        len = DH_PRIME_LEN(PRIMELEN);
1011
 
                        dh_params.prime = (u_char *)malloc(len);
1012
 
                        dh_params.generator = (u_char *)malloc(len);
1013
 
                        rval = R_GenerateDHParams(&dh_params, PRIMELEN,
1014
 
                                                  PRIMELEN / 2, &randomstr);
1015
 
                        if (rval) {
1016
 
                                printf("R_GenerateDHParams error %x\n", rval);
1017
 
                                return (-1);
1018
 
                        }
1019
 
 
1020
 
                        fprintf(str,
1021
 
                                "# Diffie-Hellman parameter file %s\n# %s",
1022
 
                                f2_dhparms, ctime(&tv.tv_sec));
1023
 
                        R_EncodePEMBlock(encoded_key, &temp,
1024
 
                                         (u_char *)dh_params.prime,
1025
 
                                         dh_params.primeLen);
1026
 
                        encoded_key[temp] = '\0';
1027
 
                        fprintf(str, "%d %s\n", dh_params.primeLen,
1028
 
                                encoded_key);
1029
 
                        R_EncodePEMBlock(encoded_key, &temp,
1030
 
                                         (u_char *)dh_params.generator,
1031
 
                                         dh_params.generatorLen);
1032
 
                        encoded_key[temp] = '\0';
1033
 
                        fprintf(str, "%d %s\n", dh_params.generatorLen,
1034
 
                                encoded_key);
1035
 
                }
1036
 
                if (str) fclose(str);
1037
 
                cleanlinks(f1_dhparms, f2_dhparms, f3_dhparms);
1038
 
        }
1039
 
#endif /* PUBKEY */
1040
 
 
1041
 
        return (0);
1042
 
}