📄 login.c
字号:
/* * Copyright (c) 1980,1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */#ifndef lintchar copyright[] ="@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n";#endif not lint#ifndef lintstatic char sccsid[] = "@(#)login.c 5.20 (Berkeley) 10/1/87";#endif not lint/* * login [ name ] * login -r hostname (for rlogind) * login -h hostname (for telnetd, etc.) * login -f name (for pre-authenticated login: datakit, xterm, etc.) */#include <sys/param.h>#ifdef QUOTA#include <sys/quota.h>#endif#include <sys/stat.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/file.h>#include <sgtty.h>#include <utmp.h>#include <signal.h>#include <pwd.h>#include <stdio.h>#include <lastlog.h>#include <errno.h>#include <ttyent.h>#include <syslog.h>#include <grp.h>#include <netdb.h>#include "skey.h"#define TTYGRPNAME "tty" /* name of group to own ttys */#define TTYGID(gid) tty_gid(gid) /* gid that owns all ttys */#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 HMAX sizeof(utmp.ut_host)#define FALSE 0#define TRUE -1char nolog[] = "/etc/nologin";char qlog[] = ".hushlogin";char maildir[30] = "/usr/spool/mail/";char lastlog[] = "/usr/adm/lastlog";struct passwd nouser = {"", "#nope", -1, -1, "", "", "", "", "" };struct sgttyb ttyb;struct utmp utmp;char minusnam[16] = "-";char *envinit[1]; /* 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 = 300;char term[64];struct passwd *pwd;char *strcat(), *rindex(), *index();int timedout();char *ttyname();char *crypt();char *getpass();char *stypeof();extern int errno;struct tchars tc = { CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK};struct ltchars ltc = { CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT};struct winsize win = { 0, 0, 0, 0 };int rflag;int usererr = -1;char rusername[NMAX+1], lusername[NMAX+1];char rpassword[NMAX+1];char name[NMAX+1];char me[MAXHOSTNAMELEN];char *rhost;main(argc, argv) char *argv[];{ extern char **environ; register char *namep; int pflag = 0, hflag = 0, fflag = 0, t, f, c; int invalid, quietlog; FILE *nlfd; char *ttyn, *tty, host[256]; int ldisc = 0, zero = 0, i; char *p, *domain, *index(); char skeyprompt[80]; int pwok; host[0] = '\0'; skeyprompt[0] = '\0'; signal(SIGALRM, timedout); alarm(timeout); signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); setpriority(PRIO_PROCESS, 0, 0);#ifdef QUOTA quota(Q_SETUID, 0, 0, 0);#endif /* * -p is used by getty to tell login not to destroy the environment * -r is used by rlogind to cause the autologin protocol; * -f is used to skip a second login authentication * -h is used by other servers to pass the name of the * remote host to login so that it may be placed in utmp and wtmp */ (void) gethostname(me, sizeof(me)); domain = index(me, '.'); while (argc > 1) { if (strcmp(argv[1], "-r") == 0) { if (rflag || hflag || fflag) { printf("Other options not allowed with -r\n"); exit(1); } if (argv[2] == 0) exit(1); rflag = 1; usererr = doremotelogin(argv[2]); strncpy(host,argv[2],sizeof(host)); if (domain != NULL && (p = index(argv[2], '.')) && strcmp(p, domain) == 0) *p = 0; SCPYN(utmp.ut_host, argv[2]); argc -= 2; argv += 2; continue; } if (strcmp(argv[1], "-h") == 0) { if (getuid() == 0) { if (rflag || hflag) { printf("Only one of -r and -h allowed\n"); exit(1); } hflag = 1; strncpy(host,argv[2],sizeof(host)); if (domain != NULL && (p = index(argv[2], '.')) && strcmp(p, domain) == 0) *p = 0; SCPYN(utmp.ut_host, argv[2]); } argc -= 2; argv += 2; continue; } if (strcmp(argv[1], "-f") == 0 && argc > 2) { if (rflag) { printf("Only one of -r and -f allowed\n"); exit(1); } fflag = 1; SCPYN(utmp.ut_name, argv[2]); argc -= 2; argv += 2; continue; } if (strcmp(argv[1], "-p") == 0) { argc--; argv++; pflag = 1; continue; } break; } ioctl(0, TIOCLSET, &zero); ioctl(0, TIOCNXCL, 0); ioctl(0, FIONBIO, &zero); ioctl(0, FIOASYNC, &zero); ioctl(0, TIOCGETP, &ttyb); /* * If talking to an rlogin process, * propagate the terminal type and * baud rate across the network. */ if (rflag) doremoteterm(term, &ttyb); ttyb.sg_erase = CERASE; ttyb.sg_kill = CKILL; ioctl(0, TIOCSLTC, <c); ioctl(0, TIOCSETC, &tc); ioctl(0, TIOCSETP, &ttyb); for (t = getdtablesize(); t > 2; t--) close(t); ttyn = ttyname(0); if (ttyn == (char *)0 || *ttyn == '\0') ttyn = "/dev/tty??"; tty = rindex(ttyn, '/'); if (tty == NULL) tty = ttyn; else tty++; openlog("login", LOG_ODELAY, LOG_AUTH); t = 0; invalid = FALSE; pwok = authfile(host); do { ldisc = 0; ioctl(0, TIOCSETD, &ldisc); if (fflag == 0) SCPYN(utmp.ut_name, ""); /* * Name specified, take it. */ if (argc > 1) { SCPYN(utmp.ut_name, argv[1]); argc = 0; } /* * If remote login take given name, * otherwise prompt user for something. */ if (rflag && !invalid) SCPYN(utmp.ut_name, lusername); else { getloginname(&utmp); if (utmp.ut_name[0] == '-') { puts("login names may not start with '-'."); invalid = TRUE; continue; } } invalid = FALSE; if (!strcmp(pwd->pw_shell, "/bin/csh")) { ldisc = NTTYDISC; ioctl(0, TIOCSETD, &ldisc); } if (fflag) { int uid = getuid(); if (uid != 0 && uid != pwd->pw_uid) fflag = 0; /* * Disallow automatic login for root. */ if (pwd->pw_uid == 0) fflag = 0; } /* * If no remote login authentication and * a password exists for this user, prompt * for one and verify it. */ if (usererr == -1 && fflag == 0 && *pwd->pw_passwd != '\0') { char *pp; struct skey skey; int i; char buf[256],*cp; void rip(); struct sgttyb ttyf,ttysave; int fflags,lword,lwordsav;#ifdef OLD setpriority(PRIO_PROCESS, 0, -4); pp = getpass("Password:"); namep = crypt(pp, pwd->pw_passwd); setpriority(PRIO_PROCESS, 0, 0); if (strcmp(namep, pwd->pw_passwd)) invalid = TRUE;#endif invalid = TRUE; /* Guilty til proven innocent */ if(feof(stdin)) exit(0) ; /* Attempt a s/key challenge */ i = skeychallenge(&skey,utmp.ut_name, skeyprompt); printf("%s\n",skeyprompt); if(!pwok) printf("(s/key required)\n"); printf("Password:"); fflush(stdout); /* Set normal line editing */ fflags = fcntl(fileno(stdin),F_GETFL,0); fcntl(fileno(stdin),F_SETFL,fflags & ~FNDELAY); ioctl(fileno(stdin),TIOCLGET,&lword); ioctl(fileno(stdin),TIOCLGET,&lwordsav); lword |= LCRTERA|LCRTKIL; ioctl(fileno(stdin),TIOCLSET,&lword); /* Turn off echoing */ ioctl(fileno(stdin), TIOCGETP, &ttyf); ioctl(fileno(stdin), TIOCGETP, &ttysave); ttyf.sg_flags &= ~(ECHO|RAW|CBREAK); ttyf.sg_flags |= CRMOD; ioctl(fileno(stdin),TIOCSETP,&ttyf); /* Read password */ fgets(buf,sizeof(buf),stdin); rip(buf); if(feof(stdin)) exit(0); if(strlen(buf) == 0){ /* Null line entered; turn echoing back on * and read again */ printf(" (echo on)\nPassword:"); fflush(stdout); ttyf.sg_flags |= (ECHO|CRTBS); ioctl(fileno(stdin),TIOCSETP,&ttyf); fgets(buf,sizeof(buf),stdin); rip(buf); if(feof(stdin)) exit(0); } else { printf("\n"); } /* Restore previous tty modes */ fcntl(fileno(stdin),F_SETFL,fflags); ioctl(fileno(stdin),TIOCSETP,&ttysave); ioctl(fileno(stdin),TIOCLSET,&lwordsav); if(i == 0 && skeyverify(&skey,buf) == 0 && (pwd->pw_passwd[0] != '*' && pwd->pw_passwd[0] != '#' ) ){ /* S/Key authentication succeeded */ if(skey.n < 5) printf("Warning! Change password soon\n"); invalid = FALSE; } else if(pwok){ /* Try regular password check, if allowed */ pp = crypt(buf,pwd->pw_passwd); if(strcmp(pp,pwd->pw_passwd) == 0) invalid = FALSE; /* Success */ } } /* * If user not super-user, check for logins disabled. */ if (pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) > 0) { while ((c = getc(nlfd)) != EOF) putchar(c); fflush(stdout); sleep(5); exit(0); } /* * If valid so far and root is logging in, * see if root logins on this terminal are permitted. */ if (!invalid && pwd->pw_uid == 0 && !rootterm(tty)) { if (utmp.ut_host[0]) syslog(LOG_CRIT, "ROOT LOGIN REFUSED ON %s FROM %.*s", tty, HMAX, utmp.ut_host); else syslog(LOG_CRIT, "ROOT LOGIN REFUSED ON %s", tty); invalid = TRUE; } if (invalid) { printf("Login incorrect\n"); if (++t >= 5) { if (utmp.ut_host[0]) syslog(LOG_ERR, "REPEATED LOGIN FAILURES ON %s FROM %.*s, %.*s", tty, HMAX, utmp.ut_host, NMAX, utmp.ut_name); else syslog(LOG_ERR, "REPEATED LOGIN FAILURES ON %s, %.*s", tty, NMAX, utmp.ut_name); ioctl(0, TIOCHPCL, (struct sgttyb *) 0); close(0), close(1), close(2); sleep(10); exit(1); } } if (*pwd->pw_shell == '\0') pwd->pw_shell = "/bin/sh"; if (chdir(pwd->pw_dir) < 0 && !invalid ) { if (chdir("/") < 0) { printf("No directory!\n"); invalid = TRUE; } else { printf("No directory! %s\n", "Logging in with home=/"); pwd->pw_dir = "/"; } } /* * Remote login invalid must have been because * of a restriction of some sort, no extra chances. */ if (!usererr && invalid) exit(1); } while (invalid);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -