Skip to content
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