summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/catlfish.erl39
-rw-r--r--src/v1.erl189
2 files changed, 107 insertions, 121 deletions
diff --git a/src/catlfish.erl b/src/catlfish.erl
index 73066bb..6cc741d 100644
--- a/src/catlfish.erl
+++ b/src/catlfish.erl
@@ -98,13 +98,11 @@ add_chain(LeafCert, CertChain) ->
plop:spt(list_to_binary([<<?PROTOCOL_VERSION:8>>,
serialise_signature_type(certificate_timestamp),
serialise(TimestampedEntry)])),
- binary_to_list(
- jiffy:encode(
- {[{sct_version, ?PROTOCOL_VERSION},
- {id, base64:encode(plop:get_logid())},
- {timestamp, TimestampedEntry#timestamped_entry.timestamp},
- {extensions, base64:encode(<<>>)},
- {signature, base64:encode(plop:serialise(SCT_sig))}]})).
+ {[{sct_version, ?PROTOCOL_VERSION},
+ {id, base64:encode(plop:get_logid())},
+ {timestamp, TimestampedEntry#timestamped_entry.timestamp},
+ {extensions, base64:encode(<<>>)},
+ {signature, base64:encode(plop:serialise(SCT_sig))}]}.
-spec serialise_logentry(integer(), binary(), [binary()]) -> binary().
serialise_logentry(Timestamp, LeafCert, CertChain) ->
@@ -118,24 +116,21 @@ serialise_logentry(Timestamp, LeafCert, CertChain) ->
-spec entries(non_neg_integer(), non_neg_integer()) -> list().
entries(Start, End) ->
- binary_to_list(
- jiffy:encode({[{entries, x_entries(plop:get(Start, End))}]})).
+ {[{entries, x_entries(plop:get(Start, End))}]}.
-spec entry_and_proof(non_neg_integer(), non_neg_integer()) -> list().
entry_and_proof(Index, TreeSize) ->
- binary_to_list(
- jiffy:encode(
- case plop:inclusion_and_entry(Index, TreeSize) of
- {ok, Entry, Path} ->
- {Timestamp, LeafCertVector, CertChainVector} = unpack_entry(Entry),
- MTL = build_mtl(Timestamp, LeafCertVector),
- {[{leaf_input, base64:encode(MTL)},
- {extra_data, base64:encode(CertChainVector)},
- {audit_path, [base64:encode(X) || X <- Path]}]};
- {notfound, Msg} ->
- {[{success, false},
- {error_message, list_to_binary(Msg)}]}
- end)).
+ case plop:inclusion_and_entry(Index, TreeSize) of
+ {ok, Entry, Path} ->
+ {Timestamp, LeafCertVector, CertChainVector} = unpack_entry(Entry),
+ MTL = build_mtl(Timestamp, LeafCertVector),
+ {[{leaf_input, base64:encode(MTL)},
+ {extra_data, base64:encode(CertChainVector)},
+ {audit_path, [base64:encode(X) || X <- Path]}]};
+ {notfound, Msg} ->
+ {[{success, false},
+ {error_message, list_to_binary(Msg)}]}
+ end.
%% Private functions.
unpack_entry(Entry) ->
diff --git a/src/v1.erl b/src/v1.erl
index 086fa35..d9796fa 100644
--- a/src/v1.erl
+++ b/src/v1.erl
@@ -9,32 +9,31 @@
%% Public functions, i.e. part of URL.
request(post, "ct/v1/add-chain", Input) ->
- R = case (catch jiffy:decode(Input)) of
- {error, E} ->
- html("add-chain: bad input:", E);
- {[{<<"chain">>, ChainBase64}]} ->
- case (catch [base64:decode(X) || X <- ChainBase64]) of
- {'EXIT', _} ->
- html("add-chain: invalid base64-encoded chain: ",
- [ChainBase64]);
- [LeafCert | CertChain] ->
- Roots = catlfish:known_roots(),
- case x509:normalise_chain(Roots, [LeafCert|CertChain]) of
- {ok, [Leaf | Chain]} ->
- io:format("[info] adding ~p~n",
- [x509:cert_string(LeafCert)]),
- success(catlfish:add_chain(Leaf, Chain));
- {error, Reason} ->
- io:format("[info] rejecting ~p: ~p~n",
- [x509:cert_string(LeafCert), Reason]),
- html("add-chain: invalid chain", Reason)
- end;
- Invalid ->
- html("add-chain: chain is not a list: ", [Invalid])
- end;
- _ -> html("add-chain: missing input: chain", Input)
- end,
- R;
+ case (catch mochijson2:decode(Input)) of
+ {error, E} ->
+ html("add-chain: bad input:", E);
+ {struct, [{<<"chain">>, ChainBase64}]} ->
+ case (catch [base64:decode(X) || X <- ChainBase64]) of
+ {'EXIT', _} ->
+ html("add-chain: invalid base64-encoded chain: ",
+ [ChainBase64]);
+ [LeafCert | CertChain] ->
+ Roots = catlfish:known_roots(),
+ case x509:normalise_chain(Roots, [LeafCert|CertChain]) of
+ {ok, [Leaf | Chain]} ->
+ lager:info("adding ~p",
+ [x509:cert_string(LeafCert)]),
+ success(catlfish:add_chain(Leaf, Chain));
+ {error, Reason} ->
+ lager:info("rejecting ~p: ~p",
+ [x509:cert_string(LeafCert), Reason]),
+ html("add-chain: invalid chain", Reason)
+ end;
+ Invalid ->
+ html("add-chain: chain is not a list: ", [Invalid])
+ end;
+ _ -> html("add-chain: missing input: chain", Input)
+ end;
request(post, "ct/v1/add-pre-chain", _Input) ->
niy();
@@ -49,91 +48,83 @@ request(get, "ct/v1/get-sth", _Query) ->
{sha256_root_hash, base64:encode(Roothash)},
{tree_head_signature, base64:encode(
plop:serialise(Signature))}],
- success(jiffy:encode({R}));
+ success({R});
request(get, "ct/v1/get-sth-consistency", Query) ->
- R = case lists:sort(Query) of
- [{"first", FirstInput}, {"second", SecondInput}] ->
- {First, _} = string:to_integer(FirstInput),
- {Second, _} = string:to_integer(SecondInput),
- case lists:member(error, [First, Second]) of
- true ->
- html("get-sth-consistency: bad input:",
- [FirstInput, SecondInput]);
- false ->
- success(
- jiffy:encode(
- {[{consistency,
- [base64:encode(X) ||
- X <- plop:consistency(First, Second)]}]}))
- end;
- _ -> html("get-sth-consistency: bad input:", Query)
- end,
- R;
+ case lists:sort(Query) of
+ [{"first", FirstInput}, {"second", SecondInput}] ->
+ {First, _} = string:to_integer(FirstInput),
+ {Second, _} = string:to_integer(SecondInput),
+ case lists:member(error, [First, Second]) of
+ true ->
+ html("get-sth-consistency: bad input:",
+ [FirstInput, SecondInput]);
+ false ->
+ success(
+ {[{consistency,
+ [base64:encode(X) ||
+ X <- plop:consistency(First, Second)]}]})
+ end;
+ _ -> html("get-sth-consistency: bad input:", Query)
+ end;
request(get, "ct/v1/get-proof-by-hash", Query) ->
- R = case lists:sort(Query) of
- [{"hash", HashInput}, {"tree_size", TreeSizeInput}] ->
- Hash = case (catch base64:decode(HashInput)) of
- {'EXIT', _} -> error;
- H -> H
- end,
- {TreeSize, _} = string:to_integer(TreeSizeInput),
- case lists:member(error, [Hash, TreeSize]) of
- true ->
- html("get-proof-by-hash: bad input:",
- [HashInput, TreeSizeInput]);
- false ->
- success(
- jiffy:encode(
- case plop:inclusion(Hash, TreeSize) of
- {ok, Index, Path} ->
- {[{leaf_index, Index},
- {audit_path,
- [base64:encode(X) || X <- Path]}]};
- {notfound, Msg} ->
- %% FIXME: http status 400
- {[{success, false},
- {error_message, list_to_binary(Msg)}]}
- end))
- end;
- _ -> html("get-proof-by-hash: bad input:", Query)
- end,
- R;
+ case lists:sort(Query) of
+ [{"hash", HashInput}, {"tree_size", TreeSizeInput}] ->
+ Hash = case (catch base64:decode(HashInput)) of
+ {'EXIT', _} -> error;
+ H -> H
+ end,
+ {TreeSize, _} = string:to_integer(TreeSizeInput),
+ case lists:member(error, [Hash, TreeSize]) of
+ true ->
+ html("get-proof-by-hash: bad input:",
+ [HashInput, TreeSizeInput]);
+ false ->
+ case plop:inclusion(Hash, TreeSize) of
+ {ok, Index, Path} ->
+ success({[{leaf_index, Index},
+ {audit_path,
+ [base64:encode(X) || X <- Path]}]});
+ {notfound, Msg} ->
+ html("get-proof-by-hash: hash not found", Msg)
+ end
+ end;
+ _ -> html("get-proof-by-hash: bad input:", Query)
+ end;
request(get, "ct/v1/get-entries", Query) ->
- R = case lists:sort(Query) of
- [{"end", EndInput}, {"start", StartInput}] ->
- {Start, _} = string:to_integer(StartInput),
- {End, _} = string:to_integer(EndInput),
- case lists:member(error, [Start, End]) of
- true -> html("get-entries: bad input:", [Start, End]);
- false -> success(catlfish:entries(Start, min(End, Start + 999)))
- end;
- _ -> html("get-entries: bad input:", Query)
- end,
- R;
+ case lists:sort(Query) of
+ [{"end", EndInput}, {"start", StartInput}] ->
+ {Start, _} = string:to_integer(StartInput),
+ {End, _} = string:to_integer(EndInput),
+ case lists:member(error, [Start, End]) of
+ true -> html("get-entries: bad input:", [Start, End]);
+ false -> success(
+ catlfish:entries(Start, min(End, Start + 999)))
+ end;
+ _ -> html("get-entries: bad input:", Query)
+ end;
request(get, "ct/v1/get-entry-and-proof", Query) ->
- R = case lists:sort(Query) of
- [{"leaf_index", IndexInput}, {"tree_size", TreeSizeInput}] ->
- {Index, _} = string:to_integer(IndexInput),
- {TreeSize, _} = string:to_integer(TreeSizeInput),
- case lists:member(error, [Index, TreeSize]) of
- true ->
- html("get-entry-and-proof: not integers: ",
- [IndexInput, TreeSizeInput]);
- false -> success(catlfish:entry_and_proof(Index, TreeSize))
- end;
- _ -> html("get-entry-and-proof: bad input:", Query)
- end,
- R;
+ case lists:sort(Query) of
+ [{"leaf_index", IndexInput}, {"tree_size", TreeSizeInput}] ->
+ {Index, _} = string:to_integer(IndexInput),
+ {TreeSize, _} = string:to_integer(TreeSizeInput),
+ case lists:member(error, [Index, TreeSize]) of
+ true ->
+ html("get-entry-and-proof: not integers: ",
+ [IndexInput, TreeSizeInput]);
+ false -> success(catlfish:entry_and_proof(Index, TreeSize))
+ end;
+ _ -> html("get-entry-and-proof: bad input:", Query)
+ end;
request(get, "ct/v1/get-roots", _Query) ->
R = [{certificates,
[base64:encode(Der) ||
Der <- catlfish:update_known_roots()]}],
- success(jiffy:encode({R}));
+ success({R});
request(_Method, _Path, _) ->
none.
@@ -151,4 +142,4 @@ niy() ->
html("NIY - Not Implemented Yet|", []).
success(Data) ->
- {200, [{"Content-Type", "text/json"}], Data}.
+ {200, [{"Content-Type", "text/json"}], mochijson2:encode(Data)}.