struct eb_root sni_w_ctx; /* sni_ctx tree of all known certs wildcards sorted by name */
#endif
int is_ssl; /* SSL is required for these listeners */
+ struct { /* UNIX socket permissions */
+ uid_t uid; /* -1 to leave unchanged */
+ gid_t gid; /* -1 to leave unchanged */
+ mode_t mode; /* 0 to leave unchanged */
+ } ux;
+ int level; /* stats access level (ACCESS_LVL_*) */
struct list by_fe; /* next binding for the same frontend, or NULL */
struct list listeners; /* list of listeners using this bind config */
char *arg; /* argument passed to "bind" for better error reporting */
struct list wait_queue; /* link element to make the listener wait for something (LI_LIMITED) */
unsigned int analysers; /* bitmap of required protocol analysers */
int nice; /* nice value to assign to the instanciated tasks */
- union { /* protocol-dependant access restrictions */
- struct { /* UNIX socket permissions */
- uid_t uid; /* -1 to leave unchanged */
- gid_t gid; /* -1 to leave unchanged */
- mode_t mode; /* 0 to leave unchanged */
- int level; /* access level (ACCESS_LVL_*) */
- } ux;
- } perm;
char *interface; /* interface name or NULL */
int maxseg; /* for TCP, advertised MSS */
}
bind_conf = bind_conf_alloc(&global.stats_fe->conf.bind, file, line, args[2]);
+ bind_conf->level = ACCESS_LVL_OPER; /* default access level */
global.stats_sock.state = LI_INIT;
global.stats_sock.options = LI_O_UNLIMITED;
global.stats_sock.analysers = 0;
global.stats_sock.nice = -64; /* we want to boost priority for local stats */
global.stats_sock.frontend = global.stats_fe;
- global.stats_sock.perm.ux.level = ACCESS_LVL_OPER; /* default access level */
global.stats_sock.maxconn = global.stats_fe->maxconn;
global.stats_sock.timeout = &global.stats_fe->timeout.client;
global.stats_sock.bind_conf = bind_conf;
cur_arg = 3;
while (*args[cur_arg]) {
if (!strcmp(args[cur_arg], "uid")) {
- global.stats_sock.perm.ux.uid = atol(args[cur_arg + 1]);
+ bind_conf->ux.uid = atol(args[cur_arg + 1]);
cur_arg += 2;
}
else if (!strcmp(args[cur_arg], "gid")) {
- global.stats_sock.perm.ux.gid = atol(args[cur_arg + 1]);
+ bind_conf->ux.gid = atol(args[cur_arg + 1]);
cur_arg += 2;
}
else if (!strcmp(args[cur_arg], "mode")) {
- global.stats_sock.perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
+ bind_conf->ux.mode = strtol(args[cur_arg + 1], NULL, 8);
cur_arg += 2;
}
else if (!strcmp(args[cur_arg], "user")) {
memprintf(err, "'%s %s' : unknown user '%s'", args[0], args[1], args[cur_arg + 1]);
return -1;
}
- global.stats_sock.perm.ux.uid = user->pw_uid;
+ bind_conf->ux.uid = user->pw_uid;
cur_arg += 2;
}
else if (!strcmp(args[cur_arg], "group")) {
memprintf(err, "'%s %s' : unknown group '%s'", args[0], args[1], args[cur_arg + 1]);
return -1;
}
- global.stats_sock.perm.ux.gid = group->gr_gid;
+ bind_conf->ux.gid = group->gr_gid;
cur_arg += 2;
}
else if (!strcmp(args[cur_arg], "level")) {
if (!strcmp(args[cur_arg+1], "user"))
- global.stats_sock.perm.ux.level = ACCESS_LVL_USER;
+ bind_conf->level = ACCESS_LVL_USER;
else if (!strcmp(args[cur_arg+1], "operator"))
- global.stats_sock.perm.ux.level = ACCESS_LVL_OPER;
+ bind_conf->level = ACCESS_LVL_OPER;
else if (!strcmp(args[cur_arg+1], "admin"))
- global.stats_sock.perm.ux.level = ACCESS_LVL_ADMIN;
+ bind_conf->level = ACCESS_LVL_ADMIN;
else {
memprintf(err, "'%s %s' : '%s' only supports 'user', 'operator', and 'admin' (got '%s')",
args[0], args[1], args[cur_arg], args[cur_arg+1]);
/* any other information should be dumped here */
- if (target && s->listener->perm.ux.level < ACCESS_LVL_OPER)
+ if (target && s->listener->bind_conf->level < ACCESS_LVL_OPER)
chunk_printf(msg, "# contents not dumped due to insufficient privileges\n");
if (bi_putchk(si->ib, msg) == -1)
}
/* check permissions */
- if (s->listener->perm.ux.level < ACCESS_LVL_OPER) {
+ if (s->listener->bind_conf->level < ACCESS_LVL_OPER) {
si->applet.ctx.cli.msg = stats_permission_denied_msg;
si->applet.st0 = STAT_CLI_PRINT;
return;
{
struct proxy *px;
- if (s->listener->perm.ux.level < ACCESS_LVL_ADMIN) {
+ if (s->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
si->applet.ctx.cli.msg = stats_permission_denied_msg;
si->applet.st0 = STAT_CLI_PRINT;
return NULL;
struct server *sv;
char *line;
- if (s->listener->perm.ux.level < ACCESS_LVL_ADMIN) {
+ if (s->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
si->applet.ctx.cli.msg = stats_permission_denied_msg;
si->applet.st0 = STAT_CLI_PRINT;
return NULL;
}
else if (strcmp(args[1], "sess") == 0) {
si->conn.data_st = STAT_ST_INIT;
- if (s->listener->perm.ux.level < ACCESS_LVL_OPER) {
+ if (s->listener->bind_conf->level < ACCESS_LVL_OPER) {
si->applet.ctx.cli.msg = stats_permission_denied_msg;
si->applet.st0 = STAT_CLI_PRINT;
return 1;
si->applet.st0 = STAT_CLI_O_SESS; // stats_dump_sess_to_buffer
}
else if (strcmp(args[1], "errors") == 0) {
- if (s->listener->perm.ux.level < ACCESS_LVL_OPER) {
+ if (s->listener->bind_conf->level < ACCESS_LVL_OPER) {
si->applet.ctx.cli.msg = stats_permission_denied_msg;
si->applet.st0 = STAT_CLI_PRINT;
return 1;
clrall = 1;
/* check permissions */
- if (s->listener->perm.ux.level < ACCESS_LVL_OPER ||
- (clrall && s->listener->perm.ux.level < ACCESS_LVL_ADMIN)) {
+ if (s->listener->bind_conf->level < ACCESS_LVL_OPER ||
+ (clrall && s->listener->bind_conf->level < ACCESS_LVL_ADMIN)) {
si->applet.ctx.cli.msg = stats_permission_denied_msg;
si->applet.st0 = STAT_CLI_PRINT;
return 1;
else if (strcmp(args[2], "global") == 0) {
int v;
- if (s->listener->perm.ux.level < ACCESS_LVL_ADMIN) {
+ if (s->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
si->applet.ctx.cli.msg = stats_permission_denied_msg;
si->applet.st0 = STAT_CLI_PRINT;
return 1;
if (strcmp(args[3], "global") == 0) {
int v;
- if (s->listener->perm.ux.level < ACCESS_LVL_ADMIN) {
+ if (s->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
si->applet.ctx.cli.msg = stats_permission_denied_msg;
si->applet.st0 = STAT_CLI_PRINT;
return 1;
else if (strcmp(args[1], "session") == 0) {
struct session *sess, *ptr;
- if (s->listener->perm.ux.level < ACCESS_LVL_ADMIN) {
+ if (s->listener->bind_conf->level < ACCESS_LVL_ADMIN) {
si->applet.ctx.cli.msg = stats_permission_denied_msg;
si->applet.st0 = STAT_CLI_PRINT;
return 1;
return 0;
if (si->applet.ctx.table.target &&
- s->listener->perm.ux.level >= ACCESS_LVL_OPER) {
+ s->listener->bind_conf->level >= ACCESS_LVL_OPER) {
/* dump entries only if table explicitly requested */
eb = ebmb_first(&si->applet.ctx.table.proxy->table.keys);
if (eb) {
* While it is known not to be portable on every OS, it's still useful
* where it works.
*/
- if (((listener->perm.ux.uid != -1 || listener->perm.ux.gid != -1) &&
- (chown(tempname, listener->perm.ux.uid, listener->perm.ux.gid) == -1)) ||
- (listener->perm.ux.mode != 0 && chmod(tempname, listener->perm.ux.mode) == -1)) {
+ if (((listener->bind_conf->ux.uid != -1 || listener->bind_conf->ux.gid != -1) &&
+ (chown(tempname, listener->bind_conf->ux.uid, listener->bind_conf->ux.gid) == -1)) ||
+ (listener->bind_conf->ux.mode != 0 && chmod(tempname, listener->bind_conf->ux.mode) == -1)) {
msg = "cannot change UNIX socket ownership";
goto err_unlink_temp;
}
/* parse the "mode" bind keyword */
static int bind_parse_mode(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
- struct listener *l;
- int val;
-
if (!*args[cur_arg + 1]) {
if (err)
memprintf(err, "'%s' : missing mode (octal integer expected)", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
- val = strtol(args[cur_arg + 1], NULL, 8);
-
- list_for_each_entry(l, &conf->listeners, by_bind) {
- if (l->addr.ss_family == AF_UNIX)
- l->perm.ux.mode = val;
- }
-
+ conf->ux.mode = strtol(args[cur_arg + 1], NULL, 8);
return 0;
}
/* parse the "gid" bind keyword */
static int bind_parse_gid(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
- struct listener *l;
- int val;
-
if (!*args[cur_arg + 1]) {
if (err)
memprintf(err, "'%s' : missing value", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
- val = atol(args[cur_arg + 1]);
- list_for_each_entry(l, &conf->listeners, by_bind) {
- if (l->addr.ss_family == AF_UNIX)
- l->perm.ux.gid = val;
- }
-
+ conf->ux.gid = atol(args[cur_arg + 1]);
return 0;
}
/* parse the "group" bind keyword */
static int bind_parse_group(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
- struct listener *l;
struct group *group;
if (!*args[cur_arg + 1]) {
return ERR_ALERT | ERR_FATAL;
}
- list_for_each_entry(l, &conf->listeners, by_bind) {
- if (l->addr.ss_family == AF_UNIX)
- l->perm.ux.gid = group->gr_gid;
- }
-
+ conf->ux.gid = group->gr_gid;
return 0;
}
/* parse the "uid" bind keyword */
static int bind_parse_uid(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
- struct listener *l;
- int val;
-
if (!*args[cur_arg + 1]) {
if (err)
memprintf(err, "'%s' : missing value", args[cur_arg]);
return ERR_ALERT | ERR_FATAL;
}
- val = atol(args[cur_arg + 1]);
- list_for_each_entry(l, &conf->listeners, by_bind) {
- if (l->addr.ss_family == AF_UNIX)
- l->perm.ux.uid = val;
- }
-
+ conf->ux.uid = atol(args[cur_arg + 1]);
return 0;
}
/* parse the "user" bind keyword */
static int bind_parse_user(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
{
- struct listener *l;
struct passwd *user;
if (!*args[cur_arg + 1]) {
return ERR_ALERT | ERR_FATAL;
}
- list_for_each_entry(l, &conf->listeners, by_bind) {
- if (l->addr.ss_family == AF_UNIX)
- l->perm.ux.uid = user->pw_uid;
- }
-
+ conf->ux.uid = user->pw_uid;
return 0;
}