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