60 const char *top =
"/";
63 msg(
M_ERR,
"chroot to '%s' failed", path);
67 msg(
M_ERR,
"cd to '%s' failed", top);
69 msg(
M_INFO,
"chroot to '%s' and cd to '%s' succeeded", path, top);
71 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);
85#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
87 const struct passwd *pw = getpwnam(username);
90 msg(
M_ERR,
"failed to find UID for user %s", username);
94 state->uid = pw->pw_uid;
96 state->username = username;
99 msg(
M_FATAL,
"cannot get UID for user %s -- platform lacks getpwname() or setuid() system calls", username);
108#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
109 if (state->username && state->uid >= 0)
111 if (setuid(state->uid))
113 msg(
M_ERR,
"setuid('%s') failed", state->username);
115 msg(
M_INFO,
"UID set to %s", state->username);
129#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
131 const struct group *gr = getgrnam(groupname);
134 msg(
M_ERR,
"failed to find GID for group %s", groupname);
138 state->gid = gr->gr_gid;
140 state->groupname = groupname;
143 msg(
M_FATAL,
"cannot get GID for group %s -- platform lacks getgrnam() or setgid() system calls", groupname);
152#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
153 if (state->groupname && state->gid >= 0)
155 if (setgid(state->gid))
157 msg(
M_ERR,
"setgid('%s') failed", state->groupname);
159 msg(
M_INFO,
"GID set to %s", state->groupname);
163 gr_list[0] = state->gid;
164 if (setgroups(1, gr_list))
166 msg(
M_ERR,
"setgroups('%s') failed", state->groupname);
224 int new_gid = -1, new_uid = -1;
236 if (group_state->groupname && group_state->gid >= 0)
238 new_gid = group_state->gid;
240 if (user_state->username && user_state->uid >= 0)
242 new_uid = user_state->uid;
246 capng_clear(CAPNG_SELECT_BOTH);
247 res = capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_NET_ADMIN);
250 msg(err_flags,
"capng_update(CAP_NET_ADMIN) failed: %d", res);
257 res = capng_change_id(new_uid, new_gid, CAPNG_DROP_SUPP_GRP);
258 if (res == -4 || res == -6)
262 msg(
M_ERR,
"capng_change_id('%s','%s') failed: %d",
263 user_state->username, group_state->groupname, res);
268 msg(err_flags,
"NOTE: previous error likely due to missing capability CAP_SETPCAP.");
273 msg(err_flags |
M_ERRNO,
"capng_change_id('%s','%s') failed retaining capabilities: %d",
274 user_state->username, group_state->groupname, res);
280 msg(
M_INFO,
"UID set to %s", user_state->username);
284 msg(
M_INFO,
"GID set to %s", group_state->groupname);
287 msg(
M_INFO,
"Capabilities retained: CAP_NET_ADMIN");
294 if (prctl(PR_GET_KEEPCAPS) && prctl(PR_SET_KEEPCAPS, 0) < 0)
296 msg(
M_ERR,
"Clearing KEEPCAPS flag failed");
302 msg(err_flags,
"Unable to retain capabilities");
317 if (nice(niceval) < 0 && errno != 0)
323 msg(
M_INFO,
"nice %d succeeded", niceval);
326 msg(
M_WARN,
"WARNING: nice %d failed (function not implemented)", niceval);
336 return (
unsigned int) GetCurrentProcessId();
338 return (
unsigned int) getpid();
348#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_MEMLOCK)
349#define MIN_LOCKED_MEM_MB 100
351 if (getrlimit(RLIMIT_MEMLOCK, &rl) < 0)
357 msg(
M_INFO,
"mlock: MEMLOCK limit: soft=%ld KB, hard=%ld KB",
358 ((
long int) rl.rlim_cur) / 1024, ((
long int) rl.rlim_max) / 1024);
359 if (rl.rlim_cur < MIN_LOCKED_MEM_MB*1024*1024)
361 msg(
M_INFO,
"mlock: RLIMIT_MEMLOCK < %d MB, increase limit",
363 rl.rlim_cur = MIN_LOCKED_MEM_MB*1024*1024;
364 if (rl.rlim_max < rl.rlim_cur)
366 rl.rlim_max = rl.rlim_cur;
368 if (setrlimit(RLIMIT_MEMLOCK, &rl) < 0)
376 if (mlockall(MCL_CURRENT | MCL_FUTURE))
385 msg(
M_WARN,
"WARNING: mlockall call failed (function not implemented)");
419 return stat != -1 && WIFEXITED(stat) && WEXITSTATUS(stat) == 0;
427 if (stat >= 0 && stat < 255)
440 if (!WIFEXITED(stat) || stat == -1)
445 int status = WEXITSTATUS(stat);
466 return access(path, mode);
480 tv.tv_sec = n / 1000;
481 tv.tv_usec = (n % 1000) * 1000;
482 select(0, NULL, NULL, NULL, &tv);
496 return (unlink(filename) == 0);
509 return fopen(path, mode);
522 return open(path, flags, mode);
535 return stat(path, buf);
544 const char *retfname = NULL;
545 unsigned int attempts = 0;
546 char fname[256] = { 0 };
547 const char *fname_fmt = PACKAGE
"_%.*s_%08lx%08lx.tmp";
548 const int max_prefix_len =
sizeof(fname) - (
sizeof(PACKAGE) + 7 + (2 * 8));
554 if (!snprintf(fname,
sizeof(fname), fname_fmt, max_prefix_len,
558 msg(
M_WARN,
"ERROR: temporary filename too long");
565 msg(
M_WARN,
"Failed to create temporary filename and path");
571 fd =
platform_open(retfname, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
577 else if (fd == -1 && errno != EEXIST)
586 msg(
M_WARN,
"Failed to create temporary file after %i attempts", attempts);
601 const int CC_PATH_RESERVED =
CC_SLASH;
612 && strcmp(safe_filename,
".")
613 && strcmp(safe_filename,
"..")
619 const size_t outsize = strlen(safe_filename) + (directory ? strlen(directory) : 0) + 16;
681 filename ? filename :
"UNDEF",
bool buf_printf(struct buffer *buf, const char *format,...)
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
const char * string_mod_const(const char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace, struct gc_arena *gc)
Returns a copy of a string with certain classes of characters of it replaced with a specified charact...
#define CC_DOUBLE_QUOTE
double quote
#define CC_ASTERISK
asterisk
#define CC_BACKSLASH
backslash
#define CC_LESS_THAN
less than sign
#define CC_GREATER_THAN
greater than sign
static void gc_free(struct gc_arena *a)
#define CC_PRINT
printable (>= 32, != 127)
#define CC_QUESTION_MARK
question mark
static struct gc_arena gc_new(void)
long int get_random(void)
Data Channel Cryptography Module.
static SERVICE_STATUS status
static bool dco_enabled(const struct options *o)
Returns whether the current configuration has dco enabled.
Wrapper structure for dynamically allocated memory.
int len
Length in bytes of the actual content within the allocated memory.
Contains all state information for one tunnel.
struct options options
Options loaded from command line or configuration file.
Garbage collection arena used to keep track of dynamically allocated memory.
bool win_safe_filename(const char *fn)
WCHAR * wide_string(const char *utf8, struct gc_arena *gc)