]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Add option to authenticate automatically on chronyc start
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 15 May 2013 17:25:15 +0000 (19:25 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 16 May 2013 12:18:57 +0000 (14:18 +0200)
chrony.texi
chronyc.1
client.c

index d0617c709d9d0ad451ce591ced3a33acf5dadc5b..a284741a216a8f8c10d4b6b93ac53ee795d9a136 100644 (file)
@@ -699,19 +699,13 @@ previous section.
 In the file @file{/etc/ppp/ip-up} we add the command sequence
 
 @example
-/usr/local/bin/chronyc <<EOF
-password xyzzy
-online
-EOF
+/usr/local/bin/chronyc -a online
 @end example
 
 and in the file @file{/etc/ppp/ip-down} we add the sequence
 
 @example
-/usr/local/bin/chronyc <<EOF 
-password xyzzy
-offline
-EOF
+/usr/local/bin/chronyc -a offline
 @end example
 
 @code{chronyd's} polling of the servers will now only occur whilst the
@@ -927,21 +921,16 @@ I use @code{pppd} for connecting to my ISP.  This runs two scripts
 @file{/etc/ppp/ip-up} and @file{/etc/ppp/ip-down} when the link goes
 online and offline respectively.
 
-The relevant part of the @file{/etc/ppp/ip-up} file is (with a dummy
-password)
+The relevant part of the @file{/etc/ppp/ip-up} file is
 
 @example
-/usr/local/bin/chronyc <<EOF
-password xxxxxxxx
-online
-EOF
+/usr/local/bin/chronyc -a online
 @end example
 
 and the relevant part of the @file{/etc/ppp/ip-down} script is
 
 @example
-/usr/local/bin/chronyc <<EOF
-password xxxxxxxx
+/usr/local/bin/chronyc -a <<EOF
 offline
 dump
 writertc
@@ -1484,7 +1473,8 @@ password foobar
 @end example
 
 must be entered before any commands affecting the operation of the
-daemon can be entered.
+daemon can be entered, or chronyc must be started with the `-a' option to run
+the password command automatically.
 @c }}}
 @c {{{ cmdport
 @node cmdport directive
@@ -2957,6 +2947,14 @@ With this option hostnames will be resolved only to IPv6 addresses.
 @item -m
 With this option multiple commands can be specified on the command line.
 Each argument will be interpreted as a whole command.
+@item -f <conf-file>
+This option can be used to specify an alternate location of the @code{chronyd}
+configuration file (default @file{/etc/chrony.conf}). The configuration file is
+needed for the `-a' option.
+@item -a
+With this option @code{chronyc} will try to authenticate automatically on
+start. It will read the configuration file, read the command key from the
+keyfile and run the authhash and password commands.
 @end table
 @c }}}
 @c {{{ SS:Security with chronyc
@@ -3188,6 +3186,9 @@ An example is
 @example
 authhash SHA1
 @end example
+
+The authhash command is run automatically on start if @code{chronyc} was
+started with the `-a' option.
 @c }}}
 @c {{{ burst
 @node burst command
@@ -3858,6 +3859,9 @@ The 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.  It has to match @code{chronyd's} currently defined command key
 (@pxref{commandkey directive}).
+
+The password command is run automatically on start if @code{chronyc} was
+started with the `-a' option.
 @c }}}
 @c {{{ polltarget
 @node polltarget command
index 4d7ac7e402a04144c9c43f9a65f37717b0e21450..3da0229c0db2086a8dcaa2524da89697e657f911 100644 (file)
--- a/chronyc.1
+++ b/chronyc.1
@@ -42,6 +42,16 @@ resolve hostnames only to IPv6 addresses
 allow multiple commands to be specified on the command line.  Each argument
 will be interpreted as a whole command.
 .TP
+\fB\-f\fR \fIconf-file\fR
+This option can be used to specify an alternate location for the
+configuration file (default \fI/etc/chrony.conf\fR). The configuration file is
+needed for the \fB-a\fR option.
+.TP
+\fB\-a\fR
+With this option chronyc will try to authenticate automatically on
+start. It will read the configuration file, read the command key from the
+keyfile and run the authhash and password commands.
+.TP
 \fIcommand\fR
 specify command.  If no command is given, chronyc will read commands
 interactively.
index 64be42a0087ca7265940b7a453c3c32c52c40129..7cd016ef974b29a2c7f0c721133e1a7688b84264 100644 (file)
--- a/client.c
+++ b/client.c
@@ -2512,9 +2512,9 @@ process_cmd_dns(const char *line)
 /* ================================================== */
 
 static int
-process_cmd_authhash(char *line)
+process_cmd_authhash(const char *line)
 {
-  char *hash_name;
+  const char *hash_name;
   int new_hash_id;
 
   assert(auth_hash_id >= 0);
@@ -2748,6 +2748,77 @@ process_line(char *line, int *quit)
 
 /* ================================================== */
 
+static int
+authenticate_from_config(const char *filename)
+{
+  CMD_Request tx_message;
+  CMD_Reply rx_message;
+  char line[2048], keyfile[2048], *command, *arg, *password;
+  const char *hashname;
+  unsigned long key_id = 0, key_id2 = -1;
+  int ret;
+  FILE *in;
+
+  in = fopen(filename, "r");
+  if (!in) {
+    fprintf(stderr, "Could not open file %s\n", filename);
+    return 0;
+  }
+
+  *keyfile = '\0';
+  while (fgets(line, sizeof (line), in)) {
+    CPS_NormalizeLine(line);
+    command = line;
+    arg = CPS_SplitWord(line);
+    if (!strcasecmp(command, "keyfile")) {
+      snprintf(keyfile, sizeof (keyfile), "%s", arg);
+    } else if (!strcasecmp(command, "commandkey")) {
+      if (sscanf(arg, "%lu", &key_id) != 1)
+        key_id = -1;
+    }
+  }
+  fclose(in);
+
+  if (!*keyfile || key_id == -1) {
+    fprintf(stderr, "Could not read keyfile or commandkey in file %s\n", filename);
+    return 0;
+  }
+
+  in = fopen(keyfile, "r");
+  if (!in) {
+    fprintf(stderr, "Could not open keyfile %s\n", filename);
+    return 0;
+  }
+
+  while (fgets(line, sizeof (line), in)) {
+    CPS_NormalizeLine(line);
+    if (!*line || !CPS_ParseKey(line, &key_id2, &hashname, &password))
+      continue;
+    if (key_id == key_id2)
+      break;
+  }
+  fclose(in);
+
+  if (key_id == key_id2) {
+    if (process_cmd_authhash(hashname) &&
+        process_cmd_password(&tx_message, password)) {
+      ret = request_reply(&tx_message, &rx_message, RPY_NULL, 1);
+    } else {
+      ret = 0;
+    }
+  } else {
+    fprintf(stderr, "Could not find key %lu in keyfile %s\n", key_id, keyfile);
+    ret = 0;
+  }
+
+  /* Erase password from stack */
+  memset(line, sizeof (line), 0);
+
+  return ret;
+}
+
+/* ================================================== */
+
 static int
 process_args(int argc, char **argv, int multi)
 {
@@ -2804,7 +2875,8 @@ main(int argc, char **argv)
   char *line;
   const char *progname = argv[0];
   const char *hostname = "localhost";
-  int quit = 0, ret = 1, multi = 0;
+  const char *conf_file = DEFAULT_CONF_FILE;
+  int quit = 0, ret = 1, multi = 0, auto_auth = 0;
   int port = DEFAULT_CANDM_PORT;
 
   /* Parse command line options */
@@ -2819,6 +2891,13 @@ main(int argc, char **argv)
       if (*argv) {
         port = atoi(*argv);
       }
+    } else if (!strcmp(*argv, "-f")) {
+      ++argv, --argc;
+      if (*argv) {
+        conf_file = *argv;
+      }
+    } else if (!strcmp(*argv, "-a")) {
+      auto_auth = 1;
     } else if (!strcmp(*argv, "-m")) {
       multi = 1;
     } else if (!strcmp(*argv, "-n")) {
@@ -2833,7 +2912,7 @@ main(int argc, char **argv)
       printf("chronyc (chrony) version %s\n", CHRONY_VERSION);
       exit(0);
     } else if (!strncmp(*argv, "-", 1)) {
-      fprintf(stderr, "Usage : %s [-h <hostname>] [-p <port-number>] [-n] [-4|-6] [-m] [command]\n", progname);
+      fprintf(stderr, "Usage : %s [-h <hostname>] [-p <port-number>] [-n] [-4|-6] [-m] [-a] [-f <file>]] [command]\n", progname);
       exit(1);
     } else {
       break; /* And process remainder of line as a command */
@@ -2857,7 +2936,13 @@ main(int argc, char **argv)
   
   open_io(hostname, port);
 
-  if (argc > 0) {
+  if (auto_auth) {
+    ret = authenticate_from_config(conf_file);
+  }
+
+  if (!ret) {
+    ;
+  } else if (argc > 0) {
     ret = process_args(argc, argv, multi);
   } else {
     do {