aboutsummaryrefslogtreecommitdiff
path: root/internal/nametransform/longnames.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2017-05-23 20:46:24 +0200
committerJakob Unterwurzacher2017-05-23 21:26:38 +0200
commite827763f2e6226d9f5778d56c28270264950c0f5 (patch)
tree2f5f4adeed482dd473cc4714b97a8903806fdbb3 /internal/nametransform/longnames.go
parent508fd9e1d64131958c86175cb8d848f730e629cf (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.go27
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".