aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--handler.go71
-rw-r--r--type.go23
2 files changed, 91 insertions, 3 deletions
diff --git a/handler.go b/handler.go
index 90dbc27..7b986c1 100644
--- a/handler.go
+++ b/handler.go
@@ -4,9 +4,13 @@ import (
"context"
"fmt"
+ "encoding/json"
+ "io/ioutil"
"net/http"
"github.com/golang/glog"
+ "github.com/google/certificate-transparency-go/tls"
+ "github.com/google/trillian"
)
// appHandler implements the http.Handler interface, and contains a reference
@@ -31,7 +35,7 @@ func (a appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
statusCode, err := a.handler(ctx, a.instance, w, r)
if err != nil {
- glog.Warningf("handler error %s: %v", a.instance.prefix+a.endpoint, err)
+ glog.Warningf("handler error %s/%s: %v", a.instance.prefix, a.endpoint, err)
a.sendHTTPError(w, statusCode, err)
}
}
@@ -41,10 +45,71 @@ func (a appHandler) sendHTTPError(w http.ResponseWriter, statusCode int, err err
http.Error(w, http.StatusText(statusCode), statusCode)
}
-// addEntry adds an entry to the Trillian backend
func addEntry(ctx context.Context, i *instance, w http.ResponseWriter, r *http.Request) (int, error) {
glog.Info("in addEntry")
- return http.StatusOK, nil // TODO
+ var request AddEntryRequest
+ if err := unpackRequest(r, &request); err != nil {
+ return http.StatusBadRequest, err
+ }
+
+ item, err := verifyAddEntryRequest(request)
+ if err != nil {
+ return http.StatusBadRequest, err
+ }
+ glog.Infof("got item: %s", item)
+
+ serializedItem, err := tls.Marshal(*item)
+ if err != nil {
+ return http.StatusInternalServerError, fmt.Errorf("tls marshal failed: %v", err)
+ }
+ trillianRequest := trillian.QueueLeafRequest{
+ LogId: i.logID,
+ Leaf: &trillian.LogLeaf{
+ LeafValue: serializedItem,
+ //TODO: add appendix here w/ chain + signature
+ },
+ }
+
+ trillianResponse, err := i.client.QueueLeaf(ctx, &trillianRequest)
+ if err != nil {
+ return http.StatusInternalServerError, fmt.Errorf("backend QueueLeaf request failed: %v", err)
+ }
+ if trillianResponse == nil {
+ return http.StatusInternalServerError, fmt.Errorf("missing QueueLeaf response")
+ }
+ // TODO: check that we got gRPC OK as specified in Trillian's API doc
+
+ queuedLeaf := trillianResponse.QueuedLeaf
+ glog.Infof("Queued leaf: %v", queuedLeaf.Leaf.LeafValue)
+ // TODO: respond with an SDI
+
+ return http.StatusOK, nil
+}
+
+// verifyAddEntryRequest
+func verifyAddEntryRequest(r AddEntryRequest) (*StItem, error) {
+ item, err := StItemFromB64(r.Item)
+ if err != nil {
+ return nil, fmt.Errorf("failed decoding StItem: %v", err)
+ }
+ if item.Format != StFormatChecksumV1 {
+ return nil, fmt.Errorf("invalid StItem format: %s", item.Format)
+ }
+ // TODO: verify checksum length
+ // TODO: verify r.Signature and r.Certificate
+ return item, nil
+}
+
+// unpackRequest tries to unpack a json-encoded HTTP POST request into `unpack`
+func unpackRequest(r *http.Request, unpack interface{}) error {
+ body, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ return fmt.Errorf("failed reading request body: %v", err)
+ }
+ if err := json.Unmarshal(body, &unpack); err != nil {
+ return fmt.Errorf("failed parsing json body: %v", err)
+ }
+ return nil
}
// getEntries provides with a list of entries from the Trillian backend
diff --git a/type.go b/type.go
index e9b5ef2..031ae8d 100644
--- a/type.go
+++ b/type.go
@@ -55,6 +55,22 @@ func (i StItem) String() string {
}
}
+func StItemFromB64(s string) (*StItem, error) {
+ b, err := base64.StdEncoding.DecodeString(s)
+ if err != nil {
+ return nil, fmt.Errorf("base64 decoding failed: %v", err)
+ }
+
+ var item StItem
+ extra, err := tls.Unmarshal(b, &item)
+ if err != nil {
+ return nil, fmt.Errorf("tls unmarshal failed: %v", err)
+ } else if len(extra) > 0 {
+ return nil, fmt.Errorf("tls unmarshal found extra data: %v", extra)
+ }
+ return &item, nil
+}
+
// ChecksumV1 associates a package name with an arbitrary checksum value
type ChecksumV1 struct {
Package []byte `tls:"minlen:0,maxlen:255"`
@@ -75,3 +91,10 @@ func NewChecksumV1(name string, checksum []byte) (StItem, error) {
func (i ChecksumV1) String() string {
return fmt.Sprintf("%v %v", string(i.Package), base64.StdEncoding.EncodeToString(i.Checksum))
}
+
+// AddEntryRequest is a collection of add-entry input parameters
+type AddEntryRequest struct {
+ Item string `json:"item"`
+ Signature string `json:"signature"`
+ Certificate string `json:"certificate"`
+}