Hi,
Following http://marc.info/?l=openbsd-tech&m=142136923124184&w=2 which
added TLS client support in syslogd and since now libtls supports client
certificates, this patch adds client's certificate support in syslogd
for mutual authentication to a remote syslog server.
It is based on code from netcat.c
tested on -current logging to a a remote syslog-ng server using syslog
driver requiring trusted certificates from it's peers.
It adds two switches:
-c client_cert_file
-k client_key_file
Minor modification in CAfile setup as well to match the netcat code.
It is missing manual page change for the two switches. I will fix this
if ok.
comments?
Giannis
Index: syslogd.c
===================================================================
RCS file: /cvs/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.205
diff -u -p -r1.205 syslogd.c
--- syslogd.c 2 Apr 2016 19:55:10 -0000 1.205
+++ syslogd.c 23 Jun 2016 15:09:23 -0000
@@ -63,6 +63,7 @@
#define DEFUPRI (LOG_USER|LOG_NOTICE)
#define DEFSPRI (LOG_KERN|LOG_CRIT)
#define TIMERINTVL 30 /* interval for checking flush, mark */
+#define DEFAULT_CA_FILE "/etc/ssl/cert.pem"
#include <sys/ioctl.h>
#include <sys/stat.h>
@@ -223,8 +224,16 @@ char *path_ctlsock = NULL; /* Path to co
struct tls *server_ctx;
struct tls_config *client_config, *server_config;
-const char *CAfile = "/etc/ssl/cert.pem"; /* file containing CA certificates */
-int NoVerify = 0; /* do not verify TLS server x509 certificate */
+int NoVerify = 0; /* verify TLS server x509 certificate */
+char *CAfile = DEFAULT_CA_FILE; /* file containing CA certificates */
+char *PubCertfile; /* file containing public certificate */
+char *PrivKeyfile; /* file containing private key */
+uint8_t *cacert;
+size_t cacertlen;
+uint8_t *privkey;
+size_t privkeylen;
+uint8_t *pubcert;
+size_t pubcertlen;
int tcpbuf_dropped = 0; /* count messages dropped from TCP or TLS */
#define CTL_READING_CMD 1
@@ -353,7 +362,7 @@ main(int argc, char *argv[])
int ch, i;
int lockpipe[2] = { -1, -1}, pair[2], nullfd, fd;
- while ((ch = getopt(argc, argv, "46a:C:dFf:hm:np:S:s:T:U:uV")) != -1)
+ while ((ch = getopt(argc, argv, "46a:C:c:dFf:hk:m:np:S:s:T:U:uV")) !=
-1)
switch (ch) {
case '4': /* disable IPv6 */
Family = PF_INET;
@@ -369,6 +378,9 @@ main(int argc, char *argv[])
case 'C': /* file containing CA certificates */
CAfile = optarg;
break;
+ case 'c': /* file containing public certificate */
+ PubCertfile = optarg;
+ break;
case 'd': /* debug */
Debug++;
break;
@@ -381,6 +393,9 @@ main(int argc, char *argv[])
case 'h': /* RFC 3164 hostnames */
IncludeHostname = 1;
break;
+ case 'k': /* file containing private key */
+ PrivKeyfile = optarg;
+ break;
case 'm': /* mark interval */
MarkInterval = strtonum(optarg, 0, 365*24*60, &errstr);
if (errstr)
@@ -553,35 +568,37 @@ main(int argc, char *argv[])
tls_config_insecure_noverifycert(client_config);
tls_config_insecure_noverifyname(client_config);
} else {
- struct stat sb;
int fail = 1;
- fd = -1;
- p = NULL;
- if ((fd = open(CAfile, O_RDONLY)) == -1) {
- logerror("open CAfile");
- } else if (fstat(fd, &sb) == -1) {
- logerror("fstat CAfile");
- } else if (sb.st_size > 50*1024*1024) {
- logerrorx("CAfile larger than 50MB");
- } else if ((p = calloc(sb.st_size, 1)) == NULL) {
- logerror("calloc CAfile");
- } else if (read(fd, p, sb.st_size) != sb.st_size) {
- logerror("read CAfile");
- } else if (tls_config_set_ca_mem(client_config, p,
- sb.st_size) == -1) {
- logerrorx("tls_config_set_ca_mem");
- } else {
+ if (CAfile && (cacert = tls_load_file(CAfile,
&cacertlen, NULL))
+ == NULL)
+ errx(1, "unable to load CAfile %s", CAfile);
+ if (CAfile && tls_config_set_ca_mem(client_config,
cacert, cacertlen)
+ == -1)
+ errx(1, "unable to set CAfile %s", CAfile);
+ else {
fail = 0;
- logdebug("CAfile %s, size %lld\n",
- CAfile, sb.st_size);
+ logdebug("CAfile %s\n", CAfile);
}
/* avoid reading default certs in chroot */
if (fail)
tls_config_set_ca_mem(client_config, "", 0);
- free(p);
- close(fd);
}
+ if (PubCertfile && PrivKeyfile) {
+ if ((pubcert = tls_load_file(PubCertfile, &pubcertlen,
NULL)) == NULL)
+ errx(1, "unable to load TLS certificate file
%s", PubCertfile);
+ if (tls_config_set_cert_mem(client_config, pubcert,
pubcertlen) == -1)
+ errx(1, "unable to set TLS certificate file
%s", PubCertfile);
+ else
+ logdebug("TLS certificate %s\n", PubCertfile);
+ if ((privkey = tls_load_file(PrivKeyfile, &privkeylen,
NULL)) == NULL)
+ errx(1, "unable to load TLS key file %s",
PrivKeyfile);
+ if (tls_config_set_key_mem(client_config, privkey,
privkeylen) == -1)
+ errx(1, "unable to set TLS key file %s",
PrivKeyfile);
+ else
+ logdebug("TLS key %s\n", PrivKeyfile);
+ }
+
tls_config_set_protocols(client_config, TLS_PROTOCOLS_ALL);
if (tls_config_set_ciphers(client_config, "compat") != 0)
logerror("tls set client ciphers");