From: Willy Tarreau Date: Sun, 25 Mar 2007 13:39:23 +0000 (+0200) Subject: [MEDIUM] add user/groupname support X-Git-Tag: v1.3.8~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=95c20aca3540fae7b3bc4df1b0c7fb86dced191c;p=thirdparty%2Fhaproxy.git [MEDIUM] add user/groupname support Patch from Marcus Rueckert for 1.2.17 : "I added the attached patch to haproxy. I don't have a static uid/gid for haproxy so i need to specify the username/groupname to run it as non root user." --- diff --git a/doc/haproxy-en.txt b/doc/haproxy-en.txt index ab26df5795..dbe78f5f50 100644 --- a/doc/haproxy-en.txt +++ b/doc/haproxy-en.txt @@ -112,6 +112,8 @@ the following ones : - maxconn - uid - gid + - user + - group - chroot - nbproc - daemon @@ -197,9 +199,14 @@ In the 'global' section, the 'uid' parameter sets a numerical user identifier which the process will switch to after binding its listening sockets. The value '0', which normally represents the super-user, here indicates that the UID must not change during startup. It's the default behaviour. The 'gid' parameter does -the same for the group identifier. It's particularly advised against use of -generic accounts such as 'nobody' because it has the same consequences as using -'root' if other services use them. +the same for the group identifier. If setting an uid is not possible because of +deployment constraints, it is possible to set a user name with the 'user' +keyword followed by a valid user name. The same is true for the gid. It is +possible to specify a group name after the 'group' keyword. + +It is particularly advised against use of generic accounts such as 'nobody' +because it has the same consequences as using 'root' if other services use +them. The 'chroot' parameter makes the process isolate itself in an empty directory just before switching its UID. This type of isolation (chroot) can sometimes @@ -227,11 +234,18 @@ directories. Do not forget to allow core dumps prior to start the process : Example : --------- + # with uid/gid global uid 30000 gid 30000 chroot /var/chroot/haproxy + # with user/group + global + user haproxy + group public + chroot /var/chroot/haproxy + 1.4) Startup modes ------------------ diff --git a/doc/haproxy-fr.txt b/doc/haproxy-fr.txt index 9282cb42dd..7f6d2318d1 100644 --- a/doc/haproxy-fr.txt +++ b/doc/haproxy-fr.txt @@ -119,6 +119,8 @@ support - maxconn - uid - gid + - user + - group - chroot - nbproc - daemon @@ -208,9 +210,14 @@ utilisateur, poss l'on ne souhaite pas changer cet identifiant et conserver la valeur courante. C'est la valeur par défaut. De la même manière, le paramètre 'gid' correspond à un identifiant de groupe, et utilise par défaut la valeur 0 pour ne rien -changer. Il est particulièrement déconseillé d'utiliser des comptes génériques -tels que 'nobody' car cette pratique revient à utiliser 'root' si d'autres -processus utilisent les mêmes identifiants. +changer. Dans le cas où il ne serait pas possible de spécifier un identifiant +numérique pour l'uid, il est possible de spécifier un nom d'utilisateur après +le mot-clé 'user'. De la même manière, il est possible de préciser un nom de +groupe après le mot-clé 'group'. + +Il est particulièrement déconseillé d'utiliser des comptes génériques tels que +'nobody' car cette pratique revient à utiliser 'root' si d'autres processus +utilisent les mêmes identifiants. Le paramètre 'chroot' autorise à changer la racine du processus une fois le programme lancé, de sorte que ni le processus, ni l'un de ses descendants ne @@ -246,11 +253,19 @@ lancer le programme : Exemple : --------- + # with uid/gid global uid 30000 gid 30000 chroot /var/chroot/haproxy + # with user/group + global + user haproxy + group public + chroot /var/chroot/haproxy + + 1.4) Modes de fonctionnement ---------------------------- Le service peut fonctionner dans plusieurs modes : diff --git a/src/cfgparse.c b/src/cfgparse.c index ae5433ea42..4c1f032ec6 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -269,7 +271,7 @@ int cfg_parse_global(const char *file, int linenum, char **args) } else if (!strcmp(args[0], "uid")) { if (global.uid != 0) { - Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]); + Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum); return 0; } if (*(args[1]) == 0) { @@ -280,7 +282,7 @@ int cfg_parse_global(const char *file, int linenum, char **args) } else if (!strcmp(args[0], "gid")) { if (global.gid != 0) { - Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]); + Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum); return 0; } if (*(args[1]) == 0) { @@ -289,6 +291,40 @@ int cfg_parse_global(const char *file, int linenum, char **args) } global.gid = atol(args[1]); } + /* user/group name handling */ + else if (!strcmp(args[0], "user")) { + struct passwd *ha_user; + if (global.uid != 0) { + Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum); + return 0; + } + errno = 0; + ha_user = getpwnam(args[1]); + if (ha_user != NULL) { + global.uid = (int)ha_user->pw_uid; + } + else { + Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno)); + exit(1); + } + } + else if (!strcmp(args[0], "group")) { + struct group *ha_group; + if (global.gid != 0) { + Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum, args[0]); + return 0; + } + errno = 0; + ha_group = getgrnam(args[1]); + if (ha_group != NULL) { + global.gid = (int)ha_group->gr_gid; + } + else { + Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno)); + exit(1); + } + } + /* end of user/group name handling*/ else if (!strcmp(args[0], "nbproc")) { if (global.nbproc != 0) { Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);