Telopt STARTTLS: weitere Ausgaben unterbinden.

Die Pruefung auf eine aktive Verhandlung in logon2()
ging irgendwann verloren und wurde wieder ergaenzt.
Ausserdem an zwei Stellen im Telnegshandler pruefen, ob
eine Verhandlung laeuft.

Change-Id: I15333d719c7f53c187f52e4fdc28b04fbce8d8e9
diff --git a/secure/login.c b/secure/login.c
index bd8726e..d51402a 100644
--- a/secure/login.c
+++ b/secure/login.c
@@ -169,26 +169,6 @@
   tls_init_connection(this_object(), #'tls_init_callback);
 }
 
-// Wenn der Client via STARTTLS eine TLS negotiation angestossen hat und
-// die noch laeuft, darf keine Ausgabe erfolgen. In diesem Fall wird das
-// Loginverfahren ausgesetzt, bis die TLS-Verhandlung abgeschlossen ist.
-// Danach wird es fortgesetzt bzw. neugestartet. Dies gilt auch fuer Fall,
-// dass STARTTLS verhandelt wurde, aber die TLS-Verhandlung noch nicht
-// laeuft. (Bemerkung: beides pruefen ist nicht ueberfluessig. Den Zustand
-// der Telnet-Option muss man pruefen, weil der Client evtl. seine
-// Verhandlung noch nicht signalisiert hat (FOLLOWS vom Client) und die
-// efun muss man pruefen, weil nach Empfang von FOLLOWS vom Client der
-// Status der Telnet-Optiosn resettet wurde - standardkonform.)
-private int check_tls_negotiation()
-{
-  struct telopt_s s_tls = query_telnet_neg()[TELOPT_STARTTLS];
-  if (tls_query_connection_state(this_object()) < 0
-      || (structp(s_tls) && s_tls->state->remoteside) )
-    return 1;
-
-  return 0;
-}
-
 /*
  * This is the function that gets called by /secure/master for every user
  */
@@ -348,6 +328,10 @@
     int i, arg;
     mixed txt;
 
+    // ggf. muss TLS (initiiert durch STARTTLS) noch ausverhandelt werden.
+    if (check_tls_negotiation())
+      return;
+
     if ( !str || str == "" ){
         write( "Abbruch!\n" );
         destruct( this_object() );
diff --git a/secure/telnetneg.c b/secure/telnetneg.c
index 1b175a5..f6f254b 100644
--- a/secure/telnetneg.c
+++ b/secure/telnetneg.c
@@ -138,7 +138,8 @@
     return efun::binary_message(arr, bm_flags);
 }
 
-protected varargs int send_telnet_neg_str(bytes str, int bm_flags) {
+protected varargs int send_telnet_neg_str(bytes str, int bm_flags)
+{
 #ifdef __DEBUG__
     // Debugausgaben zur Zeit nur fuer arraybasierte Variante
     return send_telnet_neg(to_array(str), bm_flags);
@@ -171,6 +172,28 @@
 #endif // __DEBUG__
 }
 
+// Wenn der Client via STARTTLS eine TLS negotiation angestossen hat und
+// die noch laeuft, darf keine Ausgabe erfolgen. In diesem Fall wird das
+// Loginverfahren ausgesetzt, bis die TLS-Verhandlung abgeschlossen ist.
+// Danach wird es fortgesetzt bzw. neugestartet. Dies gilt auch fuer Fall,
+// dass STARTTLS verhandelt wurde, aber die TLS-Verhandlung noch nicht
+// laeuft. (Bemerkung: beides pruefen ist nicht ueberfluessig. Den Zustand
+// der Telnet-Option muss man pruefen, weil der Client evtl. seine
+// Verhandlung noch nicht signalisiert hat (FOLLOWS vom Client) und die
+// efun muss man pruefen, weil nach Empfang von FOLLOWS vom Client der
+// Status der Telnet-Optiosn resettet wurde - standardkonform.)
+protected int check_tls_negotiation()
+{
+  struct telopt_s s_tls = TN[TELOPT_STARTTLS];
+  if (tls_query_connection_state(this_object()) < 0
+      || (structp(s_tls) && s_tls->state->remoteside) )
+  {
+    debug_message("In TLS negotiation.\n");
+    return 1;
+  }
+  return 0;
+}
+
 // Startet eine Verhandlung, um den Status einer Option zu aendern.
 // Wenn bereits eine Verhandlung laeuft, wird nichts gemacht und -1
 // zurueckgeben.
@@ -182,6 +205,12 @@
 //           DO  : Option soll auf der anderen Seite eingeschaltet werden.
 //           DONT: Option soll auf der anderen Seite ausgeschaltet werden.
 protected int do_telnet_neg(int option, int action) {
+
+  // ggf. muss TLS (initiiert durch STARTTLS) noch ausverhandelt werden. In
+  // dem Fall nix verhandeln/senden, was nicht STARTTLS ist.
+  if (option != TELOPT_STARTTLS && check_tls_negotiation())
+    return 0;
+
   struct telopt_s opt = TN[option];
   if (!structp(opt))
   {
@@ -735,6 +764,11 @@
 {
     DTN("recv_tn: ", ({IAC, command, option}) + (optargs||({})));
 
+    // ggf. muss TLS (initiiert durch STARTTLS) noch ausverhandelt werden. In
+    // dem Fall muessen wir alles ignorieren, was nicht STARTTLS ist.
+    if (option != TELOPT_STARTTLS && check_tls_negotiation())
+      return;
+
     struct telopt_s opt = TN[option];
     if (!structp(opt))
     {