Bug 122526 - www/lighttpd active SSL connection loss (SSL3_WRITE_PENDING:bad write retry)
Summary: www/lighttpd active SSL connection loss (SSL3_WRITE_PENDING:bad write retry)
Status: Closed FIXED
Alias: None
Product: Ports & Packages
Classification: Unclassified
Component: Individual Port(s) (show other bugs)
Version: Latest
Hardware: Any Any
: Normal Affects Only Me
Assignee: Marcus Alves Grando
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-04-07 12:20 UTC by Harald Schmalzbauer
Modified: 2008-04-13 05:00 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Harald Schmalzbauer 2008-04-07 12:20:00 UTC
	lighttpd 1.4.19 shows these lines in the error-log:
(network_openssl.c.130) SSL: 1 -1 error:1409F07F:SSL routines:SSL3_WRITE_PENDING:bad write retry 
(connections.c.614) connection closed: write failed on fd 8
If one of two concurrent SSL connections get cancelled by the client then also the other connection gets closed by lighhtpd.
According to http://trac.lighttpd.net/trac/ticket/285 this is a closed DoS vulnerability
(http://nvd.nist.gov/nvd.cfm?cvename=CVE-2008-1531)

Fix: 

add patch-SSL_shutdown to files directory:

--- src/connections.c (revision 2103)
+++ src/connections.c (revision 2136)
@@ -200,4 +200,5 @@
        /* don't resize the buffer if we were in SSL_ERROR_WANT_* */

+       ERR_clear_error();
        do {
                if (!con->ssl_error_want_reuse_buffer) {
@@ -1670,4 +1671,5 @@
                        if (srv_sock->is_ssl) {
                                int ret;
+                               ERR_clear_error();
                                switch ((ret = SSL_shutdown(con->ssl))) {
                                case 1:
@@ -1675,6 +1677,8 @@
                                        break;
                                case 0:
-                                       SSL_shutdown(con->ssl);
-                                       break;
+                                       ERR_clear_error();
+                                       if ((ret = SSL_shutdown(con->ssl)) == 1) break;
+
+                                       // fall through
                                default:
                                        log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
--- src/network_openssl.c (revision 2084)
+++ src/network_openssl.c (revision 2136)
@@ -86,4 +86,5 @@
                         */

+                       ERR_clear_error();
                        if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
                                unsigned long err;
@@ -188,4 +189,5 @@
                                close(ifd);

+                               ERR_clear_error();
                                if ((r = SSL_write(ssl, s, toSend)) <= 0) {
                                        unsigned long err;
--- NEWS (revision 2130)
+++ NEWS (revision 2136)
@@ -9,4 +9,5 @@
   * Fix mod_extforward to compile with old gcc version (#1591)
   * Update documentation for #1587
+  * Fix #285 again: read error after SSL_shutdown (thx marton.illes@balabit.com) and clear the error queue before some other calls

 - 1.4.19 - 2008-03-10
--- src/connections.c (revision 2136)
+++ src/connections.c (revision 2139)
@@ -1670,5 +1670,6 @@
 #ifdef USE_OPENSSL
                        if (srv_sock->is_ssl) {
-                               int ret;
+                               int ret, ssl_r;
+                               unsigned long err;
                                ERR_clear_error();
                                switch ((ret = SSL_shutdown(con->ssl))) {
@@ -1678,14 +1679,40 @@
                                case 0:
                                        ERR_clear_error();
-                                       if ((ret = SSL_shutdown(con->ssl)) == 1) break;
+                                       if (-1 != (ret = SSL_shutdown(con->ssl))) break;

                                        // fall through
                                default:
-                                       log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
-                                                       SSL_get_error(con->ssl, ret),
-                                                       ERR_error_string(ERR_get_error(), NULL));
-                                       return -1;
+
+                                       switch ((ssl_r = SSL_get_error(con->ssl, ret))) {
+                                       case SSL_ERROR_WANT_WRITE:
+                                       case SSL_ERROR_WANT_READ:
+                                               break;
+                                       case SSL_ERROR_SYSCALL:
+                                               /* perhaps we have error waiting in our error-queue */
+                                               if (0 != (err = ERR_get_error())) {
+                                                       do {
+                                                               log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
+                                                                               ssl_r, ret,
+                                                                               ERR_error_string(err, NULL));
+                                                       } while((err = ERR_get_error()));
+                                               } else {
+                                                       log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
+                                                                       ssl_r, r, errno,
+                                                                       strerror(errno));
+                                               }
+       
+                                               break;
+                                       default:
+                                               while((err = ERR_get_error())) {
+                                                       log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
+                                                                       ssl_r, ret,
+                                                                       ERR_error_string(err, NULL));
+                                               }
+       
+                                               break;
+                                       }
                                }
                        }
+                       ERR_clear_error();
 #endif
How-To-Repeat: 	Install lighttpd 1.4.19 and download something using SSL
Comment 1 Edwin Groothuis freebsd_committer freebsd_triage 2008-04-07 13:26:32 UTC
Responsible Changed
From-To: freebsd-ports-bugs->mnag

Over to maintainer (via the GNATS Auto Assign Tool)
Comment 2 h.schmalzbauer 2008-04-07 13:38:20 UTC
FreeBSD-gnats-submit@FreeBSD.org wrote am 07.04.2008 13:20 (localtime):

Sorry, there as a select'n'paste error, here is the correct patch:

--- src/connections.c (revision 2103)
+++ src/connections.c (revision 2136)
@@ -200,4 +200,5 @@
  	/* don't resize the buffer if we were in SSL_ERROR_WANT_* */

+	ERR_clear_error();
  	do {
  		if (!con->ssl_error_want_reuse_buffer) {
@@ -1670,4 +1671,5 @@
  			if (srv_sock->is_ssl) {
  				int ret;
+				ERR_clear_error();
  				switch ((ret = SSL_shutdown(con->ssl))) {
  				case 1:
@@ -1675,6 +1677,8 @@
  					break;
  				case 0:
-					SSL_shutdown(con->ssl);
-					break;
+					ERR_clear_error();
+					if ((ret = SSL_shutdown(con->ssl)) == 1) break;
+
+					// fall through
  				default:
  					log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
--- src/network_openssl.c (revision 2084)
+++ src/network_openssl.c (revision 2136)
@@ -86,4 +86,5 @@
  			 */

+			ERR_clear_error();
  			if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
  				unsigned long err;
@@ -188,4 +189,5 @@
  				close(ifd);

+				ERR_clear_error();
  				if ((r = SSL_write(ssl, s, toSend)) <= 0) {
  					unsigned long err;
--- NEWS (revision 2130)
+++ NEWS (revision 2136)
@@ -9,4 +9,5 @@
    * Fix mod_extforward to compile with old gcc version (#1591)
    * Update documentation for #1587
+  * Fix #285 again: read error after SSL_shutdown (thx 
marton.illes@balabit.com) and clear the error queue before some other calls

  - 1.4.19 - 2008-03-10
--- src/connections.c (revision 2136)
+++ src/connections.c (revision 2139)
@@ -1670,5 +1670,6 @@
  #ifdef USE_OPENSSL
  			if (srv_sock->is_ssl) {
-				int ret;
+				int ret, ssl_r;
+				unsigned long err;
  				ERR_clear_error();
  				switch ((ret = SSL_shutdown(con->ssl))) {
@@ -1678,14 +1679,40 @@
  				case 0:
  					ERR_clear_error();
-					if ((ret = SSL_shutdown(con->ssl)) == 1) break;
+					if (-1 != (ret = SSL_shutdown(con->ssl))) break;

  					// fall through
  				default:
-					log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
-							SSL_get_error(con->ssl, ret),
-							ERR_error_string(ERR_get_error(), NULL));
-					return -1;
+
+					switch ((ssl_r = SSL_get_error(con->ssl, ret))) {
+					case SSL_ERROR_WANT_WRITE:
+					case SSL_ERROR_WANT_READ:
+						break;
+					case SSL_ERROR_SYSCALL:
+						/* perhaps we have error waiting in our error-queue */
+						if (0 != (err = ERR_get_error())) {
+							do {
+								log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
+										ssl_r, ret,
+										ERR_error_string(err, NULL));
+							} while((err = ERR_get_error()));
+						} else {
+							log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
+									ssl_r, r, errno,
+									strerror(errno));
+						}
+	
+						break;
+					default:
+						while((err = ERR_get_error())) {
+							log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
+									ssl_r, ret,
+									ERR_error_string(err, NULL));
+						}
+	
+						break;
+					}
  				}
  			}
+			ERR_clear_error();
  #endif
Comment 3 dfilter service freebsd_committer freebsd_triage 2008-04-13 04:50:36 UTC
mnag        2008-04-13 03:50:28 UTC

  FreeBSD ports repository

  Modified files:
    www/lighttpd         Makefile 
  Added files:
    www/lighttpd/files   patch-CVE-2008-1531 
  Log:
  - Fix DOS in SSL connection
  
  PR:             122526
  Submitted by:   Harald Schmalzbauer <harry___omnisec.de>
  Security:       http://www.vuxml.org/freebsd/1ac77649-0908-11dd-974d-000fea2763ce.html
  
  Revision  Changes    Path
  1.59      +1 -0      ports/www/lighttpd/Makefile
  1.1       +119 -0    ports/www/lighttpd/files/patch-CVE-2008-1531 (new)
_______________________________________________
cvs-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/cvs-all
To unsubscribe, send any mail to "cvs-all-unsubscribe@freebsd.org"
Comment 4 Marcus Alves Grando freebsd_committer freebsd_triage 2008-04-13 04:52:45 UTC
State Changed
From-To: open->closed

Committed, with minor changes. Thanks!