diff options
author | Alexey Shchepin <alexey@process-one.net> | 2005-10-25 01:08:37 +0000 |
---|---|---|
committer | Alexey Shchepin <alexey@process-one.net> | 2005-10-25 01:08:37 +0000 |
commit | 1433dafe6bda9840cb687c5c3270584fb3ee55d1 (patch) | |
tree | 0da87012f614b5de26f1d8b28233fff4225e92c7 /src/tls | |
parent | * src/ejabberd_app.erl: Try to load tls_drv at startup to avoid (diff) |
* src/tls/tls_drv.c: Support for "connect" method
* src/tls/tls.erl: Likewise
* src/ejabberd_s2s_in.erl: Support for STARTTLS+Dialback
* src/ejabberd_s2s_out.erl: Likewise
* src/ejabberd_receiver.erl: Added a few hacks ({active,once} mode
should be used instead of recv/3 call to avoid them)
* src/ejabberd_config.erl: Added s2s_use_starttls and s2s_certfile
options
* src/ejabberd.cfg.example: Likewise
SVN Revision: 426
Diffstat (limited to '')
-rw-r--r-- | src/tls/tls.erl | 30 | ||||
-rw-r--r-- | src/tls/tls_drv.c | 44 |
2 files changed, 50 insertions, 24 deletions
diff --git a/src/tls/tls.erl b/src/tls/tls.erl index 361c92fc..e1925520 100644 --- a/src/tls/tls.erl +++ b/src/tls/tls.erl @@ -27,11 +27,12 @@ code_change/3, terminate/2]). --define(SET_CERTIFICATE_FILE, 1). --define(SET_ENCRYPTED_INPUT, 2). --define(SET_DECRYPTED_OUTPUT, 3). --define(GET_ENCRYPTED_OUTPUT, 4). --define(GET_DECRYPTED_INPUT, 5). +-define(SET_CERTIFICATE_FILE_ACCEPT, 1). +-define(SET_CERTIFICATE_FILE_CONNECT, 2). +-define(SET_ENCRYPTED_INPUT, 3). +-define(SET_DECRYPTED_OUTPUT, 4). +-define(GET_ENCRYPTED_OUTPUT, 5). +-define(GET_DECRYPTED_INPUT, 6). -record(tlssock, {tcpsock, tlsport}). @@ -44,7 +45,7 @@ start_link() -> init([]) -> ok = erl_ddll:load_driver(ejabberd:get_so_path(), tls_drv), Port = open_port({spawn, tls_drv}, [binary]), - Res = port_control(Port, ?SET_CERTIFICATE_FILE, "./ssl.pem" ++ [0]), + Res = port_control(Port, ?SET_CERTIFICATE_FILE_ACCEPT, "./ssl.pem" ++ [0]), case Res of <<0>> -> %ets:new(iconv_table, [set, public, named_table]), @@ -86,8 +87,13 @@ tcp_to_tls(TCPSocket, Options) -> {value, {certfile, CertFile}} -> ok = erl_ddll:load_driver(ejabberd:get_so_path(), tls_drv), Port = open_port({spawn, tls_drv}, [binary]), - case port_control(Port, ?SET_CERTIFICATE_FILE, - CertFile ++ [0]) of + Command = case lists:member(connect, Options) of + true -> + ?SET_CERTIFICATE_FILE_CONNECT; + false -> + ?SET_CERTIFICATE_FILE_ACCEPT + end, + case port_control(Port, Command, CertFile ++ [0]) of <<0>> -> {ok, #tlssock{tcpsock = TCPSocket, tlsport = Port}}; <<1, Error/binary>> -> @@ -145,7 +151,10 @@ send(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet) -> {error, binary_to_list(Error)} end; <<1, Error/binary>> -> - {error, binary_to_list(Error)} + {error, binary_to_list(Error)}; + <<2>> -> % Dirty hack + receive after 100 -> ok end, + send(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet) end. @@ -158,7 +167,8 @@ test() -> ok = erl_ddll:load_driver(ejabberd:get_so_path(), tls_drv), Port = open_port({spawn, tls_drv}, [binary]), io:format("open_port: ~p~n", [Port]), - PCRes = port_control(Port, ?SET_CERTIFICATE_FILE, "./ssl.pem" ++ [0]), + PCRes = port_control(Port, ?SET_CERTIFICATE_FILE_ACCEPT, + "./ssl.pem" ++ [0]), io:format("port_control: ~p~n", [PCRes]), {ok, ListenSocket} = gen_tcp:listen(1234, [binary, {packet, 0}, diff --git a/src/tls/tls_drv.c b/src/tls/tls_drv.c index f320ee31..608830ff 100644 --- a/src/tls/tls_drv.c +++ b/src/tls/tls_drv.c @@ -4,6 +4,7 @@ #include <string.h> #include <erl_driver.h> #include <openssl/ssl.h> +#include <openssl/err.h> #define BUF_SIZE 1024 @@ -45,11 +46,12 @@ static void tls_drv_stop(ErlDrvData handle) } -#define SET_CERTIFICATE_FILE 1 -#define SET_ENCRYPTED_INPUT 2 -#define SET_DECRYPTED_OUTPUT 3 -#define GET_ENCRYPTED_OUTPUT 4 -#define GET_DECRYPTED_INPUT 5 +#define SET_CERTIFICATE_FILE_ACCEPT 1 +#define SET_CERTIFICATE_FILE_CONNECT 2 +#define SET_ENCRYPTED_INPUT 3 +#define SET_DECRYPTED_OUTPUT 4 +#define GET_ENCRYPTED_OUTPUT 5 +#define GET_DECRYPTED_INPUT 6 #define die_unless(cond, errstr) \ @@ -76,8 +78,9 @@ static int tls_drv_control(ErlDrvData handle, switch (command) { - case SET_CERTIFICATE_FILE: - d->ctx = SSL_CTX_new(SSLv23_server_method()); + case SET_CERTIFICATE_FILE_ACCEPT: + case SET_CERTIFICATE_FILE_CONNECT: + d->ctx = SSL_CTX_new(SSLv23_method()); die_unless(d->ctx, "SSL_CTX_new failed"); res = SSL_CTX_use_certificate_file(d->ctx, buf, SSL_FILETYPE_PEM); @@ -97,7 +100,10 @@ static int tls_drv_control(ErlDrvData handle, SSL_set_bio(d->ssl, d->bio_read, d->bio_write); - SSL_set_accept_state(d->ssl); + if (command == SET_CERTIFICATE_FILE_ACCEPT) + SSL_set_accept_state(d->ssl); + else + SSL_set_connect_state(d->ssl); break; case SET_ENCRYPTED_INPUT: die_unless(d->ssl, "SSL not initialized"); @@ -106,6 +112,19 @@ static int tls_drv_control(ErlDrvData handle, case SET_DECRYPTED_OUTPUT: die_unless(d->ssl, "SSL not initialized"); res = SSL_write(d->ssl, buf, len); + if (res <= 0) + { + res = SSL_get_error(d->ssl, res); + if (res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE) + { + b = driver_alloc_binary(1); + b->orig_bytes[0] = 2; + *rbuf = (char *)b; + return 1; + } else { + die_unless(0, "SSL_write failed"); + } + } break; case GET_ENCRYPTED_OUTPUT: die_unless(d->ssl, "SSL not initialized"); @@ -128,13 +147,10 @@ static int tls_drv_control(ErlDrvData handle, case GET_DECRYPTED_INPUT: if (!SSL_is_init_finished(d->ssl)) { - //printf("Doing SSL_accept\r\n"); - res = SSL_accept(d->ssl); - //if (res == 0) - // printf("SSL_accept returned zero\r\n"); - if (res < 0) + res = SSL_do_handshake(d->ssl); + if (res <= 0) die_unless(SSL_get_error(d->ssl, res) == SSL_ERROR_WANT_READ, - "SSL_accept failed"); + "SSL_do_handshake failed"); } else { size = BUF_SIZE + 1; rlen = 1; |