diff options
author | Jakob Unterwurzacher | 2017-05-23 20:46:24 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2017-05-23 21:26:38 +0200 |
commit | e827763f2e6226d9f5778d56c28270264950c0f5 (patch) | |
tree | 2f5f4adeed482dd473cc4714b97a8903806fdbb3 /internal/nametransform/longnames.go | |
parent | 508fd9e1d64131958c86175cb8d848f730e629cf (diff) |
nametransform: harden name decryption against invalid input
This fixes a few issues I have found reviewing the code:
1) Limit the amount of data ReadLongName() will read. Previously,
you could send gocryptfs into out-of-memory by symlinking
gocryptfs.diriv to /dev/zero.
2) Handle the empty input case in unPad16() by returning an
error. Previously, it would panic with an out-of-bounds array
read. It is unclear to me if this could actually be triggered.
3) Reject empty names after base64-decoding in DecryptName().
An empty name crashes emeCipher.Decrypt().
It is unclear to me if B64.DecodeString() can actually return
a non-error empty result, but let's guard against it anyway.
Diffstat (limited to 'internal/nametransform/longnames.go')
-rw-r--r-- | internal/nametransform/longnames.go | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/internal/nametransform/longnames.go b/internal/nametransform/longnames.go index 54095a4..8af191d 100644 --- a/internal/nametransform/longnames.go +++ b/internal/nametransform/longnames.go @@ -2,7 +2,8 @@ package nametransform import ( "crypto/sha256" - "io/ioutil" + "fmt" + "io" "os" "path/filepath" "strings" @@ -62,13 +63,29 @@ func IsLongContent(cName string) bool { return NameType(cName) == LongNameContent } -// ReadLongName - read path.name +// ReadLongName - read "$path.name" func ReadLongName(path string) (string, error) { - content, err := ioutil.ReadFile(path + LongNameSuffix) + path += LongNameSuffix + fd, err := os.Open(path) if err != nil { - tlog.Warn.Printf("ReadLongName: %v", err) + return "", err } - return string(content), err + defer fd.Close() + // 256 (=255 padded to 16) bytes base64-encoded take 344 bytes: "AAAAAAA...AAA==" + lim := 344 + // Allocate a bigger buffer so we see whether the file is too big + buf := make([]byte, lim+1) + n, err := fd.ReadAt(buf, 0) + if err != nil && err != io.EOF { + return "", err + } + if n == 0 { + return "", fmt.Errorf("ReadLongName: empty file") + } + if n > lim { + return "", fmt.Errorf("ReadLongName: size=%d > limit=%d", n, lim) + } + return string(buf[0:n]), nil } // DeleteLongName deletes "hashName.name". |