summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTom Yu <tlyu@mit.edu>2004-11-15 21:25:41 +0000
committerTom Yu <tlyu@mit.edu>2004-11-15 21:25:41 +0000
commit7e47f7162cb6fe83e269e9ddc3602b2869a46c90 (patch)
tree476e3a142b1a48c5fcdb9457c7a491d6f91a7972 /src
parentafdca1d03a20d907d6e00bc31a69423a0c969ad9 (diff)
downloadkrb5-7e47f7162cb6fe83e269e9ddc3602b2869a46c90.tar.gz
krb5-7e47f7162cb6fe83e269e9ddc3602b2869a46c90.tar.xz
krb5-7e47f7162cb6fe83e269e9ddc3602b2869a46c90.zip
Merge Athena changes for requiring encrypted connections
ticket: 841 tags: pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16866 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/appl/telnet/libtelnet/ChangeLog5
-rw-r--r--src/appl/telnet/libtelnet/auth-proto.h3
-rw-r--r--src/appl/telnet/libtelnet/auth.c33
-rw-r--r--src/appl/telnet/telnetd/ChangeLog12
-rw-r--r--src/appl/telnet/telnetd/ext.h4
-rw-r--r--src/appl/telnet/telnetd/telnetd.813
-rw-r--r--src/appl/telnet/telnetd/telnetd.c48
-rw-r--r--src/appl/telnet/telnetd/utility.c61
-rw-r--r--src/tests/dejagnu/krb-root/ChangeLog7
-rw-r--r--src/tests/dejagnu/krb-root/telnet.exp53
10 files changed, 203 insertions, 36 deletions
diff --git a/src/appl/telnet/libtelnet/ChangeLog b/src/appl/telnet/libtelnet/ChangeLog
index 9e5c888d7..3467422dd 100644
--- a/src/appl/telnet/libtelnet/ChangeLog
+++ b/src/appl/telnet/libtelnet/ChangeLog
@@ -1,3 +1,8 @@
+2004-11-15 Tom Yu <tlyu@mit.edu>
+
+ * auth-proto.h, auth.c: Merge Athena changes for requiring
+ encrypted connections.
+
2004-06-04 Ken Raeburn <raeburn@mit.edu>
* Makefile.in (LIBBASE): Renamed from LIB.
diff --git a/src/appl/telnet/libtelnet/auth-proto.h b/src/appl/telnet/libtelnet/auth-proto.h
index 68cae7efc..6b4957032 100644
--- a/src/appl/telnet/libtelnet/auth-proto.h
+++ b/src/appl/telnet/libtelnet/auth-proto.h
@@ -67,7 +67,8 @@ void auth_send_retry (void);
void auth_is (unsigned char *, int);
void auth_reply (unsigned char *, int);
void auth_finished (Authenticator *, int);
-int auth_wait (char *);
+void auth_wait (char *);
+int auth_check (char *);
int auth_must_encrypt (void);
void auth_disable_name (char *);
void auth_gen_printsub (unsigned char *, int, unsigned char *, unsigned int);
diff --git a/src/appl/telnet/libtelnet/auth.c b/src/appl/telnet/libtelnet/auth.c
index 9c1b0b0fc..28b8ae8d1 100644
--- a/src/appl/telnet/libtelnet/auth.c
+++ b/src/appl/telnet/libtelnet/auth.c
@@ -85,6 +85,7 @@
int auth_debug_mode = 0;
int auth_has_failed = 0;
int auth_enable_encrypt = 0;
+int auth_client_non_unix = 0;
static char *Name = "Noname";
static int Server = 0;
static Authenticator *authenticated = 0;
@@ -337,15 +338,28 @@ auth_request()
authenticating = 1;
while (ap->type) {
if (i_support & ~i_wont_support & typemask(ap->type)) {
- if (auth_debug_mode) {
- printf(">>>%s: Sending type %d %d\r\n",
- Name, ap->type, ap->way);
+ if (ap->type == AUTHTYPE_KERBEROS_V4 ||
+ !auth_client_non_unix) {
+ if (auth_debug_mode) {
+ printf(">>>%s: Sending type %d %d\r\n",
+ Name, ap->type, ap->way);
+ }
+ *e++ = ap->type;
+ *e++ = ap->way;
}
- *e++ = ap->type;
- *e++ = ap->way;
}
++ap;
}
+ if (auth_client_non_unix) {
+ ap = authenticators;
+ while (ap->type) {
+ if (i_support & ~i_wont_support & typemask(ap->type)) {
+ *e++ = ap->type;
+ *e++ = ap->way;
+ }
+ ++ap;
+ }
+ }
*e++ = IAC;
*e++ = SE;
net_write(str_request, e - str_request);
@@ -562,7 +576,7 @@ auth_intr(sig)
auth_finished(0, AUTH_REJECT);
}
- int
+ void
auth_wait(name)
char *name;
{
@@ -570,7 +584,7 @@ auth_wait(name)
printf(">>>%s: in auth_wait.\r\n", Name);
if (Server && !authenticating)
- return(0);
+ return;
(void) signal(SIGALRM, auth_intr);
alarm(30);
@@ -579,7 +593,12 @@ auth_wait(name)
break;
alarm(0);
(void) signal(SIGALRM, SIG_DFL);
+}
+ int
+auth_check(name)
+ char *name;
+{
/*
* Now check to see if the user is valid or not
*/
diff --git a/src/appl/telnet/telnetd/ChangeLog b/src/appl/telnet/telnetd/ChangeLog
index 1902a32f7..760cbb23f 100644
--- a/src/appl/telnet/telnetd/ChangeLog
+++ b/src/appl/telnet/telnetd/ChangeLog
@@ -1,3 +1,15 @@
+2004-11-15 Tom Yu <tlyu@mit.edu>
+
+ * ext.h: New variable "must_encrypt".
+
+ * telnetd.8: Update for changed command-line options.
+
+ * telnetd.c (getterminaltype): Merge Athena changes to require
+ encrypted connections.
+
+ * utility.c (ttsuck): Merge Athena changes to work around some
+ client timing bugs.
+
2004-09-22 Tom Yu <tlyu@mit.edu>
* Makefile.in (telnetd): Use UTIL_LIB.
diff --git a/src/appl/telnet/telnetd/ext.h b/src/appl/telnet/telnetd/ext.h
index 9fe38ef8b..7b77a44b0 100644
--- a/src/appl/telnet/telnetd/ext.h
+++ b/src/appl/telnet/telnetd/ext.h
@@ -88,6 +88,10 @@ extern char *unptyip; /* pointer to remaining characters in buffer */
extern int pty, net;
extern int SYNCHing; /* we are in TELNET SYNCH mode */
+#ifdef ENCRYPTION
+extern int must_encrypt;
+#endif
+
extern void
_termstat (void),
add_slc (int, int, int),
diff --git a/src/appl/telnet/telnetd/telnetd.8 b/src/appl/telnet/telnetd/telnetd.8
index 9426a0c3b..78700cbed 100644
--- a/src/appl/telnet/telnetd/telnetd.8
+++ b/src/appl/telnet/telnetd/telnetd.8
@@ -39,7 +39,7 @@ protocol server
.SH SYNOPSIS
.B /usr/libexec/telnetd
[\fB\-a\fP \fIauthmode\fP] [\fB\-B\fP] [\fB\-D\fP] [\fIdebugmode\fP]
-[\fB\-edebug\fP] [\fB\-h\fP] [\fB\-I\fP\fIinitid\fP] [\fB\-l\fP]
+[\fB\-e\fP] [\fB\-h\fP] [\fB\-I\fP\fIinitid\fP] [\fB\-l\fP]
[\fB\-k\fP] [\fB\-n\fP] [\fB\-r\fP\fIlowpty-highpty\fP] [\fB\-s\fP]
[\fB\-S\fP \fItos\fP] [\fB\-U\fP] [\fB\-X\fP \fIauthtype\fP]
[\fB\-w\fP [\fBip\fP|\fImaxhostlen\fP[\fB,\fP[\fBno\fP]\fBstriplocal\fP]]]
@@ -163,6 +163,9 @@ Displays the data stream received by
.B ptydata
Displays data written to the pty.
.TP
+.B encrypt
+Enables encryption debugging code.
+.TP
.B exercise
Has not been implemented yet.
.RE
@@ -175,12 +178,10 @@ Enables debugging on each socket created by
in
.IR socket (2)).
.TP
-.B \-edebug
-If
+.B \-e
+This option causes
.B telnetd
-has been compiled with support for data encryption, then the
-.B edebug
-option may be used to enable encryption debugging code.
+to refuse unencrypted connections.
.TP
.B \-h
Disables the printing of host-specific information before login has been
diff --git a/src/appl/telnet/telnetd/telnetd.c b/src/appl/telnet/telnetd/telnetd.c
index 5633d5625..a90fa5c5c 100644
--- a/src/appl/telnet/telnetd/telnetd.c
+++ b/src/appl/telnet/telnetd/telnetd.c
@@ -173,7 +173,7 @@ char valid_opts[] = {
'D', ':',
#endif
#ifdef ENCRYPTION
- 'e', ':',
+ 'e',
#endif
#if defined(CRAY) && defined(NEWINIT)
'I', ':',
@@ -308,6 +308,9 @@ main(argc, argv)
diagnostic |= TD_PTYDATA;
} else if (!strcmp(optarg, "options")) {
diagnostic |= TD_OPTIONS;
+ } else if (!strcmp(optarg, "encrypt")) {
+ extern int encrypt_debug_mode;
+ encrypt_debug_mode = 1;
} else {
usage();
/* NOT REACHED */
@@ -317,13 +320,7 @@ main(argc, argv)
#ifdef ENCRYPTION
case 'e':
- if (strcmp(optarg, "debug") == 0) {
- extern int encrypt_debug_mode;
- encrypt_debug_mode = 1;
- break;
- }
- usage();
- /* NOTREACHED */
+ must_encrypt = 1;
break;
#endif /* ENCRYPTION */
@@ -694,8 +691,12 @@ usage()
static void encrypt_failure()
{
- char *lerror_message =
- "Encryption was not successfully negotiated. Goodbye.\r\n\r\n";
+ char *lerror_message;
+
+ if (auth_must_encrypt())
+ lerror_message = "Encryption was not successfully negotiated. Goodbye.\r\n\r\n";
+ else
+ lerror_message = "Unencrypted connection refused. Goodbye.\r\n\r\n";
netputs(lerror_message);
netflush();
@@ -720,6 +721,7 @@ getterminaltype(name)
settimer(baseline);
#if defined(AUTHENTICATION)
+ ttsuck();
/*
* Handle the Authentication option before we do anything else.
*/
@@ -727,7 +729,7 @@ getterminaltype(name)
while (his_will_wont_is_changing(TELOPT_AUTHENTICATION))
ttloop();
if (his_state_is_will(TELOPT_AUTHENTICATION)) {
- retval = auth_wait(name);
+ auth_wait(name);
}
#endif
@@ -760,15 +762,25 @@ getterminaltype(name)
if (his_state_is_will(TELOPT_ENCRYPT)) {
encrypt_wait();
}
- if (auth_must_encrypt()) {
+ if (must_encrypt || auth_must_encrypt()) {
time_t timeout = time(0) + 60;
if (my_state_is_dont(TELOPT_ENCRYPT) ||
- my_state_is_wont(TELOPT_ENCRYPT))
+ my_state_is_wont(TELOPT_ENCRYPT) ||
+ his_state_is_wont(TELOPT_AUTHENTICATION))
encrypt_failure();
- if (!EncryptStartInput() || !EncryptStartOutput())
- encrypt_failure();
+ while (!EncryptStartInput()) {
+ if (time (0) > timeout)
+ encrypt_failure();
+ ttloop();
+ }
+
+ while (!EncryptStartOutput()) {
+ if (time (0) > timeout)
+ encrypt_failure();
+ ttloop();
+ }
while (!encrypt_is_encrypting()) {
if (time(0) > timeout)
@@ -865,7 +877,11 @@ getterminaltype(name)
}
}
}
- return(retval);
+#ifdef AUTHENTICATION
+ return(auth_check(name));
+#else
+ return(-1);
+#endif
} /* end of getterminaltype */
static void
diff --git a/src/appl/telnet/telnetd/utility.c b/src/appl/telnet/telnetd/utility.c
index fc8ff7601..f4568ec28 100644
--- a/src/appl/telnet/telnetd/utility.c
+++ b/src/appl/telnet/telnetd/utility.c
@@ -90,6 +90,67 @@ read_again:
}
} /* end of ttloop */
+/*
+ * ttsuck - This is a horrible kludge to deal with a bug in
+ * HostExplorer. HostExplorer thinks it knows how to do krb5 auth, but
+ * it doesn't really. So if you offer it krb5 as an auth choice before
+ * krb4, it will sabotage the connection. So we peek ahead into the
+ * input stream to see if the client is a UNIX client, and then
+ * (later) offer krb5 first only if it is. Since no Mac/PC telnet
+ * clients do auto switching between krb4 and krb5 like the UNIX
+ * client does, it doesn't matter what order they see the choices in
+ * (except for HostExplorer).
+ *
+ * It is actually not possible to do this without looking ahead into
+ * the input stream: the client and server both try to begin
+ * auth/encryption negotiation as soon as possible, so if we let the
+ * server process things normally, it will already have sent the list
+ * of supported auth types before seeing the NEW-ENVIRON option. If
+ * you change the code to hold off sending the list of supported auth
+ * types until after it knows whether or not the remote side supports
+ * NEW-ENVIRON, then the auth negotiation and encryption negotiation
+ * race conditions won't interact properly, and encryption negotiation
+ * will reliably fail.
+ */
+
+ void
+ttsuck()
+{
+ extern int auth_client_non_unix;
+ int nread;
+ struct timeval tv;
+ fd_set fds;
+ char *p, match[] = {IAC, WILL, TELOPT_NEW_ENVIRON};
+
+ if (nfrontp-nbackp) {
+ netflush();
+ }
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ FD_SET(net, &fds);
+
+ while (select(net + 1, &fds, NULL, NULL, &tv) == 1)
+ {
+ nread = read(net, netibuf + ncc, sizeof(netibuf) - ncc);
+ if (nread <= 0)
+ break;
+ ncc += nread;
+ }
+
+ auth_client_non_unix = 1;
+ for (p = netibuf; p < netibuf + ncc; p++)
+ {
+ if (!memcmp(p, match, sizeof(match)))
+ {
+ auth_client_non_unix = 0;
+ break;
+ }
+ }
+
+ if (ncc > 0)
+ telrcv();
+}
+
/*
* Check a descriptor to see if out of band data exists on it.
*/
diff --git a/src/tests/dejagnu/krb-root/ChangeLog b/src/tests/dejagnu/krb-root/ChangeLog
index df5650558..328a26cfd 100644
--- a/src/tests/dejagnu/krb-root/ChangeLog
+++ b/src/tests/dejagnu/krb-root/ChangeLog
@@ -1,3 +1,10 @@
+2004-11-15 Tom Yu <tlyu@mit.edu>
+
+ * telnet.exp (telnet_test): Work around possible race condition
+ with client's resetting of terminal mode when returning from
+ interactive command mode. Test whether requiring encryption
+ works.
+
2004-03-14 Ken Raeburn <raeburn@mit.edu>
* rlogin.exp (start_rlogin_daemon, rlogin_test): Use portbase to
diff --git a/src/tests/dejagnu/krb-root/telnet.exp b/src/tests/dejagnu/krb-root/telnet.exp
index 17ca35e3c..03bdb7910 100644
--- a/src/tests/dejagnu/krb-root/telnet.exp
+++ b/src/tests/dejagnu/krb-root/telnet.exp
@@ -50,7 +50,7 @@ if {![get_hostname] \
# A procedure to start up the telnet daemon.
-proc start_telnet_daemon { } {
+proc start_telnet_daemon { args } {
global REALMNAME
global TELNETD
global LOGINKRB5
@@ -70,7 +70,7 @@ proc start_telnet_daemon { } {
# we don't need to use inetd. The portbase+8 is the port to listen at.
# Note that tmppwd here is a shell variable, which is set in
# setup_root_shell, not a TCL variable.
- send -i $rlogin_spawn_id "sh -c \"$TELNETD -debug -t \$tmppwd/srvtab -R $REALMNAME -L $tmppwd/login.wrap -X KERBEROS_V4 [expr 8 + $portbase]\" &\r"
+ send -i $rlogin_spawn_id "sh -c \"$TELNETD $args -debug -t \$tmppwd/srvtab -R $REALMNAME -L $tmppwd/login.wrap -X KERBEROS_V4 [expr 8 + $portbase]\" &\r"
expect {
-i $rlogin_spawn_id
-re "$ROOT_PROMPT" { }
@@ -174,7 +174,7 @@ proc telnet_test { } {
set testname "simple telnet"
expect {
- "ogin:" {
+ "ogin: " {
pass $testname
}
}
@@ -184,7 +184,7 @@ proc telnet_test { } {
set testname "telnet command mode"
send "\035"
expect {
- "telnet>" {
+ "telnet> " {
pass $testname
}
}
@@ -200,9 +200,16 @@ proc telnet_test { } {
}
set testname "back to command mode"
+
+ # For some reason, the telnet client doesn't necessarily reset the
+ # terminal mode back to raw after exiting command mode.
+ # Kick it somewhat by sending a CR.
+ send "\r"
+ expect "ogin: "
+
send "\035"
expect {
- "telnet>" {
+ "telnet> " {
pass $testname
}
}
@@ -299,6 +306,7 @@ proc telnet_test { } {
}
expect_after
+ catch "expect eof"
# We can't use check_exit_status, because we expect an exit status
# of 1.
@@ -355,7 +363,7 @@ proc telnet_test { } {
# Move back to telnet command mode and check the encryption status.
set testname "encryption status"
send "\035"
- expect "telnet>"
+ expect "telnet> "
send "status\r"
expect {
-re "Currently encrypting output with DES_CFB64.*Currently decrypting input with DES_CFB64" {
@@ -368,6 +376,7 @@ proc telnet_test { } {
expect "Connection closed by foreign host.\r"
expect_after
+ catch "expect eof"
# We can't use check_exit_status, because we expect an exit status
# of 1.
@@ -384,6 +393,38 @@ proc telnet_test { } {
# The telnet daemon should have stopped, but we have no easy way
# of checking whether it actually did. Kill it just in case.
stop_telnet_daemon
+
+ set testname "reject unencrypted telnet"
+ # Check rejection of unencrypted client when encryption is required
+ start_telnet_daemon -e
+
+ # unencrypted, unauthenticated
+ spawn $TELNET -- $hostname -[expr 8 + $portbase]
+ expect_after {
+ timeout {
+ fail $testname
+ catch "expect_after"
+ return
+ }
+ eof {
+ fail $testname
+ catch "expect_after"
+ return
+ }
+ }
+
+ expect {
+ -re "Unencrypted connection refused.*\n" {
+ pass $testname
+ }
+ }
+ catch "expect_after"
+ catch "expect eof"
+ catch wait
+
+ # The telnet daemon should have stopped, but we have no easy way
+ # of checking whether it actually did. Kill it just in case.
+ stop_telnet_daemon
}
# Run the test. Logging in sometimes takes a while, so increase the