From 579d99ee39d918269afcc4b4208b6f121e97f0aa Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Thu, 10 May 2018 20:03:08 +0200 Subject: [PATCH 1/2] ocserv: added the --no-chdir command line option This allows running on the background but without changing the current directory. Signed-off-by: Nikos Mavrogiannopoulos --- src/config.c | 6 ++++++ src/main.c | 2 +- src/vpn.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 5bda2e73..becf5ec3 100644 --- a/src/config.c +++ b/src/config.c @@ -1371,12 +1371,14 @@ static void check_cfg(vhost_cfg_st *vhost, vhost_cfg_st *defvhost, unsigned sile } +#define OPT_NO_CHDIR 1 static const struct option long_options[] = { {"debug", 1, 0, 'd'}, {"config", 1, 0, 'c'}, {"pid-file", 1, 0, 'p'}, {"test-config", 0, 0, 't'}, {"foreground", 0, 0, 'f'}, + {"no-chdir", 0, 0, OPT_NO_CHDIR}, {"help", 0, 0, 'h'}, {"version", 0, 0, 'v'}, {NULL, 0, 0, 0} @@ -1395,6 +1397,7 @@ void usage(void) fprintf(stderr, " -c, --config=file Configuration file for the server\n"); fprintf(stderr, " - file must exist\n"); fprintf(stderr, " -t, --test-config Test the provided configuration file\n"); + fprintf(stderr, " --no-chdir Do not perform a chdir on daemonize\n"); fprintf(stderr, " -p, --pid-file=file Specify pid file for the server\n"); fprintf(stderr, " -v, --version output version information and exit\n"); fprintf(stderr, " -h, --help display extended usage information and exit\n\n"); @@ -1435,6 +1438,9 @@ int cmd_parser (void *pool, int argc, char **argv, struct list_head *head) case 't': test_only = 1; break; + case OPT_NO_CHDIR: + vhost->perm_config.no_chdir = 1; + break; case 'h': usage(); exit(0); diff --git a/src/main.c b/src/main.c index cb473752..9f6d9545 100644 --- a/src/main.c +++ b/src/main.c @@ -1345,7 +1345,7 @@ int main(int argc, char** argv) #endif if (GETPCONFIG(s)->foreground == 0) { - if (daemon(0, 0) == -1) { + if (daemon(GETPCONFIG(s)->no_chdir, 0) == -1) { e = errno; fprintf(stderr, "daemon failed: %s\n", strerror(e)); exit(1); diff --git a/src/vpn.h b/src/vpn.h index 92201396..29acba97 100644 --- a/src/vpn.h +++ b/src/vpn.h @@ -378,6 +378,7 @@ struct perm_cfg_st { unsigned int stats_reset_time; unsigned foreground; + unsigned no_chdir; unsigned debug; char *ca; From 807ce345de41b2969ba76ef31812cc9beded7249 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Thu, 10 May 2018 19:38:50 +0200 Subject: [PATCH 2/2] main: create a sec-mod socket file independent of pid That addresses the issue of not being able to run under systemd, or under non-forking mode. Added test case to detect proper operation. Resolves #154 Signed-off-by: Nikos Mavrogiannopoulos --- NEWS | 1 + src/main-sec-mod-cmd.c | 27 +++++++++++++++++---- src/main.h | 2 +- src/tlslib.c | 2 +- tests/data/test1.config | 4 +-- tests/test-fork | 54 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 81 insertions(+), 9 deletions(-) create mode 100755 tests/test-fork diff --git a/NEWS b/NEWS index e8aada58..eefa7e33 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,5 @@ * Version 0.12.1 (unreleased) +- Fixed crash on initialization when server was running on background. - Reject compilation on systems which have gnutls with a broken gnutls_certificate_set_key(). Provide a configure option (--with-broken-gnutls) which work-arounds the issues at the cost of a memory leak. diff --git a/src/main-sec-mod-cmd.c b/src/main-sec-mod-cmd.c index 95a0eacc..7bfbb99b 100644 --- a/src/main-sec-mod-cmd.c +++ b/src/main-sec-mod-cmd.c @@ -693,11 +693,26 @@ int secmod_reload(main_server_st * s) return 0; } -void secmod_socket_file_name(struct perm_cfg_st *perm_config, char *name, unsigned max_name_size) +/* Creates a permanent filename to use for secmod to main communication + */ +const char *secmod_socket_file_name(struct perm_cfg_st *perm_config) { - /* make socket name and full socket name */ - snprintf(name, max_name_size, "%s.%u", - perm_config->socket_file_prefix, (unsigned)getpid()); + unsigned int rnd; + int ret; + static char socket_file[_POSIX_PATH_MAX] = {0}; + + if (socket_file[0] != 0) + return socket_file; + + ret = gnutls_rnd(GNUTLS_RND_NONCE, &rnd, sizeof(rnd)); + if (ret < 0) + exit(1); + + /* make socket name */ + snprintf(socket_file, sizeof(socket_file), "%s.%x", + perm_config->socket_file_prefix, rnd); + + return socket_file; } static void clear_unneeded_mem(struct list_head *vconfig) @@ -721,7 +736,9 @@ int run_sec_mod(main_server_st *s, int *sync_fd) pid_t pid; const char *p; - secmod_socket_file_name(GETPCONFIG(s), s->socket_file, sizeof(s->socket_file)); + /* fills s->socket_file */ + strlcpy(s->socket_file, secmod_socket_file_name(GETPCONFIG(s)), sizeof(s->socket_file)); + mslog(s, NULL, LOG_DEBUG, "created sec-mod socket file (%s)", s->socket_file); if (GETPCONFIG(s)->chroot_dir != NULL) { ret = snprintf(s->full_socket_file, sizeof(s->full_socket_file), "%s/%s", diff --git a/src/main.h b/src/main.h index 827f8d6b..3df9ca74 100644 --- a/src/main.h +++ b/src/main.h @@ -348,7 +348,7 @@ int send_socket_msg_to_worker(main_server_st* s, struct proc_st* proc, uint8_t c int secmod_reload(main_server_st * s); -void secmod_socket_file_name(struct perm_cfg_st *perm_config, char *name, unsigned max_name_size); +const char *secmod_socket_file_name(struct perm_cfg_st *perm_config); void clear_vhosts(struct list_head *head); void request_reload(int signo); diff --git a/src/tlslib.c b/src/tlslib.c index 904a2869..6b2429b1 100644 --- a/src/tlslib.c +++ b/src/tlslib.c @@ -857,7 +857,7 @@ int load_cert_files(main_server_st *s, struct vhost_cfg_st *vhost) /* when called here configuration may not be populated, so avoid using it */ cdata->sa.sun_family = AF_UNIX; - secmod_socket_file_name(&vhost->perm_config, cdata->sa.sun_path, sizeof(cdata->sa.sun_path)); + strlcpy(cdata->sa.sun_path, secmod_socket_file_name(&vhost->perm_config), sizeof(cdata->sa.sun_path)); cdata->sa_len = SUN_LEN(&cdata->sa); diff --git a/tests/data/test1.config b/tests/data/test1.config index 89aa07bf..42ee3e29 100644 --- a/tests/data/test1.config +++ b/tests/data/test1.config @@ -28,8 +28,8 @@ max-clients = 16 max-same-clients = 2 # TCP and UDP port number -tcp-port = 4444 -udp-port = 4444 +tcp-port = @PORT@ +udp-port = @PORT@ # Keepalive in seconds keepalive = 32400 diff --git a/tests/test-fork b/tests/test-fork new file mode 100755 index 00000000..e027e138 --- /dev/null +++ b/tests/test-fork @@ -0,0 +1,54 @@ +#!/bin/sh +# +# Copyright (C) 2018 Red Hat, Inc. +# +# This file is part of ocserv. +# +# ocserv is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at +# your option) any later version. +# +# ocserv is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see + +SERV="${SERV:-../src/ocserv}" +srcdir=${srcdir:-.} +NO_NEED_ROOT=1 +PORT=4432 +PIDFILE=ocserv-pid.$$.tmp + +. `dirname $0`/common.sh + +echo "Testing operation when run on background..." + +update_config test1.config +launch_simple_sr_server -d 1 -p ${PIDFILE} --no-chdir -c ${CONFIG} + +sleep 3 + +PID=$(cat ${PIDFILE}) +if test -z "${PID}";then + echo "server did not start" + exit 1 +fi + +echo "Server started with PID $PID..." + +echo "Connecting to obtain cookie..." +( echo "test" | LD_PRELOAD=libsocket_wrapper.so $OPENCONNECT -q $ADDRESS:$PORT -u test --servercert=d66b507ae074d03b02eafca40d35f87dd81049d3 --cookieonly ) || + fail $PID "Could not receive cookie from server" + +if ! test -f ${PIDFILE};then + fail $PID "Could not find pid file ${PIDFILE}" +fi + + +cleanup + +exit 0