Verify requests against model (fixes #15)

This commit is contained in:
Jakob Borg 2014-01-06 21:31:36 +01:00
parent 28d3936a3c
commit 4b11e66914
3 changed files with 39 additions and 0 deletions

View File

@ -88,6 +88,9 @@ fingerprint is computed as the SHA-1 hash of the certificate and
displayed in BASE32 encoding to form a compact yet convenient string.
Currently SHA-1 is deemed secure against preimage attacks.
Incoming requests for file data are verified to the extent that the
requested file name must exist in the local index and the global model.
Installing
==========

View File

@ -13,6 +13,7 @@ acquire locks, but document what locks they require.
import (
"crypto/sha1"
"errors"
"fmt"
"io"
"log"
@ -58,6 +59,8 @@ const (
idxBcastMaxDelay = 120 * time.Second // Unless we've already waited this long
)
var ErrNoSuchFile = errors.New("no such file")
// NewModel creates and starts a new model. The model starts in read-only mode,
// where it sends index information to connected peers and responds to requests
// for file data without altering the local repository in any way.
@ -271,6 +274,16 @@ func (m *Model) Close(node string, err error) {
// Request returns the specified data segment by reading it from local disk.
// Implements the protocol.Model interface.
func (m *Model) Request(nodeID, name string, offset uint64, size uint32, hash []byte) ([]byte, error) {
// Verify that the requested file exists in the local and global model.
m.RLock()
_, localOk := m.local[name]
_, globalOk := m.global[name]
m.RUnlock()
if !localOk || !globalOk {
log.Printf("SECURITY (nonexistent file) REQ(in): %s: %q o=%d s=%d h=%x", nodeID, name, offset, size, hash)
return nil, ErrNoSuchFile
}
if m.trace["net"] && nodeID != "<local>" {
log.Printf("NET REQ(in): %s: %q o=%d s=%d h=%x", nodeID, name, offset, size, hash)
}

View File

@ -1,6 +1,7 @@
package model
import (
"bytes"
"os"
"reflect"
"testing"
@ -317,3 +318,25 @@ func TestForgetNode(t *testing.T) {
t.Errorf("Model len(need) incorrect (%d != %d)", l1, l2)
}
}
func TestRequest(t *testing.T) {
m := NewModel("testdata")
fs, _ := m.Walk(false)
m.ReplaceLocal(fs)
bs, err := m.Request("some node", "foo", 0, 6, nil)
if err != nil {
t.Fatal(err)
}
if bytes.Compare(bs, []byte("foobar")) != 0 {
t.Errorf("Incorrect data from request: %q", string(bs))
}
bs, err = m.Request("some node", "../walk.go", 0, 6, nil)
if err == nil {
t.Error("Unexpected nil error on insecure file read")
}
if bs != nil {
t.Errorf("Unexpected non nil data on insecure file read: %q", string(bs))
}
}