From ae1e3bf73ce36c36938c39f872bf092513f773e2 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Wed, 15 May 2013 19:25:15 +0200 Subject: [PATCH] Add option to authenticate automatically on chronyc start --- chrony.texi | 38 +++++++++++---------- chronyc.1 | 10 ++++++ client.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 121 insertions(+), 22 deletions(-) diff --git a/chrony.texi b/chrony.texi index d0617c7..a284741 100644 --- a/chrony.texi +++ b/chrony.texi @@ -699,19 +699,13 @@ previous section. In the file @file{/etc/ppp/ip-up} we add the command sequence @example -/usr/local/bin/chronyc < +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 diff --git a/chronyc.1 b/chronyc.1 index 4d7ac7e..3da0229 100644 --- 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. diff --git a/client.c b/client.c index 64be42a..7cd016e 100644 --- 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 ] [-p ] [-n] [-4|-6] [-m] [command]\n", progname); + fprintf(stderr, "Usage : %s [-h ] [-p ] [-n] [-4|-6] [-m] [-a] [-f ]] [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 {