]> granicus.if.org Git - ejabberd/commitdiff
Don't treat 'Host' header as a virtual XMPP host
authorEvgeny Khramtsov <ekhramtsov@process-one.net>
Tue, 13 Aug 2019 15:30:28 +0000 (18:30 +0300)
committerEvgeny Khramtsov <ekhramtsov@process-one.net>
Tue, 13 Aug 2019 15:30:28 +0000 (18:30 +0300)
Fixes #2989

src/ejabberd_http.erl
src/ejabberd_option.erl
src/ejabberd_options.erl
src/ejabberd_web_admin.erl
src/mod_register_web.erl

index 12ee51d6642e5c8197b249ebf344c56748825190..c021b6685f25952a2ed7706cb0fa7fe96544e0d0 100644 (file)
@@ -280,37 +280,29 @@ process_header(State, Data) ->
            send_text(State1, Out),
            process_header(State, {ok, {http_error, <<>>}});
       {ok, http_eoh} ->
-         ?DEBUG("(~w) http query: ~w ~p~n",
-                [State#state.socket, State#state.request_method,
-                 element(2, State#state.request_path)]),
-         case ejabberd_router:is_my_route(State#state.request_host) of
-             true ->
-                 {State3, Out} = process_request(State),
-                 send_text(State3, Out),
-                 case State3#state.request_keepalive of
-                     true ->
-                         #state{sockmod = SockMod, socket = Socket,
-                                trail = State3#state.trail,
-                                options = State#state.options,
-                                default_host = State#state.default_host,
-                                custom_headers = State#state.custom_headers,
-                                request_handlers = State#state.request_handlers,
-                                addr_re = State#state.addr_re};
-                     _ ->
-                         #state{end_of_request = true,
-                                trail = State3#state.trail,
-                                options = State#state.options,
-                                default_host = State#state.default_host,
-                                custom_headers = State#state.custom_headers,
-                                request_handlers = State#state.request_handlers,
-                                addr_re = State#state.addr_re}
-                 end;
-             false ->
-                 Out = make_text_output(State, 400, State#state.custom_headers,
-                                        <<"Host not served">>),
-                 send_text(State, Out),
-                 process_header(State, {ok, {http_error, <<>>}})
-         end;
+           ?DEBUG("(~w) http query: ~w ~p~n",
+                  [State#state.socket, State#state.request_method,
+                   element(2, State#state.request_path)]),
+           {State3, Out} = process_request(State),
+           send_text(State3, Out),
+           case State3#state.request_keepalive of
+               true ->
+                   #state{sockmod = SockMod, socket = Socket,
+                          trail = State3#state.trail,
+                          options = State#state.options,
+                          default_host = State#state.default_host,
+                          custom_headers = State#state.custom_headers,
+                          request_handlers = State#state.request_handlers,
+                          addr_re = State#state.addr_re};
+               _ ->
+                   #state{end_of_request = true,
+                          trail = State3#state.trail,
+                          options = State#state.options,
+                          default_host = State#state.default_host,
+                          custom_headers = State#state.custom_headers,
+                          request_handlers = State#state.request_handlers,
+                          addr_re = State#state.addr_re}
+           end;
       _ ->
          #state{end_of_request = true,
                 options = State#state.options,
@@ -475,7 +467,7 @@ process_request(#state{request_method = Method,
                          {error, _} = E -> throw(E)
                      end,
            XFF = proplists:get_value('X-Forwarded-For', RequestHeaders, []),
-           IP = analyze_ip_xff(IPHere, XFF, Host),
+           IP = analyze_ip_xff(IPHere, XFF),
             Request = #request{method = Method,
                                path = LPath,
                                q = LQuery,
@@ -526,12 +518,11 @@ make_bad_request(State) ->
                                                          [{xmlcdata,
                                                            <<"400 Bad Request">>}]}])).
 
-analyze_ip_xff(IP, [], _Host) -> IP;
-analyze_ip_xff({IPLast, Port}, XFF, Host) ->
+analyze_ip_xff(IP, []) -> IP;
+analyze_ip_xff({IPLast, Port}, XFF) ->
     [ClientIP | ProxiesIPs] = str:tokens(XFF, <<", ">>) ++
                                [misc:ip_to_list(IPLast)],
-    ServerHost = ejabberd_router:host_of_route(Host),
-    TrustedProxies = ejabberd_option:trusted_proxies(ServerHost),
+    TrustedProxies = ejabberd_option:trusted_proxies(),
     IPClient = case is_ipchain_trusted(ProxiesIPs,
                                       TrustedProxies)
                   of
index b0a6adfe8d1f2f85da5a14bdbb14dd2bf1fb419c..d7fd65cfed1fd7c25df70bc728167b9be3a4eccf 100644 (file)
 -export([sql_start_interval/0, sql_start_interval/1]).
 -export([sql_type/0, sql_type/1]).
 -export([sql_username/0, sql_username/1]).
--export([trusted_proxies/0, trusted_proxies/1]).
+-export([trusted_proxies/0]).
 -export([use_cache/0, use_cache/1]).
 -export([validate_stream/0]).
 -export([version/0]).
@@ -991,10 +991,7 @@ sql_username(Host) ->
 
 -spec trusted_proxies() -> 'all' | [{inet:ip4_address() | inet:ip6_address(),byte()}].
 trusted_proxies() ->
-    trusted_proxies(global).
--spec trusted_proxies(global | binary()) -> 'all' | [{inet:ip4_address() | inet:ip6_address(),byte()}].
-trusted_proxies(Host) ->
-    ejabberd_config:get_option({trusted_proxies, Host}).
+    ejabberd_config:get_option({trusted_proxies, global}).
 
 -spec use_cache() -> boolean().
 use_cache() ->
index f7025fe7f146906a4c462f5cf898a7b16322af73..a83f0add717d2b16dac10edc30f4dc95834b9b00 100644 (file)
@@ -698,6 +698,7 @@ globals() ->
      sm_cache_life_time,
      sm_cache_missed,
      sm_cache_size,
+     trusted_proxies,
      validate_stream,
      version,
      websocket_origin,
index ac4ffd3960117171644dfcd910be6438a6589397..9bd278889c734c94d283ca4c000c6c839d49f1e9 100644 (file)
@@ -213,31 +213,36 @@ process(RPath,
        #request{auth = Auth, lang = Lang, host = HostHTTP,
                 method = Method} =
            Request) ->
-    case get_auth_admin(Auth, HostHTTP, RPath, Method) of
-      {ok, {User, Server}} ->
-         AJID = get_jid(Auth, HostHTTP, Method),
-         process_admin(global,
-                       Request#request{path = RPath,
-                                       us = {User, Server}},
-                       AJID);
-      {unauthorized, <<"no-auth-provided">>} ->
-         {401,
-          [{<<"WWW-Authenticate">>,
-            <<"basic realm=\"ejabberd\"">>}],
-          ejabberd_web:make_xhtml([?XCT(<<"h1">>,
-                                        ?T("Unauthorized"))])};
-      {unauthorized, Error} ->
-         {BadUser, _BadPass} = Auth,
-         {IPT, _Port} = Request#request.ip,
-         IPS = ejabberd_config:may_hide_data(misc:ip_to_list(IPT)),
-         ?WARNING_MSG("Access of ~p from ~p failed with error: ~p",
-                      [BadUser, IPS, Error]),
-         {401,
-          [{<<"WWW-Authenticate">>,
-            <<"basic realm=\"auth error, retry login "
-              "to ejabberd\"">>}],
-          ejabberd_web:make_xhtml([?XCT(<<"h1">>,
-                                        ?T("Unauthorized"))])}
+    case ejabberd_router:is_my_host(HostHTTP) of
+       true ->
+           case get_auth_admin(Auth, HostHTTP, RPath, Method) of
+               {ok, {User, Server}} ->
+                   AJID = get_jid(Auth, HostHTTP, Method),
+                   process_admin(global,
+                                 Request#request{path = RPath,
+                                                 us = {User, Server}},
+                                 AJID);
+               {unauthorized, <<"no-auth-provided">>} ->
+                   {401,
+                    [{<<"WWW-Authenticate">>,
+                      <<"basic realm=\"ejabberd\"">>}],
+                    ejabberd_web:make_xhtml([?XCT(<<"h1">>,
+                                                  ?T("Unauthorized"))])};
+               {unauthorized, Error} ->
+                   {BadUser, _BadPass} = Auth,
+                   {IPT, _Port} = Request#request.ip,
+                   IPS = ejabberd_config:may_hide_data(misc:ip_to_list(IPT)),
+                   ?WARNING_MSG("Access of ~p from ~p failed with error: ~p",
+                                [BadUser, IPS, Error]),
+                   {401,
+                    [{<<"WWW-Authenticate">>,
+                      <<"basic realm=\"auth error, retry login "
+                        "to ejabberd\"">>}],
+                    ejabberd_web:make_xhtml([?XCT(<<"h1">>,
+                                                  ?T("Unauthorized"))])}
+           end;
+       false ->
+           ejabberd_web:error(not_found)
     end.
 
 get_auth_admin(Auth, HostHTTP, RPath, Method) ->
index 3a08e1cb811eca31e22606da504680430c2836c0..b066cffcd90fef3f360ddaec077183f0248c4d00 100644 (file)
@@ -95,13 +95,29 @@ process([<<"register.css">>],
 process([<<"new">>],
        #request{method = 'GET', lang = Lang, host = Host,
                 ip = IP}) ->
-    {Addr, _Port} = IP, form_new_get(Host, Lang, Addr);
+    case ejabberd_router:is_my_host(Host) of
+       true ->
+           {Addr, _Port} = IP,
+           form_new_get(Host, Lang, Addr);
+       false ->
+           {400, [], <<"Host not served">>}
+    end;
 process([<<"delete">>],
        #request{method = 'GET', lang = Lang, host = Host}) ->
-    form_del_get(Host, Lang);
+    case ejabberd_router:is_my_host(Host) of
+       true ->
+           form_del_get(Host, Lang);
+       false ->
+           {400, [], <<"Host not served">>}
+    end;
 process([<<"change_password">>],
        #request{method = 'GET', lang = Lang, host = Host}) ->
-    form_changepass_get(Host, Lang);
+    case ejabberd_router:is_my_host(Host) of
+       true ->
+           form_changepass_get(Host, Lang);
+       false ->
+           {400, [], <<"Host not served">>}
+    end;
 process([<<"new">>],
        #request{method = 'POST', q = Q, ip = {Ip, _Port},
                 lang = Lang, host = _HTTPHost}) ->