1 #ifndef lint 2 static char sccsid[] = "@(#)uucpd.c 5.3 (Berkeley) 04/10/85"; 3 #endif 4 5 /* 6 * 4.2BSD 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 <signal.h> 12 #include <errno.h> 13 #include <sys/socket.h> 14 #include <sys/ioctl.h> 15 #include <netinet/in.h> 16 #include <netdb.h> 17 #include <sys/wait.h> 18 #include <pwd.h> 19 #include <lastlog.h> 20 21 char lastlog[] = "/usr/adm/lastlog"; 22 struct sockaddr_in hisctladdr; 23 int hisaddrlen = sizeof hisctladdr; 24 struct sockaddr_in myctladdr; 25 int mypid; 26 27 main(argc, argv) 28 int argc; 29 char **argv; 30 { 31 #ifndef BSDINETD 32 register int s, tcp_socket; 33 struct servent *sp; 34 #endif !BSDINETD 35 extern int errno; 36 int dologout(); 37 38 #ifdef BSDINETD 39 close(1); close(2); 40 dup(0); dup(0); 41 hisaddrlen = sizeof (hisctladdr); 42 if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) { 43 fprintf(stderr, "%s: ", argv[0]); 44 perror("getpeername"); 45 _exit(1); 46 } 47 if (fork() == 0) 48 doit(&hisctladdr); 49 dologout(); 50 exit(1); 51 #else !BSDINETD 52 sp = getservbyname("uucp", "tcp"); 53 if (sp == NULL){ 54 perror("uucpd: getservbyname"); 55 exit(1); 56 } 57 if ((s=open("/dev/tty", 2)) >= 0){ 58 ioctl(s, TIOCNOTTY, (char *)0); 59 close(s); 60 } 61 62 bzero((char *)&myctladdr, sizeof (myctladdr)); 63 tcp_socket = socket(AF_INET, SOCK_STREAM, 0, 0); 64 if ( tcp_socket<0 ) { 65 perror("uucpd: socket"); 66 exit(1); 67 } 68 myctladdr.sin_port = sp->s_port; 69 if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr), 0) < 0) { 70 perror("uucpd: bind"); 71 exit(1); 72 } 73 signal(SIGCHLD, dologout); 74 listen(tcp_socket, 5); /* 5's as good as any */ 75 76 for(;;) { 77 s = accept(tcp_socket, &hisctladdr, &hisaddrlen); 78 if (s < 0){ 79 if (errno == EINTR) 80 continue; 81 perror("uucpd: accept"); 82 exit(1); 83 } 84 if (fork()== 0) { 85 close(0); close(1); close(2); 86 dup(s); dup(s); dup(s); 87 close(tcp_socket);close(s); 88 doit(&hisctladdr); 89 exit(1); 90 } 91 close(s); 92 } 93 #endif 94 } 95 96 doit(sinp) 97 struct sockaddr_in *sinp; 98 { 99 char user[64]; 100 char passwd[64]; 101 char *xpasswd, *crypt(); 102 struct passwd *pw, *getpwnam(); 103 104 alarm(60); 105 printf("login: "); fflush(stdout); 106 if (readline(user, sizeof user) < 0) { 107 fprintf(stderr, "user read\n"); 108 return; 109 } 110 /* truncate username to 8 characters */ 111 user[8] = '\0'; 112 pw = getpwnam(user); 113 if (pw == NULL) { 114 fprintf(stderr, "user unknown\n"); 115 return; 116 } 117 if (strcmp(pw->pw_shell, UUCICO)) { 118 fprintf(stderr, "Login incorrect."); 119 return; 120 } 121 if (pw->pw_passwd && *pw->pw_passwd != '\0') { 122 printf("Password: "); fflush(stdout); 123 if (readline(passwd, sizeof passwd) < 0) { 124 fprintf(stderr, "passwd read\n"); 125 return; 126 } 127 xpasswd = crypt(passwd, pw->pw_passwd); 128 if (strcmp(xpasswd, pw->pw_passwd)) { 129 fprintf(stderr, "Login incorrect."); 130 return; 131 } 132 } 133 alarm(0); 134 dologin(pw, sinp); 135 setegid(pw->pw_gid); 136 initgroups(pw->pw_name, pw->pw_gid); 137 chdir(pw->pw_dir); 138 seteuid(pw->pw_uid); 139 execl(UUCICO, "uucico", (char *)0); 140 perror("uucico server: execl"); 141 } 142 143 readline(p, n) 144 register char *p; 145 register int n; 146 { 147 char c; 148 149 while (n-- > 0) { 150 if (read(0, &c, 1) <= 0) 151 return(-1); 152 c &= 0177; 153 if (c == '\n' || c == '\r') { 154 *p = '\0'; 155 return(0); 156 } 157 *p++ = c; 158 } 159 return(-1); 160 } 161 162 #include <utmp.h> 163 #include <fcntl.h> 164 165 #define SCPYN(a, b) strncpy(a, b, sizeof (a)) 166 167 struct utmp utmp; 168 169 dologout() 170 { 171 union wait status; 172 int pid, wtmp; 173 174 #ifdef BSDINETD 175 while ((pid=wait(&status)) > 0 ) { 176 #else !BSDINETD 177 while ((pid=wait3(&status,WNOHANG,0)) > 0 ) { 178 #endif !BSDINETD 179 wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); 180 if (wtmp >= 0) { 181 sprintf(utmp.ut_line, "uucp%.4d", pid); 182 SCPYN(utmp.ut_name, ""); 183 SCPYN(utmp.ut_host, ""); 184 utmp.ut_time = time(0); 185 (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 186 (void) close(wtmp); 187 } 188 } 189 } 190 191 /* 192 * Record login in wtmp file. 193 */ 194 dologin(pw, sin) 195 struct passwd *pw; 196 struct sockaddr_in *sin; 197 { 198 char line[32]; 199 char remotehost[32]; 200 int wtmp, f; 201 struct hostent *hp = gethostbyaddr(&sin->sin_addr, 202 sizeof (struct in_addr), AF_INET); 203 204 if (hp) { 205 strncpy(remotehost, hp->h_name, sizeof (remotehost)); 206 endhostent(); 207 } else 208 strncpy(remotehost, inet_ntoa(sin->sin_addr), 209 sizeof (remotehost)); 210 wtmp = open("/usr/adm/wtmp", O_WRONLY|O_APPEND); 211 if (wtmp >= 0) { 212 /* hack, but must be unique and no tty line */ 213 sprintf(line, "uucp%.4d", getpid()); 214 SCPYN(utmp.ut_line, line); 215 SCPYN(utmp.ut_name, pw->pw_name); 216 SCPYN(utmp.ut_host, remotehost); 217 utmp.ut_time = time(0); 218 (void) write(wtmp, (char *)&utmp, sizeof (utmp)); 219 (void) close(wtmp); 220 } 221 if ((f = open(lastlog, 2)) >= 0) { 222 struct lastlog ll; 223 224 time(&ll.ll_time); 225 lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0); 226 strcpy(line, remotehost); 227 SCPYN(ll.ll_line, line); 228 SCPYN(ll.ll_host, remotehost); 229 (void) write(f, (char *) &ll, sizeof ll); 230 (void) close(f); 231 } 232 } 233