login.c 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: login.c /main/8 1996/10/29 13:49:30 drk $ */
  24. /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  25. /* All Rights Reserved */
  26. /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
  27. /* The copyright notice above does not evidence any */
  28. /* actual or intended publication of such source code. */
  29. #ident "@(#)login.c 1.63 96/02/15 SMI" /* SVr4.0 1.43.6.26 */
  30. /*
  31. PROPRIETARY NOTICE(Combined)
  32. This source code is unpublished proprietary information
  33. constituting, or derived under license from AT&T's UNIX(r) System V.
  34. In addition, portions of such source code were derived from Berkeley
  35. 4.3 BSD under license from the Regents of the University of
  36. California.
  37. Copyright Notice
  38. Notice of copyright on this source code product does not indicate
  39. publication.
  40. (c) 1986, 1987, 1988, 1989, 1990, 1991, 1992 Sun Microsystems, Inc
  41. (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T.
  42. All rights reserved.
  43. *******************************************************************
  44. */
  45. /* Copyright (c) 1987, 1988 Microsoft Corporation */
  46. /* All Rights Reserved */
  47. /* This Module contains Proprietary Information of Microsoft */
  48. /* Corporation and should be treated as Confidential. */
  49. /*
  50. * Usage: login [ -d device ] [ name ] [ environment args ]
  51. *
  52. *
  53. */
  54. /*
  55. *
  56. * *** Header Files ***
  57. *
  58. *
  59. */
  60. #include <sys/types.h>
  61. #include <sys/param.h>
  62. #include <unistd.h> /* For logfile locking */
  63. #include <signal.h>
  64. #include <stdio.h>
  65. #include <sys/stat.h>
  66. #include <string.h>
  67. #include <deflt.h>
  68. #include <grp.h>
  69. #include <fcntl.h>
  70. #include <lastlog.h>
  71. #include <termio.h>
  72. #include <utmpx.h>
  73. #include <dirent.h>
  74. #include <stdlib.h>
  75. #include <wait.h>
  76. #include <errno.h>
  77. #include <ctype.h>
  78. #include <syslog.h>
  79. #include <ulimit.h>
  80. #include <libgen.h>
  81. #include <security/pam_appl.h>
  82. /*
  83. *
  84. * *** Defines, Macros, and String Constants ***
  85. *
  86. *
  87. */
  88. #define ISSUEFILE "/etc/issue" /* file to print before prompt */
  89. #define NOLOGIN "/etc/nologin" /* file to lock users out during shutdown */
  90. /*
  91. * These need to be defined for UTMP management.
  92. * If we add in the utility functions later, we
  93. * can remove them.
  94. */
  95. #define __UPDATE_ENTRY 1
  96. #define __LOGIN 2
  97. /*
  98. * Intervals to sleep after failed login
  99. */
  100. #ifndef SLEEPTIME
  101. #define SLEEPTIME 4 /* sleeptime before login incorrect msg */
  102. #endif
  103. static int Sleeptime = SLEEPTIME;
  104. /*
  105. * seconds login disabled after allowable number of unsuccessful attempts
  106. */
  107. #ifndef DISABLETIME
  108. #define DISABLETIME 20
  109. #endif
  110. #define MAXTRYS 5
  111. /*
  112. * Login logging support
  113. */
  114. #define LOGINLOG "/var/adm/loginlog" /* login log file */
  115. #define LNAME_SIZE 20 /* size of logged logname */
  116. #define TTYN_SIZE 15 /* size of logged tty name */
  117. #define TIME_SIZE 30 /* size of logged time string */
  118. #define ENT_SIZE (LNAME_SIZE + TTYN_SIZE + TIME_SIZE + 3)
  119. #define L_WAITTIME 5 /* waittime for log file to unlock */
  120. #define LOGTRYS 10 /* depth of 'try' logging */
  121. /*
  122. * String manipulation macros: SCPYN, EQN and ENVSTRNCAT
  123. */
  124. #define SCPYN(a, b) (void) strncpy(a, b, sizeof (a))
  125. #define EQN(a, b) (strncmp(a, b, sizeof (a)-1) == 0)
  126. #define ENVSTRNCAT(to, from) {int deflen; deflen = strlen(to); \
  127. (void) strncpy((to)+ deflen, (from), sizeof (to) - (1 + deflen)); }
  128. /*
  129. * Other macros
  130. */
  131. #define NMAX sizeof (utmp.ut_name)
  132. #define HMAX sizeof (utmp.ut_host)
  133. #define min(a, b) (((a) < (b)) ? (a) : (b))
  134. /*
  135. * Various useful files and string constants
  136. */
  137. #define SHELL "/usr/bin/sh"
  138. #define SHELL2 "/sbin/sh"
  139. #define SUBLOGIN "<!sublogin>"
  140. #define LASTLOG "/var/adm/lastlog"
  141. #define PROG_NAME "login"
  142. #define HUSHLOGIN ".hushlogin"
  143. /*
  144. * Array and Buffer sizes
  145. */
  146. #define PBUFSIZE 8 /* max significant characters in a password */
  147. #define MAXARGS 63
  148. #define MAXENV 1024
  149. #define MAXLINE 2048
  150. /*
  151. * Miscellaneous constants
  152. */
  153. #define ROOTUID 0
  154. #define ERROR 1
  155. #define OK 0
  156. #define LOG_ERROR 1
  157. #define DONT_LOG_ERROR 0
  158. #define TRUE 1
  159. #define FALSE 0
  160. /*
  161. * Counters for counting the number of failed login attempts
  162. */
  163. static int trys = 0;
  164. /*
  165. * Externs a plenty
  166. */
  167. extern int defopen(char *filename);
  168. extern int getsecretkey();
  169. /*
  170. * BSM hooks
  171. */
  172. extern int audit_login_save_flags(int rflag, int hflag);
  173. extern int audit_login_save_host(char *host);
  174. extern int audit_login_save_ttyn(char *ttyn);
  175. extern int audit_login_save_port(void);
  176. extern int audit_login_success(void);
  177. extern int audit_login_save_pw(struct passwd *pwd);
  178. extern int audit_login_bad_pw(void);
  179. extern int audit_login_maxtrys(void);
  180. extern int audit_login_not_console(void);
  181. extern int audit_login_bad_dialup(void);
  182. extern int audit_login_maxtrys(void);
  183. /*
  184. * utmp file variables
  185. */
  186. static struct utmpx utmp;
  187. /*
  188. * The current user name
  189. */
  190. static char user_name[64];
  191. static char minusnam[16] = "-";
  192. /*
  193. * locale environments to be passed to shells.
  194. */
  195. static char *localeenv[] = {
  196. "LANG",
  197. "LC_CTYPE", "LC_NUMERIC", "LC_TIME", "LC_COLLATE",
  198. "LC_MONETARY", "LC_MESSAGES", "LC_ALL", 0};
  199. static int locale_envmatch(char *lenv, char *penv);
  200. /*
  201. * Environment variable support
  202. */
  203. static char shell[256] = { "SHELL=" };
  204. static char home[MAXPATHLEN] = { "HOME=" };
  205. static char term[64] = { "TERM=" };
  206. static char logname[30] = { "LOGNAME=" };
  207. static char timez[100] = { "TZ=" };
  208. static char hertz[10] = { "HZ=" };
  209. static char path[MAXPATHLEN] = { "PATH=" };
  210. static char *newenv[10+MAXARGS] =
  211. {home, path, logname, hertz, term, 0, 0};
  212. static char **envinit = newenv;
  213. static int basicenv;
  214. static char envblk[MAXENV];
  215. static char *zero = (char *)0;
  216. static char **envp;
  217. static char krb5ccname[256] = { "KRB5CCNAME=" };
  218. static char krb4ccname[256] = { "KRBTKFILE=" };
  219. #ifndef NO_MAIL
  220. static char mail[30] = { "MAIL=/var/mail/" };
  221. #endif
  222. extern char **environ;
  223. char inputline[MAXLINE];
  224. /*
  225. * Strings used to prompt the user.
  226. */
  227. static char loginmsg[] = "login: ";
  228. static char passwdmsg[] = "Password:";
  229. static char incorrectmsg[] = "Login incorrect\n";
  230. /*
  231. * Password file support
  232. */
  233. static struct passwd *pwd;
  234. static char remote_host[HMAX];
  235. /*
  236. * Illegal passwd entries.
  237. */
  238. static struct passwd nouser = { "", "no:password", ~ROOTUID };
  239. /*
  240. * Log file support
  241. */
  242. static char *log_entry[LOGTRYS];
  243. static int writelog = 0;
  244. static int lastlogok = 0;
  245. static struct lastlog ll;
  246. static int dosyslog = 0;
  247. /*
  248. * Default file toggles
  249. */
  250. static char *Pndefault = "/etc/default/login";
  251. static char *Altshell = NULL;
  252. static char *Console = NULL;
  253. static char *Passreq = NULL;
  254. #define DEFUMASK 022
  255. static mode_t Umask = DEFUMASK;
  256. static char *Def_tz = NULL;
  257. static char *tmp_tz = NULL;
  258. static char *Def_hertz = NULL;
  259. #define SET_FSIZ 2 /* ulimit() command arg */
  260. static long Def_ulimit = 0;
  261. #define MAX_TIMEOUT (15 * 60)
  262. #define DEF_TIMEOUT (5 * 60)
  263. static unsigned Def_timeout = DEF_TIMEOUT;
  264. static char *Def_path = NULL;
  265. static char *Def_supath = NULL;
  266. #define DEF_PATH "/usr/bin:" /* same as PATH */
  267. #define DEF_SUPATH "/usr/sbin:/usr/bin" /* same as ROOTPATH */
  268. /*
  269. * ttyprompt will point to the environment variable TTYPROMPT.
  270. * TTYPROMPT is set by ttymon if ttymon already wrote out the prompt.
  271. */
  272. static char *ttyprompt = NULL;
  273. static char *ttyn = NULL;
  274. static struct group *grpstr;
  275. static char *ttygrp = "tty";
  276. static char *progname = PROG_NAME;
  277. /*
  278. * Pass inherited environment. Used by telnetd in support of the telnet
  279. * ENVIRON option.
  280. */
  281. static int pflag;
  282. /*
  283. * Remote login support
  284. */
  285. static int hflag, rflag;
  286. static char rusername[NMAX+1], lusername[NMAX+1];
  287. static char terminal[MAXPATHLEN];
  288. /*
  289. * Pre-authentication flag support
  290. */
  291. static int fflag;
  292. static int login_conv(int num_msg, struct pam_message **msg,
  293. struct pam_response **response, void *appdata_ptr);
  294. static struct pam_conv pam_conv = {login_conv, NULL};
  295. static pam_handle_t *pamh; /* Authentication handle */
  296. /*
  297. * Function declarations
  298. */
  299. static void turn_on_logging(void);
  300. static void defaults(void);
  301. static void usage(void);
  302. static void process_rlogin(void);
  303. static void login_authenticate();
  304. static void setup_credentials(void);
  305. static void adjust_nice(void);
  306. static void update_utmp_entry(int sublogin);
  307. static void establish_user_environment(char **renvp);
  308. static void print_banner(void);
  309. static void display_last_login_time(void);
  310. static void exec_the_shell(void);
  311. static int process_chroot_logins(void);
  312. static int chdir_to_dir_root(void);
  313. static void chdir_to_dir_user(void);
  314. static void logindevperm(char *, uid_t, gid_t);
  315. static void dir_dev_acc(char *, uid_t, gid_t, mode_t, char *);
  316. static void check_log(void);
  317. static void validate_account();
  318. static void doremoteterm(char *term);
  319. static int get_options(int argc, char *argv[]);
  320. static void uppercaseterm(char *strp);
  321. static void getstr(char *buf, int cnt, char *err);
  322. static int legalenvvar(char *s);
  323. static void check_for_root_user(void);
  324. static void check_for_dueling_unix(char inputline[]);
  325. static void get_user_name(void);
  326. static void login_exit(int exit_code);
  327. static int logins_disabled(char *user_name);
  328. static void log_bad_attempts(void);
  329. /*
  330. * *** main ***
  331. *
  332. * The primary flow of control is directed in this routine.
  333. * Control moves in line from top to bottom calling subfunctions
  334. * which perform the bulk of the work. Many of these calls exit
  335. * when a fatal error is encountered and do not return to main.
  336. *
  337. *
  338. */
  339. void
  340. main(int argc, char *argv[], char **renvp)
  341. {
  342. int sublogin;
  343. /*
  344. * Set up Defaults and flags
  345. */
  346. defaults();
  347. /*
  348. * Set up default umask
  349. */
  350. if (Umask > ((mode_t) 0777))
  351. Umask = DEFUMASK;
  352. (void) umask(Umask);
  353. /*
  354. * Set up default timeouts and delays
  355. */
  356. if (Def_timeout > MAX_TIMEOUT)
  357. Def_timeout = MAX_TIMEOUT;
  358. if (Sleeptime < 0 || Sleeptime > 5)
  359. Sleeptime = SLEEPTIME;
  360. (void) alarm(Def_timeout);
  361. /*
  362. * Ignore SIGQUIT and SIGINT and set nice to 0
  363. */
  364. (void) signal(SIGQUIT, SIG_IGN);
  365. (void) signal(SIGINT, SIG_IGN);
  366. (void) nice(0);
  367. /*
  368. * Set flag to disable the pid check if you find that you are
  369. * a subsystem login.
  370. */
  371. sublogin = 0;
  372. if (*renvp && strcmp(*renvp, SUBLOGIN) == 0)
  373. sublogin = 1;
  374. /*
  375. * Parse Arguments
  376. */
  377. if (get_options(argc, argv) == -1) {
  378. usage();
  379. login_exit(1);
  380. }
  381. audit_login_save_flags(rflag, hflag);
  382. audit_login_save_host(remote_host);
  383. /*
  384. * if devicename is not passed as argument, call ttyname(0)
  385. */
  386. if (ttyn == NULL) {
  387. ttyn = ttyname(0);
  388. if (ttyn == NULL)
  389. ttyn = "/dev/???";
  390. }
  391. audit_login_save_ttyn(ttyn);
  392. audit_login_save_port();
  393. /*
  394. * Call pam_start to initiate a PAM authentication operation
  395. */
  396. if ((pam_start(progname, user_name, &pam_conv, &pamh))
  397. != PAM_SUCCESS)
  398. login_exit(1);
  399. if ((pam_set_item(pamh, PAM_TTY, ttyn)) != PAM_SUCCESS) {
  400. login_exit(1);
  401. }
  402. if ((pam_set_item(pamh, PAM_RHOST, remote_host)) != PAM_SUCCESS) {
  403. login_exit(1);
  404. }
  405. /*
  406. * Open the log file which contains a record of successful and failed
  407. * login attempts
  408. */
  409. turn_on_logging();
  410. /*
  411. * say "hi" to syslogd ..
  412. */
  413. openlog("login", 0, LOG_AUTH);
  414. /*
  415. * Do special processing for -r (rlogin) flag
  416. */
  417. if (rflag)
  418. process_rlogin();
  419. /*
  420. * validate user
  421. */
  422. /* we are already authenticated. fill in what we must, then continue */
  423. if (fflag) {
  424. if (pwd = getpwnam(user_name))
  425. audit_login_save_pw(pwd);
  426. else {
  427. audit_login_bad_pw();
  428. log_bad_attempts();
  429. login_exit(1);
  430. }
  431. } else {
  432. /*
  433. * Perform the primary login authentication activity.
  434. */
  435. login_authenticate();
  436. }
  437. /* change root login, then we exec another login and try again */
  438. if (process_chroot_logins() != OK)
  439. login_exit(1);
  440. /*
  441. * If root login and not on system console then call exit(2)
  442. */
  443. check_for_root_user();
  444. /*
  445. * Check to see if a shutdown is in progress, if it is and
  446. * we are not root then throw the user off the system
  447. */
  448. if (logins_disabled(user_name) == TRUE)
  449. login_exit(1);
  450. if (pwd->pw_uid == 0) {
  451. if (Def_supath != NULL)
  452. Def_path = Def_supath;
  453. else
  454. Def_path = DEF_SUPATH;
  455. }
  456. /*
  457. * Check account expiration and passwd aging
  458. */
  459. validate_account();
  460. /*
  461. * We only get here if we've been authenticated.
  462. */
  463. update_utmp_entry(sublogin);
  464. /*
  465. * Now we set up the environment for the new user, which includes
  466. * the users ulimit, nice value, ownership of this tty, uid, gid,
  467. * and environment variables.
  468. */
  469. if (Def_ulimit > 0L && ulimit(SET_FSIZ, Def_ulimit) < 0L)
  470. (void) printf("Could not set ULIMIT to %ld\n", Def_ulimit);
  471. /*
  472. * Set mode to r/w user & w group, owner to user and group to tty
  473. */
  474. (void) chmod(ttyn, S_IRUSR|S_IWUSR|S_IWGRP);
  475. if ((grpstr = getgrnam(ttygrp)) == NULL)
  476. (void) chown(ttyn, pwd->pw_uid, pwd->pw_gid);
  477. else
  478. (void) chown(ttyn, pwd->pw_uid, grpstr->gr_gid);
  479. logindevperm(ttyn, pwd->pw_uid, pwd->pw_gid);
  480. adjust_nice(); /* passwd file can specify nice value */
  481. /*
  482. * Record successful login and fork process that records logout.
  483. * We have to do this before setting credentials because we need
  484. * to be root in order do a setaudit() and an audit().
  485. */
  486. audit_login_success();
  487. setup_credentials(); /* Set uid/gid - exits on failure */
  488. pam_end(pamh, PAM_SUCCESS); /* Done using PAM */
  489. /*
  490. * Set up the basic environment for the exec. This includes
  491. * HOME, PATH, LOGNAME, SHELL, TERM, TZ, HZ, and MAIL.
  492. */
  493. chdir_to_dir_user();
  494. establish_user_environment(renvp);
  495. if (pwd->pw_uid == 0)
  496. if (remote_host[0] && dosyslog)
  497. syslog(LOG_NOTICE, "ROOT LOGIN %s FROM %.*s",
  498. ttyn, HMAX, remote_host);
  499. else if (dosyslog)
  500. syslog(LOG_NOTICE, "ROOT LOGIN %s", ttyn);
  501. closelog();
  502. (void) signal(SIGQUIT, SIG_DFL);
  503. (void) signal(SIGINT, SIG_DFL);
  504. /*
  505. * Display some useful information to the new user like the banner
  506. * and last login time if not a quiet login.
  507. */
  508. if (access(HUSHLOGIN, F_OK) != 0) {
  509. print_banner();
  510. display_last_login_time();
  511. }
  512. /*
  513. * Now fire off the shell of choice
  514. */
  515. exec_the_shell();
  516. /*
  517. * All done
  518. */
  519. login_exit(1);
  520. /* NOTREACHED */
  521. }
  522. /*
  523. * *** Utility functions ***
  524. */
  525. /*
  526. * donothing & catch - Signal catching functions
  527. */
  528. /*ARGSUSED*/
  529. static void
  530. donothing(int sig)
  531. {
  532. if (pamh)
  533. pam_end(pamh, PAM_ABORT);
  534. }
  535. #ifdef notdef
  536. static int intrupt;
  537. /*ARGSUSED*/
  538. static void
  539. catch(int sig)
  540. {
  541. ++intrupt;
  542. }
  543. #endif
  544. /*
  545. * *** Bad login logging support ***
  546. */
  547. /*
  548. * badlogin() - log to the log file 'trys'
  549. * unsuccessful attempts
  550. */
  551. static void
  552. badlogin(void)
  553. {
  554. int retval, count1, fildes;
  555. /*
  556. * Tries to open the log file. If succeed, lock it and write
  557. * in the failed attempts
  558. */
  559. if ((fildes = open(LOGINLOG, O_APPEND|O_WRONLY)) != -1) {
  560. (void) sigset(SIGALRM, donothing);
  561. (void) alarm(L_WAITTIME);
  562. retval = lockf(fildes, F_LOCK, 0L);
  563. (void) alarm(0);
  564. (void) sigset(SIGALRM, SIG_DFL);
  565. if (retval == 0) {
  566. for (count1 = 0; count1 < trys; count1++)
  567. (void) write(fildes, log_entry[count1],
  568. (unsigned) strlen(log_entry[count1]));
  569. (void) lockf(fildes, F_ULOCK, 0L);
  570. }
  571. (void) close(fildes);
  572. }
  573. }
  574. /*
  575. * log_bad_attempts - log each bad login attempt - called from
  576. * login_authenticate. Exits when the maximum attempt
  577. * count is exceeded.
  578. */
  579. static void
  580. log_bad_attempts(void)
  581. {
  582. time_t timenow;
  583. if (writelog == 1 && trys < LOGTRYS) {
  584. (void) time(&timenow);
  585. (void) strncat(log_entry[trys], user_name, LNAME_SIZE);
  586. (void) strncat(log_entry[trys], ":", (size_t) 1);
  587. (void) strncat(log_entry[trys], ttyn, TTYN_SIZE);
  588. (void) strncat(log_entry[trys], ":", (size_t) 1);
  589. (void) strncat(log_entry[trys], ctime(&timenow), TIME_SIZE);
  590. trys++;
  591. }
  592. }
  593. /*
  594. * turn_on_logging - if the logfile exist, turn on attempt logging and
  595. * initialize the string storage area
  596. */
  597. static void
  598. turn_on_logging(void)
  599. {
  600. struct stat dbuf;
  601. int i;
  602. if (stat(LOGINLOG, &dbuf) == 0) {
  603. writelog = 1;
  604. for (i = 0; i < LOGTRYS; i++) {
  605. if (!(log_entry[i] = malloc((size_t) ENT_SIZE))) {
  606. writelog = 0;
  607. break;
  608. }
  609. *log_entry[i] = '\0';
  610. }
  611. }
  612. }
  613. /*
  614. * login_conv():
  615. * This is the conv (conversation) function called from
  616. * a PAM authentication module to print error messages
  617. * or garner information from the user.
  618. */
  619. static int
  620. login_conv(int num_msg, struct pam_message **msg,
  621. struct pam_response **response, void *appdata_ptr)
  622. {
  623. struct pam_message *m;
  624. struct pam_response *r;
  625. char *temp;
  626. int k, i;
  627. if (num_msg <= 0)
  628. return (PAM_CONV_ERR);
  629. *response = calloc(num_msg, sizeof (struct pam_response));
  630. if (*response == NULL)
  631. return (PAM_BUF_ERR);
  632. k = num_msg;
  633. m = *msg;
  634. r = *response;
  635. while (k--) {
  636. switch (m->msg_style) {
  637. case PAM_PROMPT_ECHO_OFF:
  638. temp = getpass(m->msg);
  639. if (temp != NULL) {
  640. r->resp = strdup(temp);
  641. if (r->resp == NULL) {
  642. /* free responses */
  643. r = *response;
  644. for (i = 0; i < num_msg; i++, r++) {
  645. if (r->resp)
  646. free(r->resp);
  647. }
  648. free(*response);
  649. *response = NULL;
  650. return (PAM_BUF_ERR);
  651. }
  652. }
  653. m++;
  654. r++;
  655. break;
  656. case PAM_PROMPT_ECHO_ON:
  657. if (m->msg != NULL)
  658. (void) fputs(m->msg, stdout);
  659. r->resp = calloc(1, PAM_MAX_RESP_SIZE);
  660. if (r->resp == NULL) {
  661. /* free responses */
  662. r = *response;
  663. for (i = 0; i < num_msg; i++, r++) {
  664. if (r->resp)
  665. free(r->resp);
  666. }
  667. free(*response);
  668. *response = NULL;
  669. return (PAM_BUF_ERR);
  670. }
  671. if (fgets(r->resp, PAM_MAX_RESP_SIZE-1, stdin)) {
  672. int len;
  673. r->resp[PAM_MAX_RESP_SIZE-1] = NULL;
  674. len = strlen(r->resp);
  675. if (r->resp[len-1] == '\n')
  676. r->resp[len-1] = '\0';
  677. } else {
  678. login_exit(1);
  679. }
  680. m++;
  681. r++;
  682. break;
  683. case PAM_ERROR_MSG:
  684. if (m->msg != NULL) {
  685. (void) fputs(m->msg, stderr);
  686. (void) fputs("\n", stderr);
  687. }
  688. m++;
  689. r++;
  690. break;
  691. case PAM_TEXT_INFO:
  692. if (m->msg != NULL) {
  693. (void) fputs(m->msg, stdout);
  694. (void) fputs("\n", stdout);
  695. }
  696. m++;
  697. r++;
  698. break;
  699. default:
  700. break;
  701. }
  702. }
  703. return (PAM_SUCCESS);
  704. }
  705. /*
  706. * verify_passwd - Checks the users password
  707. * Returns: OK if password check successful,
  708. * ERROR if password check fails.
  709. */
  710. static int
  711. verify_passwd()
  712. {
  713. int flags;
  714. int error;
  715. char *user;
  716. /*
  717. * PAM authenticates the user for us.
  718. */
  719. error = pam_authenticate(pamh, 0);
  720. /* get the user_name from the pam handle */
  721. pam_get_item(pamh, PAM_USER, (void**)&user);
  722. SCPYN(user_name, user);
  723. check_for_dueling_unix(user_name);
  724. if (error != PAM_SUCCESS) {
  725. /* something bad has happended - bye bye */
  726. if (error == PAM_ABORT) {
  727. audit_login_bad_pw();
  728. log_bad_attempts();
  729. (void) sleep(DISABLETIME);
  730. (void) printf(incorrectmsg);
  731. login_exit(1);
  732. }
  733. return (error);
  734. }
  735. if ((pwd = getpwnam(user_name)) == NULL) {
  736. audit_login_bad_pw();
  737. log_bad_attempts();
  738. return (PAM_USER_UNKNOWN);
  739. }
  740. audit_login_save_pw(pwd);
  741. return (error);
  742. }
  743. /*
  744. * quotec - Called by getargs
  745. */
  746. static int
  747. quotec(void)
  748. {
  749. register int c, i, num;
  750. switch (c = getc(stdin)) {
  751. case 'n':
  752. c = '\n';
  753. break;
  754. case 'r':
  755. c = '\r';
  756. break;
  757. case 'v':
  758. c = '\013';
  759. break;
  760. case 'b':
  761. c = '\b';
  762. break;
  763. case 't':
  764. c = '\t';
  765. break;
  766. case 'f':
  767. c = '\f';
  768. break;
  769. case '0':
  770. case '1':
  771. case '2':
  772. case '3':
  773. case '4':
  774. case '5':
  775. case '6':
  776. case '7':
  777. for (num = 0, i = 0; i < 3; i++) {
  778. num = num * 8 + (c - '0');
  779. if ((c = getc(stdin)) < '0' || c > '7')
  780. break;
  781. }
  782. (void) ungetc(c, stdin);
  783. c = num & 0377;
  784. break;
  785. default:
  786. break;
  787. }
  788. return (c);
  789. }
  790. /*
  791. * getargs - returns an input line. Exits if EOF encountered.
  792. */
  793. #define WHITESPACE 0
  794. #define ARGUMENT 1
  795. static char **
  796. getargs(char *in_line)
  797. {
  798. static char envbuf[MAXLINE];
  799. static char *args[MAXARGS];
  800. register char *ptr, **answer;
  801. register int c;
  802. int state;
  803. for (ptr = envbuf; ptr < &envbuf[sizeof (envbuf)]; /* cstyle */)
  804. *ptr++ = '\0';
  805. for (answer = args; answer < &args[MAXARGS]; /* cstyle */)
  806. *answer++ = (char *)NULL;
  807. for (ptr = envbuf, answer = &args[0], state = WHITESPACE;
  808. (c = getc(stdin)) != EOF; /* cstyle */) {
  809. *(in_line++) = c;
  810. switch (c) {
  811. case '\n':
  812. if (ptr == &envbuf[0])
  813. return ((char **)NULL);
  814. return (&args[0]);
  815. case ' ':
  816. case '\t':
  817. if (state == ARGUMENT) {
  818. *ptr++ = '\0';
  819. state = WHITESPACE;
  820. }
  821. break;
  822. case '\\':
  823. c = quotec();
  824. default:
  825. if (state == WHITESPACE) {
  826. *answer++ = ptr;
  827. state = ARGUMENT;
  828. }
  829. *ptr++ = c;
  830. }
  831. /*
  832. * If the buffer is full, force the next character to be read to
  833. * be a <newline>.
  834. */
  835. if (ptr == &envbuf[sizeof (envbuf)-1]) {
  836. (void) ungetc('\n', stdin);
  837. (void) putc('\n', stdout);
  838. }
  839. }
  840. /*
  841. * If we left loop because an EOF was received, exit immediately.
  842. */
  843. login_exit(0);
  844. /* NOTREACHED */
  845. }
  846. /*
  847. * get_user_name - Gets the user name either passed in, or from the
  848. * login: prompt.
  849. */
  850. static void
  851. get_user_name()
  852. {
  853. FILE *fp;
  854. int gotname = 0;
  855. if ((fp = fopen(ISSUEFILE, "r")) != NULL) {
  856. char *ptr, buffer[BUFSIZ];
  857. while ((ptr = fgets(buffer, sizeof (buffer),
  858. fp)) != NULL) {
  859. (void) fputs(ptr, stdout);
  860. }
  861. (void) fclose(fp);
  862. }
  863. /*
  864. * if TTYPROMPT is not set, use our own prompt
  865. * otherwise, use ttyprompt. We just set PAM_USER_PROMPT
  866. * and let the module do the prompting.
  867. */
  868. if ((ttyprompt == NULL) || (*ttyprompt == '\0'))
  869. (void) pam_set_item(pamh, PAM_USER_PROMPT, (void *)loginmsg);
  870. else
  871. (void) pam_set_item(pamh, PAM_USER_PROMPT, (void *)ttyprompt);
  872. envp = &zero; /* XXX: is this right? */
  873. }
  874. /*
  875. * Check_for_dueling_unix - Check to see if the another login is talking
  876. * to the line we've got open as a login port
  877. * Exits if we're talking to another unix system
  878. */
  879. static void
  880. check_for_dueling_unix(char *inputline)
  881. {
  882. if (EQN(loginmsg, inputline) || EQN(passwdmsg, inputline) ||
  883. EQN(incorrectmsg, inputline)) {
  884. (void) printf("Looking at a login line.\n");
  885. login_exit(8);
  886. }
  887. }
  888. /*
  889. * logins_disabled - if the file /etc/nologin exists and the user is not
  890. * root then do not permit them to login
  891. */
  892. static int
  893. logins_disabled(char *user_name)
  894. {
  895. FILE *nlfd;
  896. int c;
  897. if (!EQN("root", user_name) &&
  898. ((nlfd = fopen(NOLOGIN, "r")) != (FILE *)NULL)) {
  899. while ((c = getc(nlfd)) != EOF)
  900. putchar(c);
  901. (void) fflush(stdout);
  902. sleep(5);
  903. return (TRUE);
  904. }
  905. return (FALSE);
  906. }
  907. /*
  908. * check_for_root_user - Checks if we're getting a root login on the console
  909. * Exits if root login not on system console.
  910. *
  911. */
  912. static void
  913. check_for_root_user(void)
  914. {
  915. if (pwd->pw_uid == 0) {
  916. if ((Console != NULL) && (strcmp(ttyn, Console) != 0)) {
  917. audit_login_not_console();
  918. (void) printf("Not on system console\n");
  919. login_exit(10);
  920. }
  921. }
  922. }
  923. static char *illegal[] = {
  924. "SHELL=",
  925. "HOME=",
  926. "LOGNAME=",
  927. #ifndef NO_MAIL
  928. "MAIL=",
  929. #endif
  930. "CDPATH=",
  931. "IFS=",
  932. "PATH=",
  933. 0
  934. };
  935. /*
  936. * legalenvvar - Is it legal to insert this environmental variable?
  937. */
  938. static int
  939. legalenvvar(char *s)
  940. {
  941. register char **p;
  942. for (p = illegal; *p; p++)
  943. if (strncmp(s, *p, strlen(*p)) == 0)
  944. return (0);
  945. if (s[0] == 'L' && s[1] == 'D' && s[2] == '_')
  946. return (0);
  947. return (1);
  948. }
  949. /*
  950. * getstr - Get a string from standard input
  951. * Calls exit if read(2) fails.
  952. */
  953. static void
  954. getstr(char *buf, int cnt, char *err)
  955. {
  956. char c;
  957. do {
  958. if (read(0, &c, 1) != 1)
  959. login_exit(1);
  960. *buf++ = c;
  961. } while (cnt > 1 && c != 0);
  962. *buf = 0;
  963. err = err; /* For lint */
  964. }
  965. /*
  966. * uppercaseterm - if all input char are upper case
  967. * set the corresponding termio
  968. */
  969. static void
  970. uppercaseterm(char *strp)
  971. {
  972. int upper = 0;
  973. int lower = 0;
  974. char *sp;
  975. struct termio termio;
  976. for (sp = strp; *sp; sp++) {
  977. if (islower(*sp))
  978. lower++;
  979. else if (isupper(*sp))
  980. upper++;
  981. }
  982. if (upper > 0 && lower == 0) {
  983. (void) ioctl(0, TCGETA, &termio);
  984. termio.c_iflag |= IUCLC;
  985. termio.c_oflag |= OLCUC;
  986. termio.c_lflag |= XCASE;
  987. (void) ioctl(0, TCSETAW, &termio);
  988. for (sp = strp; *sp; sp++)
  989. if (*sp >= 'A' && *sp <= 'Z') *sp += ('a' - 'A');
  990. }
  991. }
  992. /*
  993. * defaults - read defaults
  994. */
  995. static void
  996. defaults(void)
  997. {
  998. extern int defcntl();
  999. register int flags;
  1000. register char *ptr;
  1001. if (defopen(Pndefault) == 0) {
  1002. /*
  1003. * ignore case
  1004. */
  1005. flags = defcntl(DC_GETFLAGS, 0);
  1006. TURNOFF(flags, DC_CASE);
  1007. defcntl(DC_SETFLAGS, flags);
  1008. if ((Console = defread("CONSOLE=")) != NULL)
  1009. Console = strdup(Console);
  1010. if ((Altshell = defread("ALTSHELL=")) != NULL)
  1011. Altshell = strdup(Altshell);
  1012. if ((Passreq = defread("PASSREQ=")) != NULL)
  1013. Passreq = strdup(Passreq);
  1014. if ((Def_tz = defread("TIMEZONE=")) != NULL)
  1015. Def_tz = strdup(Def_tz);
  1016. if ((Def_hertz = defread("HZ=")) != NULL)
  1017. Def_hertz = strdup(Def_hertz);
  1018. if ((Def_path = defread("PATH=")) != NULL)
  1019. Def_path = strdup(Def_path);
  1020. if ((Def_supath = defread("SUPATH=")) != NULL)
  1021. Def_supath = strdup(Def_supath);
  1022. if ((ptr = defread("ULIMIT=")) != NULL)
  1023. Def_ulimit = atol(ptr);
  1024. if ((ptr = defread("TIMEOUT=")) != NULL)
  1025. Def_timeout = (unsigned) atoi(ptr);
  1026. if ((ptr = defread("UMASK=")) != NULL) {
  1027. long long_umask;
  1028. if (sscanf(ptr, "%lo", &long_umask) != 1)
  1029. Umask = DEFUMASK;
  1030. else
  1031. Umask = (mode_t) long_umask;
  1032. }
  1033. if ((ptr = defread("SLEEPTIME=")) != NULL)
  1034. Sleeptime = atoi(ptr);
  1035. if ((ptr = defread("SYSLOG=")) != NULL)
  1036. dosyslog = strcmp(ptr, "YES") == 0;
  1037. (void) defopen((char *)NULL);
  1038. }
  1039. }
  1040. /*
  1041. * get_options(argc, argv)
  1042. * - parse the cmd line.
  1043. * - return 0 if successful, -1 if failed.
  1044. * Calls login_exit() on misuse of -r and -h flags
  1045. */
  1046. static int
  1047. get_options(int argc, char *argv[])
  1048. {
  1049. int c;
  1050. int errflg = 0;
  1051. while ((c = getopt(argc, argv, "f:h:r:pad:")) != -1) {
  1052. switch (c) {
  1053. case 'a':
  1054. break;
  1055. case 'd':
  1056. /*
  1057. * Must be root to pass in device name
  1058. * otherwise we exit() as punishment for trying.
  1059. */
  1060. if (getuid() != 0 || geteuid() != 0) {
  1061. login_exit(1); /* sigh */
  1062. /*NOTREACHED*/
  1063. }
  1064. ttyn = optarg;
  1065. break;
  1066. case 'h':
  1067. if (hflag || rflag) {
  1068. (void) fprintf(stderr,
  1069. "Only one of -r and -h allowed\n");
  1070. login_exit(1);
  1071. }
  1072. hflag++;
  1073. SCPYN(remote_host, optarg);
  1074. if (argv[optind]) {
  1075. if (argv[optind][0] != '-')
  1076. SCPYN(terminal, argv[optind]);
  1077. optind++;
  1078. }
  1079. progname = "telnet";
  1080. break;
  1081. case 'r':
  1082. if (hflag || rflag) {
  1083. (void) fprintf(stderr,
  1084. "Only one of -r and -h allowed\n");
  1085. login_exit(1);
  1086. }
  1087. rflag++;
  1088. SCPYN(remote_host, optarg);
  1089. progname = "rlogin";
  1090. break;
  1091. case 'p':
  1092. pflag++;
  1093. break;
  1094. case 'f':
  1095. /*
  1096. * Must be root to bypass authentication
  1097. * otherwise we exit() as punishment for trying.
  1098. */
  1099. if (getuid() != 0 || geteuid() != 0) {
  1100. login_exit(1); /* sigh */
  1101. /*NOTREACHED*/
  1102. }
  1103. /* save fflag user name for future use */
  1104. SCPYN(user_name, optarg);
  1105. fflag = 1;
  1106. break;
  1107. default:
  1108. errflg++;
  1109. break;
  1110. } /* end switch */
  1111. } /* end while */
  1112. /*
  1113. * get the prompt set by ttymon
  1114. */
  1115. ttyprompt = getenv("TTYPROMPT");
  1116. if ((ttyprompt != NULL) && (*ttyprompt != '\0')) {
  1117. /*
  1118. * if ttyprompt is set, there should be data on
  1119. * the stream already.
  1120. */
  1121. if ((envp = getargs(inputline)) != (char **)NULL) {
  1122. uppercaseterm(*envp);
  1123. /*
  1124. * don't get name if name passed as argument.
  1125. */
  1126. SCPYN(user_name, *envp++);
  1127. }
  1128. } else if (optind < argc) {
  1129. SCPYN(user_name, argv[optind]);
  1130. (void) strcpy(inputline, user_name);
  1131. (void) strcat(inputline, " \n");
  1132. envp = &argv[optind+1];
  1133. }
  1134. if (errflg)
  1135. return (-1);
  1136. return (0);
  1137. }
  1138. /*
  1139. * usage - Print usage message
  1140. *
  1141. */
  1142. static void
  1143. usage(void)
  1144. {
  1145. (void) fprintf(stderr,
  1146. "Usage:\tlogin [-h|-r] [ name [ env-var ... ]]\n");
  1147. }
  1148. /*
  1149. * *** Remote login support ***
  1150. *
  1151. */
  1152. /*
  1153. * doremoteterm - Sets the appropriate ioctls for a remote terminal
  1154. */
  1155. static char *speeds[] = {
  1156. "0", "50", "75", "110", "134", "150", "200", "300",
  1157. "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400",
  1158. "57600", "76800", "115200", "153600", "230400", "307200", "460800"
  1159. };
  1160. #define NSPEEDS (sizeof (speeds) / sizeof (speeds[0]))
  1161. static void
  1162. doremoteterm(char *term)
  1163. {
  1164. struct termios tp;
  1165. register char *cp = strchr(term, '/'), **cpp;
  1166. char *speed;
  1167. (void) ioctl(0, TCGETS, &tp);
  1168. if (cp) {
  1169. *cp++ = '\0';
  1170. speed = cp;
  1171. cp = strchr(speed, '/');
  1172. if (cp)
  1173. *cp++ = '\0';
  1174. for (cpp = speeds; cpp < &speeds[NSPEEDS]; cpp++)
  1175. if (strcmp(*cpp, speed) == 0) {
  1176. cfsetospeed(&tp, cpp-speeds);
  1177. break;
  1178. }
  1179. }
  1180. tp.c_lflag |= ECHO|ICANON;
  1181. tp.c_iflag |= IGNPAR|ICRNL;
  1182. (void) ioctl(0, TCSETS, &tp);
  1183. }
  1184. /*
  1185. * Process_rlogin - Does the work that rlogin and telnet
  1186. * need done
  1187. */
  1188. static void
  1189. process_rlogin(void)
  1190. {
  1191. getstr(rusername, sizeof (rusername), "remuser");
  1192. getstr(lusername, sizeof (lusername), "locuser");
  1193. getstr(terminal, sizeof (terminal), "Terminal type");
  1194. /* fflag has precedence over stuff passed by rlogind */
  1195. if (fflag || getuid()) {
  1196. pwd = &nouser;
  1197. doremoteterm(terminal);
  1198. return;
  1199. } else {
  1200. if (pam_set_item(pamh, PAM_USER, lusername) != PAM_SUCCESS)
  1201. login_exit(1);
  1202. pwd = getpwnam(lusername);
  1203. if (pwd == NULL) {
  1204. pwd = &nouser;
  1205. doremoteterm(terminal);
  1206. return;
  1207. }
  1208. }
  1209. doremoteterm(terminal);
  1210. /*
  1211. * Update PAM on the user name
  1212. */
  1213. if (pam_set_item(pamh, PAM_USER, lusername) != PAM_SUCCESS)
  1214. login_exit(1);
  1215. if (pam_set_item(pamh, PAM_RUSER, rusername) != PAM_SUCCESS)
  1216. login_exit(1);
  1217. SCPYN(user_name, lusername);
  1218. envp = &zero;
  1219. lusername[0] = '\0';
  1220. }
  1221. /*
  1222. * *** Account validation routines ***
  1223. *
  1224. */
  1225. /*
  1226. * validate_account - This is the PAM version of validate.
  1227. */
  1228. static void
  1229. validate_account()
  1230. {
  1231. int error;
  1232. int n;
  1233. int flag;
  1234. (void) alarm(0); /* give user time to come up with password */
  1235. check_log();
  1236. if ((Passreq != NULL) && (!strcasecmp("YES", Passreq)))
  1237. flag = PAM_DISALLOW_NULL_AUTHTOK;
  1238. else
  1239. flag = 0;
  1240. if ((error = pam_acct_mgmt(pamh, flag)) != PAM_SUCCESS) {
  1241. if (error == PAM_AUTHTOKEN_REQD) {
  1242. (void) printf("Choose a new password.\n");
  1243. if ((error = pam_chauthtok(pamh, 0)) != PAM_SUCCESS) {
  1244. if (dosyslog)
  1245. syslog(LOG_CRIT,
  1246. "change password failure: %s",
  1247. pam_strerror(pamh, error));
  1248. login_exit(1);
  1249. }
  1250. } else {
  1251. (void) printf(incorrectmsg);
  1252. if (dosyslog)
  1253. syslog(LOG_CRIT,
  1254. "login account failure: %s",
  1255. pam_strerror(pamh, error));
  1256. login_exit(1);
  1257. }
  1258. }
  1259. }
  1260. /*
  1261. * Check_log - This is really a hack because PAM checks the log, but login
  1262. * wants to know if the log is okay and PAM doesn't have
  1263. * a module independent way of handing this info back.
  1264. */
  1265. static void
  1266. check_log(void)
  1267. {
  1268. int fdl;
  1269. long long offset;
  1270. offset = (long long) pwd->pw_uid * (long long) sizeof (struct lastlog);
  1271. if ((fdl = open(LASTLOG, O_RDWR|O_CREAT, 0444)) >= 0) {
  1272. if (llseek(fdl, offset, SEEK_SET) == offset &&
  1273. read(fdl, (char *)&ll, sizeof (ll)) == sizeof (ll) &&
  1274. ll.ll_time != 0)
  1275. lastlogok = 1;
  1276. (void) close(fdl);
  1277. }
  1278. }
  1279. /*
  1280. * chdir_to_dir_root - Attempts to chdir us to the home directory.
  1281. * defaults to "/" if it can't cd to the home
  1282. * directory, and returns ERROR if it can't do that.
  1283. */
  1284. static int
  1285. chdir_to_dir_root(void)
  1286. {
  1287. if (chdir(pwd->pw_dir) < 0) {
  1288. if (chdir("/") < 0) {
  1289. (void) printf("No directory!\n");
  1290. return (ERROR);
  1291. }
  1292. }
  1293. return (OK);
  1294. }
  1295. /*
  1296. * chdir_to_dir_user - Now chdir after setuid/setgid have happened to
  1297. * place us in the user's home directory just in
  1298. * case it was protected and the first chdir failed.
  1299. * No chdir errors should happen at this point because
  1300. * all failures should have happened on the first
  1301. * time around.
  1302. */
  1303. static void
  1304. chdir_to_dir_user(void)
  1305. {
  1306. if (chdir(pwd->pw_dir) < 0) {
  1307. if (chdir("/") < 0) {
  1308. (void) printf("No directory!\n");
  1309. /*
  1310. * This probably won't work since we can't get to /.
  1311. */
  1312. if (remote_host[0] && dosyslog) {
  1313. syslog(LOG_CRIT,
  1314. "REPEATED LOGIN FAILURES ON %s FROM %.*s",
  1315. ttyn, HMAX, remote_host);
  1316. } else if (dosyslog) {
  1317. syslog(LOG_CRIT,
  1318. "REPEATED LOGIN FAILURES ON %s", ttyn);
  1319. }
  1320. closelog();
  1321. (void) sleep(DISABLETIME);
  1322. exit(1);
  1323. } else {
  1324. (void) printf("No directory! Logging in with home=/\n");
  1325. pwd->pw_dir = "/";
  1326. }
  1327. }
  1328. }
  1329. /*
  1330. * login_authenticate - Performs the main authentication work
  1331. * 1. Prints the login prompt
  1332. * 2. Requests and verifys the password
  1333. * 3. Checks the port password
  1334. */
  1335. static void
  1336. login_authenticate()
  1337. {
  1338. int cnt = 1;
  1339. char *user;
  1340. int err;
  1341. do {
  1342. /* if scheme broken, then nothing to do but quit */
  1343. if (pam_get_item(pamh, PAM_USER, (void **)&user)
  1344. != PAM_SUCCESS)
  1345. exit(1);
  1346. /*
  1347. * only get name from utility if it is not already
  1348. * supplied by pam_start or a pam_set_item.
  1349. */
  1350. if (!user || !user[0]) {
  1351. /* use call back to get user name */
  1352. get_user_name();
  1353. }
  1354. err = verify_passwd();
  1355. if ((err == PAM_SUCCESS) && (chdir_to_dir_root() == OK)) {
  1356. cnt = 0;
  1357. break;
  1358. }
  1359. /* scheme has kept count of retries. time to bail */
  1360. if (err == PAM_MAXTRIES)
  1361. cnt = MAXTRYS;
  1362. /* only sleep after first bad passwd */
  1363. if (cnt)
  1364. (void) sleep(Sleeptime);
  1365. (void) printf(incorrectmsg);
  1366. user_name[0] = '\0'; /* is this needed? */
  1367. /* force name to be null in this case */
  1368. if (pam_set_item(pamh, PAM_USER, NULL) != PAM_SUCCESS)
  1369. login_exit(1);
  1370. if (pam_set_item(pamh, PAM_RUSER, NULL) != PAM_SUCCESS)
  1371. login_exit(1);
  1372. } while (cnt++ < MAXTRYS);
  1373. if (cnt >= MAXTRYS) {
  1374. audit_login_maxtrys();
  1375. /*
  1376. * If logging is turned on, output the
  1377. * string storage area to the log file,
  1378. * and sleep for DISABLETIME
  1379. * seconds before exiting.
  1380. */
  1381. if (writelog)
  1382. badlogin();
  1383. if (remote_host[0] && dosyslog) {
  1384. syslog(LOG_CRIT,
  1385. "REPEATED LOGIN FAILURES ON %s FROM %.*s",
  1386. ttyn, HMAX, remote_host);
  1387. } else if (dosyslog) {
  1388. syslog(LOG_CRIT,
  1389. "REPEATED LOGIN FAILURES ON %s", ttyn);
  1390. }
  1391. (void) sleep(DISABLETIME);
  1392. exit(1);
  1393. }
  1394. }
  1395. /*
  1396. * *** Credential Related routines ***
  1397. *
  1398. */
  1399. /*
  1400. * setup_credentials - sets the group ID, initializes the groups
  1401. * and sets up the secretkey.
  1402. * Exits if a failure occurrs.
  1403. */
  1404. /*
  1405. * setup_credentials - PAM does all the work for us on this one.
  1406. */
  1407. static void
  1408. setup_credentials(void)
  1409. {
  1410. int error = 0;
  1411. int flags;
  1412. /* set the real (and effective) GID */
  1413. if (setgid(pwd->pw_gid) == -1) {
  1414. login_exit(1);
  1415. }
  1416. /*
  1417. * Initialize the supplementary group access list.
  1418. */
  1419. if (!user_name)
  1420. login_exit(1);
  1421. if (initgroups(user_name, pwd->pw_gid) == -1) {
  1422. login_exit(1);
  1423. }
  1424. /* XXX really should be after setgid */
  1425. if ((error = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
  1426. login_exit(error);
  1427. }
  1428. /* set the real (and effective) UID */
  1429. if (setuid(pwd->pw_uid) == -1) {
  1430. login_exit(1);
  1431. }
  1432. }
  1433. /*
  1434. *
  1435. * *** Routines to get a new user set up and running ***
  1436. *
  1437. * Things to do when starting up a new user:
  1438. * adjust_nice
  1439. * update_utmp_entry
  1440. * establish_user_environment
  1441. * print_banner
  1442. * display_last_login_time
  1443. * exec_the_shell
  1444. *
  1445. */
  1446. /*
  1447. * adjust_nice - Set the nice (process priority) value if the
  1448. * gecos value contains an appropriate value.
  1449. */
  1450. static void
  1451. adjust_nice(void)
  1452. {
  1453. int pri, mflg, i;
  1454. if (strncmp("pri=", pwd->pw_gecos, 4) == 0) {
  1455. pri = 0;
  1456. mflg = 0;
  1457. i = 4;
  1458. if (pwd->pw_gecos[i] == '-') {
  1459. mflg++;
  1460. i++;
  1461. }
  1462. while (pwd->pw_gecos[i] >= '0' && pwd->pw_gecos[i] <= '9')
  1463. pri = (pri * 10) + pwd->pw_gecos[i++] - '0';
  1464. if (mflg)
  1465. pri = -pri;
  1466. (void) nice(pri);
  1467. }
  1468. }
  1469. /*
  1470. * update_utmp_entry - Searchs for the correct utmp entry, making an
  1471. * entry there if it finds one, otherwise exits.
  1472. */
  1473. static void
  1474. update_utmp_entry(int sublogin)
  1475. {
  1476. char *user;
  1477. int error;
  1478. static char *errmsg = "No utmpx entry. "
  1479. "You must exec \"login\" from the lowest level \"shell\".";
  1480. int tmplen;
  1481. struct utmpx *u = (struct utmpx *)0;
  1482. struct utmpx utmp;
  1483. char *ttyntail;
  1484. /*
  1485. * If we're not a sublogin then
  1486. * we'll get an error back if our PID doesn't match the PID of the
  1487. * entry we are updating, otherwise if its a sublogin the flags
  1488. * field is set to 0, which means we just write a matching entry
  1489. * (without checking the pid), or a new entry if an entry doesn't
  1490. * exist.
  1491. */
  1492. if (error = pam_open_session(pamh, 0) != PAM_SUCCESS) {
  1493. login_exit(1);
  1494. }
  1495. if ((error = pam_get_item(pamh, PAM_USER, (void **) &user))
  1496. != PAM_SUCCESS) {
  1497. login_exit(1);
  1498. }
  1499. (void) memset((void *)&utmp, 0, sizeof (utmp));
  1500. (void) time(&utmp.ut_tv.tv_sec);
  1501. utmp.ut_pid = getpid();
  1502. if (rflag || hflag) {
  1503. SCPYN(utmp.ut_host, remote_host);
  1504. tmplen = strlen(remote_host) + 1;
  1505. if (tmplen < sizeof (utmp.ut_host))
  1506. utmp.ut_syslen = tmplen;
  1507. else
  1508. utmp.ut_syslen = sizeof (utmp.ut_host);
  1509. } else {
  1510. utmp.ut_syslen = 0;
  1511. }
  1512. SCPYN(utmp.ut_user, user);
  1513. /* skip over "/dev/" */
  1514. ttyntail = basename(ttyn);
  1515. while ((u = getutxent()) != NULL) {
  1516. if ((u->ut_type == INIT_PROCESS ||
  1517. u->ut_type == LOGIN_PROCESS ||
  1518. u->ut_type == USER_PROCESS) &&
  1519. ((sublogin && strncmp(u->ut_line, ttyntail,
  1520. sizeof (u->ut_line)) == 0) ||
  1521. u->ut_pid == utmp.ut_pid)) {
  1522. SCPYN(utmp.ut_line, (ttyn+sizeof ("/dev/")-1));
  1523. (void) memcpy(utmp.ut_id, u->ut_id,
  1524. sizeof (utmp.ut_id));
  1525. utmp.ut_type = USER_PROCESS;
  1526. pututxline(&utmp);
  1527. break;
  1528. }
  1529. }
  1530. endutxent();
  1531. if (u == (struct utmpx *)NULL) {
  1532. if (!sublogin) {
  1533. /*
  1534. * no utmp entry already setup
  1535. * (init or rlogind/telnetd)
  1536. */
  1537. (void) puts(errmsg);
  1538. login_exit(1);
  1539. }
  1540. } else {
  1541. /* Now attempt to write out this entry to the wtmp file if */
  1542. /* we were successful in getting it from the utmp file and */
  1543. /* the wtmp file exists. */
  1544. updwtmpx(WTMPX_FILE, &utmp);
  1545. }
  1546. }
  1547. /*
  1548. * process_chroot_logins - Chroots to the specified subdirectory and
  1549. * re executes login.
  1550. */
  1551. static int
  1552. process_chroot_logins(void)
  1553. {
  1554. /*
  1555. * If the shell field starts with a '*', do a chroot to the home
  1556. * directory and perform a new login.
  1557. */
  1558. if (*pwd->pw_shell == '*') {
  1559. pam_end(pamh, PAM_SUCCESS); /* Done using PAM */
  1560. if (chroot(pwd->pw_dir) < 0) {
  1561. (void) printf("No Root Directory\n");
  1562. return (ERROR);
  1563. }
  1564. /*
  1565. * Set the environment flag <!sublogin> so that the next login
  1566. * knows that it is a sublogin.
  1567. */
  1568. envinit[0] = SUBLOGIN;
  1569. envinit[1] = (char *)NULL;
  1570. (void) printf("Subsystem root: %s\n", pwd->pw_dir);
  1571. (void) execle("/usr/bin/login", "login", (char *)0,
  1572. &envinit[0]);
  1573. (void) execle("/etc/login", "login", (char *)0, &envinit[0]);
  1574. (void) printf("No /usr/bin/login or /etc/login on root\n");
  1575. login_exit(1);
  1576. }
  1577. return (OK);
  1578. }
  1579. /*
  1580. * establish_user_environment - Set up the new users environment
  1581. */
  1582. static void
  1583. establish_user_environment(char **renvp)
  1584. {
  1585. int i, j, k, l_index, length;
  1586. char *ptr;
  1587. char *endptr;
  1588. char **lenvp;
  1589. char *krb5p;
  1590. char *krb4p;
  1591. lenvp = environ;
  1592. while (*lenvp++)
  1593. ;
  1594. envinit = (char **) calloc(lenvp - environ + 10
  1595. + MAXARGS, sizeof (char *));
  1596. if (envinit == NULL) {
  1597. (void) printf("Calloc failed - out of swap space.\n");
  1598. login_exit(8);
  1599. }
  1600. memcpy(envinit, newenv, sizeof (newenv));
  1601. /* Set up environment */
  1602. if (rflag) {
  1603. ENVSTRNCAT(term, terminal);
  1604. } else if (hflag) {
  1605. /* XXX: this causes an environment variable with the value */
  1606. /* "" to be created later on, because terminal is "". */
  1607. (void) strncpy(term, terminal, sizeof (term) - 1);
  1608. } else {
  1609. char *tp = getenv("TERM");
  1610. if ((tp != NULL) && (*tp != '\0'))
  1611. ENVSTRNCAT(term, tp);
  1612. }
  1613. ENVSTRNCAT(logname, pwd->pw_name);
  1614. /*
  1615. * There are three places to get timezone info. init.c sets
  1616. * TZ if the file /etc/TIMEZONE contains a value for TZ.
  1617. * login.c looks in the file /etc/default/login for a
  1618. * variable called TIMEZONE being set. If TIMEZONE has a
  1619. * value, TZ is set to that value; no environment variable
  1620. * TIMEZONE is set, only TZ. If neither of these methods
  1621. * work to set TZ, then the library routines will default
  1622. * to using the file /usr/lib/locale/TZ/localtime.
  1623. *
  1624. * There is a priority set up here. If /etc/TIMEZONE has
  1625. * a value for TZ, that value remains top priority. If the
  1626. * file /etc/default/login has TIMEZONE set, that has second
  1627. * highest priority not overriding the value of TZ in
  1628. * /etc/TIMEZONE. The reason for this priority is that the
  1629. * file /etc/TIMEZONE is supposed to be sourced by
  1630. * /etc/profile. We are doing the "sourcing" prematurely in
  1631. * init.c. Additionally, a login C shell doesn't source the
  1632. * file /etc/profile thus not sourcing /etc/TIMEZONE thus not
  1633. * allowing an administrator to globally set TZ for all users
  1634. */
  1635. if (Def_tz != NULL) /* Is there a TZ from defaults/login? */
  1636. tmp_tz = Def_tz;
  1637. if ((Def_tz = getenv("TZ")) != NULL) {
  1638. ENVSTRNCAT(timez, Def_tz);
  1639. } else if (tmp_tz != NULL) {
  1640. Def_tz = tmp_tz;
  1641. ENVSTRNCAT(timez, Def_tz);
  1642. }
  1643. if (Def_hertz == NULL)
  1644. (void) sprintf(hertz + strlen(hertz), "%u", HZ);
  1645. else
  1646. ENVSTRNCAT(hertz, Def_hertz);
  1647. if (Def_path == NULL)
  1648. (void) strcat(path, DEF_PATH);
  1649. else
  1650. ENVSTRNCAT(path, Def_path);
  1651. ENVSTRNCAT(home, pwd->pw_dir);
  1652. /*
  1653. * Find the end of the basic environment
  1654. */
  1655. for (basicenv = 0; envinit[basicenv] != NULL; basicenv++)
  1656. ;
  1657. /*
  1658. * If TZ has a value, add it.
  1659. */
  1660. if (strcmp(timez, "TZ=") != 0)
  1661. envinit[basicenv++] = timez;
  1662. if (*pwd->pw_shell == '\0') {
  1663. /*
  1664. * If possible, use the primary default shell,
  1665. * otherwise, use the secondary one.
  1666. */
  1667. if (access(SHELL, X_OK) == 0)
  1668. pwd->pw_shell = SHELL;
  1669. else
  1670. pwd->pw_shell = SHELL2;
  1671. } else if (Altshell != NULL && strcmp(Altshell, "YES") == 0) {
  1672. envinit[basicenv++] = shell;
  1673. ENVSTRNCAT(shell, pwd->pw_shell);
  1674. }
  1675. #ifndef NO_MAIL
  1676. envinit[basicenv++] = mail;
  1677. (void) strcat(mail, pwd->pw_name);
  1678. #endif
  1679. /*
  1680. * Pick up locale environment variables, if any.
  1681. */
  1682. lenvp = renvp;
  1683. while (*lenvp != NULL) {
  1684. j = 0;
  1685. while (localeenv[j] != 0) {
  1686. /*
  1687. * locale_envmatch() returns 1 if
  1688. * *lenvp is localenev[j] and valid.
  1689. */
  1690. if (locale_envmatch(localeenv[j], *lenvp) == 1) {
  1691. envinit[basicenv++] = *lenvp;
  1692. break;
  1693. }
  1694. j++;
  1695. }
  1696. lenvp++;
  1697. }
  1698. /*
  1699. * If '-p' flag, then try to pass on allowable environment
  1700. * variables. Note that by processing this first, what is
  1701. * passed on the final "login:" line may over-ride the invocation
  1702. * values. XXX is this correct?
  1703. */
  1704. if (pflag) {
  1705. for (lenvp = renvp; *lenvp; lenvp++) {
  1706. if (!legalenvvar(*lenvp)) {
  1707. continue;
  1708. }
  1709. /*
  1710. * If this isn't 'xxx=yyy', skip it. XXX
  1711. */
  1712. if ((endptr = strchr(*lenvp, '=')) == NULL) {
  1713. continue;
  1714. }
  1715. length = endptr + 1 - *lenvp;
  1716. for (j = 0; j < basicenv; j++) {
  1717. if (strncmp(envinit[j], *lenvp, length) == 0) {
  1718. /*
  1719. * Replace previously established value
  1720. */
  1721. envinit[j] = *lenvp;
  1722. break;
  1723. }
  1724. }
  1725. if (j == basicenv) {
  1726. /*
  1727. * It's a new definition, so add it at the end.
  1728. */
  1729. envinit[basicenv++] = *lenvp;
  1730. }
  1731. }
  1732. }
  1733. /*
  1734. * Add in all the environment variables picked up from the
  1735. * argument list to "login" or from the user response to the
  1736. * "login" request.
  1737. */
  1738. for (j = 0, k = 0, l_index = 0, ptr = &envblk[0];
  1739. *envp && j < (MAXARGS-1); j++, envp++) {
  1740. /*
  1741. * Scan each string provided. If it doesn't have the
  1742. * format xxx=yyy, then add the string "Ln=" to the beginning.
  1743. */
  1744. if ((endptr = strchr(*envp, '=')) == NULL) {
  1745. envinit[basicenv+k] = ptr;
  1746. (void) sprintf(ptr, "L%d=%s", l_index, *envp);
  1747. /*
  1748. * Advance "ptr" to the beginning of the
  1749. * next argument.
  1750. */
  1751. while (*ptr++)
  1752. ;
  1753. k++;
  1754. l_index++;
  1755. } else {
  1756. if (!legalenvvar(*envp)) { /* this env var permited? */
  1757. continue;
  1758. } else {
  1759. /*
  1760. * Check to see whether this string replaces
  1761. * any previously defined string
  1762. */
  1763. for (i = 0, length = endptr + 1 - *envp;
  1764. i < basicenv + k; i++) {
  1765. if (strncmp(*envp, envinit[i], length)
  1766. == 0) {
  1767. envinit[i] = *envp;
  1768. break;
  1769. }
  1770. }
  1771. /*
  1772. * If it doesn't, place it at the end of
  1773. * environment array.
  1774. */
  1775. if (i == basicenv+k) {
  1776. envinit[basicenv+k] = *envp;
  1777. k++;
  1778. }
  1779. }
  1780. }
  1781. } /* for (j = 0 ... ) */
  1782. /*
  1783. * Add DCE/Kerberos cred name, if any.
  1784. * XXX - The module specific stuff should be removed from login
  1785. * program eventually. This is better placed in DCE module.
  1786. * So far, we haven't come up with a way to deal with these
  1787. * environment variables.
  1788. */
  1789. krb5p = getenv("KRB5CCNAME");
  1790. if ((krb5p != NULL) && (*krb5p != '\0')) {
  1791. ENVSTRNCAT(krb5ccname, krb5p);
  1792. envinit[basicenv++] = krb5ccname;
  1793. }
  1794. krb4p = getenv("KRBTKFILE");
  1795. if ((krb4p != NULL) && (*krb4p != '\0')) {
  1796. ENVSTRNCAT(krb4ccname, krb4p);
  1797. envinit[basicenv++] = krb4ccname;
  1798. }
  1799. /*
  1800. * Switch to the new environment.
  1801. */
  1802. environ = envinit;
  1803. }
  1804. /*
  1805. * print_banner - Print the banner at start up
  1806. * Do not turn on DOBANNER ifdef. This is not
  1807. * relevant to SunOS.
  1808. */
  1809. static void
  1810. print_banner(void)
  1811. {
  1812. #ifdef DOBANNER
  1813. uname(&un);
  1814. #if i386
  1815. (void) printf("UNIX System V/386 Release %s\n%s\n"
  1816. "Copyright (C) 1984, 1986, 1987, 1988 AT&T\n"
  1817. "Copyright (C) 1987, 1988 Microsoft Corp.\nAll Rights Reserved\n",
  1818. un.release, un.nodename);
  1819. #elif sun
  1820. (void) printf("SunOS Release %s Sun Microsystems %s\n%s\n"
  1821. "Copyright (c) 1984, 1986, 1987, 1988 AT&T\n"
  1822. "Copyright (c) 1988, 1989, 1990, 1991 Sun Microsystems\n"
  1823. "All Rights Reserved\n",
  1824. un.release, un.machine, un.nodename);
  1825. #else
  1826. (void) printf("UNIX System V Release %s AT&T %s\n%s\n"
  1827. "Copyright (c) 1984, 1986, 1987, 1988 AT&T\nAll Rights Reserved\n",
  1828. un.release, un.machine, un.nodename);
  1829. #endif /* i386 */
  1830. #endif /* DOBANNER */
  1831. }
  1832. /*
  1833. * display_last_login_time - Advise the user the time and date
  1834. * that this login-id was last used.
  1835. */
  1836. static void
  1837. display_last_login_time(void)
  1838. {
  1839. if (lastlogok) {
  1840. (void) printf("Last login: %.*s ", 24-5, ctime(&ll.ll_time));
  1841. if (*ll.ll_host != '\0')
  1842. (void) printf("from %.*s\n", sizeof (ll.ll_host),
  1843. ll.ll_host);
  1844. else
  1845. (void) printf("on %.*s\n", sizeof (ll.ll_line),
  1846. ll.ll_line);
  1847. }
  1848. }
  1849. /*
  1850. * exec_the_shell - invoke the specified shell or start up program
  1851. */
  1852. static void
  1853. exec_the_shell(void)
  1854. {
  1855. char *endptr;
  1856. int i;
  1857. (void) strcat(minusnam, basename(pwd->pw_shell));
  1858. /*
  1859. * Exec the shell
  1860. */
  1861. (void) execl(pwd->pw_shell, minusnam, (char *)0);
  1862. /*
  1863. * pwd->pw_shell was not an executable object file, maybe it
  1864. * is a shell proceedure or a command line with arguments.
  1865. * If so, turn off the SHELL= environment variable.
  1866. */
  1867. for (i = 0; envinit[i] != NULL; ++i) {
  1868. if ((envinit[i] == shell) &&
  1869. ((endptr = strchr(shell, '=')) != NULL))
  1870. (*++endptr) = '\0';
  1871. }
  1872. if (access(pwd->pw_shell, R_OK|X_OK) == 0) {
  1873. (void) execl(SHELL, "sh", pwd->pw_shell, (char *)0);
  1874. (void) execl(SHELL2, "sh", pwd->pw_shell, (char *)0);
  1875. }
  1876. (void) printf("No shell\n");
  1877. }
  1878. /*
  1879. * login_exit - Call exit() and terminate.
  1880. * This function is here for PAM so cleanup can
  1881. * be done before the process exits.
  1882. */
  1883. static void
  1884. login_exit(int exit_code)
  1885. {
  1886. if (pamh)
  1887. pam_end(pamh, PAM_ABORT);
  1888. exit(exit_code);
  1889. /*NOTREACHED*/
  1890. }
  1891. /*
  1892. * Check if lenv and penv matches or not.
  1893. */
  1894. static int
  1895. locale_envmatch(char *lenv, char *penv)
  1896. {
  1897. while ((*lenv == *penv) && *lenv && *penv != '=') {
  1898. lenv++;
  1899. penv++;
  1900. }
  1901. /*
  1902. * '/' is eliminated for security reason.
  1903. */
  1904. if (*lenv == '\0' && *penv == '=' && *(penv + 1) != '/')
  1905. return (1);
  1906. return (0);
  1907. }
  1908. /*
  1909. * logindevperm - change owner/group/permissions of devices
  1910. * list in /etc/logindevperm. (Code derived from set_fb_attrs()
  1911. * in 4.x usr/src/bin/login.c and usr/src/etc/getty/main.c.)
  1912. */
  1913. #define MAX_LINELEN 256
  1914. #define LOGINDEVPERM "/etc/logindevperm"
  1915. #define DIRWILD "/*" /* directory wildcard */
  1916. #define DIRWLDLEN 2 /* strlen(DIRWILD) */
  1917. static void
  1918. logindevperm(char *ttyn, uid_t uid, gid_t gid)
  1919. {
  1920. char *field_delims = " \t\n";
  1921. char *permfile = LOGINDEVPERM;
  1922. char line[MAX_LINELEN];
  1923. char *console;
  1924. char *mode_str;
  1925. char *dev_list;
  1926. char *device;
  1927. char *ptr;
  1928. int mode;
  1929. FILE *fp;
  1930. size_t l;
  1931. int lineno;
  1932. if ((fp = fopen(permfile, "r")) == NULL)
  1933. return;
  1934. lineno = 0;
  1935. while (fgets(line, MAX_LINELEN, fp) != NULL) {
  1936. lineno++;
  1937. if ((ptr = strchr(line, '#')) != NULL)
  1938. *ptr = '\0'; /* handle comments */
  1939. if ((console = strtok(line, field_delims)) == NULL)
  1940. continue; /* ignore blank lines */
  1941. if (strcmp(console, ttyn) != 0)
  1942. continue; /* not our tty, skip */
  1943. mode_str = strtok((char *)NULL, field_delims);
  1944. if (mode_str == NULL) {
  1945. (void) fprintf(stderr,
  1946. "%s: line %d, invalid entry -- %s\n", permfile,
  1947. lineno, line);
  1948. continue;
  1949. }
  1950. /* convert string to octal value */
  1951. mode = strtol(mode_str, &ptr, 8);
  1952. if (mode < 0 || mode > 0777 || *ptr != '\0') {
  1953. (void) fprintf(stderr,
  1954. "%s: line %d, invalid mode -- %s\n", permfile,
  1955. lineno, mode_str);
  1956. continue;
  1957. }
  1958. dev_list = strtok((char *)NULL, field_delims);
  1959. if (dev_list == NULL) {
  1960. (void) fprintf(stderr,
  1961. "%s: line %d, %s -- empty device list\n",
  1962. permfile, lineno, console);
  1963. continue;
  1964. }
  1965. device = strtok(dev_list, ":");
  1966. while (device != NULL) {
  1967. l = strlen(device);
  1968. ptr = &device[l - DIRWLDLEN];
  1969. if ((l > DIRWLDLEN) && (strcmp(ptr, DIRWILD) == 0)) {
  1970. *ptr = '\0'; /* chop off wildcard */
  1971. dir_dev_acc(device, uid, gid, mode, permfile);
  1972. } else {
  1973. /*
  1974. * change the owner/group/permission;
  1975. * nonexistent devices are ignored
  1976. */
  1977. if (chown(device, uid, gid) == -1) {
  1978. if (errno != ENOENT) {
  1979. (void) fprintf(stderr, "%s: ",
  1980. permfile);
  1981. perror(device);
  1982. }
  1983. } else {
  1984. if ((chmod(device, mode) == -1) &&
  1985. (errno != ENOENT)) {
  1986. (void) fprintf(stderr, "%s: ",
  1987. permfile);
  1988. perror(device);
  1989. }
  1990. }
  1991. }
  1992. device = strtok((char *)NULL, ":");
  1993. }
  1994. }
  1995. (void) fclose(fp);
  1996. }
  1997. /*
  1998. * Apply owner/group/perms to all files (except "." and "..")
  1999. * in a directory.
  2000. */
  2001. static void
  2002. dir_dev_acc(char *dir, uid_t uid, gid_t gid, mode_t mode, char *permfile)
  2003. {
  2004. DIR *dirp;
  2005. struct dirent *direntp;
  2006. char *name, path[MAX_LINELEN + MAXNAMELEN];
  2007. dirp = opendir(dir);
  2008. if (dirp == NULL)
  2009. return;
  2010. while ((direntp = readdir(dirp)) != NULL) {
  2011. name = direntp->d_name;
  2012. if ((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0))
  2013. continue;
  2014. (void) sprintf(path, "%s/%s", dir, name);
  2015. if (chown(path, uid, gid) == -1) {
  2016. if (errno != ENOENT) {
  2017. (void) fprintf(stderr, "%s: ", permfile);
  2018. perror(path);
  2019. }
  2020. } else {
  2021. if ((chmod(path, mode) == -1) && (errno != ENOENT)) {
  2022. (void) fprintf(stderr, "%s: ", permfile);
  2023. perror(path);
  2024. }
  2025. }
  2026. }
  2027. (void) closedir(dirp);
  2028. }