117144Sralph #ifndef lint 2*23682Sbloom static char sccsid[] = "@(#)uucpd.c 5.4 (Berkeley) 06/23/85"; 317144Sralph #endif 417144Sralph 517144Sralph /* 6*23682Sbloom * 4.2BSD or 2.9BSD TCP/IP server for uucico 717843Sralph * uucico's TCP channel causes this server to be run at the remote end. 817144Sralph */ 917144Sralph 1017843Sralph #include "uucp.h" 11*23682Sbloom #include <netdb.h> 12*23682Sbloom #ifdef BSD2_9 13*23682Sbloom #include <sys/localopts.h> 14*23682Sbloom #include <sys/file.h> 15*23682Sbloom #endif BSD2_9 1617843Sralph #include <signal.h> 1717144Sralph #include <errno.h> 1817144Sralph #include <sys/socket.h> 1917144Sralph #include <netinet/in.h> 2017843Sralph #include <sys/wait.h> 21*23682Sbloom #include <sys/ioctl.h> 2217843Sralph #include <pwd.h> 2317843Sralph #include <lastlog.h> 2417144Sralph 25*23682Sbloom #if !defined(BSD4_2) && !defined(BSD2_9) 26*23682Sbloom --- You must have either BSD4_2 or BSD2_9 defined for this to work 27*23682Sbloom #endif !BSD4_2 && !BSD2_9 28*23682Sbloom #if defined(BSD4_2) && defined(BSD2_9) 29*23682Sbloom --- You may not have both BSD4_2 and BSD2_9 defined for this to work 30*23682Sbloom #endif /* check for stupidity */ 31*23682Sbloom 3217843Sralph char lastlog[] = "/usr/adm/lastlog"; 3317843Sralph struct sockaddr_in hisctladdr; 3417843Sralph int hisaddrlen = sizeof hisctladdr; 3517843Sralph struct sockaddr_in myctladdr; 3617843Sralph int mypid; 3717144Sralph 38*23682Sbloom char Username[64]; 39*23682Sbloom char *nenv[] = { 40*23682Sbloom Username, 41*23682Sbloom NULL, 42*23682Sbloom }; 43*23682Sbloom extern char **environ; 44*23682Sbloom 4517144Sralph main(argc, argv) 4617843Sralph int argc; 4717843Sralph char **argv; 4817144Sralph { 4918625Sralph #ifndef BSDINETD 5017843Sralph register int s, tcp_socket; 5117843Sralph struct servent *sp; 5218625Sralph #endif !BSDINETD 5317843Sralph extern int errno; 5417843Sralph int dologout(); 5517144Sralph 56*23682Sbloom environ = nenv; 5717843Sralph #ifdef BSDINETD 5817843Sralph close(1); close(2); 5917843Sralph dup(0); dup(0); 6017843Sralph hisaddrlen = sizeof (hisctladdr); 6117843Sralph if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) { 6217144Sralph fprintf(stderr, "%s: ", argv[0]); 6317144Sralph perror("getpeername"); 6417144Sralph _exit(1); 6517144Sralph } 6617843Sralph if (fork() == 0) 6717843Sralph doit(&hisctladdr); 6817843Sralph dologout(); 6917843Sralph exit(1); 7017843Sralph #else !BSDINETD 7117843Sralph sp = getservbyname("uucp", "tcp"); 7217843Sralph if (sp == NULL){ 7317843Sralph perror("uucpd: getservbyname"); 7417843Sralph exit(1); 7517843Sralph } 76*23682Sbloom if (fork()) 77*23682Sbloom exit(0); 7817843Sralph if ((s=open("/dev/tty", 2)) >= 0){ 7917843Sralph ioctl(s, TIOCNOTTY, (char *)0); 8017843Sralph close(s); 8117843Sralph } 8217144Sralph 8317843Sralph bzero((char *)&myctladdr, sizeof (myctladdr)); 84*23682Sbloom myctladdr.sin_family = AF_INET; 85*23682Sbloom myctladdr.sin_port = sp->s_port; 86*23682Sbloom #ifdef BSD4_2 87*23682Sbloom tcp_socket = socket(AF_INET, SOCK_STREAM, 0); 88*23682Sbloom if (tcp_socket < 0) { 8917843Sralph perror("uucpd: socket"); 9017843Sralph exit(1); 9117843Sralph } 92*23682Sbloom if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) { 9317843Sralph perror("uucpd: bind"); 9417843Sralph exit(1); 9517843Sralph } 96*23682Sbloom listen(tcp_socket, 3); /* at most 3 simultaneuos uucp connections */ 9717843Sralph signal(SIGCHLD, dologout); 9817843Sralph 9917843Sralph for(;;) { 10017843Sralph s = accept(tcp_socket, &hisctladdr, &hisaddrlen); 10117843Sralph if (s < 0){ 102*23682Sbloom if (errno == EINTR) 10317843Sralph continue; 10417843Sralph perror("uucpd: accept"); 10517843Sralph exit(1); 10617843Sralph } 107*23682Sbloom if (fork() == 0) { 10817843Sralph close(0); close(1); close(2); 10917843Sralph dup(s); dup(s); dup(s); 110*23682Sbloom close(tcp_socket); close(s); 11117843Sralph doit(&hisctladdr); 11217843Sralph exit(1); 11317843Sralph } 11417843Sralph close(s); 11517843Sralph } 116*23682Sbloom #endif BSD4_2 117*23682Sbloom 118*23682Sbloom #ifdef BSD2_9 119*23682Sbloom for(;;) { 120*23682Sbloom signal(SIGCHLD, dologout); 121*23682Sbloom s = socket(SOCK_STREAM, 0, &myctladdr, 122*23682Sbloom SO_ACCEPTCONN|SO_KEEPALIVE); 123*23682Sbloom if (s < 0) { 124*23682Sbloom perror("uucpd: socket"); 125*23682Sbloom exit(1); 126*23682Sbloom } 127*23682Sbloom if (accept(s, &hisctladdr) < 0) { 128*23682Sbloom if (errno == EINTR) { 129*23682Sbloom close(s); 130*23682Sbloom continue; 131*23682Sbloom } 132*23682Sbloom perror("uucpd: accept"); 133*23682Sbloom exit(1); 134*23682Sbloom } 135*23682Sbloom if (fork() == 0) { 136*23682Sbloom close(0); close(1); close(2); 137*23682Sbloom dup(s); dup(s); dup(s); 138*23682Sbloom close(s); 139*23682Sbloom doit(&hisctladdr); 140*23682Sbloom exit(1); 141*23682Sbloom } 142*23682Sbloom } 143*23682Sbloom #endif BSD2_9 144*23682Sbloom #endif !BSDINETD 14517144Sralph } 14617843Sralph 14717843Sralph doit(sinp) 14817843Sralph struct sockaddr_in *sinp; 14917843Sralph { 150*23682Sbloom char user[64], passwd[64]; 15117843Sralph char *xpasswd, *crypt(); 15217843Sralph struct passwd *pw, *getpwnam(); 15317843Sralph 15417843Sralph alarm(60); 15518625Sralph printf("login: "); fflush(stdout); 15617843Sralph if (readline(user, sizeof user) < 0) { 15717843Sralph fprintf(stderr, "user read\n"); 15817843Sralph return; 15917843Sralph } 16017843Sralph /* truncate username to 8 characters */ 16117843Sralph user[8] = '\0'; 16217843Sralph pw = getpwnam(user); 16317843Sralph if (pw == NULL) { 16417843Sralph fprintf(stderr, "user unknown\n"); 16517843Sralph return; 16617843Sralph } 16717843Sralph if (strcmp(pw->pw_shell, UUCICO)) { 16817843Sralph fprintf(stderr, "Login incorrect."); 16917843Sralph return; 17017843Sralph } 17117843Sralph if (pw->pw_passwd && *pw->pw_passwd != '\0') { 17218625Sralph printf("Password: "); fflush(stdout); 17317843Sralph if (readline(passwd, sizeof passwd) < 0) { 17417843Sralph fprintf(stderr, "passwd read\n"); 17517843Sralph return; 17617843Sralph } 17717843Sralph xpasswd = crypt(passwd, pw->pw_passwd); 17817843Sralph if (strcmp(xpasswd, pw->pw_passwd)) { 17917843Sralph fprintf(stderr, "Login incorrect."); 18017843Sralph return; 18117843Sralph } 18217843Sralph } 18317843Sralph alarm(0); 184*23682Sbloom sprintf(Username, "USER=%s", user); 18517843Sralph dologin(pw, sinp); 186*23682Sbloom setgid(pw->pw_gid); 187*23682Sbloom #ifdef BSD4_2 18817843Sralph initgroups(pw->pw_name, pw->pw_gid); 189*23682Sbloom #endif BSD4_2 19017843Sralph chdir(pw->pw_dir); 191*23682Sbloom setuid(pw->pw_uid); 192*23682Sbloom #ifdef BSD4_2 19317843Sralph execl(UUCICO, "uucico", (char *)0); 194*23682Sbloom #endif BSD4_2 195*23682Sbloom #ifdef BSD2_9 196*23682Sbloom sprintf(passwd, "-h%s", inet_ntoa(sinp->sin_addr)); 197*23682Sbloom execl(UUCICO, "uucico", passwd, (char *)0); 198*23682Sbloom #endif BSD2_9 19917843Sralph perror("uucico server: execl"); 20017843Sralph } 20117843Sralph 20217843Sralph readline(p, n) 20318625Sralph register char *p; 20418625Sralph register int n; 20517843Sralph { 20617843Sralph char c; 20717843Sralph 20817843Sralph while (n-- > 0) { 20917843Sralph if (read(0, &c, 1) <= 0) 21017843Sralph return(-1); 21117843Sralph c &= 0177; 21217843Sralph if (c == '\n' || c == '\r') { 21317843Sralph *p = '\0'; 21417843Sralph return(0); 21517843Sralph } 21617843Sralph *p++ = c; 21717843Sralph } 21817843Sralph return(-1); 21917843Sralph } 22017843Sralph 22117843Sralph #include <utmp.h> 222*23682Sbloom #ifdef BSD4_2 22317843Sralph #include <fcntl.h> 224*23682Sbloom #endif BSD4_2 22517843Sralph 226*23682Sbloom #ifdef BSD2_9 227*23682Sbloom #define O_APPEND 0 /* kludge */ 228*23682Sbloom #define wait3(a,b,c) wait2(a,b) 229*23682Sbloom #endif BSD2_9 230*23682Sbloom 23117843Sralph #define SCPYN(a, b) strncpy(a, b, sizeof (a)) 23217843Sralph 23317843Sralph struct utmp utmp; 23417843Sralph 23517843Sralph dologout() 23617843Sralph { 23717843Sralph union wait status; 23817843Sralph int pid, wtmp; 23917843Sralph 24017843Sralph #ifdef BSDINETD 241*23682Sbloom while ((pid=wait(&status)) > 0) { 24217843Sralph #else !BSDINETD 243*23682Sbloom while ((pid=wait3(&status,WNOHANG,0)) > 0) { 24417843Sralph #endif !BSDINETD 24517843Sralph wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); 24617843Sralph if (wtmp >= 0) { 24717843Sralph sprintf(utmp.ut_line, "uucp%.4d", pid); 24817843Sralph SCPYN(utmp.ut_name, ""); 24917843Sralph SCPYN(utmp.ut_host, ""); 250*23682Sbloom (void) time(&utmp.ut_time); 251*23682Sbloom #ifdef BSD2_9 252*23682Sbloom (void) lseek(wtmp, 0L, 2); 253*23682Sbloom #endif BSD2_9 25417843Sralph (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 25517843Sralph (void) close(wtmp); 25617843Sralph } 25717843Sralph } 25817843Sralph } 25917843Sralph 26017843Sralph /* 26117843Sralph * Record login in wtmp file. 26217843Sralph */ 26317843Sralph dologin(pw, sin) 26417843Sralph struct passwd *pw; 26517843Sralph struct sockaddr_in *sin; 26617843Sralph { 26717843Sralph char line[32]; 26817843Sralph char remotehost[32]; 26917843Sralph int wtmp, f; 27017843Sralph struct hostent *hp = gethostbyaddr(&sin->sin_addr, 27117843Sralph sizeof (struct in_addr), AF_INET); 27217843Sralph 27317843Sralph if (hp) { 27417843Sralph strncpy(remotehost, hp->h_name, sizeof (remotehost)); 27517843Sralph endhostent(); 27617843Sralph } else 27717843Sralph strncpy(remotehost, inet_ntoa(sin->sin_addr), 27817843Sralph sizeof (remotehost)); 27917843Sralph wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); 28017843Sralph if (wtmp >= 0) { 28117843Sralph /* hack, but must be unique and no tty line */ 28217843Sralph sprintf(line, "uucp%.4d", getpid()); 28317843Sralph SCPYN(utmp.ut_line, line); 28417843Sralph SCPYN(utmp.ut_name, pw->pw_name); 28517843Sralph SCPYN(utmp.ut_host, remotehost); 286*23682Sbloom time(&utmp.ut_time); 287*23682Sbloom #ifdef BSD2_9 288*23682Sbloom (void) lseek(wtmp, 0L, 2); 289*23682Sbloom #endif BSD2_9 29017843Sralph (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 29117843Sralph (void) close(wtmp); 29217843Sralph } 29317843Sralph if ((f = open(lastlog, 2)) >= 0) { 29417843Sralph struct lastlog ll; 29517843Sralph 29617843Sralph time(&ll.ll_time); 29717843Sralph lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0); 29817843Sralph strcpy(line, remotehost); 29917843Sralph SCPYN(ll.ll_line, line); 30017843Sralph SCPYN(ll.ll_host, remotehost); 30117843Sralph (void) write(f, (char *) &ll, sizeof ll); 30217843Sralph (void) close(f); 30317843Sralph } 30417843Sralph } 305