Skip to content

Commit

Permalink
tlsdated: support config files
Browse files Browse the repository at this point in the history
The config file is a list of key/value pairs, separated by whitespace.

Signed-off-by: Elly Fong-Jones <ellyjones@chromium.org>
  • Loading branch information
elly committed Jan 16, 2013
1 parent 99b51df commit 677a136
Show file tree
Hide file tree
Showing 12 changed files with 502 additions and 67 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Don't hardfail if DEFAULT_RTC_DEVICE cannot be opened, even if desired
Support -j to add jitter to tlsdated time checks.
Exponential backoff when tls connections fail.
Add config file support (have a look at man/tlsdated.conf.5)
0.0.4 Wed 7 Nov, 2012
Fixup CHANGELOG and properly tag
Version Numbers Are Free! Hooray!
Expand Down
5 changes: 5 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,16 @@ certdir = @TLSDATE_CA_ROOTS@
cert_DATA = ca-roots/tlsdate-ca-roots.conf
EXTRA_DIST+= $(cert_DATA)

confdir = @TLSDATE_CONF_DIR@
conf_DATA = etc/tlsdated.conf
EXTRA_DIST+= $(conf_DATA)

# Our documentation
man_MANS+= man/tlsdate.1
man_MANS+= man/tlsdated.1
man_MANS+= man/tlsdate-helper.1
man_MANS+= man/tlsdate-routeup.1
man_MANS+= man/tlsdated.conf.5
EXTRA_DIST+= $(man_MANS)

