Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement dropping group privileges #239

Merged
merged 2 commits into from
Apr 24, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sniproxy.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# lines with only white space are ignored

user nobody
group nogroup

# PID file, needs to be placed in directory writable by user
pidfile /var/tmp/sniproxy.pid
Expand Down
19 changes: 19 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct LoggerBuilder {
};

static int accept_username(struct Config *, char *);
static int accept_groupname(struct Config *, char *);
static int accept_pidfile(struct Config *, char *);
static int end_listener_stanza(struct Config *, struct Listener *);
static int end_table_stanza(struct Config *, struct Table *);
Expand Down Expand Up @@ -146,6 +147,11 @@ static struct Keyword global_grammar[] = {
(int(*)(void *, char *))accept_username,
NULL,
NULL},
{ "groupname",
NULL,
(int(*)(void *, char *))accept_groupname,
NULL,
NULL},
{ "pidfile",
NULL,
(int(*)(void *, char *))accept_pidfile,
Expand Down Expand Up @@ -198,6 +204,7 @@ init_config(const char *filename, struct ev_loop *loop) {

config->filename = NULL;
config->user = NULL;
config->group = NULL;
config->pidfile = NULL;
config->access_log = NULL;
config->resolver.nameservers = NULL;
Expand Down Expand Up @@ -253,6 +260,7 @@ void
free_config(struct Config *config, struct ev_loop *loop) {
free(config->filename);
free(config->user);
free(config->group);
free(config->pidfile);

free_string_vector(config->resolver.nameservers);
Expand Down Expand Up @@ -325,6 +333,17 @@ accept_username(struct Config *config, char *username) {
return 1;
}

static int
accept_groupname(struct Config *config, char *groupname) {
config->group = strdup(groupname);
if (config->group == NULL) {
err("%s: strdup", __func__);
return -1;
}

return 1;
}

static int
accept_pidfile(struct Config *config, char *pidfile) {
config->pidfile = strdup(pidfile);
Expand Down
1 change: 1 addition & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
struct Config {
char *filename;
char *user;
char *group;
char *pidfile;
struct ResolverConfig {
char **nameservers;
Expand Down
24 changes: 19 additions & 5 deletions src/sniproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static void usage();
static void daemonize(void);
static void write_pidfile(const char *, pid_t);
static void set_limits(int);
static void drop_perms(const char* username);
static void drop_perms(const char* username, const char* groupname);
static void perror_exit(const char *);
static void signal_cb(struct ev_loop *, struct ev_signal *, int revents);

Expand Down Expand Up @@ -119,7 +119,7 @@ main(int argc, char **argv) {
init_listeners(&config->listeners, &config->tables, EV_DEFAULT);

/* Drop permissions only when we can */
drop_perms(config->user ? config->user : default_username);
drop_perms(config->user ? config->user : default_username, config->group);

ev_signal_init(&sighup_watcher, signal_cb, SIGHUP);
ev_signal_init(&sigusr1_watcher, signal_cb, SIGUSR1);
Expand Down Expand Up @@ -210,7 +210,7 @@ set_limits(int max_nofiles) {
}

static void
drop_perms(const char *username) {
drop_perms(const char *username, const char *groupname) {
/* check if we are already an unprivileged user */
if (getuid() != 0)
return;
Expand All @@ -222,11 +222,25 @@ drop_perms(const char *username) {
else if (user == NULL)
fatal("getpwnam(): user %s does not exist", username);

gid_t gid = user->pw_gid;

if (groupname) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we explicitly check groupname != NULL?

errno = 0;
struct group *group = getgrnam(groupname);
if (errno)
fatal("getgrnam(): %s", strerror(errno));
else if (group == NULL)
fatal("getgrnam(): group %s does not exist", groupname);

gid = group->gr_gid;
}

/* drop any supplementary groups */
if (setgroups(1, &user->pw_gid) < 0)
if (setgroups(1, &gid) < 0)
fatal("setgroups(): %s", strerror(errno));

if (setgid(user->pw_gid) < 0)
/* set the main gid */
if (setgid(gid) < 0)
fatal("setgid(): %s", strerror(errno));

if (setuid(user->pw_uid) < 0)
Expand Down