summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--src/catlfish_web.erl32
-rw-r--r--test/config/frontend-1.config21
-rw-r--r--test/config/privatekeys/frontend-1-private.pem5
-rw-r--r--test/config/privatekeys/merge-1-private.pem5
-rw-r--r--test/config/privatekeys/storage-1-private.pem5
-rw-r--r--test/config/publickeys/frontend-1.pem4
-rw-r--r--test/config/publickeys/merge-1.pem4
-rw-r--r--test/config/publickeys/storage-1.pem4
-rw-r--r--test/config/storage-1.config10
-rwxr-xr-xtools/merge.py42
-rwxr-xr-xtools/testcase1.py2
12 files changed, 119 insertions, 17 deletions
diff --git a/Makefile b/Makefile
index 56064ad..08f6584 100644
--- a/Makefile
+++ b/Makefile
@@ -34,6 +34,8 @@ tests-prepare:
mkdir -p test/nodes/storage-2/log
cp test/config/frontend-1.config rel
cp test/config/storage-1.config rel
+ cp -r test/config/privatekeys rel
+ cp -r test/config/publickeys rel
rm -r rel/tests || true
mkdir -p rel/tests/machine/machine-1/db
printf "0" > rel/tests/machine/machine-1/db/treesize
diff --git a/src/catlfish_web.erl b/src/catlfish_web.erl
index 9869b21..5ee5743 100644
--- a/src/catlfish_web.erl
+++ b/src/catlfish_web.erl
@@ -11,15 +11,31 @@ start(Options, Module) ->
end,
mochiweb_http:start([{name, Module}, {loop, Loop} | Options]).
+
+add_auth(Path, {Code, Headers, Data}) ->
+ AuthHeader = http_auth:create_auth("REPLY", Path, Data),
+ lager:debug("sent auth header: ~p", [AuthHeader]),
+ {Code, [{"X-Catlfish-Auth", AuthHeader} | Headers], Data}.
+
loop(Req, Module) ->
"/" ++ Path = Req:get(path),
try
Starttime = os:timestamp(),
+ AuthHeader = Req:get_header_value("X-Catlfish-Auth"),
case Req:get(method) of
'GET' ->
Query = Req:parse_qs(),
- lager:debug("GET ~p ~p", [Path, Query]),
- Result = Module:request(get, Path, Query),
+ {_, RawQuery, _} = mochiweb_util:urlsplit_path(Req:get(raw_path)),
+ Result = case http_auth:verify_auth(AuthHeader, "GET", "/" ++ Path, RawQuery) of
+ failure ->
+ {403, [{"Content-Type", "text/plain"}], "Invalid credentials"};
+ success ->
+ lager:debug("GET ~p ~p", [Path, Query]),
+ add_auth("/" ++ Path, Module:request(get, Path, Query));
+ noauth ->
+ lager:debug("GET ~p ~p", [Path, Query]),
+ Module:request(get, Path, Query)
+ end,
lager:debug("GET finished: ~p us", [timer:now_diff(os:timestamp(), Starttime)]),
case Result of
none ->
@@ -29,8 +45,16 @@ loop(Req, Module) ->
end;
'POST' ->
Body = Req:recv_body(),
- lager:debug("POST ~p ~p", [Path, Body]),
- Result = Module:request(post, Path, Body),
+ Result = case http_auth:verify_auth(AuthHeader, "POST", "/" ++ Path, Body) of
+ failure ->
+ {403, [{"Content-Type", "text/plain"}], "Invalid credentials"};
+ success ->
+ lager:debug("POST ~p ~p", [Path, Body]),
+ add_auth("/" ++ Path, Module:request(post, Path, Body));
+ noauth ->
+ lager:debug("POST ~p ~p", [Path, Body]),
+ Module:request(post, Path, Body)
+ end,
lager:debug("POST finished: ~p us", [timer:now_diff(os:timestamp(), Starttime)]),
case Result of
none ->
diff --git a/test/config/frontend-1.config b/test/config/frontend-1.config
index 79d887d..9d7e37c 100644
--- a/test/config/frontend-1.config
+++ b/test/config/frontend-1.config
@@ -31,5 +31,24 @@
{treesize_path, "tests/machine/machine-1/db/treesize"},
{indexforhash_root_path, "tests/machine/machine-1/db/certindex/"},
{storage_nodes, ["https://127.0.0.1:8081/ct/storage/"]},
- {storage_nodes_quorum, 1}
+ {storage_nodes_quorum, 1},
+ {publickey_path, "publickeys"},
+ {own_key, {"frontend-1", "privatekeys/frontend-1-private.pem"}},
+ {allowed_clients, [{"/ct/frontend/sendentry", ["merge-1"]},
+ {"/ct/frontend/sendlog", ["merge-1"]},
+ {"/ct/frontend/sendsth", ["merge-1"]},
+ {"/ct/frontend/currentposition", ["merge-1"]},
+ {"/ct/frontend/missingentries", ["merge-1"]},
+ {"/ct/v1/add-chain", noauth},
+ {"/ct/v1/add-pre-chain", noauth},
+ {"/ct/v1/get-sth", noauth},
+ {"/ct/v1/get-sth-consistency", noauth},
+ {"/ct/v1/get-proof-by-hash", noauth},
+ {"/ct/v1/get-entries", noauth},
+ {"/ct/v1/get-entry-and-proof", noauth},
+ {"/ct/v1/get-roots", noauth}
+ ]},
+ {allowed_servers, [{"/ct/storage/sendentry", ["storage-1"]},
+ {"/ct/storage/entrycommitted", ["storage-1"]}
+ ]}
]}].
diff --git a/test/config/privatekeys/frontend-1-private.pem b/test/config/privatekeys/frontend-1-private.pem
new file mode 100644
index 0000000..718efda
--- /dev/null
+++ b/test/config/privatekeys/frontend-1-private.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIPER9WFIxLXvXDHTwPvGnNvBAKOB+/6ahpvuCjtlzOU8oAoGCCqGSM49
+AwEHoUQDQgAEibeLqrVV7QAE6Wytzpxi4sd0JtGNGRfXNZ9r9CNIVudDnNjtFRF5
+gwm/AxUWEuBXjnbVvq4HOLqZ0bP2qc+uRQ==
+-----END EC PRIVATE KEY-----
diff --git a/test/config/privatekeys/merge-1-private.pem b/test/config/privatekeys/merge-1-private.pem
new file mode 100644
index 0000000..55d50b1
--- /dev/null
+++ b/test/config/privatekeys/merge-1-private.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIBQcXtOVX29dno+aYqGddVOpg23FfhJmrMFOpOegyYZxoAoGCCqGSM49
+AwEHoUQDQgAExHAsjFFgKFlrcCveHhVdjE7A/Uh0gXdAeN9+P7SDGgRNe0WWDjCr
+0Da3c8X5JulA1cOLlQ0h2B67Yp3WZ9ONHg==
+-----END EC PRIVATE KEY-----
diff --git a/test/config/privatekeys/storage-1-private.pem b/test/config/privatekeys/storage-1-private.pem
new file mode 100644
index 0000000..b68d2a9
--- /dev/null
+++ b/test/config/privatekeys/storage-1-private.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIAjVa6lTbhiNUfrfTGELRXqHSHF0nuk13lKF8NSHzU07oAoGCCqGSM49
+AwEHoUQDQgAE1vFWiMT9PItJGvyhMKPF5TnFirHPSh5u5swetajmNLyClWIDGXql
+RlXlcPwuKxTISI4rFJATBkKhNjvSZ5L3oA==
+-----END EC PRIVATE KEY-----
diff --git a/test/config/publickeys/frontend-1.pem b/test/config/publickeys/frontend-1.pem
new file mode 100644
index 0000000..938ef29
--- /dev/null
+++ b/test/config/publickeys/frontend-1.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEibeLqrVV7QAE6Wytzpxi4sd0JtGN
+GRfXNZ9r9CNIVudDnNjtFRF5gwm/AxUWEuBXjnbVvq4HOLqZ0bP2qc+uRQ==
+-----END PUBLIC KEY-----
diff --git a/test/config/publickeys/merge-1.pem b/test/config/publickeys/merge-1.pem
new file mode 100644
index 0000000..95a75f7
--- /dev/null
+++ b/test/config/publickeys/merge-1.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExHAsjFFgKFlrcCveHhVdjE7A/Uh0
+gXdAeN9+P7SDGgRNe0WWDjCr0Da3c8X5JulA1cOLlQ0h2B67Yp3WZ9ONHg==
+-----END PUBLIC KEY-----
diff --git a/test/config/publickeys/storage-1.pem b/test/config/publickeys/storage-1.pem
new file mode 100644
index 0000000..0b862a1
--- /dev/null
+++ b/test/config/publickeys/storage-1.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1vFWiMT9PItJGvyhMKPF5TnFirHP
+Sh5u5swetajmNLyClWIDGXqlRlXlcPwuKxTISI4rFJATBkKhNjvSZ5L3oA==
+-----END PUBLIC KEY-----
diff --git a/test/config/storage-1.config b/test/config/storage-1.config
index b176e1f..005a8ad 100644
--- a/test/config/storage-1.config
+++ b/test/config/storage-1.config
@@ -28,4 +28,12 @@
{newentries_path, "tests/machine/machine-1/db/newentries"},
{entryhash_root_path, "tests/machine/machine-1/db/entryhash/"},
{treesize_path, "tests/machine/machine-1/db/treesize"},
- {indexforhash_root_path, "tests/machine/machine-1/db/certindex/"}]}].
+ {indexforhash_root_path, "tests/machine/machine-1/db/certindex/"},
+ {publickey_path, "publickeys"},
+ {own_key, {"storage-1", "privatekeys/storage-1-private.pem"}},
+ {allowed_clients, [{"/ct/storage/sendentry", ["frontend-1"]},
+ {"/ct/storage/entrycommitted", ["frontend-1"]},
+ {"/ct/storage/fetchnewentries", ["merge-1"]},
+ {"/ct/storage/getentry", noauth}
+ ]}
+]}].
diff --git a/tools/merge.py b/tools/merge.py
index f4a007d..6becf7e 100755
--- a/tools/merge.py
+++ b/tools/merge.py
@@ -11,6 +11,9 @@ import urllib
import urllib2
import sys
import time
+import ecdsa
+import hashlib
+import urlparse
from certtools import build_merkle_tree, create_sth_signature, check_sth_signature, get_eckey_from_file, timing_point
parser = argparse.ArgumentParser(description="")
@@ -19,6 +22,8 @@ parser.add_argument("--frontend", action="append", metavar="url", help="Base URL
parser.add_argument("--storage", action="append", metavar="url", help="Base URL for storage server", required=True)
parser.add_argument("--mergedb", metavar="dir", help="Merge database directory", required=True)
parser.add_argument("--keyfile", metavar="keyfile", help="File containing log key", required=True)
+parser.add_argument("--own-keyname", metavar="keyname", help="The key name of the merge node", required=True)
+parser.add_argument("--own-keyfile", metavar="keyfile", help="The file containing the private key of the merge node", required=True)
parser.add_argument("--nomerge", action='store_true', help="Don't actually do merge")
args = parser.parse_args()
@@ -52,9 +57,26 @@ def add_to_logorder(key):
f.write(base64.b16encode(key) + "\n")
f.close()
+def http_request(url, data=None):
+ req = urllib2.Request(url, data)
+ keyname = args.own_keyname
+ privatekey = get_eckey_from_file(args.own_keyfile)
+ sk = ecdsa.SigningKey.from_der(privatekey)
+ parsed_url = urlparse.urlparse(url)
+ if data == None:
+ data = parsed_url.query
+ method = "GET"
+ else:
+ method = "POST"
+ signature = sk.sign("%s\0%s\0%s" % (method, parsed_url.path, data), hashfunc=hashlib.sha256,
+ sigencode=ecdsa.util.sigencode_der)
+ req.add_header('X-Catlfish-Auth', base64.b64encode(signature) + ";key=" + keyname)
+ result = urllib2.urlopen(req).read()
+ return result
+
def get_new_entries(baseurl):
try:
- result = urllib2.urlopen(baseurl + "ct/storage/fetchnewentries").read()
+ result = http_request(baseurl + "ct/storage/fetchnewentries")
parsed_result = json.loads(result)
if parsed_result.get(u"result") == u"ok":
return [base64.b64decode(entry) for entry in parsed_result[u"entries"]]
@@ -67,7 +89,7 @@ def get_new_entries(baseurl):
def get_entries(baseurl, hashes):
try:
params = urllib.urlencode({"hash":[base64.b64encode(hash) for hash in hashes]}, doseq=True)
- result = urllib2.urlopen(baseurl + "ct/storage/getentry?" + params).read()
+ result = http_request(baseurl + "ct/storage/getentry?" + params)
parsed_result = json.loads(result)
if parsed_result.get(u"result") == u"ok":
entries = dict([(base64.b64decode(entry["hash"]), base64.b64decode(entry["entry"])) for entry in parsed_result[u"entries"]])
@@ -82,7 +104,7 @@ def get_entries(baseurl, hashes):
def get_curpos(baseurl):
try:
- result = urllib2.urlopen(baseurl + "ct/frontend/currentposition").read()
+ result = http_request(baseurl + "ct/frontend/currentposition")
parsed_result = json.loads(result)
if parsed_result.get(u"result") == u"ok":
return parsed_result[u"position"]
@@ -94,8 +116,8 @@ def get_curpos(baseurl):
def sendlog(baseurl, submission):
try:
- result = urllib2.urlopen(baseurl + "ct/frontend/sendlog",
- json.dumps(submission)).read()
+ result = http_request(baseurl + "ct/frontend/sendlog",
+ json.dumps(submission))
return json.loads(result)
except urllib2.HTTPError, e:
print "ERROR: sendlog", e.read()
@@ -110,8 +132,8 @@ def sendlog(baseurl, submission):
def sendentry(baseurl, entry, hash):
try:
- result = urllib2.urlopen(baseurl + "ct/frontend/sendentry",
- json.dumps({"entry":base64.b64encode(entry), "treeleafhash":base64.b64encode(hash)})).read()
+ result = http_request(baseurl + "ct/frontend/sendentry",
+ json.dumps({"entry":base64.b64encode(entry), "treeleafhash":base64.b64encode(hash)}))
return json.loads(result)
except urllib2.HTTPError, e:
print "ERROR: sendentry", e.read()
@@ -126,8 +148,8 @@ def sendentry(baseurl, entry, hash):
def sendsth(baseurl, submission):
try:
- result = urllib2.urlopen(baseurl + "ct/frontend/sendsth",
- json.dumps(submission)).read()
+ result = http_request(baseurl + "ct/frontend/sendsth",
+ json.dumps(submission))
return json.loads(result)
except urllib2.HTTPError, e:
print "ERROR: sendsth", e.read()
@@ -142,7 +164,7 @@ def sendsth(baseurl, submission):
def get_missingentries(baseurl):
try:
- result = urllib2.urlopen(baseurl + "ct/frontend/missingentries").read()
+ result = http_request(baseurl + "ct/frontend/missingentries")
parsed_result = json.loads(result)
if parsed_result.get(u"result") == u"ok":
return parsed_result[u"entries"]
diff --git a/tools/testcase1.py b/tools/testcase1.py
index a41a783..c87e8eb 100755
--- a/tools/testcase1.py
+++ b/tools/testcase1.py
@@ -136,7 +136,7 @@ def get_and_check_entry(timestamp, chain, leaf_index):
len(submittedcertchain))
def merge():
- return subprocess.call(["./merge.py", "--baseurl", "https://127.0.0.1:8080/", "--frontend", "https://127.0.0.1:8082/", "--storage", "https://127.0.0.1:8081/", "--mergedb", "../rel/mergedb", "--keyfile", "../rel/test/eckey.pem"])
+ return subprocess.call(["./merge.py", "--baseurl", "https://127.0.0.1:8080/", "--frontend", "https://127.0.0.1:8082/", "--storage", "https://127.0.0.1:8081/", "--mergedb", "../rel/mergedb", "--keyfile", "../rel/test/eckey.pem", "--own-keyname", "merge-1", "--own-keyfile", "../rel/privatekeys/merge-1-private.pem"])
print_and_check_tree_size(0)