diff --git a/ChangeLog b/ChangeLog index 75ed56a3f..0ca87d186 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-05-05 Mickael Remond + + * src/ejabberd_c2s.erl: Added C2S blacklist support (EJAB-625). + * src/mod_ip_blacklist.erl: Likewise. + * src/jlib.erl: Added IP format tuple to string function. + * src/ejabberd_socket.erl: Properly handled c2s start failure (happen + for blacklisted IP). + 2008-05-04 Alexey Shchepin * src/ejabberd_receiver.erl: Don't activate a socket untill its diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 225bce8eb..afc70dc28 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -176,26 +176,35 @@ init([{SockMod, Socket}, Opts]) -> (_) -> false end, Opts), IP = peerip(SockMod, Socket), - Socket1 = - if - TLSEnabled -> - SockMod:starttls(Socket, TLSOpts); - true -> - Socket - end, - SocketMonitor = SockMod:monitor(Socket1), - {ok, wait_for_stream, #state{socket = Socket1, - sockmod = SockMod, - socket_monitor = SocketMonitor, - zlib = Zlib, - tls = TLS, - tls_required = StartTLSRequired, - tls_enabled = TLSEnabled, - tls_options = TLSOpts, - streamid = new_id(), - access = Access, - shaper = Shaper, - ip = IP}, ?C2S_OPEN_TIMEOUT}. + %% Check if IP is blacklisted: + case is_ip_blacklisted(IP) of + true -> + ?INFO_MSG("Connection attempt from blacklisted IP: ~s", + [jlib:ip_to_list(IP)]), + {stop, normal}; + false -> + Socket1 = + if + TLSEnabled -> + SockMod:starttls(Socket, TLSOpts); + true -> + Socket + end, + SocketMonitor = SockMod:monitor(Socket1), + {ok, wait_for_stream, #state{socket = Socket1, + sockmod = SockMod, + socket_monitor = SocketMonitor, + zlib = Zlib, + tls = TLS, + tls_required = StartTLSRequired, + tls_enabled = TLSEnabled, + tls_options = TLSOpts, + streamid = new_id(), + access = Access, + shaper = Shaper, + ip = IP}, + ?C2S_OPEN_TIMEOUT} + end. %% Return list of all available resources of contacts, %% in form [{JID, Caps}]. @@ -851,8 +860,6 @@ wait_for_session(closed, StateData) -> {stop, normal, StateData}. - - session_established({xmlstreamelement, El}, StateData) -> {xmlelement, Name, Attrs, _Els} = El, User = StateData#state.user, @@ -1954,3 +1961,7 @@ fsm_reply(Reply, session_established, StateData) -> {reply, Reply, session_established, StateData, ?C2S_HIBERNATE_TIMEOUT}; fsm_reply(Reply, StateName, StateData) -> {reply, Reply, StateName, StateData, ?C2S_OPEN_TIMEOUT}. + +%% Used by c2s blacklist plugins +is_ip_blacklisted({IP,_Port}) -> + ejabberd_hooks:run_fold(check_bl_c2s, false, [IP]). diff --git a/src/ejabberd_socket.erl b/src/ejabberd_socket.erl index f94a0a0e1..389b3a106 100644 --- a/src/ejabberd_socket.erl +++ b/src/ejabberd_socket.erl @@ -65,19 +65,27 @@ start(Module, SockMod, Socket, Opts) -> SocketData = #socket_state{sockmod = SockMod, socket = Socket, receiver = Receiver}, - {ok, Pid} = Module:start({?MODULE, SocketData}, Opts), - case SockMod:controlling_process(Socket, Receiver) of - ok -> - ok; + case Module:start({?MODULE, SocketData}, Opts) of + {ok, Pid} -> + case SockMod:controlling_process(Socket, Receiver) of + ok -> + ok; + {error, _Reason} -> + SockMod:close(Socket) + end, + ejabberd_receiver:become_controller(Receiver, Pid); {error, _Reason} -> SockMod:close(Socket) - end, - ejabberd_receiver:become_controller(Receiver, Pid); + end; raw -> - {ok, Pid} = Module:start({SockMod, Socket}, Opts), - case SockMod:controlling_process(Socket, Pid) of - ok -> - ok; + case Module:start({SockMod, Socket}, Opts) of + {ok, Pid} -> + case SockMod:controlling_process(Socket, Pid) of + ok -> + ok; + {error, _Reason} -> + SockMod:close(Socket) + end; {error, _Reason} -> SockMod:close(Socket) end diff --git a/src/jlib.erl b/src/jlib.erl index 1ee2e4ffa..4fd897599 100644 --- a/src/jlib.erl +++ b/src/jlib.erl @@ -59,7 +59,8 @@ now_to_local_string/1, datetime_string_to_timestamp/1, decode_base64/1, - encode_base64/1]). + encode_base64/1, + ip_to_list/1]). -include("jlib.hrl"). @@ -676,3 +677,9 @@ e(X) when X>51, X<62 -> X-4; e(62) -> $+; e(63) -> $/; e(X) -> exit({bad_encode_base64_token, X}). + +%% Convert Erlang inet IP to list +ip_to_list({IP, _Port}) -> + ip_to_list(IP); +ip_to_list({A,B,C,D}) -> + lists:flatten(io_lib:format("~w.~w.~w.~w",[A,B,C,D])).