summaryrefslogtreecommitdiffstats
path: root/crypto/kerberosIV/appl/bsd/login.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/kerberosIV/appl/bsd/login.c')
-rw-r--r--crypto/kerberosIV/appl/bsd/login.c990
1 files changed, 990 insertions, 0 deletions
diff --git a/crypto/kerberosIV/appl/bsd/login.c b/crypto/kerberosIV/appl/bsd/login.c
new file mode 100644
index 0000000..c436f8d
--- /dev/null
+++ b/crypto/kerberosIV/appl/bsd/login.c
@@ -0,0 +1,990 @@
+/*-
+ * Copyright (c) 1980, 1987, 1988, 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * login [ name ]
+ * login -h hostname (for telnetd, etc.)
+ * login -f name (for pre-authenticated login: datakit, xterm, etc.)
+ */
+
+#include "bsd_locl.h"
+
+RCSID("$Id: login.c,v 1.104 1997/05/20 20:35:06 assar Exp $");
+
+#include <otp.h>
+
+#include "sysv_default.h"
+#ifdef SYSV_SHADOW
+#include "sysv_shadow.h"
+#endif
+
+static void badlogin (char *);
+static void checknologin (void);
+static void dolastlog (int);
+static void getloginname (int);
+static int rootterm (char *);
+static char *stypeof (char *);
+static RETSIGTYPE timedout (int);
+static int doremotelogin (char *);
+void login_fbtab (char *, uid_t, gid_t);
+#ifdef KERBEROS
+int klogin (struct passwd *, char *, char *, char *);
+#endif
+
+#define TTYGRPNAME "tty" /* name of group to own ttys */
+
+/*
+ * This bounds the time given to login. Change it in
+ * `/etc/default/login'.
+ */
+
+static u_int login_timeout;
+
+#ifdef KERBEROS
+int notickets = 1;
+int noticketsdontcomplain = 1;
+char *instance;
+char *krbtkfile_env;
+int authok;
+#endif
+
+#ifdef HAVE_SHADOW_H
+static struct spwd *spwd = NULL;
+#endif
+
+static char *ttyprompt;
+
+static struct passwd *pwd;
+static int failures;
+static char term[64], *hostname, *username, *tty;
+
+static char rusername[100], lusername[100];
+
+static int
+change_passwd(struct passwd *who)
+{
+ int status;
+ int pid;
+ int wpid;
+
+ switch (pid = fork()) {
+ case -1:
+ warn("fork /bin/passwd");
+ sleepexit(1);
+ case 0:
+ execlp("/bin/passwd", "passwd", who->pw_name, (char *) 0);
+ _exit(1);
+ default:
+ while ((wpid = wait(&status)) != -1 && wpid != pid)
+ /* void */ ;
+ return (status);
+ }
+}
+
+#ifndef NO_MOTD /* message of the day stuff */
+
+jmp_buf motdinterrupt;
+
+static RETSIGTYPE
+sigint(int signo)
+{
+ longjmp(motdinterrupt, 1);
+}
+
+static void
+motd(void)
+{
+ int fd, nchars;
+ RETSIGTYPE (*oldint)();
+ char tbuf[8192];
+
+ if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
+ return;
+ oldint = signal(SIGINT, sigint);
+ if (setjmp(motdinterrupt) == 0)
+ while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+ write(fileno(stdout), tbuf, nchars);
+ signal(SIGINT, oldint);
+ close(fd);
+}
+
+#endif /* !NO_MOTD */
+
+#define AUTH_NONE 0
+#define AUTH_OTP 1
+
+/*
+ * getpwnam and try to detect the worst form of NIS attack.
+ */
+
+static struct passwd *
+paranoid_getpwnam (char *user)
+{
+ struct passwd *p;
+
+ p = k_getpwnam (user);
+ if (p == NULL)
+ return p;
+ if (p->pw_uid == 0 && strcmp (username, "root") != 0) {
+ syslog (LOG_ALERT,
+ "NIS attack, user %s has uid 0", username);
+ return NULL;
+ }
+ return p;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct group *gr;
+ int ask, ch, cnt, fflag, hflag, pflag, quietlog, nomailcheck;
+ int rootlogin, rval;
+ int rflag;
+ int changepass = 0;
+ uid_t uid;
+ char *domain, *p, passwd[128], *ttyn;
+ char tbuf[MaxPathLen + 2], tname[sizeof(_PATH_TTY) + 10];
+ char localhost[MaxHostNameLen];
+ char full_hostname[MaxHostNameLen];
+ int auth_level = AUTH_NONE;
+ OtpContext otp_ctx;
+ int mask = 022; /* Default umask (set below) */
+ int maxtrys = 5; /* Default number of allowed failed logins */
+
+ set_progname(argv[0]);
+
+ openlog("login", LOG_ODELAY, LOG_AUTH);
+
+ /* Read defaults file and set the login timeout period. */
+ sysv_defaults();
+ login_timeout = atoi(default_timeout);
+ maxtrys = atoi(default_maxtrys);
+ if (sscanf(default_umask, "%o", &mask) != 1 || (mask & ~0777))
+ syslog(LOG_WARNING, "bad umask default: %s", default_umask);
+ else
+ umask(mask);
+
+ signal(SIGALRM, timedout);
+ alarm(login_timeout);
+ signal(SIGQUIT, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ setpriority(PRIO_PROCESS, 0, 0);
+
+ /*
+ * -p is used by getty to tell login not to destroy the environment
+ * -f is used to skip a second login authentication
+ * -h is used by other servers to pass the name of the remote
+ * host to login so that it may be placed in utmp and wtmp
+ * -r is used by old-style rlogind to execute the autologin protocol
+ */
+
+ *full_hostname = '\0';
+ domain = NULL;
+ if (k_gethostname(localhost, sizeof(localhost)) < 0)
+ syslog(LOG_ERR, "couldn't get local hostname: %m");
+ else
+ domain = strchr(localhost, '.');
+
+ fflag = hflag = pflag = rflag = 0;
+ uid = getuid();
+ while ((ch = getopt(argc, argv, "a:d:fh:pr:")) != EOF)
+ switch (ch) {
+ case 'a':
+ if (strcmp (optarg, "none") == 0)
+ auth_level = AUTH_NONE;
+ else if (strcmp (optarg, "otp") == 0)
+ auth_level = AUTH_OTP;
+ else
+ warnx ("bad value for -a: %s", optarg);
+ break;
+ case 'd':
+ break;
+ case 'f':
+ fflag = 1;
+ break;
+ case 'h':
+ if (rflag || hflag) {
+ printf("Only one of -r and -h allowed\n");
+ exit(1);
+ }
+ if (uid)
+ errx(1, "-h option: %s", strerror(EPERM));
+ hflag = 1;
+ strncpy(full_hostname, optarg, sizeof(full_hostname)-1);
+ if (domain && (p = strchr(optarg, '.')) &&
+ strcasecmp(p, domain) == 0)
+ *p = 0;
+ hostname = optarg;
+ break;
+ case 'p':
+ if (getuid()) {
+ warnx("-p for super-user only.");
+ exit(1);
+ }
+ pflag = 1;
+ break;
+ case 'r':
+ if (rflag || hflag) {
+ warnx("Only one of -r and -h allowed\n");
+ exit(1);
+ }
+ if (getuid()) {
+ warnx("-r for super-user only.");
+ exit(1);
+ }
+ rflag = 1;
+ strncpy(full_hostname, optarg, sizeof(full_hostname)-1);
+ if (domain && (p = strchr(optarg, '.')) &&
+ strcasecmp(p, domain) == 0)
+ *p = 0;
+ hostname = optarg;
+ fflag = (doremotelogin(full_hostname) == 0);
+ break;
+ case '?':
+ default:
+ if (!uid)
+ syslog(LOG_ERR, "invalid flag %c", ch);
+ fprintf(stderr,
+ "usage: login [-fp] [-a otp]"
+ "[-h hostname | -r hostname] [username]\n");
+ exit(1);
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (geteuid() != 0) {
+ warnx("only root may use login, use su");
+ /* Or install login setuid root, which is not necessary */
+ sleep(10);
+ exit(1);
+ }
+ /*
+ * Figure out if we should ask for the username or not. The name
+ * may be given on the command line or via the environment, and
+ * it may even be in the terminal input queue.
+ */
+ if (rflag) {
+ username = lusername;
+ ask = 0;
+ } else
+ if (*argv && strchr(*argv, '=')) {
+ ask = 1;
+ } else
+ if (*argv && strcmp(*argv, "-") == 0) {
+ argc--;
+ argv++;
+ ask = 1;
+ } else
+ if (*argv) {
+ username = *argv;
+ ask = 0;
+ argc--;
+ argv++;
+ } else if ((ttyprompt = getenv("TTYPROMPT")) && *ttyprompt) {
+ getloginname(0);
+ ask = 0;
+ } else
+ ask = 1;
+
+ /* Default tty settings. */
+ stty_default();
+
+ for (cnt = getdtablesize(); cnt > 2; cnt--)
+ close(cnt);
+
+ /*
+ * Determine the tty name. BSD takes the basename, SYSV4 takes
+ * whatever remains after stripping the "/dev/" prefix. The code
+ * below should produce sensible results in either environment.
+ */
+ ttyn = ttyname(STDIN_FILENO);
+ if (ttyn == NULL || *ttyn == '\0') {
+ snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
+ ttyn = tname;
+ }
+ if ((tty = strchr(ttyn + 1, '/')))
+ ++tty;
+ else
+ tty = ttyn;
+
+ for (cnt = 0;; ask = 1) {
+ char prompt[128], ss[256];
+ if (ask) {
+ fflag = 0;
+ getloginname(1);
+ }
+ rootlogin = 0;
+ rval = 1;
+#ifdef KERBEROS
+ if ((instance = strchr(username, '.')) != NULL) {
+ if (strcmp(instance, ".root") == 0)
+ rootlogin = 1;
+ *instance++ = '\0';
+ } else
+ instance = "";
+#endif
+ if (strlen(username) > UT_NAMESIZE)
+ username[UT_NAMESIZE] = '\0';
+
+ /*
+ * 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)) {
+ if (failures > (pwd ? 0 : 1))
+ badlogin(tbuf);
+ failures = 0;
+ }
+ strcpy(tbuf, username);
+
+ pwd = paranoid_getpwnam (username);
+
+ /*
+ * if we have a valid account name, and it doesn't have a
+ * password, or the -f option was specified and the caller
+ * is root or the caller isn't changing their uid, don't
+ * authenticate.
+ */
+ if (pwd) {
+ if (pwd->pw_uid == 0)
+ rootlogin = 1;
+
+ if (fflag && (uid == 0 || uid == pwd->pw_uid)) {
+ /* already authenticated */
+ break;
+ } else if (pwd->pw_passwd[0] == '\0') {
+ /* pretend password okay */
+ rval = 0;
+ goto ttycheck;
+ }
+ }
+
+ fflag = 0;
+
+ setpriority(PRIO_PROCESS, 0, -4);
+
+ if (otp_challenge (&otp_ctx, username,
+ ss, sizeof(ss)) == 0)
+ snprintf (prompt, sizeof(prompt), "%s's %s Password: ",
+ username, ss);
+ else {
+ if (auth_level == AUTH_NONE)
+ snprintf(prompt, sizeof(prompt), "%s's Password: ",
+ username);
+ else {
+ char *s;
+
+ rval = 1;
+ s = otp_error(&otp_ctx);
+ if(s)
+ printf ("OTP: %s\n", s);
+ continue;
+ }
+ }
+
+ if (des_read_pw_string (passwd, sizeof(passwd) - 1, prompt, 0))
+ continue;
+ passwd[sizeof(passwd) - 1] = '\0';
+
+ /* Verify it somehow */
+
+ if (otp_verify_user (&otp_ctx, passwd) == 0)
+ rval = 0;
+ else if (pwd == NULL)
+ ;
+ else if (auth_level == AUTH_NONE) {
+ uid_t pwd_uid = pwd->pw_uid;
+
+ rval = unix_verify_user (username, passwd);
+
+ if (rval == 0)
+ {
+ if (rootlogin && pwd_uid != 0)
+ rootlogin = 0;
+ }
+ else
+ {
+ rval = klogin(pwd, instance, localhost, passwd);
+ if (rval != 0 && rootlogin && pwd_uid != 0)
+ rootlogin = 0;
+ if (rval == 0)
+ authok = 1;
+ }
+ } else {
+ char *s;
+
+ rval = 1;
+ if ((s = otp_error(&otp_ctx)))
+ printf ("OTP: %s\n", s);
+ }
+
+ memset (passwd, 0, sizeof(passwd));
+ setpriority (PRIO_PROCESS, 0, 0);
+
+ /*
+ * Santa Claus, give me a portable and reentrant getpwnam.
+ */
+ pwd = paranoid_getpwnam (username);
+
+ ttycheck:
+ /*
+ * If trying to log in as root without Kerberos,
+ * but with insecure terminal, refuse the login attempt.
+ */
+#ifdef KERBEROS
+ if (authok == 0)
+#endif
+ if (pwd && !rval && rootlogin && !rootterm(tty)
+ && !rootterm(ttyn)) {
+ warnx("%s login refused on this terminal.",
+ 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;
+ }
+
+ if (rval == 0)
+ break;
+
+ printf("Login incorrect\n");
+ failures++;
+
+ /* max number of attemps and delays taken from defaults file */
+ /* we allow maxtrys tries, but after 2 we start backing off */
+ if (++cnt > 2) {
+ if (cnt >= maxtrys) {
+ badlogin(username);
+ sleepexit(1);
+ }
+ sleep((u_int)((cnt - 2) * atoi(default_sleep)));
+ }
+ }
+
+ /* committed to login -- turn off timeout */
+ alarm(0);
+
+ endpwent();
+
+#if defined(HAVE_GETUDBNAM) && defined(HAVE_SETLIM)
+ {
+ struct udb *udb;
+ long t;
+ const long maxcpu = 46116860184; /* some random constant */
+ udb = getudbnam(pwd->pw_name);
+ if(udb == UDB_NULL){
+ warnx("Failed to get UDB entry.");
+ exit(1);
+ }
+ t = udb->ue_pcpulim[UDBRC_INTER];
+ if(t == 0 || t > maxcpu)
+ t = CPUUNLIM;
+ else
+ t *= 100 * CLOCKS_PER_SEC;
+
+ if(limit(C_PROC, 0, L_CPU, t) < 0)
+ warn("limit C_PROC");
+
+ t = udb->ue_jcpulim[UDBRC_INTER];
+ if(t == 0 || t > maxcpu)
+ t = CPUUNLIM;
+ else
+ t *= 100 * CLOCKS_PER_SEC;
+
+ if(limit(C_JOBPROCS, 0, L_CPU, t) < 0)
+ warn("limit C_JOBPROCS");
+
+ nice(udb->ue_nice[UDBRC_INTER]);
+ }
+#endif
+ /* if user not super-user, check for disabled logins */
+ if (!rootlogin)
+ checknologin();
+
+ if (chdir(pwd->pw_dir) < 0) {
+ printf("No home directory %s!\n", pwd->pw_dir);
+ if (chdir("/"))
+ exit(0);
+ pwd->pw_dir = "/";
+ printf("Logging in with home = \"/\".\n");
+ }
+
+ quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
+ nomailcheck = access(_PATH_NOMAILCHECK, F_OK) == 0;
+
+#if defined(HAVE_PASSWD_CHANGE) && defined(HAVE_PASSWD_EXPIRE)
+ if (pwd->pw_change || pwd->pw_expire)
+ gettimeofday(&tp, (struct timezone *)NULL);
+
+ if (pwd->pw_change)
+ if (tp.tv_sec >= pwd->pw_change) {
+ printf("Sorry -- your password has expired.\n");
+ changepass=1;
+ } else if (pwd->pw_change - tp.tv_sec <
+ 2 * DAYSPERWEEK * SECSPERDAY && !quietlog)
+ printf("Warning: your password expires on %s",
+ ctime(&pwd->pw_change));
+ if (pwd->pw_expire)
+ if (tp.tv_sec >= pwd->pw_expire) {
+ printf("Sorry -- your account has expired.\n");
+ sleepexit(1);
+ } else if (pwd->pw_expire - tp.tv_sec <
+ 2 * DAYSPERWEEK * SECSPERDAY && !quietlog)
+ printf("Warning: your account expires on %s",
+ ctime(&pwd->pw_expire));
+#endif /* defined(HAVE_PASSWD_CHANGE) && defined(HAVE_PASSWD_EXPIRE) */
+
+ /* Nothing else left to fail -- really log in. */
+
+ /*
+ * Update the utmp files, both BSD and SYSV style.
+ */
+ if (utmpx_login(tty, username, hostname ? hostname : "") != 0
+ && !fflag) {
+ printf("No utmpx entry. You must exec \"login\" from the lowest level \"sh\".\n");
+ sleepexit(0);
+ }
+ utmp_login(ttyn, username, hostname ? hostname : "");
+ dolastlog(quietlog);
+
+ /*
+ * Set device protections, depending on what terminal the
+ * user is logged in. This feature is used on Suns to give
+ * console users better privacy.
+ */
+ login_fbtab(tty, pwd->pw_uid, pwd->pw_gid);
+
+ chown(ttyn, pwd->pw_uid,
+ (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
+ chmod(ttyn, S_IRUSR | S_IWUSR | S_IWGRP);
+ setgid(pwd->pw_gid);
+
+ initgroups(username, pwd->pw_gid);
+
+ if (*pwd->pw_shell == '\0')
+ pwd->pw_shell = _PATH_BSHELL;
+
+ /*
+ * Set up a new environment. With SYSV, some variables are always
+ * preserved; some varables are never preserved, and some variables
+ * are always clobbered. With BSD, nothing is always preserved, and
+ * some variables are always clobbered. We add code to make sure
+ * that LD_* and IFS are never preserved.
+ */
+ if (term[0] == '\0')
+ strncpy(term, stypeof(tty), sizeof(term));
+ /* set up a somewhat censored environment. */
+ sysv_newenv(argc, argv, pwd, term, pflag);
+#ifdef KERBEROS
+ if (krbtkfile_env)
+ setenv("KRBTKFILE", krbtkfile_env, 1);
+#endif
+
+ if (tty[sizeof("tty")-1] == 'd')
+ syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
+
+ /* If fflag is on, assume caller/authenticator has logged root login. */
+ if (rootlogin && fflag == 0)
+ if (hostname)
+ syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s",
+ username, tty, hostname);
+ else
+ syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty);
+
+#ifdef KERBEROS
+ if (!quietlog && notickets == 1 && !noticketsdontcomplain)
+ printf("Warning: no Kerberos tickets issued.\n");
+#endif
+
+#ifdef LOGALL
+ /*
+ * Syslog each successful login, so we don't have to watch hundreds
+ * of wtmp or lastlogin files.
+ */
+ if (hostname) {
+ syslog(LOG_INFO, "login from %s as %s", hostname, pwd->pw_name);
+ } else {
+ syslog(LOG_INFO, "login on %s as %s", tty, pwd->pw_name);
+ }
+#endif
+
+#ifndef NO_MOTD
+ /*
+ * Optionally show the message of the day. System V login leaves
+ * motd and mail stuff up to the shell startup file.
+ */
+ if (!quietlog) {
+ struct stat st;
+#if 0
+ printf("%s\n\t%s %s\n\n",
+ "Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994",
+ "The Regents of the University of California. ",
+ "All rights reserved.");
+#endif
+ motd();
+ if(!nomailcheck){
+ snprintf(tbuf, sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
+ if (stat(tbuf, &st) == 0 && st.st_size != 0)
+ printf("You have %smail.\n",
+ (st.st_mtime > st.st_atime) ? "new " : "");
+ }
+ }
+#endif /* NO_MOTD */
+
+#ifdef LOGIN_ACCESS
+ if (login_access(pwd->pw_name, hostname ? full_hostname : tty) == 0) {
+ printf("Permission denied\n");
+ if (hostname)
+ syslog(LOG_NOTICE, "%s LOGIN REFUSED FROM %s",
+ pwd->pw_name, hostname);
+ else
+ syslog(LOG_NOTICE, "%s LOGIN REFUSED ON %s",
+ pwd->pw_name, tty);
+ sleepexit(1);
+ }
+#endif
+
+ signal(SIGALRM, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGTSTP, SIG_IGN);
+
+ tbuf[0] = '-';
+ strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
+ p + 1 : pwd->pw_shell);
+
+#ifdef HAVE_SETLOGIN
+ if (setlogin(pwd->pw_name) < 0)
+ syslog(LOG_ERR, "setlogin() failure: %m");
+#endif
+
+#ifdef HAVE_SETPCRED
+ if (setpcred (pwd->pw_name, NULL) == -1)
+ syslog(LOG_ERR, "setpcred() failure: %m");
+#endif /* HAVE_SETPCRED */
+
+#if defined(SYSV_SHADOW) && defined(HAVE_GETSPNAM)
+ spwd = getspnam (username);
+ endspent ();
+#endif
+ /* Discard permissions last so can't get killed and drop core. */
+ {
+ int uid = rootlogin ? 0 : pwd->pw_uid;
+ if(setuid(uid) != 0){
+ warn("setuid(%d)", uid);
+ if(!rootlogin)
+ exit(1);
+ }
+ }
+
+
+ /*
+ * After dropping privileges and after cleaning up the environment,
+ * optionally run, as the user, /bin/passwd.
+ */
+
+ if (pwd->pw_passwd[0] == 0 &&
+ strcasecmp(default_passreq, "YES") == 0) {
+ printf("You don't have a password. Choose one.\n");
+ if (change_passwd(pwd))
+ sleepexit(0);
+ changepass = 0;
+ }
+
+#ifdef SYSV_SHADOW
+ if (spwd && sysv_expire(spwd)) {
+ if (change_passwd(pwd))
+ sleepexit(0);
+ changepass = 0;
+ }
+#endif /* SYSV_SHADOW */
+ if (changepass) {
+ int res;
+ if ((res=system(_PATH_CHPASS)))
+ sleepexit(1);
+ }
+
+ if (k_hasafs()) {
+ char cell[64];
+ k_setpag();
+ if(k_afs_cell_of_file(pwd->pw_dir, cell, sizeof(cell)) == 0)
+ k_afsklog(cell, 0);
+ k_afsklog(0, 0);
+ }
+
+ execlp(pwd->pw_shell, tbuf, 0);
+ if (getuid() == 0) {
+ warnx("Can't exec %s, trying %s\n",
+ pwd->pw_shell, _PATH_BSHELL);
+ execlp(_PATH_BSHELL, tbuf, 0);
+ err(1, "%s", _PATH_BSHELL);
+ }
+ err(1, "%s", pwd->pw_shell);
+ return 1;
+}
+
+#ifdef KERBEROS
+#define NBUFSIZ (UT_NAMESIZE + 1 + 5) /* .root suffix */
+#else
+#define NBUFSIZ (UT_NAMESIZE + 1)
+#endif
+
+static void
+getloginname(int prompt)
+{
+ int ch;
+ char *p;
+ static char nbuf[NBUFSIZ];
+
+ for (;;) {
+ if (prompt)
+ if (ttyprompt && *ttyprompt)
+ printf("%s", ttyprompt);
+ else
+ printf("login: ");
+ prompt = 1;
+ for (p = nbuf; (ch = getchar()) != '\n'; ) {
+ if (ch == EOF) {
+ badlogin(username);
+ exit(0);
+ }
+ if (p < nbuf + (NBUFSIZ - 1))
+ *p++ = ch;
+ }
+ if (p > nbuf)
+ if (nbuf[0] == '-')
+ warnx("login names may not start with '-'.");
+ else {
+ *p = '\0';
+ username = nbuf;
+ break;
+ }
+ }
+}
+
+static int
+rootterm(char *ttyn)
+{
+#ifndef HAVE_TTYENT_H
+ return (default_console == 0 || strcmp(default_console, ttyname(0)) == 0);
+#else
+ struct ttyent *t;
+
+ return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
+#endif
+}
+
+static RETSIGTYPE
+timedout(int signo)
+{
+ fprintf(stderr, "Login timed out after %d seconds\n",
+ login_timeout);
+ exit(0);
+}
+
+static void
+checknologin(void)
+{
+ int fd, nchars;
+ char tbuf[8192];
+
+ if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) {
+ while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+ write(fileno(stdout), tbuf, nchars);
+ sleepexit(0);
+ }
+}
+
+static void
+dolastlog(int quiet)
+{
+#if defined(HAVE_LASTLOG_H) || defined(HAVE_LOGIN_H) || defined(SYSV_SHADOW)
+ struct lastlog ll;
+ int fd;
+
+ if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
+ lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
+#ifdef SYSV_SHADOW
+ if (read(fd, &ll, sizeof(ll)) == sizeof(ll) &&
+ ll.ll_time != 0) {
+ if (pwd->pw_uid && spwd && spwd->sp_inact > 0
+ && ll.ll_time / (24 * 60 * 60)
+ + spwd->sp_inact < time(0)) {
+ printf("Your account has been inactive too long.\n");
+ sleepexit(1);
+ }
+ if (!quiet) {
+ printf("Last login: %.*s ",
+ 24-5, ctime(&ll.ll_time));
+ if (*ll.ll_host != '\0') {
+ printf("from %.*s\n",
+ (int)sizeof(ll.ll_host),
+ ll.ll_host);
+ } else
+ printf("on %.*s\n",
+ (int)sizeof(ll.ll_line),
+ ll.ll_line);
+ }
+ }
+ lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
+#else /* SYSV_SHADOW */
+ if (!quiet) {
+ if (read(fd, &ll, sizeof(ll)) == sizeof(ll) &&
+ ll.ll_time != 0) {
+ printf("Last login: %.*s ",
+ 24-5, ctime(&ll.ll_time));
+ if (*ll.ll_host != '\0')
+ printf("from %.*s\n",
+ (int)sizeof(ll.ll_host),
+ ll.ll_host);
+ else
+ printf("on %.*s\n",
+ (int)sizeof(ll.ll_line),
+ ll.ll_line);
+ }
+ lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET);
+ }
+#endif /* SYSV_SHADOW */
+ memset(&ll, 0, sizeof(ll));
+ time(&ll.ll_time);
+ strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
+ if (hostname)
+ strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
+ write(fd, &ll, sizeof(ll));
+ close(fd);
+ }
+#endif /* DOLASTLOG */
+}
+
+static void
+badlogin(char *name)
+{
+
+ if (failures == 0)
+ return;
+ if (hostname) {
+ syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
+ failures, failures > 1 ? "S" : "", hostname);
+ syslog(LOG_AUTHPRIV|LOG_NOTICE,
+ "%d LOGIN FAILURE%s FROM %s, %s",
+ failures, failures > 1 ? "S" : "", hostname, name);
+ } else {
+ syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
+ failures, failures > 1 ? "S" : "", tty);
+ syslog(LOG_AUTHPRIV|LOG_NOTICE,
+ "%d LOGIN FAILURE%s ON %s, %s",
+ failures, failures > 1 ? "S" : "", tty, name);
+ }
+}
+
+#undef UNKNOWN
+#define UNKNOWN "su"
+
+static char *
+stypeof(char *ttyid)
+{
+ /* TERM is probably a better guess than anything else. */
+ char *term = getenv("TERM");
+
+ if (term != 0 && term[0] != 0)
+ return term;
+
+ {
+#ifndef HAVE_TTYENT_H
+ return UNKNOWN;
+#else
+ struct ttyent *t;
+ return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
+#endif
+ }
+}
+
+static void
+xgetstr(char *buf, int cnt, char *err)
+{
+ char ch;
+
+ do {
+ if (read(0, &ch, sizeof(ch)) != sizeof(ch))
+ exit(1);
+ if (--cnt < 0) {
+ fprintf(stderr, "%s too long\r\n", err);
+ sleepexit(1);
+ }
+ *buf++ = ch;
+ } while (ch);
+}
+
+/*
+ * Some old rlogind's unknowingly pass remuser, locuser and
+ * terminal_type/speed so we need to take care of that part of the
+ * protocol here. Also, we can't make a getpeername(2) on the socket
+ * so we have to trust that rlogind resolved the name correctly.
+ */
+
+static int
+doremotelogin(char *host)
+{
+ int code;
+ char *cp;
+
+ xgetstr(rusername, sizeof (rusername), "remuser");
+ xgetstr(lusername, sizeof (lusername), "locuser");
+ xgetstr(term, sizeof(term), "Terminal type");
+ cp = strchr(term, '/');
+ if (cp != 0)
+ *cp = 0; /* For now ignore speed/bg */
+ pwd = k_getpwnam(lusername);
+ if (pwd == NULL)
+ return(-1);
+ code = ruserok(host, (pwd->pw_uid == 0), rusername, lusername);
+ if (code == 0)
+ syslog(LOG_NOTICE,
+ "Warning: An old rlogind accepted login probably from host %s",
+ host);
+ return(code);
+}
+
+void
+sleepexit(int eval)
+{
+
+ sleep(5);
+ exit(eval);
+}
OpenPOWER on IntegriCloud