summaryrefslogtreecommitdiff
path: root/src/tls
diff options
context:
space:
mode:
authorAlexey Shchepin <alexey@process-one.net>2005-11-03 05:04:54 +0000
committerAlexey Shchepin <alexey@process-one.net>2005-11-03 05:04:54 +0000
commitf6343f01f7db7aa46658ce6ad580e96cc2710478 (patch)
treecdf133e5090307934dee3bb7f57fd723046fad36 /src/tls
parent* src/mod_disco.erl: Minor fix (diff)
* src/ejabberd_s2s_out.erl: Support for STARTTLS+SASL EXTERNAL
* src/ejabberd_s2s_in.erl: Likewise * src/tls/tls.erl: Likewise * src/tls/tls_drv.c: Likewise * src/tls/XmppAddr.asn1: Likewise * src/tls/Makefile.in: Likewise SVN Revision: 430
Diffstat (limited to '')
-rw-r--r--src/tls/Makefile.in6
-rw-r--r--src/tls/XmppAddr.asn114
-rw-r--r--src/tls/tls.erl42
-rw-r--r--src/tls/tls_drv.c48
4 files changed, 102 insertions, 8 deletions
diff --git a/src/tls/Makefile.in b/src/tls/Makefile.in
index e0ebd5d4..936747fe 100644
--- a/src/tls/Makefile.in
+++ b/src/tls/Makefile.in
@@ -12,14 +12,18 @@ ERLSHLIBS = ../tls_drv.so
OUTDIR = ..
EFLAGS = -I .. -pz ..
+ASN_FLAGS = -bber_bin +der +compact_bit_string +optimize +noobj
OBJS = \
- $(OUTDIR)/tls.beam
+ $(OUTDIR)/tls.beam $(OUTDIR)/XmppAddr.beam
all: $(OBJS) $(ERLSHLIBS)
$(OUTDIR)/%.beam: %.erl
@ERLC@ -W $(EFLAGS) -o $(OUTDIR) $<
+%.erl: %.asn1
+ erlc $(ASN_FLAGS) $<
+
#all: $(ERLSHLIBS)
# erl -s make all report "{outdir, \"..\"}" -noinput -s erlang halt
diff --git a/src/tls/XmppAddr.asn1 b/src/tls/XmppAddr.asn1
new file mode 100644
index 00000000..14f350d3
--- /dev/null
+++ b/src/tls/XmppAddr.asn1
@@ -0,0 +1,14 @@
+XmppAddr { iso(1) identified-organization(3)
+ dod(6) internet(1) security(5) mechanisms(5) pkix(7)
+ id-on(8) id-on-xmppAddr(5) }
+
+DEFINITIONS EXPLICIT TAGS ::=
+BEGIN
+
+id-on-xmppAddr OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+ dod(6) internet(1) security(5) mechanisms(5) pkix(7)
+ id-on(8) 5 }
+
+XmppAddr ::= UTF8String
+
+END
diff --git a/src/tls/tls.erl b/src/tls/tls.erl
index cdd00570..7290160e 100644
--- a/src/tls/tls.erl
+++ b/src/tls/tls.erl
@@ -17,6 +17,8 @@
send/2,
recv/2, recv/3, recv_data/2,
close/1,
+ get_peer_certificate/1,
+ get_verify_result/1,
test/0]).
%% Internal exports, call-back functions.
@@ -33,6 +35,8 @@
-define(SET_DECRYPTED_OUTPUT, 4).
-define(GET_ENCRYPTED_OUTPUT, 5).
-define(GET_DECRYPTED_INPUT, 6).
+-define(GET_PEER_CERTIFICATE, 7).
+-define(GET_VERIFY_RESULT, 8).
-record(tlssock, {tcpsock, tlsport}).
@@ -69,15 +73,16 @@ handle_call(_, _, State) ->
handle_cast(_, State) ->
{noreply, State}.
-handle_info({'EXIT', Pid, Reason}, Port) ->
- {noreply, Port};
-
handle_info({'EXIT', Port, Reason}, Port) ->
{stop, {port_died, Reason}, Port};
+
+handle_info({'EXIT', _Pid, _Reason}, Port) ->
+ {noreply, Port};
+
handle_info(_, State) ->
{noreply, State}.
-code_change(OldVsn, State, Extra) ->
+code_change(_OldVsn, State, _Extra) ->
{ok, State}.
terminate(_Reason, Port) ->
@@ -115,7 +120,7 @@ tls_to_tcp(#tlssock{tcpsock = TCPSocket, tlsport = Port}) ->
recv(Socket, Length) ->
recv(Socket, Length, infinity).
-recv(#tlssock{tcpsock = TCPSocket, tlsport = Port} = TLSSock,
+recv(#tlssock{tcpsock = TCPSocket} = TLSSock,
Length, Timeout) ->
case gen_tcp:recv(TCPSocket, Length, Timeout) of
{ok, Packet} ->
@@ -133,6 +138,7 @@ recv_data(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet) ->
<<0, Out/binary>> ->
case gen_tcp:send(TCPSocket, Out) of
ok ->
+ %io:format("IN: ~p~n", [{TCPSocket, binary_to_list(In)}]),
{ok, In};
Error ->
Error
@@ -150,6 +156,7 @@ recv_data(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet) ->
send(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet) ->
case port_control(Port, ?SET_DECRYPTED_OUTPUT, Packet) of
<<0>> ->
+ %io:format("OUT: ~p~n", [{TCPSocket, lists:flatten(Packet)}]),
case port_control(Port, ?GET_ENCRYPTED_OUTPUT, []) of
<<0, Out/binary>> ->
gen_tcp:send(TCPSocket, Out);
@@ -159,8 +166,12 @@ send(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet) ->
<<1, Error/binary>> ->
{error, binary_to_list(Error)};
<<2>> -> % Dirty hack
- receive after 100 -> ok end,
- send(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet)
+ receive
+ {timeout, _Timer, _} ->
+ {error, timeout}
+ after 100 ->
+ send(#tlssock{tcpsock = TCPSocket, tlsport = Port}, Packet)
+ end
end.
@@ -168,6 +179,23 @@ close(#tlssock{tcpsock = TCPSocket, tlsport = Port}) ->
gen_tcp:close(TCPSocket),
port_close(Port).
+get_peer_certificate(#tlssock{tlsport = Port}) ->
+ case port_control(Port, ?GET_PEER_CERTIFICATE, []) of
+ <<0, BCert/binary>> ->
+ case catch ssl_pkix:decode_cert(BCert, [pkix]) of
+ {ok, Cert} ->
+ {ok, Cert};
+ _ ->
+ error
+ end;
+ <<1>> ->
+ error
+ end.
+
+get_verify_result(#tlssock{tlsport = Port}) ->
+ <<Res>> = port_control(Port, ?GET_VERIFY_RESULT, []),
+ Res.
+
test() ->
case erl_ddll:load_driver(ejabberd:get_so_path(), tls_drv) of
diff --git a/src/tls/tls_drv.c b/src/tls/tls_drv.c
index 608830ff..742eda8f 100644
--- a/src/tls/tls_drv.c
+++ b/src/tls/tls_drv.c
@@ -46,12 +46,19 @@ static void tls_drv_stop(ErlDrvData handle)
}
+static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
+{
+ return 1;
+}
+
#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 GET_PEER_CERTIFICATE 7
+#define GET_VERIFY_RESULT 8
#define die_unless(cond, errstr) \
@@ -75,6 +82,7 @@ static int tls_drv_control(ErlDrvData handle,
int res;
int size;
ErlDrvBinary *b;
+ X509 *cert;
switch (command)
{
@@ -92,6 +100,15 @@ static int tls_drv_control(ErlDrvData handle,
res = SSL_CTX_check_private_key(d->ctx);
die_unless(res > 0, "SSL_CTX_check_private_key failed");
+ SSL_CTX_set_default_verify_paths(d->ctx);
+
+ if (command == SET_CERTIFICATE_FILE_ACCEPT)
+ {
+ SSL_CTX_set_verify(d->ctx,
+ SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
+ verify_callback);
+ }
+
d->ssl = SSL_new(d->ctx);
die_unless(d->ssl, "SSL_new failed");
@@ -182,6 +199,37 @@ static int tls_drv_control(ErlDrvData handle,
return rlen;
}
break;
+ case GET_PEER_CERTIFICATE:
+ cert = SSL_get_peer_certificate(d->ssl);
+ if (cert == NULL)
+ {
+ b = driver_alloc_binary(1);
+ b->orig_bytes[0] = 1;
+ *rbuf = (char *)b;
+ return 1;
+ } else {
+ unsigned char *tmp_buf;
+ rlen = i2d_X509(cert, NULL);
+ if (rlen >= 0)
+ {
+ rlen++;
+ b = driver_alloc_binary(rlen);
+ b->orig_bytes[0] = 0;
+ tmp_buf = &b->orig_bytes[1];
+ i2d_X509(cert, &tmp_buf);
+ X509_free(cert);
+ *rbuf = (char *)b;
+ return rlen;
+ } else
+ X509_free(cert);
+ }
+ break;
+ case GET_VERIFY_RESULT:
+ b = driver_alloc_binary(1);
+ b->orig_bytes[0] = SSL_get_verify_result(d->ssl);
+ *rbuf = (char *)b;
+ return 1;
+ break;
}
b = driver_alloc_binary(1);