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