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