summaryrefslogtreecommitdiff
path: root/src/plugins/down-root/down-root.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/down-root/down-root.c')
-rw-r--r--src/plugins/down-root/down-root.c260
1 files changed, 144 insertions, 116 deletions
diff --git a/src/plugins/down-root/down-root.c b/src/plugins/down-root/down-root.c
index 6931bec..ae85ecb 100644
--- a/src/plugins/down-root/down-root.c
+++ b/src/plugins/down-root/down-root.c
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2002-2013 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net>
* Copyright (C) 2013 David Sommerseth <davids@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -59,7 +59,7 @@
#define RESPONSE_SCRIPT_FAILED 13
/* Background process function */
-static void down_root_server (const int fd, char * const * argv, char * const *envp, const int verb);
+static void down_root_server(const int fd, char *const *argv, char *const *envp, const int verb);
/*
* Plugin state, used by foreground
@@ -85,19 +85,21 @@ struct down_root_context
* if found or NULL otherwise.
*/
static const char *
-get_env (const char *name, const char *envp[])
+get_env(const char *name, const char *envp[])
{
if (envp)
{
int i;
- const int namelen = strlen (name);
+ const int namelen = strlen(name);
for (i = 0; envp[i]; ++i)
{
- if (!strncmp (envp[i], name, namelen))
+ if (!strncmp(envp[i], name, namelen))
{
const char *cp = envp[i] + namelen;
if (*cp == '=')
+ {
return cp + 1;
+ }
}
}
}
@@ -108,7 +110,7 @@ get_env (const char *name, const char *envp[])
* Return the length of a string array
*/
static int
-string_array_len (const char *array[])
+string_array_len(const char *array[])
{
int i = 0;
if (array)
@@ -124,25 +126,33 @@ string_array_len (const char *array[])
*/
static int
-recv_control (int fd)
+recv_control(int fd)
{
unsigned char c;
- const ssize_t size = read (fd, &c, sizeof (c));
- if (size == sizeof (c))
+ const ssize_t size = read(fd, &c, sizeof(c));
+ if (size == sizeof(c))
+ {
return c;
+ }
else
+ {
return -1;
+ }
}
static int
-send_control (int fd, int code)
+send_control(int fd, int code)
{
unsigned char c = (unsigned char) code;
- const ssize_t size = write (fd, &c, sizeof (c));
- if (size == sizeof (c))
+ const ssize_t size = write(fd, &c, sizeof(c));
+ if (size == sizeof(c))
+ {
return (int) size;
+ }
else
+ {
return -1;
+ }
}
/*
@@ -151,23 +161,25 @@ send_control (int fd, int code)
* "daemon_log_redirect" env var is true.
*/
static void
-daemonize (const char *envp[])
+daemonize(const char *envp[])
{
- const char *daemon_string = get_env ("daemon", envp);
+ const char *daemon_string = get_env("daemon", envp);
if (daemon_string && daemon_string[0] == '1')
{
- const char *log_redirect = get_env ("daemon_log_redirect", envp);
+ const char *log_redirect = get_env("daemon_log_redirect", envp);
int fd = -1;
if (log_redirect && log_redirect[0] == '1')
- fd = dup (2);
- if (daemon (0, 0) < 0)
{
- warn ("DOWN-ROOT: daemonization failed");
+ fd = dup(2);
+ }
+ if (daemon(0, 0) < 0)
+ {
+ warn("DOWN-ROOT: daemonization failed");
}
else if (fd >= 3)
{
- dup2 (fd, 2);
- close (fd);
+ dup2(fd, 2);
+ close(fd);
}
}
}
@@ -183,14 +195,16 @@ daemonize (const char *envp[])
* fds from crossing a fork().
*/
static void
-close_fds_except (int keep)
+close_fds_except(int keep)
{
int i;
- closelog ();
+ closelog();
for (i = 3; i <= 100; ++i)
{
if (i != keep)
- close (i);
+ {
+ close(i);
+ }
}
}
@@ -199,28 +213,28 @@ close_fds_except (int keep)
* deal with them.
*/
static void
-set_signals (void)
+set_signals(void)
{
- signal (SIGTERM, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
- signal (SIGINT, SIG_IGN);
- signal (SIGHUP, SIG_IGN);
- signal (SIGUSR1, SIG_IGN);
- signal (SIGUSR2, SIG_IGN);
- signal (SIGPIPE, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGUSR1, SIG_IGN);
+ signal(SIGUSR2, SIG_IGN);
+ signal(SIGPIPE, SIG_IGN);
}
static void
-free_context (struct down_root_context *context)
+free_context(struct down_root_context *context)
{
if (context)
{
if (context->command)
{
- free (context->command);
+ free(context->command);
}
- free (context);
+ free(context);
}
}
@@ -229,7 +243,7 @@ free_context (struct down_root_context *context)
* calling execve()
*/
static int
-run_script(char * const *argv, char * const *envp)
+run_script(char *const *argv, char *const *envp)
{
pid_t pid;
int ret = 0;
@@ -241,14 +255,14 @@ run_script(char * const *argv, char * const *envp)
/* If execve() fails to run, exit child with exit code 127 */
err(127, "DOWN-ROOT: Failed execute: %s", argv[0]);
}
- else if (pid < (pid_t)0 )
+ else if (pid < (pid_t)0)
{
- warn ("DOWN-ROOT: Failed to fork child to run %s", argv[0]);
+ warn("DOWN-ROOT: Failed to fork child to run %s", argv[0]);
return -1;
}
else /* parent side */
{
- if( waitpid (pid, &ret, 0) != pid )
+ if (waitpid(pid, &ret, 0) != pid)
{
/* waitpid does not return error information via errno */
fprintf(stderr, "DOWN-ROOT: waitpid() failed, don't know exit code of child (%s)\n", argv[0]);
@@ -259,7 +273,7 @@ run_script(char * const *argv, char * const *envp)
}
OPENVPN_EXPORT openvpn_plugin_handle_t
-openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[])
+openvpn_plugin_open_v1(unsigned int *type_mask, const char *argv[], const char *envp[])
{
struct down_root_context *context;
int i = 0;
@@ -267,10 +281,10 @@ openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char
/*
* Allocate our context
*/
- context = (struct down_root_context *) calloc (1, sizeof (struct down_root_context));
+ context = (struct down_root_context *) calloc(1, sizeof(struct down_root_context));
if (!context)
{
- warn ("DOWN-ROOT: Could not allocate memory for plug-in context");
+ warn("DOWN-ROOT: Could not allocate memory for plug-in context");
goto error;
}
context->foreground_fd = -1;
@@ -278,15 +292,15 @@ openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char
/*
* Intercept the --up and --down callbacks
*/
- *type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) | OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_DOWN);
+ *type_mask = OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_UP) | OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_DOWN);
/*
* Make sure we have two string arguments: the first is the .so name,
* the second is the script command.
*/
- if (string_array_len (argv) < 2)
+ if (string_array_len(argv) < 2)
{
- fprintf (stderr, "DOWN-ROOT: need down script command\n");
+ fprintf(stderr, "DOWN-ROOT: need down script command\n");
goto error;
}
@@ -296,7 +310,7 @@ openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char
context->command = calloc(string_array_len(argv), sizeof(char *));
if (!context->command)
{
- warn ("DOWN-ROOT: Could not allocate memory for command array");
+ warn("DOWN-ROOT: Could not allocate memory for command array");
goto error;
}
@@ -310,20 +324,22 @@ openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char
* Get verbosity level from environment
*/
{
- const char *verb_string = get_env ("verb", envp);
+ const char *verb_string = get_env("verb", envp);
if (verb_string)
- context->verb = atoi (verb_string);
+ {
+ context->verb = atoi(verb_string);
+ }
}
return (openvpn_plugin_handle_t) context;
error:
- free_context (context);
+ free_context(context);
return NULL;
}
OPENVPN_EXPORT int
-openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
+openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
{
struct down_root_context *context = (struct down_root_context *) handle;
@@ -336,9 +352,9 @@ openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const ch
* Make a socket for foreground and background processes
* to communicate.
*/
- if (socketpair (PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
+ if (socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
{
- warn ("DOWN-ROOT: socketpair call failed");
+ warn("DOWN-ROOT: socketpair call failed");
return OPENVPN_PLUGIN_FUNC_ERROR;
}
@@ -346,7 +362,7 @@ openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const ch
* Fork off the privileged process. It will remain privileged
* even after the foreground process drops its privileges.
*/
- pid = fork ();
+ pid = fork();
if (pid)
{
@@ -359,16 +375,16 @@ openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const ch
context->background_pid = pid;
/* close our copy of child's socket */
- close (fd[1]);
+ close(fd[1]);
/* don't let future subprocesses inherit child socket */
- if (fcntl (fd[0], F_SETFD, FD_CLOEXEC) < 0)
+ if (fcntl(fd[0], F_SETFD, FD_CLOEXEC) < 0)
{
- warn ("DOWN-ROOT: Set FD_CLOEXEC flag on socket file descriptor failed");
+ warn("DOWN-ROOT: Set FD_CLOEXEC flag on socket file descriptor failed");
}
/* wait for background child process to initialize */
- status = recv_control (fd[0]);
+ status = recv_control(fd[0]);
if (status == RESPONSE_INIT_SUCCEEDED)
{
context->foreground_fd = fd[0];
@@ -382,36 +398,38 @@ openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const ch
*/
/* close all parent fds except our socket back to parent */
- close_fds_except (fd[1]);
+ close_fds_except(fd[1]);
/* Ignore most signals (the parent will receive them) */
- set_signals ();
+ set_signals();
/* Daemonize if --daemon option is set. */
- daemonize (envp);
+ daemonize(envp);
/* execute the event loop */
- down_root_server (fd[1], context->command, (char * const *) envp, context->verb);
+ down_root_server(fd[1], context->command, (char *const *) envp, context->verb);
- close (fd[1]);
- exit (0);
+ close(fd[1]);
+ exit(0);
return 0; /* NOTREACHED */
}
}
else if (type == OPENVPN_PLUGIN_DOWN && context->foreground_fd >= 0)
{
- if (send_control (context->foreground_fd, COMMAND_RUN_SCRIPT) == -1)
+ if (send_control(context->foreground_fd, COMMAND_RUN_SCRIPT) == -1)
{
- warn ("DOWN-ROOT: Error sending script execution signal to background process");
+ warn("DOWN-ROOT: Error sending script execution signal to background process");
}
else
{
- const int status = recv_control (context->foreground_fd);
+ const int status = recv_control(context->foreground_fd);
if (status == RESPONSE_SCRIPT_SUCCEEDED)
+ {
return OPENVPN_PLUGIN_FUNC_SUCCESS;
+ }
if (status == -1)
{
- warn ("DOWN-ROOT: Error receiving script execution confirmation from background process");
+ warn("DOWN-ROOT: Error receiving script execution confirmation from background process");
}
}
}
@@ -419,42 +437,46 @@ openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const ch
}
OPENVPN_EXPORT void
-openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle)
+openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
{
struct down_root_context *context = (struct down_root_context *) handle;
- if (DEBUG (context->verb))
- fprintf (stderr, "DOWN-ROOT: close\n");
+ if (DEBUG(context->verb))
+ {
+ fprintf(stderr, "DOWN-ROOT: close\n");
+ }
if (context->foreground_fd >= 0)
{
/* tell background process to exit */
- if (send_control (context->foreground_fd, COMMAND_EXIT) == -1)
+ if (send_control(context->foreground_fd, COMMAND_EXIT) == -1)
{
- warn ("DOWN-ROOT: Error signalling background process to exit");
+ warn("DOWN-ROOT: Error signalling background process to exit");
}
/* wait for background process to exit */
if (context->background_pid > 0)
- waitpid (context->background_pid, NULL, 0);
+ {
+ waitpid(context->background_pid, NULL, 0);
+ }
- close (context->foreground_fd);
+ close(context->foreground_fd);
context->foreground_fd = -1;
}
- free_context (context);
+ free_context(context);
}
OPENVPN_EXPORT void
-openvpn_plugin_abort_v1 (openvpn_plugin_handle_t handle)
+openvpn_plugin_abort_v1(openvpn_plugin_handle_t handle)
{
struct down_root_context *context = (struct down_root_context *) handle;
if (context && context->foreground_fd >= 0)
{
/* tell background process to exit */
- send_control (context->foreground_fd, COMMAND_EXIT);
- close (context->foreground_fd);
+ send_control(context->foreground_fd, COMMAND_EXIT);
+ close(context->foreground_fd);
context->foreground_fd = -1;
}
}
@@ -463,20 +485,22 @@ openvpn_plugin_abort_v1 (openvpn_plugin_handle_t handle)
* Background process -- runs with privilege.
*/
static void
-down_root_server (const int fd, char * const *argv, char * const *envp, const int verb)
+down_root_server(const int fd, char *const *argv, char *const *envp, const int verb)
{
/*
* Do initialization
*/
- if (DEBUG (verb))
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: INIT command='%s'\n", argv[0]);
+ if (DEBUG(verb))
+ {
+ fprintf(stderr, "DOWN-ROOT: BACKGROUND: INIT command='%s'\n", argv[0]);
+ }
/*
* Tell foreground that we initialized successfully
*/
- if (send_control (fd, RESPONSE_INIT_SUCCEEDED) == -1)
+ if (send_control(fd, RESPONSE_INIT_SUCCEEDED) == -1)
{
- warn ("DOWN-ROOT: BACKGROUND: write error on response socket [1]");
+ warn("DOWN-ROOT: BACKGROUND: write error on response socket [1]");
goto done;
}
@@ -489,59 +513,63 @@ down_root_server (const int fd, char * const *argv, char * const *envp, const in
int exit_code = -1;
/* get a command from foreground process */
- command_code = recv_control (fd);
+ command_code = recv_control(fd);
- if (DEBUG (verb))
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: received command code: %d\n", command_code);
+ if (DEBUG(verb))
+ {
+ fprintf(stderr, "DOWN-ROOT: BACKGROUND: received command code: %d\n", command_code);
+ }
switch (command_code)
{
- case COMMAND_RUN_SCRIPT:
- if ( (exit_code = run_script(argv, envp)) == 0 ) /* Succeeded */
- {
- if (send_control (fd, RESPONSE_SCRIPT_SUCCEEDED) == -1)
+ case COMMAND_RUN_SCRIPT:
+ if ( (exit_code = run_script(argv, envp)) == 0) /* Succeeded */
{
- warn ("DOWN-ROOT: BACKGROUND: write error on response socket [2]");
- goto done;
+ if (send_control(fd, RESPONSE_SCRIPT_SUCCEEDED) == -1)
+ {
+ warn("DOWN-ROOT: BACKGROUND: write error on response socket [2]");
+ goto done;
+ }
}
- }
- else /* Failed */
- {
- fprintf(stderr, "DOWN-ROOT: BACKGROUND: %s exited with exit code %i\n", argv[0], exit_code);
- if (send_control (fd, RESPONSE_SCRIPT_FAILED) == -1)
+ else /* Failed */
{
- warn ("DOWN-ROOT: BACKGROUND: write error on response socket [3]");
- goto done;
+ fprintf(stderr, "DOWN-ROOT: BACKGROUND: %s exited with exit code %i\n", argv[0], exit_code);
+ if (send_control(fd, RESPONSE_SCRIPT_FAILED) == -1)
+ {
+ warn("DOWN-ROOT: BACKGROUND: write error on response socket [3]");
+ goto done;
+ }
}
- }
- break;
+ break;
- case COMMAND_EXIT:
- goto done;
+ case COMMAND_EXIT:
+ goto done;
- case -1:
- warn ("DOWN-ROOT: BACKGROUND: read error on command channel");
- goto done;
+ case -1:
+ warn("DOWN-ROOT: BACKGROUND: read error on command channel");
+ goto done;
- default:
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: unknown command code: code=%d, exiting\n",
- command_code);
- goto done;
+ default:
+ fprintf(stderr, "DOWN-ROOT: BACKGROUND: unknown command code: code=%d, exiting\n",
+ command_code);
+ goto done;
}
}
done:
- if (DEBUG (verb))
- fprintf (stderr, "DOWN-ROOT: BACKGROUND: EXIT\n");
+ if (DEBUG(verb))
+ {
+ fprintf(stderr, "DOWN-ROOT: BACKGROUND: EXIT\n");
+ }
return;
}
/*
-Local variables:
-c-file-style: "bsd"
-c-basic-offset: 4
-indent-tabs-mode: nil
-End:
-*/
+ * Local variables:
+ * c-file-style: "bsd"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */