summaryrefslogtreecommitdiff
path: root/src/v1.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/v1.erl')
-rw-r--r--src/v1.erl182
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.