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",
86#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
88 const struct passwd *pw = getpwnam(username);
91 msg(
M_ERR,
"failed to find UID for user %s", username);
95 state->uid = pw->pw_uid;
97 state->username = username;
101 "cannot get UID for user %s -- platform lacks getpwname() or setuid() system calls",
111#if defined(HAVE_GETPWNAM) && defined(HAVE_SETUID)
112 if (state->username && state->uid >= 0)
114 if (setuid(state->uid))
116 msg(
M_ERR,
"setuid('%s') failed", state->username);
118 msg(
M_INFO,
"UID set to %s", state->username);
132#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
134 const struct group *gr = getgrnam(groupname);
137 msg(
M_ERR,
"failed to find GID for group %s", groupname);
141 state->gid = gr->gr_gid;
143 state->groupname = groupname;
147 "cannot get GID for group %s -- platform lacks getgrnam() or setgid() system calls",
157#if defined(HAVE_GETGRNAM) && defined(HAVE_SETGID)
158 if (state->groupname && state->gid >= 0)
160 if (setgid(state->gid))
162 msg(
M_ERR,
"setgid('%s') failed", state->groupname);
164 msg(
M_INFO,
"GID set to %s", state->groupname);
168 gr_list[0] = state->gid;
169 if (setgroups(1, gr_list))
171 msg(
M_ERR,
"setgroups('%s') failed", state->groupname);
228 int new_gid = -1, new_uid = -1;
240 if (group_state->groupname && group_state->gid >= 0)
242 new_gid = group_state->gid;
244 if (user_state->username && user_state->uid >= 0)
246 new_uid = user_state->uid;
250 capng_clear(CAPNG_SELECT_BOTH);
251 res = capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_NET_ADMIN);
254 msg(err_flags,
"capng_update(CAP_NET_ADMIN) failed: %d",
res);
261 res = capng_change_id(new_uid, new_gid, CAPNG_DROP_SUPP_GRP);
262 if (
res == -4 ||
res == -6)
266 msg(
M_ERR,
"capng_change_id('%s','%s') failed: %d", user_state->username,
267 group_state->groupname,
res);
272 msg(err_flags,
"NOTE: previous error likely due to missing capability CAP_SETPCAP.");
277 msg(err_flags |
M_ERRNO,
"capng_change_id('%s','%s') failed retaining capabilities: %d",
278 user_state->username, group_state->groupname,
res);
284 msg(
M_INFO,
"UID set to %s", user_state->username);
288 msg(
M_INFO,
"GID set to %s", group_state->groupname);
291 msg(
M_INFO,
"Capabilities retained: CAP_NET_ADMIN");
298 if (prctl(PR_GET_KEEPCAPS) && prctl(PR_SET_KEEPCAPS, 0) < 0)
300 msg(
M_ERR,
"Clearing KEEPCAPS flag failed");
306 msg(err_flags,
"Unable to retain capabilities");
321 if (nice(niceval) < 0 && errno != 0)
327 msg(
M_INFO,
"nice %d succeeded", niceval);
330 msg(
M_WARN,
"WARNING: nice %d failed (function not implemented)", niceval);
340 return (
unsigned int)GetCurrentProcessId();
342 return (
unsigned int)getpid();
352#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_MEMLOCK)
353#define MIN_LOCKED_MEM_MB 100
355 if (getrlimit(RLIMIT_MEMLOCK, &rl) < 0)
361 msg(
M_INFO,
"mlock: MEMLOCK limit: soft=%ld KB, hard=%ld KB",
362 ((
long int)rl.rlim_cur) / 1024, ((
long int)rl.rlim_max) / 1024);
363 if (rl.rlim_cur < MIN_LOCKED_MEM_MB * 1024 * 1024)
365 msg(
M_INFO,
"mlock: RLIMIT_MEMLOCK < %d MB, increase limit", MIN_LOCKED_MEM_MB);
366 rl.rlim_cur = MIN_LOCKED_MEM_MB * 1024 * 1024;
367 if (rl.rlim_max < rl.rlim_cur)
369 rl.rlim_max = rl.rlim_cur;
371 if (setrlimit(RLIMIT_MEMLOCK, &rl) < 0)
379 if (mlockall(MCL_CURRENT | MCL_FUTURE))
388 msg(
M_WARN,
"WARNING: mlockall call failed (function not implemented)");
422 return stat != -1 && WIFEXITED(stat) && WEXITSTATUS(stat) == 0;
430 if (stat >= 0 && stat < 255)
443 if (!WIFEXITED(stat) || stat == -1)
448 int status = WEXITSTATUS(stat);
469 return access(path, mode);
483 tv.tv_sec = n / 1000;
484 tv.tv_usec = (n % 1000) * 1000;
485 select(0, NULL, NULL, NULL, &tv);
499 return (unlink(filename) == 0);
512 return fopen(path, mode);
525 return open(path, flags, mode);
538 return stat(path, buf);
547 const char *retfname = NULL;
548 unsigned int attempts = 0;
549 char fname[256] = { 0 };
550 const char *fname_fmt = PACKAGE
"_%.*s_%08lx%08lx.tmp";
551 const int max_prefix_len =
sizeof(fname) - (
sizeof(PACKAGE) + 7 + (2 * 8));
557 if (!snprintf(fname,
sizeof(fname), fname_fmt, max_prefix_len, prefix,
560 msg(
M_WARN,
"ERROR: temporary filename too long");
567 msg(
M_WARN,
"Failed to create temporary filename and path");
573 fd =
platform_open(retfname, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
579 else if (fd == -1 && errno != EEXIST)
587 msg(
M_WARN,
"Failed to create temporary file after %i attempts", attempts);
602 const int CC_PATH_RESERVED =
CC_SLASH;
612 if (safe_filename && strcmp(safe_filename,
".") && strcmp(safe_filename,
"..")
618 const size_t outsize = strlen(safe_filename) + (directory ? strlen(directory) : 0) + 16;
679 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)