summaryrefslogtreecommitdiff
path: root/src/openvpn/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/misc.c')
-rw-r--r--src/openvpn/misc.c93
1 files changed, 56 insertions, 37 deletions
diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c
index 581a890..f44c65f 100644
--- a/src/openvpn/misc.c
+++ b/src/openvpn/misc.c
@@ -99,44 +99,57 @@ save_inetd_socket_descriptor(void)
}
/*
- * Print an error message based on the status code returned by system().
+ * Generate an error message based on the status code returned by openvpn_execve().
*/
const char *
system_error_message(int stat, struct gc_arena *gc)
{
struct buffer out = alloc_buf_gc(256, gc);
-#ifdef _WIN32
- if (stat == -1)
+
+ switch (stat)
{
- buf_printf(&out, "external program did not execute -- ");
- }
- buf_printf(&out, "returned error code %d", stat);
+ case OPENVPN_EXECVE_NOT_ALLOWED:
+ buf_printf(&out, "disallowed by script-security setting");
+ break;
+
+#ifdef _WIN32
+ case OPENVPN_EXECVE_ERROR:
+ buf_printf(&out, "external program did not execute -- ");
+ /* fall through */
+
+ default:
+ buf_printf(&out, "returned error code %d", stat);
+ break;
#else /* ifdef _WIN32 */
- if (stat == -1)
- {
- buf_printf(&out, "external program fork failed");
- }
- else if (!WIFEXITED(stat))
- {
- buf_printf(&out, "external program did not exit normally");
- }
- else
- {
- const int cmd_ret = WEXITSTATUS(stat);
- if (!cmd_ret)
- {
- buf_printf(&out, "external program exited normally");
- }
- else if (cmd_ret == 127)
- {
- buf_printf(&out, "could not execute external program");
- }
- else
- {
- buf_printf(&out, "external program exited with error status: %d", cmd_ret);
- }
- }
+
+ case OPENVPN_EXECVE_ERROR:
+ buf_printf(&out, "external program fork failed");
+ break;
+
+ default:
+ if (!WIFEXITED(stat))
+ {
+ buf_printf(&out, "external program did not exit normally");
+ }
+ else
+ {
+ const int cmd_ret = WEXITSTATUS(stat);
+ if (!cmd_ret)
+ {
+ buf_printf(&out, "external program exited normally");
+ }
+ else if (cmd_ret == OPENVPN_EXECVE_FAILURE)
+ {
+ buf_printf(&out, "could not execute external program");
+ }
+ else
+ {
+ buf_printf(&out, "external program exited with error status: %d", cmd_ret);
+ }
+ }
+ break;
#endif /* ifdef _WIN32 */
+ }
return (const char *)out.data;
}
@@ -186,12 +199,14 @@ openvpn_execve_allowed(const unsigned int flags)
* Run execve() inside a fork(). Designed to replicate the semantics of system() but
* in a safer way that doesn't require the invocation of a shell or the risks
* assocated with formatting and parsing a command line.
+ * Returns the exit status of child, OPENVPN_EXECVE_NOT_ALLOWED if openvpn_execve_allowed()
+ * returns false, or OPENVPN_EXECVE_ERROR on other errors.
*/
int
openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags)
{
struct gc_arena gc = gc_new();
- int ret = -1;
+ int ret = OPENVPN_EXECVE_ERROR;
static bool warn_shown = false;
if (a && a->argv[0])
@@ -208,7 +223,7 @@ openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned in
if (pid == (pid_t)0) /* child side */
{
execve(cmd, argv, envp);
- exit(127);
+ exit(OPENVPN_EXECVE_FAILURE);
}
else if (pid < (pid_t)0) /* fork failed */
{
@@ -218,14 +233,18 @@ openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned in
{
if (waitpid(pid, &ret, 0) != pid)
{
- ret = -1;
+ ret = OPENVPN_EXECVE_ERROR;
}
}
}
- else if (!warn_shown && (script_security < SSEC_SCRIPTS))
+ else
{
- msg(M_WARN, SCRIPT_SECURITY_WARNING);
- warn_shown = true;
+ ret = OPENVPN_EXECVE_NOT_ALLOWED;
+ if (!warn_shown && (script_security < SSEC_SCRIPTS))
+ {
+ msg(M_WARN, SCRIPT_SECURITY_WARNING);
+ warn_shown = true;
+ }
}
#else /* if defined(ENABLE_FEATURE_EXECVE) */
msg(M_WARN, "openvpn_execve: execve function not available");
@@ -272,7 +291,7 @@ openvpn_popen(const struct argv *a, const struct env_set *es)
close(pipe_stdout[0]); /* Close read end */
dup2(pipe_stdout[1],1);
execve(cmd, argv, envp);
- exit(127);
+ exit(OPENVPN_EXECVE_FAILURE);
}
else if (pid > (pid_t)0) /* parent side */
{