17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57d080b24Sas145665 * Common Development and Distribution License (the "License").
67d080b24Sas145665 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21aecfc01dSrui zang - Sun Microsystems - Beijing China
227c478bd9Sstevel@tonic-gate /*
23de81e71eSTim Marsland * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*cbea7acaSDominik Hassler *
26*cbea7acaSDominik Hassler * Copyright 2023 OmniOS Community Edition (OmniOSce) Association.
277c478bd9Sstevel@tonic-gate */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
307c478bd9Sstevel@tonic-gate /* All Rights Reserved */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988
347c478bd9Sstevel@tonic-gate * The Regents of the University of California
357c478bd9Sstevel@tonic-gate * All Rights Reserved
367c478bd9Sstevel@tonic-gate *
377c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from
387c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its
397c478bd9Sstevel@tonic-gate * contributors.
407c478bd9Sstevel@tonic-gate */
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate /* Copyright (c) 1987, 1988 Microsoft Corporation */
437c478bd9Sstevel@tonic-gate /* All Rights Reserved */
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate * For a complete reference to login(1), see the manual page. However,
477c478bd9Sstevel@tonic-gate * login has accreted some intentionally undocumented options, which are
487c478bd9Sstevel@tonic-gate * explained here:
497c478bd9Sstevel@tonic-gate *
507c478bd9Sstevel@tonic-gate * -a: This legacy flag appears to be unused.
517c478bd9Sstevel@tonic-gate *
527c478bd9Sstevel@tonic-gate * -f <username>: This flag was introduced by PSARC 1995/039 in support
537c478bd9Sstevel@tonic-gate * of Kerberos. But it's not used by Sun's Kerberos implementation.
547c478bd9Sstevel@tonic-gate * It is however employed by zlogin(1), since it allows one to tell
557c478bd9Sstevel@tonic-gate * login: "This user is authenticated." In the case of zlogin that's
567c478bd9Sstevel@tonic-gate * true because the zone always trusts the global zone.
577c478bd9Sstevel@tonic-gate *
587c478bd9Sstevel@tonic-gate * -z <zonename>: This flag is passed to login when zlogin(1) executes a
597c478bd9Sstevel@tonic-gate * zone login. This tells login(1) to skip it's normal CONSOLE check
607c478bd9Sstevel@tonic-gate * (i.e. that the root login must be on /dev/console) and tells us the
61da6c28aaSamw * name of the zone from which the login is occurring.
627c478bd9Sstevel@tonic-gate */
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate #include <sys/types.h>
657c478bd9Sstevel@tonic-gate #include <sys/param.h>
667c478bd9Sstevel@tonic-gate #include <unistd.h> /* For logfile locking */
677c478bd9Sstevel@tonic-gate #include <signal.h>
687c478bd9Sstevel@tonic-gate #include <stdio.h>
697c478bd9Sstevel@tonic-gate #include <sys/stat.h>
707c478bd9Sstevel@tonic-gate #include <string.h>
717c478bd9Sstevel@tonic-gate #include <deflt.h>
727c478bd9Sstevel@tonic-gate #include <grp.h>
737c478bd9Sstevel@tonic-gate #include <fcntl.h>
742de0a7d6SDan McDonald #include <lastlog.h>
757c478bd9Sstevel@tonic-gate #include <termio.h>
767c478bd9Sstevel@tonic-gate #include <utmpx.h>
777c478bd9Sstevel@tonic-gate #include <stdlib.h>
787c478bd9Sstevel@tonic-gate #include <wait.h>
797c478bd9Sstevel@tonic-gate #include <errno.h>
807c478bd9Sstevel@tonic-gate #include <ctype.h>
817c478bd9Sstevel@tonic-gate #include <syslog.h>
827c478bd9Sstevel@tonic-gate #include <ulimit.h>
837c478bd9Sstevel@tonic-gate #include <libgen.h>
847c478bd9Sstevel@tonic-gate #include <pwd.h>
857c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
867c478bd9Sstevel@tonic-gate #include <strings.h>
877c478bd9Sstevel@tonic-gate #include <libdevinfo.h>
887c478bd9Sstevel@tonic-gate #include <zone.h>
897c478bd9Sstevel@tonic-gate #include "login_audit.h"
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate #include <krb5_repository.h>
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate *
947c478bd9Sstevel@tonic-gate * *** Defines, Macros, and String Constants ***
957c478bd9Sstevel@tonic-gate *
967c478bd9Sstevel@tonic-gate *
977c478bd9Sstevel@tonic-gate */
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate #define ISSUEFILE "/etc/issue" /* file to print before prompt */
1007c478bd9Sstevel@tonic-gate #define NOLOGIN "/etc/nologin" /* file to lock users out during shutdown */
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate /*
1037c478bd9Sstevel@tonic-gate * These need to be defined for UTMPX management.
1047c478bd9Sstevel@tonic-gate * If we add in the utility functions later, we
1057c478bd9Sstevel@tonic-gate * can remove them.
1067c478bd9Sstevel@tonic-gate */
1077c478bd9Sstevel@tonic-gate #define __UPDATE_ENTRY 1
1087c478bd9Sstevel@tonic-gate #define __LOGIN 2
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate /*
1117c478bd9Sstevel@tonic-gate * Intervals to sleep after failed login
1127c478bd9Sstevel@tonic-gate */
1137c478bd9Sstevel@tonic-gate #ifndef SLEEPTIME
1147c478bd9Sstevel@tonic-gate #define SLEEPTIME 4 /* sleeptime before login incorrect msg */
1157c478bd9Sstevel@tonic-gate #endif
1167c478bd9Sstevel@tonic-gate static int Sleeptime = SLEEPTIME;
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate * seconds login disabled after allowable number of unsuccessful attempts
1207c478bd9Sstevel@tonic-gate */
1217c478bd9Sstevel@tonic-gate #ifndef DISABLETIME
1227c478bd9Sstevel@tonic-gate #define DISABLETIME 20
1237c478bd9Sstevel@tonic-gate #endif
1247c478bd9Sstevel@tonic-gate static int Disabletime = DISABLETIME;
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate #define MAXTRYS 5
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate static int retry = MAXTRYS;
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate /*
1317c478bd9Sstevel@tonic-gate * Login logging support
1327c478bd9Sstevel@tonic-gate */
1337c478bd9Sstevel@tonic-gate #define LOGINLOG "/var/adm/loginlog" /* login log file */
1347c478bd9Sstevel@tonic-gate #define LNAME_SIZE 20 /* size of logged logname */
1357c478bd9Sstevel@tonic-gate #define TTYN_SIZE 15 /* size of logged tty name */
1367c478bd9Sstevel@tonic-gate #define TIME_SIZE 30 /* size of logged time string */
1377c478bd9Sstevel@tonic-gate #define ENT_SIZE (LNAME_SIZE + TTYN_SIZE + TIME_SIZE + 3)
1387c478bd9Sstevel@tonic-gate #define L_WAITTIME 5 /* waittime for log file to unlock */
1397c478bd9Sstevel@tonic-gate #define LOGTRYS 10 /* depth of 'try' logging */
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate /*
1427c478bd9Sstevel@tonic-gate * String manipulation macros: SCPYN, SCPYL, EQN and ENVSTRNCAT
1437c478bd9Sstevel@tonic-gate * SCPYL is the safer version of SCPYN
1447c478bd9Sstevel@tonic-gate */
1457c478bd9Sstevel@tonic-gate #define SCPYL(a, b) (void) strlcpy(a, b, sizeof (a))
1467c478bd9Sstevel@tonic-gate #define SCPYN(a, b) (void) strncpy(a, b, sizeof (a))
1477c478bd9Sstevel@tonic-gate #define EQN(a, b) (strncmp(a, b, sizeof (a)-1) == 0)
1487c478bd9Sstevel@tonic-gate #define ENVSTRNCAT(to, from) {int deflen; deflen = strlen(to); \
1497c478bd9Sstevel@tonic-gate (void) strncpy((to)+ deflen, (from), sizeof (to) - (1 + deflen)); }
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate * Other macros
1537c478bd9Sstevel@tonic-gate */
1547c478bd9Sstevel@tonic-gate #define NMAX sizeof (((struct utmpx *)0)->ut_name)
1557c478bd9Sstevel@tonic-gate #define HMAX sizeof (((struct utmpx *)0)->ut_host)
1567c478bd9Sstevel@tonic-gate #define min(a, b) (((a) < (b)) ? (a) : (b))
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate /*
1597c478bd9Sstevel@tonic-gate * Various useful files and string constants
1607c478bd9Sstevel@tonic-gate */
1617c478bd9Sstevel@tonic-gate #define SHELL "/usr/bin/sh"
1627c478bd9Sstevel@tonic-gate #define SHELL2 "/sbin/sh"
1637c478bd9Sstevel@tonic-gate #define SUBLOGIN "<!sublogin>"
1642de0a7d6SDan McDonald #define LASTLOG "/var/adm/lastlog"
1657c478bd9Sstevel@tonic-gate #define PROG_NAME "login"
1667c478bd9Sstevel@tonic-gate #define HUSHLOGIN ".hushlogin"
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate * Array and Buffer sizes
1707c478bd9Sstevel@tonic-gate */
1717c478bd9Sstevel@tonic-gate #define PBUFSIZE 8 /* max significant characters in a password */
1727c478bd9Sstevel@tonic-gate #define MAXARGS 63 /* change value below if changing this */
1737c478bd9Sstevel@tonic-gate #define MAXARGSWIDTH 2 /* log10(MAXARGS) */
1747c478bd9Sstevel@tonic-gate #define MAXENV 1024
1757c478bd9Sstevel@tonic-gate #define MAXLINE 2048
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate /*
1787c478bd9Sstevel@tonic-gate * Miscellaneous constants
1797c478bd9Sstevel@tonic-gate */
1807c478bd9Sstevel@tonic-gate #define ROOTUID 0
1817c478bd9Sstevel@tonic-gate #define ERROR 1
1827c478bd9Sstevel@tonic-gate #define OK 0
1837c478bd9Sstevel@tonic-gate #define LOG_ERROR 1
1847c478bd9Sstevel@tonic-gate #define DONT_LOG_ERROR 0
1857c478bd9Sstevel@tonic-gate #define TRUE 1
1867c478bd9Sstevel@tonic-gate #define FALSE 0
1877c478bd9Sstevel@tonic-gate
1887c478bd9Sstevel@tonic-gate /*
1897c478bd9Sstevel@tonic-gate * Counters for counting the number of failed login attempts
1907c478bd9Sstevel@tonic-gate */
1917c478bd9Sstevel@tonic-gate static int trys = 0;
1927c478bd9Sstevel@tonic-gate static int count = 1;
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate * error value for login_exit() audit output (0 == no audit record)
1967c478bd9Sstevel@tonic-gate */
1977c478bd9Sstevel@tonic-gate static int audit_error = 0;
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate /*
2007c478bd9Sstevel@tonic-gate * Externs a plenty
2017c478bd9Sstevel@tonic-gate */
2027c478bd9Sstevel@tonic-gate extern int getsecretkey();
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate /*
2057c478bd9Sstevel@tonic-gate * The current user name
2067c478bd9Sstevel@tonic-gate */
2077c478bd9Sstevel@tonic-gate static char user_name[NMAX];
2087c478bd9Sstevel@tonic-gate static char minusnam[16] = "-";
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate /*
211f0243e0aSrz201010 * login_pid, used to find utmpx entry to update.
212f0243e0aSrz201010 */
213f0243e0aSrz201010 static pid_t login_pid;
214f0243e0aSrz201010
215f0243e0aSrz201010 /*
2167c478bd9Sstevel@tonic-gate * locale environments to be passed to shells.
2177c478bd9Sstevel@tonic-gate */
2187c478bd9Sstevel@tonic-gate static char *localeenv[] = {
2197c478bd9Sstevel@tonic-gate "LANG",
2207c478bd9Sstevel@tonic-gate "LC_CTYPE", "LC_NUMERIC", "LC_TIME", "LC_COLLATE",
2217c478bd9Sstevel@tonic-gate "LC_MONETARY", "LC_MESSAGES", "LC_ALL", 0};
2227c478bd9Sstevel@tonic-gate static int locale_envmatch(char *, char *);
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate /*
2257c478bd9Sstevel@tonic-gate * Environment variable support
2267c478bd9Sstevel@tonic-gate */
2277c478bd9Sstevel@tonic-gate static char shell[256] = { "SHELL=" };
2287c478bd9Sstevel@tonic-gate static char home[MAXPATHLEN] = { "HOME=" };
2297c478bd9Sstevel@tonic-gate static char term[64] = { "TERM=" };
2307c478bd9Sstevel@tonic-gate static char logname[30] = { "LOGNAME=" };
2317c478bd9Sstevel@tonic-gate static char timez[100] = { "TZ=" };
2327c478bd9Sstevel@tonic-gate static char hertz[10] = { "HZ=" };
2337c478bd9Sstevel@tonic-gate static char path[MAXPATHLEN] = { "PATH=" };
2347c478bd9Sstevel@tonic-gate static char *newenv[10+MAXARGS] =
2357c478bd9Sstevel@tonic-gate {home, path, logname, hertz, term, 0, 0};
2367c478bd9Sstevel@tonic-gate static char **envinit = newenv;
2377c478bd9Sstevel@tonic-gate static int basicenv;
2387c478bd9Sstevel@tonic-gate static char *zero = (char *)0;
2397c478bd9Sstevel@tonic-gate static char **envp;
2407c478bd9Sstevel@tonic-gate #ifndef NO_MAIL
2417c478bd9Sstevel@tonic-gate static char mail[30] = { "MAIL=/var/mail/" };
2427c478bd9Sstevel@tonic-gate #endif
2437c478bd9Sstevel@tonic-gate extern char **environ;
2447c478bd9Sstevel@tonic-gate static char inputline[MAXLINE];
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate #define MAX_ID_LEN 256
2477c478bd9Sstevel@tonic-gate #define MAX_REPOSITORY_LEN 256
2487c478bd9Sstevel@tonic-gate #define MAX_PAMSERVICE_LEN 256
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate static char identity[MAX_ID_LEN];
2517c478bd9Sstevel@tonic-gate static char repository[MAX_REPOSITORY_LEN];
2527c478bd9Sstevel@tonic-gate static char progname[MAX_PAMSERVICE_LEN];
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate /*
2567c478bd9Sstevel@tonic-gate * Strings used to prompt the user.
2577c478bd9Sstevel@tonic-gate */
2587c478bd9Sstevel@tonic-gate static char loginmsg[] = "login: ";
2597c478bd9Sstevel@tonic-gate static char passwdmsg[] = "Password:";
2607c478bd9Sstevel@tonic-gate static char incorrectmsg[] = "Login incorrect\n";
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate /*
2637c478bd9Sstevel@tonic-gate * Password file support
2647c478bd9Sstevel@tonic-gate */
2657c478bd9Sstevel@tonic-gate static struct passwd *pwd = NULL;
2667c478bd9Sstevel@tonic-gate static char remote_host[HMAX];
2677c478bd9Sstevel@tonic-gate static char zone_name[ZONENAME_MAX];
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate /*
2707c478bd9Sstevel@tonic-gate * Illegal passwd entries.
2717c478bd9Sstevel@tonic-gate */
272f48205beScasper static struct passwd nouser = { "", "no:password", (uid_t)-1 };
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate /*
2757c478bd9Sstevel@tonic-gate * Log file support
2767c478bd9Sstevel@tonic-gate */
2777c478bd9Sstevel@tonic-gate static char *log_entry[LOGTRYS];
2787c478bd9Sstevel@tonic-gate static int writelog = 0;
2792de0a7d6SDan McDonald static int lastlogok = 0;
2802de0a7d6SDan McDonald static struct lastlog ll;
2817c478bd9Sstevel@tonic-gate static int dosyslog = 0;
2827c478bd9Sstevel@tonic-gate static int flogin = MAXTRYS; /* flag for SYSLOG_FAILED_LOGINS */
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate * Default file toggles
2867c478bd9Sstevel@tonic-gate */
2877c478bd9Sstevel@tonic-gate static char *Pndefault = "/etc/default/login";
2887c478bd9Sstevel@tonic-gate static char *Altshell = NULL;
2897c478bd9Sstevel@tonic-gate static char *Console = NULL;
2907c478bd9Sstevel@tonic-gate static int Passreqflag = 0;
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate #define DEFUMASK 022
2937c478bd9Sstevel@tonic-gate static mode_t Umask = DEFUMASK;
2947c478bd9Sstevel@tonic-gate static char *Def_tz = NULL;
2957c478bd9Sstevel@tonic-gate static char *tmp_tz = NULL;
2967c478bd9Sstevel@tonic-gate static char *Def_hertz = NULL;
2977c478bd9Sstevel@tonic-gate #define SET_FSIZ 2 /* ulimit() command arg */
2987c478bd9Sstevel@tonic-gate static long Def_ulimit = 0;
2997c478bd9Sstevel@tonic-gate #define MAX_TIMEOUT (15 * 60)
3007c478bd9Sstevel@tonic-gate #define DEF_TIMEOUT (5 * 60)
3017c478bd9Sstevel@tonic-gate static unsigned Def_timeout = DEF_TIMEOUT;
3027c478bd9Sstevel@tonic-gate static char *Def_path = NULL;
3037c478bd9Sstevel@tonic-gate static char *Def_supath = NULL;
3047c478bd9Sstevel@tonic-gate #define DEF_PATH "/usr/bin:" /* same as PATH */
3057c478bd9Sstevel@tonic-gate #define DEF_SUPATH "/usr/sbin:/usr/bin" /* same as ROOTPATH */
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /*
3087c478bd9Sstevel@tonic-gate * Defaults for updating expired passwords
3097c478bd9Sstevel@tonic-gate */
3107c478bd9Sstevel@tonic-gate #define DEF_ATTEMPTS 3
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate /*
3137c478bd9Sstevel@tonic-gate * ttyprompt will point to the environment variable TTYPROMPT.
3147c478bd9Sstevel@tonic-gate * TTYPROMPT is set by ttymon if ttymon already wrote out the prompt.
3157c478bd9Sstevel@tonic-gate */
3167c478bd9Sstevel@tonic-gate static char *ttyprompt = NULL;
3177c478bd9Sstevel@tonic-gate static char *ttyn = NULL;
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate /*
3207c478bd9Sstevel@tonic-gate * Pass inherited environment. Used by telnetd in support of the telnet
3217c478bd9Sstevel@tonic-gate * ENVIRON option.
3227c478bd9Sstevel@tonic-gate */
3237c478bd9Sstevel@tonic-gate static boolean_t pflag = B_FALSE;
3247c478bd9Sstevel@tonic-gate static boolean_t uflag = B_FALSE;
3257c478bd9Sstevel@tonic-gate static boolean_t Rflag = B_FALSE;
3267c478bd9Sstevel@tonic-gate static boolean_t sflag = B_FALSE;
3277c478bd9Sstevel@tonic-gate static boolean_t Uflag = B_FALSE;
3287c478bd9Sstevel@tonic-gate static boolean_t tflag = B_FALSE;
3297c478bd9Sstevel@tonic-gate static boolean_t hflag = B_FALSE;
3307c478bd9Sstevel@tonic-gate static boolean_t rflag = B_FALSE;
3317c478bd9Sstevel@tonic-gate static boolean_t zflag = B_FALSE;
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate /*
3347c478bd9Sstevel@tonic-gate * Remote login support
3357c478bd9Sstevel@tonic-gate */
3367c478bd9Sstevel@tonic-gate static char rusername[NMAX+1], lusername[NMAX+1];
3377c478bd9Sstevel@tonic-gate static char terminal[MAXPATHLEN];
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate /*
3407c478bd9Sstevel@tonic-gate * Pre-authentication flag support
3417c478bd9Sstevel@tonic-gate */
3427c478bd9Sstevel@tonic-gate static int fflag;
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate static char ** getargs(char *);
3457c478bd9Sstevel@tonic-gate
346*cbea7acaSDominik Hassler static int login_conv(int, const struct pam_message **,
3477c478bd9Sstevel@tonic-gate struct pam_response **, void *);
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate static struct pam_conv pam_conv = {login_conv, NULL};
3507c478bd9Sstevel@tonic-gate static pam_handle_t *pamh; /* Authentication handle */
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate /*
3537c478bd9Sstevel@tonic-gate * Function declarations
3547c478bd9Sstevel@tonic-gate */
3557c478bd9Sstevel@tonic-gate static void turn_on_logging(void);
3567c478bd9Sstevel@tonic-gate static void defaults(void);
3577c478bd9Sstevel@tonic-gate static void usage(void);
3587c478bd9Sstevel@tonic-gate static void process_rlogin(void);
3597c478bd9Sstevel@tonic-gate static void login_authenticate();
3607c478bd9Sstevel@tonic-gate static void setup_credentials(void);
3617c478bd9Sstevel@tonic-gate static void adjust_nice(void);
3622de0a7d6SDan McDonald static void update_utmpx_entry(int);
3637c478bd9Sstevel@tonic-gate static void establish_user_environment(char **);
3642de0a7d6SDan McDonald static void print_banner(void);
3652de0a7d6SDan McDonald static void display_last_login_time(void);
3667c478bd9Sstevel@tonic-gate static void exec_the_shell(void);
3677c478bd9Sstevel@tonic-gate static int process_chroot_logins(void);
3687c478bd9Sstevel@tonic-gate static void chdir_to_dir_user(void);
3692de0a7d6SDan McDonald static void check_log(void);
3707c478bd9Sstevel@tonic-gate static void validate_account(void);
3717c478bd9Sstevel@tonic-gate static void doremoteterm(char *);
3727c478bd9Sstevel@tonic-gate static int get_options(int, char **);
3737c478bd9Sstevel@tonic-gate static void getstr(char *, int, char *);
3747c478bd9Sstevel@tonic-gate static int legalenvvar(char *);
3757c478bd9Sstevel@tonic-gate static void check_for_console(void);
3767c478bd9Sstevel@tonic-gate static void check_for_dueling_unix(char *);
3777c478bd9Sstevel@tonic-gate static void get_user_name(void);
3787c478bd9Sstevel@tonic-gate static uint_t get_audit_id(void);
379032624d5Sbasabi static void login_exit(int)__NORETURN;
3807c478bd9Sstevel@tonic-gate static int logins_disabled(char *);
3817c478bd9Sstevel@tonic-gate static void log_bad_attempts(void);
3827c478bd9Sstevel@tonic-gate static int is_number(char *);
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate /*
3857c478bd9Sstevel@tonic-gate * *** main ***
3867c478bd9Sstevel@tonic-gate *
3877c478bd9Sstevel@tonic-gate * The primary flow of control is directed in this routine.
3887c478bd9Sstevel@tonic-gate * Control moves in line from top to bottom calling subfunctions
3897c478bd9Sstevel@tonic-gate * which perform the bulk of the work. Many of these calls exit
3907c478bd9Sstevel@tonic-gate * when a fatal error is encountered and do not return to main.
3917c478bd9Sstevel@tonic-gate *
3927c478bd9Sstevel@tonic-gate *
3937c478bd9Sstevel@tonic-gate */
3947c478bd9Sstevel@tonic-gate
395032624d5Sbasabi int
main(int argc,char * argv[],char ** renvp)3967c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char **renvp)
3977c478bd9Sstevel@tonic-gate {
3987c478bd9Sstevel@tonic-gate int sublogin;
3997c478bd9Sstevel@tonic-gate int pam_rc;
4007c478bd9Sstevel@tonic-gate
401f0243e0aSrz201010 login_pid = getpid();
402f0243e0aSrz201010
4037c478bd9Sstevel@tonic-gate /*
4047c478bd9Sstevel@tonic-gate * Set up Defaults and flags
4057c478bd9Sstevel@tonic-gate */
4067c478bd9Sstevel@tonic-gate defaults();
4077c478bd9Sstevel@tonic-gate SCPYL(progname, PROG_NAME);
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate /*
4107c478bd9Sstevel@tonic-gate * Set up default umask
4117c478bd9Sstevel@tonic-gate */
4127c478bd9Sstevel@tonic-gate if (Umask > ((mode_t)0777))
4137c478bd9Sstevel@tonic-gate Umask = DEFUMASK;
4147c478bd9Sstevel@tonic-gate (void) umask(Umask);
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate /*
4177c478bd9Sstevel@tonic-gate * Set up default timeouts and delays
4187c478bd9Sstevel@tonic-gate */
4197c478bd9Sstevel@tonic-gate if (Def_timeout > MAX_TIMEOUT)
4207c478bd9Sstevel@tonic-gate Def_timeout = MAX_TIMEOUT;
4217c478bd9Sstevel@tonic-gate if (Sleeptime < 0 || Sleeptime > 5)
4227c478bd9Sstevel@tonic-gate Sleeptime = SLEEPTIME;
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate (void) alarm(Def_timeout);
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate /*
4277c478bd9Sstevel@tonic-gate * Ignore SIGQUIT and SIGINT and set nice to 0
4287c478bd9Sstevel@tonic-gate */
4297c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN);
4307c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN);
4317c478bd9Sstevel@tonic-gate (void) nice(0);
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate /*
4347c478bd9Sstevel@tonic-gate * Set flag to disable the pid check if you find that you are
4357c478bd9Sstevel@tonic-gate * a subsystem login.
4367c478bd9Sstevel@tonic-gate */
4377c478bd9Sstevel@tonic-gate sublogin = 0;
4387c478bd9Sstevel@tonic-gate if (*renvp && strcmp(*renvp, SUBLOGIN) == 0)
4397c478bd9Sstevel@tonic-gate sublogin = 1;
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate /*
4427c478bd9Sstevel@tonic-gate * Parse Arguments
4437c478bd9Sstevel@tonic-gate */
4447c478bd9Sstevel@tonic-gate if (get_options(argc, argv) == -1) {
4457c478bd9Sstevel@tonic-gate usage();
4467c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_BAD_CMD;
4477c478bd9Sstevel@tonic-gate login_exit(1);
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate
4507c478bd9Sstevel@tonic-gate /*
4517c478bd9Sstevel@tonic-gate * if devicename is not passed as argument, call ttyname(0)
4527c478bd9Sstevel@tonic-gate */
4537c478bd9Sstevel@tonic-gate if (ttyn == NULL) {
4547c478bd9Sstevel@tonic-gate ttyn = ttyname(0);
4557c478bd9Sstevel@tonic-gate if (ttyn == NULL)
4567c478bd9Sstevel@tonic-gate ttyn = "/dev/???";
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate /*
4607c478bd9Sstevel@tonic-gate * Call pam_start to initiate a PAM authentication operation
4617c478bd9Sstevel@tonic-gate */
4627c478bd9Sstevel@tonic-gate
4637c478bd9Sstevel@tonic-gate if ((pam_rc = pam_start(progname, user_name, &pam_conv, &pamh))
4647c478bd9Sstevel@tonic-gate != PAM_SUCCESS) {
4657c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + pam_rc;
4667c478bd9Sstevel@tonic-gate login_exit(1);
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate if ((pam_rc = pam_set_item(pamh, PAM_TTY, ttyn)) != PAM_SUCCESS) {
4697c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + pam_rc;
4707c478bd9Sstevel@tonic-gate login_exit(1);
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate if ((pam_rc = pam_set_item(pamh, PAM_RHOST, remote_host)) !=
4737c478bd9Sstevel@tonic-gate PAM_SUCCESS) {
4747c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + pam_rc;
4757c478bd9Sstevel@tonic-gate login_exit(1);
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate /*
4797c478bd9Sstevel@tonic-gate * We currently only support special handling of the KRB5 PAM repository
4807c478bd9Sstevel@tonic-gate */
4817c478bd9Sstevel@tonic-gate if ((Rflag && strlen(repository)) &&
4827c478bd9Sstevel@tonic-gate strcmp(repository, KRB5_REPOSITORY_NAME) == 0 &&
4837c478bd9Sstevel@tonic-gate (uflag && strlen(identity))) {
4847c478bd9Sstevel@tonic-gate krb5_repository_data_t krb5_data;
4857c478bd9Sstevel@tonic-gate pam_repository_t pam_rep_data;
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate krb5_data.principal = identity;
4887c478bd9Sstevel@tonic-gate krb5_data.flags = SUNW_PAM_KRB5_ALREADY_AUTHENTICATED;
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate pam_rep_data.type = repository;
4917c478bd9Sstevel@tonic-gate pam_rep_data.scope = (void *)&krb5_data;
4927c478bd9Sstevel@tonic-gate pam_rep_data.scope_len = sizeof (krb5_data);
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_REPOSITORY,
4957c478bd9Sstevel@tonic-gate (void *)&pam_rep_data);
4967c478bd9Sstevel@tonic-gate }
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate /*
4997c478bd9Sstevel@tonic-gate * Open the log file which contains a record of successful and failed
5007c478bd9Sstevel@tonic-gate * login attempts
5017c478bd9Sstevel@tonic-gate */
5027c478bd9Sstevel@tonic-gate turn_on_logging();
5037c478bd9Sstevel@tonic-gate
5047c478bd9Sstevel@tonic-gate /*
5057c478bd9Sstevel@tonic-gate * say "hi" to syslogd ..
5067c478bd9Sstevel@tonic-gate */
5077c478bd9Sstevel@tonic-gate openlog("login", 0, LOG_AUTH);
5087c478bd9Sstevel@tonic-gate
5097c478bd9Sstevel@tonic-gate /*
5107c478bd9Sstevel@tonic-gate * Do special processing for -r (rlogin) flag
5117c478bd9Sstevel@tonic-gate */
5127c478bd9Sstevel@tonic-gate if (rflag)
5137c478bd9Sstevel@tonic-gate process_rlogin();
5147c478bd9Sstevel@tonic-gate
5157c478bd9Sstevel@tonic-gate /*
5167c478bd9Sstevel@tonic-gate * validate user
5177c478bd9Sstevel@tonic-gate */
5187c478bd9Sstevel@tonic-gate /* we are already authenticated. fill in what we must, then continue */
5197c478bd9Sstevel@tonic-gate if (fflag) {
5207c478bd9Sstevel@tonic-gate if ((pwd = getpwnam(user_name)) == NULL) {
5217c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_USERNAME;
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate log_bad_attempts();
5247c478bd9Sstevel@tonic-gate (void) printf("Login failed: unknown user '%s'.\n",
5257c478bd9Sstevel@tonic-gate user_name);
5267c478bd9Sstevel@tonic-gate login_exit(1);
5277c478bd9Sstevel@tonic-gate }
5287c478bd9Sstevel@tonic-gate } else {
5297c478bd9Sstevel@tonic-gate /*
5307c478bd9Sstevel@tonic-gate * Perform the primary login authentication activity.
5317c478bd9Sstevel@tonic-gate */
5327c478bd9Sstevel@tonic-gate login_authenticate();
5337c478bd9Sstevel@tonic-gate }
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate /* change root login, then we exec another login and try again */
5367c478bd9Sstevel@tonic-gate if (process_chroot_logins() != OK)
5377c478bd9Sstevel@tonic-gate login_exit(1);
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate /*
5407c478bd9Sstevel@tonic-gate * If root login and not on system console then call exit(2)
5417c478bd9Sstevel@tonic-gate */
5427c478bd9Sstevel@tonic-gate check_for_console();
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate /*
5457c478bd9Sstevel@tonic-gate * Check to see if a shutdown is in progress, if it is and
5467c478bd9Sstevel@tonic-gate * we are not root then throw the user off the system
5477c478bd9Sstevel@tonic-gate */
5487c478bd9Sstevel@tonic-gate if (logins_disabled(user_name) == TRUE) {
5497c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_LOGIN_DISABLED;
5507c478bd9Sstevel@tonic-gate login_exit(1);
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate if (pwd->pw_uid == 0) {
5547c478bd9Sstevel@tonic-gate if (Def_supath != NULL)
5557c478bd9Sstevel@tonic-gate Def_path = Def_supath;
5567c478bd9Sstevel@tonic-gate else
5577c478bd9Sstevel@tonic-gate Def_path = DEF_SUPATH;
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate
5607c478bd9Sstevel@tonic-gate /*
5617c478bd9Sstevel@tonic-gate * Check account expiration and passwd aging
5627c478bd9Sstevel@tonic-gate */
5637c478bd9Sstevel@tonic-gate validate_account();
5647c478bd9Sstevel@tonic-gate
5657c478bd9Sstevel@tonic-gate /*
5667c478bd9Sstevel@tonic-gate * We only get here if we've been authenticated.
5677c478bd9Sstevel@tonic-gate */
5687c478bd9Sstevel@tonic-gate
5697c478bd9Sstevel@tonic-gate /*
5707c478bd9Sstevel@tonic-gate * Now we set up the environment for the new user, which includes
5717c478bd9Sstevel@tonic-gate * the users ulimit, nice value, ownership of this tty, uid, gid,
5727c478bd9Sstevel@tonic-gate * and environment variables.
5737c478bd9Sstevel@tonic-gate */
5747c478bd9Sstevel@tonic-gate if (Def_ulimit > 0L && ulimit(SET_FSIZ, Def_ulimit) < 0L)
5757c478bd9Sstevel@tonic-gate (void) printf("Could not set ULIMIT to %ld\n", Def_ulimit);
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate /* di_devperm_login() sends detailed errors to syslog */
5787c478bd9Sstevel@tonic-gate if (di_devperm_login((const char *)ttyn, pwd->pw_uid, pwd->pw_gid,
5797c478bd9Sstevel@tonic-gate NULL) == -1) {
5807c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "error processing /etc/logindevperm,"
5817c478bd9Sstevel@tonic-gate " see syslog for more details\n");
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate adjust_nice(); /* passwd file can specify nice value */
5857c478bd9Sstevel@tonic-gate
586f0243e0aSrz201010 setup_credentials(); /* Set user credentials - exits on failure */
587f0243e0aSrz201010
588f0243e0aSrz201010 /*
589f0243e0aSrz201010 * NOTE: telnetd and rlogind rely upon this updating of utmpx
590f0243e0aSrz201010 * to indicate that the authentication completed successfully,
591f0243e0aSrz201010 * pam_open_session was called and therefore they are required to
592f0243e0aSrz201010 * call pam_close_session.
593f0243e0aSrz201010 */
5942de0a7d6SDan McDonald update_utmpx_entry(sublogin);
595f0243e0aSrz201010
596f0243e0aSrz201010 /* set the real (and effective) UID */
597f0243e0aSrz201010 if (setuid(pwd->pw_uid) == -1) {
598f0243e0aSrz201010 login_exit(1);
599f0243e0aSrz201010 }
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate /*
6027c478bd9Sstevel@tonic-gate * Set up the basic environment for the exec. This includes
6037c478bd9Sstevel@tonic-gate * HOME, PATH, LOGNAME, SHELL, TERM, TZ, HZ, and MAIL.
6047c478bd9Sstevel@tonic-gate */
6057c478bd9Sstevel@tonic-gate chdir_to_dir_user();
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate establish_user_environment(renvp);
6087c478bd9Sstevel@tonic-gate
6097c478bd9Sstevel@tonic-gate (void) pam_end(pamh, PAM_SUCCESS); /* Done using PAM */
6107c478bd9Sstevel@tonic-gate pamh = NULL;
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate if (pwd->pw_uid == 0) {
6137c478bd9Sstevel@tonic-gate if (dosyslog) {
6147c478bd9Sstevel@tonic-gate if (remote_host[0]) {
6157c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
6167c478bd9Sstevel@tonic-gate ttyn, HMAX, remote_host);
6177c478bd9Sstevel@tonic-gate } else
6187c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE, "ROOT LOGIN %s", ttyn);
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate }
6217c478bd9Sstevel@tonic-gate closelog();
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_DFL);
6247c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_DFL);
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate /*
6272de0a7d6SDan McDonald * Display some useful information to the new user like the banner
6282de0a7d6SDan McDonald * and last login time if not a quiet login.
6292de0a7d6SDan McDonald */
6302de0a7d6SDan McDonald
6312de0a7d6SDan McDonald if (access(HUSHLOGIN, F_OK) != 0) {
6322de0a7d6SDan McDonald print_banner();
6332de0a7d6SDan McDonald display_last_login_time();
6342de0a7d6SDan McDonald }
6352de0a7d6SDan McDonald
6362de0a7d6SDan McDonald /*
6377c478bd9Sstevel@tonic-gate * Set SIGXCPU and SIGXFSZ to default disposition.
6387c478bd9Sstevel@tonic-gate * Shells inherit signal disposition from parent.
6397c478bd9Sstevel@tonic-gate * And the shells should have default dispositions
6407c478bd9Sstevel@tonic-gate * for the two below signals.
6417c478bd9Sstevel@tonic-gate */
6427c478bd9Sstevel@tonic-gate (void) signal(SIGXCPU, SIG_DFL);
6437c478bd9Sstevel@tonic-gate (void) signal(SIGXFSZ, SIG_DFL);
6447c478bd9Sstevel@tonic-gate
6457c478bd9Sstevel@tonic-gate /*
6467c478bd9Sstevel@tonic-gate * Now fire off the shell of choice
6477c478bd9Sstevel@tonic-gate */
6487c478bd9Sstevel@tonic-gate exec_the_shell();
6497c478bd9Sstevel@tonic-gate
6507c478bd9Sstevel@tonic-gate /*
6517c478bd9Sstevel@tonic-gate * All done
6527c478bd9Sstevel@tonic-gate */
6537c478bd9Sstevel@tonic-gate login_exit(1);
654032624d5Sbasabi return (0);
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate
6577c478bd9Sstevel@tonic-gate
6587c478bd9Sstevel@tonic-gate /*
6597c478bd9Sstevel@tonic-gate * *** Utility functions ***
6607c478bd9Sstevel@tonic-gate */
6617c478bd9Sstevel@tonic-gate
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate
6647c478bd9Sstevel@tonic-gate /*
6657c478bd9Sstevel@tonic-gate * donothing & catch - Signal catching functions
6667c478bd9Sstevel@tonic-gate */
6677c478bd9Sstevel@tonic-gate
6687c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6697c478bd9Sstevel@tonic-gate static void
donothing(int sig)6707c478bd9Sstevel@tonic-gate donothing(int sig)
6717c478bd9Sstevel@tonic-gate {
6727c478bd9Sstevel@tonic-gate if (pamh)
6737c478bd9Sstevel@tonic-gate (void) pam_end(pamh, PAM_ABORT);
6747c478bd9Sstevel@tonic-gate }
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate #ifdef notdef
6777c478bd9Sstevel@tonic-gate static int intrupt;
6787c478bd9Sstevel@tonic-gate
6797c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6807c478bd9Sstevel@tonic-gate static void
catch(int sig)6817c478bd9Sstevel@tonic-gate catch(int sig)
6827c478bd9Sstevel@tonic-gate {
6837c478bd9Sstevel@tonic-gate ++intrupt;
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate #endif
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate /*
6887c478bd9Sstevel@tonic-gate * *** Bad login logging support ***
6897c478bd9Sstevel@tonic-gate */
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate /*
6927c478bd9Sstevel@tonic-gate * badlogin() - log to the log file 'trys'
6937c478bd9Sstevel@tonic-gate * unsuccessful attempts
6947c478bd9Sstevel@tonic-gate */
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate static void
badlogin(void)6977c478bd9Sstevel@tonic-gate badlogin(void)
6987c478bd9Sstevel@tonic-gate {
6997c478bd9Sstevel@tonic-gate int retval, count1, fildes;
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate /*
7027c478bd9Sstevel@tonic-gate * Tries to open the log file. If succeed, lock it and write
7037c478bd9Sstevel@tonic-gate * in the failed attempts
7047c478bd9Sstevel@tonic-gate */
7057c478bd9Sstevel@tonic-gate if ((fildes = open(LOGINLOG, O_APPEND|O_WRONLY)) != -1) {
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate (void) sigset(SIGALRM, donothing);
7087c478bd9Sstevel@tonic-gate (void) alarm(L_WAITTIME);
7097c478bd9Sstevel@tonic-gate retval = lockf(fildes, F_LOCK, 0L);
7107c478bd9Sstevel@tonic-gate (void) alarm(0);
7117c478bd9Sstevel@tonic-gate (void) sigset(SIGALRM, SIG_DFL);
7127c478bd9Sstevel@tonic-gate if (retval == 0) {
7137c478bd9Sstevel@tonic-gate for (count1 = 0; count1 < trys; count1++)
7147c478bd9Sstevel@tonic-gate (void) write(fildes, log_entry[count1],
7157c478bd9Sstevel@tonic-gate (unsigned)strlen(log_entry[count1]));
7167c478bd9Sstevel@tonic-gate (void) lockf(fildes, F_ULOCK, 0L);
7177c478bd9Sstevel@tonic-gate }
7187c478bd9Sstevel@tonic-gate (void) close(fildes);
7197c478bd9Sstevel@tonic-gate }
7207c478bd9Sstevel@tonic-gate }
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate
7237c478bd9Sstevel@tonic-gate /*
7247c478bd9Sstevel@tonic-gate * log_bad_attempts - log each bad login attempt - called from
7257c478bd9Sstevel@tonic-gate * login_authenticate. Exits when the maximum attempt
7267c478bd9Sstevel@tonic-gate * count is exceeded.
7277c478bd9Sstevel@tonic-gate */
7287c478bd9Sstevel@tonic-gate
7297c478bd9Sstevel@tonic-gate static void
log_bad_attempts(void)7307c478bd9Sstevel@tonic-gate log_bad_attempts(void)
7317c478bd9Sstevel@tonic-gate {
7327c478bd9Sstevel@tonic-gate time_t timenow;
7337c478bd9Sstevel@tonic-gate
7347c478bd9Sstevel@tonic-gate if (trys >= LOGTRYS)
7357c478bd9Sstevel@tonic-gate return;
7367c478bd9Sstevel@tonic-gate if (writelog) {
7377c478bd9Sstevel@tonic-gate (void) time(&timenow);
7387c478bd9Sstevel@tonic-gate (void) strncat(log_entry[trys], user_name, LNAME_SIZE);
7397c478bd9Sstevel@tonic-gate (void) strncat(log_entry[trys], ":", (size_t)1);
7407c478bd9Sstevel@tonic-gate (void) strncat(log_entry[trys], ttyn, TTYN_SIZE);
7417c478bd9Sstevel@tonic-gate (void) strncat(log_entry[trys], ":", (size_t)1);
7422a0352b4Sgww (void) strncat(log_entry[trys], ctime(&timenow), TIME_SIZE);
7437c478bd9Sstevel@tonic-gate trys++;
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate if (count > flogin) {
7467c478bd9Sstevel@tonic-gate if ((pwd = getpwnam(user_name)) != NULL) {
7477c478bd9Sstevel@tonic-gate if (remote_host[0]) {
7487c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE,
7497c478bd9Sstevel@tonic-gate "Login failure on %s from %.*s, "
7507c478bd9Sstevel@tonic-gate "%.*s", ttyn, HMAX, remote_host,
7517c478bd9Sstevel@tonic-gate NMAX, user_name);
7527c478bd9Sstevel@tonic-gate } else {
7537c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE,
7547c478bd9Sstevel@tonic-gate "Login failure on %s, %.*s",
7557c478bd9Sstevel@tonic-gate ttyn, NMAX, user_name);
7567c478bd9Sstevel@tonic-gate }
7577c478bd9Sstevel@tonic-gate } else {
7587c478bd9Sstevel@tonic-gate if (remote_host[0]) {
7597c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE,
7607c478bd9Sstevel@tonic-gate "Login failure on %s from %.*s",
7617c478bd9Sstevel@tonic-gate ttyn, HMAX, remote_host);
7627c478bd9Sstevel@tonic-gate } else {
7637c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE,
7647c478bd9Sstevel@tonic-gate "Login failure on %s", ttyn);
7657c478bd9Sstevel@tonic-gate }
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate /*
7727c478bd9Sstevel@tonic-gate * turn_on_logging - if the logfile exist, turn on attempt logging and
7737c478bd9Sstevel@tonic-gate * initialize the string storage area
7747c478bd9Sstevel@tonic-gate */
7757c478bd9Sstevel@tonic-gate
7767c478bd9Sstevel@tonic-gate static void
turn_on_logging(void)7777c478bd9Sstevel@tonic-gate turn_on_logging(void)
7787c478bd9Sstevel@tonic-gate {
7797c478bd9Sstevel@tonic-gate struct stat dbuf;
7807c478bd9Sstevel@tonic-gate int i;
7817c478bd9Sstevel@tonic-gate
7827c478bd9Sstevel@tonic-gate if (stat(LOGINLOG, &dbuf) == 0) {
7837c478bd9Sstevel@tonic-gate writelog = 1;
7847c478bd9Sstevel@tonic-gate for (i = 0; i < LOGTRYS; i++) {
7857c478bd9Sstevel@tonic-gate if (!(log_entry[i] = malloc((size_t)ENT_SIZE))) {
7867c478bd9Sstevel@tonic-gate writelog = 0;
7877c478bd9Sstevel@tonic-gate break;
7887c478bd9Sstevel@tonic-gate }
7897c478bd9Sstevel@tonic-gate *log_entry[i] = '\0';
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate }
7927c478bd9Sstevel@tonic-gate }
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate
7957c478bd9Sstevel@tonic-gate /*
7967c478bd9Sstevel@tonic-gate * login_conv():
7977c478bd9Sstevel@tonic-gate * This is the conv (conversation) function called from
7987c478bd9Sstevel@tonic-gate * a PAM authentication module to print error messages
7997c478bd9Sstevel@tonic-gate * or garner information from the user.
8007c478bd9Sstevel@tonic-gate */
8017c478bd9Sstevel@tonic-gate static int
login_conv(int num_msg,const struct pam_message ** msg,struct pam_response ** response,void * appdata_ptr)802*cbea7acaSDominik Hassler login_conv(int num_msg, const struct pam_message **msg,
8037c478bd9Sstevel@tonic-gate struct pam_response **response, void *appdata_ptr)
8047c478bd9Sstevel@tonic-gate {
805*cbea7acaSDominik Hassler const struct pam_message *m;
8067c478bd9Sstevel@tonic-gate struct pam_response *r;
8077c478bd9Sstevel@tonic-gate char *temp;
8087c478bd9Sstevel@tonic-gate int k, i;
8097c478bd9Sstevel@tonic-gate
8107c478bd9Sstevel@tonic-gate if (num_msg <= 0)
8117c478bd9Sstevel@tonic-gate return (PAM_CONV_ERR);
8127c478bd9Sstevel@tonic-gate
8137c478bd9Sstevel@tonic-gate *response = calloc(num_msg, sizeof (struct pam_response));
8147c478bd9Sstevel@tonic-gate if (*response == NULL)
8157c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR);
8167c478bd9Sstevel@tonic-gate
8177c478bd9Sstevel@tonic-gate k = num_msg;
8187c478bd9Sstevel@tonic-gate m = *msg;
8197c478bd9Sstevel@tonic-gate r = *response;
8207c478bd9Sstevel@tonic-gate while (k--) {
8217c478bd9Sstevel@tonic-gate
8227c478bd9Sstevel@tonic-gate switch (m->msg_style) {
8237c478bd9Sstevel@tonic-gate
8247c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_OFF:
8257d080b24Sas145665 errno = 0;
8267c478bd9Sstevel@tonic-gate temp = getpassphrase(m->msg);
8277c478bd9Sstevel@tonic-gate if (temp != NULL) {
8287d080b24Sas145665 if (errno == EINTR)
8297d080b24Sas145665 return (PAM_CONV_ERR);
8307d080b24Sas145665
8317c478bd9Sstevel@tonic-gate r->resp = strdup(temp);
8327c478bd9Sstevel@tonic-gate if (r->resp == NULL) {
8337c478bd9Sstevel@tonic-gate /* free responses */
8347c478bd9Sstevel@tonic-gate r = *response;
8357c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) {
8367c478bd9Sstevel@tonic-gate if (r->resp)
8377c478bd9Sstevel@tonic-gate free(r->resp);
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate free(*response);
8407c478bd9Sstevel@tonic-gate *response = NULL;
8417c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR);
8427c478bd9Sstevel@tonic-gate }
8437c478bd9Sstevel@tonic-gate }
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate m++;
8467c478bd9Sstevel@tonic-gate r++;
8477c478bd9Sstevel@tonic-gate break;
8487c478bd9Sstevel@tonic-gate
8497c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_ON:
8507c478bd9Sstevel@tonic-gate if (m->msg != NULL)
8517c478bd9Sstevel@tonic-gate (void) fputs(m->msg, stdout);
8527c478bd9Sstevel@tonic-gate r->resp = calloc(1, PAM_MAX_RESP_SIZE);
8537c478bd9Sstevel@tonic-gate if (r->resp == NULL) {
8547c478bd9Sstevel@tonic-gate /* free responses */
8557c478bd9Sstevel@tonic-gate r = *response;
8567c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) {
8577c478bd9Sstevel@tonic-gate if (r->resp)
8587c478bd9Sstevel@tonic-gate free(r->resp);
8597c478bd9Sstevel@tonic-gate }
8607c478bd9Sstevel@tonic-gate free(*response);
8617c478bd9Sstevel@tonic-gate *response = NULL;
8627c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR);
8637c478bd9Sstevel@tonic-gate }
8647c478bd9Sstevel@tonic-gate /*
8657c478bd9Sstevel@tonic-gate * The response might include environment variables
8667c478bd9Sstevel@tonic-gate * information. We should store that information in
8677c478bd9Sstevel@tonic-gate * envp if there is any; otherwise, envp is set to
8687c478bd9Sstevel@tonic-gate * NULL.
8697c478bd9Sstevel@tonic-gate */
8707c478bd9Sstevel@tonic-gate bzero((void *)inputline, MAXLINE);
8717c478bd9Sstevel@tonic-gate
8727c478bd9Sstevel@tonic-gate envp = getargs(inputline);
8737c478bd9Sstevel@tonic-gate
8747c478bd9Sstevel@tonic-gate /* If we read in any input, process it. */
8757c478bd9Sstevel@tonic-gate if (inputline[0] != '\0') {
8767c478bd9Sstevel@tonic-gate int len;
8777c478bd9Sstevel@tonic-gate
8787c478bd9Sstevel@tonic-gate if (envp != (char **)NULL)
8797c478bd9Sstevel@tonic-gate /*
8807c478bd9Sstevel@tonic-gate * If getargs() did not return NULL,
8817c478bd9Sstevel@tonic-gate * *envp is the first string in
8827c478bd9Sstevel@tonic-gate * inputline. envp++ makes envp point
8837c478bd9Sstevel@tonic-gate * to environment variables information
8847c478bd9Sstevel@tonic-gate * or be NULL.
8857c478bd9Sstevel@tonic-gate */
8867c478bd9Sstevel@tonic-gate envp++;
8877c478bd9Sstevel@tonic-gate
8887c478bd9Sstevel@tonic-gate (void) strncpy(r->resp, inputline,
8897c478bd9Sstevel@tonic-gate PAM_MAX_RESP_SIZE-1);
890723f377cSToomas Soome r->resp[PAM_MAX_RESP_SIZE-1] = '\0';
8917c478bd9Sstevel@tonic-gate len = strlen(r->resp);
8927c478bd9Sstevel@tonic-gate if (r->resp[len-1] == '\n')
8937c478bd9Sstevel@tonic-gate r->resp[len-1] = '\0';
8947c478bd9Sstevel@tonic-gate } else {
8957c478bd9Sstevel@tonic-gate login_exit(1);
8967c478bd9Sstevel@tonic-gate }
8977c478bd9Sstevel@tonic-gate m++;
8987c478bd9Sstevel@tonic-gate r++;
8997c478bd9Sstevel@tonic-gate break;
9007c478bd9Sstevel@tonic-gate
9017c478bd9Sstevel@tonic-gate case PAM_ERROR_MSG:
9027c478bd9Sstevel@tonic-gate if (m->msg != NULL) {
9037c478bd9Sstevel@tonic-gate (void) fputs(m->msg, stderr);
9047c478bd9Sstevel@tonic-gate (void) fputs("\n", stderr);
9057c478bd9Sstevel@tonic-gate }
9067c478bd9Sstevel@tonic-gate m++;
9077c478bd9Sstevel@tonic-gate r++;
9087c478bd9Sstevel@tonic-gate break;
9097c478bd9Sstevel@tonic-gate case PAM_TEXT_INFO:
9107c478bd9Sstevel@tonic-gate if (m->msg != NULL) {
9117c478bd9Sstevel@tonic-gate (void) fputs(m->msg, stdout);
9127c478bd9Sstevel@tonic-gate (void) fputs("\n", stdout);
9137c478bd9Sstevel@tonic-gate }
9147c478bd9Sstevel@tonic-gate m++;
9157c478bd9Sstevel@tonic-gate r++;
9167c478bd9Sstevel@tonic-gate break;
9177c478bd9Sstevel@tonic-gate
9187c478bd9Sstevel@tonic-gate default:
9197c478bd9Sstevel@tonic-gate break;
9207c478bd9Sstevel@tonic-gate }
9217c478bd9Sstevel@tonic-gate }
9227c478bd9Sstevel@tonic-gate return (PAM_SUCCESS);
9237c478bd9Sstevel@tonic-gate }
9247c478bd9Sstevel@tonic-gate
9257c478bd9Sstevel@tonic-gate /*
9267c478bd9Sstevel@tonic-gate * verify_passwd - Authenticates the user.
9277c478bd9Sstevel@tonic-gate * Returns: PAM_SUCCESS if authentication successful,
9287c478bd9Sstevel@tonic-gate * PAM error code if authentication fails.
9297c478bd9Sstevel@tonic-gate */
9307c478bd9Sstevel@tonic-gate
9317c478bd9Sstevel@tonic-gate static int
verify_passwd(void)932032624d5Sbasabi verify_passwd(void)
9337c478bd9Sstevel@tonic-gate {
9347c478bd9Sstevel@tonic-gate int error;
935*cbea7acaSDominik Hassler const char *user;
93657c40785SJoep Vesseur int flag = (Passreqflag ? PAM_DISALLOW_NULL_AUTHTOK : 0);
9377c478bd9Sstevel@tonic-gate
9387c478bd9Sstevel@tonic-gate /*
9397c478bd9Sstevel@tonic-gate * PAM authenticates the user for us.
9407c478bd9Sstevel@tonic-gate */
9412a0352b4Sgww error = pam_authenticate(pamh, flag);
9427c478bd9Sstevel@tonic-gate
9437c478bd9Sstevel@tonic-gate /* get the user_name from the pam handle */
944*cbea7acaSDominik Hassler (void) pam_get_item(pamh, PAM_USER, (const void **)&user);
9457c478bd9Sstevel@tonic-gate
9467c478bd9Sstevel@tonic-gate if (user == NULL || *user == '\0')
9477c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR);
9487c478bd9Sstevel@tonic-gate
9497c478bd9Sstevel@tonic-gate SCPYL(user_name, user);
9507c478bd9Sstevel@tonic-gate check_for_dueling_unix(user_name);
9517c478bd9Sstevel@tonic-gate
9522a0352b4Sgww if (((pwd = getpwnam(user_name)) == NULL) &&
9532a0352b4Sgww (error != PAM_USER_UNKNOWN)) {
9547c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR);
9557c478bd9Sstevel@tonic-gate }
9567c478bd9Sstevel@tonic-gate
9577c478bd9Sstevel@tonic-gate return (error);
9587c478bd9Sstevel@tonic-gate }
9597c478bd9Sstevel@tonic-gate
9607c478bd9Sstevel@tonic-gate /*
9617c478bd9Sstevel@tonic-gate * quotec - Called by getargs
9627c478bd9Sstevel@tonic-gate */
9637c478bd9Sstevel@tonic-gate
9647c478bd9Sstevel@tonic-gate static int
quotec(void)9657c478bd9Sstevel@tonic-gate quotec(void)
9667c478bd9Sstevel@tonic-gate {
9677c478bd9Sstevel@tonic-gate int c, i, num;
9687c478bd9Sstevel@tonic-gate
9697c478bd9Sstevel@tonic-gate switch (c = getc(stdin)) {
9707c478bd9Sstevel@tonic-gate
9717c478bd9Sstevel@tonic-gate case 'n':
9727c478bd9Sstevel@tonic-gate c = '\n';
9737c478bd9Sstevel@tonic-gate break;
9747c478bd9Sstevel@tonic-gate
9757c478bd9Sstevel@tonic-gate case 'r':
9767c478bd9Sstevel@tonic-gate c = '\r';
9777c478bd9Sstevel@tonic-gate break;
9787c478bd9Sstevel@tonic-gate
9797c478bd9Sstevel@tonic-gate case 'v':
9807c478bd9Sstevel@tonic-gate c = '\013';
9817c478bd9Sstevel@tonic-gate break;
9827c478bd9Sstevel@tonic-gate
9837c478bd9Sstevel@tonic-gate case 'b':
9847c478bd9Sstevel@tonic-gate c = '\b';
9857c478bd9Sstevel@tonic-gate break;
9867c478bd9Sstevel@tonic-gate
9877c478bd9Sstevel@tonic-gate case 't':
9887c478bd9Sstevel@tonic-gate c = '\t';
9897c478bd9Sstevel@tonic-gate break;
9907c478bd9Sstevel@tonic-gate
9917c478bd9Sstevel@tonic-gate case 'f':
9927c478bd9Sstevel@tonic-gate c = '\f';
9937c478bd9Sstevel@tonic-gate break;
9947c478bd9Sstevel@tonic-gate
9957c478bd9Sstevel@tonic-gate case '0':
9967c478bd9Sstevel@tonic-gate case '1':
9977c478bd9Sstevel@tonic-gate case '2':
9987c478bd9Sstevel@tonic-gate case '3':
9997c478bd9Sstevel@tonic-gate case '4':
10007c478bd9Sstevel@tonic-gate case '5':
10017c478bd9Sstevel@tonic-gate case '6':
10027c478bd9Sstevel@tonic-gate case '7':
10037c478bd9Sstevel@tonic-gate for (num = 0, i = 0; i < 3; i++) {
10047c478bd9Sstevel@tonic-gate num = num * 8 + (c - '0');
10057c478bd9Sstevel@tonic-gate if ((c = getc(stdin)) < '0' || c > '7')
10067c478bd9Sstevel@tonic-gate break;
10077c478bd9Sstevel@tonic-gate }
10087c478bd9Sstevel@tonic-gate (void) ungetc(c, stdin);
10097c478bd9Sstevel@tonic-gate c = num & 0377;
10107c478bd9Sstevel@tonic-gate break;
10117c478bd9Sstevel@tonic-gate
10127c478bd9Sstevel@tonic-gate default:
10137c478bd9Sstevel@tonic-gate break;
10147c478bd9Sstevel@tonic-gate }
10157c478bd9Sstevel@tonic-gate return (c);
10167c478bd9Sstevel@tonic-gate }
10177c478bd9Sstevel@tonic-gate
10187c478bd9Sstevel@tonic-gate /*
10197c478bd9Sstevel@tonic-gate * getargs - returns an input line. Exits if EOF encountered.
10207c478bd9Sstevel@tonic-gate */
10217c478bd9Sstevel@tonic-gate #define WHITESPACE 0
10227c478bd9Sstevel@tonic-gate #define ARGUMENT 1
10237c478bd9Sstevel@tonic-gate
10247c478bd9Sstevel@tonic-gate static char **
getargs(char * input_line)10257c478bd9Sstevel@tonic-gate getargs(char *input_line)
10267c478bd9Sstevel@tonic-gate {
10277c478bd9Sstevel@tonic-gate static char envbuf[MAXLINE];
10287c478bd9Sstevel@tonic-gate static char *args[MAXARGS];
10297c478bd9Sstevel@tonic-gate char *ptr, **answer;
10307c478bd9Sstevel@tonic-gate int c;
10317c478bd9Sstevel@tonic-gate int state;
10327c478bd9Sstevel@tonic-gate char *p = input_line;
10337c478bd9Sstevel@tonic-gate
10347c478bd9Sstevel@tonic-gate ptr = envbuf;
10357c478bd9Sstevel@tonic-gate answer = &args[0];
10367c478bd9Sstevel@tonic-gate state = WHITESPACE;
10377c478bd9Sstevel@tonic-gate
10387c478bd9Sstevel@tonic-gate while ((c = getc(stdin)) != EOF && answer < &args[MAXARGS-1]) {
10397c478bd9Sstevel@tonic-gate
10407c478bd9Sstevel@tonic-gate *(input_line++) = c;
10417c478bd9Sstevel@tonic-gate
10427c478bd9Sstevel@tonic-gate switch (c) {
10437c478bd9Sstevel@tonic-gate
10447c478bd9Sstevel@tonic-gate case '\n':
10457c478bd9Sstevel@tonic-gate if (ptr == &envbuf[0])
10467c478bd9Sstevel@tonic-gate return ((char **)NULL);
10477c478bd9Sstevel@tonic-gate *input_line = *ptr = '\0';
10487c478bd9Sstevel@tonic-gate *answer = NULL;
10497c478bd9Sstevel@tonic-gate return (&args[0]);
10507c478bd9Sstevel@tonic-gate
10517c478bd9Sstevel@tonic-gate case ' ':
10527c478bd9Sstevel@tonic-gate case '\t':
10537c478bd9Sstevel@tonic-gate if (state == ARGUMENT) {
10547c478bd9Sstevel@tonic-gate *ptr++ = '\0';
10557c478bd9Sstevel@tonic-gate state = WHITESPACE;
10567c478bd9Sstevel@tonic-gate }
10577c478bd9Sstevel@tonic-gate break;
10587c478bd9Sstevel@tonic-gate
10597c478bd9Sstevel@tonic-gate case '\\':
10607c478bd9Sstevel@tonic-gate c = quotec();
10615196acaeSToomas Soome /* FALLTHROUGH */
10627c478bd9Sstevel@tonic-gate
10637c478bd9Sstevel@tonic-gate default:
10647c478bd9Sstevel@tonic-gate if (state == WHITESPACE) {
10657c478bd9Sstevel@tonic-gate *answer++ = ptr;
10667c478bd9Sstevel@tonic-gate state = ARGUMENT;
10677c478bd9Sstevel@tonic-gate }
10687c478bd9Sstevel@tonic-gate *ptr++ = c;
10697c478bd9Sstevel@tonic-gate }
10707c478bd9Sstevel@tonic-gate
10717c478bd9Sstevel@tonic-gate /* Attempt at overflow, exit */
10727c478bd9Sstevel@tonic-gate if (input_line - p >= MAXLINE - 1 ||
10737c478bd9Sstevel@tonic-gate ptr >= &envbuf[sizeof (envbuf) - 1]) {
10747c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_INPUT_OVERFLOW;
10757c478bd9Sstevel@tonic-gate login_exit(1);
10767c478bd9Sstevel@tonic-gate }
10777c478bd9Sstevel@tonic-gate }
10787c478bd9Sstevel@tonic-gate
10797c478bd9Sstevel@tonic-gate /*
10807c478bd9Sstevel@tonic-gate * If we left loop because an EOF was received or we've overflown
10817c478bd9Sstevel@tonic-gate * args[], exit immediately.
10827c478bd9Sstevel@tonic-gate */
10837c478bd9Sstevel@tonic-gate login_exit(0);
10847c478bd9Sstevel@tonic-gate /* NOTREACHED */
10857c478bd9Sstevel@tonic-gate }
10867c478bd9Sstevel@tonic-gate
10877c478bd9Sstevel@tonic-gate /*
10887c478bd9Sstevel@tonic-gate * get_user_name - Gets the user name either passed in, or from the
10897c478bd9Sstevel@tonic-gate * login: prompt.
10907c478bd9Sstevel@tonic-gate */
10917c478bd9Sstevel@tonic-gate
10927c478bd9Sstevel@tonic-gate static void
get_user_name(void)1093032624d5Sbasabi get_user_name(void)
10947c478bd9Sstevel@tonic-gate {
10957c478bd9Sstevel@tonic-gate FILE *fp;
10967c478bd9Sstevel@tonic-gate
10977c478bd9Sstevel@tonic-gate if ((fp = fopen(ISSUEFILE, "r")) != NULL) {
10987c478bd9Sstevel@tonic-gate char *ptr, buffer[BUFSIZ];
10992a0352b4Sgww while ((ptr = fgets(buffer, sizeof (buffer), fp)) != NULL) {
11007c478bd9Sstevel@tonic-gate (void) fputs(ptr, stdout);
11017c478bd9Sstevel@tonic-gate }
11027c478bd9Sstevel@tonic-gate (void) fclose(fp);
11037c478bd9Sstevel@tonic-gate }
11047c478bd9Sstevel@tonic-gate
11057c478bd9Sstevel@tonic-gate /*
11067c478bd9Sstevel@tonic-gate * if TTYPROMPT is not set, use our own prompt
11077c478bd9Sstevel@tonic-gate * otherwise, use ttyprompt. We just set PAM_USER_PROMPT
11087c478bd9Sstevel@tonic-gate * and let the module do the prompting.
11097c478bd9Sstevel@tonic-gate */
11107c478bd9Sstevel@tonic-gate
11117c478bd9Sstevel@tonic-gate if ((ttyprompt == NULL) || (*ttyprompt == '\0'))
11127c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_USER_PROMPT, (void *)loginmsg);
11137c478bd9Sstevel@tonic-gate else
11147c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_USER_PROMPT, (void *)ttyprompt);
11157c478bd9Sstevel@tonic-gate
11167c478bd9Sstevel@tonic-gate envp = &zero; /* XXX: is this right? */
11177c478bd9Sstevel@tonic-gate }
11187c478bd9Sstevel@tonic-gate
11197c478bd9Sstevel@tonic-gate
11207c478bd9Sstevel@tonic-gate /*
11217c478bd9Sstevel@tonic-gate * Check_for_dueling_unix - Check to see if the another login is talking
11227c478bd9Sstevel@tonic-gate * to the line we've got open as a login port
11237c478bd9Sstevel@tonic-gate * Exits if we're talking to another unix system
11247c478bd9Sstevel@tonic-gate */
11257c478bd9Sstevel@tonic-gate
11267c478bd9Sstevel@tonic-gate static void
check_for_dueling_unix(char * inputline)11277c478bd9Sstevel@tonic-gate check_for_dueling_unix(char *inputline)
11287c478bd9Sstevel@tonic-gate {
11297c478bd9Sstevel@tonic-gate if (EQN(loginmsg, inputline) || EQN(passwdmsg, inputline) ||
11307c478bd9Sstevel@tonic-gate EQN(incorrectmsg, inputline)) {
11317c478bd9Sstevel@tonic-gate (void) printf("Looking at a login line.\n");
11327c478bd9Sstevel@tonic-gate login_exit(8);
11337c478bd9Sstevel@tonic-gate }
11347c478bd9Sstevel@tonic-gate }
11357c478bd9Sstevel@tonic-gate
11367c478bd9Sstevel@tonic-gate /*
11377c478bd9Sstevel@tonic-gate * logins_disabled - if the file /etc/nologin exists and the user is not
11387c478bd9Sstevel@tonic-gate * root then do not permit them to login
11397c478bd9Sstevel@tonic-gate */
11407c478bd9Sstevel@tonic-gate static int
logins_disabled(char * user_name)11417c478bd9Sstevel@tonic-gate logins_disabled(char *user_name)
11427c478bd9Sstevel@tonic-gate {
11437c478bd9Sstevel@tonic-gate FILE *nlfd;
11447c478bd9Sstevel@tonic-gate int c;
11457c478bd9Sstevel@tonic-gate if (!EQN("root", user_name) &&
11467c478bd9Sstevel@tonic-gate ((nlfd = fopen(NOLOGIN, "r")) != (FILE *)NULL)) {
11477c478bd9Sstevel@tonic-gate while ((c = getc(nlfd)) != EOF)
11487c478bd9Sstevel@tonic-gate (void) putchar(c);
11497c478bd9Sstevel@tonic-gate (void) fflush(stdout);
11507c478bd9Sstevel@tonic-gate (void) sleep(5);
11517c478bd9Sstevel@tonic-gate return (TRUE);
11527c478bd9Sstevel@tonic-gate }
11537c478bd9Sstevel@tonic-gate return (FALSE);
11547c478bd9Sstevel@tonic-gate }
11557c478bd9Sstevel@tonic-gate
1156aecfc01dSrui zang - Sun Microsystems - Beijing China #define DEFAULT_CONSOLE "/dev/console"
1157aecfc01dSrui zang - Sun Microsystems - Beijing China
11587c478bd9Sstevel@tonic-gate /*
11597c478bd9Sstevel@tonic-gate * check_for_console - Checks if we're getting a root login on the
11607c478bd9Sstevel@tonic-gate * console, or a login from the global zone. Exits if not.
11617c478bd9Sstevel@tonic-gate *
1162aecfc01dSrui zang - Sun Microsystems - Beijing China * If CONSOLE is set to /dev/console in /etc/default/login, then root logins
1163aecfc01dSrui zang - Sun Microsystems - Beijing China * on /dev/vt/# are permitted as well. /dev/vt/# does not exist in non-global
1164aecfc01dSrui zang - Sun Microsystems - Beijing China * zones, but checking them does no harm.
11657c478bd9Sstevel@tonic-gate */
11667c478bd9Sstevel@tonic-gate static void
check_for_console(void)11677c478bd9Sstevel@tonic-gate check_for_console(void)
11687c478bd9Sstevel@tonic-gate {
1169aecfc01dSrui zang - Sun Microsystems - Beijing China const char *consoles[] = { "/dev/console", "/dev/vt/", NULL };
1170aecfc01dSrui zang - Sun Microsystems - Beijing China int i;
1171aecfc01dSrui zang - Sun Microsystems - Beijing China
1172aecfc01dSrui zang - Sun Microsystems - Beijing China if (pwd == NULL || pwd->pw_uid != 0 || zflag != B_FALSE ||
1173aecfc01dSrui zang - Sun Microsystems - Beijing China Console == NULL)
1174aecfc01dSrui zang - Sun Microsystems - Beijing China return;
1175aecfc01dSrui zang - Sun Microsystems - Beijing China
1176aecfc01dSrui zang - Sun Microsystems - Beijing China if (strcmp(Console, DEFAULT_CONSOLE) == 0) {
1177aecfc01dSrui zang - Sun Microsystems - Beijing China for (i = 0; consoles[i] != NULL; i ++) {
1178aecfc01dSrui zang - Sun Microsystems - Beijing China if (strncmp(ttyn, consoles[i],
1179aecfc01dSrui zang - Sun Microsystems - Beijing China strlen(consoles[i])) == 0)
1180aecfc01dSrui zang - Sun Microsystems - Beijing China return;
1181aecfc01dSrui zang - Sun Microsystems - Beijing China }
1182aecfc01dSrui zang - Sun Microsystems - Beijing China } else {
1183aecfc01dSrui zang - Sun Microsystems - Beijing China if (strcmp(ttyn, Console) == 0)
1184aecfc01dSrui zang - Sun Microsystems - Beijing China return;
1185aecfc01dSrui zang - Sun Microsystems - Beijing China }
1186aecfc01dSrui zang - Sun Microsystems - Beijing China
11877c478bd9Sstevel@tonic-gate (void) printf("Not on system console\n");
11887c478bd9Sstevel@tonic-gate
11897c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_CONSOLE;
11907c478bd9Sstevel@tonic-gate login_exit(10);
1191aecfc01dSrui zang - Sun Microsystems - Beijing China
11927c478bd9Sstevel@tonic-gate }
11937c478bd9Sstevel@tonic-gate
11947c478bd9Sstevel@tonic-gate /*
11957c478bd9Sstevel@tonic-gate * List of environment variables or environment variable prefixes that should
11967c478bd9Sstevel@tonic-gate * not be propagated across logins, such as when the login -p option is used.
11977c478bd9Sstevel@tonic-gate */
11987c478bd9Sstevel@tonic-gate static const char *const illegal[] = {
11997c478bd9Sstevel@tonic-gate "SHELL=",
12007c478bd9Sstevel@tonic-gate "HOME=",
12017c478bd9Sstevel@tonic-gate "LOGNAME=",
12027c478bd9Sstevel@tonic-gate #ifndef NO_MAIL
12037c478bd9Sstevel@tonic-gate "MAIL=",
12047c478bd9Sstevel@tonic-gate #endif
12057c478bd9Sstevel@tonic-gate "CDPATH=",
12067c478bd9Sstevel@tonic-gate "IFS=",
12077c478bd9Sstevel@tonic-gate "PATH=",
12087c478bd9Sstevel@tonic-gate "LD_",
12097c478bd9Sstevel@tonic-gate "SMF_",
12107c478bd9Sstevel@tonic-gate NULL
12117c478bd9Sstevel@tonic-gate };
12127c478bd9Sstevel@tonic-gate
12137c478bd9Sstevel@tonic-gate /*
12147c478bd9Sstevel@tonic-gate * legalenvvar - Is it legal to insert this environmental variable?
12157c478bd9Sstevel@tonic-gate */
12167c478bd9Sstevel@tonic-gate
12177c478bd9Sstevel@tonic-gate static int
legalenvvar(char * s)12187c478bd9Sstevel@tonic-gate legalenvvar(char *s)
12197c478bd9Sstevel@tonic-gate {
12207c478bd9Sstevel@tonic-gate const char *const *p;
12217c478bd9Sstevel@tonic-gate
12227c478bd9Sstevel@tonic-gate for (p = &illegal[0]; *p; p++) {
12237c478bd9Sstevel@tonic-gate if (strncmp(s, *p, strlen(*p)) == 0)
12247c478bd9Sstevel@tonic-gate return (0);
12257c478bd9Sstevel@tonic-gate }
12267c478bd9Sstevel@tonic-gate
12277c478bd9Sstevel@tonic-gate return (1);
12287c478bd9Sstevel@tonic-gate }
12297c478bd9Sstevel@tonic-gate
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate /*
12327c478bd9Sstevel@tonic-gate * getstr - Get a string from standard input
12337c478bd9Sstevel@tonic-gate * Calls exit if read(2) fails.
12347c478bd9Sstevel@tonic-gate */
12357c478bd9Sstevel@tonic-gate
12367c478bd9Sstevel@tonic-gate static void
getstr(char * buf,int cnt,char * err)12377c478bd9Sstevel@tonic-gate getstr(char *buf, int cnt, char *err)
12387c478bd9Sstevel@tonic-gate {
12397c478bd9Sstevel@tonic-gate char c;
12407c478bd9Sstevel@tonic-gate
12417c478bd9Sstevel@tonic-gate do {
12427c478bd9Sstevel@tonic-gate if (read(0, &c, 1) != 1)
12437c478bd9Sstevel@tonic-gate login_exit(1);
12447c478bd9Sstevel@tonic-gate *buf++ = c;
12457c478bd9Sstevel@tonic-gate } while (--cnt > 1 && c != 0);
12467c478bd9Sstevel@tonic-gate
12477c478bd9Sstevel@tonic-gate *buf = 0;
12487c478bd9Sstevel@tonic-gate err = err; /* For lint */
12497c478bd9Sstevel@tonic-gate }
12507c478bd9Sstevel@tonic-gate
12517c478bd9Sstevel@tonic-gate
12527c478bd9Sstevel@tonic-gate /*
12537c478bd9Sstevel@tonic-gate * defaults - read defaults
12547c478bd9Sstevel@tonic-gate */
12557c478bd9Sstevel@tonic-gate
12567c478bd9Sstevel@tonic-gate static void
defaults(void)12577c478bd9Sstevel@tonic-gate defaults(void)
12587c478bd9Sstevel@tonic-gate {
12597c478bd9Sstevel@tonic-gate int flags;
12607c478bd9Sstevel@tonic-gate char *ptr;
12617c478bd9Sstevel@tonic-gate
12627c478bd9Sstevel@tonic-gate if (defopen(Pndefault) == 0) {
12637c478bd9Sstevel@tonic-gate /*
12647c478bd9Sstevel@tonic-gate * ignore case
12657c478bd9Sstevel@tonic-gate */
12667c478bd9Sstevel@tonic-gate flags = defcntl(DC_GETFLAGS, 0);
12677c478bd9Sstevel@tonic-gate TURNOFF(flags, DC_CASE);
12687c478bd9Sstevel@tonic-gate (void) defcntl(DC_SETFLAGS, flags);
12697c478bd9Sstevel@tonic-gate
12707c478bd9Sstevel@tonic-gate if ((Console = defread("CONSOLE=")) != NULL)
12717c478bd9Sstevel@tonic-gate Console = strdup(Console);
12727c478bd9Sstevel@tonic-gate
12737c478bd9Sstevel@tonic-gate if ((Altshell = defread("ALTSHELL=")) != NULL)
12747c478bd9Sstevel@tonic-gate Altshell = strdup(Altshell);
12757c478bd9Sstevel@tonic-gate
12767c478bd9Sstevel@tonic-gate if ((ptr = defread("PASSREQ=")) != NULL &&
12777c478bd9Sstevel@tonic-gate strcasecmp("YES", ptr) == 0)
12787c478bd9Sstevel@tonic-gate Passreqflag = 1;
12797c478bd9Sstevel@tonic-gate
12807c478bd9Sstevel@tonic-gate if ((Def_tz = defread("TIMEZONE=")) != NULL)
12817c478bd9Sstevel@tonic-gate Def_tz = strdup(Def_tz);
12827c478bd9Sstevel@tonic-gate
12837c478bd9Sstevel@tonic-gate if ((Def_hertz = defread("HZ=")) != NULL)
12847c478bd9Sstevel@tonic-gate Def_hertz = strdup(Def_hertz);
12857c478bd9Sstevel@tonic-gate
12867c478bd9Sstevel@tonic-gate if ((Def_path = defread("PATH=")) != NULL)
12877c478bd9Sstevel@tonic-gate Def_path = strdup(Def_path);
12887c478bd9Sstevel@tonic-gate
12897c478bd9Sstevel@tonic-gate if ((Def_supath = defread("SUPATH=")) != NULL)
12907c478bd9Sstevel@tonic-gate Def_supath = strdup(Def_supath);
12917c478bd9Sstevel@tonic-gate
12927c478bd9Sstevel@tonic-gate if ((ptr = defread("ULIMIT=")) != NULL)
12937c478bd9Sstevel@tonic-gate Def_ulimit = atol(ptr);
12947c478bd9Sstevel@tonic-gate
12957c478bd9Sstevel@tonic-gate if ((ptr = defread("TIMEOUT=")) != NULL)
12967c478bd9Sstevel@tonic-gate Def_timeout = (unsigned)atoi(ptr);
12977c478bd9Sstevel@tonic-gate
12987c478bd9Sstevel@tonic-gate if ((ptr = defread("UMASK=")) != NULL)
12997c478bd9Sstevel@tonic-gate if (sscanf(ptr, "%lo", &Umask) != 1)
13007c478bd9Sstevel@tonic-gate Umask = DEFUMASK;
13017c478bd9Sstevel@tonic-gate
13027c478bd9Sstevel@tonic-gate if ((ptr = defread("SLEEPTIME=")) != NULL) {
13037c478bd9Sstevel@tonic-gate if (is_number(ptr))
13047c478bd9Sstevel@tonic-gate Sleeptime = atoi(ptr);
13057c478bd9Sstevel@tonic-gate }
13067c478bd9Sstevel@tonic-gate
13077c478bd9Sstevel@tonic-gate if ((ptr = defread("DISABLETIME=")) != NULL) {
13087c478bd9Sstevel@tonic-gate if (is_number(ptr))
13097c478bd9Sstevel@tonic-gate Disabletime = atoi(ptr);
13107c478bd9Sstevel@tonic-gate }
13117c478bd9Sstevel@tonic-gate
13127c478bd9Sstevel@tonic-gate if ((ptr = defread("SYSLOG=")) != NULL)
13137c478bd9Sstevel@tonic-gate dosyslog = strcmp(ptr, "YES") == 0;
13147c478bd9Sstevel@tonic-gate
13157c478bd9Sstevel@tonic-gate if ((ptr = defread("RETRIES=")) != NULL) {
13167c478bd9Sstevel@tonic-gate if (is_number(ptr))
13177c478bd9Sstevel@tonic-gate retry = atoi(ptr);
13187c478bd9Sstevel@tonic-gate }
13197c478bd9Sstevel@tonic-gate
13207c478bd9Sstevel@tonic-gate if ((ptr = defread("SYSLOG_FAILED_LOGINS=")) != NULL) {
13217c478bd9Sstevel@tonic-gate if (is_number(ptr))
13227c478bd9Sstevel@tonic-gate flogin = atoi(ptr);
13237c478bd9Sstevel@tonic-gate else
13247c478bd9Sstevel@tonic-gate flogin = retry;
13257c478bd9Sstevel@tonic-gate } else
13267c478bd9Sstevel@tonic-gate flogin = retry;
13277c478bd9Sstevel@tonic-gate (void) defopen((char *)NULL);
13287c478bd9Sstevel@tonic-gate }
13297c478bd9Sstevel@tonic-gate }
13307c478bd9Sstevel@tonic-gate
13317c478bd9Sstevel@tonic-gate
13327c478bd9Sstevel@tonic-gate /*
13337c478bd9Sstevel@tonic-gate * get_options(argc, argv)
13347c478bd9Sstevel@tonic-gate * - parse the cmd line.
13357c478bd9Sstevel@tonic-gate * - return 0 if successful, -1 if failed.
13367c478bd9Sstevel@tonic-gate * Calls login_exit() on misuse of -r, -h, and -z flags
13377c478bd9Sstevel@tonic-gate */
13387c478bd9Sstevel@tonic-gate
13397c478bd9Sstevel@tonic-gate static int
get_options(int argc,char * argv[])13407c478bd9Sstevel@tonic-gate get_options(int argc, char *argv[])
13417c478bd9Sstevel@tonic-gate {
13427c478bd9Sstevel@tonic-gate int c;
13437c478bd9Sstevel@tonic-gate int errflg = 0;
13447c478bd9Sstevel@tonic-gate char sflagname[NMAX+1];
13457c478bd9Sstevel@tonic-gate const char *flags_message = "Only one of -r, -h and -z allowed\n";
13467c478bd9Sstevel@tonic-gate
13477c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "u:s:R:f:h:r:pad:t:U:z:")) != -1) {
13487c478bd9Sstevel@tonic-gate switch (c) {
13497c478bd9Sstevel@tonic-gate case 'a':
13507c478bd9Sstevel@tonic-gate break;
13517c478bd9Sstevel@tonic-gate
13527c478bd9Sstevel@tonic-gate case 'd':
13537c478bd9Sstevel@tonic-gate /*
13547c478bd9Sstevel@tonic-gate * Must be root to pass in device name
13557c478bd9Sstevel@tonic-gate * otherwise we exit() as punishment for trying.
13567c478bd9Sstevel@tonic-gate */
13577c478bd9Sstevel@tonic-gate if (getuid() != 0 || geteuid() != 0) {
13587c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_DEVICE_PERM;
13597c478bd9Sstevel@tonic-gate login_exit(1); /* sigh */
13607c478bd9Sstevel@tonic-gate /*NOTREACHED*/
13617c478bd9Sstevel@tonic-gate }
13627c478bd9Sstevel@tonic-gate ttyn = optarg;
13637c478bd9Sstevel@tonic-gate break;
13647c478bd9Sstevel@tonic-gate
13657c478bd9Sstevel@tonic-gate case 'h':
13667c478bd9Sstevel@tonic-gate if (hflag || rflag || zflag) {
13677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, flags_message);
13687c478bd9Sstevel@tonic-gate login_exit(1);
13697c478bd9Sstevel@tonic-gate }
13707c478bd9Sstevel@tonic-gate hflag = B_TRUE;
13717c478bd9Sstevel@tonic-gate SCPYL(remote_host, optarg);
13727c478bd9Sstevel@tonic-gate if (argv[optind]) {
13737c478bd9Sstevel@tonic-gate if (argv[optind][0] != '-') {
13747c478bd9Sstevel@tonic-gate SCPYL(terminal, argv[optind]);
13757c478bd9Sstevel@tonic-gate optind++;
13767c478bd9Sstevel@tonic-gate } else {
13777c478bd9Sstevel@tonic-gate /*
13787c478bd9Sstevel@tonic-gate * Allow "login -h hostname -" to
13797c478bd9Sstevel@tonic-gate * skip setting up an username as "-".
13807c478bd9Sstevel@tonic-gate */
13817c478bd9Sstevel@tonic-gate if (argv[optind][1] == '\0')
13827c478bd9Sstevel@tonic-gate optind++;
13837c478bd9Sstevel@tonic-gate }
13847c478bd9Sstevel@tonic-gate
13857c478bd9Sstevel@tonic-gate }
13867c478bd9Sstevel@tonic-gate SCPYL(progname, "telnet");
13877c478bd9Sstevel@tonic-gate break;
13887c478bd9Sstevel@tonic-gate
13897c478bd9Sstevel@tonic-gate case 'r':
13907c478bd9Sstevel@tonic-gate if (hflag || rflag || zflag) {
13917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, flags_message);
13927c478bd9Sstevel@tonic-gate login_exit(1);
13937c478bd9Sstevel@tonic-gate }
13947c478bd9Sstevel@tonic-gate rflag = B_TRUE;
13957c478bd9Sstevel@tonic-gate SCPYL(remote_host, optarg);
13967c478bd9Sstevel@tonic-gate SCPYL(progname, "rlogin");
13977c478bd9Sstevel@tonic-gate break;
13987c478bd9Sstevel@tonic-gate
13997c478bd9Sstevel@tonic-gate case 'p':
14007c478bd9Sstevel@tonic-gate pflag = B_TRUE;
14017c478bd9Sstevel@tonic-gate break;
14027c478bd9Sstevel@tonic-gate
14037c478bd9Sstevel@tonic-gate case 'f':
14047c478bd9Sstevel@tonic-gate /*
14057c478bd9Sstevel@tonic-gate * Must be root to bypass authentication
14067c478bd9Sstevel@tonic-gate * otherwise we exit() as punishment for trying.
14077c478bd9Sstevel@tonic-gate */
14087c478bd9Sstevel@tonic-gate if (getuid() != 0 || geteuid() != 0) {
14097c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_AUTH_BYPASS;
14107c478bd9Sstevel@tonic-gate
14117c478bd9Sstevel@tonic-gate login_exit(1); /* sigh */
14127c478bd9Sstevel@tonic-gate /*NOTREACHED*/
14137c478bd9Sstevel@tonic-gate }
14147c478bd9Sstevel@tonic-gate /* save fflag user name for future use */
14157c478bd9Sstevel@tonic-gate SCPYL(user_name, optarg);
14167c478bd9Sstevel@tonic-gate fflag = B_TRUE;
14177c478bd9Sstevel@tonic-gate break;
14187c478bd9Sstevel@tonic-gate case 'u':
14197c478bd9Sstevel@tonic-gate if (!strlen(optarg)) {
14207c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
14217c478bd9Sstevel@tonic-gate "Empty string supplied with -u\n");
14227c478bd9Sstevel@tonic-gate login_exit(1);
14237c478bd9Sstevel@tonic-gate }
14247c478bd9Sstevel@tonic-gate SCPYL(identity, optarg);
14257c478bd9Sstevel@tonic-gate uflag = B_TRUE;
14267c478bd9Sstevel@tonic-gate break;
14277c478bd9Sstevel@tonic-gate case 's':
14287c478bd9Sstevel@tonic-gate if (!strlen(optarg)) {
14297c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
14307c478bd9Sstevel@tonic-gate "Empty string supplied with -s\n");
14317c478bd9Sstevel@tonic-gate login_exit(1);
14327c478bd9Sstevel@tonic-gate }
14337c478bd9Sstevel@tonic-gate SCPYL(sflagname, optarg);
14347c478bd9Sstevel@tonic-gate sflag = B_TRUE;
14357c478bd9Sstevel@tonic-gate break;
14367c478bd9Sstevel@tonic-gate case 'R':
14377c478bd9Sstevel@tonic-gate if (!strlen(optarg)) {
14387c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
14397c478bd9Sstevel@tonic-gate "Empty string supplied with -R\n");
14407c478bd9Sstevel@tonic-gate login_exit(1);
14417c478bd9Sstevel@tonic-gate }
14427c478bd9Sstevel@tonic-gate SCPYL(repository, optarg);
14437c478bd9Sstevel@tonic-gate Rflag = B_TRUE;
14447c478bd9Sstevel@tonic-gate break;
14457c478bd9Sstevel@tonic-gate case 't':
14467c478bd9Sstevel@tonic-gate if (!strlen(optarg)) {
14477c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
14487c478bd9Sstevel@tonic-gate "Empty string supplied with -t\n");
14497c478bd9Sstevel@tonic-gate login_exit(1);
14507c478bd9Sstevel@tonic-gate }
14517c478bd9Sstevel@tonic-gate SCPYL(terminal, optarg);
14527c478bd9Sstevel@tonic-gate tflag = B_TRUE;
14537c478bd9Sstevel@tonic-gate break;
14547c478bd9Sstevel@tonic-gate case 'U':
14557c478bd9Sstevel@tonic-gate /*
14567c478bd9Sstevel@tonic-gate * Kerberized rlogind may fork us with
14577c478bd9Sstevel@tonic-gate * -U "" if the rlogin client used the "-a"
14587c478bd9Sstevel@tonic-gate * option to send a NULL username. This is done
14597c478bd9Sstevel@tonic-gate * to force login to prompt for a user/password.
14607c478bd9Sstevel@tonic-gate * However, if Kerberos auth was used, we dont need
14617c478bd9Sstevel@tonic-gate * to prompt, so we will accept the option and
14627c478bd9Sstevel@tonic-gate * handle the situation later.
14637c478bd9Sstevel@tonic-gate */
14647c478bd9Sstevel@tonic-gate SCPYL(rusername, optarg);
14657c478bd9Sstevel@tonic-gate Uflag = B_TRUE;
14667c478bd9Sstevel@tonic-gate break;
14677c478bd9Sstevel@tonic-gate case 'z':
14687c478bd9Sstevel@tonic-gate if (hflag || rflag || zflag) {
14697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, flags_message);
14707c478bd9Sstevel@tonic-gate login_exit(1);
14717c478bd9Sstevel@tonic-gate }
14727c478bd9Sstevel@tonic-gate (void) snprintf(zone_name, sizeof (zone_name),
14737c478bd9Sstevel@tonic-gate "zone:%s", optarg);
14747c478bd9Sstevel@tonic-gate SCPYL(progname, "zlogin");
14757c478bd9Sstevel@tonic-gate zflag = B_TRUE;
14767c478bd9Sstevel@tonic-gate break;
14777c478bd9Sstevel@tonic-gate default:
14787c478bd9Sstevel@tonic-gate errflg++;
14797c478bd9Sstevel@tonic-gate break;
14807c478bd9Sstevel@tonic-gate } /* end switch */
14817c478bd9Sstevel@tonic-gate } /* end while */
14827c478bd9Sstevel@tonic-gate
14837c478bd9Sstevel@tonic-gate /*
14847c478bd9Sstevel@tonic-gate * If the 's svcname' flag was used, override the progname
14857c478bd9Sstevel@tonic-gate * value that is to be used in the pam_start call.
14867c478bd9Sstevel@tonic-gate */
14877c478bd9Sstevel@tonic-gate if (sflag)
14887c478bd9Sstevel@tonic-gate SCPYL(progname, sflagname);
14897c478bd9Sstevel@tonic-gate
14907c478bd9Sstevel@tonic-gate /*
14917c478bd9Sstevel@tonic-gate * get the prompt set by ttymon
14927c478bd9Sstevel@tonic-gate */
14937c478bd9Sstevel@tonic-gate ttyprompt = getenv("TTYPROMPT");
14947c478bd9Sstevel@tonic-gate
14957c478bd9Sstevel@tonic-gate if ((ttyprompt != NULL) && (*ttyprompt != '\0')) {
14967c478bd9Sstevel@tonic-gate /*
14977c478bd9Sstevel@tonic-gate * if ttyprompt is set, there should be data on
14987c478bd9Sstevel@tonic-gate * the stream already.
14997c478bd9Sstevel@tonic-gate */
15007c478bd9Sstevel@tonic-gate if ((envp = getargs(inputline)) != (char **)NULL) {
15017c478bd9Sstevel@tonic-gate /*
15027c478bd9Sstevel@tonic-gate * don't get name if name passed as argument.
15037c478bd9Sstevel@tonic-gate */
15047c478bd9Sstevel@tonic-gate SCPYL(user_name, *envp++);
15057c478bd9Sstevel@tonic-gate }
15067c478bd9Sstevel@tonic-gate } else if (optind < argc) {
15077c478bd9Sstevel@tonic-gate SCPYL(user_name, argv[optind]);
15087c478bd9Sstevel@tonic-gate (void) SCPYL(inputline, user_name);
15097c478bd9Sstevel@tonic-gate (void) strlcat(inputline, " \n", sizeof (inputline));
15107c478bd9Sstevel@tonic-gate envp = &argv[optind+1];
15117c478bd9Sstevel@tonic-gate
15127c478bd9Sstevel@tonic-gate if (!fflag)
15137c478bd9Sstevel@tonic-gate SCPYL(lusername, user_name);
15147c478bd9Sstevel@tonic-gate }
15157c478bd9Sstevel@tonic-gate
15167c478bd9Sstevel@tonic-gate if (errflg)
15177c478bd9Sstevel@tonic-gate return (-1);
15187c478bd9Sstevel@tonic-gate return (0);
15197c478bd9Sstevel@tonic-gate }
15207c478bd9Sstevel@tonic-gate
15217c478bd9Sstevel@tonic-gate /*
15227c478bd9Sstevel@tonic-gate * usage - Print usage message
15237c478bd9Sstevel@tonic-gate *
15247c478bd9Sstevel@tonic-gate */
15257c478bd9Sstevel@tonic-gate static void
usage(void)15267c478bd9Sstevel@tonic-gate usage(void)
15277c478bd9Sstevel@tonic-gate {
15287c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
15297c478bd9Sstevel@tonic-gate "usage:\n"
15307c478bd9Sstevel@tonic-gate " login [-p] [-d device] [-R repository] [-s service]\n"
15317c478bd9Sstevel@tonic-gate "\t[-t terminal] [-u identity] [-U ruser]\n"
15327c478bd9Sstevel@tonic-gate "\t[-h hostname [terminal] | -r hostname] [name [environ]...]\n");
15337c478bd9Sstevel@tonic-gate
15347c478bd9Sstevel@tonic-gate }
15357c478bd9Sstevel@tonic-gate
15367c478bd9Sstevel@tonic-gate /*
15377c478bd9Sstevel@tonic-gate * doremoteterm - Sets the appropriate ioctls for a remote terminal
15387c478bd9Sstevel@tonic-gate */
15397c478bd9Sstevel@tonic-gate static char *speeds[] = {
15407c478bd9Sstevel@tonic-gate "0", "50", "75", "110", "134", "150", "200", "300",
15417c478bd9Sstevel@tonic-gate "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400",
1542de81e71eSTim Marsland "57600", "76800", "115200", "153600", "230400", "307200", "460800",
1543d9c3e05cSJoshua M. Clulow "921600", "1000000", "1152000", "1500000", "2000000", "2500000",
1544d9c3e05cSJoshua M. Clulow "3000000", "3500000", "4000000"
15457c478bd9Sstevel@tonic-gate };
15467c478bd9Sstevel@tonic-gate
15477c478bd9Sstevel@tonic-gate #define NSPEEDS (sizeof (speeds) / sizeof (speeds[0]))
15487c478bd9Sstevel@tonic-gate
15497c478bd9Sstevel@tonic-gate
15507c478bd9Sstevel@tonic-gate static void
doremoteterm(char * term)15517c478bd9Sstevel@tonic-gate doremoteterm(char *term)
15527c478bd9Sstevel@tonic-gate {
15537c478bd9Sstevel@tonic-gate struct termios tp;
15547c478bd9Sstevel@tonic-gate char *cp = strchr(term, '/'), **cpp;
15557c478bd9Sstevel@tonic-gate char *speed;
15567c478bd9Sstevel@tonic-gate
15577c478bd9Sstevel@tonic-gate (void) ioctl(0, TCGETS, &tp);
15587c478bd9Sstevel@tonic-gate
15597c478bd9Sstevel@tonic-gate if (cp) {
15607c478bd9Sstevel@tonic-gate *cp++ = '\0';
15617c478bd9Sstevel@tonic-gate speed = cp;
15627c478bd9Sstevel@tonic-gate cp = strchr(speed, '/');
15637c478bd9Sstevel@tonic-gate
15647c478bd9Sstevel@tonic-gate if (cp)
15657c478bd9Sstevel@tonic-gate *cp++ = '\0';
15667c478bd9Sstevel@tonic-gate
1567d9c3e05cSJoshua M. Clulow for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++) {
15687c478bd9Sstevel@tonic-gate if (strcmp(*cpp, speed) == 0) {
15697c478bd9Sstevel@tonic-gate (void) cfsetospeed(&tp, cpp-speeds);
15707c478bd9Sstevel@tonic-gate break;
15717c478bd9Sstevel@tonic-gate }
15727c478bd9Sstevel@tonic-gate }
1573d9c3e05cSJoshua M. Clulow }
15747c478bd9Sstevel@tonic-gate
15757c478bd9Sstevel@tonic-gate tp.c_lflag |= ECHO|ICANON;
15767c478bd9Sstevel@tonic-gate tp.c_iflag |= IGNPAR|ICRNL;
15777c478bd9Sstevel@tonic-gate
15787c478bd9Sstevel@tonic-gate (void) ioctl(0, TCSETS, &tp);
15797c478bd9Sstevel@tonic-gate
15807c478bd9Sstevel@tonic-gate }
15817c478bd9Sstevel@tonic-gate
15827c478bd9Sstevel@tonic-gate /*
15837c478bd9Sstevel@tonic-gate * Process_rlogin - Does the work that rlogin and telnet
15847c478bd9Sstevel@tonic-gate * need done
15857c478bd9Sstevel@tonic-gate */
15867c478bd9Sstevel@tonic-gate static void
process_rlogin(void)15877c478bd9Sstevel@tonic-gate process_rlogin(void)
15887c478bd9Sstevel@tonic-gate {
15897c478bd9Sstevel@tonic-gate /*
15907c478bd9Sstevel@tonic-gate * If a Kerberized rlogin was initiated, then these fields
15917c478bd9Sstevel@tonic-gate * must be read by rlogin daemon itself and passed down via
15927c478bd9Sstevel@tonic-gate * cmd line args.
15937c478bd9Sstevel@tonic-gate */
15947c478bd9Sstevel@tonic-gate if (!Uflag && !strlen(rusername))
15957c478bd9Sstevel@tonic-gate getstr(rusername, sizeof (rusername), "remuser");
15967c478bd9Sstevel@tonic-gate if (!strlen(lusername))
15977c478bd9Sstevel@tonic-gate getstr(lusername, sizeof (lusername), "locuser");
15987c478bd9Sstevel@tonic-gate if (!tflag && !strlen(terminal))
15997c478bd9Sstevel@tonic-gate getstr(terminal, sizeof (terminal), "Terminal type");
16007c478bd9Sstevel@tonic-gate
16017c478bd9Sstevel@tonic-gate if (strlen(terminal))
16027c478bd9Sstevel@tonic-gate doremoteterm(terminal);
16037c478bd9Sstevel@tonic-gate
16047c478bd9Sstevel@tonic-gate /* fflag has precedence over stuff passed by rlogind */
16057c478bd9Sstevel@tonic-gate if (fflag || getuid()) {
16067c478bd9Sstevel@tonic-gate pwd = &nouser;
16077c478bd9Sstevel@tonic-gate return;
16087c478bd9Sstevel@tonic-gate } else {
16097c478bd9Sstevel@tonic-gate if (pam_set_item(pamh, PAM_USER, lusername) != PAM_SUCCESS)
16107c478bd9Sstevel@tonic-gate login_exit(1);
16117c478bd9Sstevel@tonic-gate
16127c478bd9Sstevel@tonic-gate pwd = getpwnam(lusername);
16137c478bd9Sstevel@tonic-gate if (pwd == NULL) {
16147c478bd9Sstevel@tonic-gate pwd = &nouser;
16157c478bd9Sstevel@tonic-gate return;
16167c478bd9Sstevel@tonic-gate }
16177c478bd9Sstevel@tonic-gate }
16187c478bd9Sstevel@tonic-gate
16197c478bd9Sstevel@tonic-gate /*
16207c478bd9Sstevel@tonic-gate * Update PAM on the user name
16217c478bd9Sstevel@tonic-gate */
16227c478bd9Sstevel@tonic-gate if (strlen(lusername) &&
16237c478bd9Sstevel@tonic-gate pam_set_item(pamh, PAM_USER, lusername) != PAM_SUCCESS)
16247c478bd9Sstevel@tonic-gate login_exit(1);
16257c478bd9Sstevel@tonic-gate
16267c478bd9Sstevel@tonic-gate if (strlen(rusername) &&
16277c478bd9Sstevel@tonic-gate pam_set_item(pamh, PAM_RUSER, rusername) != PAM_SUCCESS)
16287c478bd9Sstevel@tonic-gate login_exit(1);
16297c478bd9Sstevel@tonic-gate
16307c478bd9Sstevel@tonic-gate SCPYL(user_name, lusername);
16317c478bd9Sstevel@tonic-gate envp = &zero;
16327c478bd9Sstevel@tonic-gate lusername[0] = '\0';
16337c478bd9Sstevel@tonic-gate }
16347c478bd9Sstevel@tonic-gate
16357c478bd9Sstevel@tonic-gate /*
16367c478bd9Sstevel@tonic-gate * *** Account validation routines ***
16377c478bd9Sstevel@tonic-gate *
16387c478bd9Sstevel@tonic-gate */
16397c478bd9Sstevel@tonic-gate
16407c478bd9Sstevel@tonic-gate /*
16417c478bd9Sstevel@tonic-gate * validate_account - This is the PAM version of validate.
16427c478bd9Sstevel@tonic-gate */
16437c478bd9Sstevel@tonic-gate
16447c478bd9Sstevel@tonic-gate static void
validate_account(void)16457c478bd9Sstevel@tonic-gate validate_account(void)
16467c478bd9Sstevel@tonic-gate {
16477c478bd9Sstevel@tonic-gate int error;
16487c478bd9Sstevel@tonic-gate int flag;
16497c478bd9Sstevel@tonic-gate int tries; /* new password retries */
16507c478bd9Sstevel@tonic-gate
16517c478bd9Sstevel@tonic-gate (void) alarm(0); /* give user time to come up with password */
16527c478bd9Sstevel@tonic-gate
16532de0a7d6SDan McDonald check_log();
16542de0a7d6SDan McDonald
16557c478bd9Sstevel@tonic-gate if (Passreqflag)
16567c478bd9Sstevel@tonic-gate flag = PAM_DISALLOW_NULL_AUTHTOK;
16577c478bd9Sstevel@tonic-gate else
16587c478bd9Sstevel@tonic-gate flag = 0;
16597c478bd9Sstevel@tonic-gate
16607c478bd9Sstevel@tonic-gate if ((error = pam_acct_mgmt(pamh, flag)) != PAM_SUCCESS) {
16617c478bd9Sstevel@tonic-gate if (error == PAM_NEW_AUTHTOK_REQD) {
16627c478bd9Sstevel@tonic-gate tries = 1;
16637c478bd9Sstevel@tonic-gate error = PAM_AUTHTOK_ERR;
16647c478bd9Sstevel@tonic-gate while (error == PAM_AUTHTOK_ERR &&
16657c478bd9Sstevel@tonic-gate tries <= DEF_ATTEMPTS) {
16667c478bd9Sstevel@tonic-gate if (tries > 1)
16677c478bd9Sstevel@tonic-gate (void) printf("Try again\n\n");
16687c478bd9Sstevel@tonic-gate
16697c478bd9Sstevel@tonic-gate (void) printf("Choose a new password.\n");
16707c478bd9Sstevel@tonic-gate
1671f00e6aa6Sdarrenm error = pam_chauthtok(pamh,
1672f00e6aa6Sdarrenm PAM_CHANGE_EXPIRED_AUTHTOK);
16737c478bd9Sstevel@tonic-gate if (error == PAM_TRY_AGAIN) {
16747c478bd9Sstevel@tonic-gate (void) sleep(1);
1675f00e6aa6Sdarrenm error = pam_chauthtok(pamh,
1676f00e6aa6Sdarrenm PAM_CHANGE_EXPIRED_AUTHTOK);
16777c478bd9Sstevel@tonic-gate }
16787c478bd9Sstevel@tonic-gate tries++;
16797c478bd9Sstevel@tonic-gate }
16807c478bd9Sstevel@tonic-gate
16817c478bd9Sstevel@tonic-gate if (error != PAM_SUCCESS) {
16827c478bd9Sstevel@tonic-gate if (dosyslog)
16837c478bd9Sstevel@tonic-gate syslog(LOG_CRIT,
16847c478bd9Sstevel@tonic-gate "change password failure: %s",
16857c478bd9Sstevel@tonic-gate pam_strerror(pamh, error));
16867c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + error;
16877c478bd9Sstevel@tonic-gate login_exit(1);
16887c478bd9Sstevel@tonic-gate } else {
16897c478bd9Sstevel@tonic-gate audit_success(ADT_passwd, pwd, zone_name);
16907c478bd9Sstevel@tonic-gate }
16917c478bd9Sstevel@tonic-gate } else {
16927c478bd9Sstevel@tonic-gate (void) printf(incorrectmsg);
16937c478bd9Sstevel@tonic-gate
16947c478bd9Sstevel@tonic-gate if (dosyslog)
16957c478bd9Sstevel@tonic-gate syslog(LOG_CRIT,
16967c478bd9Sstevel@tonic-gate "login account failure: %s",
16977c478bd9Sstevel@tonic-gate pam_strerror(pamh, error));
16987c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + error;
16997c478bd9Sstevel@tonic-gate login_exit(1);
17007c478bd9Sstevel@tonic-gate }
17017c478bd9Sstevel@tonic-gate }
17027c478bd9Sstevel@tonic-gate }
17037c478bd9Sstevel@tonic-gate
17047c478bd9Sstevel@tonic-gate /*
17052de0a7d6SDan McDonald * Check_log - This is really a hack because PAM checks the log, but login
17062de0a7d6SDan McDonald * wants to know if the log is okay and PAM doesn't have
17072de0a7d6SDan McDonald * a module independent way of handing this info back.
17082de0a7d6SDan McDonald */
17092de0a7d6SDan McDonald
17102de0a7d6SDan McDonald static void
check_log(void)17112de0a7d6SDan McDonald check_log(void)
17122de0a7d6SDan McDonald {
17132de0a7d6SDan McDonald int fdl;
17142de0a7d6SDan McDonald long long offset;
17152de0a7d6SDan McDonald
17162de0a7d6SDan McDonald offset = (long long) pwd->pw_uid * (long long) sizeof (struct lastlog);
17172de0a7d6SDan McDonald
17182de0a7d6SDan McDonald if ((fdl = open(LASTLOG, O_RDWR|O_CREAT, 0444)) >= 0) {
17192de0a7d6SDan McDonald if (llseek(fdl, offset, SEEK_SET) == offset &&
17202de0a7d6SDan McDonald read(fdl, (char *)&ll, sizeof (ll)) == sizeof (ll) &&
17212de0a7d6SDan McDonald ll.ll_time != 0)
17222de0a7d6SDan McDonald lastlogok = 1;
17232de0a7d6SDan McDonald (void) close(fdl);
17242de0a7d6SDan McDonald }
17252de0a7d6SDan McDonald }
17262de0a7d6SDan McDonald
17272de0a7d6SDan McDonald /*
17287c478bd9Sstevel@tonic-gate * chdir_to_dir_user - Now chdir after setuid/setgid have happened to
17297c478bd9Sstevel@tonic-gate * place us in the user's home directory just in
17307c478bd9Sstevel@tonic-gate * case it was protected and the first chdir failed.
17317c478bd9Sstevel@tonic-gate * No chdir errors should happen at this point because
17327c478bd9Sstevel@tonic-gate * all failures should have happened on the first
17337c478bd9Sstevel@tonic-gate * time around.
17347c478bd9Sstevel@tonic-gate */
17357c478bd9Sstevel@tonic-gate
17367c478bd9Sstevel@tonic-gate static void
chdir_to_dir_user(void)17377c478bd9Sstevel@tonic-gate chdir_to_dir_user(void)
17387c478bd9Sstevel@tonic-gate {
17397c478bd9Sstevel@tonic-gate if (chdir(pwd->pw_dir) < 0) {
17407c478bd9Sstevel@tonic-gate if (chdir("/") < 0) {
17417c478bd9Sstevel@tonic-gate (void) printf("No directory!\n");
17427c478bd9Sstevel@tonic-gate /*
17437c478bd9Sstevel@tonic-gate * This probably won't work since we can't get to /.
17447c478bd9Sstevel@tonic-gate */
17457c478bd9Sstevel@tonic-gate if (dosyslog) {
17467c478bd9Sstevel@tonic-gate if (remote_host[0]) {
17477c478bd9Sstevel@tonic-gate syslog(LOG_CRIT,
17487c478bd9Sstevel@tonic-gate "LOGIN FAILURES ON %s FROM %.*s ",
17497c478bd9Sstevel@tonic-gate " %.*s", ttyn, HMAX,
17507c478bd9Sstevel@tonic-gate remote_host, NMAX, pwd->pw_name);
17517c478bd9Sstevel@tonic-gate } else {
17527c478bd9Sstevel@tonic-gate syslog(LOG_CRIT,
17537c478bd9Sstevel@tonic-gate "LOGIN FAILURES ON %s, %.*s",
17547c478bd9Sstevel@tonic-gate ttyn, NMAX, pwd->pw_name);
17557c478bd9Sstevel@tonic-gate }
17567c478bd9Sstevel@tonic-gate }
17577c478bd9Sstevel@tonic-gate closelog();
17587c478bd9Sstevel@tonic-gate (void) sleep(Disabletime);
17597c478bd9Sstevel@tonic-gate exit(1);
17607c478bd9Sstevel@tonic-gate } else {
17617c478bd9Sstevel@tonic-gate (void) printf("No directory! Logging in with home=/\n");
17627c478bd9Sstevel@tonic-gate pwd->pw_dir = "/";
17637c478bd9Sstevel@tonic-gate }
17647c478bd9Sstevel@tonic-gate }
17657c478bd9Sstevel@tonic-gate }
17667c478bd9Sstevel@tonic-gate
17677c478bd9Sstevel@tonic-gate
17687c478bd9Sstevel@tonic-gate /*
17697c478bd9Sstevel@tonic-gate * login_authenticate - Performs the main authentication work
17707c478bd9Sstevel@tonic-gate * 1. Prints the login prompt
17717c478bd9Sstevel@tonic-gate * 2. Requests and verifys the password
17727c478bd9Sstevel@tonic-gate * 3. Checks the port password
17737c478bd9Sstevel@tonic-gate */
17747c478bd9Sstevel@tonic-gate
17757c478bd9Sstevel@tonic-gate static void
login_authenticate(void)1776032624d5Sbasabi login_authenticate(void)
17777c478bd9Sstevel@tonic-gate {
1778*cbea7acaSDominik Hassler const char *user;
17797c478bd9Sstevel@tonic-gate int err;
17807c478bd9Sstevel@tonic-gate int login_successful = 0;
17817c478bd9Sstevel@tonic-gate
17827c478bd9Sstevel@tonic-gate do {
17837c478bd9Sstevel@tonic-gate /* if scheme broken, then nothing to do but quit */
1784*cbea7acaSDominik Hassler if (pam_get_item(pamh, PAM_USER, (const void **)&user) !=
1785*cbea7acaSDominik Hassler PAM_SUCCESS) {
17867c478bd9Sstevel@tonic-gate exit(1);
1787*cbea7acaSDominik Hassler }
17887c478bd9Sstevel@tonic-gate
17897c478bd9Sstevel@tonic-gate /*
17907c478bd9Sstevel@tonic-gate * only get name from utility if it is not already
17917c478bd9Sstevel@tonic-gate * supplied by pam_start or a pam_set_item.
17927c478bd9Sstevel@tonic-gate */
17937c478bd9Sstevel@tonic-gate if (!user || !user[0]) {
17947c478bd9Sstevel@tonic-gate /* use call back to get user name */
17957c478bd9Sstevel@tonic-gate get_user_name();
17967c478bd9Sstevel@tonic-gate }
17977c478bd9Sstevel@tonic-gate
17987c478bd9Sstevel@tonic-gate err = verify_passwd();
17997c478bd9Sstevel@tonic-gate
18007c478bd9Sstevel@tonic-gate /*
18017c478bd9Sstevel@tonic-gate * If root login and not on system console then call exit(2)
18027c478bd9Sstevel@tonic-gate */
18037c478bd9Sstevel@tonic-gate check_for_console();
18047c478bd9Sstevel@tonic-gate
18057c478bd9Sstevel@tonic-gate switch (err) {
18067c478bd9Sstevel@tonic-gate case PAM_SUCCESS:
18077c478bd9Sstevel@tonic-gate case PAM_NEW_AUTHTOK_REQD:
18087c478bd9Sstevel@tonic-gate /*
18097c478bd9Sstevel@tonic-gate * Officially, pam_authenticate() shouldn't return this
18107c478bd9Sstevel@tonic-gate * but it's probably the right thing to return if
18117c478bd9Sstevel@tonic-gate * PAM_DISALLOW_NULL_AUTHTOK is set so the user will
18127c478bd9Sstevel@tonic-gate * be forced to change password later in this code.
18137c478bd9Sstevel@tonic-gate */
18147c478bd9Sstevel@tonic-gate count = 0;
18157c478bd9Sstevel@tonic-gate login_successful = 1;
18167c478bd9Sstevel@tonic-gate break;
18177c478bd9Sstevel@tonic-gate case PAM_MAXTRIES:
18187c478bd9Sstevel@tonic-gate count = retry;
18197c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/
18207c478bd9Sstevel@tonic-gate case PAM_AUTH_ERR:
18217c478bd9Sstevel@tonic-gate case PAM_AUTHINFO_UNAVAIL:
18227c478bd9Sstevel@tonic-gate case PAM_USER_UNKNOWN:
18237c478bd9Sstevel@tonic-gate audit_failure(get_audit_id(), ADT_FAIL_PAM + err, pwd,
18247c478bd9Sstevel@tonic-gate remote_host, ttyn, zone_name);
18257c478bd9Sstevel@tonic-gate log_bad_attempts();
18267c478bd9Sstevel@tonic-gate break;
18277c478bd9Sstevel@tonic-gate case PAM_ABORT:
18287c478bd9Sstevel@tonic-gate log_bad_attempts();
18297c478bd9Sstevel@tonic-gate (void) sleep(Disabletime);
18307c478bd9Sstevel@tonic-gate (void) printf(incorrectmsg);
18317c478bd9Sstevel@tonic-gate
18327c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + err;
18337c478bd9Sstevel@tonic-gate login_exit(1);
18347c478bd9Sstevel@tonic-gate /*NOTREACHED*/
18357c478bd9Sstevel@tonic-gate default: /* Some other PAM error */
18367c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + err;
18377c478bd9Sstevel@tonic-gate login_exit(1);
18387c478bd9Sstevel@tonic-gate /*NOTREACHED*/
18397c478bd9Sstevel@tonic-gate }
18407c478bd9Sstevel@tonic-gate
18417c478bd9Sstevel@tonic-gate if (login_successful)
18427c478bd9Sstevel@tonic-gate break;
18437c478bd9Sstevel@tonic-gate
18447c478bd9Sstevel@tonic-gate /* sleep after bad passwd */
18457c478bd9Sstevel@tonic-gate if (count)
18467c478bd9Sstevel@tonic-gate (void) sleep(Sleeptime);
18477c478bd9Sstevel@tonic-gate (void) printf(incorrectmsg);
18487c478bd9Sstevel@tonic-gate /* force name to be null in this case */
18497c478bd9Sstevel@tonic-gate if (pam_set_item(pamh, PAM_USER, NULL) != PAM_SUCCESS)
18507c478bd9Sstevel@tonic-gate login_exit(1);
18517c478bd9Sstevel@tonic-gate if (pam_set_item(pamh, PAM_RUSER, NULL) != PAM_SUCCESS)
18527c478bd9Sstevel@tonic-gate login_exit(1);
18537c478bd9Sstevel@tonic-gate } while (count++ < retry);
18547c478bd9Sstevel@tonic-gate
18557c478bd9Sstevel@tonic-gate if (count >= retry) {
18567c478bd9Sstevel@tonic-gate audit_failure(get_audit_id(), ADT_FAIL_VALUE_MAX_TRIES, pwd,
18577c478bd9Sstevel@tonic-gate remote_host, ttyn, zone_name);
18587c478bd9Sstevel@tonic-gate /*
18597c478bd9Sstevel@tonic-gate * If logging is turned on, output the
18607c478bd9Sstevel@tonic-gate * string storage area to the log file,
18617c478bd9Sstevel@tonic-gate * and sleep for Disabletime
18627c478bd9Sstevel@tonic-gate * seconds before exiting.
18637c478bd9Sstevel@tonic-gate */
18647c478bd9Sstevel@tonic-gate if (writelog)
18657c478bd9Sstevel@tonic-gate badlogin();
18667c478bd9Sstevel@tonic-gate if (dosyslog) {
18677c478bd9Sstevel@tonic-gate if ((pwd = getpwnam(user_name)) != NULL) {
18687c478bd9Sstevel@tonic-gate if (remote_host[0]) {
18697c478bd9Sstevel@tonic-gate syslog(LOG_CRIT,
18702a0352b4Sgww "REPEATED LOGIN FAILURES ON %s "
18712a0352b4Sgww "FROM %.*s, %.*s",
18727c478bd9Sstevel@tonic-gate ttyn, HMAX, remote_host, NMAX,
18737c478bd9Sstevel@tonic-gate user_name);
18747c478bd9Sstevel@tonic-gate } else {
18757c478bd9Sstevel@tonic-gate syslog(LOG_CRIT,
18762a0352b4Sgww "REPEATED LOGIN FAILURES ON "
18772a0352b4Sgww "%s, %.*s",
18787c478bd9Sstevel@tonic-gate ttyn, NMAX, user_name);
18797c478bd9Sstevel@tonic-gate }
18807c478bd9Sstevel@tonic-gate } else {
18817c478bd9Sstevel@tonic-gate if (remote_host[0]) {
18827c478bd9Sstevel@tonic-gate syslog(LOG_CRIT,
18832a0352b4Sgww "REPEATED LOGIN FAILURES ON %s "
18842a0352b4Sgww "FROM %.*s",
18857c478bd9Sstevel@tonic-gate ttyn, HMAX, remote_host);
18867c478bd9Sstevel@tonic-gate } else {
18877c478bd9Sstevel@tonic-gate syslog(LOG_CRIT,
18882a0352b4Sgww "REPEATED LOGIN FAILURES ON %s",
18892a0352b4Sgww ttyn);
18907c478bd9Sstevel@tonic-gate }
18917c478bd9Sstevel@tonic-gate }
18927c478bd9Sstevel@tonic-gate }
18937c478bd9Sstevel@tonic-gate (void) sleep(Disabletime);
18947c478bd9Sstevel@tonic-gate exit(1);
18957c478bd9Sstevel@tonic-gate }
18967c478bd9Sstevel@tonic-gate
18977c478bd9Sstevel@tonic-gate }
18987c478bd9Sstevel@tonic-gate
18997c478bd9Sstevel@tonic-gate /*
19007c478bd9Sstevel@tonic-gate * *** Credential Related routines ***
19017c478bd9Sstevel@tonic-gate *
19027c478bd9Sstevel@tonic-gate */
19037c478bd9Sstevel@tonic-gate
19047c478bd9Sstevel@tonic-gate /*
19057c478bd9Sstevel@tonic-gate * setup_credentials - sets the group ID, initializes the groups
19067c478bd9Sstevel@tonic-gate * and sets up the secretkey.
19077c478bd9Sstevel@tonic-gate * Exits if a failure occurrs.
19087c478bd9Sstevel@tonic-gate */
19097c478bd9Sstevel@tonic-gate
19107c478bd9Sstevel@tonic-gate
19117c478bd9Sstevel@tonic-gate /*
19127c478bd9Sstevel@tonic-gate * setup_credentials - PAM does all the work for us on this one.
19137c478bd9Sstevel@tonic-gate */
19147c478bd9Sstevel@tonic-gate
19157c478bd9Sstevel@tonic-gate static void
setup_credentials(void)19167c478bd9Sstevel@tonic-gate setup_credentials(void)
19177c478bd9Sstevel@tonic-gate {
19187c478bd9Sstevel@tonic-gate int error = 0;
19197c478bd9Sstevel@tonic-gate
19207c478bd9Sstevel@tonic-gate /* set the real (and effective) GID */
19217c478bd9Sstevel@tonic-gate if (setgid(pwd->pw_gid) == -1) {
19227c478bd9Sstevel@tonic-gate login_exit(1);
19237c478bd9Sstevel@tonic-gate }
19247c478bd9Sstevel@tonic-gate
19257c478bd9Sstevel@tonic-gate /*
19267c478bd9Sstevel@tonic-gate * Initialize the supplementary group access list.
19277c478bd9Sstevel@tonic-gate */
19287c478bd9Sstevel@tonic-gate if ((user_name[0] == '\0') ||
19297c478bd9Sstevel@tonic-gate (initgroups(user_name, pwd->pw_gid) == -1)) {
19307c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_PROGRAM;
19317c478bd9Sstevel@tonic-gate login_exit(1);
19327c478bd9Sstevel@tonic-gate }
19337c478bd9Sstevel@tonic-gate
19341117ab72SJan Friedel if ((error = pam_setcred(pamh, zflag ? PAM_REINITIALIZE_CRED :
19351117ab72SJan Friedel PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
19367c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + error;
19377c478bd9Sstevel@tonic-gate login_exit(error);
19387c478bd9Sstevel@tonic-gate }
19397c478bd9Sstevel@tonic-gate
19407c478bd9Sstevel@tonic-gate /*
19417c478bd9Sstevel@tonic-gate * Record successful login and fork process that records logout.
19427c478bd9Sstevel@tonic-gate * We have to do this after setting credentials because pam_setcred()
19437c478bd9Sstevel@tonic-gate * loads key audit info into the cred, but before setuid() so audit
19447c478bd9Sstevel@tonic-gate * system calls will work.
19457c478bd9Sstevel@tonic-gate */
19467c478bd9Sstevel@tonic-gate audit_success(get_audit_id(), pwd, zone_name);
19477c478bd9Sstevel@tonic-gate }
19487c478bd9Sstevel@tonic-gate
19497c478bd9Sstevel@tonic-gate static uint_t
get_audit_id(void)1950032624d5Sbasabi get_audit_id(void)
1951032624d5Sbasabi {
19527c478bd9Sstevel@tonic-gate if (rflag)
19537c478bd9Sstevel@tonic-gate return (ADT_rlogin);
19547c478bd9Sstevel@tonic-gate else if (hflag)
19557c478bd9Sstevel@tonic-gate return (ADT_telnet);
19567c478bd9Sstevel@tonic-gate else if (zflag)
19577c478bd9Sstevel@tonic-gate return (ADT_zlogin);
19587c478bd9Sstevel@tonic-gate
19597c478bd9Sstevel@tonic-gate return (ADT_login);
19607c478bd9Sstevel@tonic-gate }
19617c478bd9Sstevel@tonic-gate
19627c478bd9Sstevel@tonic-gate /*
19637c478bd9Sstevel@tonic-gate *
19647c478bd9Sstevel@tonic-gate * *** Routines to get a new user set up and running ***
19657c478bd9Sstevel@tonic-gate *
19667c478bd9Sstevel@tonic-gate * Things to do when starting up a new user:
19677c478bd9Sstevel@tonic-gate * adjust_nice
19687c478bd9Sstevel@tonic-gate * update_utmpx_entry
19697c478bd9Sstevel@tonic-gate * establish_user_environment
19702de0a7d6SDan McDonald * print_banner
19712de0a7d6SDan McDonald * display_last_login_time
19727c478bd9Sstevel@tonic-gate * exec_the_shell
19737c478bd9Sstevel@tonic-gate *
19747c478bd9Sstevel@tonic-gate */
19757c478bd9Sstevel@tonic-gate
19767c478bd9Sstevel@tonic-gate
19777c478bd9Sstevel@tonic-gate /*
19787c478bd9Sstevel@tonic-gate * adjust_nice - Set the nice (process priority) value if the
19797c478bd9Sstevel@tonic-gate * gecos value contains an appropriate value.
19807c478bd9Sstevel@tonic-gate */
19817c478bd9Sstevel@tonic-gate
19827c478bd9Sstevel@tonic-gate static void
adjust_nice(void)19837c478bd9Sstevel@tonic-gate adjust_nice(void)
19847c478bd9Sstevel@tonic-gate {
19857c478bd9Sstevel@tonic-gate int pri, mflg, i;
19867c478bd9Sstevel@tonic-gate
19877c478bd9Sstevel@tonic-gate if (strncmp("pri=", pwd->pw_gecos, 4) == 0) {
19887c478bd9Sstevel@tonic-gate pri = 0;
19897c478bd9Sstevel@tonic-gate mflg = 0;
19907c478bd9Sstevel@tonic-gate i = 4;
19917c478bd9Sstevel@tonic-gate
19927c478bd9Sstevel@tonic-gate if (pwd->pw_gecos[i] == '-') {
19937c478bd9Sstevel@tonic-gate mflg++;
19947c478bd9Sstevel@tonic-gate i++;
19957c478bd9Sstevel@tonic-gate }
19967c478bd9Sstevel@tonic-gate
19977c478bd9Sstevel@tonic-gate while (pwd->pw_gecos[i] >= '0' && pwd->pw_gecos[i] <= '9')
19987c478bd9Sstevel@tonic-gate pri = (pri * 10) + pwd->pw_gecos[i++] - '0';
19997c478bd9Sstevel@tonic-gate
20007c478bd9Sstevel@tonic-gate if (mflg)
20017c478bd9Sstevel@tonic-gate pri = -pri;
20027c478bd9Sstevel@tonic-gate
20037c478bd9Sstevel@tonic-gate (void) nice(pri);
20047c478bd9Sstevel@tonic-gate }
20057c478bd9Sstevel@tonic-gate }
20067c478bd9Sstevel@tonic-gate
20077c478bd9Sstevel@tonic-gate /*
20087c478bd9Sstevel@tonic-gate * update_utmpx_entry - Searchs for the correct utmpx entry, making an
20097c478bd9Sstevel@tonic-gate * entry there if it finds one, otherwise exits.
20107c478bd9Sstevel@tonic-gate */
20117c478bd9Sstevel@tonic-gate
20127c478bd9Sstevel@tonic-gate static void
update_utmpx_entry(int sublogin)20132de0a7d6SDan McDonald update_utmpx_entry(int sublogin)
20147c478bd9Sstevel@tonic-gate {
20157c478bd9Sstevel@tonic-gate int err;
2016*cbea7acaSDominik Hassler const char *user;
20177c478bd9Sstevel@tonic-gate static char *errmsg = "No utmpx entry. "
20187c478bd9Sstevel@tonic-gate "You must exec \"login\" from the lowest level \"shell\".";
20197c478bd9Sstevel@tonic-gate int tmplen;
2020*cbea7acaSDominik Hassler struct utmpx *u = NULL;
20217c478bd9Sstevel@tonic-gate struct utmpx utmpx;
20227c478bd9Sstevel@tonic-gate char *ttyntail;
20237c478bd9Sstevel@tonic-gate
20247c478bd9Sstevel@tonic-gate /*
20257c478bd9Sstevel@tonic-gate * If we're not a sublogin then
20267c478bd9Sstevel@tonic-gate * we'll get an error back if our PID doesn't match the PID of the
20277c478bd9Sstevel@tonic-gate * entry we are updating, otherwise if its a sublogin the flags
20287c478bd9Sstevel@tonic-gate * field is set to 0, which means we just write a matching entry
20297c478bd9Sstevel@tonic-gate * (without checking the pid), or a new entry if an entry doesn't
20307c478bd9Sstevel@tonic-gate * exist.
20317c478bd9Sstevel@tonic-gate */
20327c478bd9Sstevel@tonic-gate
20332de0a7d6SDan McDonald if ((err = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
20347c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + err;
20357c478bd9Sstevel@tonic-gate login_exit(1);
20367c478bd9Sstevel@tonic-gate }
20377c478bd9Sstevel@tonic-gate
2038*cbea7acaSDominik Hassler if ((err = pam_get_item(pamh, PAM_USER, (const void **)&user)) !=
20397c478bd9Sstevel@tonic-gate PAM_SUCCESS) {
20407c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + err;
20417c478bd9Sstevel@tonic-gate login_exit(1);
20427c478bd9Sstevel@tonic-gate }
20437c478bd9Sstevel@tonic-gate
20447c478bd9Sstevel@tonic-gate (void) memset((void *)&utmpx, 0, sizeof (utmpx));
20457c478bd9Sstevel@tonic-gate (void) time(&utmpx.ut_tv.tv_sec);
20467c478bd9Sstevel@tonic-gate utmpx.ut_pid = getpid();
20477c478bd9Sstevel@tonic-gate
20487c478bd9Sstevel@tonic-gate if (rflag || hflag) {
20497c478bd9Sstevel@tonic-gate SCPYN(utmpx.ut_host, remote_host);
20507c478bd9Sstevel@tonic-gate tmplen = strlen(remote_host) + 1;
20517c478bd9Sstevel@tonic-gate if (tmplen < sizeof (utmpx.ut_host))
20527c478bd9Sstevel@tonic-gate utmpx.ut_syslen = tmplen;
20537c478bd9Sstevel@tonic-gate else
20547c478bd9Sstevel@tonic-gate utmpx.ut_syslen = sizeof (utmpx.ut_host);
20557c478bd9Sstevel@tonic-gate } else if (zflag) {
20567c478bd9Sstevel@tonic-gate /*
20577c478bd9Sstevel@tonic-gate * If this is a login from another zone, put the
20587c478bd9Sstevel@tonic-gate * zone:<zonename> string in the utmpx entry.
20597c478bd9Sstevel@tonic-gate */
20607c478bd9Sstevel@tonic-gate SCPYN(utmpx.ut_host, zone_name);
20617c478bd9Sstevel@tonic-gate tmplen = strlen(zone_name) + 1;
20627c478bd9Sstevel@tonic-gate if (tmplen < sizeof (utmpx.ut_host))
20637c478bd9Sstevel@tonic-gate utmpx.ut_syslen = tmplen;
20647c478bd9Sstevel@tonic-gate else
20657c478bd9Sstevel@tonic-gate utmpx.ut_syslen = sizeof (utmpx.ut_host);
20667c478bd9Sstevel@tonic-gate } else {
20677c478bd9Sstevel@tonic-gate utmpx.ut_syslen = 0;
20687c478bd9Sstevel@tonic-gate }
20697c478bd9Sstevel@tonic-gate
20707c478bd9Sstevel@tonic-gate SCPYN(utmpx.ut_user, user);
20717c478bd9Sstevel@tonic-gate
20727c478bd9Sstevel@tonic-gate /* skip over "/dev/" */
20737c478bd9Sstevel@tonic-gate ttyntail = basename(ttyn);
20747c478bd9Sstevel@tonic-gate
20757c478bd9Sstevel@tonic-gate while ((u = getutxent()) != NULL) {
20767c478bd9Sstevel@tonic-gate if ((u->ut_type == INIT_PROCESS ||
20777c478bd9Sstevel@tonic-gate u->ut_type == LOGIN_PROCESS ||
20787c478bd9Sstevel@tonic-gate u->ut_type == USER_PROCESS) &&
20797c478bd9Sstevel@tonic-gate ((sublogin && strncmp(u->ut_line, ttyntail,
20807c478bd9Sstevel@tonic-gate sizeof (u->ut_line)) == 0) ||
2081f0243e0aSrz201010 u->ut_pid == login_pid)) {
20827c478bd9Sstevel@tonic-gate SCPYN(utmpx.ut_line, (ttyn+sizeof ("/dev/")-1));
20837c478bd9Sstevel@tonic-gate (void) memcpy(utmpx.ut_id, u->ut_id,
20847c478bd9Sstevel@tonic-gate sizeof (utmpx.ut_id));
20857c478bd9Sstevel@tonic-gate utmpx.ut_exit.e_exit = u->ut_exit.e_exit;
20867c478bd9Sstevel@tonic-gate utmpx.ut_type = USER_PROCESS;
20877c478bd9Sstevel@tonic-gate (void) pututxline(&utmpx);
20887c478bd9Sstevel@tonic-gate break;
20897c478bd9Sstevel@tonic-gate }
20907c478bd9Sstevel@tonic-gate }
20917c478bd9Sstevel@tonic-gate endutxent();
20927c478bd9Sstevel@tonic-gate
20937c478bd9Sstevel@tonic-gate if (u == (struct utmpx *)NULL) {
20947c478bd9Sstevel@tonic-gate if (!sublogin) {
20957c478bd9Sstevel@tonic-gate /*
20967c478bd9Sstevel@tonic-gate * no utmpx entry already setup
20977c478bd9Sstevel@tonic-gate * (init or rlogind/telnetd)
20987c478bd9Sstevel@tonic-gate */
20997c478bd9Sstevel@tonic-gate (void) puts(errmsg);
21007c478bd9Sstevel@tonic-gate
21017c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_PROGRAM;
21027c478bd9Sstevel@tonic-gate login_exit(1);
21037c478bd9Sstevel@tonic-gate }
21047c478bd9Sstevel@tonic-gate } else {
21057c478bd9Sstevel@tonic-gate /* Now attempt to write out this entry to the wtmp file if */
21067c478bd9Sstevel@tonic-gate /* we were successful in getting it from the utmpx file and */
21077c478bd9Sstevel@tonic-gate /* the wtmp file exists. */
21087c478bd9Sstevel@tonic-gate updwtmpx(WTMPX_FILE, &utmpx);
21097c478bd9Sstevel@tonic-gate }
21107c478bd9Sstevel@tonic-gate }
21117c478bd9Sstevel@tonic-gate
21127c478bd9Sstevel@tonic-gate
21137c478bd9Sstevel@tonic-gate
21147c478bd9Sstevel@tonic-gate /*
21157c478bd9Sstevel@tonic-gate * process_chroot_logins - Chroots to the specified subdirectory and
21167c478bd9Sstevel@tonic-gate * re executes login.
21177c478bd9Sstevel@tonic-gate */
21187c478bd9Sstevel@tonic-gate
21197c478bd9Sstevel@tonic-gate static int
process_chroot_logins(void)21207c478bd9Sstevel@tonic-gate process_chroot_logins(void)
21217c478bd9Sstevel@tonic-gate {
21227c478bd9Sstevel@tonic-gate /*
21237c478bd9Sstevel@tonic-gate * If the shell field starts with a '*', do a chroot to the home
21247c478bd9Sstevel@tonic-gate * directory and perform a new login.
21257c478bd9Sstevel@tonic-gate */
21267c478bd9Sstevel@tonic-gate
21277c478bd9Sstevel@tonic-gate if (*pwd->pw_shell == '*') {
21287c478bd9Sstevel@tonic-gate (void) pam_end(pamh, PAM_SUCCESS); /* Done using PAM */
21297c478bd9Sstevel@tonic-gate pamh = NULL; /* really done */
21307c478bd9Sstevel@tonic-gate if (chroot(pwd->pw_dir) < 0) {
21317c478bd9Sstevel@tonic-gate (void) printf("No Root Directory\n");
21327c478bd9Sstevel@tonic-gate
21337c478bd9Sstevel@tonic-gate audit_failure(get_audit_id(),
21347c478bd9Sstevel@tonic-gate ADT_FAIL_VALUE_CHDIR_FAILED,
21357c478bd9Sstevel@tonic-gate pwd, remote_host, ttyn, zone_name);
21367c478bd9Sstevel@tonic-gate
21377c478bd9Sstevel@tonic-gate return (ERROR);
21387c478bd9Sstevel@tonic-gate }
21397c478bd9Sstevel@tonic-gate /*
21407c478bd9Sstevel@tonic-gate * Set the environment flag <!sublogin> so that the next login
21417c478bd9Sstevel@tonic-gate * knows that it is a sublogin.
21427c478bd9Sstevel@tonic-gate */
21437c478bd9Sstevel@tonic-gate envinit[0] = SUBLOGIN;
21447c478bd9Sstevel@tonic-gate envinit[1] = (char *)NULL;
21457c478bd9Sstevel@tonic-gate (void) printf("Subsystem root: %s\n", pwd->pw_dir);
21467c478bd9Sstevel@tonic-gate (void) execle("/usr/bin/login", "login", (char *)0,
21477c478bd9Sstevel@tonic-gate &envinit[0]);
21487c478bd9Sstevel@tonic-gate (void) execle("/etc/login", "login", (char *)0, &envinit[0]);
21497c478bd9Sstevel@tonic-gate (void) printf("No /usr/bin/login or /etc/login on root\n");
21507c478bd9Sstevel@tonic-gate
21517c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_PROGRAM;
21527c478bd9Sstevel@tonic-gate
21537c478bd9Sstevel@tonic-gate login_exit(1);
21547c478bd9Sstevel@tonic-gate }
21557c478bd9Sstevel@tonic-gate return (OK);
21567c478bd9Sstevel@tonic-gate }
21577c478bd9Sstevel@tonic-gate
21587c478bd9Sstevel@tonic-gate /*
21597c478bd9Sstevel@tonic-gate * establish_user_environment - Set up the new users enviornment
21607c478bd9Sstevel@tonic-gate */
21617c478bd9Sstevel@tonic-gate
21627c478bd9Sstevel@tonic-gate static void
establish_user_environment(char ** renvp)21637c478bd9Sstevel@tonic-gate establish_user_environment(char **renvp)
21647c478bd9Sstevel@tonic-gate {
21657c478bd9Sstevel@tonic-gate int i, j, k, l_index, length, idx = 0;
21667c478bd9Sstevel@tonic-gate char *endptr;
21677c478bd9Sstevel@tonic-gate char **lenvp;
21687c478bd9Sstevel@tonic-gate char **pam_env;
21697c478bd9Sstevel@tonic-gate
21707c478bd9Sstevel@tonic-gate lenvp = environ;
21717c478bd9Sstevel@tonic-gate while (*lenvp++)
21727c478bd9Sstevel@tonic-gate ;
21737c478bd9Sstevel@tonic-gate
21747c478bd9Sstevel@tonic-gate /* count the number of PAM environment variables set by modules */
21757c478bd9Sstevel@tonic-gate if ((pam_env = pam_getenvlist(pamh)) != 0) {
21767c478bd9Sstevel@tonic-gate for (idx = 0; pam_env[idx] != 0; idx++)
21777c478bd9Sstevel@tonic-gate ;
21787c478bd9Sstevel@tonic-gate }
21797c478bd9Sstevel@tonic-gate
21802a0352b4Sgww envinit = (char **)calloc(lenvp - environ + 10 + MAXARGS + idx,
21812a0352b4Sgww sizeof (char *));
21827c478bd9Sstevel@tonic-gate if (envinit == NULL) {
21837c478bd9Sstevel@tonic-gate (void) printf("Calloc failed - out of swap space.\n");
21847c478bd9Sstevel@tonic-gate login_exit(8);
21857c478bd9Sstevel@tonic-gate }
21867c478bd9Sstevel@tonic-gate
21877c478bd9Sstevel@tonic-gate /*
21887c478bd9Sstevel@tonic-gate * add PAM environment variables first so they
21897c478bd9Sstevel@tonic-gate * can be overwritten at login's discretion.
21907c478bd9Sstevel@tonic-gate * check for illegal environment variables.
21917c478bd9Sstevel@tonic-gate */
21927c478bd9Sstevel@tonic-gate idx = 0; basicenv = 0;
21937c478bd9Sstevel@tonic-gate if (pam_env != 0) {
21947c478bd9Sstevel@tonic-gate while (pam_env[idx] != 0) {
21957c478bd9Sstevel@tonic-gate if (legalenvvar(pam_env[idx])) {
21967c478bd9Sstevel@tonic-gate envinit[basicenv] = pam_env[idx];
21977c478bd9Sstevel@tonic-gate basicenv++;
21987c478bd9Sstevel@tonic-gate }
21997c478bd9Sstevel@tonic-gate idx++;
22007c478bd9Sstevel@tonic-gate }
22017c478bd9Sstevel@tonic-gate }
22027c478bd9Sstevel@tonic-gate (void) memcpy(&envinit[basicenv], newenv, sizeof (newenv));
22037c478bd9Sstevel@tonic-gate
22047c478bd9Sstevel@tonic-gate /* Set up environment */
22057c478bd9Sstevel@tonic-gate if (rflag) {
22067c478bd9Sstevel@tonic-gate ENVSTRNCAT(term, terminal);
22077c478bd9Sstevel@tonic-gate } else if (hflag) {
22087c478bd9Sstevel@tonic-gate if (strlen(terminal)) {
22097c478bd9Sstevel@tonic-gate ENVSTRNCAT(term, terminal);
22107c478bd9Sstevel@tonic-gate }
22117c478bd9Sstevel@tonic-gate } else {
22127c478bd9Sstevel@tonic-gate char *tp = getenv("TERM");
22137c478bd9Sstevel@tonic-gate
22147c478bd9Sstevel@tonic-gate if ((tp != NULL) && (*tp != '\0'))
22157c478bd9Sstevel@tonic-gate ENVSTRNCAT(term, tp);
22167c478bd9Sstevel@tonic-gate }
22177c478bd9Sstevel@tonic-gate
22187c478bd9Sstevel@tonic-gate ENVSTRNCAT(logname, pwd->pw_name);
22197c478bd9Sstevel@tonic-gate
22207c478bd9Sstevel@tonic-gate /*
22217c478bd9Sstevel@tonic-gate * There are three places to get timezone info. init.c sets
2222052519c2SGarrett D'Amore * TZ if the file /etc/default/init contains a value for TZ.
22237c478bd9Sstevel@tonic-gate * login.c looks in the file /etc/default/login for a
22247c478bd9Sstevel@tonic-gate * variable called TIMEZONE being set. If TIMEZONE has a
22257c478bd9Sstevel@tonic-gate * value, TZ is set to that value; no environment variable
22267c478bd9Sstevel@tonic-gate * TIMEZONE is set, only TZ. If neither of these methods
22277c478bd9Sstevel@tonic-gate * work to set TZ, then the library routines will default
22287c478bd9Sstevel@tonic-gate * to using the file /usr/lib/locale/TZ/localtime.
22297c478bd9Sstevel@tonic-gate *
2230052519c2SGarrett D'Amore * There is a priority set up here. If /etc/default/init has
22317c478bd9Sstevel@tonic-gate * a value for TZ, that value remains top priority. If the
22327c478bd9Sstevel@tonic-gate * file /etc/default/login has TIMEZONE set, that has second
22337c478bd9Sstevel@tonic-gate * highest priority not overriding the value of TZ in
2234052519c2SGarrett D'Amore * /etc/default/init. The reason for this priority is that the
2235052519c2SGarrett D'Amore * file /etc/default/init is supposed to be sourced by
22367c478bd9Sstevel@tonic-gate * /etc/profile. We are doing the "sourcing" prematurely in
22377c478bd9Sstevel@tonic-gate * init.c. Additionally, a login C shell doesn't source the
2238052519c2SGarrett D'Amore * file /etc/profile thus not sourcing /etc/default/init thus not
22397c478bd9Sstevel@tonic-gate * allowing an adminstrator to globally set TZ for all users
22407c478bd9Sstevel@tonic-gate */
22417c478bd9Sstevel@tonic-gate if (Def_tz != NULL) /* Is there a TZ from defaults/login? */
22427c478bd9Sstevel@tonic-gate tmp_tz = Def_tz;
22437c478bd9Sstevel@tonic-gate
22447c478bd9Sstevel@tonic-gate if ((Def_tz = getenv("TZ")) != NULL) {
22457c478bd9Sstevel@tonic-gate ENVSTRNCAT(timez, Def_tz);
22467c478bd9Sstevel@tonic-gate } else if (tmp_tz != NULL) {
22477c478bd9Sstevel@tonic-gate Def_tz = tmp_tz;
22487c478bd9Sstevel@tonic-gate ENVSTRNCAT(timez, Def_tz);
22497c478bd9Sstevel@tonic-gate }
22507c478bd9Sstevel@tonic-gate
22517c478bd9Sstevel@tonic-gate if (Def_hertz == NULL)
22527c478bd9Sstevel@tonic-gate (void) sprintf(hertz + strlen(hertz), "%lu", HZ);
22537c478bd9Sstevel@tonic-gate else
22547c478bd9Sstevel@tonic-gate ENVSTRNCAT(hertz, Def_hertz);
22557c478bd9Sstevel@tonic-gate
22567c478bd9Sstevel@tonic-gate if (Def_path == NULL)
22577c478bd9Sstevel@tonic-gate (void) strlcat(path, DEF_PATH, sizeof (path));
22587c478bd9Sstevel@tonic-gate else
22597c478bd9Sstevel@tonic-gate ENVSTRNCAT(path, Def_path);
22607c478bd9Sstevel@tonic-gate
22617c478bd9Sstevel@tonic-gate ENVSTRNCAT(home, pwd->pw_dir);
22627c478bd9Sstevel@tonic-gate
22637c478bd9Sstevel@tonic-gate /*
22647c478bd9Sstevel@tonic-gate * Find the end of the basic environment
22657c478bd9Sstevel@tonic-gate */
22667c478bd9Sstevel@tonic-gate for (basicenv = 0; envinit[basicenv] != NULL; basicenv++)
22677c478bd9Sstevel@tonic-gate ;
22687c478bd9Sstevel@tonic-gate
22697c478bd9Sstevel@tonic-gate /*
22707c478bd9Sstevel@tonic-gate * If TZ has a value, add it.
22717c478bd9Sstevel@tonic-gate */
22727c478bd9Sstevel@tonic-gate if (strcmp(timez, "TZ=") != 0)
22737c478bd9Sstevel@tonic-gate envinit[basicenv++] = timez;
22747c478bd9Sstevel@tonic-gate
22757c478bd9Sstevel@tonic-gate if (*pwd->pw_shell == '\0') {
22767c478bd9Sstevel@tonic-gate /*
22777c478bd9Sstevel@tonic-gate * If possible, use the primary default shell,
22787c478bd9Sstevel@tonic-gate * otherwise, use the secondary one.
22797c478bd9Sstevel@tonic-gate */
22807c478bd9Sstevel@tonic-gate if (access(SHELL, X_OK) == 0)
22817c478bd9Sstevel@tonic-gate pwd->pw_shell = SHELL;
22827c478bd9Sstevel@tonic-gate else
22837c478bd9Sstevel@tonic-gate pwd->pw_shell = SHELL2;
22847c478bd9Sstevel@tonic-gate } else if (Altshell != NULL && strcmp(Altshell, "YES") == 0) {
22857c478bd9Sstevel@tonic-gate envinit[basicenv++] = shell;
22867c478bd9Sstevel@tonic-gate ENVSTRNCAT(shell, pwd->pw_shell);
22877c478bd9Sstevel@tonic-gate }
22887c478bd9Sstevel@tonic-gate
22897c478bd9Sstevel@tonic-gate #ifndef NO_MAIL
22907c478bd9Sstevel@tonic-gate envinit[basicenv++] = mail;
22917c478bd9Sstevel@tonic-gate (void) strlcat(mail, pwd->pw_name, sizeof (mail));
22927c478bd9Sstevel@tonic-gate #endif
22937c478bd9Sstevel@tonic-gate
22947c478bd9Sstevel@tonic-gate /*
22957c478bd9Sstevel@tonic-gate * Pick up locale environment variables, if any.
22967c478bd9Sstevel@tonic-gate */
22977c478bd9Sstevel@tonic-gate lenvp = renvp;
22987c478bd9Sstevel@tonic-gate while (*lenvp != NULL) {
22997c478bd9Sstevel@tonic-gate j = 0;
23007c478bd9Sstevel@tonic-gate while (localeenv[j] != 0) {
23017c478bd9Sstevel@tonic-gate /*
23027c478bd9Sstevel@tonic-gate * locale_envmatch() returns 1 if
23037c478bd9Sstevel@tonic-gate * *lenvp is localenev[j] and valid.
23047c478bd9Sstevel@tonic-gate */
23057c478bd9Sstevel@tonic-gate if (locale_envmatch(localeenv[j], *lenvp) == 1) {
23067c478bd9Sstevel@tonic-gate envinit[basicenv++] = *lenvp;
23077c478bd9Sstevel@tonic-gate break;
23087c478bd9Sstevel@tonic-gate }
23097c478bd9Sstevel@tonic-gate j++;
23107c478bd9Sstevel@tonic-gate }
23117c478bd9Sstevel@tonic-gate lenvp++;
23127c478bd9Sstevel@tonic-gate }
23137c478bd9Sstevel@tonic-gate
23147c478bd9Sstevel@tonic-gate /*
23157c478bd9Sstevel@tonic-gate * If '-p' flag, then try to pass on allowable environment
23167c478bd9Sstevel@tonic-gate * variables. Note that by processing this first, what is
23177c478bd9Sstevel@tonic-gate * passed on the final "login:" line may over-ride the invocation
23187c478bd9Sstevel@tonic-gate * values. XXX is this correct?
23197c478bd9Sstevel@tonic-gate */
23207c478bd9Sstevel@tonic-gate if (pflag) {
23217c478bd9Sstevel@tonic-gate for (lenvp = renvp; *lenvp; lenvp++) {
23227c478bd9Sstevel@tonic-gate if (!legalenvvar(*lenvp)) {
23237c478bd9Sstevel@tonic-gate continue;
23247c478bd9Sstevel@tonic-gate }
23257c478bd9Sstevel@tonic-gate /*
23267c478bd9Sstevel@tonic-gate * If this isn't 'xxx=yyy', skip it. XXX
23277c478bd9Sstevel@tonic-gate */
23287c478bd9Sstevel@tonic-gate if ((endptr = strchr(*lenvp, '=')) == NULL) {
23297c478bd9Sstevel@tonic-gate continue;
23307c478bd9Sstevel@tonic-gate }
23317c478bd9Sstevel@tonic-gate length = endptr + 1 - *lenvp;
23327c478bd9Sstevel@tonic-gate for (j = 0; j < basicenv; j++) {
23337c478bd9Sstevel@tonic-gate if (strncmp(envinit[j], *lenvp, length) == 0) {
23347c478bd9Sstevel@tonic-gate /*
23357c478bd9Sstevel@tonic-gate * Replace previously established value
23367c478bd9Sstevel@tonic-gate */
23377c478bd9Sstevel@tonic-gate envinit[j] = *lenvp;
23387c478bd9Sstevel@tonic-gate break;
23397c478bd9Sstevel@tonic-gate }
23407c478bd9Sstevel@tonic-gate }
23417c478bd9Sstevel@tonic-gate if (j == basicenv) {
23427c478bd9Sstevel@tonic-gate /*
23437c478bd9Sstevel@tonic-gate * It's a new definition, so add it at the end.
23447c478bd9Sstevel@tonic-gate */
23457c478bd9Sstevel@tonic-gate envinit[basicenv++] = *lenvp;
23467c478bd9Sstevel@tonic-gate }
23477c478bd9Sstevel@tonic-gate }
23487c478bd9Sstevel@tonic-gate }
23497c478bd9Sstevel@tonic-gate
23507c478bd9Sstevel@tonic-gate /*
23517c478bd9Sstevel@tonic-gate * Add in all the environment variables picked up from the
23527c478bd9Sstevel@tonic-gate * argument list to "login" or from the user response to the
23537c478bd9Sstevel@tonic-gate * "login" request, if any.
23547c478bd9Sstevel@tonic-gate */
23557c478bd9Sstevel@tonic-gate
23567c478bd9Sstevel@tonic-gate if (envp == NULL)
23577c478bd9Sstevel@tonic-gate goto switch_env; /* done */
23587c478bd9Sstevel@tonic-gate
23597c478bd9Sstevel@tonic-gate for (j = 0, k = 0, l_index = 0;
23607c478bd9Sstevel@tonic-gate *envp != NULL && j < (MAXARGS-1);
23617c478bd9Sstevel@tonic-gate j++, envp++) {
23627c478bd9Sstevel@tonic-gate
23637c478bd9Sstevel@tonic-gate /*
23647c478bd9Sstevel@tonic-gate * Scan each string provided. If it doesn't have the
23657c478bd9Sstevel@tonic-gate * format xxx=yyy, then add the string "Ln=" to the beginning.
23667c478bd9Sstevel@tonic-gate */
23677c478bd9Sstevel@tonic-gate if ((endptr = strchr(*envp, '=')) == NULL) {
23687c478bd9Sstevel@tonic-gate /*
23697c478bd9Sstevel@tonic-gate * This much to be malloc'd:
23707c478bd9Sstevel@tonic-gate * strlen(*envp) + 1 char for 'L' +
23717c478bd9Sstevel@tonic-gate * MAXARGSWIDTH + 1 char for '=' + 1 for null char;
23727c478bd9Sstevel@tonic-gate *
23737c478bd9Sstevel@tonic-gate * total = strlen(*envp) + MAXARGSWIDTH + 3
23747c478bd9Sstevel@tonic-gate */
23757c478bd9Sstevel@tonic-gate int total = strlen(*envp) + MAXARGSWIDTH + 3;
23767c478bd9Sstevel@tonic-gate envinit[basicenv+k] = malloc(total);
23777c478bd9Sstevel@tonic-gate if (envinit[basicenv+k] == NULL) {
23787c478bd9Sstevel@tonic-gate (void) printf("%s: malloc failed\n", PROG_NAME);
23797c478bd9Sstevel@tonic-gate login_exit(1);
23807c478bd9Sstevel@tonic-gate }
23817c478bd9Sstevel@tonic-gate (void) snprintf(envinit[basicenv+k], total, "L%d=%s",
23827c478bd9Sstevel@tonic-gate l_index, *envp);
23837c478bd9Sstevel@tonic-gate
23847c478bd9Sstevel@tonic-gate k++;
23857c478bd9Sstevel@tonic-gate l_index++;
23867c478bd9Sstevel@tonic-gate } else {
23877c478bd9Sstevel@tonic-gate if (!legalenvvar(*envp)) { /* this env var permited? */
23887c478bd9Sstevel@tonic-gate continue;
23897c478bd9Sstevel@tonic-gate } else {
23907c478bd9Sstevel@tonic-gate
23917c478bd9Sstevel@tonic-gate /*
23927c478bd9Sstevel@tonic-gate * Check to see whether this string replaces
23937c478bd9Sstevel@tonic-gate * any previously defined string
23947c478bd9Sstevel@tonic-gate */
23957c478bd9Sstevel@tonic-gate for (i = 0, length = endptr + 1 - *envp;
23967c478bd9Sstevel@tonic-gate i < basicenv + k; i++) {
23977c478bd9Sstevel@tonic-gate if (strncmp(*envp, envinit[i], length)
23987c478bd9Sstevel@tonic-gate == 0) {
23997c478bd9Sstevel@tonic-gate envinit[i] = *envp;
24007c478bd9Sstevel@tonic-gate break;
24017c478bd9Sstevel@tonic-gate }
24027c478bd9Sstevel@tonic-gate }
24037c478bd9Sstevel@tonic-gate
24047c478bd9Sstevel@tonic-gate /*
24057c478bd9Sstevel@tonic-gate * If it doesn't, place it at the end of
24067c478bd9Sstevel@tonic-gate * environment array.
24077c478bd9Sstevel@tonic-gate */
24087c478bd9Sstevel@tonic-gate if (i == basicenv+k) {
24097c478bd9Sstevel@tonic-gate envinit[basicenv+k] = *envp;
24107c478bd9Sstevel@tonic-gate k++;
24117c478bd9Sstevel@tonic-gate }
24127c478bd9Sstevel@tonic-gate }
24137c478bd9Sstevel@tonic-gate }
24147c478bd9Sstevel@tonic-gate } /* for (j = 0 ... ) */
24157c478bd9Sstevel@tonic-gate
24167c478bd9Sstevel@tonic-gate switch_env:
24177c478bd9Sstevel@tonic-gate /*
24187c478bd9Sstevel@tonic-gate * Switch to the new environment.
24197c478bd9Sstevel@tonic-gate */
24207c478bd9Sstevel@tonic-gate environ = envinit;
24217c478bd9Sstevel@tonic-gate }
24227c478bd9Sstevel@tonic-gate
24237c478bd9Sstevel@tonic-gate /*
24242de0a7d6SDan McDonald * print_banner - Print the banner at start up
24252de0a7d6SDan McDonald * Do not turn on DOBANNER ifdef. This is not
24262de0a7d6SDan McDonald * relevant to SunOS.
24272de0a7d6SDan McDonald */
24282de0a7d6SDan McDonald
24292de0a7d6SDan McDonald static void
print_banner(void)24302de0a7d6SDan McDonald print_banner(void)
24312de0a7d6SDan McDonald {
24322de0a7d6SDan McDonald #ifdef DOBANNER
24332de0a7d6SDan McDonald uname(&un);
24342de0a7d6SDan McDonald #if i386
24352de0a7d6SDan McDonald (void) printf("UNIX System V/386 Release %s\n%s\n"
24362de0a7d6SDan McDonald "Copyright (C) 1984, 1986, 1987, 1988 AT&T\n"
24372de0a7d6SDan McDonald "Copyright (C) 1987, 1988 Microsoft Corp.\nAll Rights Reserved\n",
24382de0a7d6SDan McDonald un.release, un.nodename);
24392de0a7d6SDan McDonald #elif sun
24402de0a7d6SDan McDonald (void) printf("SunOS Release %s Sun Microsystems %s\n%s\n"
24412de0a7d6SDan McDonald "Copyright (c) 1984, 1986, 1987, 1988 AT&T\n"
24422de0a7d6SDan McDonald "Copyright (c) 1988, 1989, 1990, 1991 Sun Microsystems\n"
24432de0a7d6SDan McDonald "All Rights Reserved\n",
24442de0a7d6SDan McDonald un.release, un.machine, un.nodename);
24452de0a7d6SDan McDonald #else
24462de0a7d6SDan McDonald (void) printf("UNIX System V Release %s AT&T %s\n%s\n"
24472de0a7d6SDan McDonald "Copyright (c) 1984, 1986, 1987, 1988 AT&T\nAll Rights Reserved\n",
24482de0a7d6SDan McDonald un.release, un.machine, un.nodename);
24492de0a7d6SDan McDonald #endif /* i386 */
24502de0a7d6SDan McDonald #endif /* DOBANNER */
24512de0a7d6SDan McDonald }
24522de0a7d6SDan McDonald
24532de0a7d6SDan McDonald /*
24542de0a7d6SDan McDonald * display_last_login_time - Advise the user the time and date
24552de0a7d6SDan McDonald * that this login-id was last used.
24562de0a7d6SDan McDonald */
24572de0a7d6SDan McDonald
24582de0a7d6SDan McDonald static void
display_last_login_time(void)24592de0a7d6SDan McDonald display_last_login_time(void)
24602de0a7d6SDan McDonald {
24612de0a7d6SDan McDonald if (lastlogok) {
24622de0a7d6SDan McDonald (void) printf("Last login: %.*s ", 24-5, ctime(&ll.ll_time));
24632de0a7d6SDan McDonald
24642de0a7d6SDan McDonald if (*ll.ll_host != '\0')
24652de0a7d6SDan McDonald (void) printf("from %.*s\n", sizeof (ll.ll_host),
24662de0a7d6SDan McDonald ll.ll_host);
24672de0a7d6SDan McDonald else
24682de0a7d6SDan McDonald (void) printf("on %.*s\n", sizeof (ll.ll_line),
24692de0a7d6SDan McDonald ll.ll_line);
24702de0a7d6SDan McDonald }
24712de0a7d6SDan McDonald }
24722de0a7d6SDan McDonald
24732de0a7d6SDan McDonald /*
24747c478bd9Sstevel@tonic-gate * exec_the_shell - invoke the specified shell or start up program
24757c478bd9Sstevel@tonic-gate */
24767c478bd9Sstevel@tonic-gate
24777c478bd9Sstevel@tonic-gate static void
exec_the_shell(void)24787c478bd9Sstevel@tonic-gate exec_the_shell(void)
24797c478bd9Sstevel@tonic-gate {
24807c478bd9Sstevel@tonic-gate char *endptr;
24817c478bd9Sstevel@tonic-gate int i;
24827c478bd9Sstevel@tonic-gate
24837c478bd9Sstevel@tonic-gate (void) strlcat(minusnam, basename(pwd->pw_shell),
24847c478bd9Sstevel@tonic-gate sizeof (minusnam));
24857c478bd9Sstevel@tonic-gate
24867c478bd9Sstevel@tonic-gate /*
24877c478bd9Sstevel@tonic-gate * Exec the shell
24887c478bd9Sstevel@tonic-gate */
24897c478bd9Sstevel@tonic-gate (void) execl(pwd->pw_shell, minusnam, (char *)0);
24907c478bd9Sstevel@tonic-gate
24917c478bd9Sstevel@tonic-gate /*
24927c478bd9Sstevel@tonic-gate * pwd->pw_shell was not an executable object file, maybe it
24937c478bd9Sstevel@tonic-gate * is a shell proceedure or a command line with arguments.
24947c478bd9Sstevel@tonic-gate * If so, turn off the SHELL= environment variable.
24957c478bd9Sstevel@tonic-gate */
24967c478bd9Sstevel@tonic-gate for (i = 0; envinit[i] != NULL; ++i) {
24977c478bd9Sstevel@tonic-gate if ((envinit[i] == shell) &&
24987c478bd9Sstevel@tonic-gate ((endptr = strchr(shell, '=')) != NULL))
24997c478bd9Sstevel@tonic-gate (*++endptr) = '\0';
25007c478bd9Sstevel@tonic-gate }
25017c478bd9Sstevel@tonic-gate
25027c478bd9Sstevel@tonic-gate if (access(pwd->pw_shell, R_OK|X_OK) == 0) {
25037c478bd9Sstevel@tonic-gate (void) execl(SHELL, "sh", pwd->pw_shell, (char *)0);
25047c478bd9Sstevel@tonic-gate (void) execl(SHELL2, "sh", pwd->pw_shell, (char *)0);
25057c478bd9Sstevel@tonic-gate }
25067c478bd9Sstevel@tonic-gate
25077c478bd9Sstevel@tonic-gate (void) printf("No shell\n");
25087c478bd9Sstevel@tonic-gate }
25097c478bd9Sstevel@tonic-gate
25107c478bd9Sstevel@tonic-gate /*
25117c478bd9Sstevel@tonic-gate * login_exit - Call exit() and terminate.
25127c478bd9Sstevel@tonic-gate * This function is here for PAM so cleanup can
25137c478bd9Sstevel@tonic-gate * be done before the process exits.
25147c478bd9Sstevel@tonic-gate */
25157c478bd9Sstevel@tonic-gate static void
login_exit(int exit_code)25167c478bd9Sstevel@tonic-gate login_exit(int exit_code)
25177c478bd9Sstevel@tonic-gate {
25187c478bd9Sstevel@tonic-gate if (pamh)
25197c478bd9Sstevel@tonic-gate (void) pam_end(pamh, PAM_ABORT);
25207c478bd9Sstevel@tonic-gate
25217c478bd9Sstevel@tonic-gate if (audit_error)
25227c478bd9Sstevel@tonic-gate audit_failure(get_audit_id(), audit_error,
25237c478bd9Sstevel@tonic-gate pwd, remote_host, ttyn, zone_name);
25247c478bd9Sstevel@tonic-gate
25257c478bd9Sstevel@tonic-gate exit(exit_code);
25267c478bd9Sstevel@tonic-gate /*NOTREACHED*/
25277c478bd9Sstevel@tonic-gate }
25287c478bd9Sstevel@tonic-gate
25297c478bd9Sstevel@tonic-gate /*
25307c478bd9Sstevel@tonic-gate * Check if lenv and penv matches or not.
25317c478bd9Sstevel@tonic-gate */
25327c478bd9Sstevel@tonic-gate static int
locale_envmatch(char * lenv,char * penv)25337c478bd9Sstevel@tonic-gate locale_envmatch(char *lenv, char *penv)
25347c478bd9Sstevel@tonic-gate {
25357c478bd9Sstevel@tonic-gate while ((*lenv == *penv) && *lenv && *penv != '=') {
25367c478bd9Sstevel@tonic-gate lenv++;
25377c478bd9Sstevel@tonic-gate penv++;
25387c478bd9Sstevel@tonic-gate }
25397c478bd9Sstevel@tonic-gate
25407c478bd9Sstevel@tonic-gate /*
25417c478bd9Sstevel@tonic-gate * '/' is eliminated for security reason.
25427c478bd9Sstevel@tonic-gate */
25437c478bd9Sstevel@tonic-gate if (*lenv == '\0' && *penv == '=' && *(penv + 1) != '/')
25447c478bd9Sstevel@tonic-gate return (1);
25457c478bd9Sstevel@tonic-gate return (0);
25467c478bd9Sstevel@tonic-gate }
25477c478bd9Sstevel@tonic-gate
25487c478bd9Sstevel@tonic-gate static int
is_number(char * ptr)25497c478bd9Sstevel@tonic-gate is_number(char *ptr)
25507c478bd9Sstevel@tonic-gate {
25517c478bd9Sstevel@tonic-gate while (*ptr != '\0') {
25527c478bd9Sstevel@tonic-gate if (!isdigit(*ptr))
25537c478bd9Sstevel@tonic-gate return (0);
25547c478bd9Sstevel@tonic-gate ptr++;
25557c478bd9Sstevel@tonic-gate }
25567c478bd9Sstevel@tonic-gate return (1);
25577c478bd9Sstevel@tonic-gate }
2558