Last active
August 29, 2015 14:00
-
-
Save weiss/11379060 to your computer and use it in GitHub Desktop.
Shortened version of the patch submitted as ejabberd pull request #185
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl | |
index 057c60a..eb98943 100644 | |
--- a/src/ejabberd_s2s.erl | |
+++ b/src/ejabberd_s2s.erl | |
@@ -207,6 +216,31 @@ try_register(FromTo) -> | |
dirty_get_connections() -> | |
mnesia:dirty_all_keys(s2s). | |
+check_peer_certificate(SockMod, Sock, Peer) -> | |
+ case SockMod:get_peer_certificate(Sock) of | |
+ {ok, Cert} -> | |
+ case SockMod:get_verify_result(Sock) of | |
+ 0 -> | |
+ case idna:domain_utf8_to_ascii(Peer) of | |
+ false -> | |
+ {error, <<"Cannot decode remote server name">>}; | |
+ AsciiPeer -> | |
+ case | |
+ lists:any(fun(D) -> match_domain(AsciiPeer, D) end, | |
+ get_cert_domains(Cert)) of | |
+ true -> | |
+ {ok, <<"Verification successful">>}; | |
+ false -> | |
+ {error, <<"Certificate host name mismatch">>} | |
+ end | |
+ end; | |
+ VerifyRes -> | |
+ {error, p1_tls:get_cert_verify_string(VerifyRes, Cert)} | |
+ end; | |
+ error -> | |
+ {error, <<"Cannot get peer certificate">>} | |
+ end. | |
+ | |
%%==================================================================== | |
%% gen_server callbacks | |
%%==================================================================== | |
diff --git a/src/ejabberd_s2s_in.erl b/src/ejabberd_s2s_in.erl | |
index 3eb0b71..c490704 100644 | |
--- a/src/ejabberd_s2s_in.erl | |
+++ b/src/ejabberd_s2s_in.erl | |
@@ -227,45 +218,11 @@ wait_for_stream({xmlstreamstart, _Name, Attrs}, | |
Auth = if StateData#state.tls_enabled -> | |
case jlib:nameprep(xml:get_attr_s(<<"from">>, Attrs)) of | |
From when From /= <<"">>, From /= error -> | |
- case | |
- (StateData#state.sockmod):get_peer_certificate(StateData#state.socket) | |
- of | |
- {ok, Cert} -> | |
- case | |
- (StateData#state.sockmod):get_verify_result(StateData#state.socket) | |
- of | |
- 0 -> | |
- case | |
- idna:domain_utf8_to_ascii(From) | |
- of | |
- false -> | |
- {error, From, | |
- <<"Cannot decode 'from' attribute">>}; | |
- PCAuthDomain -> | |
- case | |
- lists:any(fun (D) -> | |
- match_domain(PCAuthDomain, | |
- D) | |
- end, | |
- get_cert_domains(Cert)) | |
- of | |
- true -> | |
- {ok, From, | |
- <<"Success">>}; | |
- false -> | |
- {error, From, | |
- <<"Certificate host name mismatch">>} | |
- end | |
- end; | |
- CertVerifyRes -> | |
- {error, From, | |
- p1_tls:get_cert_verify_string(CertVerifyRes, | |
- Cert)} | |
- end; | |
- error -> | |
- {error, From, | |
- <<"Cannot get peer certificate">>} | |
- end; | |
+ {Result, Message} = | |
+ ejabberd_s2s:check_peer_certificate(StateData#state.sockmod, | |
+ StateData#state.socket, | |
+ From), | |
+ {Result, From, Message}; | |
_ -> | |
{error, <<"(unknown)">>, | |
<<"Got no valid 'from' attribute">>} | |
diff --git a/src/ejabberd_s2s_out.erl b/src/ejabberd_s2s_out.erl | |
index a0a8363..9977fcd 100644 | |
--- a/src/ejabberd_s2s_out.erl | |
+++ b/src/ejabberd_s2s_out.erl | |
@@ -345,35 +345,57 @@ open_socket2(Type, Addr, Port) -> | |
wait_for_stream({xmlstreamstart, _Name, Attrs}, | |
StateData) -> | |
+ {CertCheckRes, CertCheckMsg, NewStateData} = | |
+ if StateData#state.tls_certverify, StateData#state.tls_enabled -> | |
+ {Res, Msg} = | |
+ ejabberd_s2s:check_peer_certificate(ejabberd_socket, | |
+ StateData#state.socket, | |
+ StateData#state.server), | |
+ ?DEBUG("Certificate verification result for ~s: ~s", | |
+ [StateData#state.server, Msg]), | |
+ {Res, Msg, StateData#state{tls_certverify = false}}; | |
+ true -> | |
+ {no_verify, <<"Not verified">>, StateData} | |
+ end, | |
case {xml:get_attr_s(<<"xmlns">>, Attrs), | |
xml:get_attr_s(<<"xmlns:db">>, Attrs), | |
xml:get_attr_s(<<"version">>, Attrs) == <<"1.0">>} | |
of | |
+ _ when CertCheckRes == error -> | |
+ send_text(NewStateData, | |
+ <<(xml:element_to_binary(?SERRT_POLICY_VIOLATION(<<"en">>, | |
+ CertCheckMsg)))/binary, | |
+ (?STREAM_TRAILER)/binary>>), | |
+ ?INFO_MSG("Closing s2s connection: ~s -> ~s (~s)", | |
+ [NewStateData#state.myname, | |
+ NewStateData#state.server, | |
+ CertCheckMsg]), | |
+ {stop, normal, NewStateData}; | |
{<<"jabber:server">>, <<"jabber:server:dialback">>, | |
false} -> | |
send_db_request(StateData); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment