diff options
| author | Rasmus Dahlberg <rasmus.dahlberg@kau.se> | 2020-10-30 16:09:11 +0100 | 
|---|---|---|
| committer | Rasmus Dahlberg <rasmus.dahlberg@kau.se> | 2020-10-30 16:09:11 +0100 | 
| commit | 14f2ed32f13b55dbce0f417f21ccf7b68056ae05 (patch) | |
| tree | 1d89fd0ac07141d629048b4ff8233f1ab508b3f6 | |
| parent | b8a8e56d4a311f15060efcd455c444949b2d20b9 (diff) | |
added max range and get-entries sanity checking
| -rw-r--r-- | handler.go | 20 | ||||
| -rw-r--r-- | instance.go | 2 | ||||
| -rw-r--r-- | reqres.go | 11 | ||||
| -rw-r--r-- | trillian.go | 32 | 
4 files changed, 46 insertions, 19 deletions
| @@ -80,11 +80,11 @@ func addEntry(ctx context.Context, i *Instance, w http.ResponseWriter, r *http.R  // getEntries provides a list of entries from the Trillian backend  func getEntries(ctx context.Context, i *Instance, w http.ResponseWriter, r *http.Request) (int, error) { -	glog.Info("in getEntries") -	request, err := NewGetEntriesRequest(r) +	glog.Info("handling get-entries request") +	request, err := NewGetEntriesRequest(i.LogParameters, r)  	if err != nil {  		return http.StatusBadRequest, err -	} // request can be decoded and is valid +	} // request can be decoded and is mostly valid (range not cmp vs tree size)  	trillianRequest := trillian.GetLeavesByRangeRequest{  		LogId:      i.LogParameters.TreeId, @@ -95,19 +95,9 @@ func getEntries(ctx context.Context, i *Instance, w http.ResponseWriter, r *http  	if err != nil {  		return http.StatusInternalServerError, fmt.Errorf("backend GetLeavesByRange request failed: %v", err)  	} - -	// Santity check -	if len(trillianResponse.Leaves) > int(request.End-request.Start+1) { -		return http.StatusInternalServerError, fmt.Errorf("backend GetLeavesByRange returned too many leaves: %d for [%d,%d]", len(trillianResponse.Leaves), request.Start, request.End) -	} -	for i, leaf := range trillianResponse.Leaves { -		if leaf.LeafIndex != request.Start+int64(i) { -			return http.StatusInternalServerError, fmt.Errorf("backend GetLeavesByRange returned unexpected leaf index: wanted %d, got %d", request.Start+int64(i), leaf.LeafIndex) -		} - -		glog.Infof("Leaf(%d) => %v", request.Start+int64(i), leaf.GetLeafValue()) +	if status, err := checkGetLeavesByRange(trillianResponse, request); err != nil { +		return status, err  	} -	// TODO: use the returned root for tree_size santity checking against start?  	response, err := NewGetEntriesResponse(trillianResponse.Leaves)  	if err != nil { diff --git a/instance.go b/instance.go index 6b67096..b13bdbe 100644 --- a/instance.go +++ b/instance.go @@ -27,6 +27,7 @@ type LogParameters struct {  	LogId      []byte // used externally by everyone  	TreeId     int64  // used internally by Trillian  	Prefix     string +	MaxRange   int64               // max entries per get-entries request  	AnchorPool *x509.CertPool      // for chain verification  	AnchorList []*x509.Certificate // for access to the raw certificates  	Signer     crypto.Signer @@ -68,6 +69,7 @@ func NewLogParameters(treeId int64, prefix string, anchorPath, keyPath string) (  		LogId:      logId,  		TreeId:     treeId,  		Prefix:     prefix, +		MaxRange:   2, // TODO: allow configuration  		AnchorPool: anchorPool,  		AnchorList: anchorList,  		Signer:     key, @@ -93,8 +93,10 @@ func NewAddEntryRequest(lp *LogParameters, r *http.Request) ([]byte, []byte, err  }  // NewGetEntriesRequest parses and sanitizes the URL-encoded get-entries -// parameters from an incoming HTTP request. -func NewGetEntriesRequest(httpRequest *http.Request) (GetEntriesRequest, error) { +// parameters from an incoming HTTP request.  Too large ranges are truncated +// based on the log's configured max range, but without taking the log's +// current tree size into consideration (because it is not know at this point). +func NewGetEntriesRequest(lp *LogParameters, httpRequest *http.Request) (GetEntriesRequest, error) {  	start, err := strconv.ParseInt(httpRequest.FormValue("start"), 10, 64)  	if err != nil {  		return GetEntriesRequest{}, fmt.Errorf("bad start parameter: %v", err) @@ -110,8 +112,9 @@ func NewGetEntriesRequest(httpRequest *http.Request) (GetEntriesRequest, error)  	if start > end {  		return GetEntriesRequest{}, fmt.Errorf("bad parameters: start(%v) must be less than or equal to end(%v)", start, end)  	} -	// TODO: check that range is not larger than the max range. Yes -> truncate -	// TODO: check that end is not past the most recent STH. Yes -> truncate +	if end-start+1 > lp.MaxRange { +		end = start + lp.MaxRange - 1 +	}  	return GetEntriesRequest{Start: start, End: end}, nil  } diff --git a/trillian.go b/trillian.go new file mode 100644 index 0000000..e5117da --- /dev/null +++ b/trillian.go @@ -0,0 +1,32 @@ +package stfe + +import ( +	"fmt" + +	"net/http" + +	"github.com/google/trillian" +	"github.com/google/trillian/types" +) + +// checkGetLeavesByRange does santity-checking on a Trillian response +func checkGetLeavesByRange(rsp *trillian.GetLeavesByRangeResponse, req GetEntriesRequest) (int, error) { +	if len(rsp.Leaves) > int(req.End-req.Start+1) { +		return http.StatusInternalServerError, fmt.Errorf("backend GetLeavesByRange returned too many leaves: %d for [%d,%d]", len(rsp.Leaves), req.Start, req.End) +	} + +	var lr types.LogRootV1 +	if err := lr.UnmarshalBinary(rsp.GetSignedLogRoot().GetLogRoot()); err != nil { +		return http.StatusInternalServerError, fmt.Errorf("failed unmarshaling log root: %v", err) +	} +	if uint64(req.Start) >= lr.TreeSize { +		return http.StatusBadRequest, fmt.Errorf("invalid start(%d): tree size is %d", req.Start, lr.TreeSize) +	} + +	for i, leaf := range rsp.Leaves { +		if leaf.LeafIndex != req.Start+int64(i) { +			return http.StatusInternalServerError, fmt.Errorf("backend GetLeavesByRange returned unexpected leaf index: wanted %d, got %d", req.Start+int64(i), leaf.LeafIndex) +		} +	} +	return 0, nil +} | 
