From 8ecfbfa2a57708366763d7adbfcb87f9b0df7d03 Mon Sep 17 00:00:00 2001 From: Magnus Ahltorp Date: Sat, 18 Feb 2017 00:41:07 +0100 Subject: Require that storage servers sign stored entries --- src/sign.erl | 58 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 10 deletions(-) (limited to 'src/sign.erl') diff --git a/src/sign.erl b/src/sign.erl index 6e0e0bd..f7c7194 100644 --- a/src/sign.erl +++ b/src/sign.erl @@ -8,7 +8,7 @@ %% API. -export([start_link/0, stop/0]). --export([sign_sct/1, sign_sth/1, get_pubkey/0, get_logid/0, verify_sth/2]). +-export([sign_sct/2, sign_sth/1, get_pubkey/0, get_logid/0, verify_sth/2]). -export([read_keyfile_ec/1, pem_entry_decode/1]). %% API for tests. -export([read_keyfile_rsa/2]). @@ -145,20 +145,58 @@ remote_sign_request([URL|RestURLs], Request) -> remote_sign_request(RestURLs, Request) end. +verify_storage_signature(Data, Signature) -> + case string:tokens(Signature, ":") of + [Nodename, Sig] -> + case http_auth:verify_stored(Nodename, Data, base64:decode(Sig)) of + true -> + {ok, Nodename}; + _ -> + error + end; + _ -> + error + end. + +verify_storage_signatures(Data, Signatures) -> + Nodenames = sets:from_list(verify_storage_signatures(Data, Signatures, [])), + AllowedStorageNodes = sets:from_list(plopconfig:get_env(storage_node_names, [])), + sets:intersection(Nodenames, AllowedStorageNodes). + +verify_storage_signatures(_Data, [], Nodes) -> + Nodes; +verify_storage_signatures(Data, [Signature | Rest], Nodes) -> + case verify_storage_signature(Data, Signature) of + {ok, Node} -> + verify_storage_signatures(Data, Rest, [Node | Nodes]); + _ -> + [] + end. + %%%%%%%%%%%%%%%%%%%% %% Public API. sign_sct(Data = <<_Version:8, ?CERTIFICATE_TIMESTAMP:8, - _/binary>>) -> - case plopconfig:get_env(signing_nodes) of - {ok, URLBases} -> - Request = {[{plop_version, 1}, - {data, base64:encode(Data)} - ]}, - remote_sign_request([URLBase ++ "sct" || URLBase <- URLBases], Request); - undefined -> - call(?MODULE, {sign, Data}) + _/binary>>, Signatures) -> + Nodenames = verify_storage_signatures(Data, Signatures), + lager:debug("sign_sct: signatures ~p ~p", [Signatures, sets:to_list(Nodenames)]), + {ok, Quorum} = plopconfig:get_env(storage_sign_quorum), + case sets:size(Nodenames) >= Quorum of + true -> + case plopconfig:get_env(signing_nodes) of + {ok, URLBases} -> + Request = {[{plop_version, 1}, + {data, base64:encode(Data)}, + {signatures, Signatures} + ]}, + remote_sign_request([URLBase ++ "sct" || URLBase <- URLBases], Request); + undefined -> + call(?MODULE, {sign, Data}) + end; + _ -> + lager:error("signatures (~p) less than quorum (~p)", [sets:size(Nodenames), Quorum]), + error end. sign_sth(Data = <<_Version:8, -- cgit v1.1