forcedecode: tighten checks
...and fix a few golint issues and print a scary warning message on mount. Also, force the fs to ro,noexec.
This commit is contained in:
parent
f1945c4daa
commit
3409ade272
@ -67,11 +67,16 @@ failing with an IO error. Warning messages are still printed to syslog if corrup
|
|||||||
files are encountered.
|
files are encountered.
|
||||||
It can be useful to recover files from disks with bad sectors or other corrupted
|
It can be useful to recover files from disks with bad sectors or other corrupted
|
||||||
media. It shall not be used if the origin of corruption is unknown, specially
|
media. It shall not be used if the origin of corruption is unknown, specially
|
||||||
if you want to run executable files. For corrupted media, note that you probably want
|
if you want to run executable files.
|
||||||
to use dd_rescue(1) instead.
|
|
||||||
This option has no effect in reverse mode. It requires gocryptfs to be compiled with openssl
|
For corrupted media, note that you probably want to use dd_rescue(1)
|
||||||
|
instead, which will recover all but the corrupted 4kB block.
|
||||||
|
|
||||||
|
This option makes no sense in reverse mode. It requires gocryptfs to be compiled with openssl
|
||||||
support and implies -openssl true. Because of this, it is not compatible with -aessiv,
|
support and implies -openssl true. Because of this, it is not compatible with -aessiv,
|
||||||
that uses built-in Go crpyto.
|
that uses built-in Go crypto.
|
||||||
|
|
||||||
|
Setting this option forces the filesystem to read-only and noexec.
|
||||||
|
|
||||||
#### -fsname string
|
#### -fsname string
|
||||||
Override the filesystem name (first column in df -T). Can also be
|
Override the filesystem name (first column in df -T). Can also be
|
||||||
|
12
cli_args.go
12
cli_args.go
@ -171,11 +171,17 @@ func parseCliOpts() (args argContainer) {
|
|||||||
tlog.Fatal.Printf("The reverse mode and the -forcedecode option are not compatible")
|
tlog.Fatal.Printf("The reverse mode and the -forcedecode option are not compatible")
|
||||||
os.Exit(ErrExitUsage)
|
os.Exit(ErrExitUsage)
|
||||||
}
|
}
|
||||||
v, e := strconv.ParseBool(opensslAuto)
|
// Has the user explicitely disabled openssl using "-openssl=false/0"?
|
||||||
if e == nil && v == false {
|
if !args.openssl && opensslAuto != "auto" {
|
||||||
tlog.Warn.Printf("-openssl set to true, as it is required by -forcedecode flag")
|
tlog.Fatal.Printf("-forcedecode requires openssl, but is disabled via command-line option")
|
||||||
|
os.Exit(ErrExitUsage)
|
||||||
}
|
}
|
||||||
args.openssl = true
|
args.openssl = true
|
||||||
|
|
||||||
|
// Try to make it harder for the user to shoot himself in the foot.
|
||||||
|
args.ro = true
|
||||||
|
args.allow_other = false
|
||||||
|
args.ko = "noexec"
|
||||||
}
|
}
|
||||||
// '-passfile FILE' is a shortcut for -extpass='/bin/cat -- FILE'
|
// '-passfile FILE' is a shortcut for -extpass='/bin/cat -- FILE'
|
||||||
if args.passfile != "" {
|
if args.passfile != "" {
|
||||||
|
@ -86,7 +86,9 @@ func (be *ContentEnc) DecryptBlocks(ciphertext []byte, firstBlockNo uint64, file
|
|||||||
var pBlock []byte
|
var pBlock []byte
|
||||||
pBlock, err = be.DecryptBlock(cBlock, firstBlockNo, fileID)
|
pBlock, err = be.DecryptBlock(cBlock, firstBlockNo, fileID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if be.forceDecode == false || (be.forceDecode == true && stupidgcm.AuthError != err) {
|
if be.forceDecode && err == stupidgcm.ErrAuth {
|
||||||
|
tlog.Warn.Printf("DecryptBlocks: authentication failure in block #%d, overriden by forcedecode", firstBlockNo)
|
||||||
|
} else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,11 +141,10 @@ func (be *ContentEnc) DecryptBlock(ciphertext []byte, blockNo uint64, fileID []b
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
tlog.Warn.Printf("DecryptBlock: %s, len=%d", err.Error(), len(ciphertextOrig))
|
tlog.Warn.Printf("DecryptBlock: %s, len=%d", err.Error(), len(ciphertextOrig))
|
||||||
tlog.Debug.Println(hex.Dump(ciphertextOrig))
|
tlog.Debug.Println(hex.Dump(ciphertextOrig))
|
||||||
if be.forceDecode == true {
|
if be.forceDecode && err == stupidgcm.ErrAuth {
|
||||||
return plaintext, err
|
return plaintext, err
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return plaintext, nil
|
return plaintext, nil
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
|
|
||||||
"github.com/rfjakob/gocryptfs/internal/contentenc"
|
"github.com/rfjakob/gocryptfs/internal/contentenc"
|
||||||
"github.com/rfjakob/gocryptfs/internal/serialize_reads"
|
"github.com/rfjakob/gocryptfs/internal/serialize_reads"
|
||||||
|
"github.com/rfjakob/gocryptfs/internal/stupidgcm"
|
||||||
"github.com/rfjakob/gocryptfs/internal/syscallcompat"
|
"github.com/rfjakob/gocryptfs/internal/syscallcompat"
|
||||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||||
)
|
)
|
||||||
@ -200,9 +201,14 @@ func (f *file) doRead(off uint64, length uint64) ([]byte, fuse.Status) {
|
|||||||
// Decrypt it
|
// Decrypt it
|
||||||
plaintext, err := f.contentEnc.DecryptBlocks(ciphertext, firstBlockNo, fileID)
|
plaintext, err := f.contentEnc.DecryptBlocks(ciphertext, firstBlockNo, fileID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
curruptBlockNo := firstBlockNo + f.contentEnc.PlainOffToBlockNo(uint64(len(plaintext)))
|
if f.fs.args.ForceDecode && err == stupidgcm.ErrAuth {
|
||||||
tlog.Warn.Printf("ino%d: doRead: corrupt block #%d: %v", f.devIno.ino, curruptBlockNo, err)
|
// We do not have the information which block was corrupt here anymore,
|
||||||
if (f.fs.args.ForceDecode == false) {
|
// but DecryptBlocks() has already logged it anyway.
|
||||||
|
tlog.Warn.Printf("ino%d: doRead off=%d len=%d: returning corrupt data due to forcedecode",
|
||||||
|
f.devIno.ino, off, length)
|
||||||
|
} else {
|
||||||
|
curruptBlockNo := firstBlockNo + f.contentEnc.PlainOffToBlockNo(uint64(len(plaintext)))
|
||||||
|
tlog.Warn.Printf("ino%d: doRead: corrupt block #%d: %v", f.devIno.ino, curruptBlockNo, err)
|
||||||
return nil, fuse.EIO
|
return nil, fuse.EIO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
internal/stupidgcm/autherr.go
Normal file
8
internal/stupidgcm/autherr.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package stupidgcm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrAuth is returned when the message authentication fails
|
||||||
|
var ErrAuth = fmt.Errorf("stupidgcm: message authentication failed")
|
@ -10,7 +10,6 @@ import "C"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
@ -30,9 +29,6 @@ type stupidGCM struct {
|
|||||||
forceDecode bool
|
forceDecode bool
|
||||||
}
|
}
|
||||||
|
|
||||||
//authentication error
|
|
||||||
var AuthError error = fmt.Errorf("stupidgcm: message authentication failed")
|
|
||||||
|
|
||||||
var _ cipher.AEAD = &stupidGCM{}
|
var _ cipher.AEAD = &stupidGCM{}
|
||||||
|
|
||||||
// New returns a new cipher.AEAD implementation..
|
// New returns a new cipher.AEAD implementation..
|
||||||
@ -193,10 +189,9 @@ func (g stupidGCM) Open(dst, iv, in, authData []byte) ([]byte, error) {
|
|||||||
// The error code must always be checked by the calling function, because the decrypted buffer
|
// The error code must always be checked by the calling function, because the decrypted buffer
|
||||||
// may contain corrupted data that we are returning in case the user forced reads
|
// may contain corrupted data that we are returning in case the user forced reads
|
||||||
if g.forceDecode == true {
|
if g.forceDecode == true {
|
||||||
return append(dst, buf...), AuthError
|
return append(dst, buf...), ErrAuth
|
||||||
} else {
|
|
||||||
return nil, AuthError
|
|
||||||
}
|
}
|
||||||
|
return nil, ErrAuth
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(dst, buf...), nil
|
return append(dst, buf...), nil
|
||||||
|
@ -14,9 +14,6 @@ const (
|
|||||||
BuiltWithoutOpenssl = true
|
BuiltWithoutOpenssl = true
|
||||||
)
|
)
|
||||||
|
|
||||||
//authentication error - needed to compile as same varaible is exported when openssl is enable via stupidgcm.go
|
|
||||||
var AuthError error = fmt.Errorf("stupidgcm: message authentication failed with openssl disabled!")
|
|
||||||
|
|
||||||
func errExit() {
|
func errExit() {
|
||||||
fmt.Fprintln(os.Stderr, "gocryptfs has been compiled without openssl support but you are still trying to use openssl")
|
fmt.Fprintln(os.Stderr, "gocryptfs has been compiled without openssl support but you are still trying to use openssl")
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
|
4
mount.go
4
mount.go
@ -249,6 +249,10 @@ func initFuseFrontend(key []byte, args *argContainer, confFile *configfile.ConfF
|
|||||||
// Make the kernel check the file permissions for us
|
// Make the kernel check the file permissions for us
|
||||||
mOpts.Options = append(mOpts.Options, "default_permissions")
|
mOpts.Options = append(mOpts.Options, "default_permissions")
|
||||||
}
|
}
|
||||||
|
if args.forcedecode {
|
||||||
|
tlog.Info.Printf(tlog.ColorYellow + "THE OPTION \"-forcedecode\" IS ACTIVE. GOCRYPTFS WILL RETURN CORRUPT DATA!" +
|
||||||
|
tlog.ColorReset)
|
||||||
|
}
|
||||||
if args.nonempty {
|
if args.nonempty {
|
||||||
mOpts.Options = append(mOpts.Options, "nonempty")
|
mOpts.Options = append(mOpts.Options, "nonempty")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user