1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 28*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate /* 32*7c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 33*7c478bd9Sstevel@tonic-gate * The Regents of the University of California 34*7c478bd9Sstevel@tonic-gate * All Rights Reserved 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 37*7c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 38*7c478bd9Sstevel@tonic-gate * contributors. 39*7c478bd9Sstevel@tonic-gate */ 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1987, 1988 Microsoft Corporation */ 42*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate /* 49*7c478bd9Sstevel@tonic-gate * For a complete reference to login(1), see the manual page. However, 50*7c478bd9Sstevel@tonic-gate * login has accreted some intentionally undocumented options, which are 51*7c478bd9Sstevel@tonic-gate * explained here: 52*7c478bd9Sstevel@tonic-gate * 53*7c478bd9Sstevel@tonic-gate * -a: This legacy flag appears to be unused. 54*7c478bd9Sstevel@tonic-gate * 55*7c478bd9Sstevel@tonic-gate * -f <username>: This flag was introduced by PSARC 1995/039 in support 56*7c478bd9Sstevel@tonic-gate * of Kerberos. But it's not used by Sun's Kerberos implementation. 57*7c478bd9Sstevel@tonic-gate * It is however employed by zlogin(1), since it allows one to tell 58*7c478bd9Sstevel@tonic-gate * login: "This user is authenticated." In the case of zlogin that's 59*7c478bd9Sstevel@tonic-gate * true because the zone always trusts the global zone. 60*7c478bd9Sstevel@tonic-gate * 61*7c478bd9Sstevel@tonic-gate * -z <zonename>: This flag is passed to login when zlogin(1) executes a 62*7c478bd9Sstevel@tonic-gate * zone login. This tells login(1) to skip it's normal CONSOLE check 63*7c478bd9Sstevel@tonic-gate * (i.e. that the root login must be on /dev/console) and tells us the 64*7c478bd9Sstevel@tonic-gate * name of the zone from which the login is occuring. 65*7c478bd9Sstevel@tonic-gate */ 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 68*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 69*7c478bd9Sstevel@tonic-gate #include <unistd.h> /* For logfile locking */ 70*7c478bd9Sstevel@tonic-gate #include <signal.h> 71*7c478bd9Sstevel@tonic-gate #include <stdio.h> 72*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 73*7c478bd9Sstevel@tonic-gate #include <string.h> 74*7c478bd9Sstevel@tonic-gate #include <deflt.h> 75*7c478bd9Sstevel@tonic-gate #include <grp.h> 76*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 77*7c478bd9Sstevel@tonic-gate #include <lastlog.h> 78*7c478bd9Sstevel@tonic-gate #include <termio.h> 79*7c478bd9Sstevel@tonic-gate #include <utmpx.h> 80*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 81*7c478bd9Sstevel@tonic-gate #include <wait.h> 82*7c478bd9Sstevel@tonic-gate #include <errno.h> 83*7c478bd9Sstevel@tonic-gate #include <ctype.h> 84*7c478bd9Sstevel@tonic-gate #include <syslog.h> 85*7c478bd9Sstevel@tonic-gate #include <ulimit.h> 86*7c478bd9Sstevel@tonic-gate #include <libgen.h> 87*7c478bd9Sstevel@tonic-gate #include <pwd.h> 88*7c478bd9Sstevel@tonic-gate #include <security/pam_appl.h> 89*7c478bd9Sstevel@tonic-gate #include <strings.h> 90*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 91*7c478bd9Sstevel@tonic-gate #include <zone.h> 92*7c478bd9Sstevel@tonic-gate #include "login_audit.h" 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate #include <krb5_repository.h> 95*7c478bd9Sstevel@tonic-gate /* 96*7c478bd9Sstevel@tonic-gate * 97*7c478bd9Sstevel@tonic-gate * *** Defines, Macros, and String Constants *** 98*7c478bd9Sstevel@tonic-gate * 99*7c478bd9Sstevel@tonic-gate * 100*7c478bd9Sstevel@tonic-gate */ 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate #define ISSUEFILE "/etc/issue" /* file to print before prompt */ 103*7c478bd9Sstevel@tonic-gate #define NOLOGIN "/etc/nologin" /* file to lock users out during shutdown */ 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate /* 106*7c478bd9Sstevel@tonic-gate * These need to be defined for UTMPX management. 107*7c478bd9Sstevel@tonic-gate * If we add in the utility functions later, we 108*7c478bd9Sstevel@tonic-gate * can remove them. 109*7c478bd9Sstevel@tonic-gate */ 110*7c478bd9Sstevel@tonic-gate #define __UPDATE_ENTRY 1 111*7c478bd9Sstevel@tonic-gate #define __LOGIN 2 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate /* 114*7c478bd9Sstevel@tonic-gate * Intervals to sleep after failed login 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate #ifndef SLEEPTIME 117*7c478bd9Sstevel@tonic-gate #define SLEEPTIME 4 /* sleeptime before login incorrect msg */ 118*7c478bd9Sstevel@tonic-gate #endif 119*7c478bd9Sstevel@tonic-gate static int Sleeptime = SLEEPTIME; 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate /* 122*7c478bd9Sstevel@tonic-gate * seconds login disabled after allowable number of unsuccessful attempts 123*7c478bd9Sstevel@tonic-gate */ 124*7c478bd9Sstevel@tonic-gate #ifndef DISABLETIME 125*7c478bd9Sstevel@tonic-gate #define DISABLETIME 20 126*7c478bd9Sstevel@tonic-gate #endif 127*7c478bd9Sstevel@tonic-gate static int Disabletime = DISABLETIME; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate #define MAXTRYS 5 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate static int retry = MAXTRYS; 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate /* 134*7c478bd9Sstevel@tonic-gate * Login logging support 135*7c478bd9Sstevel@tonic-gate */ 136*7c478bd9Sstevel@tonic-gate #define LOGINLOG "/var/adm/loginlog" /* login log file */ 137*7c478bd9Sstevel@tonic-gate #define LNAME_SIZE 20 /* size of logged logname */ 138*7c478bd9Sstevel@tonic-gate #define TTYN_SIZE 15 /* size of logged tty name */ 139*7c478bd9Sstevel@tonic-gate #define TIME_SIZE 30 /* size of logged time string */ 140*7c478bd9Sstevel@tonic-gate #define ENT_SIZE (LNAME_SIZE + TTYN_SIZE + TIME_SIZE + 3) 141*7c478bd9Sstevel@tonic-gate #define L_WAITTIME 5 /* waittime for log file to unlock */ 142*7c478bd9Sstevel@tonic-gate #define LOGTRYS 10 /* depth of 'try' logging */ 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate /* 145*7c478bd9Sstevel@tonic-gate * String manipulation macros: SCPYN, SCPYL, EQN and ENVSTRNCAT 146*7c478bd9Sstevel@tonic-gate * SCPYL is the safer version of SCPYN 147*7c478bd9Sstevel@tonic-gate */ 148*7c478bd9Sstevel@tonic-gate #define SCPYL(a, b) (void) strlcpy(a, b, sizeof (a)) 149*7c478bd9Sstevel@tonic-gate #define SCPYN(a, b) (void) strncpy(a, b, sizeof (a)) 150*7c478bd9Sstevel@tonic-gate #define EQN(a, b) (strncmp(a, b, sizeof (a)-1) == 0) 151*7c478bd9Sstevel@tonic-gate #define ENVSTRNCAT(to, from) {int deflen; deflen = strlen(to); \ 152*7c478bd9Sstevel@tonic-gate (void) strncpy((to)+ deflen, (from), sizeof (to) - (1 + deflen)); } 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate /* 155*7c478bd9Sstevel@tonic-gate * Other macros 156*7c478bd9Sstevel@tonic-gate */ 157*7c478bd9Sstevel@tonic-gate #define NMAX sizeof (((struct utmpx *)0)->ut_name) 158*7c478bd9Sstevel@tonic-gate #define HMAX sizeof (((struct utmpx *)0)->ut_host) 159*7c478bd9Sstevel@tonic-gate #define min(a, b) (((a) < (b)) ? (a) : (b)) 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate /* 162*7c478bd9Sstevel@tonic-gate * Various useful files and string constants 163*7c478bd9Sstevel@tonic-gate */ 164*7c478bd9Sstevel@tonic-gate #define SHELL "/usr/bin/sh" 165*7c478bd9Sstevel@tonic-gate #define SHELL2 "/sbin/sh" 166*7c478bd9Sstevel@tonic-gate #define SUBLOGIN "<!sublogin>" 167*7c478bd9Sstevel@tonic-gate #define LASTLOG "/var/adm/lastlog" 168*7c478bd9Sstevel@tonic-gate #define PROG_NAME "login" 169*7c478bd9Sstevel@tonic-gate #define HUSHLOGIN ".hushlogin" 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 172*7c478bd9Sstevel@tonic-gate /* 173*7c478bd9Sstevel@tonic-gate * Array and Buffer sizes 174*7c478bd9Sstevel@tonic-gate */ 175*7c478bd9Sstevel@tonic-gate #define PBUFSIZE 8 /* max significant characters in a password */ 176*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 177*7c478bd9Sstevel@tonic-gate #define MAXARGS 63 /* change value below if changing this */ 178*7c478bd9Sstevel@tonic-gate #define MAXARGSWIDTH 2 /* log10(MAXARGS) */ 179*7c478bd9Sstevel@tonic-gate #define MAXENV 1024 180*7c478bd9Sstevel@tonic-gate #define MAXLINE 2048 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate /* 183*7c478bd9Sstevel@tonic-gate * Miscellaneous constants 184*7c478bd9Sstevel@tonic-gate */ 185*7c478bd9Sstevel@tonic-gate #define ROOTUID 0 186*7c478bd9Sstevel@tonic-gate #define ERROR 1 187*7c478bd9Sstevel@tonic-gate #define OK 0 188*7c478bd9Sstevel@tonic-gate #define LOG_ERROR 1 189*7c478bd9Sstevel@tonic-gate #define DONT_LOG_ERROR 0 190*7c478bd9Sstevel@tonic-gate #define TRUE 1 191*7c478bd9Sstevel@tonic-gate #define FALSE 0 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate /* 194*7c478bd9Sstevel@tonic-gate * Counters for counting the number of failed login attempts 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate static int trys = 0; 197*7c478bd9Sstevel@tonic-gate static int count = 1; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate /* 200*7c478bd9Sstevel@tonic-gate * error value for login_exit() audit output (0 == no audit record) 201*7c478bd9Sstevel@tonic-gate */ 202*7c478bd9Sstevel@tonic-gate static int audit_error = 0; 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate /* 205*7c478bd9Sstevel@tonic-gate * Externs a plenty 206*7c478bd9Sstevel@tonic-gate */ 207*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 208*7c478bd9Sstevel@tonic-gate extern int getsecretkey(); 209*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * The current user name 213*7c478bd9Sstevel@tonic-gate */ 214*7c478bd9Sstevel@tonic-gate static char user_name[NMAX]; 215*7c478bd9Sstevel@tonic-gate static char minusnam[16] = "-"; 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate /* 218*7c478bd9Sstevel@tonic-gate * locale environments to be passed to shells. 219*7c478bd9Sstevel@tonic-gate */ 220*7c478bd9Sstevel@tonic-gate static char *localeenv[] = { 221*7c478bd9Sstevel@tonic-gate "LANG", 222*7c478bd9Sstevel@tonic-gate "LC_CTYPE", "LC_NUMERIC", "LC_TIME", "LC_COLLATE", 223*7c478bd9Sstevel@tonic-gate "LC_MONETARY", "LC_MESSAGES", "LC_ALL", 0}; 224*7c478bd9Sstevel@tonic-gate static int locale_envmatch(char *, char *); 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate /* 227*7c478bd9Sstevel@tonic-gate * Environment variable support 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate static char shell[256] = { "SHELL=" }; 230*7c478bd9Sstevel@tonic-gate static char home[MAXPATHLEN] = { "HOME=" }; 231*7c478bd9Sstevel@tonic-gate static char term[64] = { "TERM=" }; 232*7c478bd9Sstevel@tonic-gate static char logname[30] = { "LOGNAME=" }; 233*7c478bd9Sstevel@tonic-gate static char timez[100] = { "TZ=" }; 234*7c478bd9Sstevel@tonic-gate static char hertz[10] = { "HZ=" }; 235*7c478bd9Sstevel@tonic-gate static char path[MAXPATHLEN] = { "PATH=" }; 236*7c478bd9Sstevel@tonic-gate static char *newenv[10+MAXARGS] = 237*7c478bd9Sstevel@tonic-gate {home, path, logname, hertz, term, 0, 0}; 238*7c478bd9Sstevel@tonic-gate static char **envinit = newenv; 239*7c478bd9Sstevel@tonic-gate static int basicenv; 240*7c478bd9Sstevel@tonic-gate static char *zero = (char *)0; 241*7c478bd9Sstevel@tonic-gate static char **envp; 242*7c478bd9Sstevel@tonic-gate #ifndef NO_MAIL 243*7c478bd9Sstevel@tonic-gate static char mail[30] = { "MAIL=/var/mail/" }; 244*7c478bd9Sstevel@tonic-gate #endif 245*7c478bd9Sstevel@tonic-gate extern char **environ; 246*7c478bd9Sstevel@tonic-gate static char inputline[MAXLINE]; 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate #define MAX_ID_LEN 256 249*7c478bd9Sstevel@tonic-gate #define MAX_REPOSITORY_LEN 256 250*7c478bd9Sstevel@tonic-gate #define MAX_PAMSERVICE_LEN 256 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate static char identity[MAX_ID_LEN]; 253*7c478bd9Sstevel@tonic-gate static char repository[MAX_REPOSITORY_LEN]; 254*7c478bd9Sstevel@tonic-gate static char progname[MAX_PAMSERVICE_LEN]; 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* 258*7c478bd9Sstevel@tonic-gate * Strings used to prompt the user. 259*7c478bd9Sstevel@tonic-gate */ 260*7c478bd9Sstevel@tonic-gate static char loginmsg[] = "login: "; 261*7c478bd9Sstevel@tonic-gate static char passwdmsg[] = "Password:"; 262*7c478bd9Sstevel@tonic-gate static char incorrectmsg[] = "Login incorrect\n"; 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 265*7c478bd9Sstevel@tonic-gate /* 266*7c478bd9Sstevel@tonic-gate * Password file support 267*7c478bd9Sstevel@tonic-gate */ 268*7c478bd9Sstevel@tonic-gate static struct passwd *pwd = NULL; 269*7c478bd9Sstevel@tonic-gate static char remote_host[HMAX]; 270*7c478bd9Sstevel@tonic-gate static char zone_name[ZONENAME_MAX]; 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* 273*7c478bd9Sstevel@tonic-gate * Illegal passwd entries. 274*7c478bd9Sstevel@tonic-gate */ 275*7c478bd9Sstevel@tonic-gate static struct passwd nouser = { "", "no:password", ~ROOTUID }; 276*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate /* 279*7c478bd9Sstevel@tonic-gate * Log file support 280*7c478bd9Sstevel@tonic-gate */ 281*7c478bd9Sstevel@tonic-gate static char *log_entry[LOGTRYS]; 282*7c478bd9Sstevel@tonic-gate static int writelog = 0; 283*7c478bd9Sstevel@tonic-gate static int lastlogok = 0; 284*7c478bd9Sstevel@tonic-gate static struct lastlog ll; 285*7c478bd9Sstevel@tonic-gate static int dosyslog = 0; 286*7c478bd9Sstevel@tonic-gate static int flogin = MAXTRYS; /* flag for SYSLOG_FAILED_LOGINS */ 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate /* 289*7c478bd9Sstevel@tonic-gate * Default file toggles 290*7c478bd9Sstevel@tonic-gate */ 291*7c478bd9Sstevel@tonic-gate static char *Pndefault = "/etc/default/login"; 292*7c478bd9Sstevel@tonic-gate static char *Altshell = NULL; 293*7c478bd9Sstevel@tonic-gate static char *Console = NULL; 294*7c478bd9Sstevel@tonic-gate static int Passreqflag = 0; 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate #define DEFUMASK 022 297*7c478bd9Sstevel@tonic-gate static mode_t Umask = DEFUMASK; 298*7c478bd9Sstevel@tonic-gate static char *Def_tz = NULL; 299*7c478bd9Sstevel@tonic-gate static char *tmp_tz = NULL; 300*7c478bd9Sstevel@tonic-gate static char *Def_hertz = NULL; 301*7c478bd9Sstevel@tonic-gate #define SET_FSIZ 2 /* ulimit() command arg */ 302*7c478bd9Sstevel@tonic-gate static long Def_ulimit = 0; 303*7c478bd9Sstevel@tonic-gate #define MAX_TIMEOUT (15 * 60) 304*7c478bd9Sstevel@tonic-gate #define DEF_TIMEOUT (5 * 60) 305*7c478bd9Sstevel@tonic-gate static unsigned Def_timeout = DEF_TIMEOUT; 306*7c478bd9Sstevel@tonic-gate static char *Def_path = NULL; 307*7c478bd9Sstevel@tonic-gate static char *Def_supath = NULL; 308*7c478bd9Sstevel@tonic-gate #define DEF_PATH "/usr/bin:" /* same as PATH */ 309*7c478bd9Sstevel@tonic-gate #define DEF_SUPATH "/usr/sbin:/usr/bin" /* same as ROOTPATH */ 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate /* 312*7c478bd9Sstevel@tonic-gate * Defaults for updating expired passwords 313*7c478bd9Sstevel@tonic-gate */ 314*7c478bd9Sstevel@tonic-gate #define DEF_ATTEMPTS 3 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate /* 317*7c478bd9Sstevel@tonic-gate * ttyprompt will point to the environment variable TTYPROMPT. 318*7c478bd9Sstevel@tonic-gate * TTYPROMPT is set by ttymon if ttymon already wrote out the prompt. 319*7c478bd9Sstevel@tonic-gate */ 320*7c478bd9Sstevel@tonic-gate static char *ttyprompt = NULL; 321*7c478bd9Sstevel@tonic-gate static char *ttyn = NULL; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate /* 324*7c478bd9Sstevel@tonic-gate * Pass inherited environment. Used by telnetd in support of the telnet 325*7c478bd9Sstevel@tonic-gate * ENVIRON option. 326*7c478bd9Sstevel@tonic-gate */ 327*7c478bd9Sstevel@tonic-gate static boolean_t pflag = B_FALSE; 328*7c478bd9Sstevel@tonic-gate static boolean_t uflag = B_FALSE; 329*7c478bd9Sstevel@tonic-gate static boolean_t Rflag = B_FALSE; 330*7c478bd9Sstevel@tonic-gate static boolean_t sflag = B_FALSE; 331*7c478bd9Sstevel@tonic-gate static boolean_t Uflag = B_FALSE; 332*7c478bd9Sstevel@tonic-gate static boolean_t tflag = B_FALSE; 333*7c478bd9Sstevel@tonic-gate static boolean_t hflag = B_FALSE; 334*7c478bd9Sstevel@tonic-gate static boolean_t rflag = B_FALSE; 335*7c478bd9Sstevel@tonic-gate static boolean_t zflag = B_FALSE; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* 338*7c478bd9Sstevel@tonic-gate * Remote login support 339*7c478bd9Sstevel@tonic-gate */ 340*7c478bd9Sstevel@tonic-gate static char rusername[NMAX+1], lusername[NMAX+1]; 341*7c478bd9Sstevel@tonic-gate static char terminal[MAXPATHLEN]; 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * Pre-authentication flag support 346*7c478bd9Sstevel@tonic-gate */ 347*7c478bd9Sstevel@tonic-gate static int fflag; 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate static char ** getargs(char *); 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate static int login_conv(int, struct pam_message **, 352*7c478bd9Sstevel@tonic-gate struct pam_response **, void *); 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate static struct pam_conv pam_conv = {login_conv, NULL}; 355*7c478bd9Sstevel@tonic-gate static pam_handle_t *pamh; /* Authentication handle */ 356*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate /* 359*7c478bd9Sstevel@tonic-gate * Function declarations 360*7c478bd9Sstevel@tonic-gate */ 361*7c478bd9Sstevel@tonic-gate static void turn_on_logging(void); 362*7c478bd9Sstevel@tonic-gate static void defaults(void); 363*7c478bd9Sstevel@tonic-gate static void usage(void); 364*7c478bd9Sstevel@tonic-gate static void process_rlogin(void); 365*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 366*7c478bd9Sstevel@tonic-gate static void login_authenticate(); 367*7c478bd9Sstevel@tonic-gate static void setup_credentials(void); 368*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 369*7c478bd9Sstevel@tonic-gate static void adjust_nice(void); 370*7c478bd9Sstevel@tonic-gate static void update_utmpx_entry(int); 371*7c478bd9Sstevel@tonic-gate static void establish_user_environment(char **); 372*7c478bd9Sstevel@tonic-gate static void print_banner(void); 373*7c478bd9Sstevel@tonic-gate static void display_last_login_time(void); 374*7c478bd9Sstevel@tonic-gate static void exec_the_shell(void); 375*7c478bd9Sstevel@tonic-gate static int process_chroot_logins(void); 376*7c478bd9Sstevel@tonic-gate static void chdir_to_dir_user(void); 377*7c478bd9Sstevel@tonic-gate static void check_log(void); 378*7c478bd9Sstevel@tonic-gate static void validate_account(void); 379*7c478bd9Sstevel@tonic-gate static void doremoteterm(char *); 380*7c478bd9Sstevel@tonic-gate static int get_options(int, char **); 381*7c478bd9Sstevel@tonic-gate static void getstr(char *, int, char *); 382*7c478bd9Sstevel@tonic-gate static int legalenvvar(char *); 383*7c478bd9Sstevel@tonic-gate static void check_for_console(void); 384*7c478bd9Sstevel@tonic-gate static void check_for_dueling_unix(char *); 385*7c478bd9Sstevel@tonic-gate static void get_user_name(void); 386*7c478bd9Sstevel@tonic-gate static uint_t get_audit_id(void); 387*7c478bd9Sstevel@tonic-gate static void login_exit(int); 388*7c478bd9Sstevel@tonic-gate static int logins_disabled(char *); 389*7c478bd9Sstevel@tonic-gate static void log_bad_attempts(void); 390*7c478bd9Sstevel@tonic-gate static int is_number(char *); 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 393*7c478bd9Sstevel@tonic-gate /* 394*7c478bd9Sstevel@tonic-gate * *** main *** 395*7c478bd9Sstevel@tonic-gate * 396*7c478bd9Sstevel@tonic-gate * The primary flow of control is directed in this routine. 397*7c478bd9Sstevel@tonic-gate * Control moves in line from top to bottom calling subfunctions 398*7c478bd9Sstevel@tonic-gate * which perform the bulk of the work. Many of these calls exit 399*7c478bd9Sstevel@tonic-gate * when a fatal error is encountered and do not return to main. 400*7c478bd9Sstevel@tonic-gate * 401*7c478bd9Sstevel@tonic-gate * 402*7c478bd9Sstevel@tonic-gate */ 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate void 405*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char **renvp) 406*7c478bd9Sstevel@tonic-gate { 407*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 408*7c478bd9Sstevel@tonic-gate int sublogin; 409*7c478bd9Sstevel@tonic-gate int pam_rc; 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate /* 412*7c478bd9Sstevel@tonic-gate * Set up Defaults and flags 413*7c478bd9Sstevel@tonic-gate */ 414*7c478bd9Sstevel@tonic-gate defaults(); 415*7c478bd9Sstevel@tonic-gate SCPYL(progname, PROG_NAME); 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate /* 418*7c478bd9Sstevel@tonic-gate * Set up default umask 419*7c478bd9Sstevel@tonic-gate */ 420*7c478bd9Sstevel@tonic-gate if (Umask > ((mode_t)0777)) 421*7c478bd9Sstevel@tonic-gate Umask = DEFUMASK; 422*7c478bd9Sstevel@tonic-gate (void) umask(Umask); 423*7c478bd9Sstevel@tonic-gate 424*7c478bd9Sstevel@tonic-gate /* 425*7c478bd9Sstevel@tonic-gate * Set up default timeouts and delays 426*7c478bd9Sstevel@tonic-gate */ 427*7c478bd9Sstevel@tonic-gate if (Def_timeout > MAX_TIMEOUT) 428*7c478bd9Sstevel@tonic-gate Def_timeout = MAX_TIMEOUT; 429*7c478bd9Sstevel@tonic-gate if (Sleeptime < 0 || Sleeptime > 5) 430*7c478bd9Sstevel@tonic-gate Sleeptime = SLEEPTIME; 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate (void) alarm(Def_timeout); 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate /* 435*7c478bd9Sstevel@tonic-gate * Ignore SIGQUIT and SIGINT and set nice to 0 436*7c478bd9Sstevel@tonic-gate */ 437*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_IGN); 438*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_IGN); 439*7c478bd9Sstevel@tonic-gate (void) nice(0); 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate /* 442*7c478bd9Sstevel@tonic-gate * Set flag to disable the pid check if you find that you are 443*7c478bd9Sstevel@tonic-gate * a subsystem login. 444*7c478bd9Sstevel@tonic-gate */ 445*7c478bd9Sstevel@tonic-gate sublogin = 0; 446*7c478bd9Sstevel@tonic-gate if (*renvp && strcmp(*renvp, SUBLOGIN) == 0) 447*7c478bd9Sstevel@tonic-gate sublogin = 1; 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate /* 450*7c478bd9Sstevel@tonic-gate * Parse Arguments 451*7c478bd9Sstevel@tonic-gate */ 452*7c478bd9Sstevel@tonic-gate if (get_options(argc, argv) == -1) { 453*7c478bd9Sstevel@tonic-gate usage(); 454*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_BAD_CMD; 455*7c478bd9Sstevel@tonic-gate login_exit(1); 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate /* 459*7c478bd9Sstevel@tonic-gate * if devicename is not passed as argument, call ttyname(0) 460*7c478bd9Sstevel@tonic-gate */ 461*7c478bd9Sstevel@tonic-gate if (ttyn == NULL) { 462*7c478bd9Sstevel@tonic-gate ttyn = ttyname(0); 463*7c478bd9Sstevel@tonic-gate if (ttyn == NULL) 464*7c478bd9Sstevel@tonic-gate ttyn = "/dev/???"; 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 468*7c478bd9Sstevel@tonic-gate /* 469*7c478bd9Sstevel@tonic-gate * Call pam_start to initiate a PAM authentication operation 470*7c478bd9Sstevel@tonic-gate */ 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate if ((pam_rc = pam_start(progname, user_name, &pam_conv, &pamh)) 473*7c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 474*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + pam_rc; 475*7c478bd9Sstevel@tonic-gate login_exit(1); 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate if ((pam_rc = pam_set_item(pamh, PAM_TTY, ttyn)) != PAM_SUCCESS) { 478*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + pam_rc; 479*7c478bd9Sstevel@tonic-gate login_exit(1); 480*7c478bd9Sstevel@tonic-gate } 481*7c478bd9Sstevel@tonic-gate if ((pam_rc = pam_set_item(pamh, PAM_RHOST, remote_host)) != 482*7c478bd9Sstevel@tonic-gate PAM_SUCCESS) { 483*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + pam_rc; 484*7c478bd9Sstevel@tonic-gate login_exit(1); 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate /* 488*7c478bd9Sstevel@tonic-gate * We currently only support special handling of the KRB5 PAM repository 489*7c478bd9Sstevel@tonic-gate */ 490*7c478bd9Sstevel@tonic-gate if ((Rflag && strlen(repository)) && 491*7c478bd9Sstevel@tonic-gate strcmp(repository, KRB5_REPOSITORY_NAME) == 0 && 492*7c478bd9Sstevel@tonic-gate (uflag && strlen(identity))) { 493*7c478bd9Sstevel@tonic-gate krb5_repository_data_t krb5_data; 494*7c478bd9Sstevel@tonic-gate pam_repository_t pam_rep_data; 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate krb5_data.principal = identity; 497*7c478bd9Sstevel@tonic-gate krb5_data.flags = SUNW_PAM_KRB5_ALREADY_AUTHENTICATED; 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate pam_rep_data.type = repository; 500*7c478bd9Sstevel@tonic-gate pam_rep_data.scope = (void *)&krb5_data; 501*7c478bd9Sstevel@tonic-gate pam_rep_data.scope_len = sizeof (krb5_data); 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_REPOSITORY, 504*7c478bd9Sstevel@tonic-gate (void *)&pam_rep_data); 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate /* 509*7c478bd9Sstevel@tonic-gate * Open the log file which contains a record of successful and failed 510*7c478bd9Sstevel@tonic-gate * login attempts 511*7c478bd9Sstevel@tonic-gate */ 512*7c478bd9Sstevel@tonic-gate turn_on_logging(); 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate /* 515*7c478bd9Sstevel@tonic-gate * say "hi" to syslogd .. 516*7c478bd9Sstevel@tonic-gate */ 517*7c478bd9Sstevel@tonic-gate openlog("login", 0, LOG_AUTH); 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate /* 520*7c478bd9Sstevel@tonic-gate * Do special processing for -r (rlogin) flag 521*7c478bd9Sstevel@tonic-gate */ 522*7c478bd9Sstevel@tonic-gate if (rflag) 523*7c478bd9Sstevel@tonic-gate process_rlogin(); 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 526*7c478bd9Sstevel@tonic-gate /* 527*7c478bd9Sstevel@tonic-gate * validate user 528*7c478bd9Sstevel@tonic-gate */ 529*7c478bd9Sstevel@tonic-gate /* we are already authenticated. fill in what we must, then continue */ 530*7c478bd9Sstevel@tonic-gate if (fflag) { 531*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 532*7c478bd9Sstevel@tonic-gate if ((pwd = getpwnam(user_name)) == NULL) { 533*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_USERNAME; 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate log_bad_attempts(); 536*7c478bd9Sstevel@tonic-gate (void) printf("Login failed: unknown user '%s'.\n", 537*7c478bd9Sstevel@tonic-gate user_name); 538*7c478bd9Sstevel@tonic-gate login_exit(1); 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 541*7c478bd9Sstevel@tonic-gate } else { 542*7c478bd9Sstevel@tonic-gate /* 543*7c478bd9Sstevel@tonic-gate * Perform the primary login authentication activity. 544*7c478bd9Sstevel@tonic-gate */ 545*7c478bd9Sstevel@tonic-gate login_authenticate(); 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate /* change root login, then we exec another login and try again */ 550*7c478bd9Sstevel@tonic-gate if (process_chroot_logins() != OK) 551*7c478bd9Sstevel@tonic-gate login_exit(1); 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate /* 554*7c478bd9Sstevel@tonic-gate * If root login and not on system console then call exit(2) 555*7c478bd9Sstevel@tonic-gate */ 556*7c478bd9Sstevel@tonic-gate check_for_console(); 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate /* 559*7c478bd9Sstevel@tonic-gate * Check to see if a shutdown is in progress, if it is and 560*7c478bd9Sstevel@tonic-gate * we are not root then throw the user off the system 561*7c478bd9Sstevel@tonic-gate */ 562*7c478bd9Sstevel@tonic-gate if (logins_disabled(user_name) == TRUE) { 563*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_LOGIN_DISABLED; 564*7c478bd9Sstevel@tonic-gate login_exit(1); 565*7c478bd9Sstevel@tonic-gate } 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate if (pwd->pw_uid == 0) { 568*7c478bd9Sstevel@tonic-gate if (Def_supath != NULL) 569*7c478bd9Sstevel@tonic-gate Def_path = Def_supath; 570*7c478bd9Sstevel@tonic-gate else 571*7c478bd9Sstevel@tonic-gate Def_path = DEF_SUPATH; 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate /* 575*7c478bd9Sstevel@tonic-gate * Check account expiration and passwd aging 576*7c478bd9Sstevel@tonic-gate */ 577*7c478bd9Sstevel@tonic-gate validate_account(); 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate /* 580*7c478bd9Sstevel@tonic-gate * We only get here if we've been authenticated. 581*7c478bd9Sstevel@tonic-gate */ 582*7c478bd9Sstevel@tonic-gate /* 583*7c478bd9Sstevel@tonic-gate * NOTE: telnetd and rlogind rely upon this updating of utmpx 584*7c478bd9Sstevel@tonic-gate * to indicate that the authentication completed successfully, 585*7c478bd9Sstevel@tonic-gate * pam_open_session was called and therefore they are required to 586*7c478bd9Sstevel@tonic-gate * call pam_close_session. 587*7c478bd9Sstevel@tonic-gate */ 588*7c478bd9Sstevel@tonic-gate update_utmpx_entry(sublogin); 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate /* 591*7c478bd9Sstevel@tonic-gate * Now we set up the environment for the new user, which includes 592*7c478bd9Sstevel@tonic-gate * the users ulimit, nice value, ownership of this tty, uid, gid, 593*7c478bd9Sstevel@tonic-gate * and environment variables. 594*7c478bd9Sstevel@tonic-gate */ 595*7c478bd9Sstevel@tonic-gate if (Def_ulimit > 0L && ulimit(SET_FSIZ, Def_ulimit) < 0L) 596*7c478bd9Sstevel@tonic-gate (void) printf("Could not set ULIMIT to %ld\n", Def_ulimit); 597*7c478bd9Sstevel@tonic-gate 598*7c478bd9Sstevel@tonic-gate /* di_devperm_login() sends detailed errors to syslog */ 599*7c478bd9Sstevel@tonic-gate if (di_devperm_login((const char *)ttyn, pwd->pw_uid, pwd->pw_gid, 600*7c478bd9Sstevel@tonic-gate NULL) == -1) { 601*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "error processing /etc/logindevperm," 602*7c478bd9Sstevel@tonic-gate " see syslog for more details\n"); 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate adjust_nice(); /* passwd file can specify nice value */ 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 608*7c478bd9Sstevel@tonic-gate setup_credentials(); /* Set uid/gid - exits on failure */ 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate /* 611*7c478bd9Sstevel@tonic-gate * Set up the basic environment for the exec. This includes 612*7c478bd9Sstevel@tonic-gate * HOME, PATH, LOGNAME, SHELL, TERM, TZ, HZ, and MAIL. 613*7c478bd9Sstevel@tonic-gate */ 614*7c478bd9Sstevel@tonic-gate chdir_to_dir_user(); 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate establish_user_environment(renvp); 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate (void) pam_end(pamh, PAM_SUCCESS); /* Done using PAM */ 619*7c478bd9Sstevel@tonic-gate pamh = NULL; 620*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate if (pwd->pw_uid == 0) { 623*7c478bd9Sstevel@tonic-gate if (dosyslog) { 624*7c478bd9Sstevel@tonic-gate if (remote_host[0]) { 625*7c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s", 626*7c478bd9Sstevel@tonic-gate ttyn, HMAX, remote_host); 627*7c478bd9Sstevel@tonic-gate } else 628*7c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE, "ROOT LOGIN %s", ttyn); 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate closelog(); 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_DFL); 634*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_DFL); 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate /* 637*7c478bd9Sstevel@tonic-gate * Display some useful information to the new user like the banner 638*7c478bd9Sstevel@tonic-gate * and last login time if not a quiet login. 639*7c478bd9Sstevel@tonic-gate */ 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate if (access(HUSHLOGIN, F_OK) != 0) { 642*7c478bd9Sstevel@tonic-gate print_banner(); 643*7c478bd9Sstevel@tonic-gate display_last_login_time(); 644*7c478bd9Sstevel@tonic-gate } 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate /* 647*7c478bd9Sstevel@tonic-gate * Set SIGXCPU and SIGXFSZ to default disposition. 648*7c478bd9Sstevel@tonic-gate * Shells inherit signal disposition from parent. 649*7c478bd9Sstevel@tonic-gate * And the shells should have default dispositions 650*7c478bd9Sstevel@tonic-gate * for the two below signals. 651*7c478bd9Sstevel@tonic-gate */ 652*7c478bd9Sstevel@tonic-gate (void) signal(SIGXCPU, SIG_DFL); 653*7c478bd9Sstevel@tonic-gate (void) signal(SIGXFSZ, SIG_DFL); 654*7c478bd9Sstevel@tonic-gate 655*7c478bd9Sstevel@tonic-gate /* 656*7c478bd9Sstevel@tonic-gate * Now fire off the shell of choice 657*7c478bd9Sstevel@tonic-gate */ 658*7c478bd9Sstevel@tonic-gate exec_the_shell(); 659*7c478bd9Sstevel@tonic-gate 660*7c478bd9Sstevel@tonic-gate /* 661*7c478bd9Sstevel@tonic-gate * All done 662*7c478bd9Sstevel@tonic-gate */ 663*7c478bd9Sstevel@tonic-gate login_exit(1); 664*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 665*7c478bd9Sstevel@tonic-gate } 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate /* 669*7c478bd9Sstevel@tonic-gate * *** Utility functions *** 670*7c478bd9Sstevel@tonic-gate */ 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate 673*7c478bd9Sstevel@tonic-gate 674*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 675*7c478bd9Sstevel@tonic-gate /* 676*7c478bd9Sstevel@tonic-gate * donothing & catch - Signal catching functions 677*7c478bd9Sstevel@tonic-gate */ 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 680*7c478bd9Sstevel@tonic-gate static void 681*7c478bd9Sstevel@tonic-gate donothing(int sig) 682*7c478bd9Sstevel@tonic-gate { 683*7c478bd9Sstevel@tonic-gate if (pamh) 684*7c478bd9Sstevel@tonic-gate (void) pam_end(pamh, PAM_ABORT); 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate #ifdef notdef 689*7c478bd9Sstevel@tonic-gate static int intrupt; 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 692*7c478bd9Sstevel@tonic-gate static void 693*7c478bd9Sstevel@tonic-gate catch(int sig) 694*7c478bd9Sstevel@tonic-gate { 695*7c478bd9Sstevel@tonic-gate ++intrupt; 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate #endif 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate /* 700*7c478bd9Sstevel@tonic-gate * *** Bad login logging support *** 701*7c478bd9Sstevel@tonic-gate */ 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate /* 704*7c478bd9Sstevel@tonic-gate * badlogin() - log to the log file 'trys' 705*7c478bd9Sstevel@tonic-gate * unsuccessful attempts 706*7c478bd9Sstevel@tonic-gate */ 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate static void 709*7c478bd9Sstevel@tonic-gate badlogin(void) 710*7c478bd9Sstevel@tonic-gate { 711*7c478bd9Sstevel@tonic-gate int retval, count1, fildes; 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate /* 714*7c478bd9Sstevel@tonic-gate * Tries to open the log file. If succeed, lock it and write 715*7c478bd9Sstevel@tonic-gate * in the failed attempts 716*7c478bd9Sstevel@tonic-gate */ 717*7c478bd9Sstevel@tonic-gate if ((fildes = open(LOGINLOG, O_APPEND|O_WRONLY)) != -1) { 718*7c478bd9Sstevel@tonic-gate 719*7c478bd9Sstevel@tonic-gate (void) sigset(SIGALRM, donothing); 720*7c478bd9Sstevel@tonic-gate (void) alarm(L_WAITTIME); 721*7c478bd9Sstevel@tonic-gate retval = lockf(fildes, F_LOCK, 0L); 722*7c478bd9Sstevel@tonic-gate (void) alarm(0); 723*7c478bd9Sstevel@tonic-gate (void) sigset(SIGALRM, SIG_DFL); 724*7c478bd9Sstevel@tonic-gate if (retval == 0) { 725*7c478bd9Sstevel@tonic-gate for (count1 = 0; count1 < trys; count1++) 726*7c478bd9Sstevel@tonic-gate (void) write(fildes, log_entry[count1], 727*7c478bd9Sstevel@tonic-gate (unsigned)strlen(log_entry[count1])); 728*7c478bd9Sstevel@tonic-gate (void) lockf(fildes, F_ULOCK, 0L); 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate (void) close(fildes); 731*7c478bd9Sstevel@tonic-gate } 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate /* 736*7c478bd9Sstevel@tonic-gate * log_bad_attempts - log each bad login attempt - called from 737*7c478bd9Sstevel@tonic-gate * login_authenticate. Exits when the maximum attempt 738*7c478bd9Sstevel@tonic-gate * count is exceeded. 739*7c478bd9Sstevel@tonic-gate */ 740*7c478bd9Sstevel@tonic-gate 741*7c478bd9Sstevel@tonic-gate static void 742*7c478bd9Sstevel@tonic-gate log_bad_attempts(void) 743*7c478bd9Sstevel@tonic-gate { 744*7c478bd9Sstevel@tonic-gate time_t timenow; 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate if (trys >= LOGTRYS) 747*7c478bd9Sstevel@tonic-gate return; 748*7c478bd9Sstevel@tonic-gate if (writelog) { 749*7c478bd9Sstevel@tonic-gate (void) time(&timenow); 750*7c478bd9Sstevel@tonic-gate (void) strncat(log_entry[trys], user_name, LNAME_SIZE); 751*7c478bd9Sstevel@tonic-gate (void) strncat(log_entry[trys], ":", (size_t)1); 752*7c478bd9Sstevel@tonic-gate (void) strncat(log_entry[trys], ttyn, TTYN_SIZE); 753*7c478bd9Sstevel@tonic-gate (void) strncat(log_entry[trys], ":", (size_t)1); 754*7c478bd9Sstevel@tonic-gate (void) strncat(log_entry[trys], ctime(&timenow), 755*7c478bd9Sstevel@tonic-gate TIME_SIZE); 756*7c478bd9Sstevel@tonic-gate trys++; 757*7c478bd9Sstevel@tonic-gate } 758*7c478bd9Sstevel@tonic-gate if (count > flogin) { 759*7c478bd9Sstevel@tonic-gate if ((pwd = getpwnam(user_name)) != NULL) { 760*7c478bd9Sstevel@tonic-gate if (remote_host[0]) { 761*7c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE, 762*7c478bd9Sstevel@tonic-gate "Login failure on %s from %.*s, " 763*7c478bd9Sstevel@tonic-gate "%.*s", ttyn, HMAX, remote_host, 764*7c478bd9Sstevel@tonic-gate NMAX, user_name); 765*7c478bd9Sstevel@tonic-gate } else { 766*7c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE, 767*7c478bd9Sstevel@tonic-gate "Login failure on %s, %.*s", 768*7c478bd9Sstevel@tonic-gate ttyn, NMAX, user_name); 769*7c478bd9Sstevel@tonic-gate } 770*7c478bd9Sstevel@tonic-gate } else { 771*7c478bd9Sstevel@tonic-gate if (remote_host[0]) { 772*7c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE, 773*7c478bd9Sstevel@tonic-gate "Login failure on %s from %.*s", 774*7c478bd9Sstevel@tonic-gate ttyn, HMAX, remote_host); 775*7c478bd9Sstevel@tonic-gate } else { 776*7c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE, 777*7c478bd9Sstevel@tonic-gate "Login failure on %s", ttyn); 778*7c478bd9Sstevel@tonic-gate } 779*7c478bd9Sstevel@tonic-gate } 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate /* 785*7c478bd9Sstevel@tonic-gate * turn_on_logging - if the logfile exist, turn on attempt logging and 786*7c478bd9Sstevel@tonic-gate * initialize the string storage area 787*7c478bd9Sstevel@tonic-gate */ 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate static void 790*7c478bd9Sstevel@tonic-gate turn_on_logging(void) 791*7c478bd9Sstevel@tonic-gate { 792*7c478bd9Sstevel@tonic-gate struct stat dbuf; 793*7c478bd9Sstevel@tonic-gate int i; 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate if (stat(LOGINLOG, &dbuf) == 0) { 796*7c478bd9Sstevel@tonic-gate writelog = 1; 797*7c478bd9Sstevel@tonic-gate for (i = 0; i < LOGTRYS; i++) { 798*7c478bd9Sstevel@tonic-gate if (!(log_entry[i] = malloc((size_t)ENT_SIZE))) { 799*7c478bd9Sstevel@tonic-gate writelog = 0; 800*7c478bd9Sstevel@tonic-gate break; 801*7c478bd9Sstevel@tonic-gate } 802*7c478bd9Sstevel@tonic-gate *log_entry[i] = '\0'; 803*7c478bd9Sstevel@tonic-gate } 804*7c478bd9Sstevel@tonic-gate } 805*7c478bd9Sstevel@tonic-gate } 806*7c478bd9Sstevel@tonic-gate 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 809*7c478bd9Sstevel@tonic-gate /* 810*7c478bd9Sstevel@tonic-gate * login_conv(): 811*7c478bd9Sstevel@tonic-gate * This is the conv (conversation) function called from 812*7c478bd9Sstevel@tonic-gate * a PAM authentication module to print error messages 813*7c478bd9Sstevel@tonic-gate * or garner information from the user. 814*7c478bd9Sstevel@tonic-gate */ 815*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 816*7c478bd9Sstevel@tonic-gate static int 817*7c478bd9Sstevel@tonic-gate login_conv(int num_msg, struct pam_message **msg, 818*7c478bd9Sstevel@tonic-gate struct pam_response **response, void *appdata_ptr) 819*7c478bd9Sstevel@tonic-gate { 820*7c478bd9Sstevel@tonic-gate struct pam_message *m; 821*7c478bd9Sstevel@tonic-gate struct pam_response *r; 822*7c478bd9Sstevel@tonic-gate char *temp; 823*7c478bd9Sstevel@tonic-gate int k, i; 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate if (num_msg <= 0) 826*7c478bd9Sstevel@tonic-gate return (PAM_CONV_ERR); 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate *response = calloc(num_msg, sizeof (struct pam_response)); 829*7c478bd9Sstevel@tonic-gate if (*response == NULL) 830*7c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate k = num_msg; 833*7c478bd9Sstevel@tonic-gate m = *msg; 834*7c478bd9Sstevel@tonic-gate r = *response; 835*7c478bd9Sstevel@tonic-gate while (k--) { 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate switch (m->msg_style) { 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_OFF: 840*7c478bd9Sstevel@tonic-gate temp = getpassphrase(m->msg); 841*7c478bd9Sstevel@tonic-gate if (temp != NULL) { 842*7c478bd9Sstevel@tonic-gate r->resp = strdup(temp); 843*7c478bd9Sstevel@tonic-gate if (r->resp == NULL) { 844*7c478bd9Sstevel@tonic-gate /* free responses */ 845*7c478bd9Sstevel@tonic-gate r = *response; 846*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) { 847*7c478bd9Sstevel@tonic-gate if (r->resp) 848*7c478bd9Sstevel@tonic-gate free(r->resp); 849*7c478bd9Sstevel@tonic-gate } 850*7c478bd9Sstevel@tonic-gate free(*response); 851*7c478bd9Sstevel@tonic-gate *response = NULL; 852*7c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 853*7c478bd9Sstevel@tonic-gate } 854*7c478bd9Sstevel@tonic-gate } 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate m++; 857*7c478bd9Sstevel@tonic-gate r++; 858*7c478bd9Sstevel@tonic-gate break; 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate case PAM_PROMPT_ECHO_ON: 861*7c478bd9Sstevel@tonic-gate if (m->msg != NULL) 862*7c478bd9Sstevel@tonic-gate (void) fputs(m->msg, stdout); 863*7c478bd9Sstevel@tonic-gate r->resp = calloc(1, PAM_MAX_RESP_SIZE); 864*7c478bd9Sstevel@tonic-gate if (r->resp == NULL) { 865*7c478bd9Sstevel@tonic-gate /* free responses */ 866*7c478bd9Sstevel@tonic-gate r = *response; 867*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_msg; i++, r++) { 868*7c478bd9Sstevel@tonic-gate if (r->resp) 869*7c478bd9Sstevel@tonic-gate free(r->resp); 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate free(*response); 872*7c478bd9Sstevel@tonic-gate *response = NULL; 873*7c478bd9Sstevel@tonic-gate return (PAM_BUF_ERR); 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate /* 876*7c478bd9Sstevel@tonic-gate * The response might include environment variables 877*7c478bd9Sstevel@tonic-gate * information. We should store that information in 878*7c478bd9Sstevel@tonic-gate * envp if there is any; otherwise, envp is set to 879*7c478bd9Sstevel@tonic-gate * NULL. 880*7c478bd9Sstevel@tonic-gate */ 881*7c478bd9Sstevel@tonic-gate bzero((void *)inputline, MAXLINE); 882*7c478bd9Sstevel@tonic-gate 883*7c478bd9Sstevel@tonic-gate envp = getargs(inputline); 884*7c478bd9Sstevel@tonic-gate 885*7c478bd9Sstevel@tonic-gate /* If we read in any input, process it. */ 886*7c478bd9Sstevel@tonic-gate if (inputline[0] != '\0') { 887*7c478bd9Sstevel@tonic-gate int len; 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate if (envp != (char **)NULL) 890*7c478bd9Sstevel@tonic-gate /* 891*7c478bd9Sstevel@tonic-gate * If getargs() did not return NULL, 892*7c478bd9Sstevel@tonic-gate * *envp is the first string in 893*7c478bd9Sstevel@tonic-gate * inputline. envp++ makes envp point 894*7c478bd9Sstevel@tonic-gate * to environment variables information 895*7c478bd9Sstevel@tonic-gate * or be NULL. 896*7c478bd9Sstevel@tonic-gate */ 897*7c478bd9Sstevel@tonic-gate envp++; 898*7c478bd9Sstevel@tonic-gate 899*7c478bd9Sstevel@tonic-gate (void) strncpy(r->resp, inputline, 900*7c478bd9Sstevel@tonic-gate PAM_MAX_RESP_SIZE-1); 901*7c478bd9Sstevel@tonic-gate r->resp[PAM_MAX_RESP_SIZE-1] = NULL; 902*7c478bd9Sstevel@tonic-gate len = strlen(r->resp); 903*7c478bd9Sstevel@tonic-gate if (r->resp[len-1] == '\n') 904*7c478bd9Sstevel@tonic-gate r->resp[len-1] = '\0'; 905*7c478bd9Sstevel@tonic-gate } else { 906*7c478bd9Sstevel@tonic-gate login_exit(1); 907*7c478bd9Sstevel@tonic-gate } 908*7c478bd9Sstevel@tonic-gate m++; 909*7c478bd9Sstevel@tonic-gate r++; 910*7c478bd9Sstevel@tonic-gate break; 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate case PAM_ERROR_MSG: 913*7c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 914*7c478bd9Sstevel@tonic-gate (void) fputs(m->msg, stderr); 915*7c478bd9Sstevel@tonic-gate (void) fputs("\n", stderr); 916*7c478bd9Sstevel@tonic-gate } 917*7c478bd9Sstevel@tonic-gate m++; 918*7c478bd9Sstevel@tonic-gate r++; 919*7c478bd9Sstevel@tonic-gate break; 920*7c478bd9Sstevel@tonic-gate case PAM_TEXT_INFO: 921*7c478bd9Sstevel@tonic-gate if (m->msg != NULL) { 922*7c478bd9Sstevel@tonic-gate (void) fputs(m->msg, stdout); 923*7c478bd9Sstevel@tonic-gate (void) fputs("\n", stdout); 924*7c478bd9Sstevel@tonic-gate } 925*7c478bd9Sstevel@tonic-gate m++; 926*7c478bd9Sstevel@tonic-gate r++; 927*7c478bd9Sstevel@tonic-gate break; 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate default: 930*7c478bd9Sstevel@tonic-gate break; 931*7c478bd9Sstevel@tonic-gate } 932*7c478bd9Sstevel@tonic-gate } 933*7c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 934*7c478bd9Sstevel@tonic-gate } 935*7c478bd9Sstevel@tonic-gate 936*7c478bd9Sstevel@tonic-gate /* 937*7c478bd9Sstevel@tonic-gate * verify_passwd - Authenticates the user. 938*7c478bd9Sstevel@tonic-gate * Returns: PAM_SUCCESS if authentication successful, 939*7c478bd9Sstevel@tonic-gate * PAM error code if authentication fails. 940*7c478bd9Sstevel@tonic-gate */ 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate static int 943*7c478bd9Sstevel@tonic-gate verify_passwd() 944*7c478bd9Sstevel@tonic-gate { 945*7c478bd9Sstevel@tonic-gate int error; 946*7c478bd9Sstevel@tonic-gate char *user; 947*7c478bd9Sstevel@tonic-gate int flag = 0; 948*7c478bd9Sstevel@tonic-gate 949*7c478bd9Sstevel@tonic-gate /* 950*7c478bd9Sstevel@tonic-gate * PAM authenticates the user for us. 951*7c478bd9Sstevel@tonic-gate */ 952*7c478bd9Sstevel@tonic-gate if ((error = pam_authenticate(pamh, flag)) != PAM_SUCCESS) { 953*7c478bd9Sstevel@tonic-gate return (error); 954*7c478bd9Sstevel@tonic-gate } 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate /* get the user_name from the pam handle */ 957*7c478bd9Sstevel@tonic-gate (void) pam_get_item(pamh, PAM_USER, (void**)&user); 958*7c478bd9Sstevel@tonic-gate 959*7c478bd9Sstevel@tonic-gate if (user == NULL || *user == '\0') 960*7c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate SCPYL(user_name, user); 963*7c478bd9Sstevel@tonic-gate check_for_dueling_unix(user_name); 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate if ((pwd = getpwnam(user_name)) == NULL) { 966*7c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 967*7c478bd9Sstevel@tonic-gate } 968*7c478bd9Sstevel@tonic-gate 969*7c478bd9Sstevel@tonic-gate return (error); 970*7c478bd9Sstevel@tonic-gate } 971*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate /* 974*7c478bd9Sstevel@tonic-gate * quotec - Called by getargs 975*7c478bd9Sstevel@tonic-gate */ 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate static int 978*7c478bd9Sstevel@tonic-gate quotec(void) 979*7c478bd9Sstevel@tonic-gate { 980*7c478bd9Sstevel@tonic-gate int c, i, num; 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate switch (c = getc(stdin)) { 983*7c478bd9Sstevel@tonic-gate 984*7c478bd9Sstevel@tonic-gate case 'n': 985*7c478bd9Sstevel@tonic-gate c = '\n'; 986*7c478bd9Sstevel@tonic-gate break; 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate case 'r': 989*7c478bd9Sstevel@tonic-gate c = '\r'; 990*7c478bd9Sstevel@tonic-gate break; 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate case 'v': 993*7c478bd9Sstevel@tonic-gate c = '\013'; 994*7c478bd9Sstevel@tonic-gate break; 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate case 'b': 997*7c478bd9Sstevel@tonic-gate c = '\b'; 998*7c478bd9Sstevel@tonic-gate break; 999*7c478bd9Sstevel@tonic-gate 1000*7c478bd9Sstevel@tonic-gate case 't': 1001*7c478bd9Sstevel@tonic-gate c = '\t'; 1002*7c478bd9Sstevel@tonic-gate break; 1003*7c478bd9Sstevel@tonic-gate 1004*7c478bd9Sstevel@tonic-gate case 'f': 1005*7c478bd9Sstevel@tonic-gate c = '\f'; 1006*7c478bd9Sstevel@tonic-gate break; 1007*7c478bd9Sstevel@tonic-gate 1008*7c478bd9Sstevel@tonic-gate case '0': 1009*7c478bd9Sstevel@tonic-gate case '1': 1010*7c478bd9Sstevel@tonic-gate case '2': 1011*7c478bd9Sstevel@tonic-gate case '3': 1012*7c478bd9Sstevel@tonic-gate case '4': 1013*7c478bd9Sstevel@tonic-gate case '5': 1014*7c478bd9Sstevel@tonic-gate case '6': 1015*7c478bd9Sstevel@tonic-gate case '7': 1016*7c478bd9Sstevel@tonic-gate for (num = 0, i = 0; i < 3; i++) { 1017*7c478bd9Sstevel@tonic-gate num = num * 8 + (c - '0'); 1018*7c478bd9Sstevel@tonic-gate if ((c = getc(stdin)) < '0' || c > '7') 1019*7c478bd9Sstevel@tonic-gate break; 1020*7c478bd9Sstevel@tonic-gate } 1021*7c478bd9Sstevel@tonic-gate (void) ungetc(c, stdin); 1022*7c478bd9Sstevel@tonic-gate c = num & 0377; 1023*7c478bd9Sstevel@tonic-gate break; 1024*7c478bd9Sstevel@tonic-gate 1025*7c478bd9Sstevel@tonic-gate default: 1026*7c478bd9Sstevel@tonic-gate break; 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate return (c); 1029*7c478bd9Sstevel@tonic-gate } 1030*7c478bd9Sstevel@tonic-gate 1031*7c478bd9Sstevel@tonic-gate /* 1032*7c478bd9Sstevel@tonic-gate * getargs - returns an input line. Exits if EOF encountered. 1033*7c478bd9Sstevel@tonic-gate */ 1034*7c478bd9Sstevel@tonic-gate #define WHITESPACE 0 1035*7c478bd9Sstevel@tonic-gate #define ARGUMENT 1 1036*7c478bd9Sstevel@tonic-gate 1037*7c478bd9Sstevel@tonic-gate static char ** 1038*7c478bd9Sstevel@tonic-gate getargs(char *input_line) 1039*7c478bd9Sstevel@tonic-gate { 1040*7c478bd9Sstevel@tonic-gate static char envbuf[MAXLINE]; 1041*7c478bd9Sstevel@tonic-gate static char *args[MAXARGS]; 1042*7c478bd9Sstevel@tonic-gate char *ptr, **answer; 1043*7c478bd9Sstevel@tonic-gate int c; 1044*7c478bd9Sstevel@tonic-gate int state; 1045*7c478bd9Sstevel@tonic-gate char *p = input_line; 1046*7c478bd9Sstevel@tonic-gate 1047*7c478bd9Sstevel@tonic-gate ptr = envbuf; 1048*7c478bd9Sstevel@tonic-gate answer = &args[0]; 1049*7c478bd9Sstevel@tonic-gate state = WHITESPACE; 1050*7c478bd9Sstevel@tonic-gate 1051*7c478bd9Sstevel@tonic-gate while ((c = getc(stdin)) != EOF && answer < &args[MAXARGS-1]) { 1052*7c478bd9Sstevel@tonic-gate 1053*7c478bd9Sstevel@tonic-gate *(input_line++) = c; 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate switch (c) { 1056*7c478bd9Sstevel@tonic-gate 1057*7c478bd9Sstevel@tonic-gate case '\n': 1058*7c478bd9Sstevel@tonic-gate if (ptr == &envbuf[0]) 1059*7c478bd9Sstevel@tonic-gate return ((char **)NULL); 1060*7c478bd9Sstevel@tonic-gate *input_line = *ptr = '\0'; 1061*7c478bd9Sstevel@tonic-gate *answer = NULL; 1062*7c478bd9Sstevel@tonic-gate return (&args[0]); 1063*7c478bd9Sstevel@tonic-gate 1064*7c478bd9Sstevel@tonic-gate case ' ': 1065*7c478bd9Sstevel@tonic-gate case '\t': 1066*7c478bd9Sstevel@tonic-gate if (state == ARGUMENT) { 1067*7c478bd9Sstevel@tonic-gate *ptr++ = '\0'; 1068*7c478bd9Sstevel@tonic-gate state = WHITESPACE; 1069*7c478bd9Sstevel@tonic-gate } 1070*7c478bd9Sstevel@tonic-gate break; 1071*7c478bd9Sstevel@tonic-gate 1072*7c478bd9Sstevel@tonic-gate case '\\': 1073*7c478bd9Sstevel@tonic-gate c = quotec(); 1074*7c478bd9Sstevel@tonic-gate 1075*7c478bd9Sstevel@tonic-gate default: 1076*7c478bd9Sstevel@tonic-gate if (state == WHITESPACE) { 1077*7c478bd9Sstevel@tonic-gate *answer++ = ptr; 1078*7c478bd9Sstevel@tonic-gate state = ARGUMENT; 1079*7c478bd9Sstevel@tonic-gate } 1080*7c478bd9Sstevel@tonic-gate *ptr++ = c; 1081*7c478bd9Sstevel@tonic-gate } 1082*7c478bd9Sstevel@tonic-gate 1083*7c478bd9Sstevel@tonic-gate /* Attempt at overflow, exit */ 1084*7c478bd9Sstevel@tonic-gate if (input_line - p >= MAXLINE - 1 || 1085*7c478bd9Sstevel@tonic-gate ptr >= &envbuf[sizeof (envbuf) - 1]) { 1086*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_INPUT_OVERFLOW; 1087*7c478bd9Sstevel@tonic-gate login_exit(1); 1088*7c478bd9Sstevel@tonic-gate } 1089*7c478bd9Sstevel@tonic-gate } 1090*7c478bd9Sstevel@tonic-gate 1091*7c478bd9Sstevel@tonic-gate /* 1092*7c478bd9Sstevel@tonic-gate * If we left loop because an EOF was received or we've overflown 1093*7c478bd9Sstevel@tonic-gate * args[], exit immediately. 1094*7c478bd9Sstevel@tonic-gate */ 1095*7c478bd9Sstevel@tonic-gate login_exit(0); 1096*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1097*7c478bd9Sstevel@tonic-gate } 1098*7c478bd9Sstevel@tonic-gate 1099*7c478bd9Sstevel@tonic-gate /* 1100*7c478bd9Sstevel@tonic-gate * get_user_name - Gets the user name either passed in, or from the 1101*7c478bd9Sstevel@tonic-gate * login: prompt. 1102*7c478bd9Sstevel@tonic-gate */ 1103*7c478bd9Sstevel@tonic-gate 1104*7c478bd9Sstevel@tonic-gate static void 1105*7c478bd9Sstevel@tonic-gate get_user_name() 1106*7c478bd9Sstevel@tonic-gate { 1107*7c478bd9Sstevel@tonic-gate FILE *fp; 1108*7c478bd9Sstevel@tonic-gate 1109*7c478bd9Sstevel@tonic-gate if ((fp = fopen(ISSUEFILE, "r")) != NULL) { 1110*7c478bd9Sstevel@tonic-gate char *ptr, buffer[BUFSIZ]; 1111*7c478bd9Sstevel@tonic-gate while ((ptr = fgets(buffer, sizeof (buffer), 1112*7c478bd9Sstevel@tonic-gate fp)) != NULL) { 1113*7c478bd9Sstevel@tonic-gate (void) fputs(ptr, stdout); 1114*7c478bd9Sstevel@tonic-gate } 1115*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 1116*7c478bd9Sstevel@tonic-gate } 1117*7c478bd9Sstevel@tonic-gate 1118*7c478bd9Sstevel@tonic-gate /* 1119*7c478bd9Sstevel@tonic-gate * if TTYPROMPT is not set, use our own prompt 1120*7c478bd9Sstevel@tonic-gate * otherwise, use ttyprompt. We just set PAM_USER_PROMPT 1121*7c478bd9Sstevel@tonic-gate * and let the module do the prompting. 1122*7c478bd9Sstevel@tonic-gate */ 1123*7c478bd9Sstevel@tonic-gate 1124*7c478bd9Sstevel@tonic-gate if ((ttyprompt == NULL) || (*ttyprompt == '\0')) 1125*7c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_USER_PROMPT, (void *)loginmsg); 1126*7c478bd9Sstevel@tonic-gate else 1127*7c478bd9Sstevel@tonic-gate (void) pam_set_item(pamh, PAM_USER_PROMPT, (void *)ttyprompt); 1128*7c478bd9Sstevel@tonic-gate 1129*7c478bd9Sstevel@tonic-gate envp = &zero; /* XXX: is this right? */ 1130*7c478bd9Sstevel@tonic-gate } 1131*7c478bd9Sstevel@tonic-gate 1132*7c478bd9Sstevel@tonic-gate 1133*7c478bd9Sstevel@tonic-gate /* 1134*7c478bd9Sstevel@tonic-gate * Check_for_dueling_unix - Check to see if the another login is talking 1135*7c478bd9Sstevel@tonic-gate * to the line we've got open as a login port 1136*7c478bd9Sstevel@tonic-gate * Exits if we're talking to another unix system 1137*7c478bd9Sstevel@tonic-gate */ 1138*7c478bd9Sstevel@tonic-gate 1139*7c478bd9Sstevel@tonic-gate static void 1140*7c478bd9Sstevel@tonic-gate check_for_dueling_unix(char *inputline) 1141*7c478bd9Sstevel@tonic-gate { 1142*7c478bd9Sstevel@tonic-gate if (EQN(loginmsg, inputline) || EQN(passwdmsg, inputline) || 1143*7c478bd9Sstevel@tonic-gate EQN(incorrectmsg, inputline)) { 1144*7c478bd9Sstevel@tonic-gate (void) printf("Looking at a login line.\n"); 1145*7c478bd9Sstevel@tonic-gate login_exit(8); 1146*7c478bd9Sstevel@tonic-gate } 1147*7c478bd9Sstevel@tonic-gate } 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate /* 1150*7c478bd9Sstevel@tonic-gate * logins_disabled - if the file /etc/nologin exists and the user is not 1151*7c478bd9Sstevel@tonic-gate * root then do not permit them to login 1152*7c478bd9Sstevel@tonic-gate */ 1153*7c478bd9Sstevel@tonic-gate static int 1154*7c478bd9Sstevel@tonic-gate logins_disabled(char *user_name) 1155*7c478bd9Sstevel@tonic-gate { 1156*7c478bd9Sstevel@tonic-gate FILE *nlfd; 1157*7c478bd9Sstevel@tonic-gate int c; 1158*7c478bd9Sstevel@tonic-gate if (!EQN("root", user_name) && 1159*7c478bd9Sstevel@tonic-gate ((nlfd = fopen(NOLOGIN, "r")) != (FILE *)NULL)) { 1160*7c478bd9Sstevel@tonic-gate while ((c = getc(nlfd)) != EOF) 1161*7c478bd9Sstevel@tonic-gate (void) putchar(c); 1162*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 1163*7c478bd9Sstevel@tonic-gate (void) sleep(5); 1164*7c478bd9Sstevel@tonic-gate return (TRUE); 1165*7c478bd9Sstevel@tonic-gate } 1166*7c478bd9Sstevel@tonic-gate return (FALSE); 1167*7c478bd9Sstevel@tonic-gate } 1168*7c478bd9Sstevel@tonic-gate 1169*7c478bd9Sstevel@tonic-gate /* 1170*7c478bd9Sstevel@tonic-gate * check_for_console - Checks if we're getting a root login on the 1171*7c478bd9Sstevel@tonic-gate * console, or a login from the global zone. Exits if not. 1172*7c478bd9Sstevel@tonic-gate * 1173*7c478bd9Sstevel@tonic-gate */ 1174*7c478bd9Sstevel@tonic-gate static void 1175*7c478bd9Sstevel@tonic-gate check_for_console(void) 1176*7c478bd9Sstevel@tonic-gate { 1177*7c478bd9Sstevel@tonic-gate if (pwd != NULL && pwd->pw_uid == 0 && zflag == B_FALSE) { 1178*7c478bd9Sstevel@tonic-gate if ((Console != NULL) && (strcmp(ttyn, Console) != 0)) { 1179*7c478bd9Sstevel@tonic-gate (void) printf("Not on system console\n"); 1180*7c478bd9Sstevel@tonic-gate 1181*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_CONSOLE; 1182*7c478bd9Sstevel@tonic-gate login_exit(10); 1183*7c478bd9Sstevel@tonic-gate } 1184*7c478bd9Sstevel@tonic-gate } 1185*7c478bd9Sstevel@tonic-gate } 1186*7c478bd9Sstevel@tonic-gate 1187*7c478bd9Sstevel@tonic-gate /* 1188*7c478bd9Sstevel@tonic-gate * List of environment variables or environment variable prefixes that should 1189*7c478bd9Sstevel@tonic-gate * not be propagated across logins, such as when the login -p option is used. 1190*7c478bd9Sstevel@tonic-gate */ 1191*7c478bd9Sstevel@tonic-gate static const char *const illegal[] = { 1192*7c478bd9Sstevel@tonic-gate "SHELL=", 1193*7c478bd9Sstevel@tonic-gate "HOME=", 1194*7c478bd9Sstevel@tonic-gate "LOGNAME=", 1195*7c478bd9Sstevel@tonic-gate #ifndef NO_MAIL 1196*7c478bd9Sstevel@tonic-gate "MAIL=", 1197*7c478bd9Sstevel@tonic-gate #endif 1198*7c478bd9Sstevel@tonic-gate "CDPATH=", 1199*7c478bd9Sstevel@tonic-gate "IFS=", 1200*7c478bd9Sstevel@tonic-gate "PATH=", 1201*7c478bd9Sstevel@tonic-gate "LD_", 1202*7c478bd9Sstevel@tonic-gate "SMF_", 1203*7c478bd9Sstevel@tonic-gate NULL 1204*7c478bd9Sstevel@tonic-gate }; 1205*7c478bd9Sstevel@tonic-gate 1206*7c478bd9Sstevel@tonic-gate /* 1207*7c478bd9Sstevel@tonic-gate * legalenvvar - Is it legal to insert this environmental variable? 1208*7c478bd9Sstevel@tonic-gate */ 1209*7c478bd9Sstevel@tonic-gate 1210*7c478bd9Sstevel@tonic-gate static int 1211*7c478bd9Sstevel@tonic-gate legalenvvar(char *s) 1212*7c478bd9Sstevel@tonic-gate { 1213*7c478bd9Sstevel@tonic-gate const char *const *p; 1214*7c478bd9Sstevel@tonic-gate 1215*7c478bd9Sstevel@tonic-gate for (p = &illegal[0]; *p; p++) { 1216*7c478bd9Sstevel@tonic-gate if (strncmp(s, *p, strlen(*p)) == 0) 1217*7c478bd9Sstevel@tonic-gate return (0); 1218*7c478bd9Sstevel@tonic-gate } 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate return (1); 1221*7c478bd9Sstevel@tonic-gate } 1222*7c478bd9Sstevel@tonic-gate 1223*7c478bd9Sstevel@tonic-gate 1224*7c478bd9Sstevel@tonic-gate /* 1225*7c478bd9Sstevel@tonic-gate * getstr - Get a string from standard input 1226*7c478bd9Sstevel@tonic-gate * Calls exit if read(2) fails. 1227*7c478bd9Sstevel@tonic-gate */ 1228*7c478bd9Sstevel@tonic-gate 1229*7c478bd9Sstevel@tonic-gate static void 1230*7c478bd9Sstevel@tonic-gate getstr(char *buf, int cnt, char *err) 1231*7c478bd9Sstevel@tonic-gate { 1232*7c478bd9Sstevel@tonic-gate char c; 1233*7c478bd9Sstevel@tonic-gate 1234*7c478bd9Sstevel@tonic-gate do { 1235*7c478bd9Sstevel@tonic-gate if (read(0, &c, 1) != 1) 1236*7c478bd9Sstevel@tonic-gate login_exit(1); 1237*7c478bd9Sstevel@tonic-gate *buf++ = c; 1238*7c478bd9Sstevel@tonic-gate } while (--cnt > 1 && c != 0); 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate *buf = 0; 1241*7c478bd9Sstevel@tonic-gate err = err; /* For lint */ 1242*7c478bd9Sstevel@tonic-gate } 1243*7c478bd9Sstevel@tonic-gate 1244*7c478bd9Sstevel@tonic-gate 1245*7c478bd9Sstevel@tonic-gate /* 1246*7c478bd9Sstevel@tonic-gate * defaults - read defaults 1247*7c478bd9Sstevel@tonic-gate */ 1248*7c478bd9Sstevel@tonic-gate 1249*7c478bd9Sstevel@tonic-gate static void 1250*7c478bd9Sstevel@tonic-gate defaults(void) 1251*7c478bd9Sstevel@tonic-gate { 1252*7c478bd9Sstevel@tonic-gate int flags; 1253*7c478bd9Sstevel@tonic-gate char *ptr; 1254*7c478bd9Sstevel@tonic-gate 1255*7c478bd9Sstevel@tonic-gate if (defopen(Pndefault) == 0) { 1256*7c478bd9Sstevel@tonic-gate /* 1257*7c478bd9Sstevel@tonic-gate * ignore case 1258*7c478bd9Sstevel@tonic-gate */ 1259*7c478bd9Sstevel@tonic-gate flags = defcntl(DC_GETFLAGS, 0); 1260*7c478bd9Sstevel@tonic-gate TURNOFF(flags, DC_CASE); 1261*7c478bd9Sstevel@tonic-gate (void) defcntl(DC_SETFLAGS, flags); 1262*7c478bd9Sstevel@tonic-gate 1263*7c478bd9Sstevel@tonic-gate if ((Console = defread("CONSOLE=")) != NULL) 1264*7c478bd9Sstevel@tonic-gate Console = strdup(Console); 1265*7c478bd9Sstevel@tonic-gate 1266*7c478bd9Sstevel@tonic-gate if ((Altshell = defread("ALTSHELL=")) != NULL) 1267*7c478bd9Sstevel@tonic-gate Altshell = strdup(Altshell); 1268*7c478bd9Sstevel@tonic-gate 1269*7c478bd9Sstevel@tonic-gate if ((ptr = defread("PASSREQ=")) != NULL && 1270*7c478bd9Sstevel@tonic-gate strcasecmp("YES", ptr) == 0) 1271*7c478bd9Sstevel@tonic-gate Passreqflag = 1; 1272*7c478bd9Sstevel@tonic-gate 1273*7c478bd9Sstevel@tonic-gate if ((Def_tz = defread("TIMEZONE=")) != NULL) 1274*7c478bd9Sstevel@tonic-gate Def_tz = strdup(Def_tz); 1275*7c478bd9Sstevel@tonic-gate 1276*7c478bd9Sstevel@tonic-gate if ((Def_hertz = defread("HZ=")) != NULL) 1277*7c478bd9Sstevel@tonic-gate Def_hertz = strdup(Def_hertz); 1278*7c478bd9Sstevel@tonic-gate 1279*7c478bd9Sstevel@tonic-gate if ((Def_path = defread("PATH=")) != NULL) 1280*7c478bd9Sstevel@tonic-gate Def_path = strdup(Def_path); 1281*7c478bd9Sstevel@tonic-gate 1282*7c478bd9Sstevel@tonic-gate if ((Def_supath = defread("SUPATH=")) != NULL) 1283*7c478bd9Sstevel@tonic-gate Def_supath = strdup(Def_supath); 1284*7c478bd9Sstevel@tonic-gate 1285*7c478bd9Sstevel@tonic-gate if ((ptr = defread("ULIMIT=")) != NULL) 1286*7c478bd9Sstevel@tonic-gate Def_ulimit = atol(ptr); 1287*7c478bd9Sstevel@tonic-gate 1288*7c478bd9Sstevel@tonic-gate if ((ptr = defread("TIMEOUT=")) != NULL) 1289*7c478bd9Sstevel@tonic-gate Def_timeout = (unsigned)atoi(ptr); 1290*7c478bd9Sstevel@tonic-gate 1291*7c478bd9Sstevel@tonic-gate if ((ptr = defread("UMASK=")) != NULL) 1292*7c478bd9Sstevel@tonic-gate if (sscanf(ptr, "%lo", &Umask) != 1) 1293*7c478bd9Sstevel@tonic-gate Umask = DEFUMASK; 1294*7c478bd9Sstevel@tonic-gate 1295*7c478bd9Sstevel@tonic-gate if ((ptr = defread("SLEEPTIME=")) != NULL) { 1296*7c478bd9Sstevel@tonic-gate if (is_number(ptr)) 1297*7c478bd9Sstevel@tonic-gate Sleeptime = atoi(ptr); 1298*7c478bd9Sstevel@tonic-gate } 1299*7c478bd9Sstevel@tonic-gate 1300*7c478bd9Sstevel@tonic-gate if ((ptr = defread("DISABLETIME=")) != NULL) { 1301*7c478bd9Sstevel@tonic-gate if (is_number(ptr)) 1302*7c478bd9Sstevel@tonic-gate Disabletime = atoi(ptr); 1303*7c478bd9Sstevel@tonic-gate } 1304*7c478bd9Sstevel@tonic-gate 1305*7c478bd9Sstevel@tonic-gate if ((ptr = defread("SYSLOG=")) != NULL) 1306*7c478bd9Sstevel@tonic-gate dosyslog = strcmp(ptr, "YES") == 0; 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate if ((ptr = defread("RETRIES=")) != NULL) { 1309*7c478bd9Sstevel@tonic-gate if (is_number(ptr)) 1310*7c478bd9Sstevel@tonic-gate retry = atoi(ptr); 1311*7c478bd9Sstevel@tonic-gate } 1312*7c478bd9Sstevel@tonic-gate 1313*7c478bd9Sstevel@tonic-gate if ((ptr = defread("SYSLOG_FAILED_LOGINS=")) != NULL) { 1314*7c478bd9Sstevel@tonic-gate if (is_number(ptr)) 1315*7c478bd9Sstevel@tonic-gate flogin = atoi(ptr); 1316*7c478bd9Sstevel@tonic-gate else 1317*7c478bd9Sstevel@tonic-gate flogin = retry; 1318*7c478bd9Sstevel@tonic-gate } else 1319*7c478bd9Sstevel@tonic-gate flogin = retry; 1320*7c478bd9Sstevel@tonic-gate (void) defopen((char *)NULL); 1321*7c478bd9Sstevel@tonic-gate } 1322*7c478bd9Sstevel@tonic-gate } 1323*7c478bd9Sstevel@tonic-gate 1324*7c478bd9Sstevel@tonic-gate 1325*7c478bd9Sstevel@tonic-gate /* 1326*7c478bd9Sstevel@tonic-gate * get_options(argc, argv) 1327*7c478bd9Sstevel@tonic-gate * - parse the cmd line. 1328*7c478bd9Sstevel@tonic-gate * - return 0 if successful, -1 if failed. 1329*7c478bd9Sstevel@tonic-gate * Calls login_exit() on misuse of -r, -h, and -z flags 1330*7c478bd9Sstevel@tonic-gate */ 1331*7c478bd9Sstevel@tonic-gate 1332*7c478bd9Sstevel@tonic-gate static int 1333*7c478bd9Sstevel@tonic-gate get_options(int argc, char *argv[]) 1334*7c478bd9Sstevel@tonic-gate { 1335*7c478bd9Sstevel@tonic-gate int c; 1336*7c478bd9Sstevel@tonic-gate int errflg = 0; 1337*7c478bd9Sstevel@tonic-gate char sflagname[NMAX+1]; 1338*7c478bd9Sstevel@tonic-gate const char *flags_message = "Only one of -r, -h and -z allowed\n"; 1339*7c478bd9Sstevel@tonic-gate 1340*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "u:s:R:f:h:r:pad:t:U:z:")) != -1) { 1341*7c478bd9Sstevel@tonic-gate switch (c) { 1342*7c478bd9Sstevel@tonic-gate case 'a': 1343*7c478bd9Sstevel@tonic-gate break; 1344*7c478bd9Sstevel@tonic-gate 1345*7c478bd9Sstevel@tonic-gate case 'd': 1346*7c478bd9Sstevel@tonic-gate /* 1347*7c478bd9Sstevel@tonic-gate * Must be root to pass in device name 1348*7c478bd9Sstevel@tonic-gate * otherwise we exit() as punishment for trying. 1349*7c478bd9Sstevel@tonic-gate */ 1350*7c478bd9Sstevel@tonic-gate if (getuid() != 0 || geteuid() != 0) { 1351*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_DEVICE_PERM; 1352*7c478bd9Sstevel@tonic-gate login_exit(1); /* sigh */ 1353*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1354*7c478bd9Sstevel@tonic-gate } 1355*7c478bd9Sstevel@tonic-gate ttyn = optarg; 1356*7c478bd9Sstevel@tonic-gate break; 1357*7c478bd9Sstevel@tonic-gate 1358*7c478bd9Sstevel@tonic-gate case 'h': 1359*7c478bd9Sstevel@tonic-gate if (hflag || rflag || zflag) { 1360*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, flags_message); 1361*7c478bd9Sstevel@tonic-gate login_exit(1); 1362*7c478bd9Sstevel@tonic-gate } 1363*7c478bd9Sstevel@tonic-gate hflag = B_TRUE; 1364*7c478bd9Sstevel@tonic-gate SCPYL(remote_host, optarg); 1365*7c478bd9Sstevel@tonic-gate if (argv[optind]) { 1366*7c478bd9Sstevel@tonic-gate if (argv[optind][0] != '-') { 1367*7c478bd9Sstevel@tonic-gate SCPYL(terminal, argv[optind]); 1368*7c478bd9Sstevel@tonic-gate optind++; 1369*7c478bd9Sstevel@tonic-gate } else { 1370*7c478bd9Sstevel@tonic-gate /* 1371*7c478bd9Sstevel@tonic-gate * Allow "login -h hostname -" to 1372*7c478bd9Sstevel@tonic-gate * skip setting up an username as "-". 1373*7c478bd9Sstevel@tonic-gate */ 1374*7c478bd9Sstevel@tonic-gate if (argv[optind][1] == '\0') 1375*7c478bd9Sstevel@tonic-gate optind++; 1376*7c478bd9Sstevel@tonic-gate } 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate } 1379*7c478bd9Sstevel@tonic-gate SCPYL(progname, "telnet"); 1380*7c478bd9Sstevel@tonic-gate break; 1381*7c478bd9Sstevel@tonic-gate 1382*7c478bd9Sstevel@tonic-gate case 'r': 1383*7c478bd9Sstevel@tonic-gate if (hflag || rflag || zflag) { 1384*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, flags_message); 1385*7c478bd9Sstevel@tonic-gate login_exit(1); 1386*7c478bd9Sstevel@tonic-gate } 1387*7c478bd9Sstevel@tonic-gate rflag = B_TRUE; 1388*7c478bd9Sstevel@tonic-gate SCPYL(remote_host, optarg); 1389*7c478bd9Sstevel@tonic-gate SCPYL(progname, "rlogin"); 1390*7c478bd9Sstevel@tonic-gate break; 1391*7c478bd9Sstevel@tonic-gate 1392*7c478bd9Sstevel@tonic-gate case 'p': 1393*7c478bd9Sstevel@tonic-gate pflag = B_TRUE; 1394*7c478bd9Sstevel@tonic-gate break; 1395*7c478bd9Sstevel@tonic-gate 1396*7c478bd9Sstevel@tonic-gate case 'f': 1397*7c478bd9Sstevel@tonic-gate /* 1398*7c478bd9Sstevel@tonic-gate * Must be root to bypass authentication 1399*7c478bd9Sstevel@tonic-gate * otherwise we exit() as punishment for trying. 1400*7c478bd9Sstevel@tonic-gate */ 1401*7c478bd9Sstevel@tonic-gate if (getuid() != 0 || geteuid() != 0) { 1402*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_AUTH_BYPASS; 1403*7c478bd9Sstevel@tonic-gate 1404*7c478bd9Sstevel@tonic-gate login_exit(1); /* sigh */ 1405*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1406*7c478bd9Sstevel@tonic-gate } 1407*7c478bd9Sstevel@tonic-gate /* save fflag user name for future use */ 1408*7c478bd9Sstevel@tonic-gate SCPYL(user_name, optarg); 1409*7c478bd9Sstevel@tonic-gate fflag = B_TRUE; 1410*7c478bd9Sstevel@tonic-gate break; 1411*7c478bd9Sstevel@tonic-gate case 'u': 1412*7c478bd9Sstevel@tonic-gate if (!strlen(optarg)) { 1413*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1414*7c478bd9Sstevel@tonic-gate "Empty string supplied with -u\n"); 1415*7c478bd9Sstevel@tonic-gate login_exit(1); 1416*7c478bd9Sstevel@tonic-gate } 1417*7c478bd9Sstevel@tonic-gate SCPYL(identity, optarg); 1418*7c478bd9Sstevel@tonic-gate uflag = B_TRUE; 1419*7c478bd9Sstevel@tonic-gate break; 1420*7c478bd9Sstevel@tonic-gate case 's': 1421*7c478bd9Sstevel@tonic-gate if (!strlen(optarg)) { 1422*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1423*7c478bd9Sstevel@tonic-gate "Empty string supplied with -s\n"); 1424*7c478bd9Sstevel@tonic-gate login_exit(1); 1425*7c478bd9Sstevel@tonic-gate } 1426*7c478bd9Sstevel@tonic-gate SCPYL(sflagname, optarg); 1427*7c478bd9Sstevel@tonic-gate sflag = B_TRUE; 1428*7c478bd9Sstevel@tonic-gate break; 1429*7c478bd9Sstevel@tonic-gate case 'R': 1430*7c478bd9Sstevel@tonic-gate if (!strlen(optarg)) { 1431*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1432*7c478bd9Sstevel@tonic-gate "Empty string supplied with -R\n"); 1433*7c478bd9Sstevel@tonic-gate login_exit(1); 1434*7c478bd9Sstevel@tonic-gate } 1435*7c478bd9Sstevel@tonic-gate SCPYL(repository, optarg); 1436*7c478bd9Sstevel@tonic-gate Rflag = B_TRUE; 1437*7c478bd9Sstevel@tonic-gate break; 1438*7c478bd9Sstevel@tonic-gate case 't': 1439*7c478bd9Sstevel@tonic-gate if (!strlen(optarg)) { 1440*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1441*7c478bd9Sstevel@tonic-gate "Empty string supplied with -t\n"); 1442*7c478bd9Sstevel@tonic-gate login_exit(1); 1443*7c478bd9Sstevel@tonic-gate } 1444*7c478bd9Sstevel@tonic-gate SCPYL(terminal, optarg); 1445*7c478bd9Sstevel@tonic-gate tflag = B_TRUE; 1446*7c478bd9Sstevel@tonic-gate break; 1447*7c478bd9Sstevel@tonic-gate case 'U': 1448*7c478bd9Sstevel@tonic-gate /* 1449*7c478bd9Sstevel@tonic-gate * Kerberized rlogind may fork us with 1450*7c478bd9Sstevel@tonic-gate * -U "" if the rlogin client used the "-a" 1451*7c478bd9Sstevel@tonic-gate * option to send a NULL username. This is done 1452*7c478bd9Sstevel@tonic-gate * to force login to prompt for a user/password. 1453*7c478bd9Sstevel@tonic-gate * However, if Kerberos auth was used, we dont need 1454*7c478bd9Sstevel@tonic-gate * to prompt, so we will accept the option and 1455*7c478bd9Sstevel@tonic-gate * handle the situation later. 1456*7c478bd9Sstevel@tonic-gate */ 1457*7c478bd9Sstevel@tonic-gate SCPYL(rusername, optarg); 1458*7c478bd9Sstevel@tonic-gate Uflag = B_TRUE; 1459*7c478bd9Sstevel@tonic-gate break; 1460*7c478bd9Sstevel@tonic-gate case 'z': 1461*7c478bd9Sstevel@tonic-gate if (hflag || rflag || zflag) { 1462*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, flags_message); 1463*7c478bd9Sstevel@tonic-gate login_exit(1); 1464*7c478bd9Sstevel@tonic-gate } 1465*7c478bd9Sstevel@tonic-gate (void) snprintf(zone_name, sizeof (zone_name), 1466*7c478bd9Sstevel@tonic-gate "zone:%s", optarg); 1467*7c478bd9Sstevel@tonic-gate SCPYL(progname, "zlogin"); 1468*7c478bd9Sstevel@tonic-gate zflag = B_TRUE; 1469*7c478bd9Sstevel@tonic-gate break; 1470*7c478bd9Sstevel@tonic-gate default: 1471*7c478bd9Sstevel@tonic-gate errflg++; 1472*7c478bd9Sstevel@tonic-gate break; 1473*7c478bd9Sstevel@tonic-gate } /* end switch */ 1474*7c478bd9Sstevel@tonic-gate } /* end while */ 1475*7c478bd9Sstevel@tonic-gate 1476*7c478bd9Sstevel@tonic-gate /* 1477*7c478bd9Sstevel@tonic-gate * If the 's svcname' flag was used, override the progname 1478*7c478bd9Sstevel@tonic-gate * value that is to be used in the pam_start call. 1479*7c478bd9Sstevel@tonic-gate */ 1480*7c478bd9Sstevel@tonic-gate if (sflag) 1481*7c478bd9Sstevel@tonic-gate SCPYL(progname, sflagname); 1482*7c478bd9Sstevel@tonic-gate 1483*7c478bd9Sstevel@tonic-gate /* 1484*7c478bd9Sstevel@tonic-gate * get the prompt set by ttymon 1485*7c478bd9Sstevel@tonic-gate */ 1486*7c478bd9Sstevel@tonic-gate ttyprompt = getenv("TTYPROMPT"); 1487*7c478bd9Sstevel@tonic-gate 1488*7c478bd9Sstevel@tonic-gate if ((ttyprompt != NULL) && (*ttyprompt != '\0')) { 1489*7c478bd9Sstevel@tonic-gate /* 1490*7c478bd9Sstevel@tonic-gate * if ttyprompt is set, there should be data on 1491*7c478bd9Sstevel@tonic-gate * the stream already. 1492*7c478bd9Sstevel@tonic-gate */ 1493*7c478bd9Sstevel@tonic-gate if ((envp = getargs(inputline)) != (char **)NULL) { 1494*7c478bd9Sstevel@tonic-gate /* 1495*7c478bd9Sstevel@tonic-gate * don't get name if name passed as argument. 1496*7c478bd9Sstevel@tonic-gate */ 1497*7c478bd9Sstevel@tonic-gate SCPYL(user_name, *envp++); 1498*7c478bd9Sstevel@tonic-gate } 1499*7c478bd9Sstevel@tonic-gate } else if (optind < argc) { 1500*7c478bd9Sstevel@tonic-gate SCPYL(user_name, argv[optind]); 1501*7c478bd9Sstevel@tonic-gate (void) SCPYL(inputline, user_name); 1502*7c478bd9Sstevel@tonic-gate (void) strlcat(inputline, " \n", sizeof (inputline)); 1503*7c478bd9Sstevel@tonic-gate envp = &argv[optind+1]; 1504*7c478bd9Sstevel@tonic-gate 1505*7c478bd9Sstevel@tonic-gate if (!fflag) 1506*7c478bd9Sstevel@tonic-gate SCPYL(lusername, user_name); 1507*7c478bd9Sstevel@tonic-gate } 1508*7c478bd9Sstevel@tonic-gate 1509*7c478bd9Sstevel@tonic-gate if (errflg) 1510*7c478bd9Sstevel@tonic-gate return (-1); 1511*7c478bd9Sstevel@tonic-gate return (0); 1512*7c478bd9Sstevel@tonic-gate } 1513*7c478bd9Sstevel@tonic-gate 1514*7c478bd9Sstevel@tonic-gate /* 1515*7c478bd9Sstevel@tonic-gate * usage - Print usage message 1516*7c478bd9Sstevel@tonic-gate * 1517*7c478bd9Sstevel@tonic-gate */ 1518*7c478bd9Sstevel@tonic-gate static void 1519*7c478bd9Sstevel@tonic-gate usage(void) 1520*7c478bd9Sstevel@tonic-gate { 1521*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1522*7c478bd9Sstevel@tonic-gate "usage:\n" 1523*7c478bd9Sstevel@tonic-gate " login [-p] [-d device] [-R repository] [-s service]\n" 1524*7c478bd9Sstevel@tonic-gate "\t[-t terminal] [-u identity] [-U ruser]\n" 1525*7c478bd9Sstevel@tonic-gate "\t[-h hostname [terminal] | -r hostname] [name [environ]...]\n"); 1526*7c478bd9Sstevel@tonic-gate 1527*7c478bd9Sstevel@tonic-gate } 1528*7c478bd9Sstevel@tonic-gate 1529*7c478bd9Sstevel@tonic-gate /* 1530*7c478bd9Sstevel@tonic-gate * doremoteterm - Sets the appropriate ioctls for a remote terminal 1531*7c478bd9Sstevel@tonic-gate */ 1532*7c478bd9Sstevel@tonic-gate static char *speeds[] = { 1533*7c478bd9Sstevel@tonic-gate "0", "50", "75", "110", "134", "150", "200", "300", 1534*7c478bd9Sstevel@tonic-gate "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400", 1535*7c478bd9Sstevel@tonic-gate "57600", "76800", "115200", "153600", "230400", "307200", "460800" 1536*7c478bd9Sstevel@tonic-gate }; 1537*7c478bd9Sstevel@tonic-gate 1538*7c478bd9Sstevel@tonic-gate #define NSPEEDS (sizeof (speeds) / sizeof (speeds[0])) 1539*7c478bd9Sstevel@tonic-gate 1540*7c478bd9Sstevel@tonic-gate 1541*7c478bd9Sstevel@tonic-gate static void 1542*7c478bd9Sstevel@tonic-gate doremoteterm(char *term) 1543*7c478bd9Sstevel@tonic-gate { 1544*7c478bd9Sstevel@tonic-gate struct termios tp; 1545*7c478bd9Sstevel@tonic-gate char *cp = strchr(term, '/'), **cpp; 1546*7c478bd9Sstevel@tonic-gate char *speed; 1547*7c478bd9Sstevel@tonic-gate 1548*7c478bd9Sstevel@tonic-gate (void) ioctl(0, TCGETS, &tp); 1549*7c478bd9Sstevel@tonic-gate 1550*7c478bd9Sstevel@tonic-gate if (cp) { 1551*7c478bd9Sstevel@tonic-gate *cp++ = '\0'; 1552*7c478bd9Sstevel@tonic-gate speed = cp; 1553*7c478bd9Sstevel@tonic-gate cp = strchr(speed, '/'); 1554*7c478bd9Sstevel@tonic-gate 1555*7c478bd9Sstevel@tonic-gate if (cp) 1556*7c478bd9Sstevel@tonic-gate *cp++ = '\0'; 1557*7c478bd9Sstevel@tonic-gate 1558*7c478bd9Sstevel@tonic-gate for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++) 1559*7c478bd9Sstevel@tonic-gate if (strcmp(*cpp, speed) == 0) { 1560*7c478bd9Sstevel@tonic-gate (void) cfsetospeed(&tp, cpp-speeds); 1561*7c478bd9Sstevel@tonic-gate break; 1562*7c478bd9Sstevel@tonic-gate } 1563*7c478bd9Sstevel@tonic-gate } 1564*7c478bd9Sstevel@tonic-gate 1565*7c478bd9Sstevel@tonic-gate tp.c_lflag |= ECHO|ICANON; 1566*7c478bd9Sstevel@tonic-gate tp.c_iflag |= IGNPAR|ICRNL; 1567*7c478bd9Sstevel@tonic-gate 1568*7c478bd9Sstevel@tonic-gate (void) ioctl(0, TCSETS, &tp); 1569*7c478bd9Sstevel@tonic-gate 1570*7c478bd9Sstevel@tonic-gate } 1571*7c478bd9Sstevel@tonic-gate 1572*7c478bd9Sstevel@tonic-gate /* 1573*7c478bd9Sstevel@tonic-gate * Process_rlogin - Does the work that rlogin and telnet 1574*7c478bd9Sstevel@tonic-gate * need done 1575*7c478bd9Sstevel@tonic-gate */ 1576*7c478bd9Sstevel@tonic-gate static void 1577*7c478bd9Sstevel@tonic-gate process_rlogin(void) 1578*7c478bd9Sstevel@tonic-gate { 1579*7c478bd9Sstevel@tonic-gate /* 1580*7c478bd9Sstevel@tonic-gate * If a Kerberized rlogin was initiated, then these fields 1581*7c478bd9Sstevel@tonic-gate * must be read by rlogin daemon itself and passed down via 1582*7c478bd9Sstevel@tonic-gate * cmd line args. 1583*7c478bd9Sstevel@tonic-gate */ 1584*7c478bd9Sstevel@tonic-gate if (!Uflag && !strlen(rusername)) 1585*7c478bd9Sstevel@tonic-gate getstr(rusername, sizeof (rusername), "remuser"); 1586*7c478bd9Sstevel@tonic-gate if (!strlen(lusername)) 1587*7c478bd9Sstevel@tonic-gate getstr(lusername, sizeof (lusername), "locuser"); 1588*7c478bd9Sstevel@tonic-gate if (!tflag && !strlen(terminal)) 1589*7c478bd9Sstevel@tonic-gate getstr(terminal, sizeof (terminal), "Terminal type"); 1590*7c478bd9Sstevel@tonic-gate 1591*7c478bd9Sstevel@tonic-gate if (strlen(terminal)) 1592*7c478bd9Sstevel@tonic-gate doremoteterm(terminal); 1593*7c478bd9Sstevel@tonic-gate 1594*7c478bd9Sstevel@tonic-gate /* fflag has precedence over stuff passed by rlogind */ 1595*7c478bd9Sstevel@tonic-gate if (fflag || getuid()) { 1596*7c478bd9Sstevel@tonic-gate pwd = &nouser; 1597*7c478bd9Sstevel@tonic-gate return; 1598*7c478bd9Sstevel@tonic-gate } else { 1599*7c478bd9Sstevel@tonic-gate if (pam_set_item(pamh, PAM_USER, lusername) != PAM_SUCCESS) 1600*7c478bd9Sstevel@tonic-gate login_exit(1); 1601*7c478bd9Sstevel@tonic-gate 1602*7c478bd9Sstevel@tonic-gate pwd = getpwnam(lusername); 1603*7c478bd9Sstevel@tonic-gate if (pwd == NULL) { 1604*7c478bd9Sstevel@tonic-gate pwd = &nouser; 1605*7c478bd9Sstevel@tonic-gate return; 1606*7c478bd9Sstevel@tonic-gate } 1607*7c478bd9Sstevel@tonic-gate } 1608*7c478bd9Sstevel@tonic-gate 1609*7c478bd9Sstevel@tonic-gate /* 1610*7c478bd9Sstevel@tonic-gate * Update PAM on the user name 1611*7c478bd9Sstevel@tonic-gate */ 1612*7c478bd9Sstevel@tonic-gate if (strlen(lusername) && 1613*7c478bd9Sstevel@tonic-gate pam_set_item(pamh, PAM_USER, lusername) != PAM_SUCCESS) 1614*7c478bd9Sstevel@tonic-gate login_exit(1); 1615*7c478bd9Sstevel@tonic-gate 1616*7c478bd9Sstevel@tonic-gate if (strlen(rusername) && 1617*7c478bd9Sstevel@tonic-gate pam_set_item(pamh, PAM_RUSER, rusername) != PAM_SUCCESS) 1618*7c478bd9Sstevel@tonic-gate login_exit(1); 1619*7c478bd9Sstevel@tonic-gate 1620*7c478bd9Sstevel@tonic-gate SCPYL(user_name, lusername); 1621*7c478bd9Sstevel@tonic-gate envp = &zero; 1622*7c478bd9Sstevel@tonic-gate lusername[0] = '\0'; 1623*7c478bd9Sstevel@tonic-gate } 1624*7c478bd9Sstevel@tonic-gate 1625*7c478bd9Sstevel@tonic-gate /* 1626*7c478bd9Sstevel@tonic-gate * *** Account validation routines *** 1627*7c478bd9Sstevel@tonic-gate * 1628*7c478bd9Sstevel@tonic-gate */ 1629*7c478bd9Sstevel@tonic-gate 1630*7c478bd9Sstevel@tonic-gate /* 1631*7c478bd9Sstevel@tonic-gate * validate_account - This is the PAM version of validate. 1632*7c478bd9Sstevel@tonic-gate */ 1633*7c478bd9Sstevel@tonic-gate 1634*7c478bd9Sstevel@tonic-gate static void 1635*7c478bd9Sstevel@tonic-gate validate_account(void) 1636*7c478bd9Sstevel@tonic-gate { 1637*7c478bd9Sstevel@tonic-gate int error; 1638*7c478bd9Sstevel@tonic-gate int flag; 1639*7c478bd9Sstevel@tonic-gate int tries; /* new password retries */ 1640*7c478bd9Sstevel@tonic-gate 1641*7c478bd9Sstevel@tonic-gate (void) alarm(0); /* give user time to come up with password */ 1642*7c478bd9Sstevel@tonic-gate 1643*7c478bd9Sstevel@tonic-gate check_log(); 1644*7c478bd9Sstevel@tonic-gate 1645*7c478bd9Sstevel@tonic-gate if (Passreqflag) 1646*7c478bd9Sstevel@tonic-gate flag = PAM_DISALLOW_NULL_AUTHTOK; 1647*7c478bd9Sstevel@tonic-gate else 1648*7c478bd9Sstevel@tonic-gate flag = 0; 1649*7c478bd9Sstevel@tonic-gate 1650*7c478bd9Sstevel@tonic-gate if ((error = pam_acct_mgmt(pamh, flag)) != PAM_SUCCESS) { 1651*7c478bd9Sstevel@tonic-gate if (error == PAM_NEW_AUTHTOK_REQD) { 1652*7c478bd9Sstevel@tonic-gate tries = 1; 1653*7c478bd9Sstevel@tonic-gate error = PAM_AUTHTOK_ERR; 1654*7c478bd9Sstevel@tonic-gate while (error == PAM_AUTHTOK_ERR && 1655*7c478bd9Sstevel@tonic-gate tries <= DEF_ATTEMPTS) { 1656*7c478bd9Sstevel@tonic-gate if (tries > 1) 1657*7c478bd9Sstevel@tonic-gate (void) printf("Try again\n\n"); 1658*7c478bd9Sstevel@tonic-gate 1659*7c478bd9Sstevel@tonic-gate (void) printf("Choose a new password.\n"); 1660*7c478bd9Sstevel@tonic-gate 1661*7c478bd9Sstevel@tonic-gate error = pam_chauthtok(pamh, 0); 1662*7c478bd9Sstevel@tonic-gate if (error == PAM_TRY_AGAIN) { 1663*7c478bd9Sstevel@tonic-gate (void) sleep(1); 1664*7c478bd9Sstevel@tonic-gate error = pam_chauthtok(pamh, 0); 1665*7c478bd9Sstevel@tonic-gate } 1666*7c478bd9Sstevel@tonic-gate tries++; 1667*7c478bd9Sstevel@tonic-gate } 1668*7c478bd9Sstevel@tonic-gate 1669*7c478bd9Sstevel@tonic-gate if (error != PAM_SUCCESS) { 1670*7c478bd9Sstevel@tonic-gate if (dosyslog) 1671*7c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, 1672*7c478bd9Sstevel@tonic-gate "change password failure: %s", 1673*7c478bd9Sstevel@tonic-gate pam_strerror(pamh, error)); 1674*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + error; 1675*7c478bd9Sstevel@tonic-gate login_exit(1); 1676*7c478bd9Sstevel@tonic-gate } else { 1677*7c478bd9Sstevel@tonic-gate audit_success(ADT_passwd, pwd, zone_name); 1678*7c478bd9Sstevel@tonic-gate } 1679*7c478bd9Sstevel@tonic-gate } else { 1680*7c478bd9Sstevel@tonic-gate (void) printf(incorrectmsg); 1681*7c478bd9Sstevel@tonic-gate 1682*7c478bd9Sstevel@tonic-gate if (dosyslog) 1683*7c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, 1684*7c478bd9Sstevel@tonic-gate "login account failure: %s", 1685*7c478bd9Sstevel@tonic-gate pam_strerror(pamh, error)); 1686*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + error; 1687*7c478bd9Sstevel@tonic-gate login_exit(1); 1688*7c478bd9Sstevel@tonic-gate } 1689*7c478bd9Sstevel@tonic-gate } 1690*7c478bd9Sstevel@tonic-gate } 1691*7c478bd9Sstevel@tonic-gate 1692*7c478bd9Sstevel@tonic-gate /* 1693*7c478bd9Sstevel@tonic-gate * Check_log - This is really a hack because PAM checks the log, but login 1694*7c478bd9Sstevel@tonic-gate * wants to know if the log is okay and PAM doesn't have 1695*7c478bd9Sstevel@tonic-gate * a module independent way of handing this info back. 1696*7c478bd9Sstevel@tonic-gate */ 1697*7c478bd9Sstevel@tonic-gate 1698*7c478bd9Sstevel@tonic-gate static void 1699*7c478bd9Sstevel@tonic-gate check_log(void) 1700*7c478bd9Sstevel@tonic-gate { 1701*7c478bd9Sstevel@tonic-gate int fdl; 1702*7c478bd9Sstevel@tonic-gate long long offset; 1703*7c478bd9Sstevel@tonic-gate 1704*7c478bd9Sstevel@tonic-gate offset = (long long) pwd->pw_uid * (long long) sizeof (struct lastlog); 1705*7c478bd9Sstevel@tonic-gate 1706*7c478bd9Sstevel@tonic-gate if ((fdl = open(LASTLOG, O_RDWR|O_CREAT, 0444)) >= 0) { 1707*7c478bd9Sstevel@tonic-gate if (llseek(fdl, offset, SEEK_SET) == offset && 1708*7c478bd9Sstevel@tonic-gate read(fdl, (char *)&ll, sizeof (ll)) == sizeof (ll) && 1709*7c478bd9Sstevel@tonic-gate ll.ll_time != 0) 1710*7c478bd9Sstevel@tonic-gate lastlogok = 1; 1711*7c478bd9Sstevel@tonic-gate (void) close(fdl); 1712*7c478bd9Sstevel@tonic-gate } 1713*7c478bd9Sstevel@tonic-gate } 1714*7c478bd9Sstevel@tonic-gate 1715*7c478bd9Sstevel@tonic-gate /* 1716*7c478bd9Sstevel@tonic-gate * chdir_to_dir_user - Now chdir after setuid/setgid have happened to 1717*7c478bd9Sstevel@tonic-gate * place us in the user's home directory just in 1718*7c478bd9Sstevel@tonic-gate * case it was protected and the first chdir failed. 1719*7c478bd9Sstevel@tonic-gate * No chdir errors should happen at this point because 1720*7c478bd9Sstevel@tonic-gate * all failures should have happened on the first 1721*7c478bd9Sstevel@tonic-gate * time around. 1722*7c478bd9Sstevel@tonic-gate */ 1723*7c478bd9Sstevel@tonic-gate 1724*7c478bd9Sstevel@tonic-gate static void 1725*7c478bd9Sstevel@tonic-gate chdir_to_dir_user(void) 1726*7c478bd9Sstevel@tonic-gate { 1727*7c478bd9Sstevel@tonic-gate if (chdir(pwd->pw_dir) < 0) { 1728*7c478bd9Sstevel@tonic-gate if (chdir("/") < 0) { 1729*7c478bd9Sstevel@tonic-gate (void) printf("No directory!\n"); 1730*7c478bd9Sstevel@tonic-gate /* 1731*7c478bd9Sstevel@tonic-gate * This probably won't work since we can't get to /. 1732*7c478bd9Sstevel@tonic-gate */ 1733*7c478bd9Sstevel@tonic-gate if (dosyslog) { 1734*7c478bd9Sstevel@tonic-gate if (remote_host[0]) { 1735*7c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, 1736*7c478bd9Sstevel@tonic-gate "LOGIN FAILURES ON %s FROM %.*s ", 1737*7c478bd9Sstevel@tonic-gate " %.*s", ttyn, HMAX, 1738*7c478bd9Sstevel@tonic-gate remote_host, NMAX, pwd->pw_name); 1739*7c478bd9Sstevel@tonic-gate } else { 1740*7c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, 1741*7c478bd9Sstevel@tonic-gate "LOGIN FAILURES ON %s, %.*s", 1742*7c478bd9Sstevel@tonic-gate ttyn, NMAX, pwd->pw_name); 1743*7c478bd9Sstevel@tonic-gate } 1744*7c478bd9Sstevel@tonic-gate } 1745*7c478bd9Sstevel@tonic-gate closelog(); 1746*7c478bd9Sstevel@tonic-gate (void) sleep(Disabletime); 1747*7c478bd9Sstevel@tonic-gate exit(1); 1748*7c478bd9Sstevel@tonic-gate } else { 1749*7c478bd9Sstevel@tonic-gate (void) printf("No directory! Logging in with home=/\n"); 1750*7c478bd9Sstevel@tonic-gate pwd->pw_dir = "/"; 1751*7c478bd9Sstevel@tonic-gate } 1752*7c478bd9Sstevel@tonic-gate } 1753*7c478bd9Sstevel@tonic-gate } 1754*7c478bd9Sstevel@tonic-gate 1755*7c478bd9Sstevel@tonic-gate 1756*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 1757*7c478bd9Sstevel@tonic-gate /* 1758*7c478bd9Sstevel@tonic-gate * login_authenticate - Performs the main authentication work 1759*7c478bd9Sstevel@tonic-gate * 1. Prints the login prompt 1760*7c478bd9Sstevel@tonic-gate * 2. Requests and verifys the password 1761*7c478bd9Sstevel@tonic-gate * 3. Checks the port password 1762*7c478bd9Sstevel@tonic-gate */ 1763*7c478bd9Sstevel@tonic-gate 1764*7c478bd9Sstevel@tonic-gate static void 1765*7c478bd9Sstevel@tonic-gate login_authenticate() 1766*7c478bd9Sstevel@tonic-gate { 1767*7c478bd9Sstevel@tonic-gate char *user; 1768*7c478bd9Sstevel@tonic-gate int err; 1769*7c478bd9Sstevel@tonic-gate int login_successful = 0; 1770*7c478bd9Sstevel@tonic-gate 1771*7c478bd9Sstevel@tonic-gate do { 1772*7c478bd9Sstevel@tonic-gate /* if scheme broken, then nothing to do but quit */ 1773*7c478bd9Sstevel@tonic-gate if (pam_get_item(pamh, PAM_USER, (void **)&user) 1774*7c478bd9Sstevel@tonic-gate != PAM_SUCCESS) 1775*7c478bd9Sstevel@tonic-gate exit(1); 1776*7c478bd9Sstevel@tonic-gate 1777*7c478bd9Sstevel@tonic-gate /* 1778*7c478bd9Sstevel@tonic-gate * only get name from utility if it is not already 1779*7c478bd9Sstevel@tonic-gate * supplied by pam_start or a pam_set_item. 1780*7c478bd9Sstevel@tonic-gate */ 1781*7c478bd9Sstevel@tonic-gate if (!user || !user[0]) { 1782*7c478bd9Sstevel@tonic-gate /* use call back to get user name */ 1783*7c478bd9Sstevel@tonic-gate get_user_name(); 1784*7c478bd9Sstevel@tonic-gate } 1785*7c478bd9Sstevel@tonic-gate 1786*7c478bd9Sstevel@tonic-gate err = verify_passwd(); 1787*7c478bd9Sstevel@tonic-gate 1788*7c478bd9Sstevel@tonic-gate /* 1789*7c478bd9Sstevel@tonic-gate * If root login and not on system console then call exit(2) 1790*7c478bd9Sstevel@tonic-gate */ 1791*7c478bd9Sstevel@tonic-gate check_for_console(); 1792*7c478bd9Sstevel@tonic-gate 1793*7c478bd9Sstevel@tonic-gate switch (err) { 1794*7c478bd9Sstevel@tonic-gate case PAM_SUCCESS: 1795*7c478bd9Sstevel@tonic-gate case PAM_NEW_AUTHTOK_REQD: 1796*7c478bd9Sstevel@tonic-gate /* 1797*7c478bd9Sstevel@tonic-gate * Officially, pam_authenticate() shouldn't return this 1798*7c478bd9Sstevel@tonic-gate * but it's probably the right thing to return if 1799*7c478bd9Sstevel@tonic-gate * PAM_DISALLOW_NULL_AUTHTOK is set so the user will 1800*7c478bd9Sstevel@tonic-gate * be forced to change password later in this code. 1801*7c478bd9Sstevel@tonic-gate */ 1802*7c478bd9Sstevel@tonic-gate count = 0; 1803*7c478bd9Sstevel@tonic-gate login_successful = 1; 1804*7c478bd9Sstevel@tonic-gate break; 1805*7c478bd9Sstevel@tonic-gate case PAM_MAXTRIES: 1806*7c478bd9Sstevel@tonic-gate count = retry; 1807*7c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 1808*7c478bd9Sstevel@tonic-gate case PAM_AUTH_ERR: 1809*7c478bd9Sstevel@tonic-gate case PAM_AUTHINFO_UNAVAIL: 1810*7c478bd9Sstevel@tonic-gate case PAM_USER_UNKNOWN: 1811*7c478bd9Sstevel@tonic-gate audit_failure(get_audit_id(), ADT_FAIL_PAM + err, pwd, 1812*7c478bd9Sstevel@tonic-gate remote_host, ttyn, zone_name); 1813*7c478bd9Sstevel@tonic-gate log_bad_attempts(); 1814*7c478bd9Sstevel@tonic-gate break; 1815*7c478bd9Sstevel@tonic-gate case PAM_ABORT: 1816*7c478bd9Sstevel@tonic-gate log_bad_attempts(); 1817*7c478bd9Sstevel@tonic-gate (void) sleep(Disabletime); 1818*7c478bd9Sstevel@tonic-gate (void) printf(incorrectmsg); 1819*7c478bd9Sstevel@tonic-gate 1820*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + err; 1821*7c478bd9Sstevel@tonic-gate login_exit(1); 1822*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1823*7c478bd9Sstevel@tonic-gate default: /* Some other PAM error */ 1824*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + err; 1825*7c478bd9Sstevel@tonic-gate login_exit(1); 1826*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1827*7c478bd9Sstevel@tonic-gate } 1828*7c478bd9Sstevel@tonic-gate 1829*7c478bd9Sstevel@tonic-gate if (login_successful) 1830*7c478bd9Sstevel@tonic-gate break; 1831*7c478bd9Sstevel@tonic-gate 1832*7c478bd9Sstevel@tonic-gate /* sleep after bad passwd */ 1833*7c478bd9Sstevel@tonic-gate if (count) 1834*7c478bd9Sstevel@tonic-gate (void) sleep(Sleeptime); 1835*7c478bd9Sstevel@tonic-gate (void) printf(incorrectmsg); 1836*7c478bd9Sstevel@tonic-gate /* force name to be null in this case */ 1837*7c478bd9Sstevel@tonic-gate if (pam_set_item(pamh, PAM_USER, NULL) != PAM_SUCCESS) 1838*7c478bd9Sstevel@tonic-gate login_exit(1); 1839*7c478bd9Sstevel@tonic-gate if (pam_set_item(pamh, PAM_RUSER, NULL) != PAM_SUCCESS) 1840*7c478bd9Sstevel@tonic-gate login_exit(1); 1841*7c478bd9Sstevel@tonic-gate } while (count++ < retry); 1842*7c478bd9Sstevel@tonic-gate 1843*7c478bd9Sstevel@tonic-gate if (count >= retry) { 1844*7c478bd9Sstevel@tonic-gate audit_failure(get_audit_id(), ADT_FAIL_VALUE_MAX_TRIES, pwd, 1845*7c478bd9Sstevel@tonic-gate remote_host, ttyn, zone_name); 1846*7c478bd9Sstevel@tonic-gate /* 1847*7c478bd9Sstevel@tonic-gate * If logging is turned on, output the 1848*7c478bd9Sstevel@tonic-gate * string storage area to the log file, 1849*7c478bd9Sstevel@tonic-gate * and sleep for Disabletime 1850*7c478bd9Sstevel@tonic-gate * seconds before exiting. 1851*7c478bd9Sstevel@tonic-gate */ 1852*7c478bd9Sstevel@tonic-gate if (writelog) 1853*7c478bd9Sstevel@tonic-gate badlogin(); 1854*7c478bd9Sstevel@tonic-gate if (dosyslog) { 1855*7c478bd9Sstevel@tonic-gate if ((pwd = getpwnam(user_name)) != NULL) { 1856*7c478bd9Sstevel@tonic-gate if (remote_host[0]) { 1857*7c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, 1858*7c478bd9Sstevel@tonic-gate "REPEATED LOGIN FAILURES ON %s FROM " 1859*7c478bd9Sstevel@tonic-gate "%.*s, %.*s", 1860*7c478bd9Sstevel@tonic-gate ttyn, HMAX, remote_host, NMAX, 1861*7c478bd9Sstevel@tonic-gate user_name); 1862*7c478bd9Sstevel@tonic-gate } else { 1863*7c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, 1864*7c478bd9Sstevel@tonic-gate "REPEATED LOGIN FAILURES ON %s, %.*s", 1865*7c478bd9Sstevel@tonic-gate ttyn, NMAX, user_name); 1866*7c478bd9Sstevel@tonic-gate } 1867*7c478bd9Sstevel@tonic-gate } else { 1868*7c478bd9Sstevel@tonic-gate if (remote_host[0]) { 1869*7c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, 1870*7c478bd9Sstevel@tonic-gate "REPEATED LOGIN FAILURES ON %s FROM " 1871*7c478bd9Sstevel@tonic-gate "%.*s", 1872*7c478bd9Sstevel@tonic-gate ttyn, HMAX, remote_host); 1873*7c478bd9Sstevel@tonic-gate } else { 1874*7c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, 1875*7c478bd9Sstevel@tonic-gate "REPEATED LOGIN FAILURES ON %s", ttyn); 1876*7c478bd9Sstevel@tonic-gate } 1877*7c478bd9Sstevel@tonic-gate } 1878*7c478bd9Sstevel@tonic-gate } 1879*7c478bd9Sstevel@tonic-gate (void) sleep(Disabletime); 1880*7c478bd9Sstevel@tonic-gate exit(1); 1881*7c478bd9Sstevel@tonic-gate } 1882*7c478bd9Sstevel@tonic-gate 1883*7c478bd9Sstevel@tonic-gate } 1884*7c478bd9Sstevel@tonic-gate 1885*7c478bd9Sstevel@tonic-gate /* 1886*7c478bd9Sstevel@tonic-gate * *** Credential Related routines *** 1887*7c478bd9Sstevel@tonic-gate * 1888*7c478bd9Sstevel@tonic-gate */ 1889*7c478bd9Sstevel@tonic-gate 1890*7c478bd9Sstevel@tonic-gate /* 1891*7c478bd9Sstevel@tonic-gate * setup_credentials - sets the group ID, initializes the groups 1892*7c478bd9Sstevel@tonic-gate * and sets up the secretkey. 1893*7c478bd9Sstevel@tonic-gate * Exits if a failure occurrs. 1894*7c478bd9Sstevel@tonic-gate */ 1895*7c478bd9Sstevel@tonic-gate 1896*7c478bd9Sstevel@tonic-gate 1897*7c478bd9Sstevel@tonic-gate /* 1898*7c478bd9Sstevel@tonic-gate * setup_credentials - PAM does all the work for us on this one. 1899*7c478bd9Sstevel@tonic-gate */ 1900*7c478bd9Sstevel@tonic-gate 1901*7c478bd9Sstevel@tonic-gate static void 1902*7c478bd9Sstevel@tonic-gate setup_credentials(void) 1903*7c478bd9Sstevel@tonic-gate { 1904*7c478bd9Sstevel@tonic-gate int error = 0; 1905*7c478bd9Sstevel@tonic-gate 1906*7c478bd9Sstevel@tonic-gate /* set the real (and effective) GID */ 1907*7c478bd9Sstevel@tonic-gate if (setgid(pwd->pw_gid) == -1) { 1908*7c478bd9Sstevel@tonic-gate login_exit(1); 1909*7c478bd9Sstevel@tonic-gate } 1910*7c478bd9Sstevel@tonic-gate 1911*7c478bd9Sstevel@tonic-gate /* 1912*7c478bd9Sstevel@tonic-gate * Initialize the supplementary group access list. 1913*7c478bd9Sstevel@tonic-gate */ 1914*7c478bd9Sstevel@tonic-gate if ((user_name[0] == '\0') || 1915*7c478bd9Sstevel@tonic-gate (initgroups(user_name, pwd->pw_gid) == -1)) { 1916*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_PROGRAM; 1917*7c478bd9Sstevel@tonic-gate login_exit(1); 1918*7c478bd9Sstevel@tonic-gate } 1919*7c478bd9Sstevel@tonic-gate 1920*7c478bd9Sstevel@tonic-gate if ((error = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) { 1921*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + error; 1922*7c478bd9Sstevel@tonic-gate login_exit(error); 1923*7c478bd9Sstevel@tonic-gate } 1924*7c478bd9Sstevel@tonic-gate 1925*7c478bd9Sstevel@tonic-gate /* 1926*7c478bd9Sstevel@tonic-gate * Record successful login and fork process that records logout. 1927*7c478bd9Sstevel@tonic-gate * We have to do this after setting credentials because pam_setcred() 1928*7c478bd9Sstevel@tonic-gate * loads key audit info into the cred, but before setuid() so audit 1929*7c478bd9Sstevel@tonic-gate * system calls will work. 1930*7c478bd9Sstevel@tonic-gate */ 1931*7c478bd9Sstevel@tonic-gate audit_success(get_audit_id(), pwd, zone_name); 1932*7c478bd9Sstevel@tonic-gate 1933*7c478bd9Sstevel@tonic-gate /* set the real (and effective) UID */ 1934*7c478bd9Sstevel@tonic-gate if (setuid(pwd->pw_uid) == -1) { 1935*7c478bd9Sstevel@tonic-gate login_exit(1); 1936*7c478bd9Sstevel@tonic-gate } 1937*7c478bd9Sstevel@tonic-gate 1938*7c478bd9Sstevel@tonic-gate } 1939*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 1940*7c478bd9Sstevel@tonic-gate 1941*7c478bd9Sstevel@tonic-gate static uint_t 1942*7c478bd9Sstevel@tonic-gate get_audit_id() { 1943*7c478bd9Sstevel@tonic-gate if (rflag) 1944*7c478bd9Sstevel@tonic-gate return (ADT_rlogin); 1945*7c478bd9Sstevel@tonic-gate else if (hflag) 1946*7c478bd9Sstevel@tonic-gate return (ADT_telnet); 1947*7c478bd9Sstevel@tonic-gate else if (zflag) 1948*7c478bd9Sstevel@tonic-gate return (ADT_zlogin); 1949*7c478bd9Sstevel@tonic-gate 1950*7c478bd9Sstevel@tonic-gate return (ADT_login); 1951*7c478bd9Sstevel@tonic-gate } 1952*7c478bd9Sstevel@tonic-gate 1953*7c478bd9Sstevel@tonic-gate /* 1954*7c478bd9Sstevel@tonic-gate * 1955*7c478bd9Sstevel@tonic-gate * *** Routines to get a new user set up and running *** 1956*7c478bd9Sstevel@tonic-gate * 1957*7c478bd9Sstevel@tonic-gate * Things to do when starting up a new user: 1958*7c478bd9Sstevel@tonic-gate * adjust_nice 1959*7c478bd9Sstevel@tonic-gate * update_utmpx_entry 1960*7c478bd9Sstevel@tonic-gate * establish_user_environment 1961*7c478bd9Sstevel@tonic-gate * print_banner 1962*7c478bd9Sstevel@tonic-gate * display_last_login_time 1963*7c478bd9Sstevel@tonic-gate * exec_the_shell 1964*7c478bd9Sstevel@tonic-gate * 1965*7c478bd9Sstevel@tonic-gate */ 1966*7c478bd9Sstevel@tonic-gate 1967*7c478bd9Sstevel@tonic-gate 1968*7c478bd9Sstevel@tonic-gate /* 1969*7c478bd9Sstevel@tonic-gate * adjust_nice - Set the nice (process priority) value if the 1970*7c478bd9Sstevel@tonic-gate * gecos value contains an appropriate value. 1971*7c478bd9Sstevel@tonic-gate */ 1972*7c478bd9Sstevel@tonic-gate 1973*7c478bd9Sstevel@tonic-gate static void 1974*7c478bd9Sstevel@tonic-gate adjust_nice(void) 1975*7c478bd9Sstevel@tonic-gate { 1976*7c478bd9Sstevel@tonic-gate int pri, mflg, i; 1977*7c478bd9Sstevel@tonic-gate 1978*7c478bd9Sstevel@tonic-gate if (strncmp("pri=", pwd->pw_gecos, 4) == 0) { 1979*7c478bd9Sstevel@tonic-gate pri = 0; 1980*7c478bd9Sstevel@tonic-gate mflg = 0; 1981*7c478bd9Sstevel@tonic-gate i = 4; 1982*7c478bd9Sstevel@tonic-gate 1983*7c478bd9Sstevel@tonic-gate if (pwd->pw_gecos[i] == '-') { 1984*7c478bd9Sstevel@tonic-gate mflg++; 1985*7c478bd9Sstevel@tonic-gate i++; 1986*7c478bd9Sstevel@tonic-gate } 1987*7c478bd9Sstevel@tonic-gate 1988*7c478bd9Sstevel@tonic-gate while (pwd->pw_gecos[i] >= '0' && pwd->pw_gecos[i] <= '9') 1989*7c478bd9Sstevel@tonic-gate pri = (pri * 10) + pwd->pw_gecos[i++] - '0'; 1990*7c478bd9Sstevel@tonic-gate 1991*7c478bd9Sstevel@tonic-gate if (mflg) 1992*7c478bd9Sstevel@tonic-gate pri = -pri; 1993*7c478bd9Sstevel@tonic-gate 1994*7c478bd9Sstevel@tonic-gate (void) nice(pri); 1995*7c478bd9Sstevel@tonic-gate } 1996*7c478bd9Sstevel@tonic-gate } 1997*7c478bd9Sstevel@tonic-gate 1998*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 1999*7c478bd9Sstevel@tonic-gate /* 2000*7c478bd9Sstevel@tonic-gate * update_utmpx_entry - Searchs for the correct utmpx entry, making an 2001*7c478bd9Sstevel@tonic-gate * entry there if it finds one, otherwise exits. 2002*7c478bd9Sstevel@tonic-gate */ 2003*7c478bd9Sstevel@tonic-gate 2004*7c478bd9Sstevel@tonic-gate static void 2005*7c478bd9Sstevel@tonic-gate update_utmpx_entry(int sublogin) 2006*7c478bd9Sstevel@tonic-gate { 2007*7c478bd9Sstevel@tonic-gate int err; 2008*7c478bd9Sstevel@tonic-gate char *user; 2009*7c478bd9Sstevel@tonic-gate static char *errmsg = "No utmpx entry. " 2010*7c478bd9Sstevel@tonic-gate "You must exec \"login\" from the lowest level \"shell\"."; 2011*7c478bd9Sstevel@tonic-gate int tmplen; 2012*7c478bd9Sstevel@tonic-gate struct utmpx *u = (struct utmpx *)0; 2013*7c478bd9Sstevel@tonic-gate struct utmpx utmpx; 2014*7c478bd9Sstevel@tonic-gate char *ttyntail; 2015*7c478bd9Sstevel@tonic-gate 2016*7c478bd9Sstevel@tonic-gate /* 2017*7c478bd9Sstevel@tonic-gate * If we're not a sublogin then 2018*7c478bd9Sstevel@tonic-gate * we'll get an error back if our PID doesn't match the PID of the 2019*7c478bd9Sstevel@tonic-gate * entry we are updating, otherwise if its a sublogin the flags 2020*7c478bd9Sstevel@tonic-gate * field is set to 0, which means we just write a matching entry 2021*7c478bd9Sstevel@tonic-gate * (without checking the pid), or a new entry if an entry doesn't 2022*7c478bd9Sstevel@tonic-gate * exist. 2023*7c478bd9Sstevel@tonic-gate */ 2024*7c478bd9Sstevel@tonic-gate 2025*7c478bd9Sstevel@tonic-gate if ((err = pam_open_session(pamh, 0)) != PAM_SUCCESS) { 2026*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + err; 2027*7c478bd9Sstevel@tonic-gate login_exit(1); 2028*7c478bd9Sstevel@tonic-gate } 2029*7c478bd9Sstevel@tonic-gate 2030*7c478bd9Sstevel@tonic-gate if ((err = pam_get_item(pamh, PAM_USER, (void **) &user)) != 2031*7c478bd9Sstevel@tonic-gate PAM_SUCCESS) { 2032*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_PAM + err; 2033*7c478bd9Sstevel@tonic-gate login_exit(1); 2034*7c478bd9Sstevel@tonic-gate } 2035*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 2036*7c478bd9Sstevel@tonic-gate 2037*7c478bd9Sstevel@tonic-gate (void) memset((void *)&utmpx, 0, sizeof (utmpx)); 2038*7c478bd9Sstevel@tonic-gate (void) time(&utmpx.ut_tv.tv_sec); 2039*7c478bd9Sstevel@tonic-gate utmpx.ut_pid = getpid(); 2040*7c478bd9Sstevel@tonic-gate 2041*7c478bd9Sstevel@tonic-gate if (rflag || hflag) { 2042*7c478bd9Sstevel@tonic-gate SCPYN(utmpx.ut_host, remote_host); 2043*7c478bd9Sstevel@tonic-gate tmplen = strlen(remote_host) + 1; 2044*7c478bd9Sstevel@tonic-gate if (tmplen < sizeof (utmpx.ut_host)) 2045*7c478bd9Sstevel@tonic-gate utmpx.ut_syslen = tmplen; 2046*7c478bd9Sstevel@tonic-gate else 2047*7c478bd9Sstevel@tonic-gate utmpx.ut_syslen = sizeof (utmpx.ut_host); 2048*7c478bd9Sstevel@tonic-gate } else if (zflag) { 2049*7c478bd9Sstevel@tonic-gate /* 2050*7c478bd9Sstevel@tonic-gate * If this is a login from another zone, put the 2051*7c478bd9Sstevel@tonic-gate * zone:<zonename> string in the utmpx entry. 2052*7c478bd9Sstevel@tonic-gate */ 2053*7c478bd9Sstevel@tonic-gate SCPYN(utmpx.ut_host, zone_name); 2054*7c478bd9Sstevel@tonic-gate tmplen = strlen(zone_name) + 1; 2055*7c478bd9Sstevel@tonic-gate if (tmplen < sizeof (utmpx.ut_host)) 2056*7c478bd9Sstevel@tonic-gate utmpx.ut_syslen = tmplen; 2057*7c478bd9Sstevel@tonic-gate else 2058*7c478bd9Sstevel@tonic-gate utmpx.ut_syslen = sizeof (utmpx.ut_host); 2059*7c478bd9Sstevel@tonic-gate } else { 2060*7c478bd9Sstevel@tonic-gate utmpx.ut_syslen = 0; 2061*7c478bd9Sstevel@tonic-gate } 2062*7c478bd9Sstevel@tonic-gate 2063*7c478bd9Sstevel@tonic-gate SCPYN(utmpx.ut_user, user); 2064*7c478bd9Sstevel@tonic-gate 2065*7c478bd9Sstevel@tonic-gate /* skip over "/dev/" */ 2066*7c478bd9Sstevel@tonic-gate ttyntail = basename(ttyn); 2067*7c478bd9Sstevel@tonic-gate 2068*7c478bd9Sstevel@tonic-gate while ((u = getutxent()) != NULL) { 2069*7c478bd9Sstevel@tonic-gate if ((u->ut_type == INIT_PROCESS || 2070*7c478bd9Sstevel@tonic-gate u->ut_type == LOGIN_PROCESS || 2071*7c478bd9Sstevel@tonic-gate u->ut_type == USER_PROCESS) && 2072*7c478bd9Sstevel@tonic-gate ((sublogin && strncmp(u->ut_line, ttyntail, 2073*7c478bd9Sstevel@tonic-gate sizeof (u->ut_line)) == 0) || 2074*7c478bd9Sstevel@tonic-gate u->ut_pid == utmpx.ut_pid)) { 2075*7c478bd9Sstevel@tonic-gate SCPYN(utmpx.ut_line, (ttyn+sizeof ("/dev/")-1)); 2076*7c478bd9Sstevel@tonic-gate (void) memcpy(utmpx.ut_id, u->ut_id, 2077*7c478bd9Sstevel@tonic-gate sizeof (utmpx.ut_id)); 2078*7c478bd9Sstevel@tonic-gate utmpx.ut_exit.e_exit = u->ut_exit.e_exit; 2079*7c478bd9Sstevel@tonic-gate utmpx.ut_type = USER_PROCESS; 2080*7c478bd9Sstevel@tonic-gate (void) pututxline(&utmpx); 2081*7c478bd9Sstevel@tonic-gate break; 2082*7c478bd9Sstevel@tonic-gate } 2083*7c478bd9Sstevel@tonic-gate } 2084*7c478bd9Sstevel@tonic-gate endutxent(); 2085*7c478bd9Sstevel@tonic-gate 2086*7c478bd9Sstevel@tonic-gate if (u == (struct utmpx *)NULL) { 2087*7c478bd9Sstevel@tonic-gate if (!sublogin) { 2088*7c478bd9Sstevel@tonic-gate /* 2089*7c478bd9Sstevel@tonic-gate * no utmpx entry already setup 2090*7c478bd9Sstevel@tonic-gate * (init or rlogind/telnetd) 2091*7c478bd9Sstevel@tonic-gate */ 2092*7c478bd9Sstevel@tonic-gate (void) puts(errmsg); 2093*7c478bd9Sstevel@tonic-gate 2094*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_PROGRAM; 2095*7c478bd9Sstevel@tonic-gate login_exit(1); 2096*7c478bd9Sstevel@tonic-gate } 2097*7c478bd9Sstevel@tonic-gate } else { 2098*7c478bd9Sstevel@tonic-gate /* Now attempt to write out this entry to the wtmp file if */ 2099*7c478bd9Sstevel@tonic-gate /* we were successful in getting it from the utmpx file and */ 2100*7c478bd9Sstevel@tonic-gate /* the wtmp file exists. */ 2101*7c478bd9Sstevel@tonic-gate updwtmpx(WTMPX_FILE, &utmpx); 2102*7c478bd9Sstevel@tonic-gate } 2103*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 2104*7c478bd9Sstevel@tonic-gate } 2105*7c478bd9Sstevel@tonic-gate 2106*7c478bd9Sstevel@tonic-gate 2107*7c478bd9Sstevel@tonic-gate 2108*7c478bd9Sstevel@tonic-gate /* 2109*7c478bd9Sstevel@tonic-gate * process_chroot_logins - Chroots to the specified subdirectory and 2110*7c478bd9Sstevel@tonic-gate * re executes login. 2111*7c478bd9Sstevel@tonic-gate */ 2112*7c478bd9Sstevel@tonic-gate 2113*7c478bd9Sstevel@tonic-gate static int 2114*7c478bd9Sstevel@tonic-gate process_chroot_logins(void) 2115*7c478bd9Sstevel@tonic-gate { 2116*7c478bd9Sstevel@tonic-gate /* 2117*7c478bd9Sstevel@tonic-gate * If the shell field starts with a '*', do a chroot to the home 2118*7c478bd9Sstevel@tonic-gate * directory and perform a new login. 2119*7c478bd9Sstevel@tonic-gate */ 2120*7c478bd9Sstevel@tonic-gate 2121*7c478bd9Sstevel@tonic-gate if (*pwd->pw_shell == '*') { 2122*7c478bd9Sstevel@tonic-gate (void) pam_end(pamh, PAM_SUCCESS); /* Done using PAM */ 2123*7c478bd9Sstevel@tonic-gate pamh = NULL; /* really done */ 2124*7c478bd9Sstevel@tonic-gate if (chroot(pwd->pw_dir) < 0) { 2125*7c478bd9Sstevel@tonic-gate (void) printf("No Root Directory\n"); 2126*7c478bd9Sstevel@tonic-gate 2127*7c478bd9Sstevel@tonic-gate audit_failure(get_audit_id(), 2128*7c478bd9Sstevel@tonic-gate ADT_FAIL_VALUE_CHDIR_FAILED, 2129*7c478bd9Sstevel@tonic-gate pwd, remote_host, ttyn, zone_name); 2130*7c478bd9Sstevel@tonic-gate 2131*7c478bd9Sstevel@tonic-gate return (ERROR); 2132*7c478bd9Sstevel@tonic-gate } 2133*7c478bd9Sstevel@tonic-gate /* 2134*7c478bd9Sstevel@tonic-gate * Set the environment flag <!sublogin> so that the next login 2135*7c478bd9Sstevel@tonic-gate * knows that it is a sublogin. 2136*7c478bd9Sstevel@tonic-gate */ 2137*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 2138*7c478bd9Sstevel@tonic-gate envinit[0] = SUBLOGIN; 2139*7c478bd9Sstevel@tonic-gate envinit[1] = (char *)NULL; 2140*7c478bd9Sstevel@tonic-gate (void) printf("Subsystem root: %s\n", pwd->pw_dir); 2141*7c478bd9Sstevel@tonic-gate (void) execle("/usr/bin/login", "login", (char *)0, 2142*7c478bd9Sstevel@tonic-gate &envinit[0]); 2143*7c478bd9Sstevel@tonic-gate (void) execle("/etc/login", "login", (char *)0, &envinit[0]); 2144*7c478bd9Sstevel@tonic-gate (void) printf("No /usr/bin/login or /etc/login on root\n"); 2145*7c478bd9Sstevel@tonic-gate 2146*7c478bd9Sstevel@tonic-gate audit_error = ADT_FAIL_VALUE_PROGRAM; 2147*7c478bd9Sstevel@tonic-gate 2148*7c478bd9Sstevel@tonic-gate login_exit(1); 2149*7c478bd9Sstevel@tonic-gate } 2150*7c478bd9Sstevel@tonic-gate return (OK); 2151*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT START */ 2152*7c478bd9Sstevel@tonic-gate } 2153*7c478bd9Sstevel@tonic-gate 2154*7c478bd9Sstevel@tonic-gate /* 2155*7c478bd9Sstevel@tonic-gate * establish_user_environment - Set up the new users enviornment 2156*7c478bd9Sstevel@tonic-gate */ 2157*7c478bd9Sstevel@tonic-gate 2158*7c478bd9Sstevel@tonic-gate static void 2159*7c478bd9Sstevel@tonic-gate establish_user_environment(char **renvp) 2160*7c478bd9Sstevel@tonic-gate { 2161*7c478bd9Sstevel@tonic-gate int i, j, k, l_index, length, idx = 0; 2162*7c478bd9Sstevel@tonic-gate char *endptr; 2163*7c478bd9Sstevel@tonic-gate char **lenvp; 2164*7c478bd9Sstevel@tonic-gate char **pam_env; 2165*7c478bd9Sstevel@tonic-gate 2166*7c478bd9Sstevel@tonic-gate lenvp = environ; 2167*7c478bd9Sstevel@tonic-gate while (*lenvp++) 2168*7c478bd9Sstevel@tonic-gate ; 2169*7c478bd9Sstevel@tonic-gate 2170*7c478bd9Sstevel@tonic-gate /* count the number of PAM environment variables set by modules */ 2171*7c478bd9Sstevel@tonic-gate if ((pam_env = pam_getenvlist(pamh)) != 0) { 2172*7c478bd9Sstevel@tonic-gate for (idx = 0; pam_env[idx] != 0; idx++) 2173*7c478bd9Sstevel@tonic-gate ; 2174*7c478bd9Sstevel@tonic-gate } 2175*7c478bd9Sstevel@tonic-gate 2176*7c478bd9Sstevel@tonic-gate envinit = (char **)calloc(lenvp - environ + 10 2177*7c478bd9Sstevel@tonic-gate + MAXARGS + idx, sizeof (char *)); 2178*7c478bd9Sstevel@tonic-gate if (envinit == NULL) { 2179*7c478bd9Sstevel@tonic-gate (void) printf("Calloc failed - out of swap space.\n"); 2180*7c478bd9Sstevel@tonic-gate login_exit(8); 2181*7c478bd9Sstevel@tonic-gate } 2182*7c478bd9Sstevel@tonic-gate 2183*7c478bd9Sstevel@tonic-gate /* 2184*7c478bd9Sstevel@tonic-gate * add PAM environment variables first so they 2185*7c478bd9Sstevel@tonic-gate * can be overwritten at login's discretion. 2186*7c478bd9Sstevel@tonic-gate * check for illegal environment variables. 2187*7c478bd9Sstevel@tonic-gate */ 2188*7c478bd9Sstevel@tonic-gate idx = 0; basicenv = 0; 2189*7c478bd9Sstevel@tonic-gate if (pam_env != 0) { 2190*7c478bd9Sstevel@tonic-gate while (pam_env[idx] != 0) { 2191*7c478bd9Sstevel@tonic-gate if (legalenvvar(pam_env[idx])) { 2192*7c478bd9Sstevel@tonic-gate envinit[basicenv] = pam_env[idx]; 2193*7c478bd9Sstevel@tonic-gate basicenv++; 2194*7c478bd9Sstevel@tonic-gate } 2195*7c478bd9Sstevel@tonic-gate idx++; 2196*7c478bd9Sstevel@tonic-gate } 2197*7c478bd9Sstevel@tonic-gate } 2198*7c478bd9Sstevel@tonic-gate (void) memcpy(&envinit[basicenv], newenv, sizeof (newenv)); 2199*7c478bd9Sstevel@tonic-gate /* ONC_PLUS EXTRACT END */ 2200*7c478bd9Sstevel@tonic-gate 2201*7c478bd9Sstevel@tonic-gate /* Set up environment */ 2202*7c478bd9Sstevel@tonic-gate if (rflag) { 2203*7c478bd9Sstevel@tonic-gate ENVSTRNCAT(term, terminal); 2204*7c478bd9Sstevel@tonic-gate } else if (hflag) { 2205*7c478bd9Sstevel@tonic-gate if (strlen(terminal)) { 2206*7c478bd9Sstevel@tonic-gate ENVSTRNCAT(term, terminal); 2207*7c478bd9Sstevel@tonic-gate } 2208*7c478bd9Sstevel@tonic-gate } else { 2209*7c478bd9Sstevel@tonic-gate char *tp = getenv("TERM"); 2210*7c478bd9Sstevel@tonic-gate 2211*7c478bd9Sstevel@tonic-gate if ((tp != NULL) && (*tp != '\0')) 2212*7c478bd9Sstevel@tonic-gate ENVSTRNCAT(term, tp); 2213*7c478bd9Sstevel@tonic-gate } 2214*7c478bd9Sstevel@tonic-gate 2215*7c478bd9Sstevel@tonic-gate ENVSTRNCAT(logname, pwd->pw_name); 2216*7c478bd9Sstevel@tonic-gate 2217*7c478bd9Sstevel@tonic-gate /* 2218*7c478bd9Sstevel@tonic-gate * There are three places to get timezone info. init.c sets 2219*7c478bd9Sstevel@tonic-gate * TZ if the file /etc/TIMEZONE contains a value for TZ. 2220*7c478bd9Sstevel@tonic-gate * login.c looks in the file /etc/default/login for a 2221*7c478bd9Sstevel@tonic-gate * variable called TIMEZONE being set. If TIMEZONE has a 2222*7c478bd9Sstevel@tonic-gate * value, TZ is set to that value; no environment variable 2223*7c478bd9Sstevel@tonic-gate * TIMEZONE is set, only TZ. If neither of these methods 2224*7c478bd9Sstevel@tonic-gate * work to set TZ, then the library routines will default 2225*7c478bd9Sstevel@tonic-gate * to using the file /usr/lib/locale/TZ/localtime. 2226*7c478bd9Sstevel@tonic-gate * 2227*7c478bd9Sstevel@tonic-gate * There is a priority set up here. If /etc/TIMEZONE has 2228*7c478bd9Sstevel@tonic-gate * a value for TZ, that value remains top priority. If the 2229*7c478bd9Sstevel@tonic-gate * file /etc/default/login has TIMEZONE set, that has second 2230*7c478bd9Sstevel@tonic-gate * highest priority not overriding the value of TZ in 2231*7c478bd9Sstevel@tonic-gate * /etc/TIMEZONE. The reason for this priority is that the 2232*7c478bd9Sstevel@tonic-gate * file /etc/TIMEZONE is supposed to be sourced by 2233*7c478bd9Sstevel@tonic-gate * /etc/profile. We are doing the "sourcing" prematurely in 2234*7c478bd9Sstevel@tonic-gate * init.c. Additionally, a login C shell doesn't source the 2235*7c478bd9Sstevel@tonic-gate * file /etc/profile thus not sourcing /etc/TIMEZONE thus not 2236*7c478bd9Sstevel@tonic-gate * allowing an adminstrator to globally set TZ for all users 2237*7c478bd9Sstevel@tonic-gate */ 2238*7c478bd9Sstevel@tonic-gate if (Def_tz != NULL) /* Is there a TZ from defaults/login? */ 2239*7c478bd9Sstevel@tonic-gate tmp_tz = Def_tz; 2240*7c478bd9Sstevel@tonic-gate 2241*7c478bd9Sstevel@tonic-gate if ((Def_tz = getenv("TZ")) != NULL) { 2242*7c478bd9Sstevel@tonic-gate ENVSTRNCAT(timez, Def_tz); 2243*7c478bd9Sstevel@tonic-gate } else if (tmp_tz != NULL) { 2244*7c478bd9Sstevel@tonic-gate Def_tz = tmp_tz; 2245*7c478bd9Sstevel@tonic-gate ENVSTRNCAT(timez, Def_tz); 2246*7c478bd9Sstevel@tonic-gate } 2247*7c478bd9Sstevel@tonic-gate 2248*7c478bd9Sstevel@tonic-gate if (Def_hertz == NULL) 2249*7c478bd9Sstevel@tonic-gate (void) sprintf(hertz + strlen(hertz), "%lu", HZ); 2250*7c478bd9Sstevel@tonic-gate else 2251*7c478bd9Sstevel@tonic-gate ENVSTRNCAT(hertz, Def_hertz); 2252*7c478bd9Sstevel@tonic-gate 2253*7c478bd9Sstevel@tonic-gate if (Def_path == NULL) 2254*7c478bd9Sstevel@tonic-gate (void) strlcat(path, DEF_PATH, sizeof (path)); 2255*7c478bd9Sstevel@tonic-gate else 2256*7c478bd9Sstevel@tonic-gate ENVSTRNCAT(path, Def_path); 2257*7c478bd9Sstevel@tonic-gate 2258*7c478bd9Sstevel@tonic-gate ENVSTRNCAT(home, pwd->pw_dir); 2259*7c478bd9Sstevel@tonic-gate 2260*7c478bd9Sstevel@tonic-gate /* 2261*7c478bd9Sstevel@tonic-gate * Find the end of the basic environment 2262*7c478bd9Sstevel@tonic-gate */ 2263*7c478bd9Sstevel@tonic-gate for (basicenv = 0; envinit[basicenv] != NULL; basicenv++) 2264*7c478bd9Sstevel@tonic-gate ; 2265*7c478bd9Sstevel@tonic-gate 2266*7c478bd9Sstevel@tonic-gate /* 2267*7c478bd9Sstevel@tonic-gate * If TZ has a value, add it. 2268*7c478bd9Sstevel@tonic-gate */ 2269*7c478bd9Sstevel@tonic-gate if (strcmp(timez, "TZ=") != 0) 2270*7c478bd9Sstevel@tonic-gate envinit[basicenv++] = timez; 2271*7c478bd9Sstevel@tonic-gate 2272*7c478bd9Sstevel@tonic-gate if (*pwd->pw_shell == '\0') { 2273*7c478bd9Sstevel@tonic-gate /* 2274*7c478bd9Sstevel@tonic-gate * If possible, use the primary default shell, 2275*7c478bd9Sstevel@tonic-gate * otherwise, use the secondary one. 2276*7c478bd9Sstevel@tonic-gate */ 2277*7c478bd9Sstevel@tonic-gate if (access(SHELL, X_OK) == 0) 2278*7c478bd9Sstevel@tonic-gate pwd->pw_shell = SHELL; 2279*7c478bd9Sstevel@tonic-gate else 2280*7c478bd9Sstevel@tonic-gate pwd->pw_shell = SHELL2; 2281*7c478bd9Sstevel@tonic-gate } else if (Altshell != NULL && strcmp(Altshell, "YES") == 0) { 2282*7c478bd9Sstevel@tonic-gate envinit[basicenv++] = shell; 2283*7c478bd9Sstevel@tonic-gate ENVSTRNCAT(shell, pwd->pw_shell); 2284*7c478bd9Sstevel@tonic-gate } 2285*7c478bd9Sstevel@tonic-gate 2286*7c478bd9Sstevel@tonic-gate #ifndef NO_MAIL 2287*7c478bd9Sstevel@tonic-gate envinit[basicenv++] = mail; 2288*7c478bd9Sstevel@tonic-gate (void) strlcat(mail, pwd->pw_name, sizeof (mail)); 2289*7c478bd9Sstevel@tonic-gate #endif 2290*7c478bd9Sstevel@tonic-gate 2291*7c478bd9Sstevel@tonic-gate /* 2292*7c478bd9Sstevel@tonic-gate * Pick up locale environment variables, if any. 2293*7c478bd9Sstevel@tonic-gate */ 2294*7c478bd9Sstevel@tonic-gate lenvp = renvp; 2295*7c478bd9Sstevel@tonic-gate while (*lenvp != NULL) { 2296*7c478bd9Sstevel@tonic-gate j = 0; 2297*7c478bd9Sstevel@tonic-gate while (localeenv[j] != 0) { 2298*7c478bd9Sstevel@tonic-gate /* 2299*7c478bd9Sstevel@tonic-gate * locale_envmatch() returns 1 if 2300*7c478bd9Sstevel@tonic-gate * *lenvp is localenev[j] and valid. 2301*7c478bd9Sstevel@tonic-gate */ 2302*7c478bd9Sstevel@tonic-gate if (locale_envmatch(localeenv[j], *lenvp) == 1) { 2303*7c478bd9Sstevel@tonic-gate envinit[basicenv++] = *lenvp; 2304*7c478bd9Sstevel@tonic-gate break; 2305*7c478bd9Sstevel@tonic-gate } 2306*7c478bd9Sstevel@tonic-gate j++; 2307*7c478bd9Sstevel@tonic-gate } 2308*7c478bd9Sstevel@tonic-gate lenvp++; 2309*7c478bd9Sstevel@tonic-gate } 2310*7c478bd9Sstevel@tonic-gate 2311*7c478bd9Sstevel@tonic-gate /* 2312*7c478bd9Sstevel@tonic-gate * If '-p' flag, then try to pass on allowable environment 2313*7c478bd9Sstevel@tonic-gate * variables. Note that by processing this first, what is 2314*7c478bd9Sstevel@tonic-gate * passed on the final "login:" line may over-ride the invocation 2315*7c478bd9Sstevel@tonic-gate * values. XXX is this correct? 2316*7c478bd9Sstevel@tonic-gate */ 2317*7c478bd9Sstevel@tonic-gate if (pflag) { 2318*7c478bd9Sstevel@tonic-gate for (lenvp = renvp; *lenvp; lenvp++) { 2319*7c478bd9Sstevel@tonic-gate if (!legalenvvar(*lenvp)) { 2320*7c478bd9Sstevel@tonic-gate continue; 2321*7c478bd9Sstevel@tonic-gate } 2322*7c478bd9Sstevel@tonic-gate /* 2323*7c478bd9Sstevel@tonic-gate * If this isn't 'xxx=yyy', skip it. XXX 2324*7c478bd9Sstevel@tonic-gate */ 2325*7c478bd9Sstevel@tonic-gate if ((endptr = strchr(*lenvp, '=')) == NULL) { 2326*7c478bd9Sstevel@tonic-gate continue; 2327*7c478bd9Sstevel@tonic-gate } 2328*7c478bd9Sstevel@tonic-gate length = endptr + 1 - *lenvp; 2329*7c478bd9Sstevel@tonic-gate for (j = 0; j < basicenv; j++) { 2330*7c478bd9Sstevel@tonic-gate if (strncmp(envinit[j], *lenvp, length) == 0) { 2331*7c478bd9Sstevel@tonic-gate /* 2332*7c478bd9Sstevel@tonic-gate * Replace previously established value 2333*7c478bd9Sstevel@tonic-gate */ 2334*7c478bd9Sstevel@tonic-gate envinit[j] = *lenvp; 2335*7c478bd9Sstevel@tonic-gate break; 2336*7c478bd9Sstevel@tonic-gate } 2337*7c478bd9Sstevel@tonic-gate } 2338*7c478bd9Sstevel@tonic-gate if (j == basicenv) { 2339*7c478bd9Sstevel@tonic-gate /* 2340*7c478bd9Sstevel@tonic-gate * It's a new definition, so add it at the end. 2341*7c478bd9Sstevel@tonic-gate */ 2342*7c478bd9Sstevel@tonic-gate envinit[basicenv++] = *lenvp; 2343*7c478bd9Sstevel@tonic-gate } 2344*7c478bd9Sstevel@tonic-gate } 2345*7c478bd9Sstevel@tonic-gate } 2346*7c478bd9Sstevel@tonic-gate 2347*7c478bd9Sstevel@tonic-gate /* 2348*7c478bd9Sstevel@tonic-gate * Add in all the environment variables picked up from the 2349*7c478bd9Sstevel@tonic-gate * argument list to "login" or from the user response to the 2350*7c478bd9Sstevel@tonic-gate * "login" request, if any. 2351*7c478bd9Sstevel@tonic-gate */ 2352*7c478bd9Sstevel@tonic-gate 2353*7c478bd9Sstevel@tonic-gate if (envp == NULL) 2354*7c478bd9Sstevel@tonic-gate goto switch_env; /* done */ 2355*7c478bd9Sstevel@tonic-gate 2356*7c478bd9Sstevel@tonic-gate for (j = 0, k = 0, l_index = 0; 2357*7c478bd9Sstevel@tonic-gate *envp != NULL && j < (MAXARGS-1); 2358*7c478bd9Sstevel@tonic-gate j++, envp++) { 2359*7c478bd9Sstevel@tonic-gate 2360*7c478bd9Sstevel@tonic-gate /* 2361*7c478bd9Sstevel@tonic-gate * Scan each string provided. If it doesn't have the 2362*7c478bd9Sstevel@tonic-gate * format xxx=yyy, then add the string "Ln=" to the beginning. 2363*7c478bd9Sstevel@tonic-gate */ 2364*7c478bd9Sstevel@tonic-gate if ((endptr = strchr(*envp, '=')) == NULL) { 2365*7c478bd9Sstevel@tonic-gate /* 2366*7c478bd9Sstevel@tonic-gate * This much to be malloc'd: 2367*7c478bd9Sstevel@tonic-gate * strlen(*envp) + 1 char for 'L' + 2368*7c478bd9Sstevel@tonic-gate * MAXARGSWIDTH + 1 char for '=' + 1 for null char; 2369*7c478bd9Sstevel@tonic-gate * 2370*7c478bd9Sstevel@tonic-gate * total = strlen(*envp) + MAXARGSWIDTH + 3 2371*7c478bd9Sstevel@tonic-gate */ 2372*7c478bd9Sstevel@tonic-gate int total = strlen(*envp) + MAXARGSWIDTH + 3; 2373*7c478bd9Sstevel@tonic-gate envinit[basicenv+k] = malloc(total); 2374*7c478bd9Sstevel@tonic-gate if (envinit[basicenv+k] == NULL) { 2375*7c478bd9Sstevel@tonic-gate (void) printf("%s: malloc failed\n", PROG_NAME); 2376*7c478bd9Sstevel@tonic-gate login_exit(1); 2377*7c478bd9Sstevel@tonic-gate } 2378*7c478bd9Sstevel@tonic-gate (void) snprintf(envinit[basicenv+k], total, "L%d=%s", 2379*7c478bd9Sstevel@tonic-gate l_index, *envp); 2380*7c478bd9Sstevel@tonic-gate 2381*7c478bd9Sstevel@tonic-gate k++; 2382*7c478bd9Sstevel@tonic-gate l_index++; 2383*7c478bd9Sstevel@tonic-gate } else { 2384*7c478bd9Sstevel@tonic-gate if (!legalenvvar(*envp)) { /* this env var permited? */ 2385*7c478bd9Sstevel@tonic-gate continue; 2386*7c478bd9Sstevel@tonic-gate } else { 2387*7c478bd9Sstevel@tonic-gate 2388*7c478bd9Sstevel@tonic-gate /* 2389*7c478bd9Sstevel@tonic-gate * Check to see whether this string replaces 2390*7c478bd9Sstevel@tonic-gate * any previously defined string 2391*7c478bd9Sstevel@tonic-gate */ 2392*7c478bd9Sstevel@tonic-gate for (i = 0, length = endptr + 1 - *envp; 2393*7c478bd9Sstevel@tonic-gate i < basicenv + k; i++) { 2394*7c478bd9Sstevel@tonic-gate if (strncmp(*envp, envinit[i], length) 2395*7c478bd9Sstevel@tonic-gate == 0) { 2396*7c478bd9Sstevel@tonic-gate envinit[i] = *envp; 2397*7c478bd9Sstevel@tonic-gate break; 2398*7c478bd9Sstevel@tonic-gate } 2399*7c478bd9Sstevel@tonic-gate } 2400*7c478bd9Sstevel@tonic-gate 2401*7c478bd9Sstevel@tonic-gate /* 2402*7c478bd9Sstevel@tonic-gate * If it doesn't, place it at the end of 2403*7c478bd9Sstevel@tonic-gate * environment array. 2404*7c478bd9Sstevel@tonic-gate */ 2405*7c478bd9Sstevel@tonic-gate if (i == basicenv+k) { 2406*7c478bd9Sstevel@tonic-gate envinit[basicenv+k] = *envp; 2407*7c478bd9Sstevel@tonic-gate k++; 2408*7c478bd9Sstevel@tonic-gate } 2409*7c478bd9Sstevel@tonic-gate } 2410*7c478bd9Sstevel@tonic-gate } 2411*7c478bd9Sstevel@tonic-gate } /* for (j = 0 ... ) */ 2412*7c478bd9Sstevel@tonic-gate 2413*7c478bd9Sstevel@tonic-gate switch_env: 2414*7c478bd9Sstevel@tonic-gate /* 2415*7c478bd9Sstevel@tonic-gate * Switch to the new environment. 2416*7c478bd9Sstevel@tonic-gate */ 2417*7c478bd9Sstevel@tonic-gate environ = envinit; 2418*7c478bd9Sstevel@tonic-gate } 2419*7c478bd9Sstevel@tonic-gate 2420*7c478bd9Sstevel@tonic-gate /* 2421*7c478bd9Sstevel@tonic-gate * print_banner - Print the banner at start up 2422*7c478bd9Sstevel@tonic-gate * Do not turn on DOBANNER ifdef. This is not 2423*7c478bd9Sstevel@tonic-gate * relevant to SunOS. 2424*7c478bd9Sstevel@tonic-gate */ 2425*7c478bd9Sstevel@tonic-gate 2426*7c478bd9Sstevel@tonic-gate static void 2427*7c478bd9Sstevel@tonic-gate print_banner(void) 2428*7c478bd9Sstevel@tonic-gate { 2429*7c478bd9Sstevel@tonic-gate #ifdef DOBANNER 2430*7c478bd9Sstevel@tonic-gate uname(&un); 2431*7c478bd9Sstevel@tonic-gate #if i386 2432*7c478bd9Sstevel@tonic-gate (void) printf("UNIX System V/386 Release %s\n%s\n" 2433*7c478bd9Sstevel@tonic-gate "Copyright (C) 1984, 1986, 1987, 1988 AT&T\n" 2434*7c478bd9Sstevel@tonic-gate "Copyright (C) 1987, 1988 Microsoft Corp.\nAll Rights Reserved\n", 2435*7c478bd9Sstevel@tonic-gate un.release, un.nodename); 2436*7c478bd9Sstevel@tonic-gate #elif sun 2437*7c478bd9Sstevel@tonic-gate (void) printf("SunOS Release %s Sun Microsystems %s\n%s\n" 2438*7c478bd9Sstevel@tonic-gate "Copyright (c) 1984, 1986, 1987, 1988 AT&T\n" 2439*7c478bd9Sstevel@tonic-gate "Copyright (c) 1988, 1989, 1990, 1991 Sun Microsystems\n" 2440*7c478bd9Sstevel@tonic-gate "All Rights Reserved\n", 2441*7c478bd9Sstevel@tonic-gate un.release, un.machine, un.nodename); 2442*7c478bd9Sstevel@tonic-gate #else 2443*7c478bd9Sstevel@tonic-gate (void) printf("UNIX System V Release %s AT&T %s\n%s\n" 2444*7c478bd9Sstevel@tonic-gate "Copyright (c) 1984, 1986, 1987, 1988 AT&T\nAll Rights Reserved\n", 2445*7c478bd9Sstevel@tonic-gate un.release, un.machine, un.nodename); 2446*7c478bd9Sstevel@tonic-gate #endif /* i386 */ 2447*7c478bd9Sstevel@tonic-gate #endif /* DOBANNER */ 2448*7c478bd9Sstevel@tonic-gate } 2449*7c478bd9Sstevel@tonic-gate 2450*7c478bd9Sstevel@tonic-gate /* 2451*7c478bd9Sstevel@tonic-gate * display_last_login_time - Advise the user the time and date 2452*7c478bd9Sstevel@tonic-gate * that this login-id was last used. 2453*7c478bd9Sstevel@tonic-gate */ 2454*7c478bd9Sstevel@tonic-gate 2455*7c478bd9Sstevel@tonic-gate static void 2456*7c478bd9Sstevel@tonic-gate display_last_login_time(void) 2457*7c478bd9Sstevel@tonic-gate { 2458*7c478bd9Sstevel@tonic-gate if (lastlogok) { 2459*7c478bd9Sstevel@tonic-gate (void) printf("Last login: %.*s ", 24-5, ctime(&ll.ll_time)); 2460*7c478bd9Sstevel@tonic-gate 2461*7c478bd9Sstevel@tonic-gate if (*ll.ll_host != '\0') 2462*7c478bd9Sstevel@tonic-gate (void) printf("from %.*s\n", sizeof (ll.ll_host), 2463*7c478bd9Sstevel@tonic-gate ll.ll_host); 2464*7c478bd9Sstevel@tonic-gate else 2465*7c478bd9Sstevel@tonic-gate (void) printf("on %.*s\n", sizeof (ll.ll_line), 2466*7c478bd9Sstevel@tonic-gate ll.ll_line); 2467*7c478bd9Sstevel@tonic-gate } 2468*7c478bd9Sstevel@tonic-gate } 2469*7c478bd9Sstevel@tonic-gate 2470*7c478bd9Sstevel@tonic-gate /* 2471*7c478bd9Sstevel@tonic-gate * exec_the_shell - invoke the specified shell or start up program 2472*7c478bd9Sstevel@tonic-gate */ 2473*7c478bd9Sstevel@tonic-gate 2474*7c478bd9Sstevel@tonic-gate static void 2475*7c478bd9Sstevel@tonic-gate exec_the_shell(void) 2476*7c478bd9Sstevel@tonic-gate { 2477*7c478bd9Sstevel@tonic-gate char *endptr; 2478*7c478bd9Sstevel@tonic-gate int i; 2479*7c478bd9Sstevel@tonic-gate 2480*7c478bd9Sstevel@tonic-gate (void) strlcat(minusnam, basename(pwd->pw_shell), 2481*7c478bd9Sstevel@tonic-gate sizeof (minusnam)); 2482*7c478bd9Sstevel@tonic-gate 2483*7c478bd9Sstevel@tonic-gate /* 2484*7c478bd9Sstevel@tonic-gate * Exec the shell 2485*7c478bd9Sstevel@tonic-gate */ 2486*7c478bd9Sstevel@tonic-gate (void) execl(pwd->pw_shell, minusnam, (char *)0); 2487*7c478bd9Sstevel@tonic-gate 2488*7c478bd9Sstevel@tonic-gate /* 2489*7c478bd9Sstevel@tonic-gate * pwd->pw_shell was not an executable object file, maybe it 2490*7c478bd9Sstevel@tonic-gate * is a shell proceedure or a command line with arguments. 2491*7c478bd9Sstevel@tonic-gate * If so, turn off the SHELL= environment variable. 2492*7c478bd9Sstevel@tonic-gate */ 2493*7c478bd9Sstevel@tonic-gate for (i = 0; envinit[i] != NULL; ++i) { 2494*7c478bd9Sstevel@tonic-gate if ((envinit[i] == shell) && 2495*7c478bd9Sstevel@tonic-gate ((endptr = strchr(shell, '=')) != NULL)) 2496*7c478bd9Sstevel@tonic-gate (*++endptr) = '\0'; 2497*7c478bd9Sstevel@tonic-gate } 2498*7c478bd9Sstevel@tonic-gate 2499*7c478bd9Sstevel@tonic-gate if (access(pwd->pw_shell, R_OK|X_OK) == 0) { 2500*7c478bd9Sstevel@tonic-gate (void) execl(SHELL, "sh", pwd->pw_shell, (char *)0); 2501*7c478bd9Sstevel@tonic-gate (void) execl(SHELL2, "sh", pwd->pw_shell, (char *)0); 2502*7c478bd9Sstevel@tonic-gate } 2503*7c478bd9Sstevel@tonic-gate 2504*7c478bd9Sstevel@tonic-gate (void) printf("No shell\n"); 2505*7c478bd9Sstevel@tonic-gate } 2506*7c478bd9Sstevel@tonic-gate 2507*7c478bd9Sstevel@tonic-gate /* 2508*7c478bd9Sstevel@tonic-gate * login_exit - Call exit() and terminate. 2509*7c478bd9Sstevel@tonic-gate * This function is here for PAM so cleanup can 2510*7c478bd9Sstevel@tonic-gate * be done before the process exits. 2511*7c478bd9Sstevel@tonic-gate */ 2512*7c478bd9Sstevel@tonic-gate static void 2513*7c478bd9Sstevel@tonic-gate login_exit(int exit_code) 2514*7c478bd9Sstevel@tonic-gate { 2515*7c478bd9Sstevel@tonic-gate if (pamh) 2516*7c478bd9Sstevel@tonic-gate (void) pam_end(pamh, PAM_ABORT); 2517*7c478bd9Sstevel@tonic-gate 2518*7c478bd9Sstevel@tonic-gate if (audit_error) 2519*7c478bd9Sstevel@tonic-gate audit_failure(get_audit_id(), audit_error, 2520*7c478bd9Sstevel@tonic-gate pwd, remote_host, ttyn, zone_name); 2521*7c478bd9Sstevel@tonic-gate 2522*7c478bd9Sstevel@tonic-gate exit(exit_code); 2523*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2524*7c478bd9Sstevel@tonic-gate } 2525*7c478bd9Sstevel@tonic-gate 2526*7c478bd9Sstevel@tonic-gate /* 2527*7c478bd9Sstevel@tonic-gate * Check if lenv and penv matches or not. 2528*7c478bd9Sstevel@tonic-gate */ 2529*7c478bd9Sstevel@tonic-gate static int 2530*7c478bd9Sstevel@tonic-gate locale_envmatch(char *lenv, char *penv) 2531*7c478bd9Sstevel@tonic-gate { 2532*7c478bd9Sstevel@tonic-gate while ((*lenv == *penv) && *lenv && *penv != '=') { 2533*7c478bd9Sstevel@tonic-gate lenv++; 2534*7c478bd9Sstevel@tonic-gate penv++; 2535*7c478bd9Sstevel@tonic-gate } 2536*7c478bd9Sstevel@tonic-gate 2537*7c478bd9Sstevel@tonic-gate /* 2538*7c478bd9Sstevel@tonic-gate * '/' is eliminated for security reason. 2539*7c478bd9Sstevel@tonic-gate */ 2540*7c478bd9Sstevel@tonic-gate if (*lenv == '\0' && *penv == '=' && *(penv + 1) != '/') 2541*7c478bd9Sstevel@tonic-gate return (1); 2542*7c478bd9Sstevel@tonic-gate return (0); 2543*7c478bd9Sstevel@tonic-gate } 2544*7c478bd9Sstevel@tonic-gate 2545*7c478bd9Sstevel@tonic-gate static int 2546*7c478bd9Sstevel@tonic-gate is_number(char *ptr) 2547*7c478bd9Sstevel@tonic-gate { 2548*7c478bd9Sstevel@tonic-gate while (*ptr != '\0') { 2549*7c478bd9Sstevel@tonic-gate if (!isdigit(*ptr)) 2550*7c478bd9Sstevel@tonic-gate return (0); 2551*7c478bd9Sstevel@tonic-gate ptr++; 2552*7c478bd9Sstevel@tonic-gate } 2553*7c478bd9Sstevel@tonic-gate return (1); 2554*7c478bd9Sstevel@tonic-gate } 2555