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