Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: basho/riak_kv
base: develop
...
head fork: basho/riak_kv
compare: bs-1.1.4-4.1
Checking mergeability… Don't worry, you can still create the pull request.
  • 5 commits
  • 12 files changed
  • 0 commit comments
  • 3 contributors
View
2  rebar.config
@@ -20,7 +20,7 @@
{ebloom, "1.1.1", {git, "git://github.com/basho/ebloom", {tag, "1.1.1"}}},
{eper, "0.61", {git, "git://github.com/basho/eper.git", {tag, "fdfd63c0"}}},
{eleveldb, "1.1.0", {git, "git://github.com/basho/eleveldb.git",
- {tag, "1.1.0"}}},
+ {tag, "1.1.1"}}},
{sext, ".*", {git, "git://github.com/esl/sext", {tag, "0.4.1"}}},
{riak_pipe, "1.1.2", {git, "git://github.com/basho/riak_pipe.git",
{tag, "1.1.2"}}},
View
2  src/riak_kv.app.src
@@ -3,7 +3,7 @@
{application, riak_kv,
[
{description, "Riak Key/Value Store"},
- {vsn, "1.1.2"},
+ {vsn, "1.1.4"},
{applications, [
kernel,
stdlib,
View
3  src/riak_kv_bitcask_backend.erl
@@ -379,11 +379,12 @@ callback(Ref,
merge_check,
#state{ref=Ref,
data_dir=DataDir,
+ opts=BitcaskOpts,
root=DataRoot}=State) when is_reference(Ref) ->
case bitcask:needs_merge(Ref) of
{true, Files} ->
BitcaskRoot = filename:join(DataRoot, DataDir),
- bitcask_merge_worker:merge(BitcaskRoot, [], Files);
+ bitcask_merge_worker:merge(BitcaskRoot, BitcaskOpts, Files);
false ->
ok
end,
View
3  src/riak_kv_wm_buckets.erl
@@ -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()}
View
4 src/riak_kv_wm_index.erl
@@ -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.
View
3  src/riak_kv_wm_keylist.erl
@@ -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()) ->
View
4 src/riak_kv_wm_link_walker.erl
@@ -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.
View
69 src/riak_kv_wm_mapred.erl
@@ -24,17 +24,19 @@
-module(riak_kv_wm_mapred).
--export([init/1, service_available/2, allowed_methods/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]).
-include_lib("webmachine/include/webmachine.hrl").
-include_lib("riak_pipe/include/riak_pipe.hrl").
+-define(MAPRED_CTYPE, "application/json").
-define(DEFAULT_TIMEOUT, 60000).
-record(state, {client, inputs, timeout, mrquery, boundary}).
+-type state() :: #state{}.
init(_) ->
{ok, undefined}.
@@ -48,25 +50,19 @@ 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}.
+-spec known_content_type(wrq:reqdata(), state()) ->
+ {boolean(), wrq:reqdata(), state()}.
+known_content_type(RD, State) ->
+ {ctype_ok(RD), RD, State}.
+
malformed_request(RD, State) ->
- {Verified, Message, NewState} =
- case {wrq:method(RD), wrq:req_body(RD)} of
- {'POST', Body} when Body /= undefined ->
- verify_body(Body, State);
- _ ->
- {false, usage(), State}
- end,
- {not Verified,
- if Verified -> RD;
- true ->
- wrq:set_resp_header(
- "Content-Type", "text/plain",
- wrq:set_resp_body(Message, RD))
- end,
- NewState}.
+ check_body(RD, State).
content_types_provided(RD, State) ->
{[{"application/json", nop}], RD, State}.
@@ -96,6 +92,47 @@ format_error({error, Error}) when is_list(Error) ->
format_error(_Error) ->
mochijson2:encode({struct, [{error, map_reduce_error}]}).
+-spec ctype_ok(wrq:reqdata()) -> boolean().
+%% @doc Return true if the content type from
+%% this request is appropriate.
+ctype_ok(RD) ->
+ valid_ctype(get_base_ctype(RD)).
+
+-spec get_base_ctype(wrq:reqdata()) -> string().
+%% @doc Return the "base" content-type, that
+%% is, not including the subtype parameters
+get_base_ctype(RD) ->
+ base_type(wrq:get_req_header("content-type", RD)).
+
+-spec base_type(string()) -> string().
+%% @doc Return the base media type
+base_type(CType) ->
+ {BaseType, _SubTypeParameters} = mochiweb_util:parse_header(CType),
+ BaseType.
+
+-spec valid_ctype(string()) -> boolean().
+%% @doc Return true if the base content type
+%% is equivalent to ?MAPRED_CTYPE
+valid_ctype(?MAPRED_CTYPE) -> true;
+valid_ctype(_Ctype) -> false.
+
+check_body(RD, State) ->
+ {Verified, Message, NewState} =
+ case {wrq:method(RD), wrq:req_body(RD)} of
+ {'POST', Body} when Body /= undefined ->
+ verify_body(Body, State);
+ _ ->
+ {false, usage(), State}
+ end,
+ {not Verified,
+ if Verified -> RD;
+ true ->
+ wrq:set_resp_header(
+ "Content-Type", "text/plain",
+ wrq:set_resp_body(Message, RD))
+ end,
+ NewState}.
+
verify_body(Body, State) ->
case riak_kv_mapred_json:parse_request(Body) of
{ok, ParsedInputs, ParsedQuery, Timeout} ->
View
4 src/riak_kv_wm_object.erl
@@ -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.
View
4 src/riak_kv_wm_props.erl
@@ -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.
View
4 src/riak_kv_wm_stats.erl
@@ -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}.
View
37 src/riak_kv_wm_utils.erl
@@ -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.

No commit comments for this range

Something went wrong with that request. Please try again.