mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-05-28 04:03:29 -04:00
build: move wrappers into platform module
+ Some fixups within the platform.c functions. - need to check environment set on Windows. Signed-off-by: Alon Bar-Lev <alon.barlev@gmail.com> Acked-by: Gert Doering <gert@greenie.muc.de> Signed-off-by: David Sommerseth <davids@redhat.com>
This commit is contained in:
parent
72c7b12cb6
commit
14a131ac1c
23 changed files with 584 additions and 468 deletions
|
|
@ -58,6 +58,7 @@ openvpn_SOURCES = \
|
|||
mbuf.c mbuf.h \
|
||||
memdbg.h \
|
||||
misc.c misc.h \
|
||||
platform.c platform.h \
|
||||
console.c console.h \
|
||||
mroute.c mroute.h \
|
||||
mss.c mss.h \
|
||||
|
|
|
|||
|
|
@ -1080,7 +1080,7 @@ buffer_list_advance (struct buffer_list *ol, int n)
|
|||
struct buffer_list *
|
||||
buffer_list_file (const char *fn, int max_line_len)
|
||||
{
|
||||
FILE *fp = openvpn_fopen (fn, "r");
|
||||
FILE *fp = platform_fopen (fn, "r");
|
||||
struct buffer_list *bl = NULL;
|
||||
|
||||
if (fp)
|
||||
|
|
|
|||
|
|
@ -868,7 +868,7 @@ read_key_file (struct key2 *key2, const char *file, const unsigned int flags)
|
|||
#endif
|
||||
{
|
||||
in = alloc_buf_gc (2048, &gc);
|
||||
fd = openvpn_open (file, O_RDONLY, 0);
|
||||
fd = platform_open (file, O_RDONLY, 0);
|
||||
if (fd == -1)
|
||||
msg (M_ERR, "Cannot open file key file '%s'", file);
|
||||
size = read (fd, in.data, in.capacity);
|
||||
|
|
@ -1029,7 +1029,7 @@ read_passphrase_hash (const char *passphrase_file,
|
|||
const int min_passphrase_size = 8;
|
||||
uint8_t buf[64];
|
||||
int total_size = 0;
|
||||
int fd = openvpn_open (passphrase_file, O_RDONLY, 0);
|
||||
int fd = platform_open (passphrase_file, O_RDONLY, 0);
|
||||
|
||||
if (fd == -1)
|
||||
msg (M_ERR, "Cannot open passphrase file: '%s'", passphrase_file);
|
||||
|
|
@ -1079,7 +1079,7 @@ write_key_file (const int nkeys, const char *filename)
|
|||
const int bytes_per_line = 16;
|
||||
|
||||
/* open key file */
|
||||
fd = openvpn_open (filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
|
||||
fd = platform_open (filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
|
||||
|
||||
if (fd == -1)
|
||||
msg (M_ERR, "Cannot open shared secret file '%s' for write", filename);
|
||||
|
|
|
|||
|
|
@ -640,7 +640,7 @@ x_check_status (int status,
|
|||
my_errno);
|
||||
|
||||
if (x_cs_err_delay_ms)
|
||||
sleep_milliseconds (x_cs_err_delay_ms);
|
||||
platform_sleep_milliseconds (x_cs_err_delay_ms);
|
||||
}
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -935,7 +935,7 @@ do_genkey (const struct options * options)
|
|||
"shared secret output file (--secret)");
|
||||
|
||||
if (options->mlock) /* should we disable paging? */
|
||||
do_mlockall (true);
|
||||
platform_mlockall (true);
|
||||
|
||||
nbits_written = write_key_file (2, options->shared_secret_file);
|
||||
|
||||
|
|
@ -1022,7 +1022,7 @@ do_uid_gid_chroot (struct context *c, bool no_delay)
|
|||
if (c->options.chroot_dir)
|
||||
{
|
||||
if (no_delay)
|
||||
do_chroot (c->options.chroot_dir);
|
||||
platform_chroot (c->options.chroot_dir);
|
||||
else
|
||||
msg (M_INFO, "NOTE: chroot %s", why_not);
|
||||
}
|
||||
|
|
@ -1030,8 +1030,8 @@ do_uid_gid_chroot (struct context *c, bool no_delay)
|
|||
/* set user and/or group that we want to setuid/setgid to */
|
||||
if (no_delay)
|
||||
{
|
||||
set_group (&c0->group_state);
|
||||
set_user (&c0->user_state);
|
||||
platform_group_set (&c0->platform_state_group);
|
||||
platform_user_set (&c0->platform_state_user);
|
||||
c0->uid_gid_set = true;
|
||||
}
|
||||
else if (c0->uid_gid_specified)
|
||||
|
|
@ -2780,8 +2780,8 @@ do_init_first_time (struct context *c)
|
|||
|
||||
/* get user and/or group that we want to setuid/setgid to */
|
||||
c0->uid_gid_specified =
|
||||
get_group (c->options.groupname, &c0->group_state) |
|
||||
get_user (c->options.username, &c0->user_state);
|
||||
platform_group_get (c->options.groupname, &c0->platform_state_group) |
|
||||
platform_user_get (c->options.username, &c0->platform_state_user);
|
||||
|
||||
/* get --writepid file descriptor */
|
||||
get_pid_file (c->options.writepid, &c0->pid_state);
|
||||
|
|
@ -2791,13 +2791,13 @@ do_init_first_time (struct context *c)
|
|||
|
||||
/* should we disable paging? */
|
||||
if (c->options.mlock && c->did_we_daemonize)
|
||||
do_mlockall (true); /* call again in case we daemonized */
|
||||
platform_mlockall (true); /* call again in case we daemonized */
|
||||
|
||||
/* save process ID in a file */
|
||||
write_pid (&c0->pid_state);
|
||||
|
||||
/* should we change scheduling priority? */
|
||||
set_nice (c->options.nice);
|
||||
platform_nice (c->options.nice);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3342,7 +3342,7 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
|
|||
|
||||
/* should we disable paging? */
|
||||
if (c->first_time && options->mlock)
|
||||
do_mlockall (true);
|
||||
platform_mlockall (true);
|
||||
|
||||
#if P2MP
|
||||
/* get passwords if undefined */
|
||||
|
|
|
|||
|
|
@ -1146,7 +1146,7 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
|
|||
}
|
||||
else if (streq (p[0], "pid"))
|
||||
{
|
||||
msg (M_CLIENT, "SUCCESS: pid=%d", openvpn_getpid ());
|
||||
msg (M_CLIENT, "SUCCESS: pid=%d", platform_getpid ());
|
||||
}
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
else if (streq (p[0], "nclients"))
|
||||
|
|
@ -1429,7 +1429,7 @@ man_record_peer_info (struct management *man)
|
|||
{
|
||||
const in_addr_t a = ntohl (addr.sin_addr.s_addr);
|
||||
const int p = ntohs (addr.sin_port);
|
||||
FILE *fp = openvpn_fopen (man->settings.write_peer_info_file, "w");
|
||||
FILE *fp = platform_fopen (man->settings.write_peer_info_file, "w");
|
||||
if (fp)
|
||||
{
|
||||
fprintf (fp, "%s\n%d\n", print_in_addr_t (a, 0, &gc), p);
|
||||
|
|
@ -2013,17 +2013,17 @@ man_settings_init (struct man_settings *ms,
|
|||
*/
|
||||
if (client_user)
|
||||
{
|
||||
struct user_state s;
|
||||
get_user (client_user, &s);
|
||||
ms->client_uid = user_state_uid (&s);
|
||||
struct platform_state_user s;
|
||||
platform_user_get (client_user, &s);
|
||||
ms->client_uid = platform_state_user_uid (&s);
|
||||
msg (D_MANAGEMENT, "MANAGEMENT: client_uid=%d", ms->client_uid);
|
||||
ASSERT (ms->client_uid >= 0);
|
||||
}
|
||||
if (client_group)
|
||||
{
|
||||
struct group_state s;
|
||||
get_group (client_group, &s);
|
||||
ms->client_gid = group_state_gid (&s);
|
||||
struct platform_state_group s;
|
||||
platform_group_get (client_group, &s);
|
||||
ms->client_gid = platform_state_group_gid (&s);
|
||||
msg (D_MANAGEMENT, "MANAGEMENT: client_gid=%d", ms->client_gid);
|
||||
ASSERT (ms->client_gid >= 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,122 +56,6 @@ int script_security = SSEC_BUILT_IN; /* GLOBAL */
|
|||
/* contains SM_x value defined in misc.h */
|
||||
int script_method = SM_EXECVE; /* GLOBAL */
|
||||
|
||||
/* Redefine the top level directory of the filesystem
|
||||
to restrict access to files for security */
|
||||
void
|
||||
do_chroot (const char *path)
|
||||
{
|
||||
if (path)
|
||||
{
|
||||
#ifdef HAVE_CHROOT
|
||||
const char *top = "/";
|
||||
if (chroot (path))
|
||||
msg (M_ERR, "chroot to '%s' failed", path);
|
||||
if (openvpn_chdir (top))
|
||||
msg (M_ERR, "cd to '%s' failed", top);
|
||||
msg (M_INFO, "chroot to '%s' and cd to '%s' succeeded", path, top);
|
||||
#else
|
||||
msg (M_FATAL, "Sorry but I can't chroot to '%s' because this operating system doesn't appear to support the chroot() system call", path);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Get/Set UID of process */
|
||||
|
||||
bool
|
||||
get_user (const char *username, struct user_state *state)
|
||||
{
|
||||
bool ret = false;
|
||||
CLEAR (*state);
|
||||
if (username)
|
||||
{
|
||||
#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
|
||||
state->pw = getpwnam (username);
|
||||
if (!state->pw)
|
||||
msg (M_ERR, "failed to find UID for user %s", username);
|
||||
state->username = username;
|
||||
ret = true;
|
||||
#else
|
||||
msg (M_FATAL, "cannot get UID for user %s -- platform lacks getpwname() or setuid() system calls", username);
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
set_user (const struct user_state *state)
|
||||
{
|
||||
#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
|
||||
if (state->username && state->pw)
|
||||
{
|
||||
if (setuid (state->pw->pw_uid))
|
||||
msg (M_ERR, "setuid('%s') failed", state->username);
|
||||
msg (M_INFO, "UID set to %s", state->username);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Get/Set GID of process */
|
||||
|
||||
bool
|
||||
get_group (const char *groupname, struct group_state *state)
|
||||
{
|
||||
bool ret = false;
|
||||
CLEAR (*state);
|
||||
if (groupname)
|
||||
{
|
||||
#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
|
||||
state->gr = getgrnam (groupname);
|
||||
if (!state->gr)
|
||||
msg (M_ERR, "failed to find GID for group %s", groupname);
|
||||
state->groupname = groupname;
|
||||
ret = true;
|
||||
#else
|
||||
msg (M_FATAL, "cannot get GID for group %s -- platform lacks getgrnam() or setgid() system calls", groupname);
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
set_group (const struct group_state *state)
|
||||
{
|
||||
#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
|
||||
if (state->groupname && state->gr)
|
||||
{
|
||||
if (setgid (state->gr->gr_gid))
|
||||
msg (M_ERR, "setgid('%s') failed", state->groupname);
|
||||
msg (M_INFO, "GID set to %s", state->groupname);
|
||||
#ifdef HAVE_SETGROUPS
|
||||
{
|
||||
gid_t gr_list[1];
|
||||
gr_list[0] = state->gr->gr_gid;
|
||||
if (setgroups (1, gr_list))
|
||||
msg (M_ERR, "setgroups('%s') failed", state->groupname);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Change process priority */
|
||||
void
|
||||
set_nice (int niceval)
|
||||
{
|
||||
if (niceval)
|
||||
{
|
||||
#ifdef HAVE_NICE
|
||||
errno = 0;
|
||||
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
|
||||
msg (M_WARN, "WARNING: nice %d failed (function not implemented)", niceval);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass tunnel endpoint and MTU parms to a user-supplied script.
|
||||
* Used to execute the up/down script/plugins.
|
||||
|
|
@ -253,7 +137,7 @@ get_pid_file (const char* filename, struct pid_state *state)
|
|||
CLEAR (*state);
|
||||
if (filename)
|
||||
{
|
||||
state->fp = openvpn_fopen (filename, "w");
|
||||
state->fp = platform_fopen (filename, "w");
|
||||
if (!state->fp)
|
||||
msg (M_ERR, "Open error on pid file %s", filename);
|
||||
state->filename = filename;
|
||||
|
|
@ -266,42 +150,13 @@ write_pid (const struct pid_state *state)
|
|||
{
|
||||
if (state->filename && state->fp)
|
||||
{
|
||||
unsigned int pid = openvpn_getpid ();
|
||||
unsigned int pid = platform_getpid ();
|
||||
fprintf(state->fp, "%u\n", pid);
|
||||
if (fclose (state->fp))
|
||||
msg (M_ERR, "Close error on pid file %s", state->filename);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get current PID */
|
||||
unsigned int
|
||||
openvpn_getpid ()
|
||||
{
|
||||
#ifdef WIN32
|
||||
return (unsigned int) GetCurrentProcessId ();
|
||||
#else
|
||||
#ifdef HAVE_GETPID
|
||||
return (unsigned int) getpid ();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Disable paging */
|
||||
void
|
||||
do_mlockall(bool print_msg)
|
||||
{
|
||||
#ifdef HAVE_MLOCKALL
|
||||
if (mlockall (MCL_CURRENT | MCL_FUTURE))
|
||||
msg (M_WARN | M_ERRNO, "WARNING: mlockall call failed");
|
||||
else if (print_msg)
|
||||
msg (M_INFO, "mlockall call succeeded");
|
||||
#else
|
||||
msg (M_WARN, "WARNING: mlockall call failed (function not implemented)");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Set standard file descriptors to /dev/null
|
||||
*/
|
||||
|
|
@ -324,27 +179,6 @@ set_std_files_to_null (bool stdin_only)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper for chdir library function
|
||||
*/
|
||||
int
|
||||
openvpn_chdir (const char* dir)
|
||||
{
|
||||
#ifdef HAVE_CHDIR
|
||||
#ifdef WIN32
|
||||
int res;
|
||||
struct gc_arena gc = gc_new ();
|
||||
res = _wchdir (wide_string (dir, &gc));
|
||||
gc_free (&gc);
|
||||
return res;
|
||||
#else
|
||||
return chdir (dir);
|
||||
#endif
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* dup inetd/xinetd socket descriptor and save
|
||||
*/
|
||||
|
|
@ -390,32 +224,6 @@ warn_if_group_others_accessible (const char* filename)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* convert system() return into a success/failure value
|
||||
*/
|
||||
bool
|
||||
system_ok (int stat)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return stat == 0;
|
||||
#else
|
||||
return stat != -1 && WIFEXITED (stat) && WEXITSTATUS (stat) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* did system() call execute the given command?
|
||||
*/
|
||||
bool
|
||||
system_executed (int stat)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return stat != -1;
|
||||
#else
|
||||
return stat != -1 && WEXITSTATUS (stat) != 127;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Print an error message based on the status code returned by system().
|
||||
*/
|
||||
|
|
@ -456,7 +264,7 @@ openvpn_execve_check (const struct argv *a, const struct env_set *es, const unsi
|
|||
const int stat = openvpn_execve (a, es, flags);
|
||||
int ret = false;
|
||||
|
||||
if (system_ok (stat))
|
||||
if (platform_system_ok (stat))
|
||||
ret = true;
|
||||
else
|
||||
{
|
||||
|
|
@ -554,7 +362,6 @@ openvpn_system (const char *command, const struct env_set *es, unsigned int flag
|
|||
{
|
||||
#ifdef HAVE_SYSTEM
|
||||
int ret;
|
||||
struct gc_arena gc;
|
||||
|
||||
perf_push (PERF_SCRIPT);
|
||||
|
||||
|
|
@ -573,13 +380,7 @@ openvpn_system (const char *command, const struct env_set *es, unsigned int flag
|
|||
/*
|
||||
* execute the command
|
||||
*/
|
||||
#ifdef WIN32
|
||||
gc = gc_new ();
|
||||
ret = _wsystem (wide_string (command, &gc));
|
||||
gc_free (&gc);
|
||||
#else
|
||||
ret = system (command);
|
||||
#endif
|
||||
ret = platform_system(command);
|
||||
|
||||
/* debugging */
|
||||
dmsg (D_SCRIPT, "SYSTEM return=%u", ret);
|
||||
|
|
@ -599,19 +400,6 @@ openvpn_system (const char *command, const struct env_set *es, unsigned int flag
|
|||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
openvpn_access (const char *path, int mode)
|
||||
{
|
||||
#ifdef WIN32
|
||||
struct gc_arena gc = gc_new ();
|
||||
int ret = _waccess (wide_string (path, &gc), mode);
|
||||
gc_free (&gc);
|
||||
return ret;
|
||||
#else
|
||||
return access (path, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Run execve() inside a fork(), duping stdout. Designed to replicate the semantics of popen() but
|
||||
* in a safer way that doesn't require the invocation of a shell or the risks
|
||||
|
|
@ -981,7 +769,7 @@ env_set_remove_from_environment (const struct env_set *es)
|
|||
|
||||
static struct env_item *global_env = NULL; /* GLOBAL */
|
||||
|
||||
static void
|
||||
void
|
||||
manage_env (char *str)
|
||||
{
|
||||
remove_env_item (str, true, &global_env);
|
||||
|
|
@ -1078,27 +866,11 @@ setenv_str_ex (struct env_set *es,
|
|||
}
|
||||
else
|
||||
{
|
||||
#if defined(WIN32)
|
||||
char *str = construct_name_value (name_tmp, val_tmp, NULL);
|
||||
if (platform_putenv(str))
|
||||
{
|
||||
if (!SetEnvironmentVariableW (wide_string (name_tmp, &gc),
|
||||
wide_string (val_tmp, &gc)))
|
||||
msg (M_WARN | M_ERRNO, "SetEnvironmentVariable failed, name='%s', value='%s'",
|
||||
name_tmp,
|
||||
val_tmp ? val_tmp : "NULL");
|
||||
msg (M_WARN | M_ERRNO, "putenv('%s') failed", str);
|
||||
}
|
||||
#elif defined(HAVE_PUTENV)
|
||||
{
|
||||
char *str = construct_name_value (name_tmp, val_tmp, NULL);
|
||||
int status;
|
||||
|
||||
status = putenv (str);
|
||||
/*msg (M_INFO, "PUTENV '%s'", str);*/
|
||||
if (!status)
|
||||
manage_env (str);
|
||||
if (status)
|
||||
msg (M_WARN | M_ERRNO, "putenv('%s') failed", str);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
gc_free (&gc);
|
||||
|
|
@ -1162,35 +934,6 @@ count_netmask_bits(const char *dotted_quad)
|
|||
return ((int)result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Go to sleep for n milliseconds.
|
||||
*/
|
||||
void
|
||||
sleep_milliseconds (unsigned int n)
|
||||
{
|
||||
#ifdef WIN32
|
||||
Sleep (n);
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_sec = n / 1000;
|
||||
tv.tv_usec = (n % 1000) * 1000;
|
||||
select (0, NULL, NULL, NULL, &tv);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Go to sleep indefinitely.
|
||||
*/
|
||||
void
|
||||
sleep_until_signal (void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
ASSERT (0);
|
||||
#else
|
||||
select (0, NULL, NULL, NULL, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* return true if filename can be opened for read */
|
||||
bool
|
||||
test_file (const char *filename)
|
||||
|
|
@ -1198,7 +941,7 @@ test_file (const char *filename)
|
|||
bool ret = false;
|
||||
if (filename)
|
||||
{
|
||||
FILE *fp = openvpn_fopen (filename, "r");
|
||||
FILE *fp = platform_fopen (filename, "r");
|
||||
if (fp)
|
||||
{
|
||||
fclose (fp);
|
||||
|
|
@ -1246,7 +989,7 @@ create_temp_file (const char *directory, const char *prefix, struct gc_arena *gc
|
|||
|
||||
/* Atomically create the file. Errors out if the file already
|
||||
exists. */
|
||||
fd = openvpn_open (retfname, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
|
||||
fd = platform_open (retfname, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
|
||||
if (fd != -1)
|
||||
{
|
||||
close (fd);
|
||||
|
|
@ -1342,22 +1085,6 @@ gen_path (const char *directory, const char *filename, struct gc_arena *gc)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* delete a file, return true if succeeded */
|
||||
bool
|
||||
delete_file (const char *filename)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
struct gc_arena gc = gc_new ();
|
||||
BOOL ret = DeleteFileW (wide_string (filename, &gc));
|
||||
gc_free (&gc);
|
||||
return (ret != 0);
|
||||
#elif defined(HAVE_UNLINK)
|
||||
return (unlink (filename) == 0);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
absolute_pathname (const char *pathname)
|
||||
{
|
||||
|
|
@ -1524,7 +1251,7 @@ get_user_pass_cr (struct user_pass *up,
|
|||
|
||||
warn_if_group_others_accessible (auth_file);
|
||||
|
||||
fp = openvpn_fopen (auth_file, "r");
|
||||
fp = platform_fopen (auth_file, "r");
|
||||
if (!fp)
|
||||
msg (M_ERR, "Error opening '%s' auth file: %s", prefix, auth_file);
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "common.h"
|
||||
#include "integer.h"
|
||||
#include "buffer.h"
|
||||
#include "platform.h"
|
||||
|
||||
/* socket descriptor passed by inetd/xinetd server to us */
|
||||
#define INETD_SOCKET_DESCRIPTOR 0
|
||||
|
|
@ -58,37 +59,6 @@ struct env_set {
|
|||
struct env_item *list;
|
||||
};
|
||||
|
||||
/* Get/Set UID of process */
|
||||
|
||||
struct user_state {
|
||||
#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
|
||||
const char *username;
|
||||
struct passwd *pw;
|
||||
#else
|
||||
int dummy;
|
||||
#endif
|
||||
};
|
||||
|
||||
bool get_user (const char *username, struct user_state *state);
|
||||
void set_user (const struct user_state *state);
|
||||
|
||||
/* Get/Set GID of process */
|
||||
|
||||
struct group_state {
|
||||
#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
|
||||
const char *groupname;
|
||||
struct group *gr;
|
||||
#else
|
||||
int dummy;
|
||||
#endif
|
||||
};
|
||||
|
||||
bool get_group (const char *groupname, struct group_state *state);
|
||||
void set_group (const struct group_state *state);
|
||||
|
||||
void set_nice (int niceval);
|
||||
void do_chroot (const char *path);
|
||||
|
||||
void run_up_down (const char *command,
|
||||
const struct plugin_list *plugins,
|
||||
int plugin_type,
|
||||
|
|
@ -111,9 +81,6 @@ struct pid_state {
|
|||
|
||||
void get_pid_file (const char* filename, struct pid_state *state);
|
||||
void write_pid (const struct pid_state *state);
|
||||
unsigned int openvpn_getpid (void);
|
||||
|
||||
void do_mlockall (bool print_msg); /* Disable paging */
|
||||
|
||||
/* check file protections */
|
||||
void warn_if_group_others_accessible(const char* filename);
|
||||
|
|
@ -122,9 +89,6 @@ void warn_if_group_others_accessible(const char* filename);
|
|||
#define S_SCRIPT (1<<0)
|
||||
#define S_FATAL (1<<1)
|
||||
|
||||
/* interpret the status code returned by system()/execve() */
|
||||
bool system_ok(int);
|
||||
bool system_executed (int stat);
|
||||
const char *system_error_message (int, struct gc_arena *gc);
|
||||
|
||||
/* wrapper around the execve() call */
|
||||
|
|
@ -133,7 +97,6 @@ int openvpn_execve (const struct argv *a, const struct env_set *es, const unsign
|
|||
bool openvpn_execve_check (const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message);
|
||||
bool openvpn_execve_allowed (const unsigned int flags);
|
||||
int openvpn_system (const char *command, const struct env_set *es, unsigned int flags);
|
||||
int openvpn_access (const char *path, int mode);
|
||||
|
||||
static inline bool
|
||||
openvpn_run_script (const struct argv *a, const struct env_set *es, const unsigned int flags, const char *hook)
|
||||
|
|
@ -144,37 +107,6 @@ openvpn_run_script (const struct argv *a, const struct env_set *es, const unsign
|
|||
return openvpn_execve_check(a, es, flags | S_SCRIPT, msg);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
FILE * openvpn_fopen (const char *path, const char *mode);
|
||||
#else
|
||||
static inline FILE *
|
||||
openvpn_fopen (const char *path, const char *mode)
|
||||
{
|
||||
return fopen (path, mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
int openvpn_open (const char *path, int flags, int mode);
|
||||
#else
|
||||
static inline int
|
||||
openvpn_open (const char *path, int flags, mode_t mode)
|
||||
{
|
||||
return open (path, flags, mode);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
typedef struct _stat openvpn_stat_t;
|
||||
int openvpn_stat (const char *path, openvpn_stat_t *buf);
|
||||
#else
|
||||
typedef struct stat openvpn_stat_t;
|
||||
static inline int
|
||||
openvpn_stat (const char *path, openvpn_stat_t *buf)
|
||||
{
|
||||
return stat (path, buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRERROR
|
||||
/* a thread-safe version of strerror */
|
||||
|
|
@ -184,9 +116,6 @@ const char* strerror_ts (int errnum, struct gc_arena *gc);
|
|||
/* Set standard file descriptors to /dev/null */
|
||||
void set_std_files_to_null (bool stdin_only);
|
||||
|
||||
/* Wrapper for chdir library function */
|
||||
int openvpn_chdir (const char* dir);
|
||||
|
||||
/* dup inetd/xinetd socket descriptor and save */
|
||||
extern int inetd_socket_descriptor;
|
||||
void save_inetd_socket_descriptor (void);
|
||||
|
|
@ -242,12 +171,6 @@ const char **make_extended_arg_array (char **p, struct gc_arena *gc);
|
|||
int count_netmask_bits(const char *);
|
||||
unsigned int count_bits(unsigned int );
|
||||
|
||||
/* go to sleep for n milliseconds */
|
||||
void sleep_milliseconds (unsigned int n);
|
||||
|
||||
/* go to sleep indefinitely */
|
||||
void sleep_until_signal (void);
|
||||
|
||||
/* an analogue to the random() function, but use OpenSSL functions if available */
|
||||
#ifdef ENABLE_CRYPTO
|
||||
long int get_random(void);
|
||||
|
|
@ -264,9 +187,6 @@ const char *create_temp_file (const char *directory, const char *prefix, struct
|
|||
/* put a directory and filename together */
|
||||
const char *gen_path (const char *directory, const char *filename, struct gc_arena *gc);
|
||||
|
||||
/* delete a file, return true if succeeded */
|
||||
bool delete_file (const char *filename);
|
||||
|
||||
/* return true if pathname is absolute */
|
||||
bool absolute_pathname (const char *pathname);
|
||||
|
||||
|
|
@ -448,28 +368,4 @@ void argv_printf_cat (struct argv *a, const char *format, ...)
|
|||
#endif
|
||||
;
|
||||
|
||||
/*
|
||||
* Extract UID or GID
|
||||
*/
|
||||
|
||||
static inline int
|
||||
user_state_uid (const struct user_state *s)
|
||||
{
|
||||
#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
|
||||
if (s->pw)
|
||||
return s->pw->pw_uid;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
group_state_gid (const struct group_state *s)
|
||||
{
|
||||
#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
|
||||
if (s->gr)
|
||||
return s->gr->gr_gid;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ mstats_close(void)
|
|||
mmap_stats->state = MSTATS_EXPIRED;
|
||||
if (munmap((void *)mmap_stats, sizeof(struct mmap_stats)))
|
||||
msg (M_WARN | M_ERRNO, "mstats_close: munmap error");
|
||||
delete_file(mmap_fn);
|
||||
platform_unlink(mmap_fn);
|
||||
mmap_stats = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1452,7 +1452,7 @@ multi_client_connect_post (struct multi_context *m,
|
|||
option_types_found,
|
||||
mi->context.c2.es);
|
||||
|
||||
if (!delete_file (dc_file))
|
||||
if (!platform_unlink (dc_file))
|
||||
msg (D_MULTI_ERRORS, "MULTI: problem deleting temporary file: %s",
|
||||
dc_file);
|
||||
|
||||
|
|
|
|||
|
|
@ -143,8 +143,8 @@ struct context_0
|
|||
/* workspace for --user/--group */
|
||||
bool uid_gid_specified;
|
||||
bool uid_gid_set;
|
||||
struct user_state user_state;
|
||||
struct group_state group_state;
|
||||
struct platform_state_user platform_state_user;
|
||||
struct platform_state_group platform_state_group;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -346,6 +346,10 @@
|
|||
RelativePath=".\pkcs11_openssl.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\platform.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugin.c"
|
||||
>
|
||||
|
|
@ -648,6 +652,10 @@
|
|||
RelativePath=".\pkcs11_backend.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\platform.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plugin.h"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -920,7 +920,7 @@ setenv_settings (struct env_set *es, const struct options *o)
|
|||
setenv_int (es, "daemon", o->daemon);
|
||||
setenv_int (es, "daemon_log_redirect", o->log);
|
||||
setenv_unsigned (es, "daemon_start_time", time(NULL));
|
||||
setenv_int (es, "daemon_pid", openvpn_getpid());
|
||||
setenv_int (es, "daemon_pid", platform_getpid());
|
||||
|
||||
#ifdef ENABLE_CONNECTION
|
||||
if (o->connection_list)
|
||||
|
|
@ -2640,18 +2640,18 @@ check_file_access(const int type, const char *file, const int mode, const char *
|
|||
char *fullpath = strdup(file); /* POSIX dirname() implementaion may modify its arguments */
|
||||
char *dirpath = dirname(fullpath);
|
||||
|
||||
if (openvpn_access (dirpath, mode|X_OK) != 0)
|
||||
if (platform_access (dirpath, mode|X_OK) != 0)
|
||||
errcode = errno;
|
||||
free(fullpath);
|
||||
}
|
||||
|
||||
/* Is the file itself accessible? */
|
||||
if (!errcode && (type & CHKACC_FILE) && (openvpn_access (file, mode) != 0) )
|
||||
if (!errcode && (type & CHKACC_FILE) && (platform_access (file, mode) != 0) )
|
||||
errcode = errno;
|
||||
|
||||
/* If the file exists and is accessible, is it writable? */
|
||||
if (!errcode && (type & CHKACC_FILEXSTWR) && (openvpn_access (file, F_OK) == 0) )
|
||||
if (openvpn_access (file, W_OK) != 0)
|
||||
if (!errcode && (type & CHKACC_FILEXSTWR) && (platform_access (file, F_OK) == 0) )
|
||||
if (platform_access (file, W_OK) != 0)
|
||||
errcode = errno;
|
||||
|
||||
/* Scream if an error is found */
|
||||
|
|
@ -3755,7 +3755,7 @@ read_config_file (struct options *options,
|
|||
if (streq (file, "stdin"))
|
||||
fp = stdin;
|
||||
else
|
||||
fp = openvpn_fopen (file, "r");
|
||||
fp = platform_fopen (file, "r");
|
||||
if (fp)
|
||||
{
|
||||
line_num = 0;
|
||||
|
|
@ -4528,7 +4528,7 @@ add_option (struct options *options,
|
|||
else if (streq (p[0], "cd") && p[1])
|
||||
{
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
if (openvpn_chdir (p[1]))
|
||||
if (platform_chdir (p[1]))
|
||||
{
|
||||
msg (M_ERR, "cd to '%s' failed", p[1]);
|
||||
goto err;
|
||||
|
|
|
|||
|
|
@ -368,7 +368,7 @@ packet_id_persist_load (struct packet_id_persist *p, const char *filename)
|
|||
if (!packet_id_persist_enabled (p))
|
||||
{
|
||||
/* open packet-id persist file for both read and write */
|
||||
p->fd = openvpn_open (filename,
|
||||
p->fd = platform_open (filename,
|
||||
O_CREAT | O_RDWR | O_BINARY,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (p->fd == -1)
|
||||
|
|
|
|||
|
|
@ -504,8 +504,8 @@ pf_check_reload (struct context *c)
|
|||
&& c->c2.pf.filename
|
||||
&& event_timeout_trigger (&c->c2.pf.reload, &c->c2.timeval, ETT_DEFAULT))
|
||||
{
|
||||
openvpn_stat_t s;
|
||||
if (!openvpn_stat (c->c2.pf.filename, &s))
|
||||
platform_stat_t s;
|
||||
if (!platform_stat (c->c2.pf.filename, &s))
|
||||
{
|
||||
if (s.st_mtime > c->c2.pf.file_last_mod)
|
||||
{
|
||||
|
|
@ -605,7 +605,7 @@ pf_destroy_context (struct pf_context *pfc)
|
|||
#ifdef PLUGIN_PF
|
||||
if (pfc->filename)
|
||||
{
|
||||
delete_file (pfc->filename);
|
||||
platform_unlink (pfc->filename);
|
||||
free (pfc->filename);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
369
src/openvpn/platform.c
Normal file
369
src/openvpn/platform.c
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single TCP/UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (see the file COPYING included with this
|
||||
* distribution); if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#elif defined(_MSC_VER)
|
||||
#include "config-msvc.h"
|
||||
#endif
|
||||
|
||||
#include "syshead.h"
|
||||
|
||||
#include "buffer.h"
|
||||
#include "error.h"
|
||||
#include "win32.h"
|
||||
|
||||
#include "memdbg.h"
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
/* Redefine the top level directory of the filesystem
|
||||
to restrict access to files for security */
|
||||
void
|
||||
platform_chroot (const char *path)
|
||||
{
|
||||
if (path)
|
||||
{
|
||||
#ifdef HAVE_CHROOT
|
||||
const char *top = "/";
|
||||
if (chroot (path))
|
||||
msg (M_ERR, "chroot to '%s' failed", path);
|
||||
if (platform_chdir (top))
|
||||
msg (M_ERR, "cd to '%s' failed", top);
|
||||
msg (M_INFO, "chroot to '%s' and cd to '%s' succeeded", path, top);
|
||||
#else
|
||||
msg (M_FATAL, "Sorry but I can't chroot to '%s' because this operating system doesn't appear to support the chroot() system call", path);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Get/Set UID of process */
|
||||
|
||||
bool
|
||||
platform_user_get (const char *username, struct platform_state_user *state)
|
||||
{
|
||||
bool ret = false;
|
||||
CLEAR (*state);
|
||||
if (username)
|
||||
{
|
||||
#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
|
||||
state->pw = getpwnam (username);
|
||||
if (!state->pw)
|
||||
msg (M_ERR, "failed to find UID for user %s", username);
|
||||
state->username = username;
|
||||
ret = true;
|
||||
#else
|
||||
msg (M_FATAL, "cannot get UID for user %s -- platform lacks getpwname() or setuid() system calls", username);
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
platform_user_set (const struct platform_state_user *state)
|
||||
{
|
||||
#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
|
||||
if (state->username && state->pw)
|
||||
{
|
||||
if (setuid (state->pw->pw_uid))
|
||||
msg (M_ERR, "setuid('%s') failed", state->username);
|
||||
msg (M_INFO, "UID set to %s", state->username);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Get/Set GID of process */
|
||||
|
||||
bool
|
||||
platform_group_get (const char *groupname, struct platform_state_group *state)
|
||||
{
|
||||
bool ret = false;
|
||||
CLEAR (*state);
|
||||
if (groupname)
|
||||
{
|
||||
#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
|
||||
state->gr = getgrnam (groupname);
|
||||
if (!state->gr)
|
||||
msg (M_ERR, "failed to find GID for group %s", groupname);
|
||||
state->groupname = groupname;
|
||||
ret = true;
|
||||
#else
|
||||
msg (M_FATAL, "cannot get GID for group %s -- platform lacks getgrnam() or setgid() system calls", groupname);
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
platform_group_set (const struct platform_state_group *state)
|
||||
{
|
||||
#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
|
||||
if (state->groupname && state->gr)
|
||||
{
|
||||
if (setgid (state->gr->gr_gid))
|
||||
msg (M_ERR, "setgid('%s') failed", state->groupname);
|
||||
msg (M_INFO, "GID set to %s", state->groupname);
|
||||
#ifdef HAVE_SETGROUPS
|
||||
{
|
||||
gid_t gr_list[1];
|
||||
gr_list[0] = state->gr->gr_gid;
|
||||
if (setgroups (1, gr_list))
|
||||
msg (M_ERR, "setgroups('%s') failed", state->groupname);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Change process priority */
|
||||
void
|
||||
platform_nice (int niceval)
|
||||
{
|
||||
if (niceval)
|
||||
{
|
||||
#ifdef HAVE_NICE
|
||||
errno = 0;
|
||||
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
|
||||
msg (M_WARN, "WARNING: nice %d failed (function not implemented)", niceval);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Get current PID */
|
||||
unsigned int
|
||||
platform_getpid ()
|
||||
{
|
||||
#ifdef WIN32
|
||||
return (unsigned int) GetCurrentProcessId ();
|
||||
#else
|
||||
#ifdef HAVE_GETPID
|
||||
return (unsigned int) getpid ();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Disable paging */
|
||||
void
|
||||
platform_mlockall(bool print_msg)
|
||||
{
|
||||
#ifdef HAVE_MLOCKALL
|
||||
if (mlockall (MCL_CURRENT | MCL_FUTURE))
|
||||
msg (M_WARN | M_ERRNO, "WARNING: mlockall call failed");
|
||||
else if (print_msg)
|
||||
msg (M_INFO, "mlockall call succeeded");
|
||||
#else
|
||||
msg (M_WARN, "WARNING: mlockall call failed (function not implemented)");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper for chdir library function
|
||||
*/
|
||||
int
|
||||
platform_chdir (const char* dir)
|
||||
{
|
||||
#ifdef HAVE_CHDIR
|
||||
#ifdef WIN32
|
||||
int res;
|
||||
struct gc_arena gc = gc_new ();
|
||||
res = _wchdir (wide_string (dir, &gc));
|
||||
gc_free (&gc);
|
||||
return res;
|
||||
#else
|
||||
return chdir (dir);
|
||||
#endif
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* convert system() return into a success/failure value
|
||||
*/
|
||||
bool
|
||||
platform_system_ok (int stat)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return stat == 0;
|
||||
#else
|
||||
return stat != -1 && WIFEXITED (stat) && WEXITSTATUS (stat) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* did system() call execute the given command?
|
||||
*/
|
||||
bool
|
||||
platform_system_executed (int stat)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return stat != -1;
|
||||
#else
|
||||
return stat != -1 && WEXITSTATUS (stat) != 127;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
platform_access (const char *path, int mode)
|
||||
{
|
||||
#ifdef WIN32
|
||||
struct gc_arena gc = gc_new ();
|
||||
int ret = _waccess (wide_string (path, &gc), mode & ~X_OK);
|
||||
gc_free (&gc);
|
||||
return ret;
|
||||
#else
|
||||
return access (path, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Go to sleep for n milliseconds.
|
||||
*/
|
||||
void
|
||||
platform_sleep_milliseconds (unsigned int n)
|
||||
{
|
||||
#ifdef WIN32
|
||||
Sleep (n);
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_sec = n / 1000;
|
||||
tv.tv_usec = (n % 1000) * 1000;
|
||||
select (0, NULL, NULL, NULL, &tv);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Go to sleep indefinitely.
|
||||
*/
|
||||
void
|
||||
platform_sleep_until_signal (void)
|
||||
{
|
||||
#ifdef WIN32
|
||||
ASSERT (0);
|
||||
#else
|
||||
select (0, NULL, NULL, NULL, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* delete a file, return true if succeeded */
|
||||
bool
|
||||
platform_unlink (const char *filename)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
struct gc_arena gc = gc_new ();
|
||||
BOOL ret = DeleteFileW (wide_string (filename, &gc));
|
||||
gc_free (&gc);
|
||||
return (ret != 0);
|
||||
#elif defined(HAVE_UNLINK)
|
||||
return (unlink (filename) == 0);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
int platform_system(const char *command) {
|
||||
int ret;
|
||||
#ifdef WIN32
|
||||
struct gc_arena gc = gc_new ();
|
||||
ret = _wsystem (wide_string (command, &gc));
|
||||
gc_free (&gc);
|
||||
#else
|
||||
ret = system (command);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int platform_putenv(char *string)
|
||||
{
|
||||
int status;
|
||||
#if defined(WIN32)
|
||||
struct gc_arena gc = gc_new ();
|
||||
char *s = string_alloc(string, &gc);
|
||||
char *value = strchr(s, '=');
|
||||
if (value!=NULL)
|
||||
{
|
||||
*value = '\0';
|
||||
value++;
|
||||
if (*value == '\0')
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
status = SetEnvironmentVariableW (wide_string (s, &gc),
|
||||
wide_string (value, &gc)) ? 1: 0;
|
||||
gc_free (&gc);
|
||||
#elif defined(HAVE_PUTENV)
|
||||
void manage_env (char *str); /* TODO: Resolve properly */
|
||||
status = putenv (string);
|
||||
if (!status)
|
||||
manage_env (string);
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
FILE *
|
||||
platform_fopen (const char *path, const char *mode)
|
||||
{
|
||||
#ifdef WIN32
|
||||
struct gc_arena gc = gc_new ();
|
||||
FILE *f = _wfopen (wide_string (path, &gc), wide_string (mode, &gc));
|
||||
gc_free (&gc);
|
||||
return f;
|
||||
#else
|
||||
return fopen(path, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
platform_open (const char *path, int flags, int mode)
|
||||
{
|
||||
#ifdef WIN32
|
||||
struct gc_arena gc = gc_new ();
|
||||
int fd = _wopen (wide_string (path, &gc), flags, mode);
|
||||
gc_free (&gc);
|
||||
return fd;
|
||||
#else
|
||||
return open(path, flags, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
platform_stat (const char *path, platform_stat_t *buf)
|
||||
{
|
||||
#ifdef WIN32
|
||||
struct gc_arena gc = gc_new ();
|
||||
int res = _wstat (wide_string (path, &gc), buf);
|
||||
gc_free (&gc);
|
||||
return res;
|
||||
#else
|
||||
return stat(path, buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
142
src/openvpn/platform.h
Normal file
142
src/openvpn/platform.h
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* OpenVPN -- An application to securely tunnel IP networks
|
||||
* over a single TCP/UDP port, with support for SSL/TLS-based
|
||||
* session authentication and key exchange,
|
||||
* packet encryption, packet authentication, and
|
||||
* packet compression.
|
||||
*
|
||||
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (see the file COPYING included with this
|
||||
* distribution); if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GRP_H
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "basic.h"
|
||||
|
||||
/* Get/Set UID of process */
|
||||
|
||||
struct platform_state_user {
|
||||
#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
|
||||
const char *username;
|
||||
struct passwd *pw;
|
||||
#else
|
||||
int dummy;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Get/Set GID of process */
|
||||
|
||||
struct platform_state_group {
|
||||
#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
|
||||
const char *groupname;
|
||||
struct group *gr;
|
||||
#else
|
||||
int dummy;
|
||||
#endif
|
||||
};
|
||||
|
||||
bool platform_user_get (const char *username, struct platform_state_user *state);
|
||||
void platform_user_set (const struct platform_state_user *state);
|
||||
|
||||
bool platform_group_get (const char *groupname, struct platform_state_group *state);
|
||||
void platform_group_set (const struct platform_state_group *state);
|
||||
|
||||
/*
|
||||
* Extract UID or GID
|
||||
*/
|
||||
|
||||
static inline int
|
||||
platform_state_user_uid (const struct platform_state_user *s)
|
||||
{
|
||||
#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
|
||||
if (s->pw)
|
||||
return s->pw->pw_uid;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
platform_state_group_gid (const struct platform_state_group *s)
|
||||
{
|
||||
#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
|
||||
if (s->gr)
|
||||
return s->gr->gr_gid;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
void platform_chroot (const char *path);
|
||||
|
||||
void platform_nice (int niceval);
|
||||
|
||||
unsigned int platform_getpid (void);
|
||||
|
||||
void platform_mlockall (bool print_msg); /* Disable paging */
|
||||
|
||||
int platform_chdir (const char* dir);
|
||||
|
||||
/* interpret the status code returned by system()/execve() */
|
||||
bool platform_system_ok (int stat);
|
||||
bool platform_system_executed (int stat);
|
||||
int platform_system(const char *command);
|
||||
|
||||
int platform_access (const char *path, int mode);
|
||||
|
||||
void platform_sleep_milliseconds (unsigned int n);
|
||||
|
||||
void platform_sleep_until_signal (void);
|
||||
|
||||
/* delete a file, return true if succeeded */
|
||||
bool platform_unlink (const char *filename);
|
||||
|
||||
int platform_putenv (char *string);
|
||||
|
||||
FILE *platform_fopen (const char *path, const char *mode);
|
||||
int platform_open (const char *path, int flags, int mode);
|
||||
|
||||
#ifdef WIN32
|
||||
typedef struct _stat platform_stat_t;
|
||||
#else
|
||||
typedef struct stat platform_stat_t;
|
||||
#endif
|
||||
int platform_stat (const char *path, platform_stat_t *buf);
|
||||
|
||||
#endif
|
||||
|
|
@ -337,7 +337,7 @@ journal_add (const char *journal_dir, struct proxy_connection *pc, struct proxy_
|
|||
check_malloc_return (jfn);
|
||||
openvpn_snprintf (jfn, fnlen, "%s/%s", journal_dir, t);
|
||||
dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: client origin %s -> %s", jfn, f);
|
||||
fd = openvpn_open (jfn, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
fd = platform_open (jfn, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd != -1)
|
||||
{
|
||||
write(fd, f, strlen(f));
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file,
|
|||
#endif
|
||||
{
|
||||
/* Load the PKCS #12 file */
|
||||
if (!(fp = openvpn_fopen(pkcs12_file, "rb")))
|
||||
if (!(fp = platform_fopen(pkcs12_file, "rb")))
|
||||
msg(M_SSLERR, "Error opening file %s", pkcs12_file);
|
||||
p12 = d2i_PKCS12_fp(fp, NULL);
|
||||
fclose(fp);
|
||||
|
|
|
|||
|
|
@ -517,7 +517,7 @@ verify_cert_call_command(const char *verify_command, struct env_set *es,
|
|||
if (verify_export_cert)
|
||||
{
|
||||
if (tmp_file)
|
||||
delete_file(tmp_file);
|
||||
platform_unlink(tmp_file);
|
||||
}
|
||||
|
||||
gc_free(&gc);
|
||||
|
|
@ -551,7 +551,7 @@ verify_check_crl_dir(const char *crl_dir, openvpn_x509_cert_t *cert)
|
|||
x509_free_serial(serial);
|
||||
return FAILURE;
|
||||
}
|
||||
fd = openvpn_open (fn, O_RDONLY, 0);
|
||||
fd = platform_open (fn, O_RDONLY, 0);
|
||||
if (fd >= 0)
|
||||
{
|
||||
msg (D_HANDSHAKE, "VERIFY CRL: certificate serial number %s is revoked", serial);
|
||||
|
|
@ -735,7 +735,7 @@ key_state_rm_auth_control_file (struct key_state *ks)
|
|||
{
|
||||
if (ks && ks->auth_control_file)
|
||||
{
|
||||
delete_file (ks->auth_control_file);
|
||||
platform_unlink (ks->auth_control_file);
|
||||
free (ks->auth_control_file);
|
||||
ks->auth_control_file = NULL;
|
||||
}
|
||||
|
|
@ -987,7 +987,7 @@ verify_user_pass_script (struct tls_session *session, const struct user_pass *up
|
|||
|
||||
done:
|
||||
if (tmp_file && strlen (tmp_file) > 0)
|
||||
delete_file (tmp_file);
|
||||
platform_unlink (tmp_file);
|
||||
|
||||
argv_reset (&argv);
|
||||
gc_free (&gc);
|
||||
|
|
|
|||
|
|
@ -78,17 +78,17 @@ status_open (const char *filename,
|
|||
switch (so->flags)
|
||||
{
|
||||
case STATUS_OUTPUT_WRITE:
|
||||
so->fd = openvpn_open (filename,
|
||||
so->fd = platform_open (filename,
|
||||
O_CREAT | O_TRUNC | O_WRONLY,
|
||||
S_IRUSR | S_IWUSR);
|
||||
break;
|
||||
case STATUS_OUTPUT_READ:
|
||||
so->fd = openvpn_open (filename,
|
||||
so->fd = platform_open (filename,
|
||||
O_RDONLY,
|
||||
S_IRUSR | S_IWUSR);
|
||||
break;
|
||||
case STATUS_OUTPUT_READ|STATUS_OUTPUT_WRITE:
|
||||
so->fd = openvpn_open (filename,
|
||||
so->fd = platform_open (filename,
|
||||
O_CREAT | O_RDWR,
|
||||
S_IRUSR | S_IWUSR);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1545,22 +1545,22 @@ tuncfg (const char *dev, const char *dev_type, const char *dev_node, int persist
|
|||
msg (M_ERR, "Cannot ioctl TUNSETPERSIST(%d) %s", persist_mode, dev);
|
||||
if (username != NULL)
|
||||
{
|
||||
struct user_state user_state;
|
||||
struct platform_state_user platform_state_user;
|
||||
|
||||
if (!get_user (username, &user_state))
|
||||
if (!platform_user_get (username, &platform_state_user))
|
||||
msg (M_ERR, "Cannot get user entry for %s", username);
|
||||
else
|
||||
if (ioctl (tt->fd, TUNSETOWNER, user_state.pw->pw_uid) < 0)
|
||||
if (ioctl (tt->fd, TUNSETOWNER, platform_state_user.pw->pw_uid) < 0)
|
||||
msg (M_ERR, "Cannot ioctl TUNSETOWNER(%s) %s", username, dev);
|
||||
}
|
||||
if (groupname != NULL)
|
||||
{
|
||||
struct group_state group_state;
|
||||
struct platform_state_group platform_state_group;
|
||||
|
||||
if (!get_group (groupname, &group_state))
|
||||
if (!platform_group_get (groupname, &platform_state_group))
|
||||
msg (M_ERR, "Cannot get group entry for %s", groupname);
|
||||
else
|
||||
if (ioctl (tt->fd, TUNSETGROUP, group_state.gr->gr_gid) < 0)
|
||||
if (ioctl (tt->fd, TUNSETGROUP, platform_state_group.gr->gr_gid) < 0)
|
||||
msg (M_ERR, "Cannot ioctl TUNSETOWNER(%s) %s", groupname, dev);
|
||||
}
|
||||
close_tun (tt);
|
||||
|
|
|
|||
|
|
@ -976,33 +976,6 @@ wide_string (const char* utf8, struct gc_arena *gc)
|
|||
return ucs16;
|
||||
}
|
||||
|
||||
FILE *
|
||||
openvpn_fopen (const char *path, const char *mode)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
FILE *f = _wfopen (wide_string (path, &gc), wide_string (mode, &gc));
|
||||
gc_free (&gc);
|
||||
return f;
|
||||
}
|
||||
|
||||
int
|
||||
openvpn_open (const char *path, int flags, int mode)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
int fd = _wopen (wide_string (path, &gc), flags, mode);
|
||||
gc_free (&gc);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int
|
||||
openvpn_stat (const char *path, openvpn_stat_t *buf)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
int res = _wstat (wide_string (path, &gc), buf);
|
||||
gc_free (&gc);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* call ourself in another process
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue