6 * Copyright (c) 1983 The Regents of the University of California.
9 * Redistribution and use in source and binary forms are permitted
10 * provided that the above copyright notice and this paragraph are
11 * duplicated in all such forms and that any documentation,
12 * advertising materials, and other materials related to such
13 * distribution and use acknowledge that the software was developed
14 * by the University of California, Berkeley. The name of the
15 * University may not be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * Copyright (C) 1998 by the FundsXpress, INC.
25 * All rights reserved.
27 * Export of this software from the United States of America may require
28 * a specific license from the United States Government. It is the
29 * responsibility of any person or organization contemplating export to
30 * obtain such a license before exporting.
32 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
33 * distribute this software and its documentation for any purpose and
34 * without fee is hereby granted, provided that the above copyright
35 * notice appear in all copies and that both that copyright notice and
36 * this permission notice appear in supporting documentation, and that
37 * the name of FundsXpress. not be used in advertising or publicity pertaining
38 * to distribution of the software without specific, written prior
39 * permission. FundsXpress makes no representations about the suitability of
40 * this software for any purpose. It is provided "as is" without express
41 * or implied warranty.
43 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
44 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
45 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
50 "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
51 All rights reserved.\n";
54 /* based on @(#)rlogind.c 5.17 (Berkeley) 8/31/88 */
57 * remote login server:
65 * This is the rlogin daemon. The very basic protocol for checking
66 * authentication and authorization is:
67 * 1) Check authentication.
68 * 2) Check authorization via the access-control files:
69 * ~/.k5login (using krb5_kuserok) and/or
70 * 3) Prompt for password if any checks fail, or if so configured.
71 * Allow login if all goes well either by calling the accompanying
72 * login.krb5 or /bin/login, according to the definition of
73 * DO_NOT_USE_K_LOGIN.l
75 * The configuration is done either by command-line arguments passed by
76 * inetd, or by the name of the daemon. If command-line arguments are
77 * present, they take priority. The options are:
78 * -k means trust krb4 or krb5
81 * -p and -P means prompt for password.
82 * If the -P option is passed, then the password is verified in
83 * addition to all other checks. If -p is not passed with -k or -r,
84 * and both checks fail, then login permission is denied.
85 * - -e means use encryption.
87 * If no command-line arguments are present, then the presence of the
88 * letters kKrRexpP in the program-name before "logind" determine the
89 * behaviour of the program exactly as with the command-line arguments.
91 * If the ruserok check is to be used, then the client should connect
92 * from a privileged port, else deny permission.
96 * KERBEROS - Define this if application is to be kerberised.
97 * CRYPT - Define this if encryption is to be an option.
98 * DO_NOT_USE_K_LOGIN - Define this if you want to use /bin/login
99 * instead of the accompanying login.krb5.
100 * KRB5_KRB4_COMPAT - Define this if v4 rlogin clients are also to be served.
101 * ALWAYS_V5_KUSEROK - Define this if you want .k5login to be
102 * checked even for v4 clients (instead of .klogin).
103 * LOG_ALL_LOGINS - Define this if you want to log all logins.
104 * LOG_OTHER_USERS - Define this if you want to log all principals
105 * that do not map onto the local user.
106 * LOG_REMOTE_REALM - Define this if you want to log all principals from
108 * Note: Root logins are always logged.
112 * This is usually done in the Makefile. Actually, these sources may
113 * not work without the KERBEROS #defined.
117 #define LOG_REMOTE_REALM
125 #include <sys/unistd.h>
132 #include <sys/types.h>
133 #include <sys/stat.h>
135 /* Ultrix doesn't protect it vs multiple inclusion, and krb.h includes it */
136 #include <sys/socket.h>
138 #include <sys/ioctl.h>
139 #include <sys/wait.h>
140 #include <sys/file.h>
141 #include <sys/time.h>
144 #include <netinet/in.h>
148 #ifdef HAVE_SYS_LABEL_H
150 #include <sys/label.h>
151 #include <sys/audit.h>
157 #if defined(hpux) || defined(__hpux)
158 #include <sys/ptyio.h>
164 #ifdef HAVE_SYS_SELECT_H
165 #include <sys/select.h>
169 #include <sys/stream.h>
170 #include <sys/stropts.h>
173 #if defined(POSIX_TERMIOS) && !defined(ultrix)
180 /* Ultrix doesn't protect it vs multiple inclusion, and krb.h includes it */
185 #include <sys/param.h>
188 /* krlogin doesn't test sys/tty... */
189 #ifdef HAVE_SYS_TTY_H
193 #ifdef HAVE_SYS_PTYVAR_H
194 /* Solaris actually uses packet mode, so the real macros are needed too */
195 #include <sys/ptyvar.h>
200 #ifndef TIOCPKT_NOSTOP
201 /* These values are over-the-wire protocol, *not* local values */
202 #define TIOCPKT_NOSTOP 0x10
203 #define TIOCPKT_DOSTOP 0x20
204 #define TIOCPKT_FLUSHWRITE 0x02
207 #ifdef HAVE_SYS_FILIO_H
208 /* get FIONBIO from sys/filio.h, so what if it is a compatibility feature */
209 #include <sys/filio.h>
213 #define killpg(pid, sig) kill(-(pid), (sig))
217 /* HP/UX 9.04 has but does not declare ptsname. */
218 extern char *ptsname ();
223 unsigned short ws_row, ws_col;
224 unsigned short ws_xpixel, ws_ypixel;
226 #endif /* NO_WINSIZE */
229 #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
235 #include <kerberosIV/krb.h>
241 int auth_sys = 0; /* Which version of Kerberos used to authenticate */
243 #define KRB5_RECVAUTH_V4 4
244 #define KRB5_RECVAUTH_V5 5
246 int non_privileged = 0; /* set when connection is seen to be from */
247 /* a non-privileged port */
250 Key_schedule v4_schedule;
255 #define SECURE_MESSAGE "This rlogin session is using DES encryption for all data transmissions.\r\n"
257 krb5_authenticator *kdata;
258 krb5_ticket *ticket = 0;
259 krb5_context bsd_context;
260 krb5_ccache ccache = NULL;
262 krb5_keytab keytab = NULL;
264 #define ARGSTR "k54ciepPD:S:M:L:fw:?"
265 #else /* !KERBEROS */
266 #define ARGSTR "rpPD:f?"
267 #endif /* KERBEROS */
269 #ifndef LOGIN_PROGRAM
270 #ifdef DO_NOT_USE_K_LOGIN
272 #define LOGIN_PROGRAM "/bin/remlogin"
274 #define LOGIN_PROGRAM "/bin/login"
276 #else /* DO_NOT_USE_K_LOGIN */
277 #define LOGIN_PROGRAM KRB5_PATH_LOGIN
278 #endif /* DO_NOT_USE_K_LOGIN */
279 #endif /* LOGIN_PROGRAM */
281 char *login_program = LOGIN_PROGRAM;
284 #define MAX_PROG_NAME 16
286 #ifndef UT_NAMESIZE /* linux defines it directly in <utmp.h> */
287 #define UT_NAMESIZE sizeof(((struct utmp *)0)->ut_name)
290 #if HAVE_ARPA_NAMESER_H
291 #include <arpa/nameser.h>
295 #define MAXDNAME 256 /*per the rfc*/
298 char lusername[UT_NAMESIZE+1];
299 char rusername[UT_NAMESIZE+1];
300 char *krusername = 0;
302 char rhost_name[MAXDNAME];
303 char rhost_addra[16];
304 krb5_principal client;
312 #if (defined(_AIX) && defined(i386)) || defined(ibm032) || (defined(vax) && !defined(ultrix)) || (defined(SunOS) && SunOS > 40) || defined(solaris20)
317 #define VHANG_LAST /* vhangup must occur on close, not open */
320 void fatal(), fatalperror(), doit(), usage(), do_krb_login(), getstr();
322 int princ_maps_to_lname(), default_realm();
323 krb5_sigtype cleanup();
324 krb5_error_code recvauth();
326 /* There are two authentication related masks:
327 * auth_ok and auth_sent.
328 * The auth_ok mask is the oring of authentication systems any one
329 * of which can be used.
330 * The auth_sent mask is the oring of one or more authentication/authorization
331 * systems that succeeded. If the anding
332 * of these two masks is true, then authorization is successful.
334 #define AUTH_KRB4 (0x1)
335 #define AUTH_KRB5 (0x2)
336 int auth_ok = 0, auth_sent = 0;
337 int do_encrypt = 0, passwd_if_fail = 0, passwd_req = 0;
338 int checksum_required = 0, checksum_ignored = 0;
348 extern int opterr, optind;
349 extern char * optarg;
350 int on = 1, fromlen, ch, i;
351 struct sockaddr_in from;
357 krb5_error_code status;
368 #ifndef LOG_AUTH /* 4.2 syslog */
369 openlog(progname, LOG_PID | LOG_NDELAY);
371 openlog(progname, LOG_PID | LOG_NDELAY, LOG_AUTH);
372 #endif /* 4.2 syslog */
375 status = krb5_init_context(&bsd_context);
377 syslog(LOG_ERR, "Error initializing krb5: %s",
378 error_message(status));
383 /* Analyse parameters. */
385 while ((ch = getopt(argc, argv, ARGSTR)) != -1)
389 #ifdef KRB5_KRB4_COMPAT
390 auth_ok |= (AUTH_KRB5|AUTH_KRB4);
392 auth_ok |= AUTH_KRB5;
393 #endif /* KRB5_KRB4_COMPAT*/
397 auth_ok |= AUTH_KRB5;
400 checksum_required = 1;
403 checksum_ignored = 1;
406 #ifdef KRB5_KRB4_COMPAT
408 auth_ok |= AUTH_KRB4;
412 case 'x': /* Use encryption. */
420 if ((status = krb5_kt_resolve(bsd_context, optarg, &keytab))) {
421 com_err(progname, status, "while resolving srvtab file %s",
427 krb5_set_default_realm(bsd_context, optarg);
431 passwd_if_fail = 1; /* Passwd reqd if any check fails */
433 case 'P': /* passwd is a must */
437 debug_port = atoi(optarg);
440 login_program = optarg;
446 if (!strcmp(optarg, "ip"))
450 cp = strchr(optarg, ',');
452 maxhostlen = atoi(optarg);
454 if (!strcmp(cp, "striplocal"))
456 else if (!strcmp(cp, "nostriplocal"))
463 maxhostlen = atoi(optarg);
476 fromlen = sizeof (from);
478 if (debug_port || do_fork) {
481 struct sockaddr_in sin;
485 ent = getservbyname("eklogin", "tcp");
489 debug_port = ent->s_port;
491 ent = getservbyname("klogin", "tcp");
495 debug_port = ent->s_port;
498 if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) {
499 fprintf(stderr, "Error in socket: %s\n", strerror(errno));
502 memset((char *) &sin, 0,sizeof(sin));
503 sin.sin_family = AF_INET;
504 sin.sin_port = htons(debug_port);
505 sin.sin_addr.s_addr = INADDR_ANY;
508 (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
509 (char *)&on, sizeof(on));
511 if ((bind(s, (struct sockaddr *) &sin, sizeof(sin))) < 0) {
512 fprintf(stderr, "Error in bind: %s\n", strerror(errno));
516 if ((listen(s, 5)) < 0) {
517 fprintf(stderr, "Error in listen: %s\n", strerror(errno));
523 fprintf(stderr, "daemon() failed\n");
529 fd = accept(s, (struct sockaddr *) &from, &fromlen);
532 syslog(LOG_ERR, "accept: %s", error_message(errno));
538 syslog(LOG_ERR, "fork: %s", error_message(errno));
551 if ((fd = accept(s, (struct sockaddr *) &from, &fromlen)) < 0) {
552 fprintf(stderr, "Error in accept: %s\n", strerror(errno));
557 } else { /* !do_fork && !debug_port */
558 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
559 syslog(LOG_ERR,"Can't get peer name of remote host: %m");
561 fatal(STDERR_FILENO, "Can't get peer name of remote host", 1);
563 fatal(2, "Can't get peer name of remote host", 1);
581 char line[MAXPATHLEN];
582 extern char *inet_ntoa();
585 struct winsize win = { 0, 0, 0, 0 };
588 int pid; /* child process id */
592 struct sockaddr_in *fromp;
595 register struct hostent *hp;
607 if (setsockopt(f, SOL_SOCKET, SO_KEEPALIVE,
608 (const char *) &on, sizeof (on)) < 0)
609 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
611 syslog(LOG_CRIT, "No authentication systems were enabled; all connections will be refused.");
612 fatal(f, "All authentication systems disabled; connection refused.");
615 if (checksum_required&&checksum_ignored) {
616 syslog( LOG_CRIT, "Checksums are required and ignored; these options are mutually exclusive--check the documentation.");
617 fatal(f, "Configuration error: mutually exclusive options specified");
628 /* Initialize syncpipe */
629 if (pipe( syncpipe ) < 0 )
630 fatalperror ( f , "");
634 /* Initialize "sa" structure. */
635 (void) sigemptyset(&sa.sa_mask);
639 fromp->sin_port = ntohs((u_short)fromp->sin_port);
640 hp = gethostbyaddr((char *) &fromp->sin_addr, sizeof (struct in_addr),
642 strncpy(rhost_addra, inet_ntoa(fromp->sin_addr), sizeof (rhost_addra));
643 rhost_addra[sizeof (rhost_addra) -1] = '\0';
645 /* Save hostent information.... */
646 strncpy(rhost_name,hp->h_name,sizeof (rhost_name));
647 rhost_name[sizeof (rhost_name) - 1] = '\0';
649 rhost_name[0] = '\0';
651 if (fromp->sin_family != AF_INET)
652 fatal(f, "Permission denied - Malformed from address\n");
655 if (fromp->sin_port >= IPPORT_RESERVED ||
656 fromp->sin_port < IPPORT_RESERVED/2)
657 fatal(f, "Permission denied - Connection from bad port");
658 #endif /* KERBEROS */
660 /* Set global netf to f now : we may need to drop everything
664 #if defined(KERBEROS)
665 /* All validation, and authorization goes through do_krb_login() */
666 do_krb_login(rhost_addra, rhost_name);
668 getstr(f, rusername, sizeof(rusername), "remuser");
669 getstr(f, lusername, sizeof(lusername), "locuser");
670 getstr(f, term, sizeof(term), "Terminal type");
671 rcmd_stream_init_normal();
675 if ((retval = pty_getpty(&p,line, sizeof(line)))) {
676 com_err(progname, retval, "while getting master pty");
682 (void) ioctl(p, TIOCSWINSZ, &win);
686 sa.sa_handler = cleanup;
687 (void) sigaction(SIGCHLD, &sa, (struct sigaction *)0);
688 (void) sigaction(SIGTERM, &sa, (struct sigaction *)0);
690 signal(SIGCHLD, cleanup);
691 signal(SIGTERM, cleanup);
697 #if defined(POSIX_TERMIOS) && !defined(ultrix)
698 struct termios new_termio;
701 #endif /* POSIX_TERMIOS */
702 if ((retval = pty_open_slave(line, &t))) {
703 fatal(f, error_message(retval));
708 #if defined(POSIX_TERMIOS) && !defined(ultrix)
709 tcgetattr(t,&new_termio);
710 #if !defined(USE_LOGIN_F)
711 new_termio.c_lflag &= ~(ICANON|ECHO|ISIG|IEXTEN);
712 new_termio.c_iflag &= ~(IXON|IXANY|BRKINT|INLCR|ICRNL);
714 new_termio.c_lflag |= (ICANON|ECHO|ISIG|IEXTEN);
715 new_termio.c_oflag |= (ONLCR|OPOST);
716 new_termio.c_iflag |= (IXON|IXANY|BRKINT|INLCR|ICRNL);
717 #endif /*Do we need binary stream?*/
718 new_termio.c_iflag &= ~(ISTRIP);
719 /* new_termio.c_iflag = 0; */
720 /* new_termio.c_oflag = 0; */
721 new_termio.c_cc[VMIN] = 1;
722 new_termio.c_cc[VTIME] = 0;
723 tcsetattr(t,TCSANOW,&new_termio);
725 (void)ioctl(t, TIOCGETP, &b);
726 b.sg_flags = RAW|ANYP;
727 (void)ioctl(t, TIOCSETP, &b);
728 #endif /* POSIX_TERMIOS */
730 pid = 0; /*reset pid incase exec fails*/
733 ** signal the parent that we have turned off echo
734 ** on the slave side of the pty ... he's waiting
735 ** because otherwise the rlogin protocol junk gets
736 ** echo'd to the user (locuser^@remuser^@term/baud)
737 ** and we don't get the right tty affiliation, and
738 ** other kinds of hell breaks loose ...
740 (void) write(syncpipe[1], &c, 1);
741 (void) close(syncpipe[1]);
742 (void) close(syncpipe[0]);
745 dup2(t, 0), dup2(t, 1), dup2(t, 2);
750 setcompat (COMPAT_CLRPGROUP | (getcompat() & ~COMPAT_BSDTTY));
753 /* Log access to account */
754 pwd = (struct passwd *) getpwnam(lusername);
755 if (pwd && (pwd->pw_uid == 0)) {
757 syslog(LOG_NOTICE, "ROOT login by %s (%s@%s (%s)) forcing password access",
758 krusername ? krusername : "",
759 rusername, rhost_addra, rhost_name);
761 syslog(LOG_NOTICE, "ROOT login by %s (%s@%s (%s))",
762 krusername ? krusername : "",
763 rusername, rhost_addra, rhost_name);
766 #if defined(LOG_REMOTE_REALM) && !defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS)
767 /* Log if principal is from a remote realm */
768 else if (client && !default_realm(client))
769 #endif /* LOG_REMOTE_REALM */
771 #if defined(LOG_OTHER_USERS) && !defined(LOG_ALL_LOGINS)
772 /* Log if principal name does not map to local username */
773 else if (client && !princ_maps_to_lname(client, lusername))
774 #endif /* LOG_OTHER_USERS */
776 #if defined(LOG_ALL_LOGINS)
778 #endif /* LOG_ALL_LOGINS */
780 #if defined(LOG_REMOTE_REALM) || defined(LOG_OTHER_USERS) || defined(LOG_ALL_LOGINS)
784 "login by %s (%s@%s (%s)) as %s forcing password access",
785 krusername ? krusername : "", rusername,
786 rhost_addra, rhost_name, lusername);
789 "login by %s (%s@%s (%s)) as %s",
790 krusername ? krusername : "", rusername,
791 rhost_addra, rhost_name, lusername);
793 #endif /* LOG_REMOTE_REALM || LOG_OTHER_USERS || LOG_ALL_LOGINS */
794 #endif /* KERBEROS */
799 pty_update_utmp(PTY_LOGIN_PROCESS, getpid(), "rlogin", line,
800 ""/*host*/, PTY_TTYSLOT_USABLE);
805 /* use the vendors login, which has -p and -f. Tested on
806 * AIX 4.1.4 and HPUX 10
810 if ((cp = strchr(term,'/')))
812 setenv("TERM",term, 1);
815 retval = pty_make_sane_hostname(fromp, maxhostlen,
816 stripdomain, always_ip,
819 fatalperror(f, "failed make_sane_hostname");
821 execl(login_program, "login", "-p", "-h", rhost_sane,
824 execl(login_program, "login", "-p", "-h", rhost_sane,
826 #else /* USE_LOGIN_F */
827 execl(login_program, "login", "-r", rhost_sane, 0);
828 #endif /* USE_LOGIN_F */
829 syslog(LOG_ERR, "failed exec of %s: %s",
830 login_program, error_message(errno));
831 fatalperror(f, login_program);
833 } /* if (pid == 0) */
836 ** wait for child to start ... read one byte
837 ** -- see the child, who writes one byte after
838 ** turning off echo on the slave side ...
839 ** The master blocks here until it reads a byte.
842 (void) close(syncpipe[1]);
843 if (read(syncpipe[0], &c, 1) != 1) {
845 * Problems read failed ...
847 sprintf(buferror, "Cannot read slave pty %s ",line);
848 fatalperror(p,buferror);
853 #if defined(KERBEROS)
855 if (rcmd_stream_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE), 0) < 0){
856 sprintf(buferror, "Cannot encrypt-write network.");
862 * if encrypting, don't turn on NBIO, else the read/write routines
863 * will fail to work properly
865 #endif /* KERBEROS */
866 ioctl(f, FIONBIO, &on);
867 ioctl(p, FIONBIO, &on);
869 /* FIONBIO doesn't always work on ptys, use fcntl to set O_NDELAY? */
870 (void) fcntl(p,F_SETFL,fcntl(p,F_GETFL,0) | O_NDELAY);
873 sa.sa_handler = SIG_IGN;
874 (void) sigaction(SIGTSTP, &sa, (struct sigaction *)0);
876 signal(SIGTSTP, SIG_IGN);
880 #if !defined(USE_LOGIN_F)
881 /* Pass down rusername and lusername to login. */
882 (void) write(p, rusername, strlen(rusername) +1);
883 (void) write(p, lusername, strlen(lusername) +1);
884 /* stuff term info down to login */
885 if ((write(p, term, strlen(term)+1) != (int) strlen(term)+1)) {
887 * Problems write failed ...
889 sprintf(buferror,"Cannot write slave pty %s ",line);
890 fatalperror(f,buferror);
895 signal(SIGCHLD, SIG_IGN);
899 unsigned char magic[2] = { 0377, 0377 };
901 #ifndef TIOCPKT_WINDOW
902 #define TIOCPKT_WINDOW 0x80
904 unsigned char oobdata[] = {TIOCPKT_WINDOW};
906 char oobdata[] = {0};
909 int sendoob(fd, byte)
923 cc = rcmd_stream_write(fd, message, sizeof(message), 0);
924 while (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
925 /* also shouldn't happen */
927 cc = rcmd_stream_write(fd, message, sizeof(message), 0);
930 send(fd, byte, 1, MSG_OOB);
935 * Handle a "control" request (signaled by magic being present)
936 * in the data stream. For now, we are only willing to handle
937 * window size changes.
939 int control(pty, cp, n)
947 if (n < (int) 4+sizeof (w) || cp[2] != 's' || cp[3] != 's')
950 oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */
951 memcpy((char *)&w,cp+4, sizeof(w));
952 w.ws_row = ntohs(w.ws_row);
953 w.ws_col = ntohs(w.ws_col);
954 w.ws_xpixel = ntohs(w.ws_xpixel);
955 w.ws_ypixel = ntohs(w.ws_ypixel);
956 (void)ioctl(pty, TIOCSWINSZ, &w);
957 #ifdef HAVE_TCGETPGRP
958 pgrp = tcgetpgrp (pty);
959 got_pgrp = pgrp != -1;
961 got_pgrp = ioctl(pty, TIOCGPGRP, &pgrp) >= 0;
964 (void) killpg(pgrp, SIGWINCH);
966 return (4+sizeof (w));
972 * rlogin "protocol" machine.
977 unsigned char pibuf[BUFSIZ], qpibuf[BUFSIZ*2], fibuf[BUFSIZ], *pbp, *fbp;
978 register pcc = 0, fcc = 0;
985 register tiocpkt_on = 0;
989 #if defined(TIOCPKT) && !defined(__svr4__) || defined(solaris20)
990 /* if system has TIOCPKT, try to turn it on. Some drivers
991 * may not support it. Save flag for later.
993 if ( ioctl(p, TIOCPKT, &on) < 0)
999 * Must ignore SIGTTOU, otherwise we'll stop
1000 * when we try and set slave pty's window shape
1001 * (our controlling tty is the master pty).
1003 #ifdef POSIX_SIGNALS
1004 (void) sigemptyset(&sa.sa_mask);
1006 sa.sa_handler = SIG_IGN;
1007 (void) sigaction(SIGTTOU, &sa, (struct sigaction *)0);
1009 signal(SIGTTOU, SIG_IGN);
1012 sendoob(f, oobdata);
1015 fd_set ibits, obits, ebits;
1031 if (select(8*sizeof(ibits), &ibits, &obits, &ebits, 0) < 0) {
1034 fatalperror(f, "select");
1036 #define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
1037 if (FD_ISSET(f, &ibits)) {
1038 fcc = rcmd_stream_read(f, fibuf, sizeof (fibuf), 0);
1039 if (fcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
1042 register unsigned char *cp;
1049 for (cp = fibuf; cp < fibuf+fcc-1; cp++) {
1050 if (cp[0] == magic[0] &&
1051 cp[1] == magic[1]) {
1052 left = (fibuf+fcc) - cp;
1053 n = control(p, cp, left);
1058 memmove(cp, cp+n, left);
1066 if (FD_ISSET(p, &obits) && fcc > 0) {
1067 cc = write(p, fbp, fcc);
1074 if (FD_ISSET(p, &ibits)) {
1075 pcc = read(p, pibuf, sizeof (pibuf));
1077 if (pcc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
1079 } else if (pcc <= 0) {
1083 else if (tiocpkt_on) {
1084 if (pibuf[0] == 0) {
1087 if (pkcontrol(pibuf[0])) {
1088 pibuf[0] |= oobdata[0];
1096 /* quote any double-\377's if necessary */
1099 unsigned char *qpbp;
1106 if (pbp[i] == 0377u && (i+1)<pcc && pbp[i+1] == 0377u) {
1107 qpbp[qpcc] = '\377';
1108 qpbp[qpcc+1] = '\377';
1114 qpbp[qpcc] = pbp[i];
1125 if (FD_ISSET(f, &obits) && pcc > 0) {
1126 cc = rcmd_stream_write(f, pbp, pcc, 0);
1127 if (cc < 0 && ((errno == EWOULDBLOCK) || (errno == EAGAIN))) {
1128 /* also shouldn't happen */
1142 krb5_sigtype cleanup()
1144 pty_cleanup (line, pid, 1);
1147 krb5_cc_destroy(bsd_context, ccache);
1157 int out = 1 ; /* Output queue of f */
1158 #ifdef POSIX_SIGNALS
1159 struct sigaction sa;
1162 buf[0] = '\01'; /* error indicator */
1163 (void) sprintf(buf + 1, "%s: %s.\r\n",progname, msg);
1164 if ((f == netf) && (pid > 0))
1165 (void) rcmd_stream_write(f, buf, strlen(buf), 0);
1167 (void) write(f, buf, strlen(buf));
1168 syslog(LOG_ERR,"%s\n",msg);
1170 #ifdef POSIX_SIGNALS
1171 (void) sigemptyset(&sa.sa_mask);
1173 sa.sa_handler = SIG_IGN;
1174 (void) sigaction(SIGCHLD, &sa, (struct sigaction *)0);
1176 signal(SIGCHLD,SIG_IGN);
1180 (void) ioctl(f, TIOCFLUSH, (char *)&out);
1182 (void) ioctl(f, TCFLSH, out);
1191 void fatalperror(f, msg)
1197 (void) sprintf(buf, "%s: %s", msg, error_message(errno));
1204 do_krb_login(host_addr, hostname)
1205 char *host_addr, *hostname;
1207 krb5_error_code status;
1209 char *msg_fail = NULL;
1216 /* Check authentication. This can be either Kerberos V5, */
1217 /* Kerberos V4, or host-based. */
1218 if ((status = recvauth(&valid_checksum))) {
1220 krb5_free_ticket(bsd_context, ticket);
1223 "Authentication failed from %s (%s): %s\n",host_addr,
1224 hostname,error_message(status));
1225 fatal(netf, "Kerberos authentication failed");
1229 /* OK we have authenticated this user - now check authorization. */
1230 /* The Kerberos authenticated programs must use krb5_kuserok or kuserok*/
1232 #ifndef KRB5_KRB4_COMPAT
1233 if (auth_sys == KRB5_RECVAUTH_V4) {
1234 fatal(netf, "This server does not support Kerberos V4");
1239 #if (defined(ALWAYS_V5_KUSEROK) || !defined(KRB5_KRB4_COMPAT))
1240 /* krb5_kuserok returns 1 if OK */
1241 if (client && krb5_kuserok(bsd_context, client, lusername))
1242 auth_sent |= ((auth_sys == KRB5_RECVAUTH_V4)?AUTH_KRB4:AUTH_KRB5);
1244 if (auth_sys == KRB5_RECVAUTH_V4) {
1245 /* kuserok returns 0 if OK */
1246 if (!kuserok(v4_kdata, lusername))
1247 auth_sent |= AUTH_KRB4;
1249 /* krb5_kuserok returns 1 if OK */
1250 if (client && krb5_kuserok(bsd_context, client, lusername))
1251 auth_sent |= AUTH_KRB5;
1257 if (checksum_required && !valid_checksum) {
1258 if (auth_sent & AUTH_KRB5) {
1259 syslog(LOG_WARNING, "Client did not supply required checksum--connection rejected.");
1261 fatal(netf, "You are using an old Kerberos5 without initial connection support; only newer clients are authorized.");
1264 "Configuration error: Requiring checksums with -c is inconsistent with allowing Kerberos V4 connections.");
1267 if (auth_ok&auth_sent) /* This should be bitwise.*/
1271 krb5_free_ticket(bsd_context, ticket);
1274 msg_fail = (char *)malloc(strlen(krusername) + strlen(lusername) + 80);
1276 fatal(netf, "User is not authorized to login to specified account");
1279 sprintf(msg_fail, "Access denied because of improper credentials");
1281 sprintf(msg_fail, "User %s is not authorized to login to account %s",
1282 krusername, lusername);
1284 fatal(netf, msg_fail);
1288 #endif /* KERBEROS */
1292 void getstr(fd, buf, cnt, err)
1302 if (read(fd, &c, 1) != 1) {
1306 printf("%s too long\r\n", err);
1319 "usage: klogind [-ke45pPf] [-D port] [-w[ip|maxhostlen[,[no]striplocal]]] or [r/R][k/K][x/e][p/P]logind");
1322 "usage: rlogind [-rpPf] [-D port] or [r/R][p/P]logind");
1329 int princ_maps_to_lname(principal, luser)
1330 krb5_principal principal;
1334 if (!(krb5_aname_to_localname(bsd_context, principal,
1335 sizeof(kuser), kuser))
1336 && (strcmp(kuser, luser) == 0)) {
1342 int default_realm(principal)
1343 krb5_principal principal;
1349 realm_length = krb5_princ_realm(bsd_context, principal)->length;
1351 if ((retval = krb5_get_default_realm(bsd_context, &def_realm))) {
1355 if ((realm_length != strlen(def_realm)) ||
1356 (memcmp(def_realm, krb5_princ_realm(bsd_context, principal)->data, realm_length))) {
1365 #ifndef KRB_SENDAUTH_VLEN
1366 #define KRB_SENDAUTH_VLEN 8 /* length for version strings */
1369 #define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN
1373 recvauth(valid_checksum)
1374 int *valid_checksum;
1376 krb5_auth_context auth_context = NULL;
1377 krb5_error_code status;
1378 struct sockaddr_in peersin, laddr;
1381 char v4_instance[INST_SZ]; /* V4 Instance */
1383 krb5_authenticator *authenticator;
1385 enum kcmd_proto kcmd_proto;
1388 *valid_checksum = 0;
1389 len = sizeof(laddr);
1390 if (getsockname(netf, (struct sockaddr *)&laddr, &len)) {
1394 len = sizeof(peersin);
1395 if (getpeername(netf, (struct sockaddr *)&peersin, &len)) {
1396 syslog(LOG_ERR, "get peer name failed %d", netf);
1400 strcpy(v4_instance, "*");
1402 if ((status = krb5_auth_con_init(bsd_context, &auth_context)))
1405 /* Only need remote address for rd_cred() to verify client */
1406 if ((status = krb5_auth_con_genaddrs(bsd_context, auth_context, netf,
1407 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)))
1410 status = krb5_auth_con_getrcache(bsd_context, auth_context, &rcache);
1411 if (status) return status;
1414 krb5_principal server;
1416 status = krb5_sname_to_principal(bsd_context, 0, 0,
1417 KRB5_NT_SRV_HST, &server);
1418 if (status) return status;
1420 status = krb5_get_server_rcache(bsd_context,
1421 krb5_princ_component(bsd_context, server, 0),
1423 krb5_free_principal(bsd_context, server);
1424 if (status) return status;
1426 status = krb5_auth_con_setrcache(bsd_context, auth_context, rcache);
1427 if (status) return status;
1430 if ((status = krb5_compat_recvauth_version(bsd_context, &auth_context,
1432 NULL, /* Specify daemon principal */
1434 keytab, /* normally NULL to use v5srvtab */
1436 do_encrypt ? KOPT_DO_MUTUAL : 0, /*v4_opts*/
1437 "rcmd", /* v4_service */
1438 v4_instance, /* v4_instance */
1439 &peersin, /* foriegn address */
1440 &laddr, /* our local address */
1441 "", /* use default srvtab */
1443 &ticket, /* return ticket */
1444 &auth_sys, /* which authentication system*/
1445 &v4_kdata, v4_schedule,
1447 if (auth_sys == KRB5_RECVAUTH_V5) {
1449 * clean up before exiting
1451 getstr(netf, lusername, sizeof (lusername), "locuser");
1452 getstr(netf, term, sizeof(term), "Terminal type");
1453 getstr(netf, rusername, sizeof(rusername), "remuser");
1458 getstr(netf, lusername, sizeof (lusername), "locuser");
1459 getstr(netf, term, sizeof(term), "Terminal type");
1461 kcmd_proto = KCMD_UNKNOWN_PROTOCOL;
1462 if (auth_sys == KRB5_RECVAUTH_V5) {
1463 if (version.length != 9) {
1464 fatal (netf, "bad application version length");
1466 if (!memcmp (version.data, "KCMDV0.1", 9))
1467 kcmd_proto = KCMD_OLD_PROTOCOL;
1468 else if (!memcmp (version.data, "KCMDV0.2", 9))
1469 kcmd_proto = KCMD_NEW_PROTOCOL;
1471 #ifdef KRB5_KRB4_COMPAT
1472 if (auth_sys == KRB5_RECVAUTH_V4)
1473 kcmd_proto = KCMD_V4_PROTOCOL;
1476 if ((auth_sys == KRB5_RECVAUTH_V5)
1477 && !(checksum_ignored
1478 && kcmd_proto == KCMD_OLD_PROTOCOL)) {
1480 if ((status = krb5_auth_con_getauthenticator(bsd_context, auth_context,
1484 if (authenticator->checksum) {
1485 struct sockaddr_in adr;
1486 int adr_length = sizeof(adr);
1487 char * chksumbuf = (char *) malloc(strlen(term)+strlen(lusername)+32);
1488 if (getsockname(netf, (struct sockaddr *) &adr, &adr_length) != 0)
1493 sprintf(chksumbuf,"%u:", ntohs(adr.sin_port));
1494 strcat(chksumbuf,term);
1495 strcat(chksumbuf,lusername);
1497 status = krb5_verify_checksum(bsd_context,
1498 authenticator->checksum->checksum_type,
1499 authenticator->checksum,
1500 chksumbuf, strlen(chksumbuf),
1501 ticket->enc_part2->session->contents,
1502 ticket->enc_part2->session->length);
1507 krb5_free_authenticator(bsd_context, authenticator);
1510 *valid_checksum = 1;
1512 krb5_free_authenticator(bsd_context, authenticator);
1516 #ifdef KRB5_KRB4_COMPAT
1517 if (auth_sys == KRB5_RECVAUTH_V4) {
1519 rcmd_stream_init_krb4(v4_kdata->session, do_encrypt, 1, 1);
1521 /* We do not really know the remote user's login name.
1522 * Assume it to be the same as the first component of the
1525 strncpy(rusername, v4_kdata->pname, sizeof(rusername) - 1);
1526 rusername[sizeof(rusername) - 1] = '\0';
1528 status = krb5_425_conv_principal(bsd_context, v4_kdata->pname,
1529 v4_kdata->pinst, v4_kdata->prealm,
1531 if (status) return status;
1533 status = krb5_unparse_name(bsd_context, client, &krusername);
1541 if ((status = krb5_copy_principal(bsd_context, ticket->enc_part2->client,
1546 status = krb5_auth_con_getremotesubkey (bsd_context, auth_context, &key);
1548 fatal (netf, "Server can't get session subkey");
1549 if (!key && do_encrypt && kcmd_proto == KCMD_NEW_PROTOCOL)
1550 fatal (netf, "No session subkey sent");
1551 if (key && kcmd_proto == KCMD_OLD_PROTOCOL)
1552 fatal (netf, "Session subkey not permitted under old kcmd protocol");
1554 key = ticket->enc_part2->session;
1556 rcmd_stream_init_krb5 (key, do_encrypt, 1, 0, kcmd_proto);
1558 do_inband = (kcmd_proto == KCMD_NEW_PROTOCOL);
1560 getstr(netf, rusername, sizeof(rusername), "remuser");
1562 if ((status = krb5_unparse_name(bsd_context, client, &krusername)))
1565 if ((status = krb5_read_message(bsd_context, (krb5_pointer)&netf, &inbuf)))
1566 fatal(netf, "Error reading message");
1568 if ((inbuf.length) && /* Forwarding being done, read creds */
1569 (status = rd_and_store_for_creds(bsd_context, auth_context, &inbuf,
1570 ticket, &ccache))) {
1571 fatal(netf, "Can't get forwarded credentials");
1576 #endif /* KERBEROS */