2001-08-26 Simon Josefsson * telnet/*: Port '-x' fix from MIT Kerberos. Mon Mar 18 20:56:37 1996 Theodore Y. Ts'o * encrypt.c (encrypt_is_encrypting): New function which returns true only if both sides of the telnet stream is encrypted. Mon Mar 18 20:31:44 1996 Theodore Y. Ts'o * telnet/authenc.c (telnet_spin): Implemented the telnet spin function, which works by calling the Scheduler with the tty_lockout flag set. * main.c (main): If the -x option is given, set the autologin, wantencryption, and auth_enable_encrypt flag. They enable authentication, enforcement of the encryption option, and a flag to the auth layer to negotiate authentication with mandatory encryption option. * telnet.c (telnet): If the wantencryption flag is set (because the user has given the -x option, then we enforce that encryption must be turned on. The user will not be able to type to the network stream until encryption is enabled, and if encryption is refused, the client will print an error message. (Scheduler): If the tty_lockout flag is set, then don't process keyboard read events. This prevents the user from typing over the network until encryption is enabled. diff -ur heimdal-0.4d.orig/appl/telnet/libtelnet/auth.c heimdal-0.4d/appl/telnet/libtelnet/auth.c --- heimdal-0.4d.orig/appl/telnet/libtelnet/auth.c Mon Jun 18 21:49:59 2001 +++ heimdal-0.4d/appl/telnet/libtelnet/auth.c Sun Aug 26 21:56:06 2001 @@ -100,6 +100,8 @@ #endif int auth_debug_mode = 0; +int auth_has_failed = 0; +int auth_enable_encrypt = 0; static const char *Name = "Noname"; static int Server = 0; static Authenticator *authenticated = 0; @@ -468,6 +470,7 @@ if (auth_debug_mode) printf(">>>%s: Sent failure message\r\n", Name); auth_finished(0, AUTH_REJECT); + auth_has_failed = 1; #ifdef KANNAN /* * We requested strong authentication, however no mechanisms worked. diff -ur heimdal-0.4d.orig/appl/telnet/libtelnet/enc-proto.h heimdal-0.4d/appl/telnet/libtelnet/enc-proto.h --- heimdal-0.4d.orig/appl/telnet/libtelnet/enc-proto.h Tue Jan 18 04:09:56 2000 +++ heimdal-0.4d/appl/telnet/libtelnet/enc-proto.h Sun Aug 26 22:01:03 2001 @@ -94,6 +94,7 @@ void encrypt_send_keyid(int, unsigned char*, int, int); void encrypt_send_request_end(void); void encrypt_send_request_start(void); +int encrypt_is_encrypting(void); void encrypt_send_support(void); void encrypt_session_key(Session_Key*, int); void encrypt_start(unsigned char*, int); diff -ur heimdal-0.4d.orig/appl/telnet/libtelnet/encrypt.c heimdal-0.4d/appl/telnet/libtelnet/encrypt.c --- heimdal-0.4d.orig/appl/telnet/libtelnet/encrypt.c Tue Jan 18 04:10:35 2000 +++ heimdal-0.4d/appl/telnet/libtelnet/encrypt.c Sun Aug 26 22:01:21 2001 @@ -952,6 +952,13 @@ return 0; } +int encrypt_is_encrypting() +{ + if (encrypt_output && decrypt_input) + return 1; + return 0; +} + void encrypt_debug(int mode) { diff -ur heimdal-0.4d.orig/appl/telnet/telnet/authenc.c heimdal-0.4d/appl/telnet/telnet/authenc.c --- heimdal-0.4d.orig/appl/telnet/telnet/authenc.c Thu Nov 16 00:00:58 2000 +++ heimdal-0.4d/appl/telnet/telnet/authenc.c Sun Aug 26 22:12:00 2001 @@ -62,7 +62,14 @@ int telnet_spin(void) { - return(-1); + extern int scheduler_lockout_tty; + + scheduler_lockout_tty = 1; + Scheduler(0); + scheduler_lockout_tty = 0; + + return 0; + } char * diff -ur heimdal-0.4d.orig/appl/telnet/telnet/externs.h heimdal-0.4d/appl/telnet/telnet/externs.h --- heimdal-0.4d.orig/appl/telnet/telnet/externs.h Fri Jul 6 17:39:25 2001 +++ heimdal-0.4d/appl/telnet/telnet/externs.h Sun Aug 26 22:02:52 2001 @@ -66,6 +66,7 @@ localchars, /* we recognize interrupt/quit */ donelclchars, /* the user has set "localchars" */ showoptions, + wantencryption, /* User has requested encryption */ net, /* Network file descriptor */ tin, /* Terminal input file descriptor */ tout, /* Terminal output file descriptor */ @@ -80,6 +81,8 @@ prettydump, /* Print "netdata" output in user readable format */ termdata, /* Print out terminal data flow */ debug; /* Debug level */ + +extern int intr_happened, intr_waiting; /* for interrupt handling */ extern cc_t escape; /* Escape to command mode */ extern cc_t rlogin; /* Rlogin mode escape character */ diff -ur heimdal-0.4d.orig/appl/telnet/telnet/main.c heimdal-0.4d/appl/telnet/telnet/main.c --- heimdal-0.4d.orig/appl/telnet/telnet/main.c Mon Jun 18 21:52:22 2001 +++ heimdal-0.4d/appl/telnet/telnet/main.c Sun Aug 26 22:02:20 2001 @@ -126,6 +126,7 @@ "libdefaults", "encrypt", NULL)) { encrypt_auto(1); decrypt_auto(1); + wantencryption = 1; EncryptVerbose(1); } #endif @@ -292,6 +293,7 @@ #ifdef ENCRYPTION encrypt_auto(1); decrypt_auto(1); + wantencryption = 1; EncryptVerbose(1); #else fprintf(stderr, diff -ur heimdal-0.4d.orig/appl/telnet/telnet/sys_bsd.c heimdal-0.4d/appl/telnet/telnet/sys_bsd.c --- heimdal-0.4d.orig/appl/telnet/telnet/sys_bsd.c Tue Mar 6 21:10:14 2001 +++ heimdal-0.4d/appl/telnet/telnet/sys_bsd.c Sun Aug 26 22:04:29 2001 @@ -652,10 +652,17 @@ longjmp(peerdied, -1); } +int intr_happened = 0; +int intr_waiting = 0; + /* ARGSUSED */ static RETSIGTYPE intr(int sig) { + if (intr_waiting) { + intr_happened = 1; + return; + } if (localchars) { intp(); return; diff -ur heimdal-0.4d.orig/appl/telnet/telnet/telnet.1 heimdal-0.4d/appl/telnet/telnet/telnet.1 --- heimdal-0.4d.orig/appl/telnet/telnet/telnet.1 Fri May 11 10:23:40 2001 +++ heimdal-0.4d/appl/telnet/telnet/telnet.1 Sun Aug 26 22:26:14 2001 @@ -177,8 +177,10 @@ mode, the escape character is set to the tilde (~) character, unless modified by the -e option. .It Fl x -Turns on encryption of the data stream if possible. This is -currently the default and when it fails a warning is issued. +Turn on encryption of the data stream. When this option is turned on, +.B telnet +will exit with an error if authentication cannot be negotiated or if +encryption cannot be turned on. .It Ar host Indicates the official name, an alias, or the Internet address of a remote host. diff -ur heimdal-0.4d.orig/appl/telnet/telnet/telnet.c heimdal-0.4d/appl/telnet/telnet/telnet.c --- heimdal-0.4d.orig/appl/telnet/telnet/telnet.c Wed Nov 8 18:32:43 2000 +++ heimdal-0.4d/appl/telnet/telnet/telnet.c Sun Aug 26 22:15:00 2001 @@ -70,6 +70,7 @@ netdata, /* Print out network data flow */ crlf, /* Should '\r' be mapped to (or )? */ telnetport, + wantencryption = 0, SYNCHing, /* we are in TELNET SYNCH mode */ flushout, /* flush output */ autoflush = 0, /* flush output when interrupting? */ @@ -84,6 +85,8 @@ char *prompt = 0; +int scheduler_lockout_tty = 0; + cc_t escape; cc_t rlogin; #ifdef KLUDGELINEMODE @@ -1957,7 +1960,7 @@ */ -static int + int Scheduler(int block) /* should we block in the select ? */ { /* One wants to be a bit careful about setting returnValue @@ -1988,6 +1991,10 @@ /* If we have seen a signal recently, reset things */ + if (scheduler_lockout_tty) { + ttyin = ttyout = 0; + } + /* Call to system code to process rings */ returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block); @@ -2010,6 +2017,8 @@ void my_telnet(char *user) { + int printed_encrypt = 0; + sys_telnet_init(); #if defined(AUTHENTICATION) || defined(ENCRYPTION) @@ -2047,6 +2056,64 @@ if (binary) tel_enter_binary(binary); } + +#ifdef ENCRYPTION + /* + * Note: we assume a tie to the authentication option here. This + * is necessary so that authentication fails, we don't spin + * forever. + */ + if (wantencryption) { + extern int auth_has_failed; + time_t timeout = time(0) + 60; + + send_do(TELOPT_ENCRYPT, 1); + send_will(TELOPT_ENCRYPT, 1); + while (1) { + if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) { + printf("\nServer refused to negotiate authentication, which is required\n"); + printf("for encryption. Good bye.\n\r"); + Exit(1); + } + if (auth_has_failed) { + printf("\nAuthentication negotation has failed, which is required for\n"); + printf("encryption. Good bye.\n\r"); + Exit(1); + } + if (my_want_state_is_dont(TELOPT_ENCRYPT) || + my_want_state_is_wont(TELOPT_ENCRYPT)) { + printf("\nServer refused to negotiate encryption. Good bye.\n\r"); + Exit(1); + } + if (encrypt_is_encrypting()) + break; + if (time(0) > timeout) { + printf("\nEncryption could not be enabled. Goodbye.\n\r"); + Exit(1); + } + if (printed_encrypt == 0) { + printed_encrypt = 1; + printf("Waiting for encryption to be negotiated...\n"); + /* + * Turn on MODE_TRAPSIG and then turn off localchars + * so that ^C will cause telnet to exit. + */ + TerminalNewMode(getconnmode()|MODE_TRAPSIG); + intr_waiting = 1; + } + if (intr_happened) { + printf("\nUser requested an interrupt. Goodbye.\n\r"); + Exit(1); + } + telnet_spin(); + } + if (printed_encrypt) { + printf("done.\n"); + intr_waiting = 0; + setconnmode(0); + } + } +#endif for (;;) { int schedValue;