summaryrefslogtreecommitdiffstats
path: root/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc.c')
-rw-r--r--misc.c76
1 files changed, 56 insertions, 20 deletions
diff --git a/misc.c b/misc.c
index f5a3b89..94e9efe 100644
--- a/misc.c
+++ b/misc.c
@@ -156,9 +156,8 @@ set_nice (int niceval)
{
#ifdef HAVE_NICE
errno = 0;
- nice (niceval);
- if (errno != 0)
- msg (M_WARN | M_ERRNO, "WARNING: nice %d failed", niceval);
+ if (nice (niceval) < 0 && errno != 0)
+ msg (M_WARN | M_ERRNO, "WARNING: nice %d failed: %s", niceval, strerror(errno));
else
msg (M_INFO, "nice %d succeeded", niceval);
#else
@@ -231,7 +230,7 @@ run_up_down (const char *command,
ifconfig_local, ifconfig_remote,
context);
argv_msg (M_INFO, &argv);
- openvpn_execve_check (&argv, es, S_SCRIPT|S_FATAL, "script failed");
+ openvpn_run_script (&argv, es, S_FATAL, "--up/--down");
argv_reset (&argv);
}
@@ -494,6 +493,7 @@ openvpn_execve_allowed (const unsigned int flags)
return script_security >= SSEC_BUILT_IN;
}
+
#ifndef WIN32
/*
* Run execve() inside a fork(). Designed to replicate the semantics of system() but
@@ -505,6 +505,7 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
{
struct gc_arena gc = gc_new ();
int ret = -1;
+ static bool warn_shown = false;
if (a && a->argv[0])
{
@@ -541,9 +542,10 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i
ASSERT (0);
}
}
- else
+ else if (!warn_shown && (script_security < SSEC_SCRIPTS))
{
msg (M_WARN, SCRIPT_SECURITY_WARNING);
+ warn_shown = true;
}
#else
msg (M_WARN, "openvpn_execve: execve function not available");
@@ -1166,25 +1168,57 @@ test_file (const char *filename)
/* create a temporary filename in directory */
const char *
-create_temp_filename (const char *directory, const char *prefix, struct gc_arena *gc)
+create_temp_file (const char *directory, const char *prefix, struct gc_arena *gc)
{
static unsigned int counter;
struct buffer fname = alloc_buf_gc (256, gc);
+ int fd;
+ const char *retfname = NULL;
+ unsigned int attempts = 0;
- mutex_lock_static (L_CREATE_TEMP);
- ++counter;
- mutex_unlock_static (L_CREATE_TEMP);
-
- {
- uint8_t rndbytes[16];
- const char *rndstr;
-
- prng_bytes (rndbytes, sizeof (rndbytes));
- rndstr = format_hex_ex (rndbytes, sizeof (rndbytes), 40, 0, NULL, gc);
- buf_printf (&fname, PACKAGE "_%s_%s.tmp", prefix, rndstr);
- }
+ do
+ {
+ uint8_t rndbytes[16];
+ const char *rndstr;
+
+ ++attempts;
+ mutex_lock_static (L_CREATE_TEMP);
+ ++counter;
+ mutex_unlock_static (L_CREATE_TEMP);
+
+ prng_bytes (rndbytes, sizeof rndbytes);
+ rndstr = format_hex_ex (rndbytes, sizeof rndbytes, 40, 0, NULL, gc);
+ buf_printf (&fname, PACKAGE "_%s_%s.tmp", prefix, rndstr);
+
+ retfname = gen_path (directory, BSTR (&fname), gc);
+ if (!retfname)
+ {
+ msg (M_FATAL, "Failed to create temporary filename and path");
+ return NULL;
+ }
+
+ /* Atomically create the file. Errors out if the file already
+ exists. */
+ fd = open (retfname, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
+ if (fd != -1)
+ {
+ close (fd);
+ return retfname;
+ }
+ else if (fd == -1 && errno != EEXIST)
+ {
+ /* Something else went wrong, no need to retry. */
+ struct gc_arena gcerr = gc_new ();
+ msg (M_FATAL, "Could not create temporary file '%s': %s",
+ retfname, strerror_ts (errno, &gcerr));
+ gc_free (&gcerr);
+ return NULL;
+ }
+ }
+ while (attempts < 6);
- return gen_path (directory, BSTR (&fname), gc);
+ msg (M_FATAL, "Failed to create temporary file after %i attempts", attempts);
+ return NULL;
}
/*
@@ -1684,14 +1718,16 @@ void
purge_user_pass (struct user_pass *up, const bool force)
{
const bool nocache = up->nocache;
+ static bool warn_shown = false;
if (nocache || force)
{
CLEAR (*up);
up->nocache = nocache;
}
- else
+ else if (!warn_shown)
{
msg (M_WARN, "WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this");
+ warn_shown = true;
}
}