From: Andrew Heberle Date: Fri, 12 Jul 2019 03:50:26 +0000 (+0800) Subject: MEDIUM: mworker-prog: Add user/group options to program section X-Git-Tag: v2.1-dev1~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9723696759b23276e92f201cb8163e080966419f;p=thirdparty%2Fhaproxy.git MEDIUM: mworker-prog: Add user/group options to program section This patch adds "user" and "group" config options to the "program" section so the configured command can be run as a different user. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index a46384bf50..98940a0ed3 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -2232,6 +2232,14 @@ command [arguments*] mandatory option of the program section. Arguments containing spaces must be enclosed in quotes or double quotes or be prefixed by a backslash. +user + Changes the executed command user ID to the from /etc/passwd. + See also "group". + +group + Changes the executed command group ID to the from /etc/group. + See also "user". + option start-on-reload no option start-on-reload Start (or not) a new instance of the program upon a reload of the master. diff --git a/include/types/global.h b/include/types/global.h index df0111c79a..b6ba673700 100644 --- a/include/types/global.h +++ b/include/types/global.h @@ -215,6 +215,8 @@ struct mworker_proc { int timestamp; struct server *srv; /* the server entry in the master proxy */ struct list list; + int uid; + int gid; }; extern struct global global; diff --git a/src/mworker-prog.c b/src/mworker-prog.c index ba52406e9a..1d401a3c6d 100644 --- a/src/mworker-prog.c +++ b/src/mworker-prog.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -91,6 +92,23 @@ int mworker_ext_launch_all() mworker_cleanlisteners(); mworker_cleantasks(); + /* setgid / setuid */ + if (child->gid != -1) { + if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1) + ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'" + " without 'uid'/'user' is generally useless.\n", child->command[0]); + + if (setgid(child->gid) == -1) { + ha_alert("[%s.main()] Cannot set gid %d.\n", child->command[0], child->gid); + exit(1); + } + } + + if (child->uid != -1 && setuid(child->uid) == -1) { + ha_alert("[%s.main()] Cannot set uid %d.\n", child->command[0], child->gid); + exit(1); + } + execvp(child->command[0], child->command); ha_alert("Cannot execute %s: %s\n", child->command[0], strerror(errno)); @@ -143,6 +161,8 @@ int cfg_parse_program(const char *file, int linenum, char **args, int kwm) ext_child->ipc_fd[0] = -1; ext_child->ipc_fd[1] = -1; ext_child->options |= PROC_O_START_RELOAD; /* restart the programs by default */ + ext_child->uid = -1; + ext_child->gid = -1; LIST_INIT(&ext_child->list); list_for_each_entry(child, &proc_list, list) { @@ -219,6 +239,56 @@ int cfg_parse_program(const char *file, int linenum, char **args, int kwm) err_code |= ERR_ALERT | ERR_FATAL; goto error; } + } else if (!strcmp(args[0], "user")) { + struct passwd *ext_child_user; + if (*(args[1]) == '\0') { + ha_alert("parsing [%s:%d]: '%s' expects a user name.\n", + file, linenum, args[0]); + err_code |= ERR_ALERT | ERR_FATAL; + goto error; + } + + if (alertif_too_many_args(1, file, linenum, args, &err_code)) + goto error; + + if (ext_child->uid != -1) { + ha_alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum); + err_code |= ERR_ALERT; + goto out; + } + + ext_child_user = getpwnam(args[1]); + if (ext_child_user != NULL) { + ext_child->uid = (int)ext_child_user->pw_uid; + } else { + ha_alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno)); + err_code |= ERR_ALERT | ERR_FATAL; + } + } else if (!strcmp(args[0], "group")) { + struct group *ext_child_group; + if (*(args[1]) == '\0') { + ha_alert("parsing [%s:%d]: '%s' expects a group name.\n", + file, linenum, args[0]); + err_code |= ERR_ALERT | ERR_FATAL; + goto error; + } + + if (alertif_too_many_args(1, file, linenum, args, &err_code)) + goto error; + + if (ext_child->gid != -1) { + ha_alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum); + err_code |= ERR_ALERT; + goto out; + } + + ext_child_group = getgrnam(args[1]); + if (ext_child_group != NULL) { + ext_child->gid = (int)ext_child_group->gr_gid; + } else { + ha_alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno)); + err_code |= ERR_ALERT | ERR_FATAL; + } } else { ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "program"); err_code |= ERR_ALERT | ERR_FATAL;