Skip to content
Snippets Groups Projects
Commit 25c31d4f authored by Travis Glenn Hansen's avatar Travis Glenn Hansen
Browse files

supporting new --run-as option to drop to an unpriviledged user

parent e39c47e6
No related branches found
No related tags found
No related merge requests found
......@@ -8,7 +8,10 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
......@@ -39,6 +42,7 @@ struct channel
u_int subscription_count;
};
struct subscription
{
struct client *client;
......@@ -47,6 +51,8 @@ struct subscription
struct subscription *previous;
};
int is_numeric (char *str);
int strcpos (const char *haystack, const char c);
char *substr (const char *s, int start, int stop);
void str_swap_free (char **target, char *source);
......@@ -138,6 +144,14 @@ int main (int argc, char *argv[])
server_start_time = (long)time (NULL);
char buffer[1025];
struct passwd *pwd;
struct group *grp;
char *user;
char *group;
uid_t user_id = -1;
gid_t group_id = -1;
struct epoll_event ev, events[max_events];
struct client *client_i = NULL;
......@@ -154,6 +168,7 @@ int main (int argc, char *argv[])
{"debug-level", 1, 0, 0},
{"help", 0, 0, 0},
{"client-limit", 1, 0, 0},
{"run-as", 1, 0, 0},
{NULL, 0, NULL, 0}
};
......@@ -191,6 +206,8 @@ int main (int argc, char *argv[])
printf("Recognized options are:\n");
printf(" --port=PORT port to run the service\
on\n");
printf(" --run-as=USER[:GROUP] drop permissions to def\
ined levels\n");
printf(" 1986 (default)\n");
printf(" --daemon fork to background\n");
printf(" --client-limit=LIMIT max connections\n");
......@@ -222,6 +239,37 @@ fs.file-max=100000\n");
}
break;
//run-as
case 7:
fanout_debug (3, "requsting permissions %s\n", optarg);
user = strtok (optarg, ":");
group = strtok (NULL, ":");
if (user != NULL) {
if (is_numeric (user)) {
user_id = (uid_t) atoi (user);
} else {
if ((pwd = getpwnam (user)) == NULL) {
fanout_error ("failed getting user_id");
} else {
user_id = pwd->pw_uid;
}
}
}
if (group != NULL) {
if (is_numeric (group)) {
group_id = (gid_t) atoi (group);
} else {
if ((grp = getgrnam (group)) == NULL) {
fanout_error ("failed getting group_id");
} else {
group_id = grp->gr_gid;
}
}
}
break;
}
break;
default:
......@@ -237,7 +285,6 @@ fs.file-max=100000\n");
exit (EXIT_FAILURE);
}
if ( ! portno > 0) {
fanout_debug (0, "ERROR invalid port\n");
exit (EXIT_FAILURE);
......@@ -253,6 +300,7 @@ fs.file-max=100000\n");
serv_addr.sin_port = htons (portno);
setsockopt (srvsock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (yes));
if (bind (srvsock, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
{
fanout_error ("ERROR on binding");
......@@ -319,6 +367,9 @@ fs.file-max=100000\n");
// epollfd, srvsock, extra for reporting busy
base_fds = 3;
//additional padding for safety
base_fds += 10;
//stdin/out/err
if ( ! daemonize) {
base_fds += 3;
......@@ -354,7 +405,27 @@ fs.file-max=100000\n");
client_limit = calculated_client_limit;
}
fanout_debug (1, "rlimit set at: Soft=%d Hard=%d\n", s_rlimit.rlim_cur, s_rlimit.rlim_max);
//set group first so as to not lose root permissions for user set below
if ((int) group_id > -1) {
fanout_debug (3, "attempting to set group %s\n",
getgrgid (group_id)->gr_name);
if (setgid (group_id) == -1) {
fanout_error ("failed setting group");
}
}
//set user
if ((int) user_id > -1) {
fanout_debug (3, "attempting to set user %s\n",
getpwuid (user_id)->pw_name);
if (setuid (user_id) == -1) {
fanout_error ("failed setting user");
}
}
fanout_debug (1, "rlimit set at: Soft=%d Hard=%d\n", s_rlimit.rlim_cur,
s_rlimit.rlim_max);
fanout_debug (2, "base fds: %d\n", base_fds);
fanout_debug (2, "max client connections: %d\n", client_limit);
......@@ -475,6 +546,16 @@ resetting counter\n");
}
int is_numeric (char *str)
{
while (*str) {
if (!isdigit (*str))
return 0;
str++;
}
return 1;
}
int strcpos (const char *haystack, const char c)
{
......@@ -920,7 +1001,8 @@ resetting counter\n");
}
subscription_i = subscription_i->next;
}
fanout_debug (2, "announced messge %s", s);
fanout_debug (2, "announced messge to %d client(s) %s",
get_channel (channel)->subscription_count, s);
if (announcements_count == ULLONG_MAX) {
fanout_debug (1, "wow, you've announced alot..resetting counter\n");
announcements_count = 0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment