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>