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