diff options
author | ryadav-duo <ryadav@duosecurity.com> | 2016-03-07 14:55:59 -0500 |
---|---|---|
committer | ryadav-duo <ryadav@duosecurity.com> | 2016-03-07 14:55:59 -0500 |
commit | d21badfe74d70cbef012d67144a834e7754dfa4e (patch) | |
tree | 909679e87e651c49d9b342ff212a36d5c9910981 | |
parent | 4d3727c5aac0aa4e1053da4a15b798d1cd63614c (diff) | |
parent | 4a501dc306713e7b848c223564cd8acfa96f9483 (diff) | |
download | openvpn-duo-plugin-d21badfe74d70cbef012d67144a834e7754dfa4e.tar.gz openvpn-duo-plugin-d21badfe74d70cbef012d67144a834e7754dfa4e.zip |
Merge pull request #11 from petiepooo/fix-SIG_IGN
Fix SIG_CHLD issue causing all external scripts to fail
-rw-r--r-- | duo_openvpn.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/duo_openvpn.c b/duo_openvpn.c index f914ea4..f032645 100644 --- a/duo_openvpn.c +++ b/duo_openvpn.c @@ -1,3 +1,4 @@ +#include <sys/stat.h> #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -29,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) { @@ -50,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); @@ -60,18 +61,45 @@ 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; } if (pid > 0) { - return OPENVPN_PLUGIN_FUNC_DEFERRED; + 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) { + exit(OPENVPN_PLUGIN_FUNC_ERROR); + } + + if (pid > 0) { + /* first child forked ok, pass deferred return up to parent openvpn process */ + exit(OPENVPN_PLUGIN_FUNC_DEFERRED); + } + + /* second child daemonizes 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); @@ -115,7 +143,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]) { |