25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-22 17:28:25 +01:00

* src/tls/tls_drv.c: Added freeing of SSL stuff

* src/xml_stream.erl: Added start/2 function
* src/ejabberd_receiver.erl: Now using xml_stream:start/2

SVN Revision: 250
This commit is contained in:
Alexey Shchepin 2004-07-28 20:08:53 +00:00
parent e10fc255aa
commit 76f00658f2
6 changed files with 135 additions and 76 deletions

View File

@ -1,3 +1,17 @@
2004-07-28 Alexey Shchepin <alexey@sevcom.net>
* src/tls/tls_drv.c: Added freeing of SSL stuff
* src/xml_stream.erl: Added start/2 function
* src/ejabberd_receiver.erl: Now using xml_stream:start/2
2004-07-27 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_c2s.erl: Support for TLS library (not completed)
* src/tls/tls_drv.c: Updated to return binaries instead of lists
* src/tls/tls.erl: Likewise
2004-07-26 Alexey Shchepin <alexey@sevcom.net> 2004-07-26 Alexey Shchepin <alexey@sevcom.net>
* src/tls/tls.erl: Updated * src/tls/tls.erl: Updated

View File

@ -45,6 +45,9 @@
sasl_state, sasl_state,
access, access,
shaper, shaper,
tls = false,
tls_enabled = false,
tls_options = [],
authentificated = false, authentificated = false,
jid, jid,
user = "", server = ?MYNAME, resource = "", user = "", server = ?MYNAME, resource = "",
@ -107,7 +110,6 @@ get_presence(FsmRef) ->
%% {stop, StopReason} %% {stop, StopReason}
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
init([{SockMod, Socket}, Opts]) -> init([{SockMod, Socket}, Opts]) ->
ReceiverPid = ejabberd_receiver:start(Socket, SockMod, none),
Access = case lists:keysearch(access, 1, Opts) of Access = case lists:keysearch(access, 1, Opts) of
{value, {_, A}} -> A; {value, {_, A}} -> A;
_ -> all _ -> all
@ -116,12 +118,31 @@ init([{SockMod, Socket}, Opts]) ->
{value, {_, S}} -> S; {value, {_, S}} -> S;
_ -> none _ -> none
end, end,
{ok, wait_for_stream, #state{socket = Socket, TLS = lists:member(tls, Opts),
sockmod = SockMod, TLSEnabled = lists:member(tls_from_start, Opts),
receiver = ReceiverPid, TLSOpts = lists:filter(fun({certfile, _}) -> true;
streamid = new_id(), (_) -> false
access = Access, end, Opts),
shaper = Shaper}}. {SockMod1, Socket1, ReceiverPid} =
if
TLSEnabled ->
{ok, TLSSocket} = tls:tcp_to_tls(Socket, TLSOpts),
RecPid = ejabberd_receiver:start(TLSSocket, tls, none),
{tls, TLSSocket, RecPid};
true ->
RecPid = ejabberd_receiver:start(Socket, SockMod, none),
{SockMod, Socket, RecPid}
end,
{ok, wait_for_stream, #state{socket = Socket1,
sockmod = SockMod1,
receiver = ReceiverPid,
tls = TLS,
tls_enabled = TLSEnabled,
tls_options = TLSOpts,
streamid = new_id(),
access = Access,
shaper = Shaper}}.
%%---------------------------------------------------------------------- %%----------------------------------------------------------------------
%% Func: StateName/2 %% Func: StateName/2

View File

@ -23,7 +23,7 @@ start(Socket, SockMod, Shaper) ->
receiver(Socket, SockMod, Shaper, C2SPid) -> receiver(Socket, SockMod, Shaper, C2SPid) ->
XMLStreamPid = xml_stream:start(C2SPid), XMLStreamPid = xml_stream:start(self(), C2SPid),
ShaperState = shaper:new(Shaper), ShaperState = shaper:new(Shaper),
Timeout = case SockMod of Timeout = case SockMod of
ssl -> ssl ->
@ -46,7 +46,7 @@ receiver(Socket, SockMod, ShaperState, C2SPid, XMLStreamPid, Timeout) ->
XMLStreamPid1 = receive XMLStreamPid1 = receive
reset_stream -> reset_stream ->
exit(XMLStreamPid, closed), exit(XMLStreamPid, closed),
xml_stream:start(C2SPid) xml_stream:start(self(), C2SPid)
after 0 -> after 0 ->
XMLStreamPid XMLStreamPid
end, end,

View File

@ -46,12 +46,12 @@ init([]) ->
Port = open_port({spawn, tls_drv}, [binary]), Port = open_port({spawn, tls_drv}, [binary]),
Res = port_control(Port, ?SET_CERTIFICATE_FILE, "./ssl.pem" ++ [0]), Res = port_control(Port, ?SET_CERTIFICATE_FILE, "./ssl.pem" ++ [0]),
case Res of case Res of
[0] -> <<0>> ->
%ets:new(iconv_table, [set, public, named_table]), %ets:new(iconv_table, [set, public, named_table]),
%ets:insert(iconv_table, {port, Port}), %ets:insert(iconv_table, {port, Port}),
{ok, Port}; {ok, Port};
[1 | Error] -> <<1, Error/binary>> ->
{error, Error} {error, binary_to_list(Error)}
end. end.
@ -84,14 +84,15 @@ terminate(_Reason, Port) ->
tcp_to_tls(TCPSocket, Options) -> tcp_to_tls(TCPSocket, Options) ->
case lists:keysearch(certfile, 1, Options) of case lists:keysearch(certfile, 1, Options) of
{value, {certfile, CertFile}} -> {value, {certfile, CertFile}} ->
ok = erl_ddll:load_driver(ejabberd:get_so_path(), tls_drv),
Port = open_port({spawn, tls_drv}, [binary]), Port = open_port({spawn, tls_drv}, [binary]),
io:format("open_port: ~p~n", [Port]), io:format("open_port: ~p~n", [Port]),
case port_control(Port, ?SET_CERTIFICATE_FILE, case port_control(Port, ?SET_CERTIFICATE_FILE,
CertFile ++ [0]) of CertFile ++ [0]) of
[0] -> <<0>> ->
{ok, #tlssock{tcpsock = TCPSocket, tlsport = Port}}; {ok, #tlssock{tcpsock = TCPSocket, tlsport = Port}};
[1 | Error] -> <<1, Error/binary>> ->
{error, Error} {error, binary_to_list(Error)}
end; end;
false -> false ->
{error, no_certfile} {error, no_certfile}
@ -107,40 +108,41 @@ recv(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Length, Timeout) ->
case gen_tcp:recv(TCPSocket, Length, Timeout) of case gen_tcp:recv(TCPSocket, Length, Timeout) of
{ok, Packet} -> {ok, Packet} ->
case port_control(Port, ?SET_ENCRYPTED_INPUT, Packet) of case port_control(Port, ?SET_ENCRYPTED_INPUT, Packet) of
[0] -> <<0>> ->
case port_control(Port, ?GET_DECRYPTED_INPUT, []) of case port_control(Port, ?GET_DECRYPTED_INPUT, []) of
[0 | In] -> <<0, In/binary>> ->
case port_control(Port, ?GET_ENCRYPTED_OUTPUT, []) of case port_control(Port, ?GET_ENCRYPTED_OUTPUT, []) of
[0 | Out] -> <<0, Out/binary>> ->
case gen_tcp:send(TCPSocket, Out) of case gen_tcp:send(TCPSocket, Out) of
ok -> ok ->
{ok, In}; {ok, In};
Error -> Error ->
Error Error
end; end;
[1 | Error] -> <<1, Error/binary>> ->
{error, Error} {error, binary_to_list(Error)}
end; end;
[1 | Error] -> <<1, Error/binary>> ->
{error, Error} {error, binary_to_list(Error)}
end; end;
[1 | Error] -> <<1, Error/binary>> ->
{error, Error} {error, binary_to_list(Error)}
end; end;
{error, _Reason} = Error -> {error, _Reason} = Error ->
Error Error
end. end.
send(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet) -> send(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet) ->
case port_control(Port, ?SET_DECRYPTED_OUTPUT, Packet) of case port_control(Port, ?SET_DECRYPTED_OUTPUT, Packet) of
[0] -> <<0>> ->
case port_control(Port, ?GET_ENCRYPTED_OUTPUT, []) of case port_control(Port, ?GET_ENCRYPTED_OUTPUT, []) of
[0 | Out] -> <<0, Out/binary>> ->
gen_tcp:send(TCPSocket, Out); gen_tcp:send(TCPSocket, Out);
[1 | Error] -> <<1, Error/binary>> ->
{error, Error} {error, binary_to_list(Error)}
end; end;
[1 | Error] -> <<1, Error/binary>> ->
{error, Error} {error, binary_to_list(Error)}
end. end.
@ -171,24 +173,24 @@ loop(Port, Socket) ->
{tcp, Socket, Data} -> {tcp, Socket, Data} ->
%io:format("read: ~p~n", [Data]), %io:format("read: ~p~n", [Data]),
Res = port_control(Port, ?SET_ENCRYPTED_INPUT, Data), Res = port_control(Port, ?SET_ENCRYPTED_INPUT, Data),
%io:format("SET_ENCRYPTED_INPUT: ~p~n", [Res]), io:format("SET_ENCRYPTED_INPUT: ~p~n", [Res]),
DIRes = port_control(Port, ?GET_DECRYPTED_INPUT, Data), DIRes = port_control(Port, ?GET_DECRYPTED_INPUT, Data),
%io:format("GET_DECRYPTED_INPUT: ~p~n", [DIRes]), io:format("GET_DECRYPTED_INPUT: ~p~n", [DIRes]),
case DIRes of case DIRes of
[0 | In] -> <<0, In/binary>> ->
io:format("input: ~s~n", [In]); io:format("input: ~s~n", [binary_to_list(In)]);
[1 | DIError] -> <<1, DIError/binary>> ->
io:format("GET_DECRYPTED_INPUT error: ~p~n", [DIError]) io:format("GET_DECRYPTED_INPUT error: ~p~n", [binary_to_list(DIError)])
end, end,
EORes = port_control(Port, ?GET_ENCRYPTED_OUTPUT, Data), EORes = port_control(Port, ?GET_ENCRYPTED_OUTPUT, Data),
%io:format("GET_ENCRYPTED_OUTPUT: ~p~n", [EORes]), io:format("GET_ENCRYPTED_OUTPUT: ~p~n", [EORes]),
case EORes of case EORes of
[0 | Out] -> <<0, Out/binary>> ->
gen_tcp:send(Socket, Out); gen_tcp:send(Socket, Out);
[1 | EOError] -> <<1, EOError/binary>> ->
io:format("GET_ENCRYPTED_OUTPUT error: ~p~n", [EOError]) io:format("GET_ENCRYPTED_OUTPUT error: ~p~n", [binary_to_list(EOError)])
end, end,

View File

@ -26,13 +26,21 @@ static ErlDrvData tls_drv_start(ErlDrvPort port, char *buff)
d->bio_write = NULL; d->bio_write = NULL;
d->ssl = NULL; d->ssl = NULL;
set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY);
return (ErlDrvData)d; return (ErlDrvData)d;
} }
static void tls_drv_stop(ErlDrvData handle) static void tls_drv_stop(ErlDrvData handle)
{ {
// TODO tls_data *d = (tls_data *)handle;
//XML_ParserFree(((tls_data *)handle)->parser);
if (d->ssl != NULL)
SSL_free(d->ssl);
if (d->ctx != NULL)
SSL_CTX_free(d->ctx);
driver_free((char *)handle); driver_free((char *)handle);
} }
@ -43,17 +51,16 @@ static void tls_drv_stop(ErlDrvData handle)
#define GET_ENCRYPTED_OUTPUT 4 #define GET_ENCRYPTED_OUTPUT 4
#define GET_DECRYPTED_INPUT 5 #define GET_DECRYPTED_INPUT 5
#define DECRYPTED_INPUT 1
#define ENCRYPTED_OUTPUT 2
#define die_unless(cond, errstr) \ #define die_unless(cond, errstr) \
if (!(cond)) \ if (!(cond)) \
{ \ { \
rlen = strlen(errstr) + 1; \ rlen = strlen(errstr) + 1; \
*rbuf = driver_alloc(rlen); \ b = driver_alloc_binary(rlen); \
*rbuf[0] = 1; \ b->orig_bytes[0] = 1; \
strncpy(*rbuf + 1, errstr, rlen - 1); \ strncpy(b->orig_bytes + 1, errstr, rlen - 1); \
return rlen; \ *rbuf = (char *)b; \
return rlen; \
} }
@ -65,6 +72,7 @@ static int tls_drv_control(ErlDrvData handle,
tls_data *d = (tls_data *)handle; tls_data *d = (tls_data *)handle;
int res; int res;
int size; int size;
ErlDrvBinary *b;
switch (command) switch (command)
{ {
@ -92,48 +100,54 @@ static int tls_drv_control(ErlDrvData handle,
SSL_set_accept_state(d->ssl); SSL_set_accept_state(d->ssl);
break; break;
case SET_ENCRYPTED_INPUT: case SET_ENCRYPTED_INPUT:
die_unless(d->ssl, "SSL not initialized");
BIO_write(d->bio_read, buf, len); BIO_write(d->bio_read, buf, len);
break; break;
case SET_DECRYPTED_OUTPUT: case SET_DECRYPTED_OUTPUT:
die_unless(d->ssl, "SSL not initialized");
res = SSL_write(d->ssl, buf, len); res = SSL_write(d->ssl, buf, len);
break; break;
case GET_ENCRYPTED_OUTPUT: case GET_ENCRYPTED_OUTPUT:
die_unless(d->ssl, "SSL not initialized");
size = BUF_SIZE + 1; size = BUF_SIZE + 1;
rlen = 1; rlen = 1;
*rbuf = driver_alloc(size); b = driver_alloc_binary(size);
*rbuf[0] = 0; b->orig_bytes[0] = 0;
while ((res = BIO_read(d->bio_write, *rbuf + rlen, BUF_SIZE)) > 0) while ((res = BIO_read(d->bio_write,
b->orig_bytes + rlen, BUF_SIZE)) > 0)
{ {
printf("%d bytes of encrypted data read from state machine\r\n", res); //printf("%d bytes of encrypted data read from state machine\r\n", res);
rlen += res; rlen += res;
size += BUF_SIZE; size += BUF_SIZE;
*rbuf = driver_realloc(*rbuf, size); b = driver_realloc_binary(b, size);
} }
b = driver_realloc_binary(b, rlen);
*rbuf = (char *)b;
return rlen; return rlen;
case GET_DECRYPTED_INPUT: case GET_DECRYPTED_INPUT:
if (!SSL_is_init_finished(d->ssl)) if (!SSL_is_init_finished(d->ssl))
{ {
printf("Doing SSL_accept\r\n"); //printf("Doing SSL_accept\r\n");
res = SSL_accept(d->ssl); res = SSL_accept(d->ssl);
if (res == 0) //if (res == 0)
printf("SSL_accept returned zero\r\n"); // printf("SSL_accept returned zero\r\n");
if (res < 0) if (res < 0)
die_unless(SSL_get_error(d->ssl, res) == SSL_ERROR_WANT_READ, die_unless(SSL_get_error(d->ssl, res) == SSL_ERROR_WANT_READ,
"SSL_accept failed"); "SSL_accept failed");
} else { } else {
size = BUF_SIZE + 1; size = BUF_SIZE + 1;
rlen = 1; rlen = 1;
*rbuf = driver_alloc(size); b = driver_alloc_binary(size);
*rbuf[0] = 0; b->orig_bytes[0] = 0;
while ((res = SSL_read(d->ssl,
while ((res = SSL_read(d->ssl, *rbuf + rlen, BUF_SIZE)) > 0) b->orig_bytes + rlen, BUF_SIZE)) > 0)
{ {
printf("%d bytes of decrypted data read from state machine\r\n",res); //printf("%d bytes of decrypted data read from state machine\r\n",res);
rlen += res; rlen += res;
size += BUF_SIZE; size += BUF_SIZE;
*rbuf = driver_realloc(*rbuf, size); b = driver_realloc_binary(b, size);
} }
if (res < 0) if (res < 0)
@ -142,23 +156,21 @@ static int tls_drv_control(ErlDrvData handle,
if (err == SSL_ERROR_WANT_READ) if (err == SSL_ERROR_WANT_READ)
{ {
printf("SSL_read wants more data\r\n"); //printf("SSL_read wants more data\r\n");
//return 0; //return 0;
} }
// TODO // TODO
} }
b = driver_realloc_binary(b, rlen);
*rbuf = (char *)b;
return rlen; return rlen;
} }
break; break;
} }
if (command == SET_ENCRYPTED_INPUT || command == SET_DECRYPTED_OUTPUT) b = driver_alloc_binary(1);
{ b->orig_bytes[0] = 0;
*rbuf = (char *)b;
}
*rbuf = driver_alloc(1);
*rbuf[0] = 0;
return 1; return 1;
} }

View File

@ -10,7 +10,7 @@
-author('alexey@sevcom.net'). -author('alexey@sevcom.net').
-vsn('$Revision$ '). -vsn('$Revision$ ').
-export([start/1, init/1, send_text/2]). -export([start/1, start/2, init/1, init/2, send_text/2]).
-define(XML_START, 0). -define(XML_START, 0).
-define(XML_END, 1). -define(XML_END, 1).
@ -20,10 +20,18 @@
start(CallbackPid) -> start(CallbackPid) ->
spawn(?MODULE, init, [CallbackPid]). spawn(?MODULE, init, [CallbackPid]).
start(Receiver, CallbackPid) ->
spawn(?MODULE, init, [Receiver, CallbackPid]).
init(CallbackPid) -> init(CallbackPid) ->
Port = open_port({spawn, expat_erl}, [binary]), Port = open_port({spawn, expat_erl}, [binary]),
loop(CallbackPid, Port, []). loop(CallbackPid, Port, []).
init(Receiver, CallbackPid) ->
erlang:monitor(process, Receiver),
Port = open_port({spawn, expat_erl}, [binary]),
loop(CallbackPid, Port, []).
loop(CallbackPid, Port, Stack) -> loop(CallbackPid, Port, Stack) ->
receive receive
{Port, {data, Bin}} -> {Port, {data, Bin}} ->
@ -31,7 +39,9 @@ loop(CallbackPid, Port, Stack) ->
loop(CallbackPid, Port, process_data(CallbackPid, Stack, Data)); loop(CallbackPid, Port, process_data(CallbackPid, Stack, Data));
{_From, {send, Str}} -> {_From, {send, Str}} ->
Port ! {self(), {command, Str}}, Port ! {self(), {command, Str}},
loop(CallbackPid, Port, Stack) loop(CallbackPid, Port, Stack);
{'DOWN', _Ref, _Type, _Object, _Info} ->
ok
end. end.
process_data(CallbackPid, Stack, Data) -> process_data(CallbackPid, Stack, Data) ->