1
0
mirror of https://github.com/falk-werner/webfused synced 2026-03-02 04:09:19 +00:00

switch user and group when started as root

This commit is contained in:
Falk Werner
2020-03-19 12:42:47 +01:00
parent d252fd7411
commit dcc067f258
15 changed files with 369 additions and 7 deletions

116
src/webfused/change_user.c Normal file
View File

@@ -0,0 +1,116 @@
#include "webfused/change_user.h"
#include "webfused/log/log.h"
#include <unistd.h>
#include <sys/types.h>
#include <grp.h>
#include <pwd.h>
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
static bool
wfd_switch_group(
char const * group_name)
{
struct group * group = getgrnam(group_name);
bool result = (NULL != group);
if (!result)
{
WFD_ERROR("failed to switch group: unknown group \'%s\'", group_name);
}
if (result)
{
result = (0 != group->gr_gid);
if (!result)
{
WFD_ERROR("failed to switch group: switch to root (gid 0) is not allowed");
}
}
if (result)
{
result = (0 == setgid(group->gr_gid));
if (!result)
{
WFD_ERROR("failed to set group id: %s", strerror(errno));
}
}
if (result)
{
result = (0 == setgroups(0, NULL));
if (!result)
{
WFD_ERROR("failed to release supplemenatary groups (setgroups): %s", strerror(errno));
}
}
return result;
}
static bool
wfd_switch_user(
char const * user_name)
{
struct passwd * user = getpwnam(user_name);
bool result = (NULL != user);
if (!result)
{
WFD_ERROR("failed to switch user: unknown user \'%s\'", user_name);
}
if (result)
{
result = (0 != user->pw_uid);
if (!result)
{
WFD_ERROR("failed to switch user: switch to root (uid 0) is not allowed");
}
}
if (result)
{
result = (0 == setuid(user->pw_uid));
if (!result)
{
WFD_ERROR("failed to switch user (setuid): %s", strerror(errno));
}
}
return result;
}
bool
wfd_change_user(
char const * user,
char const * group)
{
bool result = true;
bool const is_root = (0 == getuid());
if (is_root)
{
result = ((NULL != user) || (NULL != group));
if (!result)
{
WFD_ERROR("webfuse daemon cannot be run as root: specify user and group in config");
}
if (result)
{
result = wfd_switch_group(group);
}
if (result)
{
result = wfd_switch_user(user);
}
}
return result;
}

View File

@@ -0,0 +1,22 @@
#ifndef WFD_CHANGE_USER_H
#define WFD_CHANGE_USER_H
#ifndef __cplusplus
#include <stdbool.h>
#endif
#ifdef __cplusplus
extern "C"
{
#endif
extern bool
wfd_change_user(
char const * user,
char const * group);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -68,5 +68,14 @@ wfd_config_builder_set_logger(
return builder.vtable->set_logger(builder.data, provider, level, settings);
}
void
wfd_config_builder_set_user(
struct wfd_config_builder builder,
char const * user,
char const * group)
{
return builder.vtable->set_user(builder.data, user, group);
}

View File

@@ -56,6 +56,12 @@ wfd_config_builder_set_logger_fn(
int level,
struct wfd_settings * settings);
typedef void
wfd_config_builder_set_user_fn(
void * data,
char const * user,
char const * group);
struct wfd_config_builder_vtable
{
wfd_config_builder_set_server_vhostname_fn * set_server_vhostname;
@@ -66,6 +72,7 @@ struct wfd_config_builder_vtable
wfd_config_builder_add_auth_provider_fn * add_auth_provider;
wfd_config_builder_add_filesystem_fn * add_filesystem;
wfd_config_builder_set_logger_fn * set_logger;
wfd_config_builder_set_user_fn * set_user;
};
struct wfd_config_builder
@@ -118,6 +125,12 @@ wfd_config_builder_set_logger(
int level,
struct wfd_settings * settings);
extern void
wfd_config_builder_set_user(
struct wfd_config_builder builder,
char const * user,
char const * group);
#ifdef __cplusplus
}
#endif

View File

