Merge branch 'tmp-fix-forking-behavior' into 'master'

fix ocserv's forking behavior

Closes #154

See merge request ocserv/ocserv!84
This commit is contained in:
Nikos Mavrogiannopoulos
2018-05-11 20:22:23 +00:00
9 changed files with 89 additions and 10 deletions

1
NEWS
View File

@@ -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.

View File

@@ -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);

View File

@@ -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",

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -378,6 +378,7 @@ struct perm_cfg_st {
unsigned int stats_reset_time;
unsigned foreground;
unsigned no_chdir;
unsigned debug;
char *ca;

View File

@@ -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

54
tests/test-fork Executable file
View File

@@ -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 <http://www.gnu.org/licenses/>
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