From 9b6b1520f273d46b3f8d229ee1be28a68e93bc15 Mon Sep 17 00:00:00 2001 From: Christian Hesse Date: Tue, 10 Oct 2017 15:17:41 +0200 Subject: start systemd service with dynamic user This requires systemd v235 and dhcpd built with '--enable-paranoia'. --- config.def.h | 3 +++ dyndhcpd.c | 58 +++++++++++++++++++++++++++++++++++------------ systemd/dyndhcpd@.service | 6 ++++- 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/config.def.h b/config.def.h index a21c4f8..f277236 100644 --- a/config.def.h +++ b/config.def.h @@ -22,6 +22,9 @@ #define PIDFILE "/run/dhcpd-%s.pid" #define LEASESFILE "/var/lib/dhcp/dhcp-%s.leases" +/* default user */ +#define USER "dhcp" + #define FALLBACKCONFIG \ "# fallback dhcpd.conf for interface __INTERFACE__\n" \ "# generated by dyndhcpd/__VERSION__\n" \ diff --git a/dyndhcpd.c b/dyndhcpd.c index 8d2ae0c..a3c205a 100644 --- a/dyndhcpd.c +++ b/dyndhcpd.c @@ -7,14 +7,18 @@ #include "dyndhcpd.h" -const static char optstring[] = "c:hi:vV"; +const static char optstring[] = "c:hi:l:p:u:vVw:"; const static struct option options_long[] = { /* name has_arg flag val */ { "config", required_argument, NULL, 'c' }, { "help", no_argument, NULL, 'h' }, { "interface", required_argument, NULL, 'i' }, + { "leases", required_argument, NULL, 'l' }, + { "pidfile", required_argument, NULL, 'p' }, + { "user", required_argument, NULL, 'u' }, { "verbose", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'V' }, + { "write-config", required_argument, NULL, 'w' }, { 0, 0, 0, 0 } }; @@ -53,7 +57,7 @@ int main(int argc, char ** argv) { char * configfilename = NULL; size_t fsize, length = 0; - char * pidfile = NULL, * leasesfile = NULL; + char * pidfile = NULL, * leasesfile = NULL, * username = NULL; unsigned int version = 0, help = 0; @@ -77,6 +81,15 @@ int main(int argc, char ** argv) { return EXIT_FAILURE; } break; + case 'l': + leasesfile = strdup(optarg); + break; + case 'p': + pidfile = strdup(optarg); + break; + case 'u': + username = optarg; + break; case 'v': verbose++; break; @@ -84,6 +97,9 @@ int main(int argc, char ** argv) { verbose++; version++; break; + case 'w': + configfilename = strdup(optarg); + break; } if (verbose > 0) @@ -263,10 +279,14 @@ int main(int argc, char ** argv) { config[length++] = 0; /* get new filename and open file for writing */ - configfilename = malloc(strlen(CONFIG_OUTPUT) + strlen(interface) + 1); - sprintf(configfilename, CONFIG_OUTPUT, interface); + if (configfilename == NULL) { + configfilename = malloc(strlen(CONFIG_OUTPUT) + strlen(interface) + 1); + sprintf(configfilename, CONFIG_OUTPUT, interface); + } + + /* try to open the config file for writing */ if ((configfile = fopen(configfilename, "w")) == NULL) { - fprintf(stderr, "Failed opening config file for writing.\n"); + fprintf(stderr, "Failed opening config file '%s' for writing.\n", configfilename); goto out; } @@ -274,26 +294,36 @@ int main(int argc, char ** argv) { fputs(config, configfile); fclose(configfile); - /* get names for pid and leases file */ - pidfile = malloc(strlen(PIDFILE) + strlen(interface) + 1); - sprintf(pidfile, PIDFILE, interface); - leasesfile = malloc(strlen(LEASESFILE) + strlen(interface) + 1); - sprintf(leasesfile, LEASESFILE, interface); + /* get name for pidfile */ + if (pidfile == NULL) { + pidfile = malloc(strlen(PIDFILE) + strlen(interface) + 1); + sprintf(pidfile, PIDFILE, interface); + } + + /* get name for leases file */ + if (leasesfile == NULL) { + leasesfile = malloc(strlen(LEASESFILE) + strlen(interface) + 1); + sprintf(leasesfile, LEASESFILE, interface); + } /* check if leases file exists, create it if it does not */ if (access(leasesfile, R_OK) == -1) { if (verbose) - printf("Creating leases file %s.\n", leasesfile); + printf("Creating leases file '%s'.\n", leasesfile); fclose(fopen(leasesfile, "w")); } + /* get use name */ + if (username == NULL) + username = USER; + /* execute dhcp daemon, replace the current process * dyndhcpd is cleared from memory here and code below is not execuded if * everything goes well */ if (verbose > 1) - printf("Running: dhcpd -f -q -4 -pf %s -lf %s -cf %s %s\n", - pidfile, leasesfile, configfilename, interface); - rc = execlp(DHCPDFILE, "dhcpd", "-f", "-q", "-4", + printf("Running: dhcpd -f -q -4 -user %s -pf %s -lf %s -cf %s %s\n", + username, pidfile, leasesfile, configfilename, interface); + rc = execlp(DHCPDFILE, "dhcpd", "-f", "-q", "-4", "-user", username, "-pf", pidfile, "-lf", leasesfile, "-cf", configfilename, interface, NULL); fprintf(stderr, "The dhcp daemon failed to execute.\n"); diff --git a/systemd/dyndhcpd@.service b/systemd/dyndhcpd@.service index 8aceeb1..25c93cd 100644 --- a/systemd/dyndhcpd@.service +++ b/systemd/dyndhcpd@.service @@ -5,7 +5,11 @@ Requires=sys-subsystem-net-devices-%i.device After=sys-subsystem-net-devices-%i.device [Service] -ExecStart=/usr/bin/dyndhcpd -i%i +ExecStart=!/usr/bin/dyndhcpd --interface %i --user %p-%i --pidfile /run/%p@%i/dhcpd.pid --leases /var/lib/%p@%i/dhcp.leases --write-config /run/%p@%i/dhcpd.conf +RuntimeDirectory=%p@%i +StateDirectory=%p@%i +User=%p-%i +DynamicUser=on ProtectSystem=full ProtectHome=on PrivateDevices=on -- cgit v1.2.3-54-g00ecf