|
|
1.1 root 1: #include <stdio.h>
2: #include <pwd.h>
3: #include <signal.h>
4: #include <sys/types.h>
5: #include <sys/ioctl.h>
6: #include <errno.h>
7: #include <utmp.h>
8:
9: #include <sys/wait.h>
10: #include <netdb.h>
11: #include <sys/inet/in.h>
12: #include <sys/socket.h>
13:
14: extern errno;
15: extern char **environ;
16:
17: #define PATH "PATH=/usr/fbin:/bin:/usr/bin:/usr/usgbin"
18: char home[128], mail[128], user[32], shell[128];
19:
20: char *envinit[] = {
21: home, PATH, mail, user, shell,
22: NULL};
23:
24: int debug;
25: int nfd;
26: char *cmdname;
27: struct sockaddr_in sin = { AF_INET }, from;
28:
29:
30: main(argc, argv)
31: int argc;
32: char *argv[];
33: {
34: struct servent *sp;
35: register int c, i;
36: int f;
37: short lport = -1;
38: char *p, *rindex();
39: int reapchild();
40:
41: cmdname = argv[0];
42: p = rindex(cmdname, '/');
43: if (p != NULL) cmdname = p+1;
44:
45: for(i = 1; i < argc; i++) {
46: if(argv[i][0] == '-') switch(argv[i][1]) {
47: case 'd':
48: debug++;
49: continue;
50: default:
51: fprintf(stderr, "Usage: %s [-d] [port]\n", cmdname);
52: exit(1);
53: } else
54: lport = atoi(argv[i]);
55: }
56:
57: if (lport > 0) sin.sin_port = htons(lport);
58: else {
59: sp = getservbyname("uucp", "tcp");
60: if (sp == 0) {
61: fprintf(stderr, "uucpsrv: tcp/rlogin: unknown service\n");
62: exit(1);
63: }
64: sin.sin_port = sp->s_port;
65: }
66:
67: if (!debug) {
68:
69: if (fork())
70: exit(0);
71: for (f = 0; f < 10; f++)
72: (void) close(f);
73: (void) open("/", 0);
74: (void) dup2(0, 1);
75: (void) dup2(0, 2);
76: { int tt = open("/dev/tty", 2);
77: if (tt > 0) {
78: ioctl(tt, TIOCNOTTY, 0);
79: close(tt);
80: }
81: }
82: }
83: if (debug < 2) {
84: f = socket(AF_INET, SOCK_STREAM, 0, 0);
85: if (f < 0) {
86: perror("rlogind: socket");
87: exit(1);
88: }
89: if (bind(f, &sin, sizeof (sin), 0) < 0) {
90: perror("rlogind: bind");
91: exit(1);
92: }
93: signal(SIGCHLD, reapchild);
94: listen(f, 10);
95: for (;;) {
96: int len = sizeof (from);
97:
98: nfd = accept(f, &from, &len, 0);
99: if (nfd < 0) {
100: if (errno == EINTR)
101: continue;
102: perror("rlogind: accept");
103: continue;
104: }
105: if (fork() == 0) {
106: signal(SIGCHLD, SIG_IGN);
107: signal(SIGPIPE, SIG_IGN);
108: setbuf(stdin, NULL);
109: if (nfd != 0) close(0);
110: if (nfd != 1) close(1);
111: if (!debug) {
112: if (nfd != 2) close(2);
113: }
114: dup(nfd); dup(nfd); dup(nfd);
115: for (i=3; i<25; i++) close(i);
116: break;
117: }
118: close(nfd);
119: }
120: }
121: else {
122: fprintf(stderr, "pseudo-connect port %d\n", lport);
123: nfd = 2;
124: }
125: login();
126: if (debug < 2) {
127: fprintf(stderr, "%s: no shell!\n", cmdname);
128: exit(1);
129: }
130: else exit(0);
131: }
132:
133: reapchild()
134: {
135: union wait status;
136:
137: while (wait3(&status, WNOHANG, 0) > 0)
138: ;
139: }
140:
141: #define NMAX (sizeof utmp.ut_name + 1)
142: #define PWMAX 20
143: char *nolog = "/etc/nologin";
144: struct utmp utmp;
145:
146: login()
147: {
148: int c;
149: char lname[NMAX];
150: char pwt[PWMAX];
151: struct passwd *pwd, *getpwnam();
152: static struct passwd nouser = {"none", "nope"};
153: FILE *nlfd;
154: char *crypt();
155:
156: do {
157: instr("login:", lname, NMAX);
158: } while (lname[0] == '\0');
159:
160: if ((pwd = getpwnam(lname)) == NULL) {
161: pwd = &nouser;
162: }
163: if (*pwd->pw_passwd != '\0') {
164: instr("Password:", pwt, PWMAX);
165: if (strcmp(crypt(pwt, pwd->pw_passwd), pwd->pw_passwd)) {
166: fprintf(stderr, "Login incorrect\n");
167: exit(1);
168: }
169: }
170: if ((nlfd = fopen(nolog, "r")) > 0) {
171: /* logins are disabled */
172: while ((c = getc(nlfd)) != EOF) {
173: putc(c, stderr);
174: }
175: exit(0);
176: }
177: if (*pwd->pw_shell == '\0')
178: pwd->pw_shell = "/bin/sh";
179: if (chdir(pwd->pw_dir) < 0) {
180: if (chdir("/") < 0) {
181: fprintf(stderr, "No directory!\n");
182: exit(1);
183: } else {
184: fprintf(stderr, "No directory! Logging in with home=/\n");
185: pwd->pw_dir = "/";
186: }
187: }
188: strncpy(utmp.ut_name, lname, sizeof utmp.ut_name);
189: logit();
190: setgid(pwd->pw_gid);
191: setuid(pwd->pw_uid);
192: signal(SIGHUP, SIG_IGN);
193: signal(SIGINT, SIG_IGN);
194: signal(SIGQUIT, SIG_IGN);
195: envset(pwd);
196: dosh(pwd->pw_shell);
197: }
198:
199: instr(prompt, buf, len) char *buf; int len;
200: {
201: register char *p, c;
202:
203: p = buf;
204: fputs(prompt, stdout);
205: fflush(stdout);
206: while ((c = getchar()) != '\n') {
207: if (c == '\r') break;
208: if (c == ' ')
209: c = '_';
210: if (c == EOF)
211: exit(0);
212: if (p < buf+len-1)
213: *p++ = c;
214: }
215: *p = '\0';
216: }
217:
218: envset(pwd) struct passwd *pwd;
219: {
220:
221: sprintf(home, "HOME=%s", pwd->pw_dir);
222: sprintf(shell, "SHELL=%s", pwd->pw_shell);
223: sprintf(mail, "MAIL=/usr/spool/mail/%s", pwd->pw_name);
224: sprintf(user, "USER=%s", pwd->pw_name);
225: environ = envinit;
226: }
227:
228: dosh(shellp) char *shellp;
229: {
230: char shn[300], *p, *rindex();
231:
232: p = rindex(shellp, '/');
233: sprintf(shn, "-%s", (p == NULL ? shellp : p+1));
234: if (debug > 1)
235: fprintf(stderr, "exec %s %s\n", shellp, shn);
236: else execl(shellp, shn, 0);
237: }
238:
239: logit()
240: {
241: setpgrp();
242: #if 0==1
243: /* What we do here is create a utmp entry, then fork and wait */
244: /* for the child to terminate so we can record the new entry. */
245: /* The main process never returns from this subroutine, only */
246: /* the child. */
247: struct stat statb;
248: int pid, status;
249: char tmp[100];
250:
251: if ((pid = fork()) <= 0) { /* If fork fails -- no entry made */
252: setpgrp();
253: return;
254: }
255:
256: if (fstat(0, &statb) == 0)
257: sprintf(tmp, "%*.*d", sizeof utmp.ut_id,
258: sizeof utmp.ut_id, statb.st_dev & 0xff);
259: else strcpy(tmp, "unet");
260: strncpy(utmp.ut_id, tmp, sizeof utmp.ut_id);
261:
262: ut.ut_pid = pid;
263: ut.ut_type = USER_PROCESS;
264: utmp.ut_exit.e_termination = 0;
265: utmp.ut_exit.e_exit = 0;
266: time(&utmp.ut_time);
267: pututline(&utmp);
268: endutent();
269:
270: while ((i = wait(&status)) != pid)
271: if (i == ENOCHILD) break;
272:
273: ut.ut_type = DEAD_PROCESS;
274: ut.ut_exit.e_termination = status & 0xff;
275: ut.ut_exit.e_exit = (status >> 8) & 0xff;
276: #endif
277: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.