Commit fbebe541 authored by Dag Erling Smørgrav's avatar Dag Erling Smørgrav

Add two run-time parameters, "user" and "group", which specify an unprivileged

user and group to which the child process will switch immediately after fork()
returns, before it starts accepting connections.  The default values are
"nobody" and "nogroup" (they should probably be tweakable at compile time...)

Note that this does not provide full privilege separation, as there are still
channels between the parent and child processes which need to be monitored,
but it is an improvement on the previous situation.


git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@1482 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 984c5fff
......@@ -66,6 +66,12 @@ struct heritage {
struct params {
/* Unprivileged user / group */
char *user;
uid_t uid;
char *group;
gid_t gid;
/* TTL used for lack of anything better */
unsigned default_ttl;
......
......@@ -177,6 +177,11 @@ start_child(void)
if (i < 0)
errx(1, "Could not fork child");
if (i == 0) {
if (geteuid() == 0) {
XXXAZ(setgid(params->gid) == -1);
XXXAZ(setuid(params->uid) == -1);
}
/* Redirect stdin/out/err */
AZ(close(0));
i = open("/dev/null", O_RDONLY);
......
......@@ -29,6 +29,10 @@
* $Id$
*/
#include <sys/types.h>
#include <grp.h>
#include <pwd.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -133,6 +137,70 @@ tweak_generic_uint(struct cli *cli, volatile unsigned *dest, const char *arg, un
/*--------------------------------------------------------------------*/
static void
tweak_user(struct cli *cli, struct parspec *par, const char *arg)
{
struct passwd *pw;
struct group *gr;
(void)par;
if (arg != NULL) {
if ((pw = getpwnam(arg)) == NULL) {
cli_out(cli, "Unknown user");
cli_result(cli, CLIS_PARAM);
return;
}
if (params->user)
free(params->user);
params->user = strdup(pw->pw_name);
AN(params->user);
params->uid = pw->pw_uid;
/* set group to user's primary group */
if (params->group)
free(params->group);
if ((gr = getgrgid(pw->pw_gid)) != NULL &&
(gr = getgrnam(gr->gr_name)) != NULL &&
gr->gr_gid == pw->pw_gid) {
params->group = strdup(gr->gr_name);
AN(params->group);
}
params->gid = pw->pw_gid;
} else if (params->user) {
cli_out(cli, "%s (%d)", params->user, (int)params->uid);
} else {
cli_out(cli, "%d", (int)params->uid);
}
}
/*--------------------------------------------------------------------*/
static void
tweak_group(struct cli *cli, struct parspec *par, const char *arg)
{
struct group *gr;
(void)par;
if (arg != NULL) {
if ((gr = getgrnam(arg)) == NULL) {
cli_out(cli, "Unknown group");
cli_result(cli, CLIS_PARAM);
return;
}
if (params->group)
free(params->group);
params->group = strdup(gr->gr_name);
AN(params->group);
params->gid = gr->gr_gid;
} else if (params->group) {
cli_out(cli, "%s (%d)", params->group, (int)params->gid);
} else {
cli_out(cli, "%d", (int)params->gid);
}
}
/*--------------------------------------------------------------------*/
static void
tweak_default_ttl(struct cli *cli, struct parspec *par, const char *arg)
{
......@@ -447,6 +515,15 @@ tweak_ping_interval(struct cli *cli, struct parspec *par, const char *arg)
* change its default value.
*/
static struct parspec parspec[] = {
{ "user", tweak_user,
"The unprivileged user to run as. Setting this will "
"also set \"group\" to the specified user's primary group.\n"
MUST_RESTART,
"nobody" },
{ "group", tweak_group,
"The unprivileged group to run as.\n"
MUST_RESTART,
"nogroup" },
{ "default_ttl", tweak_default_ttl,
"The TTL assigned to objects if neither the backend nor "
"the VCL code assigns one.\n"
......
......@@ -28,7 +28,7 @@
.\"
.\" $Id$
.\"
.Dd May 16, 2007
.Dd May 30, 2007
.Dt VARNISHD 1
.Os
.Sh NAME
......@@ -40,12 +40,14 @@
.Op Fl b Ar host Ns Op : Ns Ar port
.Op Fl d
.Op Fl f Ar config
.Op Fl g Ar group
.Op Fl h Ar type Ns Op , Ns Ar options
.Op Fl P Ar file
.Op Fl p Ar param Ns = Ns Ar value
.Op Fl s Ar type Ns Op , Ns Ar options
.Op Fl T Ar address Ns Op : Ns Ar port
.Op Fl t Ar ttl
.Op Fl u Ar user
.Op Fl V
.Op Fl w Ar min Ns Op , Ns Ar max Ns Op , Ns Ar timeout
.Sh DESCRIPTION
......@@ -114,6 +116,12 @@ default.
See
.Xr vcl 7
for details on VCL syntax.
.It Fl g Ar group
Specifies the name of an unprivileged group to which the child process
should switch before it starts accepting connections.
This is a shortcut for specifying the
.Va group
run-time parameter.
.It Fl h Ar type Ns Op , Ns Ar options
Specifies the hash algorithm.
See
......@@ -148,6 +156,15 @@ Specifies a hard minimum time to live for cached documents.
This is a shortcut for specifying the
.Va default_ttl
run-time parameter.
.It Fl u Ar user
Specifies the name of an unprivileged user to which the child process
should switch before it starts accepting connections.
This is a shortcut for specifying the
.Va user
run-time parameter.
.Pp
If specifying both a user and a group, the user should be specified
first.
.It Fl V
Display the version number and exit.
.It Fl w Ar min Ns Op , Ns Ar max Ns Op , Ns Ar timeout
......@@ -349,6 +366,20 @@ The default chunk size used when retrieving documents for which the
backend server does not specify a content length.
.Pp
The default is 128 kilobytes.
.It Va group
The name of an unprivileged group to which the child process should
switch before it starts accepting connections.
Note that setting
.Va user
will automatically set
.Va group
to the primary group of the specified user, so if both
.Va user
and
.Va group
are specified, the latter should be specified last.
.Pp
The default is "nogroup".
.It Va http_workspace
The size of the per-session workspace for HTTP protocol data.
For performance reasons, this space is preallocated, so any change to
......@@ -443,6 +474,20 @@ when the number of worker threads exceeds
.Va thread_pool_min .
.Pp
The default is 120 seconds.
.It Va user
The name of an unprivileged user to which the child process should
switch before it starts accepting connections.
Note that setting
.Va user
will automatically set
.Va group
to the primary group of the specified user, so if both
.Va user
and
.Va group
are specified, the latter should be specified last.
.Pp
The default is "nobody".
.It Va vcl_trace
Whether to issue log entries for calls to VCL code and their results.
Note that this will generate large amounts of log data.
......
......@@ -401,7 +401,7 @@ main(int argc, char *argv[])
unsigned d_flag = 0;
const char *b_arg = NULL;
const char *f_arg = NULL;
const char *h_flag = "classic";
const char *h_arg = "classic";
const char *P_arg = NULL;
const char *s_arg = "file";
const char *T_arg = NULL;
......@@ -441,7 +441,7 @@ main(int argc, char *argv[])
MCF_ParamInit(cli);
cli_check(cli);
while ((o = getopt(argc, argv, "a:b:Cdf:h:P:p:s:T:t:Vw:")) != -1)
while ((o = getopt(argc, argv, "a:b:Cdf:g:h:P:p:s:T:t:u:Vw:")) != -1)
switch (o) {
case 'a':
MCF_ParamSet(cli, "listen_address", optarg);
......@@ -459,8 +459,11 @@ main(int argc, char *argv[])
case 'f':
f_arg = optarg;
break;
case 'g':
MCF_ParamSet(cli, "group", optarg);
break;
case 'h':
h_flag = optarg;
h_arg = optarg;
break;
case 'P':
P_arg = optarg;
......@@ -483,6 +486,9 @@ main(int argc, char *argv[])
case 'T':
T_arg = optarg;
break;
case 'u':
MCF_ParamSet(cli, "user", optarg);
break;
case 'V':
varnish_version("varnishd");
exit(0);
......@@ -521,7 +527,7 @@ main(int argc, char *argv[])
exit (0);
setup_storage(s_arg);
setup_hash(h_flag);
setup_hash(h_arg);
VSL_MgtInit(SHMLOG_FILENAME, 8*1024*1024);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment