[Openmcl-devel] Who uses CL+SSL and CCL?

Gary Byers gb at clozure.com
Thu Jan 15 17:59:32 PST 2009


I was able to reproduce the problem.  I know next to nothing about
using SSL; so so far I only have a very general idea of what's
going on.

Closing "client" at the end of TEST-HTTPS-SERVER calls
STREAM-FORCE-OUTPUT for flush buffered output; the STREAM-FORCE-OUTPUT
method on SSL-STREAM calls SSL-WRITE (via ENSURE-SSL-FUNCALL) to
actually write the data.  The call to SSL-WRITE fails (returns -1 to
generically indicate an error); ENSURE-SSL-FUNCALL calls SSL-GET-ERROR
to get more information about the problem.  ENSURE-SSL-FUNCALL handles
a couple of conditions that may indicate transient errors and uses
SSL-SIGNAL-ERROR to report more general failures.  (In the case that
fails, SSL-SIGNAL-ERROR reports that the return code (from SSL-GET-ERROR)
is 5 and calls that an "undocumented error."

On every system that I've looked at, "man SSL_get_error" claims that
the value 5 (SSL_ERROR_SYSCALL) indicates an underlying I/O layer 
reported by the BIO.  (Pay no attention to the BIO behind the curtain;
a reasonable guess is that this is some lower level I/O substrate on
which SSL is implemented.)  The man page notes that

"If ret == -1, the underlying BIO reported an I/O error (for socket I/O
on Unix systems, consult errno for details)."

These are Unix systems and this does involve socket I/O.  I don't
know how to portably consult errno (which is likely a C macro
that arranges to access a thread-local value), but if we're willing
to be non-portable, we can add an extra clause in ENSURE-SSL-FUNCALL
to handle errors that occur at the ... um, BIO level:

            ...
            ;; Non-portable code here, for debugging
            (#.#$SSL_ERROR_SYSCALL
             (let* ((errno (ccl::%get-errno)))
               (error "I/O error ~d on SSL handle ~s (~s)"
                      errno handle (ccl::%strerror errno))))
 	   (t
            ...

CCL::%GET-ERRNO returns the thread-local errno value.  (For obscure
reasons, it returns it negated.)   CCL::%STRERROR returns a string
which describes the error number it receives as an argument.  (This
is just a little wrapper around the similarly-named C library function,
and the "descriptive string" is often pretty generic.)

ENSURE-SSL-FUNCALL is declaimed INLINE, and so we may have to redefine
things which use it after adding the clause above.  In this case, we'd
want to redefine the STREAM-FORCE-OUTPUT method after redefining 
ENSURE-SSL-FUNCALL, to be sure that STREAM-FORCE-OUTPUT is inlining
the new definition of ENSURE-SSL-FUNCALL.  (We could also just rebuild
everything with ASDF.)

With that change in place, we get an error message that's at least
a little more informative:

> Error: I/O error -9 on SSL handle #<A Foreign Pointer #x1365B0> ("Bad file descriptor")
> While executing: #<STANDARD-METHOD STREAM-FORCE-OUTPUT (CL+SSL::SSL-STREAM)>, in process listener(1).

This error can indicate an attempt to use a file descriptor that's been
closed (or was never opened.)

TEST-HTTPS-SERVER does:

       (let* ((socket (trivial-sockets:accept-connection
 		      server
 		      :element-type '(unsigned-byte 8)))
 	     (client (cl+ssl:make-ssl-server-stream
 		      (cl+ssl:stream-fd socket)
 		      :external-format :iso-8859-1
 		      :certificate cert
 		      :key key)))

So, without looking at that too closely, it -looks- like SOCKET and
CLIENT share the same file descriptor.

Then:



 	  (close socket)  ; possibly closing the shared fd
 	  (close client)  ; possibly forcing output to the closed fd

           )))))

If that's what's going on, it can't work (or at least can't work
in general.)  If I add

           (force-output client)

just before those two CLOSE calls, I get output in the web browser and
in the listener that's running the server example, and the server
waits for the next connection.

I don't know for sure if this diagnosis is correct, but it certainly
seems like something similar to this (sharing an fd between two
streams and trying to do output - via a FORCE-OUTPUT call from CLOSE -
to the second stream after closing the first stream and closing the
underlying socket fd) is the problem.

The good news is that all of the other things that could go wrong
here (all of the SSL FFI stuff) seem to work.

Lastly, I tried this in the CCL trunk (and got the same error that you
did.)  I don't think that anything that's changed since 1.2-RC1
would affect this, but there were bug fixes between 1.2-RC1 and
the final version of 1.2, and there are post-1.2 fixes in the 1.2
tree, so you might avoid other problems by upgrading.