@@ -6,6 +6,7 @@
#include "webfused/log/manager.h"
#include <stdlib.h>
#include <string.h>
#define WFD_CONFIG_DEFAULT_PORT (8080)
#define WFD_CONFIG_DEFAULT_VHOSTNAME ("localhost")
@@ -16,6 +17,8 @@ struct wfd_config
bool has_authenticator;
struct wfd_authenticator authenticator;
struct wfd_mountpoint_factory * mountpoint_factory;
char * user;
char * group;
};
static void
@@ -112,6 +115,17 @@ wfd_config_set_logger(
return wfd_log_manager_set_logger(provider, level, settings);
}
static void
wfd_config_set_user(
void * data,
char const * user,
char const * group)
{
struct wfd_config * config = data;
config->user = strdup(user);
config->group = strdup(group);
}
static const struct wfd_config_builder_vtable
wfd_config_vtable_config_builder =
{
@@ -122,7 +136,8 @@ wfd_config_vtable_config_builder =
.set_server_document_root = &wfd_config_set_server_document_root,
.add_auth_provider = &wfd_config_add_auth_provider,
.add_filesystem = &wfd_config_add_filesystem,
.set_logger = &wfd_config_set_logger
.set_logger = &wfd_config_set_logger,
.set_user = &wfd_config_set_user
};
struct wfd_config *
@@ -138,6 +153,8 @@ wfd_config_create(void)
wf_server_config_set_mountpoint_factory(config->server,
wfd_mountpoint_factory_create_mountpoint,
config->mountpoint_factory);
config->user = NULL;
config->group = NULL;
return config;
}
@@ -153,6 +170,8 @@ wfd_config_dispose(
}
wfd_mountpoint_factory_dispose(config->mountpoint_factory);
free(config->user);
free(config->group);
free(config);
}
@@ -176,3 +195,17 @@ wfd_config_get_server_config(
return config->server;
}
char const *
wfd_config_get_user(
struct wfd_config * config)
{
return config->user;
}
char const *
wfd_config_get_group(
struct wfd_config * config)
{
return config->group;
}

View File

@@ -33,6 +33,14 @@ extern struct wf_server_config *
wfd_config_get_server_config(
struct wfd_config * config);
extern char const *
wfd_config_get_user(
struct wfd_config * config);
extern char const *
wfd_config_get_group(
struct wfd_config * config);
#ifdef __cplusplus
}
#endif

View File

@@ -262,6 +262,46 @@ wfd_config_read_filesystems(
return result;
}
static bool
wfd_config_read_user(
config_t * config,
struct wfd_config_builder builder)
{
bool result = true;
bool has_user = (NULL != config_lookup(config, "user"));
if (has_user)
{
char const * user;
{
int rc = config_lookup_string(config, "user.name", &user);
if (CONFIG_TRUE != rc)
{
WFD_ERROR("failed to load config: missing required user propert: \'name\'");
result = false;
}
}
char const * group;
if (result)
{
int rc = config_lookup_string(config, "user.group", &group);
if (CONFIG_TRUE != rc)
{
WFD_ERROR("failed to load config: missing required user propert: \'group\'");
result = false;
}
}
if (result)
{
wfd_config_builder_set_user(builder, user, group);
}
}
return result;
}
static bool
wfd_config_load(
struct wfd_config_builder builder,
@@ -273,6 +313,7 @@ wfd_config_load(
&& wfd_config_read_server(config, builder)
&& wfd_config_read_authentication(config, builder)
&& wfd_config_read_filesystems(config, builder)
&& wfd_config_read_user(config, builder)
;
return result;

View File

@@ -16,6 +16,7 @@
#include "webfused/log/log.h"
#include "webfused/log/logger.h"
#include "webfused/log/stderr_logger.h"
#include "webfused/change_user.h"
#define WFD_SERVICE_TIMEOUT (1 * 1000)
#define WFD_DEFAULT_CONFIG_FILE ("/etc/webfuse.conf")
@@ -111,6 +112,19 @@ int wfd_daemon_run(int argc, char * argv[])
struct wfd_config * config = wfd_config_create();
struct wfd_config_builder builder = wfd_config_get_builder(config);
bool success = wfd_config_load_file(builder, args.config_file);
if (!success)
{
fprintf(stderr, "fatal: failed to load server config\n");
result = EXIT_FAILURE;
}
if (success)
{
success = wfd_change_user(
wfd_config_get_user(config),
wfd_config_get_group(config));
}
if (success)
{
struct wf_server_config * server_config = wfd_config_get_server_config(config);
@@ -130,11 +144,6 @@ int wfd_daemon_run(int argc, char * argv[])
result = EXIT_FAILURE;
}
}
else
{
fprintf(stderr, "fatal: failed to load server config\n");
result = EXIT_FAILURE;
}
wfd_config_dispose(config);
}