136093Sbostic /* 236093Sbostic * Copyright (c) 1985 The Regents of the University of California. 336093Sbostic * All rights reserved. 436093Sbostic * 536093Sbostic * This code is derived from software contributed to Berkeley by 636093Sbostic * Rick Adams. 736093Sbostic * 836093Sbostic * Redistribution and use in source and binary forms are permitted 936093Sbostic * provided that the above copyright notice and this paragraph are 1036093Sbostic * duplicated in all such forms and that any documentation, 1136093Sbostic * advertising materials, and other materials related to such 1236093Sbostic * distribution and use acknowledge that the software was developed 1336093Sbostic * by the University of California, Berkeley. The name of the 1436093Sbostic * University may not be used to endorse or promote products derived 1536093Sbostic * from this software without specific prior written permission. 1636093Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1736093Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1836093Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1936093Sbostic */ 2036093Sbostic 2117144Sralph #ifndef lint 2236093Sbostic char copyright[] = 2336093Sbostic "@(#) Copyright (c) 1985 The Regents of the University of California.\n\ 2436093Sbostic All rights reserved.\n"; 2536093Sbostic #endif /* not lint */ 2617144Sralph 2736093Sbostic #ifndef lint 28*38030Sbostic static char sccsid[] = "@(#)uucpd.c 5.8 (Berkeley) 05/17/89"; 2936093Sbostic #endif /* not lint */ 3036093Sbostic 3117144Sralph /* 3233974Srick * 4.2BSD TCP/IP server for uucico 3317843Sralph * uucico's TCP channel causes this server to be run at the remote end. 3417144Sralph */ 3517144Sralph 36*38030Sbostic #include <sys/types.h> 37*38030Sbostic #include <sys/socket.h> 38*38030Sbostic #include <sys/wait.h> 39*38030Sbostic #include <sys/ioctl.h> 40*38030Sbostic #include <sys/file.h> 41*38030Sbostic #include <netinet/in.h> 4223682Sbloom #include <netdb.h> 4317843Sralph #include <signal.h> 4417144Sralph #include <errno.h> 4517843Sralph #include <pwd.h> 46*38030Sbostic #include <stdio.h> 4737931Sbostic #include "pathnames.h" 4817144Sralph 4917843Sralph struct sockaddr_in hisctladdr; 5017843Sralph int hisaddrlen = sizeof hisctladdr; 5117843Sralph struct sockaddr_in myctladdr; 5217843Sralph int mypid; 5317144Sralph 5423682Sbloom char Username[64]; 5523682Sbloom char *nenv[] = { 5623682Sbloom Username, 5723682Sbloom NULL, 5823682Sbloom }; 5923682Sbloom extern char **environ; 6023682Sbloom 6117144Sralph main(argc, argv) 6217843Sralph int argc; 6317843Sralph char **argv; 6417144Sralph { 6518625Sralph #ifndef BSDINETD 6617843Sralph register int s, tcp_socket; 6717843Sralph struct servent *sp; 6818625Sralph #endif !BSDINETD 6917843Sralph extern int errno; 7017843Sralph int dologout(); 7117144Sralph 7223682Sbloom environ = nenv; 7317843Sralph #ifdef BSDINETD 7417843Sralph close(1); close(2); 7517843Sralph dup(0); dup(0); 7617843Sralph hisaddrlen = sizeof (hisctladdr); 7717843Sralph if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) { 7817144Sralph fprintf(stderr, "%s: ", argv[0]); 7917144Sralph perror("getpeername"); 8017144Sralph _exit(1); 8117144Sralph } 8217843Sralph if (fork() == 0) 8317843Sralph doit(&hisctladdr); 8417843Sralph dologout(); 8517843Sralph exit(1); 8617843Sralph #else !BSDINETD 8717843Sralph sp = getservbyname("uucp", "tcp"); 8817843Sralph if (sp == NULL){ 8917843Sralph perror("uucpd: getservbyname"); 9017843Sralph exit(1); 9117843Sralph } 9223682Sbloom if (fork()) 9323682Sbloom exit(0); 9437931Sbostic if ((s=open(_PATH_TTY, 2)) >= 0){ 9517843Sralph ioctl(s, TIOCNOTTY, (char *)0); 9617843Sralph close(s); 9717843Sralph } 9817144Sralph 9917843Sralph bzero((char *)&myctladdr, sizeof (myctladdr)); 10023682Sbloom myctladdr.sin_family = AF_INET; 10123682Sbloom myctladdr.sin_port = sp->s_port; 10223682Sbloom #ifdef BSD4_2 10323682Sbloom tcp_socket = socket(AF_INET, SOCK_STREAM, 0); 10423682Sbloom if (tcp_socket < 0) { 10517843Sralph perror("uucpd: socket"); 10617843Sralph exit(1); 10717843Sralph } 10823682Sbloom if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) { 10917843Sralph perror("uucpd: bind"); 11017843Sralph exit(1); 11117843Sralph } 11223682Sbloom listen(tcp_socket, 3); /* at most 3 simultaneuos uucp connections */ 11317843Sralph signal(SIGCHLD, dologout); 11417843Sralph 11517843Sralph for(;;) { 11617843Sralph s = accept(tcp_socket, &hisctladdr, &hisaddrlen); 11717843Sralph if (s < 0){ 11823682Sbloom if (errno == EINTR) 11917843Sralph continue; 12017843Sralph perror("uucpd: accept"); 12117843Sralph exit(1); 12217843Sralph } 12323682Sbloom if (fork() == 0) { 12417843Sralph close(0); close(1); close(2); 12517843Sralph dup(s); dup(s); dup(s); 12623682Sbloom close(tcp_socket); close(s); 12717843Sralph doit(&hisctladdr); 12817843Sralph exit(1); 12917843Sralph } 13017843Sralph close(s); 13117843Sralph } 13223682Sbloom #endif BSD4_2 13323682Sbloom 13423682Sbloom #endif !BSDINETD 13517144Sralph } 13617843Sralph 13717843Sralph doit(sinp) 13817843Sralph struct sockaddr_in *sinp; 13917843Sralph { 14023682Sbloom char user[64], passwd[64]; 14117843Sralph char *xpasswd, *crypt(); 14217843Sralph struct passwd *pw, *getpwnam(); 14317843Sralph 14417843Sralph alarm(60); 14518625Sralph printf("login: "); fflush(stdout); 14617843Sralph if (readline(user, sizeof user) < 0) { 14717843Sralph fprintf(stderr, "user read\n"); 14817843Sralph return; 14917843Sralph } 15017843Sralph /* truncate username to 8 characters */ 15117843Sralph user[8] = '\0'; 15217843Sralph pw = getpwnam(user); 15317843Sralph if (pw == NULL) { 15417843Sralph fprintf(stderr, "user unknown\n"); 15517843Sralph return; 15617843Sralph } 157*38030Sbostic if (strcmp(pw->pw_shell, _PATH_UUCICO)) { 15817843Sralph fprintf(stderr, "Login incorrect."); 15917843Sralph return; 16017843Sralph } 16117843Sralph if (pw->pw_passwd && *pw->pw_passwd != '\0') { 16218625Sralph printf("Password: "); fflush(stdout); 16317843Sralph if (readline(passwd, sizeof passwd) < 0) { 16417843Sralph fprintf(stderr, "passwd read\n"); 16517843Sralph return; 16617843Sralph } 16717843Sralph xpasswd = crypt(passwd, pw->pw_passwd); 16817843Sralph if (strcmp(xpasswd, pw->pw_passwd)) { 16917843Sralph fprintf(stderr, "Login incorrect."); 17017843Sralph return; 17117843Sralph } 17217843Sralph } 17317843Sralph alarm(0); 17423682Sbloom sprintf(Username, "USER=%s", user); 17517843Sralph dologin(pw, sinp); 17623682Sbloom setgid(pw->pw_gid); 17723682Sbloom #ifdef BSD4_2 17817843Sralph initgroups(pw->pw_name, pw->pw_gid); 17923682Sbloom #endif BSD4_2 18017843Sralph chdir(pw->pw_dir); 18123682Sbloom setuid(pw->pw_uid); 18223682Sbloom #ifdef BSD4_2 18317843Sralph execl(UUCICO, "uucico", (char *)0); 18423682Sbloom #endif BSD4_2 18517843Sralph perror("uucico server: execl"); 18617843Sralph } 18717843Sralph 18817843Sralph readline(p, n) 18918625Sralph register char *p; 19018625Sralph register int n; 19117843Sralph { 19217843Sralph char c; 19317843Sralph 19417843Sralph while (n-- > 0) { 19517843Sralph if (read(0, &c, 1) <= 0) 19617843Sralph return(-1); 19717843Sralph c &= 0177; 19817843Sralph if (c == '\n' || c == '\r') { 19917843Sralph *p = '\0'; 20017843Sralph return(0); 20117843Sralph } 20217843Sralph *p++ = c; 20317843Sralph } 20417843Sralph return(-1); 20517843Sralph } 20617843Sralph 20717843Sralph #include <utmp.h> 20823682Sbloom #ifdef BSD4_2 20917843Sralph #include <fcntl.h> 21023682Sbloom #endif BSD4_2 21117843Sralph 21217843Sralph #define SCPYN(a, b) strncpy(a, b, sizeof (a)) 21317843Sralph 21417843Sralph struct utmp utmp; 21517843Sralph 21617843Sralph dologout() 21717843Sralph { 21817843Sralph union wait status; 21917843Sralph int pid, wtmp; 22017843Sralph 22117843Sralph #ifdef BSDINETD 22223682Sbloom while ((pid=wait(&status)) > 0) { 22317843Sralph #else !BSDINETD 22423682Sbloom while ((pid=wait3(&status,WNOHANG,0)) > 0) { 22517843Sralph #endif !BSDINETD 22637931Sbostic wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND); 22717843Sralph if (wtmp >= 0) { 22817843Sralph sprintf(utmp.ut_line, "uucp%.4d", pid); 22917843Sralph SCPYN(utmp.ut_name, ""); 23017843Sralph SCPYN(utmp.ut_host, ""); 23123682Sbloom (void) time(&utmp.ut_time); 23217843Sralph (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 23317843Sralph (void) close(wtmp); 23417843Sralph } 23517843Sralph } 23617843Sralph } 23717843Sralph 23817843Sralph /* 23917843Sralph * Record login in wtmp file. 24017843Sralph */ 24117843Sralph dologin(pw, sin) 24217843Sralph struct passwd *pw; 24317843Sralph struct sockaddr_in *sin; 24417843Sralph { 24517843Sralph char line[32]; 24617843Sralph char remotehost[32]; 24717843Sralph int wtmp, f; 24817843Sralph struct hostent *hp = gethostbyaddr(&sin->sin_addr, 24917843Sralph sizeof (struct in_addr), AF_INET); 25017843Sralph 25117843Sralph if (hp) { 25217843Sralph strncpy(remotehost, hp->h_name, sizeof (remotehost)); 25317843Sralph endhostent(); 25417843Sralph } else 25517843Sralph strncpy(remotehost, inet_ntoa(sin->sin_addr), 25617843Sralph sizeof (remotehost)); 25737931Sbostic wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND); 25817843Sralph if (wtmp >= 0) { 25917843Sralph /* hack, but must be unique and no tty line */ 26017843Sralph sprintf(line, "uucp%.4d", getpid()); 26117843Sralph SCPYN(utmp.ut_line, line); 26217843Sralph SCPYN(utmp.ut_name, pw->pw_name); 26317843Sralph SCPYN(utmp.ut_host, remotehost); 26423682Sbloom time(&utmp.ut_time); 26517843Sralph (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 26617843Sralph (void) close(wtmp); 26717843Sralph } 26837931Sbostic if ((f = open(_PATH_LASTLOG, O_RDWR)) >= 0) { 26917843Sralph struct lastlog ll; 27017843Sralph 27117843Sralph time(&ll.ll_time); 27217843Sralph lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0); 27317843Sralph strcpy(line, remotehost); 27417843Sralph SCPYN(ll.ll_line, line); 27517843Sralph SCPYN(ll.ll_host, remotehost); 27617843Sralph (void) write(f, (char *) &ll, sizeof ll); 27717843Sralph (void) close(f); 27817843Sralph } 27917843Sralph } 280