factor/basis/io/unix/sockets/secure/secure.factor

175 lines
5.2 KiB
Factor
Raw Normal View History

! Copyright (C) 2007, 2008, Slava Pestov, Elie CHAFTARI.
! See http://factorcode.org/license.txt for BSD license.
2008-05-21 16:54:27 -04:00
USING: accessors unix byte-arrays kernel debugger sequences namespaces math
math.order combinators init alien alien.c-types alien.strings libc
continuations destructors
openssl openssl.libcrypto openssl.libssl
2008-05-13 19:24:46 -04:00
io.files io.ports io.unix.backend io.unix.sockets
io.encodings.ascii io.buffers io.sockets io.sockets.secure
2008-07-02 01:20:01 -04:00
io.timeouts system summary ;
IN: io.unix.sockets.secure
2008-05-14 04:55:33 -04:00
M: ssl-handle handle-fd file>> handle-fd ;
2008-05-14 04:55:33 -04:00
: syscall-error ( r -- * )
ERR_get_error dup zero? [
drop
{
2008-05-21 16:54:27 -04:00
{ -1 [ err_no ECONNRESET = [ premature-close ] [ (io-error) ] if ] }
2008-05-17 18:45:56 -04:00
{ 0 [ premature-close ] }
} case
] [
2008-05-13 19:24:46 -04:00
nip (ssl-error)
] if ;
: check-accept-response ( handle r -- event )
over handle>> over SSL_get_error
{
{ SSL_ERROR_NONE [ 2drop f ] }
{ SSL_ERROR_WANT_READ [ 2drop +input+ ] }
2008-09-28 18:56:44 -04:00
{ SSL_ERROR_WANT_ACCEPT [ 2drop +input+ ] }
{ SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
{ SSL_ERROR_SYSCALL [ syscall-error ] }
2008-09-28 18:56:44 -04:00
{ SSL_ERROR_ZERO_RETURN [ (ssl-error) ] }
{ SSL_ERROR_SSL [ (ssl-error) ] }
} case ;
: do-ssl-accept ( ssl-handle -- )
dup dup handle>> SSL_accept check-accept-response dup
[ >r dup file>> r> wait-for-fd do-ssl-accept ] [ 2drop ] if ;
: maybe-handshake ( ssl-handle -- )
dup connected>> [ drop ] [
t >>connected
[ do-ssl-accept ] with-timeout
] if ;
: check-response ( port r -- port r n )
over handle>> handle>> over SSL_get_error ; inline
! Input ports
2008-05-18 20:08:56 -04:00
: check-read-response ( port r -- event )
check-response
{
2008-05-13 19:24:46 -04:00
{ SSL_ERROR_NONE [ swap buffer>> n>buffer f ] }
2008-05-18 20:02:50 -04:00
{ SSL_ERROR_ZERO_RETURN [ 2drop f ] }
2008-05-13 19:24:46 -04:00
{ SSL_ERROR_WANT_READ [ 2drop +input+ ] }
{ SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
{ SSL_ERROR_SYSCALL [ syscall-error ] }
{ SSL_ERROR_SSL [ (ssl-error) ] }
} case ;
M: ssl-handle refill
dup maybe-handshake
2008-05-13 19:24:46 -04:00
handle>> ! ssl
over buffer>>
[ buffer-end ] ! buf
[ buffer-capacity ] bi ! len
SSL_read
check-read-response ;
! Output ports
2008-05-13 19:24:46 -04:00
: check-write-response ( port r -- event )
check-response
{
{ SSL_ERROR_NONE [ swap buffer>> buffer-consume f ] }
2008-05-13 19:24:46 -04:00
{ SSL_ERROR_WANT_READ [ 2drop +input+ ] }
{ SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
{ SSL_ERROR_SYSCALL [ syscall-error ] }
{ SSL_ERROR_SSL [ (ssl-error) ] }
} case ;
M: ssl-handle drain
dup maybe-handshake
2008-05-13 19:24:46 -04:00
handle>> ! ssl
over buffer>>
[ buffer@ ] ! buf
[ buffer-length ] bi ! len
SSL_write
check-write-response ;
M: ssl-handle cancel-operation
file>> cancel-operation ;
M: ssl-handle timeout
drop secure-socket-timeout get ;
2008-05-20 19:52:11 -04:00
! Client sockets
2008-05-14 04:55:33 -04:00
: <ssl-socket> ( fd -- ssl )
[ fd>> BIO_NOCLOSE BIO_new_socket dup ssl-error ] keep <ssl-handle>
[ handle>> swap dup SSL_set_bio ] keep ;
2008-05-17 18:45:56 -04:00
M: secure ((client)) ( addrspec -- handle )
2008-05-14 04:55:33 -04:00
addrspec>> ((client)) <ssl-socket> ;
2008-05-17 18:45:56 -04:00
M: secure parse-sockaddr addrspec>> parse-sockaddr <secure> ;
2008-05-14 00:36:15 -04:00
2008-05-17 18:45:56 -04:00
M: secure (get-local-address) addrspec>> (get-local-address) ;
2008-05-15 06:19:59 -04:00
: check-connect-response ( ssl-handle r -- event )
over handle>> over SSL_get_error
{
2008-05-13 19:24:46 -04:00
{ SSL_ERROR_NONE [ 2drop f ] }
{ SSL_ERROR_WANT_READ [ 2drop +input+ ] }
{ SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
{ SSL_ERROR_SYSCALL [ syscall-error ] }
{ SSL_ERROR_SSL [ (ssl-error) ] }
} case ;
: do-ssl-connect ( ssl-handle -- )
dup dup handle>> SSL_connect check-connect-response dup
[ dupd wait-for-fd do-ssl-connect ] [ 2drop ] if ;
2008-05-13 19:24:46 -04:00
2008-06-15 23:49:54 -04:00
: resume-session ( ssl-handle ssl-session -- )
[ [ handle>> ] dip SSL_set_session ssl-error ]
[ drop do-ssl-connect ]
2bi ;
: begin-session ( ssl-handle addrspec -- )
[ drop do-ssl-connect ]
[ [ handle>> SSL_get1_session ] dip save-session ]
2bi ;
: secure-connection ( ssl-handle addrspec -- )
dup get-session [ resume-session ] [ begin-session ] ?if ;
2008-05-17 18:45:56 -04:00
M: secure establish-connection ( client-out remote -- )
2008-06-15 23:49:54 -04:00
addrspec>>
[ establish-connection ]
[
2008-06-15 23:49:54 -04:00
[ handle>> ] dip
[ [ secure-connection ] curry with-timeout ]
[ drop t >>connected drop ]
2bi
] 2bi ;
2008-05-14 04:55:33 -04:00
2008-05-17 18:45:56 -04:00
M: secure (server) addrspec>> (server) ;
2008-05-14 04:55:33 -04:00
2008-05-17 18:45:56 -04:00
M: secure (accept)
2008-05-14 04:55:33 -04:00
[
addrspec>> (accept) >r |dispose <ssl-socket> r>
2008-05-14 04:55:33 -04:00
] with-destructors ;
: check-shutdown-response ( handle r -- event )
#! We don't do two-step shutdown here because I couldn't
#! figure out how to do it with non-blocking BIOs. Also, it
#! seems that SSL_shutdown always returns 0 -- this sounds
#! like a bug
over handle>> over SSL_get_error
2008-05-14 04:55:33 -04:00
{
{ SSL_ERROR_NONE [ 2drop f ] }
{ SSL_ERROR_WANT_READ [ 2drop +input+ ] }
{ SSL_ERROR_WANT_WRITE [ 2drop +output+ ] }
{ SSL_ERROR_SYSCALL [ dup zero? [ 2drop f ] [ syscall-error ] if ] }
{ SSL_ERROR_SSL [ (ssl-error) ] }
2008-05-14 04:55:33 -04:00
} case ;
: (shutdown) ( handle -- )
dup dup handle>> SSL_shutdown check-shutdown-response
dup [ dupd wait-for-fd (shutdown) ] [ 2drop ] if ;
2008-05-21 16:54:27 -04:00
M: ssl-handle shutdown
dup connected>> [
f >>connected [ (shutdown) ] with-timeout
] [ drop ] if ;