.PHONY: debian_orig git-tag git-push git-tag-debian deb really-clean valgrind_test
Expand Down Expand Up @@ -110,6 +114,7 @@ src/configmake.h: ${top_srcdir}/Makefile.in
@{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
echo '#define TLSDATE_CONFIG "$(sysconfdir)/ca-roots/"'; \
echo '#define TLSDATE_CERTFILE "$(sysconfdir)/tlsdate/ca-roots/tlsdate-ca-roots.conf"'; \
echo '#define TLSDATE_CONF_DIR "$(sysconfdir)/tlsdate/"'; \
echo '#define TLSDATE_HELPER "$(bindir)/tlsdate-helper"'; \
echo '#define TLSDATE "$(bindir)/tlsdate"'; \
echo '#define TLSDATED "$(bindir)/tlsdated"'; \
Expand Down
4 changes: 4 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ dnl Build up the directory we will use to install certs
TLSDATE_CA_ROOTS="${sysconfdir}/$PACKAGE_NAME/ca-roots"
AC_SUBST([TLSDATE_CA_ROOTS])

dnl Place we install our config file
TLSDATE_CONF_DIR="${sysconfdir}/$PACKAGE_NAME/"
AC_SUBST([TLSDATE_CONF_DIR])

dnl Required headers
dnl First check to see if openssl is installed
AC_CHECK_HEADERS([openssl/ssl.h], ,[AC_MSG_ERROR([OpenSSL is not installed, openssl/sslh is missing])])
Expand Down
23 changes: 23 additions & 0 deletions etc/tlsdated.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# tlsdated example config file
# for boolean options, "yes" enables them, any other value disables them.
# see tlsdated.conf(5) for details about the options

base-path /var/cache/tlsdated
dry-run no
jitter 0
max-tries 10
min-steady-state-interval 86400
should-load-disk yes
should-netlink yes
should-save-disk yes
should-sync-hwclock yes
steady-state-interval 86400
subprocess-tries 10
subprocess-wait-between-tries 3
verbose yes
wait-between-tries 10

# Host configuration.
host www.ptb.de
port 443
proxy none
2 changes: 2 additions & 0 deletions man/tlsdated.1
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ add up to n seconds of jitter to steady-state fetches
be verbose
.IP "\-h"
print help message
.IP "\-f [/path/to/config/file]"
use alternate config file
.IP "[tlsdate command]"
arguments to be passed to tlsdate at launch time

Expand Down
65 changes: 65 additions & 0 deletions man/tlsdated.conf.5
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
.\" Process this file with
.\" groff -man -Tascii foo.1
.\"
.TH TLSDATED 5 "JANUARY 2013" "File Formats and Conversions"
.SH NAME
tlsdated.conf \- tlsdated config file
.SH SYNTAX
\fBtlsdated.conf\fR is the configuration file for the \fBtlsdated(1)\fR daemon.
The config file is formatted as a list of key-value pairs, one per line,
separated by whitespace. Whitespace inside values is preserved, so
.RS
foo bar baz quxx
.RE
represents the key \fBfoo\fR mapping to the value \fBbar baz quxx\fR. Empty
lines and lines beginning with \fB#\fR are ignored; leading whitespace on lines
is stripped. For boolean options, the value \fByes\fR or no value at all
indicates that the option should be switched on, and all other values indicate
that the option should be switched off. \fINote that trailing whitespace is
preserved in values.\fR
.SH OPTIONS
.IP argv (string)
Add an argument to the subprocess's argument vector. Use this option multiple
times for multiple arguments.
.IP base-path (string)
Sets the path to tlsdated's cache directory.
.IP dry-run (bool)
If enabled, don't actually adjust the system time.
.IP jitter (int)
Add or subtract up to this many seconds from the steady-state interval when
checking. This helps prevent correlation between sequential checks and smooth
load on time hosts.
.IP max-tries (int)
How many times to try running the tlsdate subprocess.
.IP min-steady-state-interval (int)
Do not check more than once this many seconds when in steady state.
.IP should-load-disk (bool)
If enabled, try loading the current timestamp out of the cache directory.
.IP should-netlink (bool)
If enabled, use a netlink socket to get network events; otherwise, read network
events from stdin.
.IP should-save-disk (bool)
If enabled, save the current timestamp to the cache directory every so often and
at exit.
.IP should-sync-hwclock (bool)
If enabled, set the hwclock to the fetched time.
.IP steady-state-interval (int)
Check at least once this many seconds when in steady state.
.IP subprocess-tries (int)
How many times to try waiting for the subprocess.
.IP subprocess-wait-between-tries (int)
How many seconds to wait between each attempt to wait for the subprocess.
.IP verbose (bool)
If enabled, tlsdated will be annoyingly verbose in syslog and on stdout.
.IP wait-between-tries (int)
How long to wait between runs of the subprocess.
.SH BUGS
It's likely! Let us know by contacting jacob@appelbaum.net

Note that
.B tlsdated(1)
is still in Alpha, and may not work as expected.
.SH AUTHOR
Jacob Appelbaum <jacob at appelbaum dot net>
.SH "SEE ALSO"
.B tlsdated(1),
79 changes: 79 additions & 0 deletions src/conf-unittest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* conf-unittest.c - config parser unit tests
* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "conf.h"
#include "test_harness.h"

FILE *fopenstr(const char *str) {
/* strlen(str) instead of strlen(str) + 1 because files shouldn't appear
* null-terminated. Cast away constness because we're in read mode, but the
* fmemopen prototype has no way to express that. */
return fmemopen((char *)str, strlen(str), "r");
}

TEST(parse_empty) {
/* can't do a truly empty file - fmemopen() combusts */
FILE *f = fopenstr("\n");
ASSERT_NE(NULL, f);
struct conf_entry *e = conf_parse(f);
EXPECT_NULL(e);
conf_free(e);
}

TEST(parse_basic) {
FILE *f = fopenstr("foo bar\nbaz quxx\n");
ASSERT_NE(NULL, f);
struct conf_entry *e = conf_parse(f);
ASSERT_NE(NULL, e);
EXPECT_STREQ(e->key, "foo");
EXPECT_STREQ(e->value, "bar");
ASSERT_NE(NULL, e->next);
EXPECT_STREQ(e->next->key, "baz");
EXPECT_STREQ(e->next->value, "quxx");
ASSERT_NULL(e->next->next);
conf_free(e);
}

TEST(parse_novalue) {
FILE *f = fopenstr("abcdef\n");
ASSERT_NE(NULL, f);
struct conf_entry *e = conf_parse(f);
ASSERT_NE(NULL, e);
EXPECT_STREQ(e->key, "abcdef");
EXPECT_NULL(e->value);
EXPECT_NULL(e->next);
conf_free(e);
}

TEST(parse_whitespace) {
FILE *f = fopenstr(" fribble grotz \n");
ASSERT_NE(NULL, f);
struct conf_entry *e = conf_parse(f);
ASSERT_NE(NULL, e);
EXPECT_STREQ(e->key, "fribble");
EXPECT_STREQ(e->value, "grotz ");
EXPECT_NULL(e->next);
conf_free(e);
}

TEST(parse_comment) {
FILE *f = fopenstr("#foo bar\nbaz quxx\n");
ASSERT_NE(NULL, f);
struct conf_entry *e = conf_parse(f);
ASSERT_NE(NULL, e);
EXPECT_STREQ(e->key, "baz");
EXPECT_STREQ(e->value, "quxx");
EXPECT_NULL(e->next);
conf_free(e);
}

TEST_HARNESS_MAIN
86 changes: 86 additions & 0 deletions src/conf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* conf.c - config file parser */

#define _GNU_SOURCE /* strchrnul */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "conf.h"

void strip_newlines(char *line)
{
*strchrnul(line, '\n') = '\0';
*strchrnul(line, '\r') = '\0';
}

char *eat_whitespace(char *line)
{
while (isspace(*line))
line++;
return line;
}

int is_ignored_line(char *line)
{
return !*line || *line == '#';
}

struct conf_entry *conf_parse(FILE *f)
{
struct conf_entry *head = NULL;
struct conf_entry *tail = NULL;
char buf[CONF_MAX_LINE];

while (fgets(buf, sizeof(buf), f)) {
struct conf_entry *e;
char *start = buf;
char *key;
char *val;

strip_newlines(start);
start = eat_whitespace(start);
if (is_ignored_line(start))
continue;

key = strtok(start, " \t");
val = strtok(NULL, "");
if (val)
val = eat_whitespace(val);
e = malloc(sizeof *e);
if (!e)
goto fail;
e->next = NULL;
e->key = strdup(key);
e->value = val ? strdup(val) : NULL;
if (!e->key || (val && !e->value)) {
free(e->key);
free(e->value);
goto fail;
}
if (!head) {
head = e;
tail = e;
} else {
tail->next = e;
tail = e;
}
}

return head;
fail:
conf_free(head);
return NULL;
}

void conf_free(struct conf_entry *e)
{
struct conf_entry *n;
while (e) {
n = e->next;
free(e->key);
free(e->value);
free(e);
e = n;
}
}
19 changes: 19 additions & 0 deletions src/conf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* conf.h - config file parser */

#ifndef CONF_H
#define CONF_H

#include <stdio.h>

#define CONF_MAX_LINE 16384

struct conf_entry {
struct conf_entry *next;
char *key;
char *value;
};

struct conf_entry *conf_parse(FILE *f);
void conf_free(struct conf_entry *e);

#endif /* !CONF_H */
8 changes: 7 additions & 1 deletion src/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ bin_PROGRAMS+= src/tlsdate-helper
bin_PROGRAMS+= src/tlsdated
bin_PROGRAMS+= src/tlsdate-dbus-announce

src_conf_unittest_SOURCES = src/conf.c
src_conf_unittest_SOURCES+= src/conf-unittest.c
check_PROGRAMS+= src/conf_unittest
noinst_PROGRAMS+= src/conf_unittest

src_tlsdate_routeup_CFLAGS = -DROUTEUP_MAIN
src_tlsdate_routeup_SOURCES = src/routeup.c
src_tlsdate_routeup_SOURCES+= src/util.c
Expand All @@ -23,7 +28,8 @@ src_tlsdate_helper_SOURCES+= src/util.c

src_tlsdated_CFLAGS = -DTLSDATED_MAIN
src_tlsdated_LDADD = -lcrypto
src_tlsdated_SOURCES = src/routeup.c
src_tlsdated_SOURCES = src/conf.c
src_tlsdated_SOURCES+= src/routeup.c
src_tlsdated_SOURCES+= src/tlsdated.c
src_tlsdated_SOURCES+= src/util.c

Expand Down
2 changes: 2 additions & 0 deletions src/tlsdate.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@

#define DEFAULT_HOST "www.ptb.de"
#define DEFAULT_PORT "443"
#define DEFAULT_PROXY "none"
#define DEFAULT_PROTOCOL "tlsv1"
#define DEFAULT_CERTDIR "/etc/ssl/certs"
#define DEFAULT_CERTFILE TLSDATE_CERTFILE
#define DEFAULT_DAEMON_CACHEDIR "/var/cache/tlsdated"
#define DEFAULT_DAEMON_TMPSUFFIX ".new"
#define DEFAULT_TLSDATE TLSDATE
#define DEFAULT_RTC_DEVICE "/dev/rtc"
#define DEFAULT_CONF_FILE TLSDATE_CONF_DIR "tlsdated.conf"

/* tlsdated magic numbers */
#define MAX_TRIES 10
Expand Down
Loading

0 comments on commit 677a136

Please sign in to comment.