2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
8 * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #elif defined(_MSC_VER)
28 #include "config-msvc.h"
41 /* Redefine the top level directory of the filesystem
42 to restrict access to files for security */
44 platform_chroot (const char *path
)
49 const char *top
= "/";
51 msg (M_ERR
, "chroot to '%s' failed", path
);
52 if (platform_chdir (top
))
53 msg (M_ERR
, "cd to '%s' failed", top
);
54 msg (M_INFO
, "chroot to '%s' and cd to '%s' succeeded", path
, top
);
56 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
);
61 /* Get/Set UID of process */
64 platform_user_get (const char *username
, struct platform_state_user
*state
)
70 #if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
71 state
->pw
= getpwnam (username
);
73 msg (M_ERR
, "failed to find UID for user %s", username
);
74 state
->username
= username
;
77 msg (M_FATAL
, "cannot get UID for user %s -- platform lacks getpwname() or setuid() system calls", username
);
84 platform_user_set (const struct platform_state_user
*state
)
86 #if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
87 if (state
->username
&& state
->pw
)
89 if (setuid (state
->pw
->pw_uid
))
90 msg (M_ERR
, "setuid('%s') failed", state
->username
);
91 msg (M_INFO
, "UID set to %s", state
->username
);
96 /* Get/Set GID of process */
99 platform_group_get (const char *groupname
, struct platform_state_group
*state
)
105 #if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
106 state
->gr
= getgrnam (groupname
);
108 msg (M_ERR
, "failed to find GID for group %s", groupname
);
109 state
->groupname
= groupname
;
112 msg (M_FATAL
, "cannot get GID for group %s -- platform lacks getgrnam() or setgid() system calls", groupname
);
119 platform_group_set (const struct platform_state_group
*state
)
121 #if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
122 if (state
->groupname
&& state
->gr
)
124 if (setgid (state
->gr
->gr_gid
))
125 msg (M_ERR
, "setgid('%s') failed", state
->groupname
);
126 msg (M_INFO
, "GID set to %s", state
->groupname
);
127 #ifdef HAVE_SETGROUPS
130 gr_list
[0] = state
->gr
->gr_gid
;
131 if (setgroups (1, gr_list
))
132 msg (M_ERR
, "setgroups('%s') failed", state
->groupname
);
139 /* Change process priority */
141 platform_nice (int niceval
)
147 if (nice (niceval
) < 0 && errno
!= 0)
148 msg (M_WARN
| M_ERRNO
, "WARNING: nice %d failed: %s", niceval
, strerror(errno
));
150 msg (M_INFO
, "nice %d succeeded", niceval
);
152 msg (M_WARN
, "WARNING: nice %d failed (function not implemented)", niceval
);
157 /* Get current PID */
162 return (unsigned int) GetCurrentProcessId ();
165 return (unsigned int) getpid ();
174 platform_mlockall(bool print_msg
)
177 if (mlockall (MCL_CURRENT
| MCL_FUTURE
))
178 msg (M_WARN
| M_ERRNO
, "WARNING: mlockall call failed");
180 msg (M_INFO
, "mlockall call succeeded");
182 msg (M_WARN
, "WARNING: mlockall call failed (function not implemented)");
187 * Wrapper for chdir library function
190 platform_chdir (const char* dir
)
195 struct gc_arena gc
= gc_new ();
196 res
= _wchdir (wide_string (dir
, &gc
));
208 * convert execve() return into a success/failure value
211 platform_system_ok (int stat
)
216 return stat
!= -1 && WIFEXITED (stat
) && WEXITSTATUS (stat
) == 0;
221 platform_access (const char *path
, int mode
)
224 struct gc_arena gc
= gc_new ();
225 int ret
= _waccess (wide_string (path
, &gc
), mode
& ~X_OK
);
229 return access (path
, mode
);
234 * Go to sleep for n milliseconds.
237 platform_sleep_milliseconds (unsigned int n
)
243 tv
.tv_sec
= n
/ 1000;
244 tv
.tv_usec
= (n
% 1000) * 1000;
245 select (0, NULL
, NULL
, NULL
, &tv
);
250 * Go to sleep indefinitely.
253 platform_sleep_until_signal (void)
258 select (0, NULL
, NULL
, NULL
, NULL
);
262 /* delete a file, return true if succeeded */
264 platform_unlink (const char *filename
)
267 struct gc_arena gc
= gc_new ();
268 BOOL ret
= DeleteFileW (wide_string (filename
, &gc
));
271 #elif defined(HAVE_UNLINK)
272 return (unlink (filename
) == 0);
279 platform_fopen (const char *path
, const char *mode
)
282 struct gc_arena gc
= gc_new ();
283 FILE *f
= _wfopen (wide_string (path
, &gc
), wide_string (mode
, &gc
));
287 return fopen(path
, mode
);
292 platform_open (const char *path
, int flags
, int mode
)
295 struct gc_arena gc
= gc_new ();
296 int fd
= _wopen (wide_string (path
, &gc
), flags
, mode
);
300 return open(path
, flags
, mode
);
305 platform_stat (const char *path
, platform_stat_t
*buf
)
308 struct gc_arena gc
= gc_new ();
309 int res
= _wstat (wide_string (path
, &gc
), buf
);
313 return stat(path
, buf
);