?? login.c
字號(hào):
#ifndef lintstatic char *sccsid = "@(#)login.c 4.6 (ULTRIX) 2/14/91";#endif lint/************************************************************************ * * * Copyright (c) 1986, 1987, 1988, 1989, 1990, 1991 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * $Source: /u1/usr/src/bin/RCS/login.c,v $ * $Author: jg $ * $Locker: $ * $Log: login.c,v $ * * 14-Nov-90 dlong * Keep prompter alive for the whole time. Prompter will be expected to * exit when the close-on-exec pipe to it is closed on shell startup. This * allows all login errors, including shell-not-found to be reportable * through prompter. It also allows prompter to signal login for * keyboard generated interrupts and provides an escape from a hard,intr * NFS home directory or mail spool file that has gone away. * * 26-Sep-90 wessex::lisa * Add two additional error messages to explain when a login is refused * because of an invalid or missing license PAK. Also extend time that * message is displayed for. * * 04-Sep-90 dlong * Don't hang with interrupts disabled if the HOME directory of mail spool * file is on an unavailable NFS partition. * * 17-Jul-89 jsd * Workaround ruserok() returning 0 on success, when it used to return 1. * * 19-Sep-89 dlong * Don't update auth entry (for fail count) if it doesn't reside on the local * machine. * * 22-Aug-89 dlong * Do an endauthent() before exec'ing password (to prevent retaining * an old cached entry), and before handing off to the user (to avoid * leaving them an open file descriptor for /etc/auth*). Also, improve * error reporting since ERRORNXIT does not actually display the error * message. Also, remove booby trap of closing all file descriptors after * having done a getauthuid() and a getpwnam() which might have intentionally * left open file decscriptors behind. Also, only use one of T_ERROR or * T_RESULT in the audit record. * * 16-Aug-89 S. Logcher * Remove extraneous setpwent() and endpwent() calls from dodecnetlogin() * routine. * * 15-Aug-89 D. Long * Added prompter "-e" support. Also, handle empty password better. * * 19-Jul-89 D. Long * Don't issue password expiration messages until after "Login succeeded" * message. Otherwise the old prompter breaks. Also, don't try and use the * UID as an audit ID. Also, recognize the "e" option and ignore it. Also, * fixed up some comments. * * 28-Jun-89 D. Long * Fixed problem logging in remotely in BSD mode. Also, look for auth.h * in usr/include, not current directory. * * 15-May-89 Giles Atkinson * Convert login limits to use LMF * * 7/Jun/89 D. Long * Added security features for 4.0 * * 029 - Gary A. Gaudet. Fri Apr 21 21:57:43 EDT 1989 * Added unbuffered stdin, cyphered name and password, * and bzero buffer, for -P. * * 028 - Gary A. Gaudet. Mon Apr 17 14:37:31 EDT 1989 * Added check for real root uid before using -P. * * 08/Jun/88 Mark Parenti * Changed signal handlers to void. * * 24/Mar/88 Tim Burke / Rich Hyde * Flush standard error after reporting an error. Return success string to * prompter program to prevent reappearance of dialogue box on successful login. * * 29/Feb/88 Tim Burke / Rich Hyde * Flush output after reporting an error. * * 1.25 20/Jan/88 Mark Parenti * Change initialization of passwd structure to reflect changes made * for POSIX compliance. * * 07/Dec/87 Tim Burke / Rich Hyde * 1) Added a option -P <programname> that causes login to set it's * standard input and output to be connected to the prompting program. * This allows one to write a X based prompter that prompts for name and * password and then ships that info back to login. * * 2) Added an option -C "string" to allow the system to specify a * command to be run using the users shell. It causes a (USER SHELL) -c * "string" to be exec'ed. This allows one to start a X based application * but still allow normal logins, and [dr]logins to work. * * 08/Aug/87 Tim Burke * Look for LPASS8 in local mode word to preserve 8-bit mode as passed on * from getty(). * * 1.22 28/Jul/87 logcher * Changed doremotelogin() to call ruserok() in libc.a * * 1.20 02/Jun/87 logcher * In doremotelogin, when opening and reading ~user/.rhosts, seteuid * to that user uid and seteuid back after. This avoids problems * when ~user is mounted remotely. * * 1.19 3/12/87 lp * Three times has to make it right! Finally fixed the decnet/telnet clash. * * 1.18 3/3/87 lp * Fixed the problem 1.15 problem abain (as 1.17 broke decnet). * * 2/25/87 Tim Burke * Allow setting of TERMIODISC if "termio" was specified in /etc/ttys. * * 1.17 2/12/87 lp * Fixed a silly problem introduced in rev 1.15 (which broke telnet logins). * * Rev 1.16 1/14/86 lp * Increased ahosts to 128 (from 32) as hostnames of the form * "washington.berekley.edu username" might be longer than 32 and * hence might not match. * * Revision 1.15 86/12/4 Tim Burke * A change to the dodecnetlogin routine to set proxy to -1 so that a prompt * for password will appear. * * Revision 1.14 86/8/8 Tim Burke * Inserted changes proposed by Peter Harbo of decnet. These changes are * mainly in the dodecnetlogin routine to return -1 if username, but no * password has been received. * * Revision 1.13 86/6/24 Tim * Changed so that invalid rlogins and dlogins are handled similarly. * Inserted copyright notice. * * Revision 1.12 86/3/11 Robin * Made change to count logins in the kernel. * * Revision 1.11 86/2/5 10:05:00 robin * fixed problem that stopped erase from working if a second try * at logging in was made. * * Revision 1.8 85/10/22 10:30:00 was * add decnet support for remote login * * Revision 1.7 84/10/29 17:24:33 jg * fix problem with -p option. Wasn't allowing user name, so getty * wasn't happy. * * Revision 1.6 84/10/25 14:12:23 jg * Undid utmp changes. Added -p flag to preserve environment passed * from getty. * * Revision 1.5 84/10/01 09:28:38 jg * fix allocation bug that caused login to fail. * * Revision 1.4 84/09/09 15:50:19 jg * fix bug introduced by environment change; was not doing rlogin right. * * Revision 1.3 84/09/09 14:51:31 jg * fixed login not to destroy the environment set up by whomever is calling it. * * Revision 1.2 84/09/01 11:39:08 jg * changes required by utmp.h changes. * * Revision 1.1 84/04/20 01:07:13 root * Initial revision * *//*static char *rcsid_login_c = "$Header: login.c,v 1.7 84/10/29 17:24:33 jg Exp $";static char *sccsid = "@(#)login.c 4.34 (Berkeley) 84/05/07";*//* * login [ name ] * login -r hostname (for rlogind) * login -h hostname (for telnetd, etc.) */#define NOPRIV#include <sys/param.h>#include <sys/quota.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/file.h>#include <sys/wait.h>#include <sys/types.h>#include <sys/sysinfo.h>#include <sys/utsname.h>#include <sys/ltatty.h>#ifndef NOPRIV#include <sys/priv.h>#endif#include <sys/svcinfo.h>#include <fcntl.h>#include <sgtty.h>#include <utmp.h>#include <signal.h>#include <pwd.h>#include <grp.h>#include <stdio.h>#include <lastlog.h>#include <errno.h>#include <ttyent.h>#include <syslog.h>#include <limits.h>#include <lmf.h>#include <strings.h>#ifndef NOAUDIT/* sample code to audit login's */#include <syscall.h>#include <sys/syscall.h>#include <sys/audit.h>#define LEN (SYSCALL_MASK_LEN+TRUSTED_MASK_LEN)#endif NOAUDIT#include <auth.h>#include "proto.h"#ifdef AUTHEN#include <krb.h>#endif AUTHEN#define SCMPN(a, b) strncmp(a, b, sizeof(a))#define SCPYN(a, b) strncpy(a, b, sizeof(a))#define NMAX sizeof(utmp.ut_name)#define FALSE 0#define TRUE -1#ifndef NOAUDITstatic char buf[LEN];static int i;#endif NOAUDITchar nolog[] = "/etc/nologin";char qlog[] = ".hushlogin";char maildir[40] = "/usr/spool/mail/";char lastlog[] = "/usr/adm/lastlog";struct passwd nouser = {"", "nope", -1, -1, -1, -1, -1, "", "", "", "" };struct sgttyb ttyb;struct utmp utmp;struct ltattyi ltattyi;char minusnam[16] = "-";char *envinit[] = { 0 }; /* now set by setenv calls *//* * This bounds the time given to login. We initialize it here * so it can be patched on machines where it's too small. */int timeout = 240;char term[64];struct passwd *pwd, pwd_save;char *auth_db = AUTHORIZATION_DB;AUTHORIZATION *auth, *getauthuid();char *strcat(), *rindex(), *index();void timedout();char *ttyname();char *crypt16(), *crypt();char *getpass();char *stypeof();extern char **environ;extern int errno;struct tchars tc = { CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK};struct ltchars ltc = { CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT};int rflag, dflag;int notty = FALSE;char rusername[NMAX+1], lusername[NMAX+1];char rpassword[NMAX+1];char name[NMAX+1];char *tty;static prompt_pid;static eflag = 0;int lastsend = -1;char *pp;/* * Signal handler to just do an exit. */void exit_handler(sig, code, scp)int sig, code;struct sigconext *scp;{ exit(0);}/* * Function to send a message to the user, either through prompter * or the tty. */static sendreq(opcode, data)int opcode;char *data;{ REQ request; register REQ *req = &request; int i, length; if(data) length = strlen(data) + 1; else length = 0;/* * If using extended protocol send a packet out on stdout. */ if(eflag) { SENDREQ(req, opcode, data, length);/* * Error messages are always acknowledged to provide a synchronous * user interface. */ if(opcode == ERROR) { GETREQ(req, i); if(req->opcode != ACKNOWLEDGE) { sendreq(ERRORNXIT, "Protocol error\n"); cleanup(10, 1, "Protocol error"); } } } else {/* * If not using the extended protocol handle each message type * locally. */ lastsend = opcode; switch(opcode) {/* * Get login user name. */ case GETNAME: case GETENAME: if(!notty) { getloginname(data); bcopy(&utmp, req->data, sizeof utmp); req->length = sizeof utmp; } break;/* * Get users password. */ case GETPWD: case GETEPWD: if(!notty) { pp = getpass(data); strncpy(req->data, pp, REQDATASIZ); req->length = strlen(pp) + 1; } break;/* * Display an error message. */ case ERROR: case ERRORNXIT: if(data && length > 0) { fputs(data, stdout); fflush(stdout); } break;/* * Display a non-error message. */ case VALID: case VALIDNXIT: case CHGPWD: if(data && length > 0) { fputs(data, stdout); fflush(stdout); } break;/* * Only meaningful to extended protocol. */ case INITIALIZE: break; } }}/* * Function to receive a message from the user, either through prompter * or some other route. */static getreq(req)REQ *req;{ int i;/* * If using extended protocol just retrieve a packet from stdin. */ if(eflag) { GETREQ(req, i); } else {/* * If not using extended protocol handle each case locally. Look at * the last sent message to determine what input should be obtained. */ i = 0; switch(lastsend) {/* * Waiting for input. */ case GETNAME: case GETENAME: case GETPWD: case GETEPWD: switch(lastsend) {/* * Waiting for a login name. */ case GETNAME: case GETENAME: req->opcode = NAME; break;/* * Waiting for a password. */ case GETPWD: case GETEPWD: req->opcode = PASSWD; break; }/* * if notty is true we are talking to an old prompter. Otherwise * we are talking to a simple tty and all cases are actually handled * in sendreq(). */ if(notty) { i = fgets(req->data, REQDATASIZ, stdin) != NULL; if(i) req->length = strlen(req->data) + 1; else { req->length = 0; i = -1; } } break;/* * The initialize case is only meaningful with the extended protocol. */ case INITIALIZE: break; } lastsend = -1; } return i;}/* * Prompter is used to solicit login identity and authentication * through a workstation display. */void start_prompter(prompter, tty) char *prompter;char *tty;{ int infds[2], outfds[2]; int i; pipe(infds); dup2(infds[0], 10); close(infds[0]); infds[0] = 10; dup2(infds[1], 11); close(infds[1]); infds[1] = 11; pipe(outfds); dup2(outfds[0], 12); close(outfds[0]); outfds[0] = 12; dup2(outfds[1], 13); close(outfds[1]); outfds[1] = 13; if(eflag) { close(2); i = open("/dev/null", O_WRONLY); if(i != 2) { dup2(i, 2); close(i); } } if(prompt_pid = fork()) { close(infds[1]); close(outfds[0]); /* * parents stdin; */ dup2(infds[0], 0); close(infds[0]); /* stdout */ dup2(outfds[1], 1); if(!eflag) { close(2); dup2(outfds[1], 2); } close(outfds[1]); } else { close(infds[0]); close(outfds[1]); /* child stdin */ dup2(outfds[0], 0); close(outfds[0]); /* stdout */ dup2(infds[1], 1); close(infds[1]); if(eflag) execlp(prompter, prompter, "-e", tty, 0); else execlp(prompter, prompter, tty, 0); exit(0); } }/* * audit_event() logs a LOGIN audit event. */audit_event(code, message)int code;char *message;{#ifndef NOAUDIT char tmask[AUD_NPARAM]; char *ar[AUD_NPARAM]; int i=0; static char name[9]; static char host[17];/* Fill in tokens.*/ strncpy(name, utmp.ut_name, 8); tmask[i] = T_LOGIN; ar[i++] = name; if(pwd) { tmask[i] = T_HOMEDIR; ar[i++] = pwd->pw_dir; tmask[i] = T_SHELL; ar[i++] = pwd->pw_shell; } if(code) tmask[i] = T_ERROR; else tmask[i] = T_RESULT; ar[i++] = (char *) code; if(message) { tmask[i] = T_CHARP; ar[i++] = message; } if(tty) { tmask[i] = T_DEVNAME; ar[i++] = tty; } strncpy(host, utmp.ut_host, 16); if(*host) { tmask[i] = T_CHARP;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -