1/*- 2 * Copyright (c) 1983, 1988, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 2002 Networks Associates Technology, Inc. 5 * All rights reserved. 6 * 7 * Portions of this software were developed for the FreeBSD Project by 8 * ThinkSec AS and NAI Labs, the Security Research Division of Network 9 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 10 * ("CBOSS"), as part of the DARPA CHATS research program. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#if 0 38#ifndef lint 39static const char copyright[] = 40"@(#) Copyright (c) 1983, 1988, 1989, 1993\n\ 41 The Regents of the University of California. All rights reserved.\n"; 42#endif /* not lint */ 43 44#ifndef lint 45static const char sccsid[] = "@(#)rlogind.c 8.1 (Berkeley) 6/4/93"; 46#endif /* not lint */ 47#endif 48#include <sys/cdefs.h> 49__FBSDID("$FreeBSD: src/libexec/rlogind/rlogind.c,v 1.44 2005/05/13 16:31:09 ume Exp $"); 50 51/* 52 * remote login server: 53 * \0 54 * remuser\0 55 * locuser\0 56 * terminal_type/speed\0 57 * data 58 */ 59 60#define FD_SETSIZE 16 /* don't need many bits for select */ 61#include <sys/types.h> 62#include <sys/param.h> 63#include <sys/stat.h> 64#include <sys/ioctl.h> 65#include <signal.h> 66#ifdef __APPLE__ 67#include <sys/termios.h> 68#else 69#include <termios.h> 70#endif 71 72#include <sys/socket.h> 73#include <netinet/in.h> 74#include <netinet/in_systm.h> 75#include <netinet/ip.h> 76#include <netinet/tcp.h> 77#include <arpa/inet.h> 78#include <netdb.h> 79 80#include <errno.h> 81#ifndef __APPLE__ 82#include <libutil.h> 83#else 84#include <util.h> 85#endif 86#include <paths.h> 87#include <pwd.h> 88#include <syslog.h> 89#include <stdio.h> 90#include <stdlib.h> 91#include <string.h> 92#include <unistd.h> 93 94#ifdef __APPLE__ 95#include "pathnames.h" 96#endif 97 98#ifndef TIOCPKT_WINDOW 99#define TIOCPKT_WINDOW 0x80 100#endif 101 102#if defined(KERBEROS) 103#include <kerberosIV/des.h> 104#include <kerberosIV/krb.h> 105#define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" 106 107AUTH_DAT *kdata; 108KTEXT ticket; 109u_char auth_buf[sizeof(AUTH_DAT)]; 110u_char tick_buf[sizeof(KTEXT_ST)]; 111Key_schedule schedule; 112int doencrypt, retval, use_kerberos, vacuous; 113 114#define ARGSTR "alnkvx" 115#else 116#define ARGSTR "Daln" 117#endif /* KERBEROS */ 118 119char *env[2]; 120#define NMAX 30 121char lusername[NMAX+1], rusername[NMAX+1]; 122static char term[64] = "TERM="; 123#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ 124int keepalive = 1; 125int check_all = 0; 126int no_delay; 127 128struct passwd *pwd; 129 130union sockunion { 131 struct sockinet { 132 u_char si_len; 133 u_char si_family; 134 u_short si_port; 135 } su_si; 136 struct sockaddr_in su_sin; 137 struct sockaddr_in6 su_sin6; 138}; 139#define su_len su_si.si_len 140#define su_family su_si.si_family 141#define su_port su_si.si_port 142 143void doit(int, union sockunion *); 144int control(int, char *, int); 145void protocol(int, int); 146void cleanup(int); 147void fatal(int, char *, int); 148int do_rlogin(union sockunion *); 149void getstr(char *, int, char *); 150void setup_term(int); 151int do_krb_login(struct sockaddr_in *); 152void usage(void); 153 154#if defined(KERBEROS) 155int local_domain(char *); 156char *topdomain(char *); 157#endif 158 159int 160main(int argc, char *argv[]) 161{ 162 extern int __check_rhosts_file; 163 union sockunion from; 164 socklen_t fromlen; 165 int ch, on; 166 167 openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); 168 169 opterr = 0; 170 while ((ch = getopt(argc, argv, ARGSTR)) != -1) 171 switch (ch) { 172 case 'D': 173 no_delay = 1; 174 break; 175 case 'a': 176 check_all = 1; 177 break; 178 case 'l': 179 __check_rhosts_file = 0; 180 break; 181 case 'n': 182 keepalive = 0; 183 break; 184#if defined(KERBEROS) 185 case 'k': 186 use_kerberos = 1; 187 break; 188 case 'v': 189 vacuous = 1; 190 break; 191#if defined(CRYPT) 192 case 'x': 193 doencrypt = 1; 194 break; 195#endif 196#endif 197 case '?': 198 default: 199 usage(); 200 break; 201 } 202 argc -= optind; 203 argv += optind; 204 205#if defined(KERBEROS) 206 if (use_kerberos && vacuous) { 207 usage(); 208 fatal(STDERR_FILENO, "only one of -k and -v allowed", 0); 209 } 210#endif 211 fromlen = sizeof (from); 212 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 213 syslog(LOG_ERR,"Can't get peer name of remote host: %m"); 214 fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); 215 } 216 on = 1; 217 if (keepalive && 218 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 219 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 220 if (no_delay && 221 setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) 222 syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m"); 223 if (from.su_family == AF_INET) 224 { 225 on = IPTOS_LOWDELAY; 226 if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 227 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 228 } 229 230 doit(0, &from); 231 return 0; 232} 233 234int child; 235int netf; 236char line[MAXPATHLEN]; 237int confirmed; 238 239struct winsize win = { 0, 0, 0, 0 }; 240 241 242void 243doit(int f, union sockunion *fromp) 244{ 245 int master, pid, on = 1; 246 int authenticated = 0; 247 char hostname[2 * MAXHOSTNAMELEN + 1]; 248 char nameinfo[2 * INET6_ADDRSTRLEN + 1]; 249 char c; 250 251 alarm(60); 252 read(f, &c, 1); 253 254 if (c != 0) 255 exit(1); 256#if defined(KERBEROS) 257 if (vacuous) 258 fatal(f, "Remote host requires Kerberos authentication", 0); 259#endif 260 261 alarm(0); 262#ifdef __APPLE__ 263 struct hostent* hp; 264 fromp->su_port = ntohs((u_short)fromp->su_port); 265 hp = gethostbyaddr((char *)&fromp->su_sin.sin_addr, 266 sizeof(struct in_addr), fromp->su_family); 267 if (hp) 268 (void)strcpy(hostname, hp->h_name); 269 else 270 (void)strcpy(hostname, inet_ntoa(fromp->su_sin.sin_addr)); 271#else 272 realhostname_sa(hostname, sizeof(hostname) - 1, 273 (struct sockaddr *)fromp, fromp->su_len); 274 /* error check ? */ 275 fromp->su_port = ntohs((u_short)fromp->su_port); 276 hostname[sizeof(hostname) - 1] = '\0'; 277#endif 278 279#if defined(KERBEROS) 280 if (use_kerberos) { 281 retval = do_krb_login(fromp); 282 if (retval == 0) 283 authenticated++; 284 else if (retval > 0) 285 fatal(f, krb_err_txt[retval], 0); 286 write(f, &c, 1); 287 confirmed = 1; /* we sent the null! */ 288 } else 289#endif 290 { 291 if ((fromp->su_family != AF_INET 292 && fromp->su_family != AF_INET6 293 ) || 294 fromp->su_port >= IPPORT_RESERVED || 295 fromp->su_port < IPPORT_RESERVED/2) { 296 getnameinfo((struct sockaddr *)fromp, 297 fromp->su_len, 298 nameinfo, sizeof(nameinfo), NULL, 0, 299 NI_NUMERICHOST); 300 /* error check ? */ 301 syslog(LOG_NOTICE, "Connection from %s on illegal port", 302 nameinfo); 303 fatal(f, "Permission denied", 0); 304 } 305#ifdef IP_OPTIONS 306 if (fromp->su_family == AF_INET) 307 { 308 u_char optbuf[BUFSIZ/3]; 309 socklen_t optsize = sizeof(optbuf); 310 int ipproto, i; 311 struct protoent *ip; 312 313 if ((ip = getprotobyname("ip")) != NULL) 314 ipproto = ip->p_proto; 315 else 316 ipproto = IPPROTO_IP; 317 if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, 318 &optsize) == 0 && optsize != 0) { 319 for (i = 0; i < optsize; ) { 320 u_char c = optbuf[i]; 321 if (c == IPOPT_LSRR || c == IPOPT_SSRR) { 322 syslog(LOG_NOTICE, 323 "Connection refused from %s with IP option %s", 324 inet_ntoa(fromp->su_sin.sin_addr), 325 c == IPOPT_LSRR ? "LSRR" : "SSRR"); 326 exit(1); 327 } 328 if (c == IPOPT_EOL) 329 break; 330 i += (c == IPOPT_NOP) ? 1 : optbuf[i+1]; 331 } 332 } 333 } 334#endif 335 if (do_rlogin(fromp) == 0) 336 authenticated++; 337 } 338 if (confirmed == 0) { 339 write(f, "", 1); 340 confirmed = 1; /* we sent the null! */ 341 } 342#if defined(KERBEROS) && defined(CRYPT) 343 if (doencrypt) 344 (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE) - 1); 345#endif 346 netf = f; 347 348 pid = forkpty(&master, line, NULL, &win); 349 if (pid < 0) { 350 if (errno == ENOENT) 351 fatal(f, "Out of ptys", 0); 352 else 353 fatal(f, "Forkpty", 1); 354 } 355 if (pid == 0) { 356 if (f > 2) /* f should always be 0, but... */ 357 (void) close(f); 358 setup_term(0); 359#ifndef __APPLE__ 360 if (*lusername=='-') { 361 syslog(LOG_ERR, "tried to pass user \"%s\" to login", 362 lusername); 363 fatal(STDERR_FILENO, "invalid user", 0); 364 } 365#endif 366 if (authenticated) { 367#if defined(KERBEROS) 368 if (use_kerberos && (pwd->pw_uid == 0)) 369 syslog(LOG_INFO|LOG_AUTH, 370 "ROOT Kerberos login from %s.%s@%s on %s\n", 371 kdata->pname, kdata->pinst, kdata->prealm, 372 hostname); 373#endif 374#ifdef __APPLE__ 375 execle(_PATH_LOGIN, "login", "-p", 376 "-h", hostname, "-f", "--", lusername, NULL, env); 377#else 378 execl(_PATH_LOGIN, "login", "-p", 379 "-h", hostname, "-f", lusername, (char *)NULL); 380#endif 381 } else 382#ifdef __APPLE__ 383 execle(_PATH_LOGIN, "login", "-p", 384 "-h", hostname, "--", lusername, NULL, env); 385#else 386 execl(_PATH_LOGIN, "login", "-p", 387 "-h", hostname, lusername, (char *)NULL); 388#endif 389 fatal(STDERR_FILENO, _PATH_LOGIN, 1); 390 /*NOTREACHED*/ 391 } 392#if defined(KERBEROS) && defined(CRYPT) 393 /* 394 * If encrypted, don't turn on NBIO or the des read/write 395 * routines will croak. 396 */ 397 398 if (!doencrypt) 399#endif 400 ioctl(f, FIONBIO, &on); 401 ioctl(master, FIONBIO, &on); 402 ioctl(master, TIOCPKT, &on); 403 signal(SIGCHLD, cleanup); 404 protocol(f, master); 405 signal(SIGCHLD, SIG_IGN); 406 cleanup(0); 407} 408 409char magic[2] = { 0377, 0377 }; 410char oobdata[] = {TIOCPKT_WINDOW}; 411 412/* 413 * Handle a "control" request (signaled by magic being present) 414 * in the data stream. For now, we are only willing to handle 415 * window size changes. 416 */ 417int 418control(int pty, char *cp, int n) 419{ 420 struct winsize w; 421 422 if (n < 4 + (int)sizeof(w) || cp[2] != 's' || cp[3] != 's') 423 return (0); 424 oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 425 bcopy(cp+4, (char *)&w, sizeof(w)); 426 w.ws_row = ntohs(w.ws_row); 427 w.ws_col = ntohs(w.ws_col); 428 w.ws_xpixel = ntohs(w.ws_xpixel); 429 w.ws_ypixel = ntohs(w.ws_ypixel); 430 (void)ioctl(pty, TIOCSWINSZ, &w); 431 return (4+sizeof (w)); 432} 433 434/* 435 * rlogin "protocol" machine. 436 */ 437void 438protocol(int f, int p) 439{ 440 char pibuf[1024+1], fibuf[1024], *pbp = NULL, *fbp = NULL; 441 int pcc = 0, fcc = 0; 442 int cc, nfd, n; 443 char cntl; 444 445 /* 446 * Must ignore SIGTTOU, otherwise we'll stop 447 * when we try and set slave pty's window shape 448 * (our controlling tty is the master pty). 449 */ 450 (void) signal(SIGTTOU, SIG_IGN); 451 send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 452 if (f > p) 453 nfd = f + 1; 454 else 455 nfd = p + 1; 456 if (nfd > FD_SETSIZE) { 457 syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); 458 fatal(f, "internal error (select mask too small)", 0); 459 } 460 for (;;) { 461 fd_set ibits, obits, ebits, *omask; 462 463 FD_ZERO(&ebits); 464 FD_ZERO(&ibits); 465 FD_ZERO(&obits); 466 omask = (fd_set *)NULL; 467 if (fcc) { 468 FD_SET(p, &obits); 469 omask = &obits; 470 } else 471 FD_SET(f, &ibits); 472 if (pcc >= 0) { 473 if (pcc) { 474 FD_SET(f, &obits); 475 omask = &obits; 476 } else 477 FD_SET(p, &ibits); 478 } 479 FD_SET(p, &ebits); 480 if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { 481 if (errno == EINTR) 482 continue; 483 fatal(f, "select", 1); 484 } 485 if (n == 0) { 486 /* shouldn't happen... */ 487 sleep(5); 488 continue; 489 } 490#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 491 if (FD_ISSET(p, &ebits)) { 492 cc = read(p, &cntl, 1); 493 if (cc == 1 && pkcontrol(cntl)) { 494 cntl |= oobdata[0]; 495 send(f, &cntl, 1, MSG_OOB); 496 if (cntl & TIOCPKT_FLUSHWRITE) { 497 pcc = 0; 498 FD_CLR(p, &ibits); 499 } 500 } 501 } 502 if (FD_ISSET(f, &ibits)) { 503#if defined(KERBEROS) && defined(CRYPT) 504 if (doencrypt) 505 fcc = des_read(f, fibuf, sizeof(fibuf)); 506 else 507#endif 508 fcc = read(f, fibuf, sizeof(fibuf)); 509 if (fcc < 0 && errno == EWOULDBLOCK) 510 fcc = 0; 511 else { 512 char *cp; 513 int left, n; 514 515 if (fcc <= 0) 516 break; 517 fbp = fibuf; 518 519 top: 520 for (cp = fibuf; cp < fibuf+fcc-1; cp++) 521 if (cp[0] == magic[0] && 522 cp[1] == magic[1]) { 523 left = fcc - (cp-fibuf); 524 n = control(p, cp, left); 525 if (n) { 526 left -= n; 527 if (left > 0) 528 bcopy(cp+n, cp, left); 529 fcc -= n; 530 goto top; /* n^2 */ 531 } 532 } 533 FD_SET(p, &obits); /* try write */ 534 } 535 } 536 537 if (FD_ISSET(p, &obits) && fcc > 0) { 538 cc = write(p, fbp, fcc); 539 if (cc > 0) { 540 fcc -= cc; 541 fbp += cc; 542 } 543 } 544 545 if (FD_ISSET(p, &ibits)) { 546 pcc = read(p, pibuf, sizeof (pibuf)); 547 pbp = pibuf; 548 if (pcc < 0 && errno == EWOULDBLOCK) 549 pcc = 0; 550 else if (pcc <= 0) 551 break; 552 else if (pibuf[0] == 0) { 553 pbp++, pcc--; 554#if defined(KERBEROS) && defined(CRYPT) 555 if (!doencrypt) 556#endif 557 FD_SET(f, &obits); /* try write */ 558 } else { 559 if (pkcontrol(pibuf[0])) { 560 pibuf[0] |= oobdata[0]; 561 send(f, &pibuf[0], 1, MSG_OOB); 562 } 563 pcc = 0; 564 } 565 } 566 if ((FD_ISSET(f, &obits)) && pcc > 0) { 567#if defined(KERBEROS) && defined(CRYPT) 568 if (doencrypt) 569 cc = des_write(f, pbp, pcc); 570 else 571#endif 572 cc = write(f, pbp, pcc); 573 if (cc < 0 && errno == EWOULDBLOCK) { 574 /* 575 * This happens when we try write after read 576 * from p, but some old kernels balk at large 577 * writes even when select returns true. 578 */ 579 if (!FD_ISSET(p, &ibits)) 580 sleep(5); 581 continue; 582 } 583 if (cc > 0) { 584 pcc -= cc; 585 pbp += cc; 586 } 587 } 588 } 589} 590 591void 592cleanup(int signo) 593{ 594#ifndef __APPLE__ 595 /* rdar://problem/4433603 */ 596 char *p; 597 598 p = line + sizeof(_PATH_DEV) - 1; 599 if (logout(p)) 600 logwtmp(p, "", ""); 601 (void)chflags(line, 0); 602 (void)chmod(line, 0666); 603 (void)chown(line, 0, 0); 604 *p = 'p'; 605 (void)chflags(line, 0); 606 (void)chmod(line, 0666); 607 (void)chown(line, 0, 0); 608#endif 609 shutdown(netf, SHUT_RDWR); 610 exit(1); 611} 612 613void 614fatal(int f, char *msg, int syserr) 615{ 616 int len; 617 char buf[BUFSIZ], *bp = buf; 618 619 /* 620 * Prepend binary one to message if we haven't sent 621 * the magic null as confirmation. 622 */ 623 if (!confirmed) 624 *bp++ = '\01'; /* error indicator */ 625 if (syserr) 626 len = snprintf(bp, sizeof(buf), "rlogind: %s: %s.\r\n", 627 msg, strerror(errno)); 628 else 629 len = snprintf(bp, sizeof(buf), "rlogind: %s.\r\n", msg); 630 if (len < 0) 631 len = 0; 632 (void) write(f, buf, bp + len - buf); 633 exit(1); 634} 635 636int 637do_rlogin(union sockunion *dest) 638{ 639 640 getstr(rusername, sizeof(rusername), "remuser too long"); 641 getstr(lusername, sizeof(lusername), "locuser too long"); 642 getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 643 644 pwd = getpwnam(lusername); 645 if (pwd == NULL) 646#ifdef __APPLE__ 647 { 648 syslog(LOG_ERR, 649 "rlogin denied for user %s: getpwnam() failed\n", 650 lusername); 651 return (-1); 652 } 653#else 654 return (-1); 655 /* XXX why don't we syslog() failure? */ 656#endif 657 658#ifdef __APPLE__ 659 /* rdar://problem/2840513 */ 660 if (pwd->pw_uid == 0 && strcmp("root", lusername)) 661 { 662 syslog(LOG_ALERT, 663 "rlogin denied for non-root user %s with uid 0\n", 664 lusername); 665 return (-1); 666 } 667#endif 668 return (iruserok_sa(dest, dest->su_len, pwd->pw_uid == 0, rusername, 669 lusername)); 670} 671 672void 673getstr(char *buf, int cnt, char *errmsg) 674{ 675 char c; 676 677 do { 678 if (read(STDIN_FILENO, &c, 1) != 1) 679 exit(1); 680 if (--cnt < 0) 681 fatal(STDOUT_FILENO, errmsg, 0); 682 *buf++ = c; 683 } while (c != 0); 684} 685 686extern char **environ; 687 688void 689setup_term(int fd) 690{ 691 char *cp = index(term+ENVSIZE, '/'); 692 char *speed; 693 struct termios tt; 694 695#ifndef notyet 696 tcgetattr(fd, &tt); 697 if (cp) { 698 *cp++ = '\0'; 699 speed = cp; 700 cp = index(speed, '/'); 701 if (cp) 702 *cp++ = '\0'; 703 cfsetspeed(&tt, atoi(speed)); 704 } 705 706 tt.c_iflag = TTYDEF_IFLAG; 707 tt.c_oflag = TTYDEF_OFLAG; 708 tt.c_lflag = TTYDEF_LFLAG; 709 tcsetattr(fd, TCSAFLUSH, &tt); 710#else 711 if (cp) { 712 *cp++ = '\0'; 713 speed = cp; 714 cp = index(speed, '/'); 715 if (cp) 716 *cp++ = '\0'; 717 tcgetattr(fd, &tt); 718 cfsetspeed(&tt, atoi(speed)); 719 tcsetattr(fd, TCSAFLUSH, &tt); 720 } 721#endif 722 723 env[0] = term; 724 env[1] = 0; 725 environ = env; 726} 727 728#if defined(KERBEROS) 729#define VERSION_SIZE 9 730 731/* 732 * Do the remote kerberos login to the named host with the 733 * given inet address 734 * 735 * Return 0 on valid authorization 736 * Return -1 on valid authentication, no authorization 737 * Return >0 for error conditions 738 */ 739int 740do_krb_login(dest) 741 struct sockaddr_in *dest; 742{ 743 int rc; 744 char instance[INST_SZ], version[VERSION_SIZE]; 745 long authopts = 0L; /* !mutual */ 746 struct sockaddr_in faddr; 747 748 kdata = (AUTH_DAT *) auth_buf; 749 ticket = (KTEXT) tick_buf; 750 751 instance[0] = '*'; 752 instance[1] = '\0'; 753 754#if defined(CRYPT) 755 if (doencrypt) { 756 rc = sizeof(faddr); 757 if (getsockname(0, (struct sockaddr *)&faddr, &rc)) 758 return (-1); 759 authopts = KOPT_DO_MUTUAL; 760 rc = krb_recvauth( 761 authopts, 0, 762 ticket, "rcmd", 763 instance, dest, &faddr, 764 kdata, "", schedule, version); 765 des_set_key(kdata->session, schedule); 766 767 } else 768#endif /* CRYPT */ 769 rc = krb_recvauth( 770 authopts, 0, 771 ticket, "rcmd", 772 instance, dest, (struct sockaddr_in *) 0, 773 kdata, "", (bit_64 *) 0, version); 774 775 if (rc != KSUCCESS) 776 return (rc); 777 778 getstr(lusername, sizeof(lusername), "locuser"); 779 /* get the "cmd" in the rcmd protocol */ 780 getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 781 782 pwd = getpwnam(lusername); 783 if (pwd == NULL) 784 return (-1); 785 786 /* returns nonzero for no access */ 787 if (kuserok(kdata, lusername) != 0) 788 return (-1); 789 790 return (0); 791 792} 793#endif /* KERBEROS */ 794 795void 796usage(void) 797{ 798#if defined(KERBEROS) 799 syslog(LOG_ERR, "usage: rlogind [-aln] [-k | -v]"); 800#else 801 syslog(LOG_ERR, "usage: rlogind [-" ARGSTR "]"); 802#endif 803} 804 805#if defined(KERBEROS) 806/* 807 * Check whether host h is in our local domain, 808 * defined as sharing the last two components of the domain part, 809 * or the entire domain part if the local domain has only one component. 810 * If either name is unqualified (contains no '.'), 811 * assume that the host is local, as it will be 812 * interpreted as such. 813 */ 814int 815local_domain(h) 816 char *h; 817{ 818 char localhost[MAXHOSTNAMELEN]; 819 char *p1, *p2; 820 821 localhost[0] = 0; 822 (void) gethostname(localhost, sizeof(localhost)); 823 p1 = topdomain(localhost); 824 p2 = topdomain(h); 825 if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) 826 return (1); 827 return (0); 828} 829 830char * 831topdomain(h) 832 char *h; 833{ 834 char *p; 835 char *maybe = NULL; 836 int dots = 0; 837 838 for (p = h + strlen(h); p >= h; p--) { 839 if (*p == '.') { 840 if (++dots == 2) 841 return (p); 842 maybe = p; 843 } 844 } 845 return (maybe); 846} 847#endif /* KERBEROS */ 848