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