From 9b44153d201d5be72d3ad3df4a3b5e73d935cfd1 Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Thu, 11 Feb 2016 09:50:45 -0500 Subject: fix issue with SIG_CHLD being ignored By just ignoring SIG_CHLD, loading this plugin breaks any external script usage in openvpn. A better solution to preventing zombies is to daemonize the spawned child and let init/systemd clean it up. --- duo_openvpn.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/duo_openvpn.c b/duo_openvpn.c index f914ea4..1f37947 100644 --- a/duo_openvpn.c +++ b/duo_openvpn.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -60,9 +61,6 @@ auth_user_pass_verify(struct context *ctx, const char *args[], const char *envp[ return OPENVPN_PLUGIN_FUNC_ERROR; } - /* prevent leaving behind zombies */ - signal(SIGCHLD, SIG_IGN); - pid = fork(); if (pid < 0) { return OPENVPN_PLUGIN_FUNC_ERROR; @@ -71,7 +69,15 @@ auth_user_pass_verify(struct context *ctx, const char *args[], const char *envp[ if (pid > 0) { return OPENVPN_PLUGIN_FUNC_DEFERRED; } - + + /* daemonize so PID 1 can reap */ + umask(0); + setsid(); + chdir("/"); + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + if (ctx->ikey && ctx->skey && ctx->host) { setenv("ikey", ctx->ikey, 1); setenv("skey", ctx->skey, 1); -- cgit v1.2.3 From 0de3b331ec8daceb9f3785baeb7301b3df688087 Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Thu, 11 Feb 2016 09:52:02 -0500 Subject: whitespace only: remove trailing tabs --- duo_openvpn.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/duo_openvpn.c b/duo_openvpn.c index 1f37947..d7db313 100644 --- a/duo_openvpn.c +++ b/duo_openvpn.c @@ -30,7 +30,7 @@ get_env(const char *name, const char *envp[]) { int i, namelen; const char *cp; - + if (envp) { namelen = strlen(name); for (i = 0; envp[i]; ++i) { @@ -51,7 +51,7 @@ auth_user_pass_verify(struct context *ctx, const char *args[], const char *envp[ int pid; const char *control, *username, *password, *ipaddr; char *argv[] = { INTERPRETER, DUO_SCRIPT_PATH, NULL }; - + control = get_env("auth_control_file", envp); username = get_env("common_name", envp); password = get_env("password", envp); @@ -121,7 +121,7 @@ OPENVPN_EXPORT openvpn_plugin_handle_t openvpn_plugin_open_v2(unsigned int *type_mask, const char *argv[], const char *envp[], struct openvpn_plugin_string_list **return_list) { struct context *ctx; - + ctx = (struct context *) calloc(1, sizeof(struct context)); if (argv[1] && argv[2] && argv[3]) { -- cgit v1.2.3 From 792fa6373244c732d97ff69799b7739326774784 Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Thu, 11 Feb 2016 19:03:59 -0500 Subject: add second fork for proper daemonize --- duo_openvpn.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/duo_openvpn.c b/duo_openvpn.c index d7db313..b4ba6eb 100644 --- a/duo_openvpn.c +++ b/duo_openvpn.c @@ -67,10 +67,32 @@ auth_user_pass_verify(struct context *ctx, const char *args[], const char *envp[ } if (pid > 0) { + int status; + + /* openvpn process forked ok, wait for first child to exit and return its status */ + pid = waitpid(pid, &status, 0); + if (pid < 0) { + return OPENVPN_PLUGIN_FUNC_ERROR; + } + + if (WIFEXITED(status)) { + return WEXITSTATUS(status); + } + + return OPENVPN_PLUGIN_FUNC_ERROR; + } + + pid = fork(); + if (pid < 0) { + return OPENVPN_PLUGIN_FUNC_ERROR; + } + + if (pid > 0) { + /* first child forked ok, pass deferred return up to parent openvpn process */ return OPENVPN_PLUGIN_FUNC_DEFERRED; } - /* daemonize so PID 1 can reap */ + /* second child daemonizes so PID 1 can reap */ umask(0); setsid(); chdir("/"); -- cgit v1.2.3 From 4a501dc306713e7b848c223564cd8acfa96f9483 Mon Sep 17 00:00:00 2001 From: Pete Nelson Date: Mon, 15 Feb 2016 10:10:06 -0500 Subject: replace returns with esits for first child --- duo_openvpn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/duo_openvpn.c b/duo_openvpn.c index b4ba6eb..f032645 100644 --- a/duo_openvpn.c +++ b/duo_openvpn.c @@ -84,12 +84,12 @@ auth_user_pass_verify(struct context *ctx, const char *args[], const char *envp[ pid = fork(); if (pid < 0) { - return OPENVPN_PLUGIN_FUNC_ERROR; + exit(OPENVPN_PLUGIN_FUNC_ERROR); } if (pid > 0) { /* first child forked ok, pass deferred return up to parent openvpn process */ - return OPENVPN_PLUGIN_FUNC_DEFERRED; + exit(OPENVPN_PLUGIN_FUNC_DEFERRED); } /* second child daemonizes so PID 1 can reap */ -- cgit v1.2.3