summaryrefslogtreecommitdiff
path: root/src/frontend.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend.erl')
-rw-r--r--src/frontend.erl139
1 files changed, 119 insertions, 20 deletions
diff --git a/src/frontend.erl b/src/frontend.erl
index 3a45f7b..3924fb8 100644
--- a/src/frontend.erl
+++ b/src/frontend.erl
@@ -55,16 +55,7 @@ request(post, "ct/frontend/sendsth", Input) ->
html("Size is older than current size", OldSize);
Treesize == 0, OldSize == 0 ->
lager:debug("both old and new size is 0, saving sth"),
- OwnRootHash = ht:root(-1),
- case {plop:verify_sth(Treesize, Timestamp, RootHash, Signature), OwnRootHash} of
- {true, RootHash} ->
- ok = plop:save_sth({struct, PropList}),
- success({[{result, <<"ok">>}]});
- {false, RootHash} ->
- html("Verification failed", hex:bin_to_hexstr(RootHash));
- _ ->
- html("Root hash not the same", hex:bin_to_hexstr(OwnRootHash))
- end;
+ verify_and_save_sth(Treesize, Timestamp, RootHash, Signature, PropList);
Treesize > Indexsize ->
html("Has too few entries", Indexsize);
true ->
@@ -77,22 +68,14 @@ request(post, "ct/frontend/sendsth", Input) ->
case Errors of
[] ->
ht:load_tree(Treesize - 1),
- OwnRootHash = ht:root(Treesize - 1),
- case {plop:verify_sth(Treesize, Timestamp, RootHash, Signature), OwnRootHash} of
- {true, RootHash} ->
- ok = plop:save_sth({struct, PropList}),
- success({[{result, <<"ok">>}]});
- {false, RootHash} ->
- html("Verification failed", hex:bin_to_hexstr(RootHash));
- _ ->
- html("Root hash not the same", hex:bin_to_hexstr(OwnRootHash))
- end;
+ verify_and_save_sth(Treesize, Timestamp, RootHash, Signature, PropList);
_ ->
html("Database not complete", Errors)
end
end
end;
+
request(get, "ct/frontend/currentposition", _Query) ->
Size = db:size(),
success({[{result, <<"ok">>},
@@ -104,8 +87,94 @@ request(get, "ct/frontend/missingentries", _Query) ->
lager:debug("missingentries: ~p", [Missing]),
success({[{result, <<"ok">>},
{entries, lists:map(fun (Entry) -> base64:encode(Entry) end,
+ Missing)}]});
+
+request(post, "catlfish/merge/sendentry", Input) ->
+ case (catch mochijson2:decode(Input)) of
+ {error, E} ->
+ html("sendentry: bad input:", E);
+ {struct, PropList} ->
+ LogEntry = base64:decode(proplists:get_value(<<"entry">>, PropList)),
+ TreeLeafHash = base64:decode(proplists:get_value(<<"treeleafhash">>, PropList)),
+
+ ok = db:add(TreeLeafHash, LogEntry),
+ success({[{result, <<"ok">>}]})
+ end;
+
+request(post, "catlfish/merge/sendlog", Input) ->
+ case (catch mochijson2:decode(Input)) of
+ {error, E} ->
+ html("sendentry: bad input:", E);
+ {struct, PropList} ->
+ Start = proplists:get_value(<<"start">>, PropList),
+ Hashes = lists:map(fun (S) -> base64:decode(S) end, proplists:get_value(<<"hashes">>, PropList)),
+
+ Indices = lists:seq(Start, Start + length(Hashes) - 1),
+ lists:foreach(fun ({Hash, Index}) ->
+ ok = db:add_index_nosync_noreverse(Hash, Index)
+ end, lists:zip(Hashes, Indices)),
+ ok = db:index_sync(),
+ success({[{result, <<"ok">>}]})
+ end;
+
+request(post, "catlfish/merge/verifyroot", Input) ->
+ case (catch mochijson2:decode(Input)) of
+ {error, E} ->
+ html("sendentry: bad input:", E);
+ {struct, PropList} ->
+ OldSize = db:verifiedsize(),
+ Treesize = proplists:get_value(<<"tree_size">>, PropList),
+ Indexsize = db:indexsize(),
+
+ if
+ Treesize > Indexsize ->
+ html("Has too few entries", Indexsize);
+ true ->
+ NewEntries = get_new_entries(OldSize, Treesize),
+ lager:debug("old size: ~p new size: ~p entries: ~p",
+ [OldSize, Treesize, NewEntries]),
+
+ Errors = check_entries_noreverse(NewEntries, OldSize, Treesize - 1),
+
+ case Errors of
+ [] ->
+ ht:load_tree(Treesize - 1),
+ RootHash = ht:root(Treesize - 1),
+ success({[{result, <<"ok">>}, {root_hash, base64:encode(RootHash)}]});
+ _ ->
+ html("Database not complete", Errors)
+ end
+ end
+ end;
+
+%% implement setverifiedsize
+
+request(get, "catlfish/merge/verifiedsize", _Query) ->
+ Size = db:verifiedsize(),
+ success({[{result, <<"ok">>},
+ {size, Size}]});
+
+request(get, "catlfish/merge/missingentries", _Query) ->
+ Size = db:verifiedsize(),
+ Missing = fetchmissingentries(Size),
+ lager:debug("missingentries: ~p", [Missing]),
+ success({[{result, <<"ok">>},
+ {entries, lists:map(fun (Entry) -> base64:encode(Entry) end,
Missing)}]}).
+verify_and_save_sth(Treesize, Timestamp, RootHash, Signature, PropList) ->
+ OwnRootHash = ht:root(Treesize - 1),
+ case {plop:verify_sth(Treesize, Timestamp, RootHash, Signature), OwnRootHash} of
+ {true, RootHash} ->
+ ok = plop:save_sth({struct, PropList}),
+ success({[{result, <<"ok">>}]});
+ {false, RootHash} ->
+ html("Verification failed", hex:bin_to_hexstr(RootHash));
+ _ ->
+ html("Root hash not the same", hex:bin_to_hexstr(OwnRootHash))
+ end.
+
+
get_new_entries(OldSize, Treesize) when OldSize < Treesize ->
db:leafhash_for_indices(OldSize, Treesize - 1);
get_new_entries(OldSize, Treesize) when OldSize == Treesize ->
@@ -121,6 +190,16 @@ check_entries(Entries, Start, End) ->
end
end, [], lists:zip(Entries, lists:seq(Start, End))).
+check_entries_noreverse(Entries, Start, End) ->
+ lists:foldl(fun ({Hash, Index}, Acc) ->
+ case check_entry_noreverse(Hash, Index) of
+ ok ->
+ Acc;
+ Error ->
+ [Error | Acc]
+ end
+ end, [], lists:zip(Entries, lists:seq(Start, End))).
+
entryhash_from_entry(Entry) ->
{ok, {Module, Function}} = application:get_env(plop, entryhash_from_entry),
Module:Function(Entry).
@@ -151,6 +230,26 @@ check_entry(LeafHash, Index) ->
end
end.
+check_entry_noreverse(LeafHash, Index) ->
+ case db:entry_for_leafhash(LeafHash) of
+ notfound ->
+ {notfound, Index};
+ Entry ->
+ case verify_entry(Entry) of
+ {ok, LeafHash} ->
+ ok;
+ {ok, DifferentLeafHash} ->
+ lager:error("leaf hash not correct: filename is ~p " ++
+ "and contents are ~p",
+ [hex:bin_to_hexstr(LeafHash),
+ hex:bin_to_hexstr(DifferentLeafHash)]),
+ {error, differentleafhash};
+ {error, Reason} ->
+ lager:error("verification failed: ~p", [Reason]),
+ {error, verificationfailed}
+ end
+ end.
+
-spec fetchmissingentries(non_neg_integer()) -> [binary() | noentry].
fetchmissingentries(Index) ->
lists:reverse(fetchmissingentries(Index, [])).