-/*
+/*-
* Copyright (c) 1980, 1987, 1988 The Regents of the University of California.
* All rights reserved.
*
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * %sccs.include.redist.c%
*/
#ifndef lint
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)login.c 5.47 (Berkeley) %G%";
+static char sccsid[] = "@(#)login.c 5.56 (Berkeley) %G%";
#endif /* not lint */
/*
*/
#include <sys/param.h>
-#include <ufs/quota.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/file.h>
-#include <sys/ioctl.h>
+#include <sgtty.h>
#include <utmp.h>
#include <signal.h>
#include <pwd.h>
#include <setjmp.h>
#include <stdio.h>
-#include <strings.h>
+#include <string.h>
#include <tzfile.h>
#include "pathnames.h"
* be patched on machines where it's too small.
*/
int timeout = 300;
+#ifdef KERBEROS
+int notickets = 1;
+#endif
struct passwd *pwd;
int failures;
-char term[64], *hostname, *username, *tty;
+char term[64], *envinit[1], *hostname, *username, *tty;
struct sgttyb sgttyb;
struct tchars tc = {
CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK
};
struct ltchars ltc = {
- CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT
+ CSUSP, CDSUSP, CRPRNT, CDISCARD, CWERASE, CLNEXT
};
char *months[] =
int argc;
char **argv;
{
- extern int errno, optind;
+ extern int optind;
extern char *optarg, **environ;
struct timeval tp;
struct tm *ttp;
register int ch;
register char *p;
int ask, fflag, hflag, pflag, rflag, cnt;
- int quietlog, passwd_req, ioctlval, timedout();
- char *domain, *salt, *envinit[1], *ttyn, *pp;
+ int quietlog, passwd_req, ioctlval, rval;
+ char *domain, *salt, *ttyn;
char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
char localhost[MAXHOSTNAMELEN];
char *ctime(), *ttyname(), *stypeof(), *crypt(), *getpass();
time_t time();
off_t lseek();
+ void timedout();
(void)signal(SIGALRM, timedout);
(void)alarm((u_int)timeout);
(void)signal(SIGQUIT, SIG_IGN);
(void)signal(SIGINT, SIG_IGN);
(void)setpriority(PRIO_PROCESS, 0, 0);
- (void)quota(Q_SETUID, 0, 0, 0);
+
+ openlog("login", LOG_ODELAY, LOG_AUTH);
/*
* -p is used by getty to tell login not to destroy the environment
fflag = hflag = pflag = rflag = 0;
passwd_req = 1;
+ uid = getuid();
while ((ch = getopt(argc, argv, "fh:pr:")) != EOF)
switch (ch) {
case 'f':
fflag = 1;
break;
case 'h':
- if (getuid()) {
+ if (uid) {
(void)fprintf(stderr,
"login: -h for super-user only.\n");
exit(1);
break;
case '?':
default:
- syslog(LOG_ERR, "invalid flag");
+ if (!uid)
+ syslog(LOG_ERR, "invalid flag %c", ch);
(void)fprintf(stderr,
"usage: login [-fp] [username]\n");
exit(1);
argv += optind;
if (*argv) {
username = *argv;
+ if (strlen(username) > UT_NAMESIZE)
+ username[UT_NAMESIZE] = '\0';
ask = 0;
} else
ask = 1;
else
tty = ttyn;
- openlog("login", LOG_ODELAY, LOG_AUTH);
-
for (cnt = 0;; ask = 1) {
ioctlval = TTYDISC;
(void)ioctl(0, TIOCSETD, &ioctlval);
getloginname();
}
/*
- * Note if trying multiple user names;
- * log failures for previous user name,
- * but don't bother logging one failure
+ * Note if trying multiple user names; log failures for
+ * previous user name, but don't bother logging one failure
* for nonexistent name (mistyped username).
*/
if (failures && strcmp(tbuf, username)) {
(void)strcpy(tbuf, username);
if (pwd = getpwnam(username))
salt = pwd->pw_passwd;
- else
- salt = "xx";
+ else {
+ /* take up the right amount of time */
+ (void)crypt(getpass("Password:"), "xx");
+ goto faked;
+ }
/* if user not super-user, check for disabled logins */
- if (pwd == NULL || pwd->pw_uid)
+ if (pwd->pw_uid)
checknologin();
/*
* Disallow automatic login to root; if not invoked by
* root, disallow if the uid's differ.
*/
- if (fflag && pwd) {
- int uid = getuid();
-
+ if (fflag) {
passwd_req =
#ifndef KERBEROS
pwd->pw_uid == 0 ||
* If no pre-authentication and a password exists
* for this user, prompt for one and verify it.
*/
- if (!passwd_req || (pwd && !*pwd->pw_passwd))
+ if (!passwd_req || !*pwd->pw_passwd)
break;
- setpriority(PRIO_PROCESS, 0, -4);
- pp = getpass("Password:");
- p = crypt(pp, salt);
- setpriority(PRIO_PROCESS, 0, 0);
+ /*
+ * If trying to log in as root, but with insecure terminal,
+ * refuse the login attempt.
+ */
+ if (pwd->pw_uid == 0 && !rootterm(tty)) {
+ (void)fprintf(stderr,
+ "%s login refused on this terminal.\n",
+ pwd->pw_name);
+ if (hostname)
+ syslog(LOG_NOTICE,
+ "LOGIN %s REFUSED FROM %s ON TTY %s",
+ pwd->pw_name, hostname, tty);
+ else
+ syslog(LOG_NOTICE,
+ "LOGIN %s REFUSED ON TTY %s",
+ pwd->pw_name, tty);
+ continue;
+ }
+
+ (void)setpriority(PRIO_PROCESS, 0, -4);
+ p = getpass("Password:");
- (void) bzero(pp, strlen(pp));
- if (pwd && !strcmp(p, pwd->pw_passwd))
+ bzero(p, strlen(p));
+ if (!rval)
break;
- (void)printf("Login incorrect\n");
+faked: (void)printf("Login incorrect\n");
failures++;
/* we allow 10 tries, but after 3 we start backing off */
if (++cnt > 3) {
/* committed to login -- turn off timeout */
(void)alarm((u_int)0);
+ /* reset priority */
+ (void)setpriority(PRIO_PROCESS, 0, 0);
+
/* paranoia... */
endpwent();
- /*
- * If valid so far and root is logging in, see if root logins on
- * this terminal are permitted.
- */
- if (pwd->pw_uid == 0 && !rootterm(tty)) {
- if (hostname)
- syslog(LOG_NOTICE, "ROOT LOGIN REFUSED FROM %s",
- hostname);
- else
- syslog(LOG_NOTICE, "ROOT LOGIN REFUSED ON %s", tty);
- (void)printf("Login incorrect\n");
- sleepexit(1);
- }
-
- if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) {
- switch(errno) {
- case EUSERS:
- (void)fprintf(stderr,
- "Too many users logged on already.\nTry again later.\n");
- break;
- case EPROCLIM:
- (void)fprintf(stderr,
- "You have too many processes running.\n");
- break;
- default:
- perror("quota (Q_SETUID)");
- }
- sleepexit(0);
- }
-
if (chdir(pwd->pw_dir) < 0) {
(void)printf("No directory %s!\n", pwd->pw_dir);
if (chdir("/"))
pwd->pw_dir = "/";
(void)printf("Logging in with home = \"/\".\n");
}
-
#define TWOWEEKS (14*24*60*60)
if (pwd->pw_change || pwd->pw_expire)
(void)gettimeofday(&tp, (struct timezone *)NULL);
{
struct utmp utmp;
- bzero((char *)&utmp, sizeof(utmp));
+ bzero((void *)&utmp, sizeof(utmp));
(void)time(&utmp.ut_time);
strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
if (hostname)
initgroups(username, pwd->pw_gid);
- quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0);
-
if (*pwd->pw_shell == '\0')
pwd->pw_shell = _PATH_BSHELL;
else
syslog(LOG_NOTICE, "ROOT LOGIN ON %s", tty);
+#ifdef KERBEROS
+ if (!quietlog && notickets == 1)
+ (void)printf("Warning: no Kerberos tickets issued.\n");
+#endif
+
if (!quietlog) {
struct stat st;
strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ?
p + 1 : pwd->pw_shell);
- if (setlogname(pwd->pw_name, strlen(pwd->pw_name)) < 0)
- syslog(LOG_ERR, "setlogname() failure: %m");
+ if (setlogin(pwd->pw_name) < 0)
+ syslog(LOG_ERR, "setlogin() failure: %m");
/* discard permissions last so can't get killed and drop core */
(void)setuid(pwd->pw_uid);
}
}
+void
timedout()
{
(void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
}
(void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
}
- bzero((char *)&ll, sizeof(ll));
+ bzero((void *)&ll, sizeof(ll));
(void)time(&ll.ll_time);
strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
if (hostname)
return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
}
-getstr(buf, cnt, err)
- char *buf, *err;
- int cnt;
-{
- char ch;
-
- do {
- if (read(0, &ch, sizeof(ch)) != sizeof(ch))
- exit(1);
- if (--cnt < 0) {
- (void)fprintf(stderr, "%s too long\r\n", err);
- sleepexit(1);
- }
- *buf++ = ch;
- } while (ch);
-}
-
sleepexit(eval)
int eval;
{