Commit b0696adb authored by Geoff Simmons's avatar Geoff Simmons

handle buffer sizes for config parameters safely

parent 551b0fe1
......@@ -47,6 +47,7 @@
#include "vtim.h"
#include "vas.h"
#include "vdef.h"
#define DEFAULT_USER "nobody"
......@@ -57,7 +58,7 @@ static const int facilitynum[8] =
static int
conf_getFacility(const char *facility) {
int localnum;
if (strcasecmp(facility, "USER") == 0)
return LOG_USER;
if (strlen(facility) != 6
......@@ -102,13 +103,24 @@ conf_getDouble(const char *rval, double *d)
return 0;
}
#define confString(name,fld) \
if (strcmp(lval, (name)) == 0) { \
strcpy((config.fld), rval); \
return(0); \
/* For char fields with fixed-size buffers */
#define confString(name,fld) \
if (strcmp(lval, (name)) == 0) { \
if (strlen(rval) > sizeof(config.fld)) \
return EINVAL; \
bprintf((config.fld), "%s", rval); \
return(0); \
}
/* XXX: need confNonNegative for chunk.size */
#define confVSB(name,fld) \
if (strcmp(lval, (name)) == 0) { \
VSB_clear(config.fld); \
VSB_cpy(config.fld, rval); \
VSB_finish(config.fld); \
return(0); \
}
/* XXX: need confNonNegative? */
#define confUnsigned(name,fld) \
if (strcmp(lval, name) == 0) { \
......@@ -126,20 +138,21 @@ CONF_Add(const char *lval, const char *rval)
int ret;
confString("pid.file", pid_file);
confString("varnish.name", varnish_name);
confString("log.file", log_file);
confString("varnish.bindump", varnish_bindump);
confString("cformat", cformat);
confString("bformat", bformat);
confString("rformat", rformat);
confString("output.file", output_file);
confString("syslog.ident", syslog_ident);
confString("varnish.bindump", varnish_bindump);
confVSB("varnish.name", varnish_name);
confVSB("cformat", cformat);
confVSB("bformat", bformat);
confVSB("rformat", rformat);
confVSB("syslog.ident", syslog_ident);
confUnsigned("max.reclen", max_reclen);
confUnsigned("max.headers", max_headers);
confUnsigned("max.vcl_log", max_vcl_log);
confUnsigned("max.vcl_call", max_vcl_call);
confUnsigned("max.timestamp", max_vcl_call);
confUnsigned("chunk_size", chunk_size);
confUnsigned("max.data", max_data);
confUnsigned("monitor.interval", monitor_interval);
confUnsigned("output.bufsiz", output_bufsiz);
......@@ -149,7 +162,7 @@ CONF_Add(const char *lval, const char *rval)
if ((ret = conf_getFacility(rval)) < 0)
return EINVAL;
config.syslog_facility = ret;
strcpy(config.syslog_facility_name, rval);
bprintf(config.syslog_facility_name, "%s", rval);
char *p = &config.syslog_facility_name[0];
do { *p = toupper(*p); } while (*++p);
return(0);
......@@ -161,7 +174,7 @@ CONF_Add(const char *lval, const char *rval)
pw = getpwnam(rval);
if (pw == NULL)
return(EINVAL);
strcpy(config.user_name, pw->pw_name);
bprintf(config.user_name, "%s", pw->pw_name);
config.uid = pw->pw_uid;
config.gid = pw->pw_gid;
return(0);
......@@ -217,16 +230,25 @@ CONF_Init(void)
{
struct passwd *pw;
strcpy(config.pid_file, DEFAULT_PID_FILE);
strcpy(config.cformat, DEFAULT_CFORMAT);
strcpy(config.syslog_ident, "varnishevent");
config.bformat[0] = '\0';
config.rformat[0] = '\0';
config.varnish_name[0] = '\0';
bprintf(config.pid_file, "%s", DEFAULT_PID_FILE);
config.log_file[0] = '\0';
/* Default is stdout */
config.output_file[0] = '\0';
config.varnish_bindump[0] = '\0';
bprintf(config.syslog_facility_name, "%s", "LOCAL0");
config.varnish_name = VSB_new_auto();
config.cformat = VSB_new_auto();
VSB_cpy(config.cformat, DEFAULT_CFORMAT);
VSB_finish(config.cformat);
config.bformat = VSB_new_auto();
config.rformat = VSB_new_auto();
config.syslog_ident = VSB_new_auto();
VSB_cpy(config.syslog_ident, "varnishevent");
VSB_finish(config.syslog_ident);
config.syslog_facility = LOG_LOCAL0;
strcpy(config.syslog_facility_name, "LOCAL0");
config.monitor_interval = 30;
config.output_bufsiz = BUFSIZ;
......@@ -234,13 +256,10 @@ CONF_Init(void)
config.max_headers = DEFAULT_MAX_HEADERS;
config.max_vcl_log = DEFAULT_MAX_VCL_LOG;
config.max_vcl_call = DEFAULT_MAX_VCL_CALL;
config.max_timestamp = DEFAULT_MAX_TIMESTAMP;
config.max_data = DEFAULT_MAX_DATA;
config.chunk_size = DEFAULT_CHUNK_SIZE;
config.idle_pause = DEFAULT_IDLE_PAUSE;
/* Default is stdout */
config.output_file[0] = '\0';
config.append = 0;
config.output_timeout.tv_sec = 0;
config.output_timeout.tv_usec = 0;
......@@ -249,7 +268,7 @@ CONF_Init(void)
if (pw == NULL)
pw = getpwuid(getuid());
AN(pw);
strcpy(config.user_name, pw->pw_name);
bprintf(config.user_name, "%s", pw->pw_name);
config.uid = pw->pw_uid;
config.gid = pw->pw_gid;
}
......@@ -273,6 +292,7 @@ CONF_ReadFile(const char *file) {
FILE *in;
char *line;
int linenum = 0;
struct vsb *orig;
in = fopen(file, "r");
if (in == NULL) {
......@@ -282,9 +302,8 @@ CONF_ReadFile(const char *file) {
line = (char *) malloc(BUFSIZ);
AN(line);
orig = VSB_new_auto();
while (conf_get_line(line, in) != -1) {
char orig[BUFSIZ];
linenum++;
char *comment = strchr(line, '#');
if (comment != NULL)
......@@ -302,18 +321,22 @@ CONF_ReadFile(const char *file) {
ptr = line;
while (isspace(*ptr) && *++ptr)
;
strcpy(orig, ptr);
VSB_clear(orig);
VSB_cpy(orig, ptr);
VSB_finish(orig);
char *lval, *rval;
if (conf_ParseLine(ptr, &lval, &rval) != 0) {
fprintf(stderr, "Cannot parse %s line %d: '%s'\n", file, linenum,
orig);
VSB_data(orig));
return(-1);
}
int ret;
if ((ret = CONF_Add((const char *) lval, (const char *) rval)) != 0) {
fprintf(stderr, "Error in %s line %d (%s): '%s'\n", file, linenum,
strerror(ret), orig);
strerror(ret), VSB_data(orig));
return(-1);
}
}
......@@ -328,6 +351,7 @@ CONF_ReadFile(const char *file) {
fprintf(stderr, "Error closing file %s: %s)\n", file, strerror(errno));
ret = -1;
}
free(line);
return(ret);
}
......@@ -338,29 +362,29 @@ void
CONF_Dump(void)
{
confdump("pid.file = %s", config.pid_file);
confdump("varnish.name = %s", config.varnish_name);
confdump("varnish.name = %s", VSB_data(config.varnish_name));
confdump("log.file = %s",
strcmp(config.log_file,"-") == 0 ? "stdout" : config.log_file);
strcmp(config.log_file,"-") == 0 ? "stdout" : config.log_file);
confdump("varnish.bindump = %s", config.varnish_bindump);
confdump("output.file = %s",
EMPTY(config.output_file) ? "stdout" : config.output_file);
EMPTY(config.output_file) ? "stdout" : config.output_file);
confdump("append = %u", config.append);
confdump("output.timeout = %f",
config.output_timeout.tv_sec
+ (double) config.output_timeout.tv_usec / 1e-6);
confdump("cformat = %s", config.cformat);
confdump("bformat = %s", config.bformat);
confdump("rformat = %s", config.rformat);
config.output_timeout.tv_sec
+ (double) config.output_timeout.tv_usec / 1e-6);
confdump("cformat = %s", VSB_data(config.cformat));
confdump("bformat = %s", VSB_data(config.bformat));
confdump("rformat = %s", VSB_data(config.rformat));
confdump("syslog.facility = %s", config.syslog_facility_name);
confdump("syslog.ident = %s", config.syslog_ident);
confdump("syslog.ident = %s", VSB_data(config.syslog_ident));
confdump("monitor.interval = %u", config.monitor_interval);
confdump("max.reclen = %u", config.max_reclen);
confdump("max.headers = %u", config.max_headers);
confdump("max.vcl_log = %u", config.max_vcl_log);
confdump("max.vcl_call = %u", config.max_vcl_call);
confdump("max.timestamp = %u", config.max_timestamp);
confdump("max.data = %u", config.max_data);
confdump("idle.pause = %d", config.idle_pause);
confdump("chunk.size = %u", config.chunk_size);
confdump("idle.pause = %f", config.idle_pause);
confdump("output.bufsiz = %u", config.output_bufsiz);
confdump("user = %s", config.user_name);
}
......@@ -1218,17 +1218,17 @@ FMT_Init(char *err)
VSTAILQ_INIT(&rincl[i]);
}
if (!EMPTY(config.cformat))
if (compile_fmt(config.cformat, &cformat, VSL_t_req, err) != 0)
return EINVAL;
if (!VSB_EMPTY(config.cformat) &&
compile_fmt(VSB_data(config.cformat), &cformat, VSL_t_req, err) != 0)
return EINVAL;
if (!EMPTY(config.bformat))
if (compile_fmt(config.bformat, &bformat, VSL_t_bereq, err) != 0)
return EINVAL;
if (!VSB_EMPTY(config.bformat) &&
compile_fmt(VSB_data(config.bformat), &bformat, VSL_t_bereq, err) != 0)
return EINVAL;
if (!EMPTY(config.rformat))
if (compile_fmt(config.rformat, &rformat, VSL_t_raw, err) != 0)
return EINVAL;
if (!VSB_EMPTY(config.rformat) &&
compile_fmt(VSB_data(config.rformat), &rformat, VSL_t_raw, err) != 0)
return EINVAL;
if (includes > 0) {
incl_arg = calloc(include_rx + 1, sizeof(char *));
......@@ -1387,10 +1387,10 @@ FMT_Fini(void)
free_incl(rincl);
}
if (!EMPTY(config.cformat))
if (!VSB_EMPTY(config.cformat))
free_format(&cformat);
if (!EMPTY(config.bformat))
if (!VSB_EMPTY(config.bformat))
free_format(&bformat);
if (!EMPTY(config.rformat))
if (!VSB_EMPTY(config.rformat))
free_format(&rformat);
}
......@@ -1476,7 +1476,9 @@ static const char
"%{Varnish:hitmiss}x %{Varnish:handling}x %{VCL_Log:baz}x "\
"%{tag:VCL_acl}x %{tag:Debug}x %{tag:Timestamp:Req}x "\
"%{tag:ReqAcct[0]}x %{tag:Timestamp:Resp[2]}x %{vxid}x %{pvxid}x"
strcpy(config.cformat, FULL_CLIENT_FMT);
VSB_clear(config.cformat);
VSB_cpy(config.cformat, FULL_CLIENT_FMT);
VSB_finish(config.cformat);
status = FMT_Init(err);
VMASSERT(status == 0, "FMT_Init: %s", err);
......@@ -1542,8 +1544,10 @@ static const char
"%t %T %{%F-%T.%i}t %U %u %{Varnish:time_firstbyte}x %{VCL_Log:baz}x "\
"%{tag:Fetch_Body}x %{tag:Debug}x %{tag:Timestamp:Bereq}x "\
"%{tag:BereqAcct[5]}x %{tag:Timestamp:Bereq[1]}x %{vxid}x %{pvxid}x"
strcpy(config.bformat, FULL_BACKEND_FMT);
config.cformat[0] = '\0';
VSB_clear(config.bformat);
VSB_cpy(config.bformat, FULL_BACKEND_FMT);
VSB_finish(config.bformat);
VSB_clear(config.cformat);
status = FMT_Init(err);
VMASSERT(status == 0, "FMT_Init: %s", err);
......@@ -1611,8 +1615,10 @@ static const char
VSB_clear(os);
#define FULL_RAW_FMT "%t %{%F-%T.%i}t %{tag:Backend_health}x %{vxid}x"
strcpy(config.rformat, FULL_RAW_FMT);
config.bformat[0] = '\0';
VSB_clear(config.rformat);
VSB_cpy(config.rformat, FULL_RAW_FMT);
VSB_finish(config.rformat);
VSB_clear(config.bformat);
status = FMT_Init(err);
VMASSERT(status == 0, "FMT_Init: %s", err);
......@@ -1647,15 +1653,19 @@ static const char
/* Illegal backend formats */
FMT_Fini();
strcpy(config.bformat, "%{Varnish:hitmiss}x");
config.rformat[0] = '\0';
VSB_clear(config.bformat);
VSB_cpy(config.bformat, "%{Varnish:hitmiss}x");
VSB_finish(config.bformat);
VSB_clear(config.rformat);
status = FMT_Init(err);
MAN(status);
MASSERT(strcmp(err,
"Varnish:hitmiss only permitted for client formats") == 0);
FMT_Fini();
strcpy(config.bformat, "%{Varnish:handling}x");
VSB_clear(config.bformat);
VSB_cpy(config.bformat, "%{Varnish:handling}x");
VSB_finish(config.bformat);
status = FMT_Init(err);
MAN(status);
MASSERT(strcmp(err,
......@@ -1663,16 +1673,20 @@ static const char
/* Illegal raw formats */
FMT_Fini();
strcpy(config.rformat, "%r");
config.bformat[0] = '\0';
VSB_clear(config.rformat);
VSB_cpy(config.rformat, "%r");
VSB_finish(config.rformat);
VSB_clear(config.bformat);
status = FMT_Init(err);
MAN(status);
MASSERT(strcmp(err, "Unknown format starting at: %r") == 0);
/* Unknown formatters */
FMT_Fini();
strcpy(config.cformat, "%a");
config.rformat[0] = '\0';
VSB_clear(config.cformat);
VSB_cpy(config.cformat, "%a");
VSB_finish(config.cformat);
VSB_clear(config.rformat);
status = FMT_Init(err);
MAN(status);
MASSERT(strcmp(err, "Unknown format starting at: %a") == 0);
......
......@@ -58,7 +58,7 @@ static char
printf("... testing write timeouts\n");
CONF_Init();
strcpy(config.cformat, "");
VSB_clear(config.cformat);
MAZ(FMT_Init(&errmsg[0]));
strcpy(config.log_file, "-");
......
......@@ -65,6 +65,7 @@
#include "vre.h"
#include "miniobj.h"
#include "vas.h"
#include "vdef.h"
#include "varnishevent.h"
#include "vtim.h"
......@@ -476,7 +477,9 @@ main(int argc, char *argv[])
d_flag = 1;
break;
case 'F':
strcpy(config.cformat, optarg);
VSB_clear(config.cformat);
VSB_cpy(config.cformat, optarg);
VSB_finish(config.cformat);
break;
case 'D':
#ifdef HAVE_DAEMON
......@@ -521,7 +524,7 @@ main(int argc, char *argv[])
d_flag = 1;
break;
case 'r':
strcpy(config.varnish_bindump, optarg);
bprintf(config.varnish_bindump, "%s", optarg);
break;
case 'L':
case 'T':
......@@ -575,7 +578,7 @@ main(int argc, char *argv[])
}
#endif
if (LOG_Open(config.syslog_ident) != 0) {
if (LOG_Open(VSB_data(config.syslog_ident)) != 0) {
exit(EXIT_FAILURE);
}
if (v_flag) {
......@@ -607,7 +610,7 @@ main(int argc, char *argv[])
LOG_Log0(LOG_CRIT, "Session grouping not permitted");
exit(EXIT_FAILURE);
case VSL_g_raw:
if (!EMPTY(config.cformat) || !EMPTY(config.bformat)) {
if (!VSB_EMPTY(config.cformat) || !VSB_EMPTY(config.bformat)) {
/* XXX: this can be allowed with multi-threaded readers */
LOG_Log0(LOG_CRIT, "Raw grouping cannot be used with client "
"or backend logging");
......@@ -622,8 +625,8 @@ main(int argc, char *argv[])
}
}
if (!EMPTY(config.rformat)) {
if (!EMPTY(config.cformat) || !EMPTY(config.bformat)) {
if (!VSB_EMPTY(config.rformat)) {
if (!VSB_EMPTY(config.cformat) || !VSB_EMPTY(config.bformat)) {
/* XXX: this can be allowed with multi-threaded readers */
LOG_Log0(LOG_CRIT, "Raw logging cannot be combined with client "
"or backend logging");
......@@ -692,7 +695,7 @@ main(int argc, char *argv[])
#include "signals.h"
if (w_arg)
strcpy(config.output_file, w_arg);
bprintf(config.output_file, "%s", w_arg);
if (!EMPTY(config.output_file))
SIGDISP(SIGHUP, reopen_action);
else
......@@ -731,9 +734,9 @@ main(int argc, char *argv[])
assert(VSL_Arg(vsl, 'i', scratch) > 0);
}
if (!EMPTY(config.cformat) && EMPTY(config.bformat))
if (!VSB_EMPTY(config.cformat) && VSB_EMPTY(config.bformat))
assert(VSL_Arg(vsl, 'c', scratch) > 0);
else if (!EMPTY(config.bformat) && EMPTY(config.cformat))
else if (!VSB_EMPTY(config.bformat) && VSB_EMPTY(config.cformat))
assert(VSL_Arg(vsl, 'b', scratch) > 0);
if ((errnum = DATA_Init()) != 0) {
......@@ -767,11 +770,11 @@ main(int argc, char *argv[])
tx_type_log[i] = 0;
tx_type_name[i] = 'X';
}
if (!EMPTY(config.cformat))
if (!VSB_EMPTY(config.cformat))
tx_type_log[VSL_t_req] = 1;
if (!EMPTY(config.bformat))
if (!VSB_EMPTY(config.bformat))
tx_type_log[VSL_t_bereq] = 1;
if (!EMPTY(config.rformat))
if (!VSB_EMPTY(config.rformat))
tx_type_log[VSL_t_raw] = 1;
tx_type_name[VSL_t_req] = 'c';
tx_type_name[VSL_t_bereq] = 'b';
......
......@@ -48,13 +48,15 @@
#define B(txtype) ((txtype) == VSL_t_bereq)
#define R(txtype) ((txtype) == VSL_t_raw)
#define EMPTY(s) (s[0] == '\0')
#define VSB_EMPTY(vsb) (VSB_len((vsb)) == 0)
/* Defaults from Varnish 4.0.3 */
#define DEFAULT_MAX_RECLEN 255 /* shm_reclen */
#define DEFAULT_MAX_HEADERS 64 /* http_max_hdr */
#define DEFAULT_MAX_VCL_CALL 10
#define DEFAULT_MAX_VCL_LOG 10
#define DEFAULT_MAX_TIMESTAMP 8
#define DEFAULT_CHUNK_SIZE 64
#define DEFAULT_MAX_DATA 4096
......@@ -127,34 +129,30 @@ pthread_cond_t spscq_ready_cond;
pthread_mutex_t spscq_ready_lock;
struct config {
char pid_file[BUFSIZ];
char pid_file[PATH_MAX + 1];
/* VSL 'n' argument */
char varnish_name[BUFSIZ];
struct vsb *varnish_name;
char log_file[BUFSIZ];
char log_file[PATH_MAX + 1];
char output_file[PATH_MAX];
char output_file[PATH_MAX + 1];
unsigned append;
struct timeval output_timeout;
double idle_pause;
/* VSL 'r' argument */
char varnish_bindump[BUFSIZ];
char varnish_bindump[PATH_MAX + 1];
/* rformat is for raw transactions */
/* XXX: better if these weren't limited to fixed buffer sizes, but the
* length of a configurable string is limited by the length of lines
* read by CONF_ReadFile(), currently BUFSIZ
*/
char cformat[BUFSIZ];
char bformat[BUFSIZ];
char rformat[BUFSIZ];
struct vsb *cformat;
struct vsb *bformat;
struct vsb *rformat;
int syslog_facility;
char syslog_facility_name[BUFSIZ];
char syslog_ident[BUFSIZ];
char syslog_facility_name[sizeof("LOCAL0")];
struct vsb *syslog_ident;
unsigned monitor_interval;
/* varnishd param shm_reclen */
......@@ -166,13 +164,12 @@ struct config {
unsigned max_headers;
unsigned max_vcl_log;
unsigned max_vcl_call;
unsigned max_timestamp;
unsigned max_data;
size_t output_bufsiz;
char user_name[BUFSIZ];
char user_name[LOGIN_NAME_MAX + 1];
uid_t uid;
gid_t gid;
} config;
......@@ -188,7 +185,6 @@ int CONF_ReadFile(const char *file);
void CONF_Dump(void);
/* log.c */
#define EMPTY(s) (s[0] == '\0')
typedef void log_log_t(int level, const char *msg, ...);
typedef void log_setlevel_t(int level);
......
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