1: #ifndef lint 2: static char sccsid[] = "@(#)uucpd.c 5.4 (Berkeley) 6/23/85"; 3: #endif 4: 5: /* 6: * 4.2BSD or 2.9BSD TCP/IP server for uucico 7: * uucico's TCP channel causes this server to be run at the remote end. 8: */ 9: 10: #include "uucp.h" 11: #include <netdb.h> 12: #ifdef BSD2_9 13: #include <sys/localopts.h> 14: #include <sys/file.h> 15: #endif BSD2_9 16: #include <signal.h> 17: #include <errno.h> 18: #include <sys/socket.h> 19: #include <netinet/in.h> 20: #include <sys/wait.h> 21: #include <sys/ioctl.h> 22: #include <pwd.h> 23: #include <lastlog.h> 24: 25: #if !defined(BSD4_2) && !defined(BSD2_9) 26: --- You must have either BSD4_2 or BSD2_9 defined for this to work 27: #endif !BSD4_2 && !BSD2_9 28: #if defined(BSD4_2) && defined(BSD2_9) 29: --- You may not have both BSD4_2 and BSD2_9 defined for this to work 30: #endif /* check for stupidity */ 31: 32: char lastlog[] = "/usr/adm/lastlog"; 33: struct sockaddr_in hisctladdr; 34: int hisaddrlen = sizeof hisctladdr; 35: struct sockaddr_in myctladdr; 36: int mypid; 37: 38: char Username[64]; 39: char *nenv[] = { 40: Username, 41: NULL, 42: }; 43: extern char **environ; 44: 45: main(argc, argv) 46: int argc; 47: char **argv; 48: { 49: #ifndef BSDINETD 50: register int s, tcp_socket; 51: struct servent *sp; 52: #endif !BSDINETD 53: extern int errno; 54: int dologout(); 55: 56: environ = nenv; 57: #ifdef BSDINETD 58: close(1); close(2); 59: dup(0); dup(0); 60: hisaddrlen = sizeof (hisctladdr); 61: if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) { 62: fprintf(stderr, "%s: ", argv[0]); 63: perror("getpeername"); 64: _exit(1); 65: } 66: if (fork() == 0) 67: doit(&hisctladdr); 68: dologout(); 69: exit(1); 70: #else !BSDINETD 71: sp = getservbyname("uucp", "tcp"); 72: if (sp == NULL){ 73: perror("uucpd: getservbyname"); 74: exit(1); 75: } 76: if (fork()) 77: exit(0); 78: if ((s=open("/dev/tty", 2)) >= 0){ 79: ioctl(s, TIOCNOTTY, (char *)0); 80: close(s); 81: } 82: 83: bzero((char *)&myctladdr, sizeof (myctladdr)); 84: myctladdr.sin_family = AF_INET; 85: myctladdr.sin_port = sp->s_port; 86: #ifdef BSD4_2 87: tcp_socket = socket(AF_INET, SOCK_STREAM, 0); 88: if (tcp_socket < 0) { 89: perror("uucpd: socket"); 90: exit(1); 91: } 92: if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) { 93: perror("uucpd: bind"); 94: exit(1); 95: } 96: listen(tcp_socket, 3); /* at most 3 simultaneuos uucp connections */ 97: signal(SIGCHLD, dologout); 98: 99: for(;;) { 100: s = accept(tcp_socket, &hisctladdr, &hisaddrlen); 101: if (s < 0){ 102: if (errno == EINTR) 103: continue; 104: perror("uucpd: accept"); 105: exit(1); 106: } 107: if (fork() == 0) { 108: close(0); close(1); close(2); 109: dup(s); dup(s); dup(s); 110: close(tcp_socket); close(s); 111: doit(&hisctladdr); 112: exit(1); 113: } 114: close(s); 115: } 116: #endif BSD4_2 117: 118: #ifdef BSD2_9 119: for(;;) { 120: signal(SIGCHLD, dologout); 121: s = socket(SOCK_STREAM, 0, &myctladdr, 122: SO_ACCEPTCONN|SO_KEEPALIVE); 123: if (s < 0) { 124: perror("uucpd: socket"); 125: exit(1); 126: } 127: if (accept(s, &hisctladdr) < 0) { 128: if (errno == EINTR) { 129: close(s); 130: continue; 131: } 132: perror("uucpd: accept"); 133: exit(1); 134: } 135: if (fork() == 0) { 136: close(0); close(1); close(2); 137: dup(s); dup(s); dup(s); 138: close(s); 139: doit(&hisctladdr); 140: exit(1); 141: } 142: } 143: #endif BSD2_9 144: #endif !BSDINETD 145: } 146: 147: doit(sinp) 148: struct sockaddr_in *sinp; 149: { 150: char user[64], passwd[64]; 151: char *xpasswd, *crypt(); 152: struct passwd *pw, *getpwnam(); 153: 154: alarm(60); 155: printf("login: "); fflush(stdout); 156: if (readline(user, sizeof user) < 0) { 157: fprintf(stderr, "user read\n"); 158: return; 159: } 160: /* truncate username to 8 characters */ 161: user[8] = '\0'; 162: pw = getpwnam(user); 163: if (pw == NULL) { 164: fprintf(stderr, "user unknown\n"); 165: return; 166: } 167: if (strcmp(pw->pw_shell, UUCICO)) { 168: fprintf(stderr, "Login incorrect."); 169: return; 170: } 171: if (pw->pw_passwd && *pw->pw_passwd != '\0') { 172: printf("Password: "); fflush(stdout); 173: if (readline(passwd, sizeof passwd) < 0) { 174: fprintf(stderr, "passwd read\n"); 175: return; 176: } 177: xpasswd = crypt(passwd, pw->pw_passwd); 178: if (strcmp(xpasswd, pw->pw_passwd)) { 179: fprintf(stderr, "Login incorrect."); 180: return; 181: } 182: } 183: alarm(0); 184: sprintf(Username, "USER=%s", user); 185: dologin(pw, sinp); 186: setgid(pw->pw_gid); 187: #ifdef BSD4_2 188: initgroups(pw->pw_name, pw->pw_gid); 189: #endif BSD4_2 190: chdir(pw->pw_dir); 191: setuid(pw->pw_uid); 192: #ifdef BSD4_2 193: execl(UUCICO, "uucico", (char *)0); 194: #endif BSD4_2 195: #ifdef BSD2_9 196: sprintf(passwd, "-h%s", inet_ntoa(sinp->sin_addr)); 197: execl(UUCICO, "uucico", passwd, (char *)0); 198: #endif BSD2_9 199: perror("uucico server: execl"); 200: } 201: 202: readline(p, n) 203: register char *p; 204: register int n; 205: { 206: char c; 207: 208: while (n-- > 0) { 209: if (read(0, &c, 1) <= 0) 210: return(-1); 211: c &= 0177; 212: if (c == '\n' || c == '\r') { 213: *p = '\0'; 214: return(0); 215: } 216: *p++ = c; 217: } 218: return(-1); 219: } 220: 221: #include <utmp.h> 222: #ifdef BSD4_2 223: #include <fcntl.h> 224: #endif BSD4_2 225: 226: #ifdef BSD2_9 227: #define O_APPEND 0 /* kludge */ 228: #define wait3(a,b,c) wait2(a,b) 229: #endif BSD2_9 230: 231: #define SCPYN(a, b) strncpy(a, b, sizeof (a)) 232: 233: struct utmp utmp; 234: 235: dologout() 236: { 237: union wait status; 238: int pid, wtmp; 239: 240: #ifdef BSDINETD 241: while ((pid=wait(&status)) > 0) { 242: #else !BSDINETD 243: while ((pid=wait3(&status,WNOHANG,0)) > 0) { 244: #endif !BSDINETD 245: wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); 246: if (wtmp >= 0) { 247: sprintf(utmp.ut_line, "uucp%.4d", pid); 248: SCPYN(utmp.ut_name, ""); 249: SCPYN(utmp.ut_host, ""); 250: (void) time(&utmp.ut_time); 251: #ifdef BSD2_9 252: (void) lseek(wtmp, 0L, 2); 253: #endif BSD2_9 254: (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 255: (void) close(wtmp); 256: } 257: } 258: } 259: 260: /* 261: * Record login in wtmp file. 262: */ 263: dologin(pw, sin) 264: struct passwd *pw; 265: struct sockaddr_in *sin; 266: { 267: char line[32]; 268: char remotehost[32]; 269: int wtmp, f; 270: struct hostent *hp = gethostbyaddr(&sin->sin_addr, 271: sizeof (struct in_addr), AF_INET); 272: 273: if (hp) { 274: strncpy(remotehost, hp->h_name, sizeof (remotehost)); 275: endhostent(); 276: } else 277: strncpy(remotehost, inet_ntoa(sin->sin_addr), 278: sizeof (remotehost)); 279: wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); 280: if (wtmp >= 0) { 281: /* hack, but must be unique and no tty line */ 282: sprintf(line, "uucp%.4d", getpid()); 283: SCPYN(utmp.ut_line, line); 284: SCPYN(utmp.ut_name, pw->pw_name); 285: SCPYN(utmp.ut_host, remotehost); 286: time(&utmp.ut_time); 287: #ifdef BSD2_9 288: (void) lseek(wtmp, 0L, 2); 289: #endif BSD2_9 290: (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 291: (void) close(wtmp); 292: } 293: if ((f = open(lastlog, 2)) >= 0) { 294: struct lastlog ll; 295: 296: time(&ll.ll_time); 297: lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0); 298: strcpy(line, remotehost); 299: SCPYN(ll.ll_line, line); 300: SCPYN(ll.ll_host, remotehost); 301: (void) write(f, (char *) &ll, sizeof ll); 302: (void) close(f); 303: } 304: }