diff options
Diffstat (limited to 'src/v1.erl')
-rw-r--r-- | src/v1.erl | 182 |
1 files changed, 0 insertions, 182 deletions
diff --git a/src/v1.erl b/src/v1.erl deleted file mode 100644 index e066cdd..0000000 --- a/src/v1.erl +++ /dev/null @@ -1,182 +0,0 @@ -%%% Copyright (c) 2014-2015, NORDUnet A/S. -%%% See LICENSE for licensing information. - -%%% @doc Certificate Transparency (RFC 6962) - --module(v1). -%% API (URL) --export([request/3]). - -check_valid_sth() -> - case plop:sth() of - noentry -> - lager:error("No valid STH found"), - exit({internalerror, "No valid STH found"}); - {struct, PropList} -> - Now = plop:generate_timestamp(), - Timestamp = proplists:get_value(<<"timestamp">>, PropList), - MMD = application:get_env(catlfish, mmd, 86400) * 1000, - if - Now - Timestamp > MMD -> - lager:error("Old STH found, " ++ - "now: ~p, STH timestamp: ~p, diff: ~p", - [Now, Timestamp, Now - Timestamp]), - exit({internalerror, "No valid STH found"}); - true -> - ok - end - end. - -%% Public functions, i.e. part of URL. -request(post, "ct/v1/add-chain", Input) -> - check_valid_sth(), - add_chain(Input, normal); - -request(post, "ct/v1/add-pre-chain", Input) -> - check_valid_sth(), - add_chain(Input, precert); - -request(get, "ct/v1/get-sth", _Query) -> - check_valid_sth(), - case plop:sth() of - noentry -> - lager:error("No valid STH found"), - internalerror("No valid STH found"); - R -> - success(R) - end; - -request(get, "ct/v1/get-sth-consistency", Query) -> - check_valid_sth(), - 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 -> - err400("get-sth-consistency: bad input:", - [FirstInput, SecondInput]); - false -> - success( - {[{consistency, - [base64:encode(X) || - X <- plop:consistency(First, Second)]}]}) - end; - _ -> err400("get-sth-consistency: bad input:", Query) - end; - -request(get, "ct/v1/get-proof-by-hash", Query) -> - check_valid_sth(), - 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 -> - err400("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} -> - err400("get-proof-by-hash: hash not found", Msg) - end - end; - _ -> err400("get-proof-by-hash: bad input:", Query) - end; - -request(get, "ct/v1/get-entries", Query) -> - check_valid_sth(), - 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 -> err400("get-entries: bad input:", [Start, End]); - false -> success( - catlfish:entries(Start, min(End, Start + 999))) - end; - _ -> err400("get-entries: bad input:", Query) - end; - -request(get, "ct/v1/get-entry-and-proof", Query) -> - check_valid_sth(), - 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 -> - err400("get-entry-and-proof: not integers: ", - [IndexInput, TreeSizeInput]); - false -> success(catlfish:entry_and_proof(Index, TreeSize)) - end; - _ -> err400("get-entry-and-proof: bad input:", Query) - end; - -request(get, "ct/v1/get-roots", _Query) -> - check_valid_sth(), - R = [{certificates, - [base64:encode(Der) || - Der <- catlfish:update_known_roots()]}], - success({R}); - -request(_Method, _Path, _) -> - none. - -%% Private functions. -err400(Text, Input) -> - {400, [{"Content-Type", "text/html"}], - io_lib:format( - "<html><body><p>~n" ++ - "~s~n" ++ - "~p~n" ++ - "</body></html>~n", [Text, Input])}. - -success(Data) -> - {200, [{"Content-Type", "text/json"}], mochijson2:encode(Data)}. - -internalerror(Text) -> - {500, [{"Content-Type", "text/html"}], - io_lib:format( - "<html><body><p>~n" ++ - "~s~n" ++ - "</body></html>~n", [Text])}. - --spec add_chain(any(), normal|precert) -> any(). -add_chain(Input, Type) -> - case (catch mochijson2:decode(Input)) of - {error, E} -> - err400("add-chain: bad input:", E); - {struct, [{<<"chain">>, ChainB64List}]} -> - case decode_chain(ChainB64List) of - [LeafCert | CertChain] -> - case x509:normalise_chain(catlfish:known_roots(), - [LeafCert|CertChain]) of - {ok, [Leaf | Chain]} -> - lager:info("adding ~p cert ~p", - [Type, x509:cert_string(LeafCert)]), - success(catlfish:add_chain(Leaf, Chain, Type)); - {error, Reason} -> - lager:info("rejecting ~p: ~p", - [x509:cert_string(LeafCert), Reason]), - err400("add-chain: invalid chain", Reason) - end; - {invalid, ErrText} -> - err400(io:format("add-chain: ~p", [ErrText]), [ChainB64List]) - end; - _ -> err400("add-chain: missing input: chain", Input) - end. - --spec decode_chain(string()) -> {invalid, string()} | [binary()]. -decode_chain(B64List) -> - case (catch [base64:decode(X) || X <- B64List]) of - {'EXIT', _} -> {invalid, "invalid base64-encoded chain"}; - L -> L - end. |