diff --git a/chrony.texi.in b/chrony.texi.in index d8bdeb9..ce557cc 100644 --- a/chrony.texi.in +++ b/chrony.texi.in @@ -1177,6 +1177,7 @@ directives can occur in any order in the file. * dumpdir directive:: Specify directory for dumping measurements * dumponexit directive:: Dump measurements when daemon exits * fallbackdrift directive:: Specify fallback drift intervals +* generatecommandkey directive:: Generate command key automatically * include directive:: Include a configuration file * initstepslew directive:: Trim the system clock on boot-up. * keyfile directive:: Specify location of file containing keys @@ -1466,7 +1467,7 @@ In the key file (see the keyfile command) there should be a line of the form @example -20 foobar +20 MD5 HEX:B028F91EA5C38D06C2E140B26C7F41EC @end example When running the chronyc program to perform run-time configuration, @@ -1638,6 +1639,16 @@ By default (or if the specified maximum or minimum is 0), no fallbacks will be used and the clock frequency will stay at the last value calculated before synchronisation was lost. @c }}} +@c {{{ generatecommandkey +@node generatecommandkey directive +@subsection generatecommandkey +With this directive, if the command key is not found on start in the file +specified by the @code{keyfile} directive, @code{chronyd} will generate a new +command key from the /dev/urandom file and write it to the key file. + +The generated key will use SHA1 if @code{chronyd} is compiled with the support, +otherwise MD5 will be used. +@c }}} @c {{{ include @node include directive @subsection include @@ -1744,8 +1755,9 @@ password can be encoded as a string of characters not containing a space with optional @code{ASCII:} prefix or as a hexadecimal number with @code{HEX:} prefix. -The ID for the chronyc authentication key is specified with the -commandkey command (see earlier). +The ID for the chronyc authentication key is specified with the commandkey +command (see earlier). The command key can be generated automatically on +start with the @code{generatecommandkey} directive. @c }}} @c {{{ leapsectz @node leapsectz directive diff --git a/conf.c b/conf.c index 87529db..67b3841 100644 --- a/conf.c +++ b/conf.c @@ -73,6 +73,7 @@ static void parse_driftfile(char *); static void parse_dumpdir(char *); static void parse_dumponexit(char *); static void parse_fallbackdrift(char *); +static void parse_generatecommandkey(char *); static void parse_include(char *); static void parse_initstepslew(char *); static void parse_keyfile(char *); @@ -111,6 +112,7 @@ static void parse_user(char *); /* Configuration variables */ static int restarted = 0; +static int generate_command_key = 0; static char *rtc_device = "/dev/rtc"; static int acquisition_port = 0; /* 0 means let kernel choose port */ static int ntp_port = 123; @@ -386,6 +388,8 @@ CNF_ReadFile(const char *filename) parse_dumponexit(p); } else if (!strcasecmp(command, "fallbackdrift")) { parse_fallbackdrift(p); + } else if (!strcasecmp(command, "generatecommandkey")) { + parse_generatecommandkey(p); } else if (!strcasecmp(command, "include")) { parse_include(p); } else if (!strcasecmp(command, "initstepslew")) { @@ -999,6 +1003,15 @@ parse_fallbackdrift(char *line) /* ================================================== */ +static void +parse_generatecommandkey(char *line) +{ + check_number_of_args(line, 0); + generate_command_key = 1; +} + +/* ================================================== */ + static void parse_makestep(char *line) { @@ -1563,6 +1576,14 @@ CNF_GetCommandKey(void) /* ================================================== */ +int +CNF_GetGenerateCommandKey(void) +{ + return generate_command_key; +} + +/* ================================================== */ + int CNF_GetDumpOnExit(void) { diff --git a/conf.h b/conf.h index 68ea0e1..af8e2a0 100644 --- a/conf.h +++ b/conf.h @@ -56,6 +56,7 @@ extern int CNF_GetLogTempComp(void); extern char *CNF_GetKeysFile(void); extern char *CNF_GetRtcFile(void); extern unsigned long CNF_GetCommandKey(void); +extern int CNF_GetGenerateCommandKey(void); extern int CNF_GetDumpOnExit(void); extern int CNF_GetManualEnabled(void); extern int CNF_GetCommandPort(void); diff --git a/configure b/configure index 46625db..c92e433 100755 --- a/configure +++ b/configure @@ -518,6 +518,7 @@ if [ $try_nss = "1" ]; then HASH_OBJ="hash_nss.o" HASH_COMPILE="$test_cflags" HASH_LINK="$test_link" + add_def GENERATE_SHA1_KEY fi fi @@ -528,6 +529,7 @@ if [ "x$HASH_LINK" = "x" ] && [ $try_tomcrypt = "1" ]; then HASH_OBJ="hash_tomcrypt.o" HASH_COMPILE="-I/usr/include/tomcrypt" HASH_LINK="-ltomcrypt" + add_def GENERATE_SHA1_KEY fi fi diff --git a/keys.c b/keys.c index edb9935..fa27440 100644 --- a/keys.c +++ b/keys.c @@ -62,6 +62,64 @@ static int cache_key_pos; /* ================================================== */ +static int +generate_key(unsigned long key_id) +{ +#ifdef GENERATE_SHA1_KEY + unsigned char key[20]; + const char *hashname = "SHA1"; +#else + unsigned char key[16]; + const char *hashname = "MD5"; +#endif + const char *key_file, *rand_dev = "/dev/urandom"; + FILE *f; + struct stat st; + int i; + + key_file = CNF_GetKeysFile(); + + if (!key_file) + return 0; + + f = fopen(rand_dev, "r"); + if (!f || fread(key, sizeof (key), 1, f) != 1) { + if (f) + fclose(f); + LOG_FATAL(LOGF_Keys, "Could not read %s", rand_dev); + return 0; + } + fclose(f); + + f = fopen(key_file, "a"); + if (!f) { + LOG_FATAL(LOGF_Keys, "Could not open keyfile %s for writing", key_file); + return 0; + } + + /* Make sure the keyfile is not world-readable */ + if (stat(key_file, &st) || chmod(key_file, st.st_mode & 0770)) { + fclose(f); + LOG_FATAL(LOGF_Keys, "Could not change permissions of keyfile %s", key_file); + return 0; + } + + fprintf(f, "\n%lu %s HEX:", key_id, hashname); + for (i = 0; i < sizeof (key); i++) + fprintf(f, "%02hhX", key[i]); + fprintf(f, "\n"); + fclose(f); + + /* Erase the key from stack */ + memset(key, sizeof (key), 0); + + LOG(LOGS_INFO, LOGF_Keys, "Generated key %lu", key_id); + + return 1; +} + +/* ================================================== */ + void KEY_Initialise(void) { @@ -69,6 +127,12 @@ KEY_Initialise(void) command_key_valid = 0; cache_valid = 0; KEY_Reload(); + + if (CNF_GetGenerateCommandKey() && !KEY_KeyKnown(KEY_GetCommandKey())) { + if (generate_key(KEY_GetCommandKey())) + KEY_Reload(); + } + return; } diff --git a/main.c b/main.c index 2fe96fa..cab0b87 100644 --- a/main.c +++ b/main.c @@ -88,13 +88,13 @@ MAI_CleanupAndExit(void) TMC_Finalise(); MNL_Finalise(); ACQ_Finalise(); - KEY_Finalise(); CLG_Finalise(); NSR_Finalise(); NCR_Finalise(); BRD_Finalise(); SST_Finalise(); REF_Finalise(); + KEY_Finalise(); RCL_Finalise(); SRC_Finalise(); RTC_Finalise(); @@ -383,6 +383,7 @@ int main RTC_Initialise(); SRC_Initialise(); RCL_Initialise(); + KEY_Initialise(); /* Command-line switch must have priority */ if (!sched_priority) { @@ -411,7 +412,6 @@ int main NCR_Initialise(); NSR_Initialise(); CLG_Initialise(); - KEY_Initialise(); ACQ_Initialise(); MNL_Initialise(); TMC_Initialise();