diff options
author | Alexey Shchepin <alexey@process-one.net> | 2005-11-03 05:04:54 +0000 |
---|---|---|
committer | Alexey Shchepin <alexey@process-one.net> | 2005-11-03 05:04:54 +0000 |
commit | f6343f01f7db7aa46658ce6ad580e96cc2710478 (patch) | |
tree | cdf133e5090307934dee3bb7f57fd723046fad36 /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.in | 6 | ||||
-rw-r--r-- | src/tls/XmppAddr.asn1 | 14 | ||||
-rw-r--r-- | src/tls/tls.erl | 42 | ||||
-rw-r--r-- | src/tls/tls_drv.c | 48 |
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); |