Date: Thu, 30 Aug 2001 20:11:02 +0200 From: Joerg Wunsch <j@ida.interface-business.de> To: audit@freebsd.org Cc: security@freebsd.org Subject: why does telnetd run as root? Message-ID: <20010830201102.O69247@ida.interface-business.de>
next in thread | raw e-mail | index | archive | help
Upon answering the question in <subject>, i noticed that the only
reason for it is that login(1) currently requires root permissions in
case -h hostname is given on its invocation. (Port 23 is bound by
inetd anyway.) But then, it's IMHO much safer to run telnetd as user
`daemon', and have login(1) allow user daemon to pass -h. This
minimally increases the chance that someone might fake a hostname to
be logged in utmp/wtmp (although user dameon is not supposed to be a
usable account anyway), but adds us the ability to run telnetd with
the little-privileged ID of daemon, so the next buffer overflow at
least won't pose a root compromise...
Index: login.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/login/login.c,v
retrieving revision 1.51.2.11
diff -u -r1.51.2.11 login.c
--- login.c 2001/08/07 09:28:52 1.51.2.11
+++ login.c 2001/08/30 16:17:46
@@ -131,6 +131,7 @@
#define DEFAULT_RETRIES 10
#define DEFAULT_PROMPT "login: "
#define DEFAULT_PASSWD_PROMPT "Password:"
+#define DAEMONUSER "daemon"
/*
* This bounds the time given to login. Not a define so it can
@@ -158,7 +159,7 @@
struct utmp utmp;
int rootok, retries, backoff;
int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval;
- int changepass;
+ int changepass, allowhopt;
time_t warntime;
uid_t uid, euid;
gid_t egid;
@@ -167,6 +168,7 @@
char tname[sizeof(_PATH_TTY) + 10];
char *shell = NULL;
login_cap_t *lc = NULL;
+ struct passwd *daemonuser;
#ifdef USE_PAM
pid_t pid;
int e;
@@ -201,13 +203,26 @@
uid = getuid();
euid = geteuid();
egid = getegid();
+ /*
+ * Try finding user "daemon". If it exists, we will allow it to
+ * set the -h option, in addition to uid == 0. This allows telnetd
+ * to be run as daemon instead of root.
+ */
+ allowhopt = 0;
+ if (uid == 0)
+ allowhopt = 1;
+ else {
+ daemonuser = getpwnam(DAEMONUSER);
+ if (daemonuser && uid == daemonuser->pw_uid)
+ allowhopt = 1;
+ }
while ((ch = getopt(argc, argv, "fh:p")) != -1)
switch (ch) {
case 'f':
fflag = 1;
break;
case 'h':
- if (uid)
+ if (!allowhopt)
errx(1, "-h option: %s", strerror(EPERM));
hflag = 1;
strncpy(full_hostname, optarg, sizeof(full_hostname)-1);
--
J"org Wunsch Unix support engineer
joerg_wunsch@interface-systems.de http://www.interface-systems.de/~j/
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-security" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010830201102.O69247>
