rlogind.c revision 24191
160786Sps/*- 260786Sps * Copyright (c) 1983, 1988, 1989, 1993 360786Sps * The Regents of the University of California. All rights reserved. 460786Sps * 560786Sps * Redistribution and use in source and binary forms, with or without 660786Sps * modification, are permitted provided that the following conditions 760786Sps * are met: 860786Sps * 1. Redistributions of source code must retain the above copyright 960786Sps * notice, this list of conditions and the following disclaimer. 1060786Sps * 2. Redistributions in binary form must reproduce the above copyright 1160786Sps * notice, this list of conditions and the following disclaimer in the 1260786Sps * documentation and/or other materials provided with the distribution. 1360786Sps * 3. All advertising materials mentioning features or use of this software 1460786Sps * must display the following acknowledgement: 1560786Sps * This product includes software developed by the University of 1660786Sps * California, Berkeley and its contributors. 1760786Sps * 4. Neither the name of the University nor the names of its contributors 1860786Sps * may be used to endorse or promote products derived from this software 1960786Sps * without specific prior written permission. 2060786Sps * 2160786Sps * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2260786Sps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2360786Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2460786Sps * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2560786Sps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2660786Sps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2760786Sps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2860786Sps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2960786Sps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3060786Sps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3160786Sps * SUCH DAMAGE. 3260786Sps * 3360786Sps * $Id: rlogind.c,v 1.15 1997/02/22 14:22:08 peter Exp $ 3460786Sps */ 3589019Sps 3660786Sps#ifndef lint 3789019Spsstatic char copyright[] = 3860786Sps"@(#) Copyright (c) 1983, 1988, 1989, 1993\n\ 3960786Sps The Regents of the University of California. All rights reserved.\n"; 4060786Sps#endif /* not lint */ 4160786Sps 4260786Sps#ifndef lint 4360786Spsstatic char sccsid[] = "@(#)rlogind.c 8.1 (Berkeley) 6/4/93"; 4460786Sps#endif /* not lint */ 4589019Sps 4689019Sps/* 4789019Sps * remote login server: 4889019Sps * \0 4989019Sps * remuser\0 5089019Sps * locuser\0 5189019Sps * terminal_type/speed\0 5289019Sps * data 5389019Sps */ 5460786Sps 5560786Sps#define FD_SETSIZE 16 /* don't need many bits for select */ 5660786Sps#include <sys/param.h> 5760786Sps#include <sys/stat.h> 5860786Sps#include <sys/ioctl.h> 5960786Sps#include <signal.h> 6060786Sps#include <termios.h> 6160786Sps 6260786Sps#include <sys/socket.h> 6360786Sps#include <netinet/in.h> 6460786Sps#include <netinet/in_systm.h> 6560786Sps#include <netinet/ip.h> 6660786Sps#include <netinet/tcp.h> 6760786Sps#include <arpa/inet.h> 6860786Sps#include <netdb.h> 6960786Sps 7060786Sps#include <pwd.h> 7160786Sps#include <syslog.h> 7260786Sps#include <errno.h> 7360786Sps#include <stdio.h> 7460786Sps#include <unistd.h> 7560786Sps#include <stdlib.h> 7660786Sps#include <string.h> 7760786Sps#include "pathnames.h" 7860786Sps 7960786Sps#ifndef TIOCPKT_WINDOW 8060786Sps#define TIOCPKT_WINDOW 0x80 8160786Sps#endif 8260786Sps 8360786Sps#ifdef KERBEROS 8460786Sps#include <des.h> 8560786Sps#include <kerberosIV/krb.h> 8660786Sps#define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" 8760786Sps 8860786SpsAUTH_DAT *kdata; 8960786SpsKTEXT ticket; 9060786Spsu_char auth_buf[sizeof(AUTH_DAT)]; 9160786Spsu_char tick_buf[sizeof(KTEXT_ST)]; 9260786SpsKey_schedule schedule; 9360786Spsint doencrypt, retval, use_kerberos, vacuous; 9460786Sps 9560786Sps#define ARGSTR "Dalnkvx" 9660786Sps#else 9760786Sps#define ARGSTR "Daln" 9860786Sps#endif /* KERBEROS */ 9960786Sps 10060786Spschar *env[2]; 10160786Sps#define NMAX 30 10260786Spschar lusername[NMAX+1], rusername[NMAX+1]; 10360786Spsstatic char term[64] = "TERM="; 10460786Sps#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ 10560786Spsint keepalive = 1; 10660786Spsint check_all = 0; 10760786Spsint no_delay; 10860786Sps 10960786Spsstruct passwd *pwd; 11060786Sps 11160786Spsvoid doit __P((int, struct sockaddr_in *)); 11260786Spsint control __P((int, char *, int)); 11360786Spsvoid protocol __P((int, int)); 11460786Spsvoid cleanup __P((int)); 11560786Spsvoid fatal __P((int, char *, int)); 11660786Spsint do_rlogin __P((struct sockaddr_in *)); 11760786Spsvoid getstr __P((char *, int, char *)); 11860786Spsvoid setup_term __P((int)); 11960786Spsint do_krb_login __P((struct sockaddr_in *)); 12060786Spsvoid usage __P((void)); 12160786Spsint local_domain __P((char *)); 12260786Spschar *topdomain __P((char *)); 12360786Sps 12460786Spsint 12560786Spsmain(argc, argv) 12660786Sps int argc; 12760786Sps char *argv[]; 12860786Sps{ 12960786Sps extern int __check_rhosts_file; 13060786Sps struct sockaddr_in from; 13160786Sps int ch, fromlen, on; 13260786Sps 13360786Sps openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); 13460786Sps 13560786Sps opterr = 0; 13660786Sps while ((ch = getopt(argc, argv, ARGSTR)) != EOF) 13760786Sps switch (ch) { 13889019Sps case 'D': 13960786Sps no_delay = 1; 14060786Sps break; 14160786Sps case 'a': 14260786Sps check_all = 1; 14389019Sps break; 14489019Sps case 'l': 14589019Sps __check_rhosts_file = 0; 14689019Sps break; 14789019Sps case 'n': 14889019Sps keepalive = 0; 14989019Sps break; 15089019Sps#ifdef KERBEROS 15189019Sps case 'k': 15289019Sps use_kerberos = 1; 15360786Sps break; 15460786Sps case 'v': 15560786Sps vacuous = 1; 15660786Sps break; 15760786Sps#ifdef CRYPT 15860786Sps case 'x': 15960786Sps doencrypt = 1; 16060786Sps break; 16160786Sps#endif 16260786Sps#endif 16360786Sps case '?': 16460786Sps default: 16560786Sps usage(); 16660786Sps break; 16760786Sps } 16860786Sps argc -= optind; 16960786Sps argv += optind; 17060786Sps 17160786Sps#ifdef KERBEROS 17260786Sps if (use_kerberos && vacuous) { 17360786Sps usage(); 17460786Sps fatal(STDERR_FILENO, "only one of -k and -v allowed", 0); 17560786Sps } 17660786Sps#endif 17760786Sps fromlen = sizeof (from); 17860786Sps if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 17960786Sps syslog(LOG_ERR,"Can't get peer name of remote host: %m"); 18060786Sps fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); 18160786Sps } 18260786Sps on = 1; 18360786Sps if (keepalive && 18460786Sps setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 18560786Sps syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 18660786Sps if (no_delay && 18760786Sps setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) 18860786Sps syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m"); 18960786Sps on = IPTOS_LOWDELAY; 19060786Sps if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 19160786Sps syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 19260786Sps 19360786Sps doit(0, &from); 19460786Sps} 19560786Sps 19660786Spsint child; 19760786Spsint netf; 19860786Spschar line[MAXPATHLEN]; 19960786Spsint confirmed; 20060786Sps 20160786Spsstruct winsize win = { 0, 0, 0, 0 }; 20260786Sps 20360786Sps 20460786Spsvoid 20560786Spsdoit(f, fromp) 20660786Sps int f; 20760786Sps struct sockaddr_in *fromp; 20860786Sps{ 20960786Sps int master, pid, on = 1; 21060786Sps int authenticated = 0; 21160786Sps register struct hostent *hp; 21260786Sps char hostname[2 * MAXHOSTNAMELEN + 1]; 21360786Sps char c; 21460786Sps 21560786Sps alarm(60); 21660786Sps read(f, &c, 1); 21760786Sps 21860786Sps if (c != 0) 21960786Sps exit(1); 22060786Sps#ifdef KERBEROS 22160786Sps if (vacuous) 22260786Sps fatal(f, "Remote host requires Kerberos authentication", 0); 22360786Sps#endif 22460786Sps 22560786Sps alarm(0); 22660786Sps fromp->sin_port = ntohs((u_short)fromp->sin_port); 22760786Sps hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof(struct in_addr), 22860786Sps fromp->sin_family); 22960786Sps if (hp) { 23060786Sps (void)strncpy(hostname, hp->h_name, sizeof(hostname)); 23160786Sps } else { 23260786Sps (void)strncpy(hostname, inet_ntoa(fromp->sin_addr), sizeof(hostname)); 23360786Sps } 23460786Sps hostname[sizeof(hostname) - 1] = '\0'; 23560786Sps 23660786Sps#ifdef KERBEROS 23760786Sps if (use_kerberos) { 23860786Sps retval = do_krb_login(fromp); 23960786Sps if (retval == 0) 24060786Sps authenticated++; 24160786Sps else if (retval > 0) 24260786Sps fatal(f, krb_err_txt[retval], 0); 24360786Sps write(f, &c, 1); 24460786Sps confirmed = 1; /* we sent the null! */ 24560786Sps } else 24660786Sps#endif 24760786Sps { 24860786Sps if (fromp->sin_family != AF_INET || 24960786Sps fromp->sin_port >= IPPORT_RESERVED || 25060786Sps fromp->sin_port < IPPORT_RESERVED/2) { 25160786Sps syslog(LOG_NOTICE, "Connection from %s on illegal port", 25260786Sps inet_ntoa(fromp->sin_addr)); 25360786Sps fatal(f, "Permission denied", 0); 25460786Sps } 25560786Sps#ifdef IP_OPTIONS 25660786Sps { 25760786Sps u_char optbuf[BUFSIZ/3]; 25860786Sps int optsize = sizeof(optbuf), ipproto, i; 25960786Sps struct protoent *ip; 26060786Sps 26160786Sps if ((ip = getprotobyname("ip")) != NULL) 26260786Sps ipproto = ip->p_proto; 26360786Sps else 26460786Sps ipproto = IPPROTO_IP; 26589019Sps if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, 26660786Sps &optsize) == 0 && optsize != 0) { 26789019Sps for (i = 0; i < optsize; ) { 26889019Sps u_char c = optbuf[i]; 26989019Sps if (c == IPOPT_LSRR || c == IPOPT_SSRR) { 27089019Sps syslog(LOG_NOTICE, 27189019Sps "Connection refused from %s with IP option %s", 27260786Sps inet_ntoa(fromp->sin_addr), 27360786Sps c == IPOPT_LSRR ? "LSRR" : "SSRR"); 27460786Sps exit(1); 27560786Sps } 27689019Sps if (c == IPOPT_EOL) 27760786Sps break; 27860786Sps i += (c == IPOPT_NOP) ? 1 : optbuf[i+1]; 27960786Sps } 28060786Sps } 28160786Sps } 28260786Sps#endif 28360786Sps if (do_rlogin(fromp) == 0) 28460786Sps authenticated++; 28560786Sps } 28660786Sps if (confirmed == 0) { 28760786Sps write(f, "", 1); 28860786Sps confirmed = 1; /* we sent the null! */ 28960786Sps } 29060786Sps#ifdef KERBEROS 29160786Sps#ifdef CRYPT 29260786Sps if (doencrypt) 29360786Sps (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE) - 1); 29460786Sps#endif 29560786Sps#endif 29660786Sps netf = f; 29760786Sps 29860786Sps pid = forkpty(&master, line, NULL, &win); 29960786Sps if (pid < 0) { 30060786Sps if (errno == ENOENT) 30160786Sps fatal(f, "Out of ptys", 0); 30260786Sps else 30360786Sps fatal(f, "Forkpty", 1); 30460786Sps } 30560786Sps if (pid == 0) { 30660786Sps if (f > 2) /* f should always be 0, but... */ 30760786Sps (void) close(f); 30860786Sps setup_term(0); 30960786Sps if (*lusername=='-') { 31060786Sps syslog(LOG_ERR, "tried to pass user \"%s\" to login", 31160786Sps lusername); 31260786Sps fatal(STDERR_FILENO, "invalid user", 0); 31360786Sps } 31460786Sps if (authenticated) { 31560786Sps#ifdef KERBEROS 31689019Sps if (use_kerberos && (pwd->pw_uid == 0)) 31789019Sps syslog(LOG_INFO|LOG_AUTH, 31889019Sps "ROOT Kerberos login from %s.%s@%s on %s\n", 31989019Sps kdata->pname, kdata->pinst, kdata->prealm, 32089019Sps hostname); 32189019Sps#endif 32289019Sps 32389019Sps execl(_PATH_LOGIN, "login", "-p", 32489019Sps "-h", hostname, "-f", lusername, (char *)NULL); 32589019Sps } else 32689019Sps execl(_PATH_LOGIN, "login", "-p", 32789019Sps "-h", hostname, lusername, (char *)NULL); 32889019Sps fatal(STDERR_FILENO, _PATH_LOGIN, 1); 32989019Sps /*NOTREACHED*/ 33089019Sps } 33189019Sps#ifdef CRYPT 33260786Sps#ifdef KERBEROS 33360786Sps /* 33460786Sps * If encrypted, don't turn on NBIO or the des read/write 33560786Sps * routines will croak. 336 */ 337 338 if (!doencrypt) 339#endif 340#endif 341 ioctl(f, FIONBIO, &on); 342 ioctl(master, FIONBIO, &on); 343 ioctl(master, TIOCPKT, &on); 344 signal(SIGCHLD, cleanup); 345 protocol(f, master); 346 signal(SIGCHLD, SIG_IGN); 347 cleanup(0); 348} 349 350char magic[2] = { 0377, 0377 }; 351char oobdata[] = {TIOCPKT_WINDOW}; 352 353/* 354 * Handle a "control" request (signaled by magic being present) 355 * in the data stream. For now, we are only willing to handle 356 * window size changes. 357 */ 358int 359control(pty, cp, n) 360 int pty; 361 char *cp; 362 int n; 363{ 364 struct winsize w; 365 366 if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 367 return (0); 368 oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 369 bcopy(cp+4, (char *)&w, sizeof(w)); 370 w.ws_row = ntohs(w.ws_row); 371 w.ws_col = ntohs(w.ws_col); 372 w.ws_xpixel = ntohs(w.ws_xpixel); 373 w.ws_ypixel = ntohs(w.ws_ypixel); 374 (void)ioctl(pty, TIOCSWINSZ, &w); 375 return (4+sizeof (w)); 376} 377 378/* 379 * rlogin "protocol" machine. 380 */ 381void 382protocol(f, p) 383 register int f, p; 384{ 385 char pibuf[1024+1], fibuf[1024], *pbp, *fbp; 386 register pcc = 0, fcc = 0; 387 int cc, nfd, n; 388 char cntl; 389 390 /* 391 * Must ignore SIGTTOU, otherwise we'll stop 392 * when we try and set slave pty's window shape 393 * (our controlling tty is the master pty). 394 */ 395 (void) signal(SIGTTOU, SIG_IGN); 396 send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 397 if (f > p) 398 nfd = f + 1; 399 else 400 nfd = p + 1; 401 if (nfd > FD_SETSIZE) { 402 syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); 403 fatal(f, "internal error (select mask too small)", 0); 404 } 405 for (;;) { 406 fd_set ibits, obits, ebits, *omask; 407 408 FD_ZERO(&ebits); 409 FD_ZERO(&ibits); 410 FD_ZERO(&obits); 411 omask = (fd_set *)NULL; 412 if (fcc) { 413 FD_SET(p, &obits); 414 omask = &obits; 415 } else 416 FD_SET(f, &ibits); 417 if (pcc >= 0) 418 if (pcc) { 419 FD_SET(f, &obits); 420 omask = &obits; 421 } else 422 FD_SET(p, &ibits); 423 FD_SET(p, &ebits); 424 if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { 425 if (errno == EINTR) 426 continue; 427 fatal(f, "select", 1); 428 } 429 if (n == 0) { 430 /* shouldn't happen... */ 431 sleep(5); 432 continue; 433 } 434#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 435 if (FD_ISSET(p, &ebits)) { 436 cc = read(p, &cntl, 1); 437 if (cc == 1 && pkcontrol(cntl)) { 438 cntl |= oobdata[0]; 439 send(f, &cntl, 1, MSG_OOB); 440 if (cntl & TIOCPKT_FLUSHWRITE) { 441 pcc = 0; 442 FD_CLR(p, &ibits); 443 } 444 } 445 } 446 if (FD_ISSET(f, &ibits)) { 447#ifdef CRYPT 448#ifdef KERBEROS 449 if (doencrypt) 450 fcc = des_read(f, fibuf, sizeof(fibuf)); 451 else 452#endif 453#endif 454 fcc = read(f, fibuf, sizeof(fibuf)); 455 if (fcc < 0 && errno == EWOULDBLOCK) 456 fcc = 0; 457 else { 458 register char *cp; 459 int left, n; 460 461 if (fcc <= 0) 462 break; 463 fbp = fibuf; 464 465 top: 466 for (cp = fibuf; cp < fibuf+fcc-1; cp++) 467 if (cp[0] == magic[0] && 468 cp[1] == magic[1]) { 469 left = fcc - (cp-fibuf); 470 n = control(p, cp, left); 471 if (n) { 472 left -= n; 473 if (left > 0) 474 bcopy(cp+n, cp, left); 475 fcc -= n; 476 goto top; /* n^2 */ 477 } 478 } 479 FD_SET(p, &obits); /* try write */ 480 } 481 } 482 483 if (FD_ISSET(p, &obits) && fcc > 0) { 484 cc = write(p, fbp, fcc); 485 if (cc > 0) { 486 fcc -= cc; 487 fbp += cc; 488 } 489 } 490 491 if (FD_ISSET(p, &ibits)) { 492 pcc = read(p, pibuf, sizeof (pibuf)); 493 pbp = pibuf; 494 if (pcc < 0 && errno == EWOULDBLOCK) 495 pcc = 0; 496 else if (pcc <= 0) 497 break; 498 else if (pibuf[0] == 0) { 499 pbp++, pcc--; 500#ifdef CRYPT 501#ifdef KERBEROS 502 if (!doencrypt) 503#endif 504#endif 505 FD_SET(f, &obits); /* try write */ 506 } else { 507 if (pkcontrol(pibuf[0])) { 508 pibuf[0] |= oobdata[0]; 509 send(f, &pibuf[0], 1, MSG_OOB); 510 } 511 pcc = 0; 512 } 513 } 514 if ((FD_ISSET(f, &obits)) && pcc > 0) { 515#ifdef CRYPT 516#ifdef KERBEROS 517 if (doencrypt) 518 cc = des_write(f, pbp, pcc); 519 else 520#endif 521#endif 522 cc = write(f, pbp, pcc); 523 if (cc < 0 && errno == EWOULDBLOCK) { 524 /* 525 * This happens when we try write after read 526 * from p, but some old kernels balk at large 527 * writes even when select returns true. 528 */ 529 if (!FD_ISSET(p, &ibits)) 530 sleep(5); 531 continue; 532 } 533 if (cc > 0) { 534 pcc -= cc; 535 pbp += cc; 536 } 537 } 538 } 539} 540 541void 542cleanup(signo) 543 int signo; 544{ 545 char *p; 546 547 p = line + sizeof(_PATH_DEV) - 1; 548 if (logout(p)) 549 logwtmp(p, "", ""); 550 (void)chmod(line, 0666); 551 (void)chown(line, 0, 0); 552 *p = 'p'; 553 (void)chmod(line, 0666); 554 (void)chown(line, 0, 0); 555 shutdown(netf, 2); 556 exit(1); 557} 558 559void 560fatal(f, msg, syserr) 561 int f; 562 char *msg; 563 int syserr; 564{ 565 int len; 566 char buf[BUFSIZ], *bp = buf; 567 568 /* 569 * Prepend binary one to message if we haven't sent 570 * the magic null as confirmation. 571 */ 572 if (!confirmed) 573 *bp++ = '\01'; /* error indicator */ 574 if (syserr) 575 len = sprintf(bp, "rlogind: %s: %s.\r\n", 576 msg, strerror(errno)); 577 else 578 len = sprintf(bp, "rlogind: %s.\r\n", msg); 579 (void) write(f, buf, bp + len - buf); 580 exit(1); 581} 582 583int 584do_rlogin(dest) 585 struct sockaddr_in *dest; 586{ 587 getstr(rusername, sizeof(rusername), "remuser too long"); 588 getstr(lusername, sizeof(lusername), "locuser too long"); 589 getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 590 591 pwd = getpwnam(lusername); 592 if (pwd == NULL) 593 return (-1); 594 /* XXX why don't we syslog() failure? */ 595 return (iruserok(dest->sin_addr.s_addr, pwd->pw_uid == 0, 596 rusername, lusername)); 597} 598 599void 600getstr(buf, cnt, errmsg) 601 char *buf; 602 int cnt; 603 char *errmsg; 604{ 605 char c; 606 607 do { 608 if (read(0, &c, 1) != 1) 609 exit(1); 610 if (--cnt < 0) 611 fatal(STDOUT_FILENO, errmsg, 0); 612 *buf++ = c; 613 } while (c != 0); 614} 615 616extern char **environ; 617 618void 619setup_term(fd) 620 int fd; 621{ 622 register char *cp = index(term+ENVSIZE, '/'); 623 char *speed; 624 struct termios tt; 625 626#ifndef notyet 627 tcgetattr(fd, &tt); 628 if (cp) { 629 *cp++ = '\0'; 630 speed = cp; 631 cp = index(speed, '/'); 632 if (cp) 633 *cp++ = '\0'; 634 cfsetspeed(&tt, atoi(speed)); 635 } 636 637 tt.c_iflag = TTYDEF_IFLAG; 638 tt.c_oflag = TTYDEF_OFLAG; 639 tt.c_lflag = TTYDEF_LFLAG; 640 tcsetattr(fd, TCSAFLUSH, &tt); 641#else 642 if (cp) { 643 *cp++ = '\0'; 644 speed = cp; 645 cp = index(speed, '/'); 646 if (cp) 647 *cp++ = '\0'; 648 tcgetattr(fd, &tt); 649 cfsetspeed(&tt, atoi(speed)); 650 tcsetattr(fd, TCSAFLUSH, &tt); 651 } 652#endif 653 654 env[0] = term; 655 env[1] = 0; 656 environ = env; 657} 658 659#ifdef KERBEROS 660#define VERSION_SIZE 9 661 662/* 663 * Do the remote kerberos login to the named host with the 664 * given inet address 665 * 666 * Return 0 on valid authorization 667 * Return -1 on valid authentication, no authorization 668 * Return >0 for error conditions 669 */ 670int 671do_krb_login(dest) 672 struct sockaddr_in *dest; 673{ 674 int rc; 675 char instance[INST_SZ], version[VERSION_SIZE]; 676 long authopts = 0L; /* !mutual */ 677 struct sockaddr_in faddr; 678 679 kdata = (AUTH_DAT *) auth_buf; 680 ticket = (KTEXT) tick_buf; 681 682 instance[0] = '*'; 683 instance[1] = '\0'; 684 685#ifdef CRYPT 686 if (doencrypt) { 687 rc = sizeof(faddr); 688 if (getsockname(0, (struct sockaddr *)&faddr, &rc)) 689 return (-1); 690 authopts = KOPT_DO_MUTUAL; 691 rc = krb_recvauth( 692 authopts, 0, 693 ticket, "rcmd", 694 instance, dest, &faddr, 695 kdata, "", schedule, version); 696 des_set_key_krb(&kdata->session, schedule); 697 698 } else 699#endif 700 rc = krb_recvauth( 701 authopts, 0, 702 ticket, "rcmd", 703 instance, dest, (struct sockaddr_in *) 0, 704 kdata, "", NULL, version); 705 706 if (rc != KSUCCESS) 707 return (rc); 708 709 getstr(lusername, sizeof(lusername), "locuser"); 710 /* get the "cmd" in the rcmd protocol */ 711 getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 712 713 pwd = getpwnam(lusername); 714 if (pwd == NULL) 715 return (-1); 716 717 /* returns nonzero for no access */ 718 if (kuserok(kdata, lusername) != 0) 719 return (-1); 720 721 return (0); 722 723} 724#endif /* KERBEROS */ 725 726void 727usage() 728{ 729#ifdef KERBEROS 730 syslog(LOG_ERR, "usage: rlogind [-Daln] [-k | -v]"); 731#else 732 syslog(LOG_ERR, "usage: rlogind [-Daln]"); 733#endif 734} 735 736/* 737 * Check whether host h is in our local domain, 738 * defined as sharing the last two components of the domain part, 739 * or the entire domain part if the local domain has only one component. 740 * If either name is unqualified (contains no '.'), 741 * assume that the host is local, as it will be 742 * interpreted as such. 743 */ 744int 745local_domain(h) 746 char *h; 747{ 748 char localhost[MAXHOSTNAMELEN]; 749 char *p1, *p2; 750 751 localhost[0] = 0; 752 (void) gethostname(localhost, sizeof(localhost)); 753 p1 = topdomain(localhost); 754 p2 = topdomain(h); 755 if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) 756 return (1); 757 return (0); 758} 759 760char * 761topdomain(h) 762 char *h; 763{ 764 register char *p; 765 char *maybe = NULL; 766 int dots = 0; 767 768 for (p = h + strlen(h); p >= h; p--) { 769 if (*p == '.') { 770 if (++dots == 2) 771 return (p); 772 maybe = p; 773 } 774 } 775 return (maybe); 776} 777