[stunnel-users] 4.13+0.9.7i server stops writing SSL output

Richard.Hall Richard.Hall at ingenta.com
Mon Oct 24 17:19:24 CEST 2005


First-time post (though long-time satisfied occasional user). Searched the
archives but if there is anything relevant, I've obviously missed it.

I really cannot decide if this is an stunnel problem or an OpenSSL
problem.

Client is remote and running
  stunnel 4.12 on i686-pc-linux-gnu UCONTEXT+POLL+IPv4 with OpenSSL 0.9.6i

Server is local, I've been through
  4.12 + 0.9.6m
  4.13 + 0.9.6m
and now trying
  stunnel 4.13 on sparc-sun-solaris2.8 UCONTEXT+POLL+IPv4 with OpenSSL 0.9.7i
(I've resisted the urge to try OpenSSL 0.9.8* as people seem to be
experiencing 'issues')

Small amounts of data are fine. But for larger amounts the connection goes
to sleep. The way I read it, the server end stops trying to write to the
SSL side. The relevant parts of

# truss -w2 -v poll -dl /usr/local/stunnel-4.13/sbin/stunnel

look like this: (apologies for doing it like this, but it seemed the
easiest way to combine the debug output and truss output)

  (fd=7 is the SSL side, fd=8 the local side,
   TIMEOUTidle is set to 35 seconds for demo purposes)

/1:     15.5722 read(8, " A B\0\n03\007\t\t\r\n\t".., 8178)     = 8178
/1:     poll(0x00049DD8, 3, 35000)      (sleeping...)
/1:             fd=3  ev=POLLIN rev=0
/1:             fd=6  ev=POLLIN rev=0
/1:             fd=7  ev=POLLIN|POLLOUT rev=POLLIN
/1:     17.3166 poll(0x00049DD8, 3, 35000)                      = 1
/1:             fd=3  ev=POLLIN rev=0
/1:             fd=6  ev=POLLIN rev=0
/1:             fd=7  ev=POLLIN|POLLOUT rev=POLLOUT
/1:     17.3229 write(7, "1703\0\0188CBEC9 : O\t u".., 16442)   = 16442
/1:     17.3234 poll(0x00049DD8, 4, 35000)                      = 1
/1:             fd=3  ev=POLLIN rev=0
/1:             fd=6  ev=POLLIN rev=0
/1:             fd=8  ev=POLLIN rev=POLLIN
/1:             fd=7  ev=POLLIN rev=0

So far, so good.

/1:     17.3238 read(8, "\t\t\t\r\n\t\t\t\r\n\t\t".., 16384)    = 16384
/1:     17.3240 poll(0x00049DD8, 3, 35000)                      = 1
/1:             fd=3  ev=POLLIN rev=0
/1:             fd=6  ev=POLLIN rev=0
/1:             fd=7  ev=POLLIN|POLLOUT rev=POLLOUT
/1:     17.3299 write(7, "1703\0\018ED 1AD91A888 i".., 16442)   = 14480

For whatever reason, the write() was only partial. I'm guessing n/w
issues, as the client is a loooong way away ;-)

/1:     17.3303 write(7, " fE3DDA8FE ! i8DD8\fEBEC".., 1962)    Err#11 EAGAIN
/1:     17.3308 write(2, 0x00071D60, 74)                        = 74
/1:        2 0 0 5 . 1 0 . 2 4   1 4 : 5 0 : 3 0   L O G 7 [ 2 0 6 4 7 : 2
/1:        ] :   S S L _ w r i t e   r e t u r n e d   W A N T _ W R I T E
/1:        :   r e t r y i n g
/1:     17.3312 write(2, "\n", 1)                               = 1
/1:     17.3315 read(7, 0x000778D8, 5)                          Err#11 EAGAIN
/1:     17.3318 write(2, 0x00071D60, 72)                        = 72
/1:        2 0 0 5 . 1 0 . 2 4   1 4 : 5 0 : 3 0   L O G 7 [ 2 0 6 4 7 : 2
/1:        ] :   S S L _ r e a d   r e t u r n e d   W A N T _ R E A D :
/1:        r e t r y i n g
/1:     17.3321 write(2, "\n", 1)                               = 1

So we've now done an SSL_write, which yielded SSL_ERROR_WANT_WRITE,
            _and_ an SSL_read,  which yielded SSL_ERROR_WANT_READ,
(and which I think removes the SSL_ERROR_WANT_WRITE condition, as we can
only have one or the other.)

This means that, the next time round the loop (in client.c:transfer()),
want_rd is TRUE, want_wr is FALSE, so we don't poll the SSL connection for
output, only input:

/1:     poll(0x00049DD8, 3, 35000)      (sleeping...)
/1:             fd=3  ev=POLLIN rev=0
/1:             fd=6  ev=POLLIN rev=0
/1:             fd=7  ev=POLLIN rev=POLLOUT

But there won't be any input (trust me on that!), so we time out ...

/1:     52.3387 poll(0x00049DD8, 3, 35000)                      = 0
/1:             fd=3  ev=POLLIN rev=0
/1:             fd=6  ev=POLLIN rev=0
/1:             fd=7  ev=POLLIN rev=0
/1:     52.3394 write(2, 0x00071D60, 72)                        = 72
/1:        2 0 0 5 . 1 0 . 2 4   1 4 : 5 1 : 0 5   L O G 6 [ 2 0 6 4 7 : 2
/1:        ] :   s _ p o l l _ w a i t   t i m e o u t :   c o n n e c t i
/1:        o n   r e s e t
/1:     52.3399 write(2, "\n", 1)                               = 1
/1:     52.3403 write(2, 0x00071DD0, 102)                       = 102
/1:        2 0 0 5 . 1 0 . 2 4   1 4 : 5 1 : 0 5   L O G 5 [ 2 0 6 4 7 : 2
/1:        ] :   C o n n e c t i o n   r e s e t :   5 7 6 1 7   b y t e s
/1:          s e n t   t o   S S L ,   1 3 1   b y t e s   s e n t   t o
/1:        s o c k e t


Now I have never before needed (nor wanted!) to delve into the inner
workings of either stunnel or OpenSSL, so I may be in completely the wrong
ballpark here. But I cannot understand the logic of the following bit of
code in transfer() :-

        if((c->sock_ptr && !want_rd) || /* socket input buffer not empty */
                ssl_closing==CL_INIT /* need to send close_notify */ ||
                ((c->ssl_ptr<BUFFSIZE || ssl_closing==CL_RETRY) && want_wr))
                /* want to SSL_read or SSL_shutdown but write to the
                 * underlying socket needed for the SSL protocol */
            s_poll_add(&c->fds, c->ssl_wfd->fd, 0, 1);

In particular, if I change the first line to

        if(c->sock_ptr || /* socket input buffer not empty */

then everything starts working (correctly as far as I can see). The
OpenSSL man pages seem (to me) to say that it is perfectly permissible to
call SSL_write when we have SSL_ERROR_WANT_READ.

Help?


TIA,
 Richard Hall





More information about the stunnel-users mailing list