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.
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!!
#
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
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
* 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);
}
#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;
.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
.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
#include <arpa/inet.h>
#include <stdlib.h>
+#include <pwd.h>
#ifndef LOG_PERROR
#define LOG_PERROR 0
#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.
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':
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,
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);
}
}
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);