Commit df4adf7c authored by arianna-aondio's avatar arianna-aondio

Merge branch 'master' of git.varnish-cache.org:varnish-cache

parents 8f3fe41e 8736d676
......@@ -7,4 +7,4 @@ before_install:
- sudo apt-get install python-docutils
- ./autogen.sh
- ./configure
script: 'make -j3 check'
script: 'make -j3 check VERBOSE=1'
......@@ -88,14 +88,16 @@ void MCF_TcpParams(void);
/* mgt_sandbox.c */
enum sandbox_e {
SANDBOX_VCC = 1,
SANDBOX_CC = 2,
SANDBOX_VCLLOAD = 3,
SANDBOX_WORKER = 4,
SANDBOX_TESTING,
SANDBOX_VCC,
SANDBOX_CC,
SANDBOX_VCLLOAD,
SANDBOX_WORKER,
};
typedef void mgt_sandbox_f(enum sandbox_e);
extern mgt_sandbox_f *mgt_sandbox;
void mgt_sandbox_init(void);
/* mgt_sandbox_solaris.c */
#ifdef HAVE_SETPPRIV
......@@ -118,7 +120,8 @@ void STV_Config_Transient(void);
/* mgt_vcc.c */
void mgt_vcc_init(void);
unsigned mgt_vcc_default(const char *bflag, const char *vcl, int Cflag);
void mgt_vcc_default(struct cli *, const char *b_arg, const char *vclsrc,
int Cflag);
int mgt_push_vcls_and_start(unsigned *status, char **p);
int mgt_has_vcl(void);
extern char *mgt_cc_cmd;
......
......@@ -36,8 +36,6 @@
#include <ctype.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -329,41 +327,11 @@ static void
init_params(struct cli *cli)
{
ssize_t def, low;
struct passwd *pwd;
struct group *grp;
MCF_CollectParams();
MCF_TcpParams();
/*
* If we have nobody/nogroup, use them as defaults for sandboxes,
* else fall back to whoever we run as.
*/
if (getpwnam("nobody") != NULL) {
MCF_SetDefault("user", "nobody");
} else {
pwd = getpwuid(getuid());
if (pwd == NULL)
ARGV_ERR("Neither user 'nobody' or my uid (%jd)"
" found in password database.\n",
(intmax_t)getuid());
MCF_SetDefault("user", pwd->pw_name);
}
endpwent();
if (getgrnam("nogroup") != NULL) {
MCF_SetDefault("group", "nogroup");
} else {
grp = getgrgid(getgid());
if (grp == NULL)
ARGV_ERR("Neither group 'nogroup' or my gid (%jd)"
" found in password database.\n",
(intmax_t)getgid());
MCF_SetDefault("group", grp->gr_name);
}
endgrent();
if (sizeof(void *) < 8) {
/*
* Adjust default parameters for 32 bit systems to conserve
......@@ -457,6 +425,15 @@ main(int argc, char * const *argv)
*/
SHA256_Test();
/*
* Find out if we can sandbox
*/
mgt_sandbox_init();
/*
* Create a cli for convenience in otherwise CLI functions
*/
INIT_OBJ(cli, CLI_MAGIC);
cli[0].sb = VSB_new_auto();
XXXAN(cli[0].sb);
......@@ -579,8 +556,6 @@ main(int argc, char * const *argv)
argc -= optind;
argv += optind;
mgt_vcc_init();
if (argc != 0)
ARGV_ERR("Too many arguments (%s...)\n", argv[0]);
......@@ -655,14 +630,19 @@ main(int argc, char * const *argv)
ARGV_ERR("Could not open pid/lock (-P) file (%s): %s\n",
P_arg, strerror(errno));
mgt_vcc_init();
if (b_arg != NULL || f_arg != NULL) {
if ((o = mgt_vcc_default(b_arg, vcl, C_flag)) != 0)
exit(o);
mgt_vcc_default(cli, b_arg, vcl, C_flag);
if (C_flag) {
AZ(VSB_finish(cli->sb));
fprintf(stderr, "%s\n", VSB_data(cli->sb));
exit(0);
}
cli_check(cli);
free(vcl);
}
if (C_flag)
exit(0);
} else if (C_flag)
ARGV_ERR("-C only good with -b or -f\n");
if (!d_flag) {
if (MGT_open_sockets())
......
......@@ -56,14 +56,11 @@ tweak_t tweak_bool;
tweak_t tweak_bytes;
tweak_t tweak_bytes_u;
tweak_t tweak_double;
tweak_t tweak_group;
tweak_t tweak_group_cc;
tweak_t tweak_listen_address;
tweak_t tweak_poolparam;
tweak_t tweak_string;
tweak_t tweak_timeout;
tweak_t tweak_uint;
tweak_t tweak_user;
tweak_t tweak_waiter;
tweak_t tweak_vsl_buffer;
tweak_t tweak_vsl_reclen;
......@@ -71,11 +68,6 @@ tweak_t tweak_vsl_reclen;
int tweak_generic_uint(struct vsb *vsb, volatile unsigned *dest,
const char *arg, const char *min, const char *max);
/* mgt_param_tbl.c */
extern struct parspec mgt_parspec[];
/* mgt_param_vsl.c */
extern struct parspec VSL_parspec[];
/* mgt_pool.c */
extern struct parspec WRK_parspec[];
extern struct parspec mgt_parspec[]; /* mgt_param_tbl.c */
extern struct parspec VSL_parspec[]; /* mgt_param_vsl.c */
extern struct parspec WRK_parspec[]; /* mgt_pool.c */
......@@ -45,22 +45,6 @@
"\tmax_age\tmax age of free element."
struct parspec mgt_parspec[] = {
{ "user", tweak_user, NULL, NULL, NULL,
"The unprivileged user to run as.",
MUST_RESTART | ONLY_ROOT,
"" },
{ "group", tweak_group, NULL, NULL, NULL,
"The unprivileged group to run as.",
MUST_RESTART | ONLY_ROOT,
"" },
{ "group_cc", tweak_group_cc, NULL, NULL, NULL,
"On some systems the C-compiler is restricted so not"
" everybody can run it. This parameter makes it possible"
" to add an extra group to the sandbox process which runs the"
" cc_command, in order to gain access to such a restricted"
" C-compiler.",
ONLY_ROOT,
"" },
{ "default_ttl", tweak_timeout, &mgt_param.default_ttl,
"0", NULL,
"The TTL assigned to objects if neither the backend nor "
......
......@@ -32,10 +32,8 @@
#include "config.h"
#include <grp.h>
#include <limits.h>
#include <math.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
......@@ -369,96 +367,6 @@ tweak_vsl_reclen(struct vsb *vsb, const struct parspec *par, const char *arg)
return (0);
}
/*--------------------------------------------------------------------
* XXX: slightly magic. We want to initialize to "nobody" (XXX: shouldn't
* XXX: that be something autocrap found for us ?) but we don't want to
* XXX: fail initialization if that user doesn't exists, even though we
* XXX: do want to fail it, in subsequent sets.
* XXX: The magic init string is a hack for this.
*/
int
tweak_user(struct vsb *vsb, const struct parspec *par, const char *arg)
{
struct passwd *pw;
(void)par;
if (arg != NULL) {
pw = getpwnam(arg);
if (pw == NULL) {
VSB_printf(vsb, "Unknown user '%s'", arg);
return(-1);
}
REPLACE(mgt_param.user, pw->pw_name);
mgt_param.uid = pw->pw_uid;
endpwent();
} else if (mgt_param.user) {
VSB_printf(vsb, "%s (%d)", mgt_param.user, (int)mgt_param.uid);
} else {
VSB_printf(vsb, "UID %d", (int)mgt_param.uid);
}
return (0);
}
/*--------------------------------------------------------------------
* XXX: see comment for tweak_user, same thing here.
*/
int
tweak_group(struct vsb *vsb, const struct parspec *par, const char *arg)
{
struct group *gr;
(void)par;
if (arg != NULL) {
gr = getgrnam(arg);
if (gr == NULL) {
VSB_printf(vsb, "Unknown group '%s'", arg);
return(-1);
}
REPLACE(mgt_param.group, gr->gr_name);
mgt_param.gid = gr->gr_gid;
endgrent();
} else if (mgt_param.group) {
VSB_printf(vsb, "%s (%d)", mgt_param.group, (int)mgt_param.gid);
} else {
VSB_printf(vsb, "GID %d", (int)mgt_param.gid);
}
return (0);
}
/*--------------------------------------------------------------------
* XXX: see comment for tweak_user, same thing here.
*/
int
tweak_group_cc(struct vsb *vsb, const struct parspec *par, const char *arg)
{
struct group *gr;
(void)par;
if (arg != NULL) {
if (*arg != '\0') {
gr = getgrnam(arg);
if (gr == NULL) {
VSB_printf(vsb, "Unknown group");
return(-1);
}
REPLACE(mgt_param.group_cc, gr->gr_name);
mgt_param.gid_cc = gr->gr_gid;
} else {
REPLACE(mgt_param.group_cc, "");
mgt_param.gid_cc = 0;
}
} else if (strlen(mgt_param.group_cc) > 0) {
VSB_printf(vsb, "%s (%d)",
mgt_param.group_cc, (int)mgt_param.gid_cc);
} else {
VSB_printf(vsb, "<not set>");
}
return (0);
}
/*--------------------------------------------------------------------*/
static void
......
......@@ -48,14 +48,142 @@
#include <sys/prctl.h>
#endif
#include <pwd.h>
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <string.h>
#include <unistd.h>
#include "mgt/mgt.h"
#include "common/params.h"
#include "mgt/mgt_param.h"
#include <vsub.h>
mgt_sandbox_f *mgt_sandbox;
/*--------------------------------------------------------------------
* XXX: slightly magic. We want to initialize to "nobody" (XXX: shouldn't
* XXX: that be something autocrap found for us ?) but we don't want to
* XXX: fail initialization if that user doesn't exists, even though we
* XXX: do want to fail it, in subsequent sets.
* XXX: The magic init string is a hack for this.
*/
static int
tweak_user(struct vsb *vsb, const struct parspec *par, const char *arg)
{
struct passwd *pw;
(void)par;
if (arg != NULL) {
pw = getpwnam(arg);
if (pw == NULL) {
VSB_printf(vsb, "Unknown user '%s'", arg);
return(-1);
}
REPLACE(mgt_param.user, pw->pw_name);
mgt_param.uid = pw->pw_uid;
endpwent();
} else if (mgt_param.user) {
VSB_printf(vsb, "%s (%d)", mgt_param.user, (int)mgt_param.uid);
} else {
VSB_printf(vsb, "UID %d", (int)mgt_param.uid);
}
return (0);
}
/*--------------------------------------------------------------------
* XXX: see comment for tweak_user, same thing here.
*/
static int
tweak_group(struct vsb *vsb, const struct parspec *par, const char *arg)
{
struct group *gr;
(void)par;
if (arg != NULL) {
gr = getgrnam(arg);
if (gr == NULL) {
VSB_printf(vsb, "Unknown group '%s'", arg);
return(-1);
}
REPLACE(mgt_param.group, gr->gr_name);
mgt_param.gid = gr->gr_gid;
endgrent();
} else if (mgt_param.group) {
VSB_printf(vsb, "%s (%d)", mgt_param.group, (int)mgt_param.gid);
} else {
VSB_printf(vsb, "GID %d", (int)mgt_param.gid);
}
return (0);
}
/*--------------------------------------------------------------------
* XXX: see comment for tweak_user, same thing here.
*/
static int
tweak_group_cc(struct vsb *vsb, const struct parspec *par, const char *arg)
{
struct group *gr;
(void)par;
if (arg != NULL) {
if (*arg != '\0') {
gr = getgrnam(arg);
if (gr == NULL) {
VSB_printf(vsb, "Unknown group");
return(-1);
}
REPLACE(mgt_param.group_cc, gr->gr_name);
mgt_param.gid_cc = gr->gr_gid;
} else {
REPLACE(mgt_param.group_cc, "");
mgt_param.gid_cc = 0;
}
} else if (strlen(mgt_param.group_cc) > 0) {
VSB_printf(vsb, "%s (%d)",
mgt_param.group_cc, (int)mgt_param.gid_cc);
} else {
VSB_printf(vsb, "<not set>");
}
return (0);
}
/*--------------------------------------------------------------------
*/
static struct parspec mgt_parspec_sandbox[] = {
{ "user", tweak_user, NULL, NULL, NULL,
"The unprivileged user to run as.",
MUST_RESTART | ONLY_ROOT,
"" },
{ "group", tweak_group, NULL, NULL, NULL,
"The unprivileged group to run as.",
MUST_RESTART | ONLY_ROOT,
"" },
{ "group_cc", tweak_group_cc, NULL, NULL, NULL,
"On some systems the C-compiler is restricted so not"
" everybody can run it. This parameter makes it possible"
" to add an extra group to the sandbox process which runs the"
" cc_command, in order to gain access to such a restricted"
" C-compiler.",
ONLY_ROOT,
"" },
{ NULL, NULL, NULL }
};
/*--------------------------------------------------------------------*/
static void __match_proto__(mgt_sandbox_f)
mgt_sandbox_null(enum sandbox_e who)
{
(void)who;
}
/*--------------------------------------------------------------------*/
......@@ -65,51 +193,122 @@ mgt_sandbox_unix(enum sandbox_e who)
{
#define NGID 2000
int i;
gid_t gid_list[NGID];
gid_t gid, gid_list[NGID];
uid_t uid;
if (geteuid() != 0) {
REPORT0(LOG_INFO, "Not running as root, no priv-sep");
return;
if (who == SANDBOX_TESTING) {
/*
* Test if sandboxing is going to work.
* Do not assert on failure here, but simply exit non-zero.
*/
gid = getgid();
gid += 1;
if (setgid(gid))
exit(1);
uid = getuid();
uid += 1;
if (setuid(uid))
exit(2);
exit(0);
}
XXXAZ(setgid(mgt_param.gid));
XXXAZ(initgroups(mgt_param.user, mgt_param.gid));
/*
* Do the real thing, assert if we fail
*/
AZ(setgid(mgt_param.gid));
AZ(initgroups(mgt_param.user, mgt_param.gid));
if (who == SANDBOX_CC && strlen(mgt_param.group_cc) > 0) {
/* Add the optional extra group for the C-compiler access */
i = getgroups(NGID, gid_list);
assert(i >= 0);
gid_list[i++] = mgt_param.gid_cc;
XXXAZ(setgroups(i, gid_list));
AZ(setgroups(i, gid_list));
}
XXXAZ(setuid(mgt_param.uid));
}
#endif
/*--------------------------------------------------------------------*/
AZ(setuid(mgt_param.uid));
#ifdef __linux__
static void __match_proto__(mgt_sandbox_f)
mgt_sandbox_linux(enum sandbox_e who)
{
mgt_sandbox_unix(who);
/*
* On linux mucking about with uid/gid disables core-dumps, * reenable them again.
*/
if (prctl(PR_SET_DUMPABLE, 1) != 0) {
REPORT0(LOG_INFO,
"Could not set dumpable bit. Core dumps turned off\n");
}
#endif
}
#endif
/*--------------------------------------------------------------------*/
static void __match_proto__(sub_func_f)
run_sandbox_test(void *priv)
{
(void)priv;
mgt_sandbox(SANDBOX_TESTING);
}
/*--------------------------------------------------------------------*/
mgt_sandbox_f *mgt_sandbox =
void
mgt_sandbox_init(void)
{
struct passwd *pwd;
struct group *grp;
struct vsb *sb;
unsigned subs;
/* Pick a sandbox */
#ifdef HAVE_SETPPRIV
mgt_sandbox_solaris;
#elif defined (__linux__)
mgt_sandbox_linux;
mgt_sandbox = mgt_sandbox_solaris;
#else
mgt_sandbox_unix;
mgt_sandbox = mgt_sandbox_unix;
#endif
/* Test it */
sb = VSB_new_auto();
subs = VSUB_run(sb, run_sandbox_test, NULL, "SANDBOX-test", 10);
VSB_delete(sb);
if (subs) {
REPORT0(LOG_INFO, "Warning: init of platform-specific sandbox "
"failed - sandboxing disabled");
REPORT0(LOG_INFO, "Warning: Varnish might run with elevated "
"privileges");
mgt_sandbox = mgt_sandbox_null;
}
MCF_AddParams(mgt_parspec_sandbox);
/*
* If we have nobody/nogroup, use them as defaults for sandboxes,
* else fall back to whoever we run as.
*/
if (getpwnam("nobody") != NULL) {
MCF_SetDefault("user", "nobody");
} else {
pwd = getpwuid(getuid());
if (pwd == NULL)
ARGV_ERR("Neither user 'nobody' or my uid (%jd)"
" found in password database.\n",
(intmax_t)getuid());
MCF_SetDefault("user", pwd->pw_name);
}
endpwent();
if (getgrnam("nogroup") != NULL) {
MCF_SetDefault("group", "nogroup");
} else {
grp = getgrgid(getgid());
if (grp == NULL)
ARGV_ERR("Neither group 'nogroup' or my gid (%jd)"
" found in password database.\n",
(intmax_t)getgid());
MCF_SetDefault("group", grp->gr_name);
}
endgrent();
}
......@@ -420,6 +420,15 @@ mgt_sandbox_solaris_waive(enum sandbox_e who)
void __match_proto__(mgt_sandbox_f)
mgt_sandbox_solaris(enum sandbox_e who)
{
/*
* XXX - clarify with phk:
* there is no "all-or-nothing" for the solaris sandbox, even
* if we cant setuid, we can still do useful things and waive
* most privileges.
*/
if (who == SANDBOX_TESTING)
exit(0);
mgt_sandbox_solaris_init(who);
mgt_sandbox_solaris_privsep(who);
mgt_sandbox_solaris_waive(who);
......
......@@ -323,6 +323,7 @@ mgt_vcc_compile(struct vcc_priv *vp, struct vsb *sb, int C_flag)
csrc = VFIL_readfile(NULL, vp->srcfile, NULL);
AN(csrc);
VSB_cat(sb, csrc);
free(csrc);
}
subs = VSUB_run(sb, run_cc, vp, "C-compiler", 10);
......@@ -335,7 +336,7 @@ mgt_vcc_compile(struct vcc_priv *vp, struct vsb *sb, int C_flag)
/*--------------------------------------------------------------------*/
static unsigned
static void
mgt_VccCompile(struct cli *cli, const char *vclname, const char *vclsrc,
int C_flag)
{
......@@ -344,7 +345,7 @@ mgt_VccCompile(struct cli *cli, const char *vclname, const char *vclsrc,
unsigned status;
char *p;
(void)cli;
AN(cli);
sb = VSB_new_auto();
XXXAN(sb);
......@@ -366,12 +367,8 @@ mgt_VccCompile(struct cli *cli, const char *vclname, const char *vclsrc,
status = mgt_vcc_compile(&vp, sb, C_flag);
AZ(VSB_finish(sb));
if (VSB_len(sb) > 0) {
if (cli != NULL)
VCLI_Out(cli, "%s", VSB_data(sb));
else
fprintf(stderr, "%s", VSB_data(sb));
}
if (VSB_len(sb) > 0)
VCLI_Out(cli, "%s", VSB_data(sb));
VSB_delete(sb);
(void)unlink(vp.srcfile);
......@@ -380,63 +377,57 @@ mgt_VccCompile(struct cli *cli, const char *vclname, const char *vclsrc,
if (status || C_flag) {
(void)unlink(vp.libfile);
free(vp.libfile);
if (cli != NULL) {
if (!C_flag) {
VCLI_Out(cli, "VCL compilation failed");
} else if (!C_flag)
fprintf(stderr, "\nVCL compilation failed\n");
return (status);
VCLI_SetResult(cli, CLIS_PARAM);
}
return;
}
if (cli != NULL)
VCLI_Out(cli, "VCL compiled.\n");
VCLI_Out(cli, "VCL compiled.\n");
if (cli == NULL || child_pid < 0) {
if (child_pid < 0) {
mgt_vcc_add(vclname, vp.libfile);
free(vp.libfile);
return (0);
return;
}
if (!mgt_cli_askchild(&status, &p,
"vcl.load %s %s\n", vclname, vp.libfile)) {
mgt_vcc_add(vclname, vp.libfile);
free(vp.libfile);
return (0);
free(p);
return;
}
VCLI_SetResult(cli, status);
VCLI_Out(cli, "%s", p);
free(p);
VCLI_SetResult(cli, CLIS_PARAM);
(void)unlink(vp.libfile);
free(vp.libfile);
return (status);
}
/*--------------------------------------------------------------------*/
unsigned
mgt_vcc_default(const char *b_arg, const char *vcl, int C_flag)
void
mgt_vcc_default(struct cli *cli, const char *b_arg, const char *vclsrc,
int C_flag)
{
char buf[BUFSIZ];
if (b_arg == NULL) {
AN(vcl);
return (mgt_VccCompile(NULL, "boot", vcl, C_flag));
AN(vclsrc);
mgt_VccCompile(cli, "boot", vclsrc, C_flag);
return;
}
AZ(vcl);
/*
* XXX: should do a "HEAD /" on the -b argument to see that
* XXX: it even works. On the other hand, we should do that
* XXX: for all backends in the cache process whenever we
* XXX: change config, but for a complex VCL, it might not be
* XXX: a bug for a backend to not reply at that time, so then
* XXX: again: we should check it here in the "trivial" case.
*/
AZ(vclsrc);
bprintf(buf,
"vcl 4.0;\n"
"backend default {\n"
" .host = \"%s\";\n"
"}\n", b_arg);
return (mgt_VccCompile(NULL, "boot", buf, C_flag));
mgt_VccCompile(cli, "boot", buf, C_flag);
}
/*--------------------------------------------------------------------*/
......@@ -509,8 +500,7 @@ mcf_vcl_inline(struct cli *cli, const char * const *av, void *priv)
return;
}
if (mgt_VccCompile(cli, av[2], av[3], 0))
VCLI_SetResult(cli, CLIS_PARAM);
mgt_VccCompile(cli, av[2], av[3], 0);
}
void
......@@ -534,8 +524,7 @@ mcf_vcl_load(struct cli *cli, const char * const *av, void *priv)
return;
}
if (mgt_VccCompile(cli, av[2], vcl, 0))
VCLI_SetResult(cli, CLIS_PARAM);
mgt_VccCompile(cli, av[2], vcl, 0);
free(vcl);
}
......
......@@ -9,7 +9,7 @@ Version: 4.0.1
Release: 1%{?v_rc}%{?dist}
License: BSD
Group: System Environment/Daemons
URL: http://www.varnish-cache.org/
URL: https://www.varnish-cache.org/
#Source0: http://repo.varnish-cache.org/source/%{name}-%{version}.tar.gz
Source0: %{name}-%{version}%{?vd_rc}.tar.gz
#Source0: %{name}-trunk.tar.gz
......
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