On Mon, May 28, 2007 at 10:23:14AM +0200, Robert Millan [ackstorm] wrote:
> On Sun, May 27, 2007 at 04:10:28PM +0200, Simon Josefsson wrote:
> > 
> > However, I'm not convinced this is the right fix.  I believe the servers
> > are buggy here, and changing gnutls seems the wrong response.
> > 
> > What we may want to do is to improve the behaviour when we encounter a
> > buggy server, which may include some kind of timeout or similar.
> > However, if the server closed the connection, I think it should be
> > possible to detect this, and then we can print a message.
> 
> I'm working on this atm.  I have almost completed a patch that implements this
> timeout option (will send it RSN).
> 
> > To work on this, I need a way to reproduce it though.  Do you know of a
> > server that exhibit this behaviour that we can use?
> 
> This works:  while sudo nc -lp 443 ; do true ; done
> 
> But please wait a day or two for my patch.

Here is it.  The SIGALRM feature was getting into the way, so I moved it to
SIGHUP, which is more consistent with existing practice.

Works for dumb netcat-like servers, but is also useful for normal servers when
you want to gather information about certificates without starting an HTTP
session.

-- 
Robert Millan

ACK STORM, S.L. - http://www.ackstorm.es
diff -ur -x stamp-vti -x version.texi -x cli-gaa.c -x cli-gaa.h gnutls13-1.7.7.old/doc/gnutls.texi gnutls13-1.7.7/doc/gnutls.texi
--- gnutls13-1.7.7.old/doc/gnutls.texi	2007-02-08 14:17:41.000000000 +0100
+++ gnutls13-1.7.7/doc/gnutls.texi	2007-05-28 18:20:37.000000000 +0200
@@ -2219,7 +2219,7 @@
      -r, --resume             Connect, establish a session. Connect
                               again and resume this session.
      -s, --starttls           Connect, establish a plain session and
-                              start TLS when EOF or a SIGALRM is
+                              start TLS when EOF or a SIGHUP is
                               received.
      --crlf                   Send CR LF instead of LF.
      --x509fmtder             Use DER format for certificates to read
diff -ur -x stamp-vti -x version.texi -x cli-gaa.c -x cli-gaa.h gnutls13-1.7.7.old/doc/manpages/gnutls-cli.1 gnutls13-1.7.7/doc/manpages/gnutls-cli.1
--- gnutls13-1.7.7.old/doc/manpages/gnutls-cli.1	2004-10-28 14:14:54.000000000 +0200
+++ gnutls13-1.7.7/doc/manpages/gnutls-cli.1	2007-05-28 18:20:37.000000000 +0200
@@ -20,7 +20,7 @@
 .IP "\-r, \-\-resume"
 Connect, establish a session.  Connect again and resume this session.
 .IP "\-s, \-\-starttls"
-Connect, establish a plain session and start TLS when EOF or a SIGALRM
+Connect, establish a plain session and start TLS when EOF or a SIGHUP
 is received.
 .IP "\-v, \-\-version"
 Prints the program's version number.
Only in gnutls13-1.7.7/po: gnutls13.pot
diff -ur -x stamp-vti -x version.texi -x cli-gaa.c -x cli-gaa.h gnutls13-1.7.7.old/src/cli.c gnutls13-1.7.7/src/cli.c
--- gnutls13-1.7.7.old/src/cli.c	2007-02-22 08:34:01.000000000 +0100
+++ gnutls13-1.7.7/src/cli.c	2007-05-28 18:59:55.000000000 +0200
@@ -82,6 +82,7 @@
 static int x509ctype;
 static int disable_extensions;
 static int debug;
+int io_timeout, io_timeout_count;
 
 char *psk_username = NULL;
 gnutls_datum psk_key = { NULL, 0 };
@@ -182,6 +183,9 @@
 static void init_global_tls_stuff (void);
 
 
+#undef MIN
+#define MIN(X,Y) (X >= Y ? Y : X);
+
 #undef MAX
 #define MAX(X,Y) (X >= Y ? X : Y);
 
@@ -619,12 +623,23 @@
   return ret;
 }
 
-int starttls_alarmed = 0;
+int starttls_sighuped = 0;
 
 void
