1/*- 2 * Copyright (c) 1983, 1988, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35static const char copyright[] = 36"@(#) Copyright (c) 1983, 1988, 1989, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41#if 0 42static const char sccsid[] = "@(#)rlogind.c 8.1 (Berkeley) 6/4/93"; 43#endif 44static const char rcsid[] =
| 1/*- 2 * Copyright (c) 1983, 1988, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35static const char copyright[] = 36"@(#) Copyright (c) 1983, 1988, 1989, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41#if 0 42static const char sccsid[] = "@(#)rlogind.c 8.1 (Berkeley) 6/4/93"; 43#endif 44static const char rcsid[] =
|
45 "$FreeBSD: head/libexec/rlogind/rlogind.c 51433 1999-09-19 22:05:32Z markm $";
| 45 "$FreeBSD: head/libexec/rlogind/rlogind.c 56590 2000-01-25 14:52:10Z shin $";
|
46#endif /* not lint */ 47 48/* 49 * remote login server: 50 * \0 51 * remuser\0 52 * locuser\0 53 * terminal_type/speed\0 54 * data 55 */ 56 57#define FD_SETSIZE 16 /* don't need many bits for select */ 58#include <sys/types.h> 59#include <sys/param.h> 60#include <sys/stat.h> 61#include <sys/ioctl.h> 62#include <signal.h> 63#include <termios.h> 64 65#include <sys/socket.h> 66#include <netinet/in.h> 67#include <netinet/in_systm.h> 68#include <netinet/ip.h> 69#include <netinet/tcp.h> 70#include <arpa/inet.h> 71#include <netdb.h> 72 73#include <errno.h> 74#include <libutil.h> 75#include <pwd.h> 76#include <syslog.h> 77#include <stdio.h> 78#include <stdlib.h> 79#include <string.h> 80#include <unistd.h> 81#include "pathnames.h" 82 83#ifndef NO_PAM 84#include <security/pam_appl.h> 85#include <security/pam_misc.h> 86#endif 87 88#ifndef TIOCPKT_WINDOW 89#define TIOCPKT_WINDOW 0x80 90#endif 91 92#define ARGSTR "Dalnx" 93
| 46#endif /* not lint */ 47 48/* 49 * remote login server: 50 * \0 51 * remuser\0 52 * locuser\0 53 * terminal_type/speed\0 54 * data 55 */ 56 57#define FD_SETSIZE 16 /* don't need many bits for select */ 58#include <sys/types.h> 59#include <sys/param.h> 60#include <sys/stat.h> 61#include <sys/ioctl.h> 62#include <signal.h> 63#include <termios.h> 64 65#include <sys/socket.h> 66#include <netinet/in.h> 67#include <netinet/in_systm.h> 68#include <netinet/ip.h> 69#include <netinet/tcp.h> 70#include <arpa/inet.h> 71#include <netdb.h> 72 73#include <errno.h> 74#include <libutil.h> 75#include <pwd.h> 76#include <syslog.h> 77#include <stdio.h> 78#include <stdlib.h> 79#include <string.h> 80#include <unistd.h> 81#include "pathnames.h" 82 83#ifndef NO_PAM 84#include <security/pam_appl.h> 85#include <security/pam_misc.h> 86#endif 87 88#ifndef TIOCPKT_WINDOW 89#define TIOCPKT_WINDOW 0x80 90#endif 91 92#define ARGSTR "Dalnx" 93
|
| 94/* wrapper for KAME-special getnameinfo() */ 95#ifndef NI_WITHSCOPEID 96#define NI_WITHSCOPEID 0 97#endif 98
|
94char *env[2]; 95#define NMAX 30 96char lusername[NMAX+1], rusername[NMAX+1]; 97static char term[64] = "TERM="; 98#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ 99int keepalive = 1; 100int check_all = 0; 101int no_delay; 102 103struct passwd *pwd; 104
| 99char *env[2]; 100#define NMAX 30 101char lusername[NMAX+1], rusername[NMAX+1]; 102static char term[64] = "TERM="; 103#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ 104int keepalive = 1; 105int check_all = 0; 106int no_delay; 107 108struct passwd *pwd; 109
|
105void doit __P((int, struct sockaddr_in *));
| 110union sockunion { 111 struct sockinet { 112 u_char si_len; 113 u_char si_family; 114 u_short si_port; 115 } su_si; 116 struct sockaddr_in su_sin; 117 struct sockaddr_in6 su_sin6; 118}; 119#define su_len su_si.si_len 120#define su_family su_si.si_family 121#define su_port su_si.si_port 122 123void doit __P((int, union sockunion *));
|
106int control __P((int, char *, int)); 107void protocol __P((int, int)); 108void cleanup __P((int)); 109void fatal __P((int, char *, int));
| 124int control __P((int, char *, int)); 125void protocol __P((int, int)); 126void cleanup __P((int)); 127void fatal __P((int, char *, int));
|
110int do_rlogin __P((struct sockaddr_in *));
| 128int do_rlogin __P((union sockunion *));
|
111void getstr __P((char *, int, char *)); 112void setup_term __P((int)); 113int do_krb_login __P((struct sockaddr_in *)); 114void usage __P((void)); 115 116#ifndef NO_PAM 117extern int auth_pam __P((char *)); 118#endif 119 120int 121main(argc, argv) 122 int argc; 123 char *argv[]; 124{ 125 extern int __check_rhosts_file;
| 129void getstr __P((char *, int, char *)); 130void setup_term __P((int)); 131int do_krb_login __P((struct sockaddr_in *)); 132void usage __P((void)); 133 134#ifndef NO_PAM 135extern int auth_pam __P((char *)); 136#endif 137 138int 139main(argc, argv) 140 int argc; 141 char *argv[]; 142{ 143 extern int __check_rhosts_file;
|
126 struct sockaddr_in from;
| 144 union sockunion from;
|
127 int ch, fromlen, on; 128 129 openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); 130 131 opterr = 0; 132 while ((ch = getopt(argc, argv, ARGSTR)) != -1) 133 switch (ch) { 134 case 'D': 135 no_delay = 1; 136 break; 137 case 'a': 138 check_all = 1; 139 break; 140 case 'l': 141 __check_rhosts_file = 0; 142 break; 143 case 'n': 144 keepalive = 0; 145 break; 146#ifdef CRYPT 147 case 'x': 148 doencrypt = 1; 149 break; 150#endif 151 case '?': 152 default: 153 usage(); 154 break; 155 } 156 argc -= optind; 157 argv += optind; 158 159 fromlen = sizeof (from); 160 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 161 syslog(LOG_ERR,"Can't get peer name of remote host: %m"); 162 fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); 163 } 164 on = 1; 165 if (keepalive && 166 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 167 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 168 if (no_delay && 169 setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) 170 syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m");
| 145 int ch, fromlen, on; 146 147 openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); 148 149 opterr = 0; 150 while ((ch = getopt(argc, argv, ARGSTR)) != -1) 151 switch (ch) { 152 case 'D': 153 no_delay = 1; 154 break; 155 case 'a': 156 check_all = 1; 157 break; 158 case 'l': 159 __check_rhosts_file = 0; 160 break; 161 case 'n': 162 keepalive = 0; 163 break; 164#ifdef CRYPT 165 case 'x': 166 doencrypt = 1; 167 break; 168#endif 169 case '?': 170 default: 171 usage(); 172 break; 173 } 174 argc -= optind; 175 argv += optind; 176 177 fromlen = sizeof (from); 178 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 179 syslog(LOG_ERR,"Can't get peer name of remote host: %m"); 180 fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); 181 } 182 on = 1; 183 if (keepalive && 184 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 185 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 186 if (no_delay && 187 setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) 188 syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m");
|
| 189 if (from.su_family == AF_INET) 190 {
|
171 on = IPTOS_LOWDELAY; 172 if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 173 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
| 191 on = IPTOS_LOWDELAY; 192 if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 193 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
|
| 194 }
|
174 175 doit(0, &from); 176 return 0; 177} 178 179int child; 180int netf; 181char line[MAXPATHLEN]; 182int confirmed; 183 184struct winsize win = { 0, 0, 0, 0 }; 185 186 187void 188doit(f, fromp) 189 int f;
| 195 196 doit(0, &from); 197 return 0; 198} 199 200int child; 201int netf; 202char line[MAXPATHLEN]; 203int confirmed; 204 205struct winsize win = { 0, 0, 0, 0 }; 206 207 208void 209doit(f, fromp) 210 int f;
|
190 struct sockaddr_in *fromp;
| 211 union sockunion *fromp;
|
191{ 192 int master, pid, on = 1; 193 int authenticated = 0;
| 212{ 213 int master, pid, on = 1; 214 int authenticated = 0;
|
194 char hostname[MAXHOSTNAMELEN];
| 215 char hostname[2 * MAXHOSTNAMELEN + 1]; 216 char nameinfo[2 * INET6_ADDRSTRLEN + 1];
|
195 char c; 196 197 alarm(60); 198 read(f, &c, 1); 199 200 if (c != 0) 201 exit(1); 202 203 alarm(0);
| 217 char c; 218 219 alarm(60); 220 read(f, &c, 1); 221 222 if (c != 0) 223 exit(1); 224 225 alarm(0);
|
204 fromp->sin_port = ntohs((u_short)fromp->sin_port); 205 realhostname(hostname, sizeof(hostname) - 1, &fromp->sin_addr);
| 226 227 realhostname_sa(hostname, sizeof(hostname) - 1, 228 (struct sockaddr *)fromp, fromp->su_len); 229 /* error check ? */ 230 fromp->su_port = ntohs((u_short)fromp->su_port);
|
206 hostname[sizeof(hostname) - 1] = '\0'; 207 208 {
| 231 hostname[sizeof(hostname) - 1] = '\0'; 232 233 {
|
209 if (fromp->sin_family != AF_INET || 210 fromp->sin_port >= IPPORT_RESERVED || 211 fromp->sin_port < IPPORT_RESERVED/2) {
| 234 if ((fromp->su_family != AF_INET && 235#ifdef INET6 236 fromp->su_family != AF_INET6 237#endif 238 ) || 239 fromp->su_port >= IPPORT_RESERVED || 240 fromp->su_port < IPPORT_RESERVED/2) { 241 getnameinfo((struct sockaddr *)fromp, 242 fromp->su_len, 243 nameinfo, sizeof(nameinfo), NULL, 0, 244 NI_NUMERICHOST|NI_WITHSCOPEID); 245 /* error check ? */
|
212 syslog(LOG_NOTICE, "Connection from %s on illegal port",
| 246 syslog(LOG_NOTICE, "Connection from %s on illegal port",
|
213 inet_ntoa(fromp->sin_addr));
| 247 nameinfo);
|
214 fatal(f, "Permission denied", 0); 215 } 216#ifdef IP_OPTIONS
| 248 fatal(f, "Permission denied", 0); 249 } 250#ifdef IP_OPTIONS
|
217 {
| 251 if (fromp->su_family == AF_INET) 252 {
|
218 u_char optbuf[BUFSIZ/3]; 219 int optsize = sizeof(optbuf), ipproto, i; 220 struct protoent *ip; 221 222 if ((ip = getprotobyname("ip")) != NULL) 223 ipproto = ip->p_proto; 224 else 225 ipproto = IPPROTO_IP; 226 if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, 227 &optsize) == 0 && optsize != 0) { 228 for (i = 0; i < optsize; ) { 229 u_char c = optbuf[i]; 230 if (c == IPOPT_LSRR || c == IPOPT_SSRR) { 231 syslog(LOG_NOTICE, 232 "Connection refused from %s with IP option %s",
| 253 u_char optbuf[BUFSIZ/3]; 254 int optsize = sizeof(optbuf), ipproto, i; 255 struct protoent *ip; 256 257 if ((ip = getprotobyname("ip")) != NULL) 258 ipproto = ip->p_proto; 259 else 260 ipproto = IPPROTO_IP; 261 if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, 262 &optsize) == 0 && optsize != 0) { 263 for (i = 0; i < optsize; ) { 264 u_char c = optbuf[i]; 265 if (c == IPOPT_LSRR || c == IPOPT_SSRR) { 266 syslog(LOG_NOTICE, 267 "Connection refused from %s with IP option %s",
|
233 inet_ntoa(fromp->sin_addr),
| 268 inet_ntoa(fromp->su_sin.sin_addr),
|
234 c == IPOPT_LSRR ? "LSRR" : "SSRR"); 235 exit(1); 236 } 237 if (c == IPOPT_EOL) 238 break; 239 i += (c == IPOPT_NOP) ? 1 : optbuf[i+1]; 240 } 241 }
| 269 c == IPOPT_LSRR ? "LSRR" : "SSRR"); 270 exit(1); 271 } 272 if (c == IPOPT_EOL) 273 break; 274 i += (c == IPOPT_NOP) ? 1 : optbuf[i+1]; 275 } 276 }
|
242 }
| 277 }
|
243#endif 244 if (do_rlogin(fromp) == 0) 245 authenticated++; 246 } 247 if (confirmed == 0) { 248 write(f, "", 1); 249 confirmed = 1; /* we sent the null! */ 250 } 251#ifdef CRYPT 252 if (doencrypt) 253 (void) des_enc_write(f, 254 SECURE_MESSAGE, 255 strlen(SECURE_MESSAGE), 256 schedule, &kdata->session); 257#endif 258 netf = f; 259 260 pid = forkpty(&master, line, NULL, &win); 261 if (pid < 0) { 262 if (errno == ENOENT) 263 fatal(f, "Out of ptys", 0); 264 else 265 fatal(f, "Forkpty", 1); 266 } 267 if (pid == 0) { 268 if (f > 2) /* f should always be 0, but... */ 269 (void) close(f); 270 setup_term(0); 271 if (*lusername=='-') { 272 syslog(LOG_ERR, "tried to pass user \"%s\" to login", 273 lusername); 274 fatal(STDERR_FILENO, "invalid user", 0); 275 } 276 if (authenticated) { 277 execl(_PATH_LOGIN, "login", "-p", 278 "-h", hostname, "-f", lusername, (char *)NULL); 279 } else 280 execl(_PATH_LOGIN, "login", "-p", 281 "-h", hostname, lusername, (char *)NULL); 282 fatal(STDERR_FILENO, _PATH_LOGIN, 1); 283 /*NOTREACHED*/ 284 } 285#ifdef CRYPT 286 /* 287 * If encrypted, don't turn on NBIO or the des read/write 288 * routines will croak. 289 */ 290 291 if (!doencrypt) 292#endif 293 ioctl(f, FIONBIO, &on); 294 ioctl(master, FIONBIO, &on); 295 ioctl(master, TIOCPKT, &on); 296 signal(SIGCHLD, cleanup); 297 protocol(f, master); 298 signal(SIGCHLD, SIG_IGN); 299 cleanup(0); 300} 301 302char magic[2] = { 0377, 0377 }; 303char oobdata[] = {TIOCPKT_WINDOW}; 304 305/* 306 * Handle a "control" request (signaled by magic being present) 307 * in the data stream. For now, we are only willing to handle 308 * window size changes. 309 */ 310int 311control(pty, cp, n) 312 int pty; 313 char *cp; 314 int n; 315{ 316 struct winsize w; 317 318 if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 319 return (0); 320 oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 321 bcopy(cp+4, (char *)&w, sizeof(w)); 322 w.ws_row = ntohs(w.ws_row); 323 w.ws_col = ntohs(w.ws_col); 324 w.ws_xpixel = ntohs(w.ws_xpixel); 325 w.ws_ypixel = ntohs(w.ws_ypixel); 326 (void)ioctl(pty, TIOCSWINSZ, &w); 327 return (4+sizeof (w)); 328} 329 330/* 331 * rlogin "protocol" machine. 332 */ 333void 334protocol(f, p) 335 register int f, p; 336{ 337 char pibuf[1024+1], fibuf[1024], *pbp, *fbp; 338 int pcc = 0, fcc = 0; 339 int cc, nfd, n; 340 char cntl; 341 342 /* 343 * Must ignore SIGTTOU, otherwise we'll stop 344 * when we try and set slave pty's window shape 345 * (our controlling tty is the master pty). 346 */ 347 (void) signal(SIGTTOU, SIG_IGN); 348 send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 349 if (f > p) 350 nfd = f + 1; 351 else 352 nfd = p + 1; 353 if (nfd > FD_SETSIZE) { 354 syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); 355 fatal(f, "internal error (select mask too small)", 0); 356 } 357 for (;;) { 358 fd_set ibits, obits, ebits, *omask; 359 360 FD_ZERO(&ebits); 361 FD_ZERO(&ibits); 362 FD_ZERO(&obits); 363 omask = (fd_set *)NULL; 364 if (fcc) { 365 FD_SET(p, &obits); 366 omask = &obits; 367 } else 368 FD_SET(f, &ibits); 369 if (pcc >= 0) { 370 if (pcc) { 371 FD_SET(f, &obits); 372 omask = &obits; 373 } else 374 FD_SET(p, &ibits); 375 } 376 FD_SET(p, &ebits); 377 if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { 378 if (errno == EINTR) 379 continue; 380 fatal(f, "select", 1); 381 } 382 if (n == 0) { 383 /* shouldn't happen... */ 384 sleep(5); 385 continue; 386 } 387#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 388 if (FD_ISSET(p, &ebits)) { 389 cc = read(p, &cntl, 1); 390 if (cc == 1 && pkcontrol(cntl)) { 391 cntl |= oobdata[0]; 392 send(f, &cntl, 1, MSG_OOB); 393 if (cntl & TIOCPKT_FLUSHWRITE) { 394 pcc = 0; 395 FD_CLR(p, &ibits); 396 } 397 } 398 } 399 if (FD_ISSET(f, &ibits)) { 400#ifdef CRYPT 401 if (doencrypt) 402 fcc = des_enc_read(f, fibuf, sizeof(fibuf), 403 schedule, &kdata->session); 404 else 405#endif 406 fcc = read(f, fibuf, sizeof(fibuf)); 407 if (fcc < 0 && errno == EWOULDBLOCK) 408 fcc = 0; 409 else { 410 register char *cp; 411 int left, n; 412 413 if (fcc <= 0) 414 break; 415 fbp = fibuf; 416 417 top: 418 for (cp = fibuf; cp < fibuf+fcc-1; cp++) 419 if (cp[0] == magic[0] && 420 cp[1] == magic[1]) { 421 left = fcc - (cp-fibuf); 422 n = control(p, cp, left); 423 if (n) { 424 left -= n; 425 if (left > 0) 426 bcopy(cp+n, cp, left); 427 fcc -= n; 428 goto top; /* n^2 */ 429 } 430 } 431 FD_SET(p, &obits); /* try write */ 432 } 433 } 434 435 if (FD_ISSET(p, &obits) && fcc > 0) { 436 cc = write(p, fbp, fcc); 437 if (cc > 0) { 438 fcc -= cc; 439 fbp += cc; 440 } 441 } 442 443 if (FD_ISSET(p, &ibits)) { 444 pcc = read(p, pibuf, sizeof (pibuf)); 445 pbp = pibuf; 446 if (pcc < 0 && errno == EWOULDBLOCK) 447 pcc = 0; 448 else if (pcc <= 0) 449 break; 450 else if (pibuf[0] == 0) { 451 pbp++, pcc--; 452#ifdef CRYPT 453 if (!doencrypt) 454#endif 455 FD_SET(f, &obits); /* try write */ 456 } else { 457 if (pkcontrol(pibuf[0])) { 458 pibuf[0] |= oobdata[0]; 459 send(f, &pibuf[0], 1, MSG_OOB); 460 } 461 pcc = 0; 462 } 463 } 464 if ((FD_ISSET(f, &obits)) && pcc > 0) { 465#ifdef CRYPT 466 if (doencrypt) 467 cc = des_enc_write(f, pbp, pcc, 468 schedule, &kdata->session); 469 else 470#endif 471 cc = write(f, pbp, pcc); 472 if (cc < 0 && errno == EWOULDBLOCK) { 473 /* 474 * This happens when we try write after read 475 * from p, but some old kernels balk at large 476 * writes even when select returns true. 477 */ 478 if (!FD_ISSET(p, &ibits)) 479 sleep(5); 480 continue; 481 } 482 if (cc > 0) { 483 pcc -= cc; 484 pbp += cc; 485 } 486 } 487 } 488} 489 490void 491cleanup(signo) 492 int signo; 493{ 494 char *p; 495 496 p = line + sizeof(_PATH_DEV) - 1; 497 if (logout(p)) 498 logwtmp(p, "", ""); 499 (void)chflags(line, 0); 500 (void)chmod(line, 0666); 501 (void)chown(line, 0, 0); 502 *p = 'p'; 503 (void)chflags(line, 0); 504 (void)chmod(line, 0666); 505 (void)chown(line, 0, 0); 506 shutdown(netf, 2); 507 exit(1); 508} 509 510void 511fatal(f, msg, syserr) 512 int f; 513 char *msg; 514 int syserr; 515{ 516 int len; 517 char buf[BUFSIZ], *bp = buf; 518 519 /* 520 * Prepend binary one to message if we haven't sent 521 * the magic null as confirmation. 522 */ 523 if (!confirmed) 524 *bp++ = '\01'; /* error indicator */ 525 if (syserr) 526 len = sprintf(bp, "rlogind: %s: %s.\r\n", 527 msg, strerror(errno)); 528 else 529 len = sprintf(bp, "rlogind: %s.\r\n", msg); 530 (void) write(f, buf, bp + len - buf); 531 exit(1); 532} 533 534int 535do_rlogin(dest)
| 278#endif 279 if (do_rlogin(fromp) == 0) 280 authenticated++; 281 } 282 if (confirmed == 0) { 283 write(f, "", 1); 284 confirmed = 1; /* we sent the null! */ 285 } 286#ifdef CRYPT 287 if (doencrypt) 288 (void) des_enc_write(f, 289 SECURE_MESSAGE, 290 strlen(SECURE_MESSAGE), 291 schedule, &kdata->session); 292#endif 293 netf = f; 294 295 pid = forkpty(&master, line, NULL, &win); 296 if (pid < 0) { 297 if (errno == ENOENT) 298 fatal(f, "Out of ptys", 0); 299 else 300 fatal(f, "Forkpty", 1); 301 } 302 if (pid == 0) { 303 if (f > 2) /* f should always be 0, but... */ 304 (void) close(f); 305 setup_term(0); 306 if (*lusername=='-') { 307 syslog(LOG_ERR, "tried to pass user \"%s\" to login", 308 lusername); 309 fatal(STDERR_FILENO, "invalid user", 0); 310 } 311 if (authenticated) { 312 execl(_PATH_LOGIN, "login", "-p", 313 "-h", hostname, "-f", lusername, (char *)NULL); 314 } else 315 execl(_PATH_LOGIN, "login", "-p", 316 "-h", hostname, lusername, (char *)NULL); 317 fatal(STDERR_FILENO, _PATH_LOGIN, 1); 318 /*NOTREACHED*/ 319 } 320#ifdef CRYPT 321 /* 322 * If encrypted, don't turn on NBIO or the des read/write 323 * routines will croak. 324 */ 325 326 if (!doencrypt) 327#endif 328 ioctl(f, FIONBIO, &on); 329 ioctl(master, FIONBIO, &on); 330 ioctl(master, TIOCPKT, &on); 331 signal(SIGCHLD, cleanup); 332 protocol(f, master); 333 signal(SIGCHLD, SIG_IGN); 334 cleanup(0); 335} 336 337char magic[2] = { 0377, 0377 }; 338char oobdata[] = {TIOCPKT_WINDOW}; 339 340/* 341 * Handle a "control" request (signaled by magic being present) 342 * in the data stream. For now, we are only willing to handle 343 * window size changes. 344 */ 345int 346control(pty, cp, n) 347 int pty; 348 char *cp; 349 int n; 350{ 351 struct winsize w; 352 353 if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 354 return (0); 355 oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 356 bcopy(cp+4, (char *)&w, sizeof(w)); 357 w.ws_row = ntohs(w.ws_row); 358 w.ws_col = ntohs(w.ws_col); 359 w.ws_xpixel = ntohs(w.ws_xpixel); 360 w.ws_ypixel = ntohs(w.ws_ypixel); 361 (void)ioctl(pty, TIOCSWINSZ, &w); 362 return (4+sizeof (w)); 363} 364 365/* 366 * rlogin "protocol" machine. 367 */ 368void 369protocol(f, p) 370 register int f, p; 371{ 372 char pibuf[1024+1], fibuf[1024], *pbp, *fbp; 373 int pcc = 0, fcc = 0; 374 int cc, nfd, n; 375 char cntl; 376 377 /* 378 * Must ignore SIGTTOU, otherwise we'll stop 379 * when we try and set slave pty's window shape 380 * (our controlling tty is the master pty). 381 */ 382 (void) signal(SIGTTOU, SIG_IGN); 383 send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 384 if (f > p) 385 nfd = f + 1; 386 else 387 nfd = p + 1; 388 if (nfd > FD_SETSIZE) { 389 syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); 390 fatal(f, "internal error (select mask too small)", 0); 391 } 392 for (;;) { 393 fd_set ibits, obits, ebits, *omask; 394 395 FD_ZERO(&ebits); 396 FD_ZERO(&ibits); 397 FD_ZERO(&obits); 398 omask = (fd_set *)NULL; 399 if (fcc) { 400 FD_SET(p, &obits); 401 omask = &obits; 402 } else 403 FD_SET(f, &ibits); 404 if (pcc >= 0) { 405 if (pcc) { 406 FD_SET(f, &obits); 407 omask = &obits; 408 } else 409 FD_SET(p, &ibits); 410 } 411 FD_SET(p, &ebits); 412 if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { 413 if (errno == EINTR) 414 continue; 415 fatal(f, "select", 1); 416 } 417 if (n == 0) { 418 /* shouldn't happen... */ 419 sleep(5); 420 continue; 421 } 422#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 423 if (FD_ISSET(p, &ebits)) { 424 cc = read(p, &cntl, 1); 425 if (cc == 1 && pkcontrol(cntl)) { 426 cntl |= oobdata[0]; 427 send(f, &cntl, 1, MSG_OOB); 428 if (cntl & TIOCPKT_FLUSHWRITE) { 429 pcc = 0; 430 FD_CLR(p, &ibits); 431 } 432 } 433 } 434 if (FD_ISSET(f, &ibits)) { 435#ifdef CRYPT 436 if (doencrypt) 437 fcc = des_enc_read(f, fibuf, sizeof(fibuf), 438 schedule, &kdata->session); 439 else 440#endif 441 fcc = read(f, fibuf, sizeof(fibuf)); 442 if (fcc < 0 && errno == EWOULDBLOCK) 443 fcc = 0; 444 else { 445 register char *cp; 446 int left, n; 447 448 if (fcc <= 0) 449 break; 450 fbp = fibuf; 451 452 top: 453 for (cp = fibuf; cp < fibuf+fcc-1; cp++) 454 if (cp[0] == magic[0] && 455 cp[1] == magic[1]) { 456 left = fcc - (cp-fibuf); 457 n = control(p, cp, left); 458 if (n) { 459 left -= n; 460 if (left > 0) 461 bcopy(cp+n, cp, left); 462 fcc -= n; 463 goto top; /* n^2 */ 464 } 465 } 466 FD_SET(p, &obits); /* try write */ 467 } 468 } 469 470 if (FD_ISSET(p, &obits) && fcc > 0) { 471 cc = write(p, fbp, fcc); 472 if (cc > 0) { 473 fcc -= cc; 474 fbp += cc; 475 } 476 } 477 478 if (FD_ISSET(p, &ibits)) { 479 pcc = read(p, pibuf, sizeof (pibuf)); 480 pbp = pibuf; 481 if (pcc < 0 && errno == EWOULDBLOCK) 482 pcc = 0; 483 else if (pcc <= 0) 484 break; 485 else if (pibuf[0] == 0) { 486 pbp++, pcc--; 487#ifdef CRYPT 488 if (!doencrypt) 489#endif 490 FD_SET(f, &obits); /* try write */ 491 } else { 492 if (pkcontrol(pibuf[0])) { 493 pibuf[0] |= oobdata[0]; 494 send(f, &pibuf[0], 1, MSG_OOB); 495 } 496 pcc = 0; 497 } 498 } 499 if ((FD_ISSET(f, &obits)) && pcc > 0) { 500#ifdef CRYPT 501 if (doencrypt) 502 cc = des_enc_write(f, pbp, pcc, 503 schedule, &kdata->session); 504 else 505#endif 506 cc = write(f, pbp, pcc); 507 if (cc < 0 && errno == EWOULDBLOCK) { 508 /* 509 * This happens when we try write after read 510 * from p, but some old kernels balk at large 511 * writes even when select returns true. 512 */ 513 if (!FD_ISSET(p, &ibits)) 514 sleep(5); 515 continue; 516 } 517 if (cc > 0) { 518 pcc -= cc; 519 pbp += cc; 520 } 521 } 522 } 523} 524 525void 526cleanup(signo) 527 int signo; 528{ 529 char *p; 530 531 p = line + sizeof(_PATH_DEV) - 1; 532 if (logout(p)) 533 logwtmp(p, "", ""); 534 (void)chflags(line, 0); 535 (void)chmod(line, 0666); 536 (void)chown(line, 0, 0); 537 *p = 'p'; 538 (void)chflags(line, 0); 539 (void)chmod(line, 0666); 540 (void)chown(line, 0, 0); 541 shutdown(netf, 2); 542 exit(1); 543} 544 545void 546fatal(f, msg, syserr) 547 int f; 548 char *msg; 549 int syserr; 550{ 551 int len; 552 char buf[BUFSIZ], *bp = buf; 553 554 /* 555 * Prepend binary one to message if we haven't sent 556 * the magic null as confirmation. 557 */ 558 if (!confirmed) 559 *bp++ = '\01'; /* error indicator */ 560 if (syserr) 561 len = sprintf(bp, "rlogind: %s: %s.\r\n", 562 msg, strerror(errno)); 563 else 564 len = sprintf(bp, "rlogind: %s.\r\n", msg); 565 (void) write(f, buf, bp + len - buf); 566 exit(1); 567} 568 569int 570do_rlogin(dest)
|
536 struct sockaddr_in *dest;
| 571 union sockunion *dest;
|
537{ 538 int retval;
| 572{ 573 int retval;
|
| 574 int af; 575 char *addr;
|
539 540 getstr(rusername, sizeof(rusername), "remuser too long"); 541 getstr(lusername, sizeof(lusername), "locuser too long"); 542 getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 543 544#ifndef NO_PAM 545 retval = auth_pam(lusername); 546 547 if (retval) { 548 if (retval == -1) { 549 syslog(LOG_ERR, "PAM authentication failed"); 550 } 551 else { 552 syslog(LOG_ERR, 553 "User %s failed PAM authentication", lusername); 554 exit(1); 555 } 556 } 557#endif 558 pwd = getpwnam(lusername); 559 if (pwd == NULL) 560 return (-1); 561 /* XXX why don't we syslog() failure? */
| 576 577 getstr(rusername, sizeof(rusername), "remuser too long"); 578 getstr(lusername, sizeof(lusername), "locuser too long"); 579 getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 580 581#ifndef NO_PAM 582 retval = auth_pam(lusername); 583 584 if (retval) { 585 if (retval == -1) { 586 syslog(LOG_ERR, "PAM authentication failed"); 587 } 588 else { 589 syslog(LOG_ERR, 590 "User %s failed PAM authentication", lusername); 591 exit(1); 592 } 593 } 594#endif 595 pwd = getpwnam(lusername); 596 if (pwd == NULL) 597 return (-1); 598 /* XXX why don't we syslog() failure? */
|
562 return (iruserok(dest->sin_addr.s_addr, pwd->pw_uid == 0, 563 rusername, lusername));
| 599 600 af = dest->su_family; 601 switch (af) { 602 case AF_INET: 603 addr = (char *)&dest->su_sin.sin_addr; 604 break; 605#ifdef INET6 606 case AF_INET6: 607 addr = (char *)&dest->su_sin6.sin6_addr; 608 break; 609#endif 610 default: 611 return -1; /*EAFNOSUPPORT*/ 612 } 613 614 return (iruserok_af(addr, pwd->pw_uid == 0, rusername, lusername, af));
|
564} 565 566void 567getstr(buf, cnt, errmsg) 568 char *buf; 569 int cnt; 570 char *errmsg; 571{ 572 char c; 573 574 do { 575 if (read(0, &c, 1) != 1) 576 exit(1); 577 if (--cnt < 0) 578 fatal(STDOUT_FILENO, errmsg, 0); 579 *buf++ = c; 580 } while (c != 0); 581} 582 583extern char **environ; 584 585void 586setup_term(fd) 587 int fd; 588{ 589 register char *cp = index(term+ENVSIZE, '/'); 590 char *speed; 591 struct termios tt; 592 593#ifndef notyet 594 tcgetattr(fd, &tt); 595 if (cp) { 596 *cp++ = '\0'; 597 speed = cp; 598 cp = index(speed, '/'); 599 if (cp) 600 *cp++ = '\0'; 601 cfsetspeed(&tt, atoi(speed)); 602 } 603 604 tt.c_iflag = TTYDEF_IFLAG; 605 tt.c_oflag = TTYDEF_OFLAG; 606 tt.c_lflag = TTYDEF_LFLAG; 607 tcsetattr(fd, TCSAFLUSH, &tt); 608#else 609 if (cp) { 610 *cp++ = '\0'; 611 speed = cp; 612 cp = index(speed, '/'); 613 if (cp) 614 *cp++ = '\0'; 615 tcgetattr(fd, &tt); 616 cfsetspeed(&tt, atoi(speed)); 617 tcsetattr(fd, TCSAFLUSH, &tt); 618 } 619#endif 620 621 env[0] = term; 622 env[1] = 0; 623 environ = env; 624} 625 626void 627usage() 628{ 629 syslog(LOG_ERR, "usage: rlogind [-" ARGSTR "]"); 630}
| 615} 616 617void 618getstr(buf, cnt, errmsg) 619 char *buf; 620 int cnt; 621 char *errmsg; 622{ 623 char c; 624 625 do { 626 if (read(0, &c, 1) != 1) 627 exit(1); 628 if (--cnt < 0) 629 fatal(STDOUT_FILENO, errmsg, 0); 630 *buf++ = c; 631 } while (c != 0); 632} 633 634extern char **environ; 635 636void 637setup_term(fd) 638 int fd; 639{ 640 register char *cp = index(term+ENVSIZE, '/'); 641 char *speed; 642 struct termios tt; 643 644#ifndef notyet 645 tcgetattr(fd, &tt); 646 if (cp) { 647 *cp++ = '\0'; 648 speed = cp; 649 cp = index(speed, '/'); 650 if (cp) 651 *cp++ = '\0'; 652 cfsetspeed(&tt, atoi(speed)); 653 } 654 655 tt.c_iflag = TTYDEF_IFLAG; 656 tt.c_oflag = TTYDEF_OFLAG; 657 tt.c_lflag = TTYDEF_LFLAG; 658 tcsetattr(fd, TCSAFLUSH, &tt); 659#else 660 if (cp) { 661 *cp++ = '\0'; 662 speed = cp; 663 cp = index(speed, '/'); 664 if (cp) 665 *cp++ = '\0'; 666 tcgetattr(fd, &tt); 667 cfsetspeed(&tt, atoi(speed)); 668 tcsetattr(fd, TCSAFLUSH, &tt); 669 } 670#endif 671 672 env[0] = term; 673 env[1] = 0; 674 environ = env; 675} 676 677void 678usage() 679{ 680 syslog(LOG_ERR, "usage: rlogind [-" ARGSTR "]"); 681}
|