Add support for dropping privileges to a specified user and/or group.

PR:		108523
Submitted by:	Dmitri Alenitchev <dmitri@dworlds.ru> (original version)
Reviewed by:	mpp (first reply to PR)
This commit is contained in:
Tom Rhodes 2007-03-09 09:33:19 +00:00
parent 018b991e1d
commit 12d7249e24
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=167356
2 changed files with 56 additions and 5 deletions

View File

@ -26,7 +26,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd August 30, 2001 .Dd March 9, 2007
.Dt DAEMON 8 .Dt DAEMON 8
.Os .Os
.Sh NAME .Sh NAME
@ -35,6 +35,8 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl cf .Op Fl cf
.Op Fl u Ar user
.Op Fl g Ar group
.Op Fl p Ar pidfile .Op Fl p Ar pidfile
.Ar command arguments ... .Ar command arguments ...
.Sh DESCRIPTION .Sh DESCRIPTION
@ -42,6 +44,7 @@ The
.Nm .Nm
utility detaches itself from the controlling terminal and utility detaches itself from the controlling terminal and
executes the program specified by its arguments. executes the program specified by its arguments.
Privileges may be lowered to specified user and/or group.
.Pp .Pp
The options are as follows: The options are as follows:
.Bl -tag -width indent .Bl -tag -width indent
@ -51,10 +54,14 @@ Change the current working directory to the root
.It Fl f .It Fl f
Redirect standard input, standard output and standard error to Redirect standard input, standard output and standard error to
.Pa /dev/null . .Pa /dev/null .
.It Fl g Ar group
Drop privileges to specified group.
.It Fl p Ar file .It Fl p Ar file
Write the ID of the created process into the Write the ID of the created process into the
.Ar file .Ar file
using using
.It Fl u Ar user
Drop privileges to specified user.
.Xr pidfile 3 .Xr pidfile 3
functionality. functionality.
Note, that the file will be created shortly before the process is Note, that the file will be created shortly before the process is
@ -77,6 +84,8 @@ standard error unless the
.Fl f .Fl f
flag is specified. flag is specified.
.Sh SEE ALSO .Sh SEE ALSO
.Xr setregid 2 ,
.Xr setreuid 2 ,
.Xr daemon 3 , .Xr daemon 3 ,
.Xr exec 3 , .Xr exec 3 ,
.Xr pidfile 3 , .Xr pidfile 3 ,

View File

@ -35,11 +35,14 @@ __FBSDID("$FreeBSD$");
#include <err.h> #include <err.h>
#include <errno.h> #include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <libutil.h> #include <libutil.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
static void restrict_process(const char *, const char *);
static void usage(void); static void usage(void);
int int
@ -47,12 +50,12 @@ main(int argc, char *argv[])
{ {
struct pidfh *pfh; struct pidfh *pfh;
int ch, nochdir, noclose, errcode; int ch, nochdir, noclose, errcode;
const char *pidfile; const char *pidfile, *user, *group;
pid_t otherpid; pid_t otherpid;
nochdir = noclose = 1; nochdir = noclose = 1;
pidfile = NULL; pidfile = user = group = NULL;
while ((ch = getopt(argc, argv, "-cfp:")) != -1) { while ((ch = getopt(argc, argv, "-cfg:p:u:")) != -1) {
switch (ch) { switch (ch) {
case 'c': case 'c':
nochdir = 0; nochdir = 0;
@ -60,6 +63,12 @@ main(int argc, char *argv[])
case 'f': case 'f':
noclose = 0; noclose = 0;
break; break;
case 'u':
user = optarg;
break;
case 'g':
group = optarg;
break;
case 'p': case 'p':
pidfile = optarg; pidfile = optarg;
break; break;
@ -72,6 +81,14 @@ main(int argc, char *argv[])
if (argc == 0) if (argc == 0)
usage(); usage();
if (user || group) {
if (getuid() != 0)
errx(1, "only root user is allowed to chroot "
"and change UID/GID");
restrict_process(user, group);
}
/* /*
* Try to open the pidfile before calling daemon(3), * Try to open the pidfile before calling daemon(3),
* to be able to report the error intelligently * to be able to report the error intelligently
@ -108,10 +125,35 @@ main(int argc, char *argv[])
errc(1, errcode, "%s", argv[0]); errc(1, errcode, "%s", argv[0]);
} }
static void
restrict_process(const char *user, const char *group)
{
struct group *gr = NULL;
struct passwd *pw = NULL;
errno = 0;
if (group != NULL) {
if (initgroups(user, gr->gr_gid) == -1)
errx(1, "User not in group list");
if ((gr = getgrnam(group)) == NULL)
errx(1, "Group %s does not exist", group);
if (setgid(gr->gr_gid) == -1)
err(1, "%s", group);
}
if (user != NULL) {
if ((pw = getpwnam(user)) == NULL)
errx(1, "User %s does not exist", user);
if (setuid(pw->pw_uid) == -1)
err(1, "%s", user);
}
}
static void static void
usage(void) usage(void)
{ {
(void)fprintf(stderr, (void)fprintf(stderr,
"usage: daemon [-cf] [-p pidfile] command arguments ...\n"); "usage: daemon [-cf] [-g group] [-p pidfile] [-u user] command "
"arguments ...\n");
exit(1); exit(1);
} }