-starttls_alarm (int signum)
+starttls_sighup (int signum)
 {
-  starttls_alarmed = 1;
+  starttls_sighuped = 1;
+}
+
+void
+starttls_sigalarm (int signum)
+{
+  if (--io_timeout_count == 0)
+    {
+      fprintf (stderr, "*** Timeout while waiting for data.\n");
+      exit (1);
+    }
+  alarm (1);
 }
 
 
@@ -662,13 +677,25 @@
   socket_open( &hd, hostname, service);
   socket_connect( &hd);
 
+  /* Start our time bomb right after we have a socket */
+#ifndef _WIN32
+  if (io_timeout)
+    {
+      io_timeout_count = io_timeout;
+      signal (SIGALRM, &starttls_sigalarm);
+      alarm (1);
+    }
+#endif
+
   hd.session = init_tls_session (hostname);
+
   if (starttls)
     goto after_handshake;
 
   for (i = 0; i < 2; i++)
     {
-
+      /* Reset the counter */
+      io_timeout_count = io_timeout;
 
       if (i == 1)
 	{
@@ -731,7 +758,7 @@
   printf ("\n- Simple Client Mode:\n\n");
 
 #ifndef _WIN32
-  signal (SIGALRM, &starttls_alarm);
+  signal (SIGHUP, &starttls_sighup);
 #endif
 
   /* do not buffer */
@@ -741,9 +768,12 @@
   setbuf (stdout, NULL);
   setbuf (stderr, NULL);
 
+  /* Reset the counter */
+  io_timeout_count = io_timeout;
+
   for (;;)
     {
-      if (starttls_alarmed && !hd.secure)
+      if (starttls_sighuped && !hd.secure)
 	{
 	  fprintf (stderr, "*** Starting TLS handshake\n");
 	  ret = do_handshake (&hd);
@@ -761,13 +791,17 @@
       FD_SET (hd.fd, &rset);
 
       maxfd = MAX (fileno (stdin), hd.fd);
-      tv.tv_sec = 3;
+      tv.tv_sec = MIN (3, io_timeout_count);
       tv.tv_usec = 0;
 
       err = select (maxfd + 1, &rset, NULL, NULL, &tv);
       if (err < 0)
 	continue;
 
+      if (err != 0)
+	/* Not stalled, reset the counter */
+	io_timeout_count = io_timeout;
+
       if (FD_ISSET (hd.fd, &rset))
 	{
 	  memset (buffer, 0, MAX_BUF + 1);
@@ -886,6 +920,7 @@
   service = info.port;
   record_max_size = info.record_size;
   fingerprint = info.fingerprint;
+  io_timeout = info.timeout;
 
   if (info.fmtder == 0)
     x509ctype = GNUTLS_X509_FMT_PEM;
diff -ur -x stamp-vti -x version.texi -x cli-gaa.c -x cli-gaa.h gnutls13-1.7.7.old/src/cli.gaa gnutls13-1.7.7/src/cli.gaa
--- gnutls13-1.7.7.old/src/cli.gaa	2007-02-22 08:17:34.000000000 +0100
+++ gnutls13-1.7.7/src/cli.gaa	2007-05-28 18:20:37.000000000 +0200
@@ -18,7 +18,7 @@
 option (r, resume) { $resume = 1 } "Connect, establish a session. Connect again and resume this session."
 
 #int starttls;
-option (s, starttls) { $starttls = 1 } "Connect, establish a plain session and start TLS when EOF or a SIGALRM is received."
+option (s, starttls) { $starttls = 1 } "Connect, establish a plain session and start TLS when EOF or a SIGHUP is received."
 
 #int crlf;
 option (crlf) { $crlf = 1 } "Send CR LF instead of LF."
@@ -44,6 +44,9 @@
 #int verbose;
 option (V, verbose) { $verbose = 1 } "More verbose output."
 
+#int timeout;
+option (t, timeout) INT "integer" { $timeout = $1 } "Set timeout (in seconds)."
+
 #int nciphers;
 #char **ciphers;
 option (ciphers) *STR "cipher1 cipher2..." { $ciphers = $1; $nciphers = @1 } "Ciphers to enable."

Reply via email to