From 3aa03ff5f95dcb78fdc29fd858ed07effe7d502b Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 23 Apr 2007 16:20:17 +1000 Subject: [PATCH] Allow uid/gid to be set at compile or run time. New compile time options to set uid and gid rather than default of '1'. Also compile-time configurable username to provide uid/gid. Also -u and -g runtime options to set same. --- Makefile | 26 +++++++++++++++++++++++--- pmap_check.c | 4 ++-- pmap_check.h | 3 +++ portmap.8 | 13 +++++++++++++ portmap.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 87 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 1376ea7..23f361b 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,23 @@ endif CPPFLAGS += -DCHECK_PORT +# The portmap daemon runs a uid=1/gid=1 by default. You can change that +# be defining DAEMON_UID and DAMEON_GID to numbers, or RPCUSER to a +# name, though you must be sure that name lookup will not require use +# of portmap. +ifdef RPCUSER +CPPFLAGS += -DRPCUSER=\"$(RPCUSER)\" +MAN_SED += -e 's/RPCUSER/$(RPCUSER)/' +else +MAN_SED += -e 's/RPCUSER//' +endif +ifdef DAEMON_UID +CPPFLAGS += -DDAEMON_UID=$(DAEMON_UID) -DDAEMON_GID=$(DAEMON_GID) +MAN_SED += -e 's/DAEMON_UID/$(DAEMON_UID)/' -e 's/DAEMON_GID/$(DAEMON_GID)/' +else +MAN_SED += -e 's/DAEMON_UID/1/' -e 's/DAEMON_GID/1/' +endif + # Warning: troublesome feature ahead!! Enable only when you are really # desperate!! # @@ -98,7 +115,7 @@ CPPFLAGS += -DFACILITY=$(FACILITY) CFLAGS ?= -O2 CFLAGS += -Wall -Wstrict-prototypes -all: portmap pmap_dump pmap_set +all: portmap pmap_dump pmap_set portmap.man CPPFLAGS += $(HOSTS_ACCESS) portmap: CFLAGS += -fpie @@ -108,17 +125,20 @@ portmap: portmap.o pmap_check.o from_local.o from_local: CPPFLAGS += -DTEST +portmap.man : portmap.8 + sed $(MAN_SED) < portmap.8 > portmap.man + install: all install -o root -g root -m 0755 -s portmap ${BASEDIR}/sbin install -o root -g root -m 0755 -s pmap_dump ${BASEDIR}/sbin install -o root -g root -m 0755 -s pmap_set ${BASEDIR}/sbin - install -o root -g root -m 0644 portmap.8 ${BASEDIR}/usr/share/man/man8 + install -o root -g root -m 0644 portmap.man ${BASEDIR}/usr/share/man/man8/portmap.8 install -o root -g root -m 0644 pmap_dump.8 ${BASEDIR}/usr/share/man/man8 install -o root -g root -m 0644 pmap_set.8 ${BASEDIR}/usr/share/man/man8 clean: rm -f *.o portmap pmap_dump pmap_set from_local \ - core + core portmap.man -include .depend .depend: *.c diff --git a/pmap_check.c b/pmap_check.c index 1fed2e1..116eb49 100644 --- a/pmap_check.c +++ b/pmap_check.c @@ -106,9 +106,9 @@ void check_startup(void) * Give up root privileges so that we can never allocate a privileged * port when forwarding an rpc request. */ - setgid(1); + setgid(daemon_gid); setgroups(0, NULL); - if (setuid(1) == -1) { + if (setuid(daemon_uid) == -1) { syslog(LOG_ERR, "setuid(1) failed: %m"); exit(1); } diff --git a/pmap_check.h b/pmap_check.h index ba18f33..abc30d6 100644 --- a/pmap_check.h +++ b/pmap_check.h @@ -28,3 +28,6 @@ extern int deny_severity __attribute__ ((visibility ("hidden"))); #define CHECK_SETUNSET(xprt,ludp,ltcp,proc,prog,port) \ check_setunset(svc_getcaller(xprt),proc,prog,port) #endif + +extern int daemon_uid; +extern int daemon_gid; diff --git a/portmap.8 b/portmap.8 index c021e15..f4d5d94 100644 --- a/portmap.8 +++ b/portmap.8 @@ -51,6 +51,8 @@ program number mapper .Op Fl v .Op Fl i Ar address .Op Fl l +.Op Fl u Ar uid +.Op Fl g Ar gid .Sh DESCRIPTION .Nm Portmap is a server that converts @@ -122,6 +124,17 @@ into .Ar dir should be empty, not writeable by the daemon user, and preferably on a filesystem mounted read-only, noexec, nodev, and nosuid. +.It Fl u Ar uid +.It Fl g Ar gid +Set the user-id and group-id of the running process to those given, +rather than the compiled-in defaults of DAEMON_UID/DAEMON_GID. +.if 'RPCUSER'' .ig +If neither are set, then +.Nm portmap +will look up the user +.Nm RPCUSER +and use the uid and gid of that user. +.. .It Fl v (verbose) run .Nm portmap diff --git a/portmap.c b/portmap.c index e561415..d1dd8c2 100644 --- a/portmap.c +++ b/portmap.c @@ -102,6 +102,7 @@ static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro"; #include #include +#include #ifndef LOG_PERROR #define LOG_PERROR 0 @@ -153,6 +154,14 @@ static int on = 1; #endif #endif +#ifdef DAEMON_UID +int daemon_uid = DAEMON_UID; +int daemon_gid = DAEMON_GID; +#else +int daemon_uid = 1; +int daemon_gid = 1; +#endif + /* * We record with each registration a flag telling whether it was * registered with a privilege port or not. @@ -178,10 +187,29 @@ main(int argc, char **argv) struct in_addr bindaddr; int have_bindaddr = 0; int foreground = 0; + int have_uid = 0; - while ((c = getopt(argc, argv, "dflt:vi:")) != EOF) { + while ((c = getopt(argc, argv, "dflt:vi:u:g:")) != EOF) { switch (c) { + case 'u': + daemon_uid = atoi(optarg); + if (daemon_uid <= 0) { + fprintf(stderr, + "portmap: illegal uid: %s\n", optarg); + exit(1); + } + have_uid = 1; + break; + case 'g': + daemon_gid = atoi(optarg); + if (daemon_gid <= 0) { + fprintf(stderr, + "portmap: illegal gid: %s\n", optarg); + exit(1); + } + have_uid = 1; + break; case 'd': debugging = 1; case 'f': @@ -204,7 +232,8 @@ main(int argc, char **argv) break; default: fprintf(stderr, - "usage: %s [-dflv] [-t dir] [-i address]\n", + "usage: %s [-dflv] [-t dir] [-i address] " + "[-u uid] [-g gid]\n", argv[0]); fprintf(stderr, "-d: debugging mode\n"); fprintf(stderr, @@ -213,6 +242,8 @@ main(int argc, char **argv) fprintf(stderr, "-v: verbose logging\n"); fprintf(stderr, "-i address: bind to address\n"); fprintf(stderr, "-l: same as -i 127.0.0.1\n"); + fprintf(stderr, "-u uid : setuid to this uid\n"); + fprintf(stderr, "-g uid : setgid to this gid\n"); exit(1); } } @@ -229,6 +260,19 @@ main(int argc, char **argv) openlog("portmap", LOG_PID|LOG_NDELAY | ( foreground ? LOG_PERROR : 0)); #endif +#ifdef RPCUSER + if (!have_uid) { + struct passwd *pwent; + pwent = getpwnam(RPCUSER); + if (pwent) { + daemon_uid = pwent->pw_uid; + daemon_gid = pwent->pw_gid; + } else + syslog(LOG_WARNING, "user '" RPCUSER + "' not found, reverting to default uid"); + } +#endif + if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { syslog(LOG_ERR, "cannot create udp socket: %m"); exit(1); -- 2.39.5