|
|
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 <setjmp.h>
13: #include <pwd.h>
14: #include <grp.h>
15: #include <stdio.h>
16: #include <sys/stat.h>
17: #include <sys/lnode.h>
18: #include <sys/share.h>
19: #include <shares.h>
20: #include <errno.h>
21:
22: #define DEFSHARES 1 /* Default number of shares for a group 0 user */
23: #define SYSERROR (-1)
24: #define MINUSAGE 1e6
25: #ifndef ETOOMANYU
26: #define ETOOMANYU ENOSPC /* Must go in errno.h or lnode.h */
27: #endif
28: #define SCPYN(a, b) strncpy(a, b, sizeof(a))
29:
30: #define ISIZE 32
31: #define POSTMKSIZ sizeof "From Sun Jan 00 00:00:00 1979"
32: char maildir[30] = "/usr/spool/mail/";
33: struct passwd nouser = {"", "nope"};
34: struct utmp utmp;
35: char minusnam[16] = "-";
36: char homedir[64] = "HOME=";
37: char path[] = "PATH=:/bin:/usr/bin";
38: char **env;
39: int nenv = 0;
40: char nolog[] = "/etc/nologin";
41: struct passwd *pwd;
42: struct passwd *pwdecode();
43: char *cmd;
44:
45: struct passwd *getpwnam();
46: char *strcat();
47: int setpwent();
48: char *ttyname();
49: char *crypt();
50: char *getpass();
51: char *strrchr(), *strchr();
52: extern char **environ;
53:
54: main(argc, argv)
55: char **argv;
56: {
57: register char *namep;
58: char input[ISIZE];
59: char pwline[128];
60: int t, f, c;
61: char *ttyn;
62: int neednopass = 0;
63: int hangitup = 0;
64: int ntries = 0;
65: FILE *nlfd;
66: int i;
67: struct ttydevb tb;
68:
69: alarm(60);
70: signal(SIGQUIT, SIG_IGN);
71: signal(SIGINT, SIG_IGN);
72: signal(SIGHUP, SIG_IGN);
73: nice(-100);
74: nice(20);
75: nice(0);
76: #define ONOFILE 20
77: for (t=NSYSFILE; t<ONOFILE; t++)
78: close(t);
79: ttyn = ttyname(0);
80: if (ttyn==0)
81: ttyn = "/dev/tty??";
82: SCPYN(input, "");
83: switch(argc) {
84:
85: case 0:
86: case 1:
87: break;
88:
89: case 2:
90: SCPYN(input, argv[1]);
91: break;
92:
93: default:
94: if (strcmp(argv[1], "-f")==0 || strcmp(argv[1], "-p")==0) {
95: if (getuid()!=0) {
96: printf("login: not super-user\n");
97: exit(1);
98: }
99: neednopass++;
100: if (strcmp(argv[1], "-f")==0)
101: SCPYN(input, argv[2]);
102: else {
103: SCPYN(pwline, argv[2]);
104: pwd = pwdecode(pwline);
105: SCPYN(input, pwd->pw_name);
106: }
107: if (argc>3)
108: cmd = argv[3];
109: } else
110: exit(1);
111: }
112: loop:
113: if (ntries) {
114: if (ntries > 5 || hangitup) {
115: ioctl(0, TIOCGDEV, &tb);
116: tb.ispeed = tb.ospeed = 0;
117: ioctl(0, TIOCSDEV, &tb);
118: sleep(5);
119: exit(1);
120: }
121: neednopass = 0;
122: pwd = NULL;
123: SCPYN(input, "");
124: }
125: ntries++;
126: while (input[0] == '\0') {
127: namep = input;
128: printf("login: ");
129: while ((c = getchar()) != '\n') {
130: if(c == ' ')
131: c = '_';
132: if (c == EOF)
133: exit(0);
134: if (namep < input + ISIZE - 1)
135: *namep++ = c;
136: }
137: *namep = NULL;
138: }
139: SCPYN(utmp.ut_name, input);
140: utmp.ut_time = 0;
141: if (pwd == NULL) {
142: setpwent();
143: if ((pwd = getpwnam(input)) == NULL)
144: pwd = &nouser;
145: endpwent();
146: }
147: if (namep = strchr(utmp.ut_name, '\001'))
148: if (namep[1]=='L' && namep[2]=='\002') /* loopback? */
149: hangitup++;
150: time(&utmp.ut_time);
151: SCPYN(utmp.ut_line, strchr(ttyn+1, '/')+1);
152: if (*pwd->pw_passwd != '\0' && !neednopass) {
153: namep = crypt(getpass("Password:"), pwd->pw_passwd);
154: if (strcmp(namep, pwd->pw_passwd)) {
155: /* magic string detects loopbacks */
156: printf("\001L\002ogin incorrect\n");
157: f = open("/usr/adm/xtmp", 1);
158: if (f > 0) {
159: lseek(f, 0L, 2);
160: write(f, (char *)&utmp, sizeof(utmp));
161: close(f);
162: }
163: goto loop;
164: }
165: }
166: if(pwd->pw_uid != 0 && (nlfd = fopen(nolog, "r")) != NULL){
167: while((c = getc(nlfd)) != EOF)
168: putchar(c);
169: exit(0);
170: }
171: if(setuplimits(pwd) < 0)
172: goto loop;
173: (void)setupgroups(pwd);
174: if(chdir(pwd->pw_dir) < 0) {
175: printf("No directory\n");
176: if(pwd->pw_uid != 0 || (access(nolog, 0) < 0))
177: goto loop;
178: }
179: setlogname(utmp.ut_name);
180: if (cmd) { /* remote exec */
181: t = strlen(utmp.ut_name);
182: if (t < sizeof(utmp.ut_name))
183: utmp.ut_name[t] = '*';
184: }
185: t = ttyslot();
186: if (t>0 && (f = open("/etc/utmp", 1)) >= 0) {
187: lseek(f, (long)(t*sizeof(utmp)), 0);
188: write(f, (char *)&utmp, sizeof(utmp));
189: close(f);
190: }
191: if (t>0 && (f = open("/usr/adm/wtmp", 1)) >= 0) {
192: lseek(f, 0L, 2);
193: write(f, (char *)&utmp, sizeof(utmp));
194: close(f);
195: }
196: chown(ttyn, pwd->pw_uid, pwd->pw_gid);
197: chmod(ttyn, 0622);
198: setgid(pwd->pw_gid);
199: setuid(pwd->pw_uid);
200: if (*pwd->pw_shell == '\0')
201: pwd->pw_shell = "/bin/sh";
202: strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
203: nenv = 0;
204: for(i = 0; environ[i]; i++)
205: ;
206: env = (char **) malloc(sizeof(char *) * (i + 10));
207: if (env == NULL) {
208: printf("No memory for environment.\n");
209: exit(1);
210: }
211: for (i = 0; environ[i]; i++) {
212: if (strncmp(environ[i], "HOME=", 5) == 0)
213: continue;
214: if (strncmp(environ[i], "PATH=", 5) == 0)
215: continue;
216: env[nenv++] = environ[i];
217: }
218: if(homedir[0])
219: env[nenv++] = homedir;
220: if(path[0])
221: env[nenv++] = path;
222: env[nenv] = NULL;
223: if ((namep = strrchr(pwd->pw_shell, '/')) == NULL)
224: namep = pwd->pw_shell;
225: else
226: namep++;
227: strcat(minusnam, namep);
228: alarm(0);
229: umask(02);
230: if (cmd==NULL) {
231: showmotd();
232: strcat(maildir, pwd->pw_name);
233: if(access(maildir,4)==0) {
234: struct stat statb;
235: stat(maildir, &statb);
236: if (statb.st_size > POSTMKSIZ)
237: printf("You have mail.\n");
238: }
239: }
240: signal(SIGQUIT, SIG_DFL);
241: signal(SIGINT, SIG_DFL);
242: signal(SIGHUP, SIG_DFL);
243: environ = env;
244: if (cmd==NULL)
245: execlp(pwd->pw_shell, minusnam, 0);
246: else {
247: env[nenv++] = "REXEC=1";
248: ioctl(0, TIOCEXCL, (void *)NULL);
249: env[nenv] = 0;
250: execlp(pwd->pw_shell, minusnam, "-c", cmd, (char *)0);
251: }
252: printf("No shell\n");
253: exit(0);
254: }
255:
256: int stopmotd;
257: catch()
258: {
259: signal(SIGINT, SIG_IGN);
260: stopmotd++;
261: }
262:
263: showmotd()
264: {
265: FILE *mf;
266: register c;
267:
268: signal(SIGINT, catch);
269: if((mf = fopen("/etc/motd","r")) != NULL) {
270: while((c = getc(mf)) != EOF && stopmotd == 0)
271: putchar(c);
272: fclose(mf);
273: }
274: signal(SIGINT, SIG_IGN);
275: }
276:
277: /*
278: ** Set up parameters for share scheduler
279: */
280:
281: int catchsys();
282: jmp_buf Sigsysbuf;
283:
284: int
285: setuplimits(pwd)
286: register struct passwd *pwd;
287: {
288: register int (*oldsig)();
289: register unsigned long extime;
290: struct sh_consts shconsts;
291: struct lnode share;
292:
293: if ( pwd->pw_uid == 0 )
294: return 0; /* root needs no set-up */
295:
296: oldsig = signal(SIGSYS, catchsys);
297:
298: if
299: (
300: setjmp(Sigsysbuf)
301: ||
302: limits((struct lnode *)&shconsts, L_GETCOSTS) == SYSERROR
303: ||
304: (Shareflags & NOSHARE)
305: )
306: {
307: (void)signal(SIGSYS, oldsig);
308: return 0; /* Share not installed/active */
309: }
310:
311: (void)signal(SIGSYS, oldsig);
312:
313: if ( (extime = getshares(&share, pwd->pw_uid, 0)) == 0 )
314: {
315: share.l_shares = DEFSHARES;
316: share.l_usage = MINUSAGE;
317: }
318: else
319: if ( limits(&share, L_OTHLIM) == SYSERROR )
320: {
321: /*
322: ** Decay usage by time since last access.
323: */
324:
325: if ( (extime = (utmp.ut_time - extime) / Delta) > 0 )
326: {
327: extern double pow();
328:
329: share.l_usage *= pow(DecayUsage, (float)extime);
330: if ( share.l_usage < MINUSAGE )
331: share.l_usage = MINUSAGE;
332: }
333: }
334:
335: if ( setlimits(&share) == SYSERROR )
336: {
337: if ( errno == ETOOMANYU )
338: {
339: char * cp = "other";
340:
341: share.l_uid = OTHERUID;
342:
343: if ( limits(&share, L_OTHLIM) != SYSERROR )
344: (void)setlimits(&share);
345: else
346: cp = "root";
347:
348: printf("Warning: system out of share structures, using \"%s\".\n", cp);
349: }
350: else
351: perror("setlimits");
352: }
353:
354: closeshares();
355:
356: return 0;
357: }
358:
359: int
360: catchsys(sig)
361: {
362: longjmp(Sigsysbuf, 1);
363: perror("longjmp");
364: abort();
365: }
366:
367: /*
368: ** Set up access groups.
369: */
370:
371: int
372: setupgroups(pwd)
373: register struct passwd *pwd;
374: {
375: register char ** cpp;
376: register short * gp;
377: register struct group * grp;
378: register int n;
379: short groups[NGROUPS];
380:
381: if ( getgroups(NGROUPS, groups) == SYSERROR )
382: return; /* Not installed */
383:
384: (void)setgrent();
385:
386: gp = groups;
387:
388: while ( gp < &groups[NGROUPS] && (grp = getgrent()) != (struct group *)0 )
389: for ( cpp = grp->gr_mem ; *cpp != (char *)0 ; cpp++ )
390: if ( strcmp(*cpp, pwd->pw_name) == 0 && grp->gr_gid != pwd->pw_gid )
391: {
392: *gp++ = grp->gr_gid;
393: break;
394: }
395:
396: (void)endgrent();
397:
398: if ( (n = gp-groups) == 0 )
399: return;
400:
401: if ( setgroups(n, groups) == SYSERROR )
402: perror("setgroups");
403: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.