|
|
1.1 root 1: /*
2: * login [ -f name ] [ -p passwdline ] [ command ]
3: * -f: if su, log in with no password
4: * -p: if su, use entire password line.
5: * command: if given, just execute command
6: */
7:
8: #include <sys/types.h>
9: #include <sgtty.h>
10: #include <utmp.h>
11: #include <signal.h>
12: #include <pwd.h>
13: #include <stdio.h>
14: #include <sys/stat.h>
15: #define SCPYN(a, b) strncpy(a, b, sizeof(a))
16:
17: #define ISIZE 32
18: #define POSTMKSIZ sizeof "From Sun Jan 00 00:00:00 1979"
19: char maildir[30] = "/usr/spool/mail/";
20: struct passwd nouser = {"", "nope"};
21: struct sgttyb ttyb;
22: struct utmp utmp;
23: char minusnam[16] = "-";
24: char homedir[64] = "HOME=";
25: char path[] = "PATH=:/bin:/usr/bin";
26: char **env;
27: int nenv = 0;
28: char nolog[] = "/etc/nologin";
29: struct passwd *pwd;
30: struct passwd *pwdecode();
31: char *cmd;
32:
33: struct passwd *getpwnam();
34: char *strcat();
35: int setpwent();
36: char *ttyname();
37: char *crypt();
38: char *getpass();
39: char *rindex(), *index();
40: extern char **environ;
41:
42: main(argc, argv)
43: char **argv;
44: {
45: register char *namep;
46: char input[ISIZE];
47: char pwline[128];
48: int t, f, c;
49: char *ttyn;
50: int neednopass = 0;
51: int hangitup = 0;
52: int ntries = 0;
53: FILE *nlfd;
54: int i;
55:
56: alarm(60);
57: signal(SIGQUIT, SIG_IGN);
58: signal(SIGINT, SIG_IGN);
59: signal(SIGHUP, SIG_IGN);
60: nice(-100);
61: nice(20);
62: nice(0);
63: gtty(0, &ttyb);
64: #define ONOFILE 20
65: for (t=NSYSFILE; t<ONOFILE; t++)
66: close(t);
67: ttyn = ttyname(0);
68: if (ttyn==0)
69: ttyn = "/dev/tty??";
70: SCPYN(input, "");
71: switch(argc) {
72:
73: case 0:
74: case 1:
75: break;
76:
77: case 2:
78: SCPYN(input, argv[1]);
79: break;
80:
81: default:
82: if (strcmp(argv[1], "-f")==0 || strcmp(argv[1], "-p")==0) {
83: if (getuid()!=0) {
84: printf("login: not super-user\n");
85: exit(1);
86: }
87: neednopass++;
88: if (strcmp(argv[1], "-f")==0)
89: SCPYN(input, argv[2]);
90: else {
91: SCPYN(pwline, argv[2]);
92: pwd = pwdecode(pwline);
93: SCPYN(input, pwd->pw_name);
94: }
95: if (argc>3)
96: cmd = argv[3];
97: } else
98: exit(1);
99: }
100: loop:
101: if (ntries) {
102: if (ntries > 5 || hangitup) {
103: ttyb.sg_ispeed = ttyb.sg_ospeed = 0;
104: stty(0, &ttyb);
105: sleep(5);
106: exit(1);
107: }
108: neednopass = 0;
109: pwd = NULL;
110: SCPYN(input, "");
111: }
112: ntries++;
113: while (input[0] == '\0') {
114: namep = input;
115: printf("login: ");
116: while ((c = getchar()) != '\n') {
117: if(c == ' ')
118: c = '_';
119: if (c == EOF)
120: exit(0);
121: if (namep < input + ISIZE - 1)
122: *namep++ = c;
123: }
124: *namep = NULL;
125: }
126: SCPYN(utmp.ut_name, input);
127: utmp.ut_time = 0;
128: if (pwd == NULL) {
129: setpwent();
130: if ((pwd = getpwnam(input)) == NULL)
131: pwd = &nouser;
132: endpwent();
133: }
134: if (namep = index(utmp.ut_name, '\001'))
135: if (namep[1]=='L' && namep[2]=='\002') /* loopback? */
136: hangitup++;
137: time(&utmp.ut_time);
138: SCPYN(utmp.ut_line, index(ttyn+1, '/')+1);
139: if (pwd->pw_uid == 0) /* root loses */
140: neednopass = 0;
141: if (*pwd->pw_passwd != '\0' && !neednopass) {
142: namep = crypt(getpass("Password:"), pwd->pw_passwd);
143: if (strcmp(namep, pwd->pw_passwd)) {
144: /* magic string detects loopbacks */
145: printf("\001L\002ogin incorrect\n");
146: f = open("/usr/adm/xtmp", 1);
147: if (f > 0) {
148: lseek(f, 0L, 2);
149: write(f, (char *)&utmp, sizeof(utmp));
150: close(f);
151: }
152: goto loop;
153: }
154: }
155: if(pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) != NULL){
156: while((c = getc(nlfd)) != EOF)
157: putchar(c);
158: exit(0);
159: }
160: if(chdir(pwd->pw_dir) < 0) {
161: printf("No directory\n");
162: if(pwd->pw_uid != 0 || (access(nolog, 0) < 0))
163: goto loop;
164: }
165: if (cmd) { /* remote exec */
166: t = strlen(utmp.ut_name);
167: if (t < sizeof(utmp.ut_name))
168: utmp.ut_name[t] = '*';
169: }
170: t = ttyslot();
171: if (t>0 && (f = open("/etc/utmp", 1)) >= 0) {
172: lseek(f, (long)(t*sizeof(utmp)), 0);
173: write(f, (char *)&utmp, sizeof(utmp));
174: close(f);
175: }
176: if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) {
177: lseek(f, 0L, 2);
178: write(f, (char *)&utmp, sizeof(utmp));
179: close(f);
180: }
181: chown(ttyn, pwd->pw_uid, pwd->pw_gid);
182: chmod(ttyn, 0622);
183: setgid(pwd->pw_gid);
184: setuid(pwd->pw_uid);
185: if (*pwd->pw_shell == '\0')
186: pwd->pw_shell = "/bin/sh";
187: strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
188: nenv = 0;
189: for(i = 0; environ[i]; i++)
190: ;
191: env = (char **) malloc(sizeof(char *) * (i + 10));
192: if (env == NULL) {
193: printf("No memory for environment.\n");
194: exit(1);
195: }
196: for (i = 0; environ[i]; i++) {
197: if (strncmp(environ[i], "HOME=", 5) == 0)
198: continue;
199: if (strncmp(environ[i], "PATH=", 5) == 0)
200: continue;
201: env[nenv++] = environ[i];
202: }
203: if(homedir[0])
204: env[nenv++] = homedir;
205: if(path[0])
206: env[nenv++] = path;
207: env[nenv] = NULL;
208: if ((namep = rindex(pwd->pw_shell, '/')) == NULL)
209: namep = pwd->pw_shell;
210: else
211: namep++;
212: strcat(minusnam, namep);
213: alarm(0);
214: umask(02);
215: if (cmd==NULL) {
216: showmotd();
217: strcat(maildir, pwd->pw_name);
218: if(access(maildir,4)==0) {
219: struct stat statb;
220: stat(maildir, &statb);
221: if (statb.st_size > POSTMKSIZ)
222: printf("You have mail.\n");
223: }
224: }
225: signal(SIGQUIT, SIG_DFL);
226: signal(SIGINT, SIG_DFL);
227: signal(SIGHUP, SIG_DFL);
228: environ = env;
229: if (cmd==NULL)
230: execlp(pwd->pw_shell, minusnam, 0);
231: else {
232: env[nenv++] = "REXEC=1";
233: ioctl(0, TIOCEXCL, NULL);
234: env[nenv] = 0;
235: execlp(pwd->pw_shell, minusnam, "-c", cmd, (char *)0);
236: }
237: printf("No shell\n");
238: exit(0);
239: }
240:
241: int stopmotd;
242: catch()
243: {
244: signal(SIGINT, SIG_IGN);
245: stopmotd++;
246: }
247:
248: showmotd()
249: {
250: FILE *mf;
251: register c;
252:
253: signal(SIGINT, catch);
254: if((mf = fopen("/etc/motd","r")) != NULL) {
255: while((c = getc(mf)) != EOF && stopmotd == 0)
256: putchar(c);
257: fclose(mf);
258: }
259: signal(SIGINT, SIG_IGN);
260: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.