59 const char *top =
"/";
62 msg(
M_ERR,
"chroot to '%s' failed", path);
66 msg(
M_ERR,
"cd to '%s' failed", top);
68 msg(
M_INFO,
"chroot to '%s' and cd to '%s' succeeded", path, top);
71 "Sorry but I can't chroot to '%s' because this operating system doesn't appear to support the chroot() system call",
85#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
86 const struct passwd *pw = getpwnam(username);
89 msg(
M_ERR,
"failed to find UID for user %s", username);
93 state->uid = pw->pw_uid;
96 state->username = username;
99 "cannot get UID for user %s -- platform lacks getpwname() or setuid() system calls",
109#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
112 if (setuid(state->uid))
114 msg(
M_ERR,
"setuid('%s') failed", state->username);
116 msg(
M_INFO,
"UID set to %s", state->username);
129#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
130 const struct group *gr = getgrnam(groupname);
133 msg(
M_ERR,
"failed to find GID for group %s", groupname);
137 state->gid = gr->gr_gid;
140 state->groupname = groupname;
143 "cannot get GID for group %s -- platform lacks getgrnam() or setgid() system calls",
153#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
156 if (setgid(state->gid))
158 msg(
M_ERR,
"setgid('%s') failed", state->groupname);
160 msg(
M_INFO,
"GID set to %s", state->groupname);
164 gr_list[0] = state->gid;
165 if (setgroups(1, gr_list))
167 msg(
M_ERR,
"setgroups('%s') failed", state->groupname);
224 int new_gid = -1, new_uid = -1;
236 if (group_state->groupname && group_state->
group_valid)
238 new_gid = (int)group_state->gid;
240 if (user_state->username && user_state->
user_valid)
242 new_uid = (int)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", user_state->username,
263 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", MIN_LOCKED_MEM_MB);
362 rl.rlim_cur = MIN_LOCKED_MEM_MB * 1024 * 1024;
363 if (rl.rlim_max < rl.rlim_cur)
365 rl.rlim_max = rl.rlim_cur;
367 if (setrlimit(RLIMIT_MEMLOCK, &rl) < 0)
375 if (mlockall(MCL_CURRENT | MCL_FUTURE))
384 msg(
M_WARN,
"WARNING: mlockall call failed (function not implemented)");
418 return stat != -1 && WIFEXITED(stat) && WEXITSTATUS(stat) == 0;
426 if (stat >= 0 && stat < 255)
439 if (!WIFEXITED(stat) || stat == -1)
444 int status = WEXITSTATUS(stat);
465 return access(path, mode);
479 tv.tv_sec = n / 1000;
480 tv.tv_usec = (n % 1000) * 1000;
481 select(0, NULL, NULL, NULL, &tv);
495 return (unlink(filename) == 0);
508 return fopen(path, mode);
521 return open(path, flags, mode);
534 return stat(path, buf);
543 const char *retfname = NULL;
544 unsigned int attempts = 0;
545 char fname[256] = { 0 };
546 const char *fname_fmt = PACKAGE
"_%.*s_%08lx%08lx.tmp";
547 const int max_prefix_len =
sizeof(fname) - (
sizeof(PACKAGE) + 7 + (2 * 8));
553 if (!snprintf(fname,
sizeof(fname), fname_fmt, max_prefix_len, prefix,
556 msg(
M_WARN,
"ERROR: temporary filename too long");
563 msg(
M_WARN,
"Failed to create temporary filename and path");
569 fd =
platform_open(retfname, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
575 else if (fd == -1 && errno != EEXIST)
583 msg(
M_WARN,
"Failed to create temporary file after %i attempts", attempts);
598 const int CC_PATH_RESERVED =
CC_SLASH;
608 if (safe_filename && strcmp(safe_filename,
".") && strcmp(safe_filename,
"..")
614 const size_t outsize = strlen(safe_filename) + (directory ? strlen(directory) : 0) + 16;
675 dmsg(
D_TEST_FILE,
"TEST FILE '%s' [%d]", filename ? filename :
"UNDEF", ret);
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)