diff options
Diffstat (limited to 'contrib/ntp/util/ntp-genkeys.c')
-rw-r--r-- | contrib/ntp/util/ntp-genkeys.c | 1042 |
1 files changed, 1042 insertions, 0 deletions
diff --git a/contrib/ntp/util/ntp-genkeys.c b/contrib/ntp/util/ntp-genkeys.c new file mode 100644 index 0000000..fd85121 --- /dev/null +++ b/contrib/ntp/util/ntp-genkeys.c @@ -0,0 +1,1042 @@ +/* + * Program to generate MD5 and RSA keys for NTP clients and servers + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef HAVE_NETINFO +#include <netinfo/ni.h> +#endif + +#include "ntpd.h" +#include "ntp_stdlib.h" +#include "ntp_string.h" +#include "ntp_filegen.h" +#include "ntp_unixtime.h" +#include "ntp_config.h" +#include "ntp_cmdargs.h" + +#include <stdio.h> +#include <unistd.h> +#include <limits.h> /* PATH_MAX */ +#include <sys/stat.h> + +#ifdef PUBKEY +# include "ntp_crypto.h" +#endif + +#ifndef PATH_MAX +# ifdef _POSIX_PATH_MAX +# define PATH_MAX _POSIX_PATH_MAX +# else +# define PATH_MAX 255 +# endif +#endif + +/* + * Cryptodefines + */ +#define MAXKEYLEN 1024 /* maximum encoded key length */ +#define MODULUSLEN 512 /* length of RSA modulus */ +#define PRIMELEN 512 /* length of D_H prime, generator */ + +/* + * This program generates (up to) four files: + * + * ntp.keys containing the DES/MD5 private keys, + * ntpkey containing the RSA private key, + * ntpkey_HOST containing the RSA public key + * where HOST is the DNS name of the generating machine, + * ntpkey_dh containing the parameters for the Diffie-Hellman + * key-agreement algorithm. + * + * The files contain cryptographic values generated by the algorithms of + * the rsaref20 package and are in printable ASCII format. Since the + * algorythms are seeded by the system clock, each run of this program + * will produce a different outcome. There are no options or frills of + * any sort, although a number of options would seem to be appropriate. + * Waving this program in the breeze will no doubt bring a cast of + * thousands to wiggle the options this way and that for various useful + * purposes. + * + * The names of all files begin with "ntp" and end with an extension + * consisting of the seconds value of the current NTP timestamp, which + * appears in the form ".*". This provides a way to distinguish between + * key generations, since the host name and timestamp can be fetched by + * a client during operation. + * + * The ntp.keys.* file contains 16 MD5 keys. Each key consists of 16 + * characters randomized over the ASCII 95-character printing subset. + * The file is read by the daemon at the location specified by the keys + * configuration file command and made visible only to root. An + * additional key consisting of a easily remembered password should be + * added by hand for use with the ntpdc program. The file must be + * distributed by secure means to other servers and clients sharing the + * same security compartment. + * + * The key identifiers for MD5 and DES keys must be less than 65536, + * although this program uses only the identifiers from 1 to 16. The key + * identifier for each association is specified as the key argument in + * the server or peer configuration file command. + * + * The ntpkey.* file contains the RSA private key. It is read by the + * daemon at the location specified by the private argument of the + * crypto configuration file command and made visible only to root. + * This file is useful only to the machine that generated it and never + * shared with any other daemon or application program. + * + * The ntpkey_host.* file contains the RSA public key, where host is the + * DNS name of the host that generated it. The file is read by the + * daemon at the location specified by the public argument to the server + * or peer configuration file command. This file can be widely + * distributed and stored without using secure means, since the data are + * public values. + * + * The ntp_dh.* file contains two Diffie-Hellman parameters, the prime + * modulus and the generator. The file is read by the daemon at the + * location specified by the dhparams argument of the crypto + * configuration file command. This file can be widely distributed and + * stored without using secure means, since the data are public values. + * + * The file formats all begin with two lines. The first line contains + * the file name and decimal timestamp, while the second contains the + * readable datestamp. Lines beginning with # are considered comments + * and ignored by the daemon. In the ntp.keys.* file, the next 16 lines + * contain the MD5 keys in order. In the ntpkey.* and ntpkey_host.* + * files, the next line contains the modulus length in bits followed by + * the key as a PEM encoded string. In the ntpkey_dh.* file, the next + * line contains the prime length in bytes followed by the prime as a + * PEM encoded string, and the next and final line contains the + * generator length in bytes followed by the generator as a PEM encoded + * string. + * + * Note: See the file ./source/rsaref.h in the rsaref20 package for + * explanation of return values, if necessary. + */ + + +extern char *config_file; + +#ifdef HAVE_NETINFO +extern struct netinfo_config_state *config_netinfo; +extern int check_netinfo; +#endif /* HAVE_NETINFO */ + +#ifdef SYS_WINNT +char *alt_config_file; +LPTSTR temp; +char config_file_storage[PATH_MAX]; +char alt_config_file_storage[PATH_MAX]; +#endif /* SYS_WINNT */ + +int make_dh = 0; /* Make D-H parameter file? */ +int make_md5 = 0; /* Make MD5 keyfile? */ +int make_rsa = 0; /* Make RSA pair? */ +int force = 0; /* Force the installation? */ +int here = 0; /* Put the files here (curdir)? */ +int nosymlinks = 0; /* Just create the (timestamped) files? */ +int memorex = 0; /* Are we live? */ +int trash = 0; /* Trash old files? */ +int errflag = 0; + +char *f1_keysdir = NTP_KEYSDIR; + +char *f1_keys; /* Visible MD5 key file name */ +char *f2_keys; /* timestamped */ +char *f3_keys; /* previous filename */ + +char *f1_publickey; +char *f2_publickey; +char *f3_publickey; + +char *f1_privatekey; +char *f2_privatekey; +char *f3_privatekey; + +char *f1_dhparms; +char *f2_dhparms; +char *f3_dhparms; + + +/* Stubs and hacks so we can link with ntp_config.o */ +u_long sys_automax; /* maximum session key lifetime */ +int sys_bclient; /* we set our time to broadcasts */ +int sys_manycastserver; /* 1 => respond to manycast client pkts */ +u_long client_limit_period; +char * req_file; /* name of the file with configuration info */ +keyid_t ctl_auth_keyid; /* keyid used for authenticating write requests */ +struct interface *any_interface; /* default interface */ +keyid_t info_auth_keyid; /* keyid used to authenticate requests */ +u_long current_time; /* current time (s) */ +const char *Version = ""; /* version declaration */ +keyid_t req_keyid; /* request keyid */ +u_long client_limit; +u_long client_limit_period; +l_fp sys_revoketime; +u_long sys_revoke; /* keys revoke timeout */ +volatile int debug = 0; /* debugging flag */ +u_char sys_minpoll; /* min poll interval (log2 s) */ + +void snifflink P((const char *, char **)); +int filep P((const char *)); +FILE *newfile P((const char *, const char *, mode_t, const char *)); +void cleanlinks P((const char *, const char *, const char *)); + +struct peer * +peer_config( + struct sockaddr_in *srcadr, + struct interface *dstadr, + int hmode, + int version, + int minpoll, + int maxpoll, + u_int flags, + int ttl, + keyid_t key, + u_char *keystr + ) +{ + if (debug > 1) printf("peer_config...\n"); + return 0; +} + + +void +set_sys_var( + char *data, + u_long size, + int def + ) +{ + if (debug > 1) printf("set_sys_var...\n"); + return; +} + + +void +ntp_intres (void) +{ + if (debug > 1) printf("ntp_intres...\n"); + return; +} + + +int +ctlsettrap( + struct sockaddr_in *raddr, + struct interface *linter, + int traptype, + int version + ) +{ + if (debug > 1) printf("ctlsettrap...\n"); + return 0; +} + + +#ifdef PUBKEY +void +crypto_config( + int item, /* configuration item */ + char *cp /* file name */ + ) +{ + switch (item) { + case CRYPTO_CONF_DH: + if (debug > 0) printf("crypto_config: DH/<%d> <%s>\n", item, cp); + f1_dhparms = strdup(cp); + break; + case CRYPTO_CONF_PRIV: + if (debug > 0) printf("crypto_config: PRIVATEKEY/<%d> <%s>\n", item, cp); + f1_privatekey = strdup(cp); + break; + case CRYPTO_CONF_PUBL: + if (debug > 0) printf("crypto_config: PUBLICKEY/<%d> <%s>\n", item, cp); + f1_publickey = strdup(cp); + break; + default: + if (debug > 1) printf("crypto_config: <%d> <%s>\n", item, cp); + break; + } + return; +} +#endif + + +struct interface * +findinterface( + struct sockaddr_in *addr + ) +{ + if (debug > 1) printf("findinterface...\n"); + return 0; +} + + +void +refclock_control( + struct sockaddr_in *srcadr, + struct refclockstat *in, + struct refclockstat *out + ) +{ + if (debug > 1) printf("refclock_control...\n"); + return; +} + + +void +loop_config( + int item, + double freq + ) +{ + if (debug > 1) printf("loop_config...\n"); + return; +} + + +void +filegen_config( + FILEGEN *gen, + char *basename, + u_int type, + u_int flag + ) +{ + if (debug > 1) printf("filegen_config...\n"); + return; +} + + +void +stats_config( + int item, + char *invalue /* only one type so far */ + ) +{ + if (debug > 1) printf("stats_config...\n"); + return; +} + + +void +hack_restrict( + int op, + struct sockaddr_in *resaddr, + struct sockaddr_in *resmask, + int mflags, + int flags + ) +{ + if (debug > 1) printf("hack_restrict...\n"); + return; +} + + +void +kill_asyncio (void) +{ + if (debug > 1) printf("kill_asyncio...\n"); + return; +} + + +void +proto_config( + int item, + u_long value, + double dvalue + ) +{ + if (debug > 1) printf("proto_config...\n"); + return; +} + +void +getauthkeys( + char *keyfile + ) +{ + if (debug > 0) printf("getauthkeys: got <%s>\n", keyfile); + f1_keys = strdup(keyfile); + return; +} + + +FILEGEN * +filegen_get( + char *name + ) +{ + if (debug > 1) printf("filegen_get...\n"); + return 0; +} + + +/* End of stubs and hacks */ + + +static void +usage( + void + ) +{ + printf("Usage: %s [ -c ntp.conf ] [ -g {d,m,r} ] [ -k key_file ]\n", + progname); + printf(" [ -d ] [ -f ] [ -h ] [ -l ] [ -n ] [ -t ]\n"); + printf(" where:\n"); + printf(" -c /etc/ntp.conf Location of ntp.conf file\n"); + printf(" -d enable debug messages (can be used multiple times)\n"); + printf(" -f force installation of generated keys.\n"); + printf(" -g d Generate D-H parameter file\n"); + printf(" -g m Generate MD5 key file\n"); + printf(" -g r Generate RSA keys\n"); + printf(" -g dmr (Can be combined)\n"); + printf(" -h Build keys here (current directory). Implies -l\n"); + printf(" -k key_file Location of key file\n"); + printf(" -l Don't make the symlinks\n"); + printf(" -n Don't actually do anything, just say what would be done\n"); + printf(" -t Trash the (old) files at the end of symlink\n"); + + exit(1); +} + + +void +getCmdOpts ( + int argc, + char *argv[] + ) +{ + int i; + + while ((i = ntp_getopt(argc, argv, "c:dfg:hlnt")) != EOF) + switch (i) { + case 'c': + config_file = ntp_optarg; +#ifdef HAVE_NETINFO + check_netinfo = 0; +#endif + break; + case 'd': + ++debug; + break; + case 'f': + ++force; + break; + case 'g': + while (*ntp_optarg) { + switch (*ntp_optarg) { + case 'd': + ++make_dh; + break; + case 'm': + ++make_md5; + break; + case 'r': + ++make_rsa; + break; + default: + ++errflag; + break; + } + ++ntp_optarg; + } + break; + case 'h': + ++here; + ++nosymlinks; + break; + case 'l': + ++nosymlinks; + break; + case 'n': + ++memorex; + break; + case 't': + ++trash; + break; + case '?': + ++errflag; + break; + } + + if (errflag) + usage(); + + /* If no file type was specified, make them all. */ + if (!(make_dh | make_md5 | make_rsa)) { + ++make_dh; + ++make_md5; + ++make_rsa; + } +} + + +void +snifflink( + const char *file, + char **linkdata + ) +{ +#ifdef HAVE_READLINK + char buf[PATH_MAX]; + int rc; + + if (!file) + return; + + rc = readlink(file, buf, sizeof buf); + if (-1 == rc) { + switch (errno) { + case EINVAL: /* Fall thru */ + case ENOENT: + return; + } + fprintf(stderr, "%s: readlink(%s) failed: (%d) %s\n", + progname, file, errno, strerror(errno)); + exit(1); + } + buf[rc] = '\0'; + *linkdata = strdup(buf); + /* XXX: make sure linkdata is not 0... */ +#endif /* not HAVE_READLINK */ + return; +} + + +int +filep( + const char *fn + ) +{ + struct stat sb; + + if (-1 == stat(fn, &sb)) { + if (ENOENT == errno) + return 0; + fprintf(stderr, "stat(%s) failed: %s\n", + fn, strerror(errno)); + exit(1); + } + return 1; +} + + +FILE * +newfile( + const char *f1, /* Visible file */ + const char *f2, /* New timestamped file name */ + mode_t fmask, /* umask for new timestamped file */ + const char *f3 /* Previous symlink target */ + ) +{ + FILE *fp; + char fb[PATH_MAX]; + char *cp; + + if (debug > 1) printf("newfile(%s,%s,%0o,%s)\n", f1, f2, + (unsigned)fmask, f3 ? f3 : "NULL"); + /* + If: + - no symlink support, or + - there is no old symlink (!f3) + - - file = dirname(f1) / f2 + Otherwise: + - If ('/' == *f3) + - - file = dirname(f3) / f2 + - else + - - file = dirname(f1) / dirname(f3) / f2 + fopen(file) + print any error message/bail + return FILE + */ + + if (here) + snprintf(fb, sizeof fb, "%s", f2); + else { + if ( +#ifdef HAVE_READLINK + !f3 +#else + 1 +#endif + ) { + /* file = dirname(f1) / f2 */ + snprintf(fb, sizeof fb, "%s", f1); + cp = strrchr(fb, '/'); + if (cp) { + *cp = 0; + } + snprintf(fb, sizeof fb, "%s/%s", fb, f2); + if (debug > 1) printf("case 1: file is <%s>\n", fb); + } else { + /* + - If ('/' == *f3) + - - file = dirname(f3) / f2 + - else + - - file = dirname(f1) / dirname(f3) / f2 + */ + if ('/' != *f3) { + snprintf(fb, sizeof fb, "%s", f1); + cp = strrchr(fb, '/'); + if (cp) { + ++cp; + *cp = 0; + } + if (debug > 1) + printf("case 2: file is <%s>\n", fb); + } else { + *fb = 0; + } + snprintf(fb, sizeof fb, "%s%s", fb, f3); + cp = strrchr(fb, '/'); + if (cp) { + *cp = 0; + } + snprintf(fb, sizeof fb, "%s/%s", fb, f2); + if (debug > 1) printf("case 3: file is <%s>\n", fb); + } + } + + /* + fopen(file) + print any error message/bail + return FILE + */ + if (memorex) { + printf("Would write file <%s>\n", fb); + fp = NULL; + } else { + mode_t omask; + + omask = umask(fmask); + fp = fopen(fb, "w"); + (void) umask(omask); + if (fp == NULL) { + perror(fb); + exit(1); + } + } + return fp; +} + +void +cleanlinks( + const char *f1, /* Visible file */ + const char *f2, /* New timestamped file name */ + const char *f3 /* Previous symlink target */ + ) +{ +#ifdef HAVE_READLINK + char *cp; + char fb[PATH_MAX]; + + /* + Just return if nosymlinks. + unlink f1 + file = dirname(f3) / f2 + symlink file, f1 + If trash: + - if f3 begins with a /, unlink it + - else, unlink dirname(f1) / f3 + */ +#endif /* HAVE_READLINK */ + + if (nosymlinks) + return; + + if (memorex) + printf("Would unlink(%s)\n", f1); + else if (unlink(f1)) { + if (errno != ENOENT) { + fprintf(stderr, "unlink(%s) failed: %s\n", f1, + strerror(errno)); + return; + } + } + /* file = dirname(f3) / f2 */ + if (f3) { + snprintf(fb, sizeof fb, "%s", f3); + cp = strrchr(fb, '/'); + if (cp) { + ++cp; + *cp = 0; + } else { + *fb = 0; + } + } else { + *fb = 0; + } + snprintf(fb, sizeof fb, "%s%s", fb, f2); + if (debug > 1) printf("cleanlinks 1: file is <%s>\n", fb); + + if (memorex) + printf("Would symlink <%s> -> <%s>\n", f1, fb); + else if (symlink(fb, f1)) { + fprintf(stderr, "symlink(%s,%s) failed: %s\n", fb, f1, + strerror(errno)); + return; + } + + /* + If trash: + - if f3 begins with a /, unlink it + - else, unlink dirname(f1) / f3 + */ + if (trash && f3) { + if ('/' == *f3) { + if (memorex) + printf("Would unlink(%s)\n", f3); + else if (unlink(f3)) { + if (errno != ENOENT) { + fprintf(stderr, "unlink(%s) failed: %s\n", f3, + strerror(errno)); + return; + } + } + } else { + snprintf(fb, sizeof fb, "%s", f1); + cp = strrchr(fb, '/'); + if (cp) { + *cp = 0; + } + snprintf(fb, sizeof fb, "%s/%s", fb, f3); + if (debug > 1) + printf("cleanlinks 2: file is <%s>\n", fb); + if (memorex) + printf("Would unlink(%s)\n", fb); + else if (unlink(fb)) { + if (errno != ENOENT) { + fprintf(stderr, "unlink(%s) failed: %s\n", fb, + strerror(errno)); + return; + } + } + } + } + + return; +} + + +int +main( + int argc, + char *argv[] + ) +{ +#ifdef PUBKEY + R_RSA_PRIVATE_KEY rsaref_private; /* RSA private key */ + R_RSA_PUBLIC_KEY rsaref_public; /* RSA public key */ + R_RSA_PROTO_KEY protokey; /* RSA prototype key */ + R_DH_PARAMS dh_params; /* Diffie-Hellman parameters */ + R_RANDOM_STRUCT randomstr; /* random structure */ + int rval; /* return value */ + u_char encoded_key[MAXKEYLEN]; /* encoded PEM string buffer */ + u_int modulus; /* modulus length */ + u_int len; +#endif /* PUBKEY */ + struct timeval tv; /* initialization vector */ + u_long ntptime; /* NTP timestamp */ + char hostname[256]; /* DNS host name */ + u_char md5key[17]; /* generated MD5 key */ + FILE *str; /* file handle */ + u_int temp; + int i, j; + mode_t std_mask; /* Standard mask */ + mode_t sec_mask = 077; /* Secure mask */ + char pathbuf[PATH_MAX]; + + gethostname(hostname, sizeof(hostname)); + gettimeofday(&tv, 0); + ntptime = tv.tv_sec + JAN_1970; + + /* Initialize config_file */ + getconfig(argc, argv); /* ntpd/ntp_config.c */ + + if (!f1_keysdir) { + /* Shouldn't happen... */ + f1_keysdir = "PATH_KEYSDIR"; + } + if (*f1_keysdir != '/') { + fprintf(stderr, + "%s: keysdir path <%s> doesn't begin with a /\n", + progname, f1_keysdir); + exit(1); + } + + if (!f2_keys) { + snprintf(pathbuf, sizeof pathbuf, "ntp.keys.%lu", + ntptime); + f2_keys = strdup(pathbuf); + } + if (!f1_keys) { + snprintf(pathbuf, sizeof pathbuf, "%s/ntp.keys", + f1_keysdir); + f1_keys = strdup(pathbuf); + } + if (*f1_keys != '/') { + fprintf(stderr, + "%s: keys path <%s> doesn't begin with a /\n", + progname, f1_keys); + exit(1); + } + snifflink(f1_keys, &f3_keys); + + if (!f2_publickey) { + snprintf(pathbuf, sizeof pathbuf, "ntpkey_%s.%lu", + hostname, ntptime); + f2_publickey = strdup(pathbuf); + } + if (!f1_publickey) { + snprintf(pathbuf, sizeof pathbuf, "%s/ntpkey_%s", + f1_keysdir, hostname); + f1_publickey = strdup(pathbuf); + } + if (*f1_publickey != '/') { + fprintf(stderr, + "%s: publickey path <%s> doesn't begin with a /\n", + progname, f1_publickey); + exit(1); + } + snifflink(f1_publickey, &f3_publickey); + + if (!f2_privatekey) { + snprintf(pathbuf, sizeof pathbuf, "ntpkey.%lu", + ntptime); + f2_privatekey = strdup(pathbuf); + } + if (!f1_privatekey) { + snprintf(pathbuf, sizeof pathbuf, "%s/ntpkey", + f1_keysdir); + f1_privatekey = strdup(pathbuf); + } + if (*f1_privatekey != '/') { + fprintf(stderr, + "%s: privatekey path <%s> doesn't begin with a /\n", + progname, f1_privatekey); + exit(1); + } + snifflink(f1_privatekey, &f3_privatekey); + + if (!f2_dhparms) { + snprintf(pathbuf, sizeof pathbuf, "ntpkey_dh.%lu", + ntptime); + f2_dhparms = strdup(pathbuf); + } + if (!f1_dhparms) { + snprintf(pathbuf, sizeof pathbuf, "%s/ntpkey_dh", + f1_keysdir); + f1_dhparms = strdup(pathbuf); + } + if (*f1_dhparms != '/') { + fprintf(stderr, + "%s: dhparms path <%s> doesn't begin with a /\n", + progname, f1_dhparms); + exit(1); + } + snifflink(f1_dhparms, &f3_dhparms); + + if (debug > 1) { + printf("After config:\n"); + printf("keysdir = <%s>\n", f1_keysdir? f1_keysdir: ""); + printf("keys = <%s> -> <%s>\n" + , f1_keys? f1_keys: "" + , f2_keys? f2_keys: "" + ); + printf(" old = <%s>\n", f3_keys? f3_keys: ""); + printf("publickey = <%s> -> <%s>\n" + , f1_publickey? f1_publickey: "" + , f2_publickey? f2_publickey: "" + ); + printf(" old = <%s>\n", f3_publickey? f3_publickey: ""); + printf("privatekey = <%s> -> <%s>\n" + , f1_privatekey? f1_privatekey: "" + , f2_privatekey? f2_privatekey: "" + ); + printf(" old = <%s>\n", f3_privatekey? f3_privatekey: ""); + printf("dhparms = <%s> -> <%s>\n" + , f1_dhparms? f1_dhparms: "" + , f2_dhparms? f2_dhparms: "" + ); + printf(" old = <%s>\n", f3_dhparms? f3_dhparms: ""); + } + + /* + for each file we're going to install: + - make the new timestamped file + - if (!nosymlinks) + - - remove any old link + - - make the link + - - if (trash) + - - - remove the old file + */ + + std_mask = umask(sec_mask); /* Get the standard mask */ + (void) umask(std_mask); + + if (make_md5 && (force || !filep(f1_keys))) { + /* + * Generate 16 random MD5 keys. + */ + printf("Generating MD5 key file...\n"); + str = newfile(f1_keys, f2_keys, sec_mask, f3_keys); + if (!memorex) { + srandom((u_int)tv.tv_usec); + fprintf(str, "# MD5 key file %s\n# %s", f2_keys, + ctime((const time_t *) &tv.tv_sec)); + for (i = 1; i <= 16; i++) { + for (j = 0; j < 16; j++) { + while (1) { + temp = random() & 0xff; + /* + ** Harlan says Karnaugh maps + ** are not his friend, and + ** compilers can optimize + ** this most easily. + */ + if (temp == '#') + continue; + if (temp > 0x20 && temp < 0x7f) + break; + } + md5key[j] = (u_char)temp; + } + md5key[16] = 0; + fprintf(str, "%2d M %16s # MD5 key\n", + i, md5key); + } + } + if (str) fclose(str); + cleanlinks(f1_keys, f2_keys, f3_keys); + } + +#ifdef PUBKEY + if (make_rsa && (force || !filep(f1_publickey) + || !filep(f1_privatekey))) { + /* + * Roll the RSA public/private key pair. + */ + printf("Generating RSA public/private key pair (%d bits)...\n", + MODULUSLEN); + if (!memorex) { + protokey.bits = MODULUSLEN; + protokey.useFermat4 = 1; + R_RandomInit(&randomstr); + R_GetRandomBytesNeeded(&len, &randomstr); + for (i = 0; i < len; i++) { + temp = random(); + R_RandomUpdate(&randomstr, (u_char *)&temp, 1); + } + rval = R_GeneratePEMKeys(&rsaref_public, + &rsaref_private, &protokey, + &randomstr); + if (rval) { + printf("R_GeneratePEMKeys error %x\n", rval); + return (-1); + } + } + + /* + * Generate the file "ntpkey.*" containing the RSA + * private key in printable ASCII format. + */ + str = newfile(f1_privatekey, f2_privatekey, sec_mask, + f3_privatekey); + if (!memorex) { + len = sizeof(rsaref_private) + - sizeof(rsaref_private.bits); + modulus = (u_int32)rsaref_private.bits; + fprintf(str, "# RSA private key file %s\n# %s", + f2_privatekey, ctime(&tv.tv_sec)); + R_EncodePEMBlock(encoded_key, &temp, + (u_char *)rsaref_private.modulus, + len); + encoded_key[temp] = '\0'; + fprintf(str, "%d %s\n", modulus, encoded_key); + } + if (str) fclose(str); + cleanlinks(f1_privatekey, f2_privatekey, f3_privatekey); + + /* + * Generate the file "ntpkey_host.*" containing the RSA + * public key in printable ASCII format. + */ + str = newfile(f1_publickey, f2_publickey, std_mask, + f3_publickey); + if (!memorex) { + len = sizeof(rsaref_public) + - sizeof(rsaref_public.bits); + modulus = (u_int32)rsaref_public.bits; + fprintf(str, "# RSA public key file %s\n# %s", + f2_publickey, ctime(&tv.tv_sec)); + R_EncodePEMBlock(encoded_key, &temp, + (u_char *)rsaref_public.modulus, len); + encoded_key[temp] = '\0'; + fprintf(str, "%d %s\n", modulus, encoded_key); + } + if (str) fclose(str); + cleanlinks(f1_publickey, f2_publickey, f3_publickey); + } +#endif /* PUBKEY */ + +#ifdef PUBKEY + if (make_dh && (force || !filep(f1_dhparms))) { + /* + * Roll the prime and generator for the Diffie-Hellman key + * agreement algorithm. + */ + printf("Generating Diffie-Hellman parameters (%d bits)...\n", + PRIMELEN); + str = newfile(f1_dhparms, f2_dhparms, std_mask, f3_dhparms); + + if (!memorex) { + R_RandomInit(&randomstr); + R_GetRandomBytesNeeded(&len, &randomstr); + for (i = 0; i < len; i++) { + temp = random(); + R_RandomUpdate(&randomstr, (u_char *)&temp, 1); + } + + /* + * Generate the file "ntpkey_dh.*" containing the + * Diffie-Hellman prime and generator in printable + * ASCII format. + */ + len = DH_PRIME_LEN(PRIMELEN); + dh_params.prime = (u_char *)malloc(len); + dh_params.generator = (u_char *)malloc(len); + rval = R_GenerateDHParams(&dh_params, PRIMELEN, + PRIMELEN / 2, &randomstr); + if (rval) { + printf("R_GenerateDHParams error %x\n", rval); + return (-1); + } + + fprintf(str, + "# Diffie-Hellman parameter file %s\n# %s", + f2_dhparms, ctime(&tv.tv_sec)); + R_EncodePEMBlock(encoded_key, &temp, + (u_char *)dh_params.prime, + dh_params.primeLen); + encoded_key[temp] = '\0'; + fprintf(str, "%d %s\n", dh_params.primeLen, + encoded_key); + R_EncodePEMBlock(encoded_key, &temp, + (u_char *)dh_params.generator, + dh_params.generatorLen); + encoded_key[temp] = '\0'; + fprintf(str, "%d %s\n", dh_params.generatorLen, + encoded_key); + } + if (str) fclose(str); + cleanlinks(f1_dhparms, f2_dhparms, f3_dhparms); + } +#endif /* PUBKEY */ + + return (0); +} |