Skip to content
Permalink
Browse files

Add Referer header validation

  • Loading branch information...
dizzyd committed Jun 19, 2012
1 parent 442fc17 commit 3cd75e76c20b77dec2be0cb36892f5cc79dbec0b
@@ -35,6 +35,7 @@
-export([
init/1,
service_available/2,
forbidden/2,
content_types_provided/2,
encodings_provided/2,
produce_bucket_list/2
@@ -87,6 +88,8 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) ->
Ctx}
end.

forbidden(RD, Ctx) ->
{not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}.

%% @spec content_types_provided(reqdata(), context()) ->
%% {[{ContentType::string(), Producer::atom()}], reqdata(), context()}
@@ -33,6 +33,7 @@
-export([
init/1,
service_available/2,
forbidden/2,
malformed_request/2,
content_types_provided/2,
encodings_provided/2,
@@ -74,6 +75,9 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) ->
Ctx}
end.

forbidden(RD, Ctx) ->
{not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}.

%% @spec malformed_request(reqdata(), context()) ->
%% {boolean(), reqdata(), context()}
%% @doc Determine whether query parameters are badly-formed.
@@ -45,6 +45,7 @@
-export([
init/1,
service_available/2,
forbidden/2,
content_types_provided/2,
encodings_provided/2,
produce_bucket_body/2
@@ -100,6 +101,8 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) ->
Ctx}
end.

forbidden(RD, Ctx) ->
{not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}.


%% @spec content_types_provided(reqdata(), context()) ->
@@ -122,6 +122,7 @@
init/1,
malformed_request/2,
service_available/2,
forbidden/2,
allowed_methods/2,
content_types_provided/2,
resource_exists/2,
@@ -250,6 +251,9 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) ->
Ctx}
end.

forbidden(RD, Ctx) ->
{not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}.

%% @spec allowed_methods(reqdata(), context()) ->
%% {[method()], reqdata(), context()}
%% @doc Get the list of methods this resource supports.
@@ -24,7 +24,7 @@

-module(riak_kv_wm_mapred).

-export([init/1, service_available/2, allowed_methods/2, known_content_type/2]).
-export([init/1, service_available/2, allowed_methods/2, known_content_type/2, forbidden/2]).
-export([malformed_request/2, process_post/2, content_types_provided/2]).
-export([nop/2]).

@@ -50,6 +50,9 @@ service_available(RD, State) ->
{false, RD, State}
end.

forbidden(RD, State) ->
{not riak_kv_wm_utils:is_valid_referer(RD), RD, State}.

allowed_methods(RD, State) ->
{['GET','HEAD','POST'], RD, State}.

@@ -99,6 +99,7 @@
-export([
init/1,
service_available/2,
forbidden/2,
allowed_methods/2,
allow_missing_post/2,
malformed_request/2,
@@ -189,6 +190,9 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) ->
Ctx}
end.

forbidden(RD, Ctx) ->
{not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}.

%% @spec allowed_methods(reqdata(), context()) ->
%% {[method()], reqdata(), context()}
%% @doc Get the list of methods this resource supports.
@@ -51,6 +51,7 @@
-export([
init/1,
service_available/2,
forbidden/2,
allowed_methods/2,
malformed_request/2,
content_types_provided/2,
@@ -108,6 +109,9 @@ service_available(RD, Ctx=#ctx{riak=RiakProps}) ->
Ctx}
end.

forbidden(RD, Ctx) ->
{not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}.

%% @spec allowed_methods(reqdata(), context()) ->
%% {[method()], reqdata(), context()}
%% @doc Get the list of methods this resource supports.
@@ -29,6 +29,7 @@
encodings_provided/2,
content_types_provided/2,
service_available/2,
forbidden/2,
produce_body/2,
pretty_print/2
]).
@@ -75,6 +76,9 @@ service_available(ReqData, Ctx) ->
{true, ReqData, Ctx}
end.

forbidden(RD, Ctx) ->
{not riak_kv_wm_utils:is_valid_referer(RD), RD, Ctx}.

produce_body(ReqData, Ctx) ->
Body = mochijson2:encode({struct, get_stats()}),
{Body, ReqData, Ctx}.
@@ -35,7 +35,8 @@
encode_value/1,
accept_value/2,
any_to_list/1,
any_to_bool/1
any_to_bool/1,
is_valid_referer/1
]).

-include_lib("webmachine/include/webmachine.hrl").
@@ -232,3 +233,37 @@ any_to_bool(V) when is_integer(V) ->
V /= 0;
any_to_bool(V) when is_boolean(V) ->
V.



%% @doc Validate that the Referer matches up with scheme, host and port of the
%% machine that received the request.
is_valid_referer(RD) ->
OriginTuple = {wrq:scheme(RD), string:join(wrq:host_tokens(RD), "."), wrq:port(RD)},
case referer_tuple(RD) of
undefined ->
true;
{invalid, Url} ->
lager:debug("WM unparsable referer: ~s\n", [Url]),
false;
OriginTuple ->
true;
RefererTuple ->
lager:debug("WM referrer not origin. Origin ~p != Referer ~p\n", [OriginTuple, RefererTuple]),
false
end.

referer_tuple(RD) ->
case wrq:get_req_header("Referer", RD) of
undefined ->
undefined;
Url ->
case http_uri:parse(Url) of
{ok, {Scheme, _, Host, Port, _, _}} -> %R15+
{Scheme, Host, Port};
{Scheme, _, Host, Port, _, _} -> % R14 and below
{Scheme, Host, Port};
{error, _} ->
{invalid, Url}
end
end.

0 comments on commit 3cd75e7

Please sign in to comment.
You can’t perform that action at this time.