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;
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);
* $Id$
*/
+#include <sys/types.h>
+
+#include <grp.h>
+#include <pwd.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
/*--------------------------------------------------------------------*/
+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)
{
* 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"
.\"
.\" $Id$
.\"
-.Dd May 16, 2007
+.Dd May 30, 2007
.Dt VARNISHD 1
.Os
.Sh NAME
.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
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
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
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
.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.
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;
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);
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;
case 'T':
T_arg = optarg;
break;
+ case 'u':
+ MCF_ParamSet(cli, "user", optarg);
+ break;
case 'V':
varnish_version("varnishd");
exit(0);
exit (0);
setup_storage(s_arg);
- setup_hash(h_flag);
+ setup_hash(h_arg);
VSL_MgtInit(SHMLOG_FILENAME, 8*1024*1024);