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