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