rlogind.c revision 50476
1193323Sed/*- 2193323Sed * Copyright (c) 1983, 1988, 1989, 1993 3193323Sed * The Regents of the University of California. All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer. 10193323Sed * 2. Redistributions in binary form must reproduce the above copyright 11193323Sed * notice, this list of conditions and the following disclaimer in the 12193323Sed * documentation and/or other materials provided with the distribution. 13204961Srdivacky * 3. All advertising materials mentioning features or use of this software 14198090Srdivacky * must display the following acknowledgement: 15193323Sed * This product includes software developed by the University of 16206274Srdivacky * California, Berkeley and its contributors. 17206274Srdivacky * 4. Neither the name of the University nor the names of its contributors 18193323Sed * may be used to endorse or promote products derived from this software 19218893Sdim * without specific prior written permission. 20198090Srdivacky * 21193323Sed * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22204961Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23198090Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24198090Srdivacky * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25204961Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26202878Srdivacky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27198090Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28218893Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29198090Srdivacky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30206274Srdivacky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31198090Srdivacky * SUCH DAMAGE. 32207618Srdivacky */ 33206274Srdivacky 34218893Sdim#ifndef lint 35205218Srdivackystatic const char copyright[] = 36198090Srdivacky"@(#) Copyright (c) 1983, 1988, 1989, 1993\n\ 37207618Srdivacky The Regents of the University of California. All rights reserved.\n"; 38198090Srdivacky#endif /* not lint */ 39198090Srdivacky 40203954Srdivacky#ifndef lint 41202878Srdivacky#if 0 42193323Sedstatic const char sccsid[] = "@(#)rlogind.c 8.1 (Berkeley) 6/4/93"; 43218893Sdim#endif 44193323Sedstatic const char rcsid[] = 45193323Sed "$FreeBSD: head/libexec/rlogind/rlogind.c 50476 1999-08-28 00:22:10Z peter $"; 46207618Srdivacky#endif /* not lint */ 47207618Srdivacky 48207618Srdivacky/* 49212904Sdim * remote login server: 50210299Sed * \0 51207618Srdivacky * remuser\0 52207618Srdivacky * locuser\0 53208599Srdivacky * terminal_type/speed\0 54208599Srdivacky * data 55208599Srdivacky */ 56208599Srdivacky 57218893Sdim#define FD_SETSIZE 16 /* don't need many bits for select */ 58218893Sdim#include <sys/types.h> 59218893Sdim#include <sys/param.h> 60218893Sdim#include <sys/stat.h> 61207618Srdivacky#include <sys/ioctl.h> 62207618Srdivacky#include <signal.h> 63207618Srdivacky#include <termios.h> 64207618Srdivacky 65207618Srdivacky#include <sys/socket.h> 66193323Sed#include <netinet/in.h> 67193323Sed#include <netinet/in_systm.h> 68193323Sed#include <netinet/ip.h> 69193323Sed#include <netinet/tcp.h> 70193323Sed#include <arpa/inet.h> 71193323Sed#include <netdb.h> 72193323Sed 73193323Sed#include <errno.h> 74193323Sed#include <libutil.h> 75193323Sed#include <pwd.h> 76193323Sed#include <syslog.h> 77199481Srdivacky#include <stdio.h> 78193323Sed#include <stdlib.h> 79193323Sed#include <string.h> 80193323Sed#include <unistd.h> 81193323Sed#include "pathnames.h" 82193323Sed 83193323Sed#ifndef TIOCPKT_WINDOW 84205218Srdivacky#define TIOCPKT_WINDOW 0x80 85193323Sed#endif 86205218Srdivacky 87199989Srdivacky#ifdef KERBEROS 88199989Srdivacky#include <des.h> 89210299Sed#include <krb.h> 90193323Sed#define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" 91210299Sed 92193323SedAUTH_DAT *kdata; 93210299SedKTEXT ticket; 94193323Sedu_char auth_buf[sizeof(AUTH_DAT)]; 95210299Sedu_char tick_buf[sizeof(KTEXT_ST)]; 96193323SedKey_schedule schedule; 97193323Sedint doencrypt, retval, use_kerberos, vacuous; 98193323Sed 99193323Sed#define ARGSTR "Dalnkvx" 100193323Sed#else 101199989Srdivacky#define ARGSTR "Daln" 102193323Sed#endif /* KERBEROS */ 103199989Srdivacky 104199989Srdivackychar *env[2]; 105193323Sed#define NMAX 30 106193323Sedchar lusername[NMAX+1], rusername[NMAX+1]; 107199989Srdivackystatic char term[64] = "TERM="; 108193323Sed#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ 109193323Sedint keepalive = 1; 110199989Srdivackyint check_all = 0; 111205218Srdivackyint no_delay; 112199989Srdivacky 113199989Srdivackystruct passwd *pwd; 114193323Sed 115193323Sedvoid doit __P((int, struct sockaddr_in *)); 116193323Sedint control __P((int, char *, int)); 117199989Srdivackyvoid protocol __P((int, int)); 118193323Sedvoid cleanup __P((int)); 119199989Srdivackyvoid fatal __P((int, char *, int)); 120193323Sedint do_rlogin __P((struct sockaddr_in *)); 121206083Srdivackyvoid getstr __P((char *, int, char *)); 122193323Sedvoid setup_term __P((int)); 123199989Srdivackyint do_krb_login __P((struct sockaddr_in *)); 124199989Srdivackyvoid usage __P((void)); 125212904Sdim 126212904Sdimint 127199989Srdivackymain(argc, argv) 128199989Srdivacky int argc; 129199989Srdivacky char *argv[]; 130193323Sed{ 131210299Sed extern int __check_rhosts_file; 132193323Sed struct sockaddr_in from; 133199989Srdivacky int ch, fromlen, on; 134208599Srdivacky 135210299Sed openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); 136193323Sed 137193323Sed opterr = 0; 138199989Srdivacky while ((ch = getopt(argc, argv, ARGSTR)) != -1) 139199989Srdivacky switch (ch) { 140212904Sdim case 'D': 141212904Sdim no_delay = 1; 142212904Sdim break; 143210299Sed case 'a': 144201360Srdivacky check_all = 1; 145201360Srdivacky break; 146201360Srdivacky case 'l': 147199989Srdivacky __check_rhosts_file = 0; 148199989Srdivacky break; 149208599Srdivacky case 'n': 150210299Sed keepalive = 0; 151199989Srdivacky break; 152199989Srdivacky#ifdef KERBEROS 153199989Srdivacky case 'k': 154193323Sed use_kerberos = 1; 155199989Srdivacky break; 156199989Srdivacky case 'v': 157199989Srdivacky vacuous = 1; 158193323Sed break; 159199989Srdivacky#ifdef CRYPT 160199989Srdivacky case 'x': 161199989Srdivacky doencrypt = 1; 162199989Srdivacky break; 163193323Sed#endif 164199989Srdivacky#endif 165199989Srdivacky case '?': 166199989Srdivacky default: 167199989Srdivacky usage(); 168193323Sed break; 169199989Srdivacky } 170193323Sed argc -= optind; 171193323Sed argv += optind; 172193323Sed 173193323Sed#ifdef KERBEROS 174193323Sed if (use_kerberos && vacuous) { 175198892Srdivacky usage(); 176193323Sed fatal(STDERR_FILENO, "only one of -k and -v allowed", 0); 177208599Srdivacky } 178208599Srdivacky#endif 179193323Sed fromlen = sizeof (from); 180205218Srdivacky if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 181208599Srdivacky syslog(LOG_ERR,"Can't get peer name of remote host: %m"); 182193323Sed fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); 183193323Sed } 184199481Srdivacky on = 1; 185199481Srdivacky if (keepalive && 186199481Srdivacky setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 187208599Srdivacky syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 188208599Srdivacky if (no_delay && 189212904Sdim setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) 190212904Sdim syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m"); 191212904Sdim on = IPTOS_LOWDELAY; 192212904Sdim if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 193212904Sdim syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 194212904Sdim 195212904Sdim doit(0, &from); 196212904Sdim return 0; 197212904Sdim} 198212904Sdim 199212904Sdimint child; 200212904Sdimint netf; 201212904Sdimchar line[MAXPATHLEN]; 202212904Sdimint confirmed; 203212904Sdim 204212904Sdimstruct winsize win = { 0, 0, 0, 0 }; 205212904Sdim 206212904Sdim 207212904Sdimvoid 208212904Sdimdoit(f, fromp) 209212904Sdim int f; 210212904Sdim struct sockaddr_in *fromp; 211212904Sdim{ 212212904Sdim int master, pid, on = 1; 213212904Sdim int authenticated = 0; 214212904Sdim char hostname[MAXHOSTNAMELEN]; 215212904Sdim char c; 216212904Sdim 217212904Sdim alarm(60); 218212904Sdim read(f, &c, 1); 219212904Sdim 220212904Sdim if (c != 0) 221212904Sdim exit(1); 222212904Sdim#ifdef KERBEROS 223212904Sdim if (vacuous) 224212904Sdim fatal(f, "Remote host requires Kerberos authentication", 0); 225212904Sdim#endif 226212904Sdim 227212904Sdim alarm(0); 228212904Sdim fromp->sin_port = ntohs((u_short)fromp->sin_port); 229212904Sdim realhostname(hostname, sizeof(hostname) - 1, &fromp->sin_addr); 230212904Sdim hostname[sizeof(hostname) - 1] = '\0'; 231212904Sdim 232212904Sdim#ifdef KERBEROS 233212904Sdim if (use_kerberos) { 234212904Sdim retval = do_krb_login(fromp); 235212904Sdim if (retval == 0) 236212904Sdim authenticated++; 237212904Sdim else if (retval > 0) 238212904Sdim fatal(f, krb_err_txt[retval], 0); 239212904Sdim write(f, &c, 1); 240212904Sdim confirmed = 1; /* we sent the null! */ 241212904Sdim } else 242212904Sdim#endif 243212904Sdim { 244212904Sdim if (fromp->sin_family != AF_INET || 245212904Sdim fromp->sin_port >= IPPORT_RESERVED || 246212904Sdim fromp->sin_port < IPPORT_RESERVED/2) { 247212904Sdim syslog(LOG_NOTICE, "Connection from %s on illegal port", 248212904Sdim inet_ntoa(fromp->sin_addr)); 249212904Sdim fatal(f, "Permission denied", 0); 250212904Sdim } 251212904Sdim#ifdef IP_OPTIONS 252212904Sdim { 253212904Sdim u_char optbuf[BUFSIZ/3]; 254212904Sdim int optsize = sizeof(optbuf), ipproto, i; 255212904Sdim struct protoent *ip; 256193323Sed 257193323Sed if ((ip = getprotobyname("ip")) != NULL) 258193323Sed ipproto = ip->p_proto; 259207618Srdivacky else 260207618Srdivacky ipproto = IPPROTO_IP; 261207618Srdivacky if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, 262207618Srdivacky &optsize) == 0 && optsize != 0) { 263207618Srdivacky for (i = 0; i < optsize; ) { 264207618Srdivacky u_char c = optbuf[i]; 265193323Sed if (c == IPOPT_LSRR || c == IPOPT_SSRR) { 266193323Sed syslog(LOG_NOTICE, 267198892Srdivacky "Connection refused from %s with IP option %s", 268193323Sed inet_ntoa(fromp->sin_addr), 269199989Srdivacky c == IPOPT_LSRR ? "LSRR" : "SSRR"); 270203954Srdivacky exit(1); 271212904Sdim } 272199481Srdivacky if (c == IPOPT_EOL) 273198090Srdivacky break; 274198090Srdivacky i += (c == IPOPT_NOP) ? 1 : optbuf[i+1]; 275207618Srdivacky } 276205218Srdivacky } 277205218Srdivacky } 278205218Srdivacky#endif 279205218Srdivacky if (do_rlogin(fromp) == 0) 280207618Srdivacky authenticated++; 281195098Sed } 282195098Sed if (confirmed == 0) { 283193323Sed write(f, "", 1); 284208599Srdivacky confirmed = 1; /* we sent the null! */ 285199481Srdivacky } 286207618Srdivacky#ifdef KERBEROS 287207618Srdivacky#ifdef CRYPT 288193323Sed if (doencrypt) 289193323Sed (void) des_enc_write(f, 290193323Sed SECURE_MESSAGE, 291193323Sed strlen(SECURE_MESSAGE), 292199481Srdivacky schedule, &kdata->session); 293193323Sed#endif 294208599Srdivacky#endif 295208599Srdivacky netf = f; 296205218Srdivacky 297212904Sdim pid = forkpty(&master, line, NULL, &win); 298207618Srdivacky if (pid < 0) { 299207618Srdivacky if (errno == ENOENT) 300207618Srdivacky fatal(f, "Out of ptys", 0); 301207618Srdivacky else 302212904Sdim fatal(f, "Forkpty", 1); 303207618Srdivacky } 304212904Sdim if (pid == 0) { 305207618Srdivacky if (f > 2) /* f should always be 0, but... */ 306207618Srdivacky (void) close(f); 307207618Srdivacky setup_term(0); 308207618Srdivacky if (*lusername=='-') { 309212904Sdim syslog(LOG_ERR, "tried to pass user \"%s\" to login", 310207618Srdivacky lusername); 311207618Srdivacky fatal(STDERR_FILENO, "invalid user", 0); 312207618Srdivacky } 313207618Srdivacky if (authenticated) { 314207618Srdivacky#ifdef KERBEROS 315207618Srdivacky if (use_kerberos && (pwd->pw_uid == 0)) 316207618Srdivacky syslog(LOG_INFO|LOG_AUTH, 317207618Srdivacky "ROOT Kerberos login from %s.%s@%s on %s\n", 318207618Srdivacky kdata->pname, kdata->pinst, kdata->prealm, 319207618Srdivacky hostname); 320207618Srdivacky#endif 321207618Srdivacky 322207618Srdivacky execl(_PATH_LOGIN, "login", "-p", 323207618Srdivacky "-h", hostname, "-f", lusername, (char *)NULL); 324212904Sdim } else 325207618Srdivacky execl(_PATH_LOGIN, "login", "-p", 326212904Sdim "-h", hostname, lusername, (char *)NULL); 327207618Srdivacky fatal(STDERR_FILENO, _PATH_LOGIN, 1); 328207618Srdivacky /*NOTREACHED*/ 329207618Srdivacky } 330207618Srdivacky#ifdef CRYPT 331207618Srdivacky#ifdef KERBEROS 332199481Srdivacky /* 333199481Srdivacky * If encrypted, don't turn on NBIO or the des read/write 334199481Srdivacky * routines will croak. 335207618Srdivacky */ 336207618Srdivacky 337207618Srdivacky if (!doencrypt) 338207618Srdivacky#endif 339207618Srdivacky#endif 340207618Srdivacky ioctl(f, FIONBIO, &on); 341212904Sdim ioctl(master, FIONBIO, &on); 342207618Srdivacky ioctl(master, TIOCPKT, &on); 343207618Srdivacky signal(SIGCHLD, cleanup); 344207618Srdivacky protocol(f, master); 345207618Srdivacky signal(SIGCHLD, SIG_IGN); 346207618Srdivacky cleanup(0); 347207618Srdivacky} 348199989Srdivacky 349193323Sedchar magic[2] = { 0377, 0377 }; 350199989Srdivackychar oobdata[] = {TIOCPKT_WINDOW}; 351193323Sed 352199989Srdivacky/* 353193323Sed * Handle a "control" request (signaled by magic being present) 354199989Srdivacky * in the data stream. For now, we are only willing to handle 355193323Sed * window size changes. 356193323Sed */ 357193323Sedint 358193323Sedcontrol(pty, cp, n) 359193323Sed int pty; 360207618Srdivacky char *cp; 361206274Srdivacky int n; 362193323Sed{ 363193323Sed struct winsize w; 364193323Sed 365201360Srdivacky if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') 366198090Srdivacky return (0); 367208599Srdivacky oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ 368199481Srdivacky bcopy(cp+4, (char *)&w, sizeof(w)); 369199481Srdivacky w.ws_row = ntohs(w.ws_row); 370199481Srdivacky w.ws_col = ntohs(w.ws_col); 371193323Sed w.ws_xpixel = ntohs(w.ws_xpixel); 372193323Sed w.ws_ypixel = ntohs(w.ws_ypixel); 373199481Srdivacky (void)ioctl(pty, TIOCSWINSZ, &w); 374199481Srdivacky return (4+sizeof (w)); 375193323Sed} 376193323Sed 377193323Sed/* 378193323Sed * rlogin "protocol" machine. 379193323Sed */ 380193323Sedvoid 381193323Sedprotocol(f, p) 382193323Sed register int f, p; 383193323Sed{ 384193323Sed char pibuf[1024+1], fibuf[1024], *pbp, *fbp; 385193323Sed int pcc = 0, fcc = 0; 386193323Sed int cc, nfd, n; 387193323Sed char cntl; 388206274Srdivacky 389208599Srdivacky /* 390212904Sdim * Must ignore SIGTTOU, otherwise we'll stop 391207618Srdivacky * when we try and set slave pty's window shape 392205218Srdivacky * (our controlling tty is the master pty). 393212904Sdim */ 394206274Srdivacky (void) signal(SIGTTOU, SIG_IGN); 395206274Srdivacky send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ 396212904Sdim if (f > p) 397208599Srdivacky nfd = f + 1; 398210299Sed else 399210299Sed nfd = p + 1; 400210299Sed if (nfd > FD_SETSIZE) { 401210299Sed syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); 402207618Srdivacky fatal(f, "internal error (select mask too small)", 0); 403193323Sed } 404193323Sed for (;;) { 405206083Srdivacky fd_set ibits, obits, ebits, *omask; 406206083Srdivacky 407193323Sed FD_ZERO(&ebits); 408193323Sed FD_ZERO(&ibits); 409205218Srdivacky FD_ZERO(&obits); 410205218Srdivacky omask = (fd_set *)NULL; 411205218Srdivacky if (fcc) { 412205218Srdivacky FD_SET(p, &obits); 413205218Srdivacky omask = &obits; 414206274Srdivacky } else 415205218Srdivacky FD_SET(f, &ibits); 416205218Srdivacky if (pcc >= 0) { 417205218Srdivacky if (pcc) { 418199989Srdivacky FD_SET(f, &obits); 419193323Sed omask = &obits; 420199989Srdivacky } else 421193323Sed FD_SET(p, &ibits); 422193323Sed } 423193323Sed FD_SET(p, &ebits); 424193323Sed if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { 425193323Sed if (errno == EINTR) 426193323Sed continue; 427193323Sed fatal(f, "select", 1); 428193323Sed } 429193323Sed if (n == 0) { 430193323Sed /* shouldn't happen... */ 431193323Sed sleep(5); 432193323Sed continue; 433193323Sed } 434193323Sed#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) 435193323Sed if (FD_ISSET(p, &ebits)) { 436193323Sed cc = read(p, &cntl, 1); 437193323Sed if (cc == 1 && pkcontrol(cntl)) { 438193323Sed cntl |= oobdata[0]; 439193323Sed send(f, &cntl, 1, MSG_OOB); 440193323Sed if (cntl & TIOCPKT_FLUSHWRITE) { 441199989Srdivacky pcc = 0; 442193323Sed FD_CLR(p, &ibits); 443199989Srdivacky } 444206083Srdivacky } 445193323Sed } 446193323Sed if (FD_ISSET(f, &ibits)) { 447193323Sed#ifdef CRYPT 448199989Srdivacky#ifdef KERBEROS 449193323Sed if (doencrypt) 450199989Srdivacky fcc = des_enc_read(f, fibuf, sizeof(fibuf), 451193323Sed schedule, &kdata->session); 452193323Sed else 453212904Sdim#endif 454210299Sed#endif 455199989Srdivacky fcc = read(f, fibuf, sizeof(fibuf)); 456193323Sed if (fcc < 0 && errno == EWOULDBLOCK) 457193323Sed fcc = 0; 458199989Srdivacky else { 459193323Sed register char *cp; 460199989Srdivacky int left, n; 461193323Sed 462193323Sed if (fcc <= 0) 463206083Srdivacky break; 464199989Srdivacky fbp = fibuf; 465193323Sed 466193323Sed top: 467200581Srdivacky for (cp = fibuf; cp < fibuf+fcc-1; cp++) 468212904Sdim if (cp[0] == magic[0] && 469199989Srdivacky cp[1] == magic[1]) { 470202878Srdivacky left = fcc - (cp-fibuf); 471206083Srdivacky n = control(p, cp, left); 472199989Srdivacky if (n) { 473193323Sed left -= n; 474193323Sed if (left > 0) 475199989Srdivacky bcopy(cp+n, cp, left); 476193323Sed fcc -= n; 477199989Srdivacky goto top; /* n^2 */ 478204961Srdivacky } 479206083Srdivacky } 480199989Srdivacky FD_SET(p, &obits); /* try write */ 481193323Sed } 482193323Sed } 483199989Srdivacky 484193323Sed if (FD_ISSET(p, &obits) && fcc > 0) { 485199989Srdivacky cc = write(p, fbp, fcc); 486204961Srdivacky if (cc > 0) { 487206083Srdivacky fcc -= cc; 488199989Srdivacky fbp += cc; 489193323Sed } 490193323Sed } 491206274Srdivacky 492206274Srdivacky if (FD_ISSET(p, &ibits)) { 493206274Srdivacky pcc = read(p, pibuf, sizeof (pibuf)); 494206274Srdivacky pbp = pibuf; 495206274Srdivacky if (pcc < 0 && errno == EWOULDBLOCK) 496206274Srdivacky pcc = 0; 497206274Srdivacky else if (pcc <= 0) 498206274Srdivacky break; 499199989Srdivacky else if (pibuf[0] == 0) { 500193323Sed pbp++, pcc--; 501199989Srdivacky#ifdef CRYPT 502193323Sed#ifdef KERBEROS 503206274Srdivacky if (!doencrypt) 504206083Srdivacky#endif 505199989Srdivacky#endif 506193323Sed FD_SET(f, &obits); /* try write */ 507193323Sed } else { 508199989Srdivacky if (pkcontrol(pibuf[0])) { 509193323Sed pibuf[0] |= oobdata[0]; 510212904Sdim send(f, &pibuf[0], 1, MSG_OOB); 511208599Srdivacky } 512212904Sdim pcc = 0; 513193323Sed } 514193323Sed } 515212904Sdim if ((FD_ISSET(f, &obits)) && pcc > 0) { 516218893Sdim#ifdef CRYPT 517218893Sdim#ifdef KERBEROS 518218893Sdim if (doencrypt) 519193323Sed cc = des_enc_write(f, pbp, pcc, 520199989Srdivacky schedule, &kdata->session); 521199989Srdivacky else 522193323Sed#endif 523193323Sed#endif 524199989Srdivacky cc = write(f, pbp, pcc); 525193323Sed if (cc < 0 && errno == EWOULDBLOCK) { 526212904Sdim /* 527208599Srdivacky * This happens when we try write after read 528212904Sdim * from p, but some old kernels balk at large 529193323Sed * writes even when select returns true. 530193323Sed */ 531212904Sdim if (!FD_ISSET(p, &ibits)) 532218893Sdim sleep(5); 533218893Sdim continue; 534218893Sdim } 535193323Sed if (cc > 0) { 536199989Srdivacky pcc -= cc; 537199989Srdivacky pbp += cc; 538193323Sed } 539198090Srdivacky } 540199989Srdivacky } 541198090Srdivacky} 542212904Sdim 543208599Srdivackyvoid 544212904Sdimcleanup(signo) 545198090Srdivacky int signo; 546198090Srdivacky{ 547212904Sdim char *p; 548198090Srdivacky 549198090Srdivacky p = line + sizeof(_PATH_DEV) - 1; 550212904Sdim if (logout(p)) 551212904Sdim logwtmp(p, "", ""); 552204961Srdivacky (void)chflags(line, 0); 553218893Sdim (void)chmod(line, 0666); 554198090Srdivacky (void)chown(line, 0, 0); 555199989Srdivacky *p = 'p'; 556199989Srdivacky (void)chflags(line, 0); 557198090Srdivacky (void)chmod(line, 0666); 558198090Srdivacky (void)chown(line, 0, 0); 559199989Srdivacky shutdown(netf, 2); 560198090Srdivacky exit(1); 561212904Sdim} 562208599Srdivacky 563212904Sdimvoid 564193323Sedfatal(f, msg, syserr) 565193323Sed int f; 566212904Sdim char *msg; 567218893Sdim int syserr; 568204961Srdivacky{ 569218893Sdim int len; 570193323Sed char buf[BUFSIZ], *bp = buf; 571199989Srdivacky 572199989Srdivacky /* 573193323Sed * Prepend binary one to message if we haven't sent 574193323Sed * the magic null as confirmation. 575201360Srdivacky */ 576201360Srdivacky if (!confirmed) 577212904Sdim *bp++ = '\01'; /* error indicator */ 578208599Srdivacky if (syserr) 579212904Sdim len = sprintf(bp, "rlogind: %s: %s.\r\n", 580201360Srdivacky msg, strerror(errno)); 581201360Srdivacky else 582212904Sdim len = sprintf(bp, "rlogind: %s.\r\n", msg); 583218893Sdim (void) write(f, buf, bp + len - buf); 584218893Sdim exit(1); 585212904Sdim} 586201360Srdivacky 587218893Sdimint 588201360Srdivackydo_rlogin(dest) 589201360Srdivacky struct sockaddr_in *dest; 590201360Srdivacky{ 591201360Srdivacky getstr(rusername, sizeof(rusername), "remuser too long"); 592201360Srdivacky getstr(lusername, sizeof(lusername), "locuser too long"); 593212904Sdim getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); 594212904Sdim 595212904Sdim pwd = getpwnam(lusername); 596212904Sdim if (pwd == NULL) 597212904Sdim return (-1); 598218893Sdim /* XXX why don't we syslog() failure? */ 599218893Sdim return (iruserok(dest->sin_addr.s_addr, pwd->pw_uid == 0, 600212904Sdim rusername, lusername)); 601198090Srdivacky} 602212904Sdim 603212904Sdimvoid 604212904Sdimgetstr(buf, cnt, errmsg) 605212904Sdim char *buf; 606212904Sdim int cnt; 607212904Sdim char *errmsg; 608198090Srdivacky{ 609198090Srdivacky char c; 610199989Srdivacky 611198090Srdivacky do { 612198090Srdivacky if (read(0, &c, 1) != 1) 613198090Srdivacky exit(1); 614198090Srdivacky if (--cnt < 0) 615199989Srdivacky fatal(STDOUT_FILENO, errmsg, 0); 616198090Srdivacky *buf++ = c; 617198090Srdivacky } while (c != 0); 618212904Sdim} 619198090Srdivacky 620198090Srdivackyextern char **environ; 621198090Srdivacky 622206274Srdivackyvoid 623198090Srdivackysetup_term(fd) 624206083Srdivacky int fd; 625198090Srdivacky{ 626198090Srdivacky register char *cp = index(term+ENVSIZE, '/'); 627198090Srdivacky char *speed; 628199989Srdivacky struct termios tt; 629198090Srdivacky 630218893Sdim#ifndef notyet 631199989Srdivacky tcgetattr(fd, &tt); 632198090Srdivacky if (cp) { 633198090Srdivacky *cp++ = '\0'; 634198090Srdivacky speed = cp; 635199989Srdivacky cp = index(speed, '/'); 636198090Srdivacky if (cp) 637199989Srdivacky *cp++ = '\0'; 638199989Srdivacky cfsetspeed(&tt, atoi(speed)); 639198090Srdivacky } 640198090Srdivacky 641199989Srdivacky tt.c_iflag = TTYDEF_IFLAG; 642198090Srdivacky tt.c_oflag = TTYDEF_OFLAG; 643198090Srdivacky tt.c_lflag = TTYDEF_LFLAG; 644212904Sdim tcsetattr(fd, TCSAFLUSH, &tt); 645212904Sdim#else 646198090Srdivacky if (cp) { 647198090Srdivacky *cp++ = '\0'; 648199989Srdivacky speed = cp; 649212904Sdim cp = index(speed, '/'); 650198090Srdivacky if (cp) 651199989Srdivacky *cp++ = '\0'; 652198090Srdivacky tcgetattr(fd, &tt); 653198090Srdivacky cfsetspeed(&tt, atoi(speed)); 654198090Srdivacky tcsetattr(fd, TCSAFLUSH, &tt); 655198090Srdivacky } 656199989Srdivacky#endif 657198090Srdivacky 658198090Srdivacky env[0] = term; 659198090Srdivacky env[1] = 0; 660198090Srdivacky environ = env; 661198090Srdivacky} 662198090Srdivacky 663198090Srdivacky#ifdef KERBEROS 664198090Srdivacky#define VERSION_SIZE 9 665198090Srdivacky 666198090Srdivacky/* 667198090Srdivacky * Do the remote kerberos login to the named host with the 668199989Srdivacky * given inet address 669198090Srdivacky * 670198090Srdivacky * Return 0 on valid authorization 671198090Srdivacky * Return -1 on valid authentication, no authorization 672198090Srdivacky * Return >0 for error conditions 673198090Srdivacky */ 674198090Srdivackyint 675198090Srdivackydo_krb_login(dest) 676198090Srdivacky struct sockaddr_in *dest; 677198090Srdivacky{ 678198090Srdivacky int rc; 679198090Srdivacky char instance[INST_SZ], version[VERSION_SIZE]; 680198090Srdivacky long authopts = 0L; /* !mutual */ 681198090Srdivacky struct sockaddr_in faddr; 682198090Srdivacky 683198090Srdivacky kdata = (AUTH_DAT *) auth_buf; 684198090Srdivacky ticket = (KTEXT) tick_buf; 685198090Srdivacky 686198090Srdivacky instance[0] = '*'; 687198090Srdivacky instance[1] = '\0'; 688198090Srdivacky 689198090Srdivacky#ifdef CRYPT 690198090Srdivacky if (doencrypt) { 691198090Srdivacky rc = sizeof(faddr); 692198090Srdivacky if (getsockname(0, (struct sockaddr *)&faddr, &rc)) 693198090Srdivacky return (-1); 694198090Srdivacky authopts = KOPT_DO_MUTUAL; 695198090Srdivacky rc = krb_recvauth( 696203954Srdivacky authopts, 0, 697198090Srdivacky ticket, "rcmd", 698198090Srdivacky instance, dest, &faddr, 699198090Srdivacky kdata, "", schedule, version); 700198090Srdivacky des_set_key(&kdata->session, schedule); 701198090Srdivacky 702198090Srdivacky } else 703198090Srdivacky#endif 704198090Srdivacky rc = krb_recvauth( 705198090Srdivacky authopts, 0, 706198090Srdivacky ticket, "rcmd", 707198090Srdivacky instance, dest, (struct sockaddr_in *) 0, 708198090Srdivacky kdata, "", NULL, version); 709198090Srdivacky 710198090Srdivacky if (rc != KSUCCESS) 711198090Srdivacky return (rc); 712198090Srdivacky 713199989Srdivacky getstr(lusername, sizeof(lusername), "locuser"); 714198090Srdivacky /* get the "cmd" in the rcmd protocol */ 715198090Srdivacky getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); 716198090Srdivacky 717198090Srdivacky pwd = getpwnam(lusername); 718198090Srdivacky if (pwd == NULL) 719199989Srdivacky return (-1); 720198090Srdivacky 721198090Srdivacky /* returns nonzero for no access */ 722212904Sdim if (kuserok(kdata, lusername) != 0) 723198090Srdivacky return (-1); 724198090Srdivacky 725198090Srdivacky return (0); 726198090Srdivacky 727212904Sdim} 728198090Srdivacky#endif /* KERBEROS */ 729198090Srdivacky 730208599Srdivackyvoid 731198090Srdivackyusage() 732198090Srdivacky{ 733198090Srdivacky#ifdef KERBEROS 734198090Srdivacky syslog(LOG_ERR, "usage: rlogind [-Daln] [-k | -v]"); 735208599Srdivacky#else 736198090Srdivacky syslog(LOG_ERR, "usage: rlogind [-Daln]"); 737198090Srdivacky#endif 738198090Srdivacky} 739198090Srdivacky