]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Add option to generate command key on start
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 21 May 2013 11:58:52 +0000 (13:58 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Tue, 21 May 2013 12:02:31 +0000 (14:02 +0200)
With generatecommandkey directive, if no command key is found in the key
file on start, one will be generated automatically from /dev/urandom.

chrony.texi.in
conf.c
conf.h
configure
keys.c
main.c

index d8bdeb988aeb10c55ab26f3ee87dcf9d3fabe9e7..ce557cc0036ad57332f28f188eb7a94f3c1e995a 100644 (file)
@@ -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 87529db97e1bd7e10f0e81c346689fe92042d03b..67b3841c27823ff3af752e48516fec6711a1c83d 100644 (file)
--- 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 68ea0e1e8d43b88c98dd97b403aeb131abe0014e..af8e2a0bba35544fdc04adb6bd86ab4f95c40a99 100644 (file)
--- 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);
index 46625dbc58a663e694574f1ecc42f67221b3e4e2..c92e433e5549a75c411e3b61af82c4540ecbba02 100755 (executable)
--- 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 edb9935781813866af3128bbc28fff2ff396a873..fa27440e2dd2fa5fe22be339390326d0e92d9bba 100644 (file)
--- 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 2fe96faff128448655d5b5d8c54b58a53d93e050..cab0b876be7865ce14309934625feea814dc30ef 100644 (file)
--- 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();