diff --git a/appl/telnet/telnet/authenc.c b/appl/telnet/telnet/authenc.c index 909ee5af2..ee7a1f5c0 100644 --- a/appl/telnet/telnet/authenc.c +++ b/appl/telnet/telnet/authenc.c @@ -62,7 +62,14 @@ net_encrypt(void) 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 --git a/appl/telnet/telnet/externs.h b/appl/telnet/telnet/externs.h index b4c7d08ab..251160edc 100644 --- a/appl/telnet/telnet/externs.h +++ b/appl/telnet/telnet/externs.h @@ -66,6 +66,7 @@ extern int 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 */ @@ -81,6 +82,8 @@ extern int 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 */ #ifdef KLUDGELINEMODE diff --git a/appl/telnet/telnet/main.c b/appl/telnet/telnet/main.c index b28657528..f450c3ab9 100644 --- a/appl/telnet/telnet/main.c +++ b/appl/telnet/telnet/main.c @@ -126,6 +126,7 @@ krb5_init(void) "libdefaults", "encrypt", NULL)) { encrypt_auto(1); decrypt_auto(1); + wantencryption = 1; EncryptVerbose(1); } #endif @@ -295,6 +296,7 @@ main(int argc, char **argv) #ifdef ENCRYPTION encrypt_auto(1); decrypt_auto(1); + wantencryption = 1; EncryptVerbose(1); #else fprintf(stderr, diff --git a/appl/telnet/telnet/sys_bsd.c b/appl/telnet/telnet/sys_bsd.c index 822b38299..167a6d73b 100644 --- a/appl/telnet/telnet/sys_bsd.c +++ b/appl/telnet/telnet/sys_bsd.c @@ -651,10 +651,17 @@ deadpeer(int sig) 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 --git a/appl/telnet/telnet/telnet.1 b/appl/telnet/telnet/telnet.1 index a89d725c8..0e037b7b5 100644 --- a/appl/telnet/telnet/telnet.1 +++ b/appl/telnet/telnet/telnet.1 @@ -177,8 +177,10 @@ In this 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 --git a/appl/telnet/telnet/telnet.c b/appl/telnet/telnet/telnet.c index a7a9d9397..0e3708846 100644 --- a/appl/telnet/telnet/telnet.c +++ b/appl/telnet/telnet/telnet.c @@ -70,6 +70,7 @@ int 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 @@ int char *prompt = 0; +int scheduler_lockout_tty = 0; + cc_t escape; cc_t rlogin; #ifdef KLUDGELINEMODE @@ -1957,7 +1960,7 @@ telsnd() */ -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 @@ Scheduler(int block) /* should we block in the select ? */ /* 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 @@ Scheduler(int block) /* should we block in the select ? */ void my_telnet(char *user) { + int printed_encrypt = 0; + sys_telnet_init(); #if defined(AUTHENTICATION) || defined(ENCRYPTION) @@ -2048,6 +2057,64 @@ my_telnet(char *user) 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,\n"); + printf("which is required for encryption.\n"); + Exit(1); + } + if (auth_has_failed) { + printf("\nAuthentication negotation has failed,\n"); + printf("which is required for encryption.\n"); + Exit(1); + } + if (my_want_state_is_dont(TELOPT_ENCRYPT) || + my_want_state_is_wont(TELOPT_ENCRYPT)) { + printf("\nServer refused to negotiate encryption.\n"); + Exit(1); + } + if (encrypt_is_encrypting()) + break; + if (time(0) > timeout) { + printf("\nEncryption could not be enabled.\n"); + 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 interrupt.\n"); + Exit(1); + } + telnet_spin(); + } + if (printed_encrypt) { + printf("done.\n"); + intr_waiting = 0; + setconnmode(0); + } + } +#endif + for (;;) { int schedValue; diff --git a/appl/telnet/telnet/telnet_locl.h b/appl/telnet/telnet/telnet_locl.h index 79b5ab8d6..2ea10b7f8 100644 --- a/appl/telnet/telnet/telnet_locl.h +++ b/appl/telnet/telnet/telnet_locl.h @@ -138,6 +138,10 @@ #include #endif #ifdef HAVE_ARPA_INET_H +#ifdef _AIX +struct sockaddr_dl; /* AIX fun */ +struct ether_addr; +#endif #include #endif