On Thu, 15 Jan 2009, John McAleely wrote:

> Hi,
>
> I'm trying to add support for SSL to a web server implemented in ccl.
> CL+SSL seemed like the route to follow, and at the moment I'm loading
> just its own test suite to see if I can get that to work.
>
> It appears to be capable of being a client ( (ssl-test::test-https-
> client) passes), and it can almost be a server. It seems it can accept
> and decrypt a session, but fails when it tries to write data back to
> the client.
>
> I observe identical behaviour on Mac OS X 10.5.6, and a debian/amd64
> machine (both Clozure Common Lisp Version 1.2-r9226-RC1). I suspect
> there is some missing configuration, or perhaps I have mis-configured
> one of its dependencies. Does anyone else use cl+ssl on ccl?
>
> Alternatively, is anyone doing SSL for a web server with another
> library?
>
> J
>
> Here is the output:
>
> ? (ssl-test::test-https-server)
> SSL server listening on port 8080
> HTTPS> GET / HTTP/1.1
> HTTPS> User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6;
> en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/
> 525.27.1
> HTTPS> Accept: text/xml,application/xml,application/xhtml+xml,text/
> html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
> HTTPS> Accept-Language: en-us
> HTTPS> Accept-Encoding: gzip, deflate
> HTTPS> Connection: keep-alive
> HTTPS> Host: debian-lisp.local:8080
> > Error: An I/O error occurred: undocumented reason. (return code:
> 5)SSL error queue:
> >
> > While executing: CL+SSL::SSL-SIGNAL-ERROR, in process listener(1).
> > Type :POP to abort, :R for a list of available restarts.
> > Type :? for other options.
> 1 > :b
>  (2AAAAACBB848) : 0 (SSL-SIGNAL-ERROR #<A Foreign Pointer #x684B70>
> #<Compiled-function CL+SSL::SSL-WRITE #x300040FEF01F> 5 -1) 397
>  (2AAAAACBB880) : 1 (FUNCALL #'#<#<STANDARD-METHOD STREAM-FORCE-
> OUTPUT (CL+SSL::SSL-STREAM)>> #<SSL-SERVER-STREAM for 6>) 1037
>  (2AAAAACBB908) : 2 (FORCE-OUTPUT [...]) 69
>  (2AAAAACBB920) : 3 (FUNCALL #'#<#<STANDARD-METHOD CLOSE (CL+SSL::SSL-
> STREAM)>> #<SSL-SERVER-STREAM for 6> [...]) 157
>  (2AAAAACBB950) : 4 (%%CHECK-KEYWORDS #(1 #(:ABORT) #<METHOD-FUNCTION
> CLOSE #>) 5864062285622) 245
>  (2AAAAACBB9D0) : 6 (%%CHECK-KEYWORDS #(1 #(:ABORT) #<METHOD-FUNCTION
> CLOSE #>) 5864062285637) 245
>  (2AAAAACBBA38) : 8 (TEST-HTTPS-SERVER [...]) 557
>  (2AAAAACBBAF8) : 9 (CALL-CHECK-REGS 'SSL-TEST::TEST-HTTPS-SERVER
> [...]) 229
>  (2AAAAACBBB30) : 10 (TOPLEVEL-EVAL '(SSL-TEST::TEST-HTTPS-SERVER)
> [...]) 733
>  (2AAAAACBBBD0) : 11 (READ-LOOP [...]) 1741
>  (2AAAAACBBDD8) : 12 (TOPLEVEL-LOOP) 125
>  (2AAAAACBBE08) : 13 (FUNCALL #'#<(:INTERNAL (TOPLEVEL-FUNCTION
> (CCL::LISP-DEVELOPMENT-SYSTEM T)))>) 101
>  (2AAAAACBBE20) : 14 (FUNCALL #'#<(:INTERNAL CCL::MAKE-MCL-LISTENER-
> PROCESS)>) 645
>  (2AAAAACBBEB8) : 15 (RUN-PROCESS-INITIAL-FORM #<TTY-LISTENER
> listener(1) [Active] #x300040CBAB4D> '(#)) 717
>  (2AAAAACBBF48) : 16 (FUNCALL #'#<(:INTERNAL CCL::%PROCESS-PRESET-
> INTERNAL)> #<TTY-LISTENER listener(1) [Active] #x300040CBAB4D> '(#)) 397
>  (2AAAAACBBF98) : 17 (FUNCALL #'#<(:INTERNAL CCL::THREAD-MAKE-STARTUP-
> FUNCTION)>) 293
>
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel
>
>



More information about the Openmcl-devel mailing list