Implement force_owner option to display ownership as a specific user.
This commit is contained in:
parent
fc2a5f5ab0
commit
cf1ded5236
@ -78,6 +78,17 @@ that uses built-in Go crypto.
|
||||
|
||||
Setting this option forces the filesystem to read-only and noexec.
|
||||
|
||||
#### -force_owner string
|
||||
If given a string of the form "uid:gid" (where both "uid" and "gid" are
|
||||
substituted with positive integers), presents all files as owned by the given
|
||||
uid and gid, regardless of their actual ownership. Implies "allow_other".
|
||||
|
||||
This is rarely desired behavior: One should *usually* run gocryptfs as the
|
||||
account which owns the backing-store files, which should *usually* be one and
|
||||
the same with the account intended to access the decrypted content. An example
|
||||
of a case where this may be useful is a situation where content is stored on a
|
||||
filesystem that doesn't properly support UNIX ownership and permissions.
|
||||
|
||||
#### -fsname string
|
||||
Override the filesystem name (first column in df -T). Can also be
|
||||
passed as "-o fsname=" and is equivalent to libfuse's option of the
|
||||
|
@ -144,6 +144,9 @@ Changelog
|
||||
---------
|
||||
|
||||
v1.4 (not yet released)
|
||||
* Add `force_owner` option to allow files to be presented as owned by a
|
||||
different user or group from the user running gocryptfs. Please see caveats
|
||||
and guidance in the man page before using this functionality.
|
||||
* Increase open file limit to 4096 ([#82](https://github.com/rfjakob/gocryptfs/issues/82)).
|
||||
* Implement path decryption via ctlsock ([#84](https://github.com/rfjakob/gocryptfs/issues/84)).
|
||||
Previously, decryption was only implemented for reverse mode. Now both
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/rfjakob/gocryptfs/internal/prefer_openssl"
|
||||
"github.com/rfjakob/gocryptfs/internal/stupidgcm"
|
||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
// argContainer stores the parsed CLI options and arguments
|
||||
@ -22,7 +23,7 @@ type argContainer struct {
|
||||
longnames, allow_other, ro, reverse, aessiv, nonempty, raw64,
|
||||
noprealloc, speed, hkdf, serialize_reads, forcedecode, hh, info bool
|
||||
masterkey, mountpoint, cipherdir, cpuprofile, extpass,
|
||||
memprofile, ko, passfile, ctlsock, fsname string
|
||||
memprofile, ko, passfile, ctlsock, fsname, force_owner string
|
||||
// Configuration file name override
|
||||
config string
|
||||
notifypid, scryptn int
|
||||
@ -31,6 +32,8 @@ type argContainer struct {
|
||||
_configCustom bool
|
||||
// _ctlsockFd stores the control socket file descriptor (ctlsock stores the path)
|
||||
_ctlsockFd net.Listener
|
||||
// _forceOwner is, if non-nil, a parsed, validated Owner (as opposed to the string above)
|
||||
_forceOwner *fuse.Owner
|
||||
}
|
||||
|
||||
var flagSet *flag.FlagSet
|
||||
@ -136,6 +139,7 @@ func parseCliOpts() (args argContainer) {
|
||||
flagSet.StringVar(&args.ko, "ko", "", "Pass additional options directly to the kernel, comma-separated list")
|
||||
flagSet.StringVar(&args.ctlsock, "ctlsock", "", "Create control socket at specified path")
|
||||
flagSet.StringVar(&args.fsname, "fsname", "", "Override the filesystem name")
|
||||
flagSet.StringVar(&args.force_owner, "force_owner", "", "uid:gid pair to coerce ownership")
|
||||
flagSet.IntVar(&args.notifypid, "notifypid", 0, "Send USR1 to the specified process after "+
|
||||
"successful mount - used internally for daemonization")
|
||||
flagSet.IntVar(&args.scryptn, "scryptn", configfile.ScryptDefaultLogN, "scrypt cost parameter logN. Possible values: 10-28. "+
|
||||
|
@ -1,6 +1,7 @@
|
||||
package fusefrontend
|
||||
|
||||
import (
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
"github.com/rfjakob/gocryptfs/internal/cryptocore"
|
||||
)
|
||||
|
||||
@ -16,6 +17,12 @@ type Args struct {
|
||||
// Should we chown a file after it has been created?
|
||||
// This only makes sense if (1) allow_other is set and (2) we run as root.
|
||||
PreserveOwner bool
|
||||
// Should we force ownership to be presented with a given user and group?
|
||||
// This only makes sense if allow_other is set. In *most* cases, it also
|
||||
// only makes sense with PreserveOwner set, but can also make sense without
|
||||
// PreserveOwner if the underlying filesystem acting as backing store
|
||||
// enforces ownership itself.
|
||||
ForceOwner *fuse.Owner
|
||||
// ConfigCustom is true when the user select a non-default config file
|
||||
// location. If it is false, reverse mode maps ".gocryptfs.reverse.conf"
|
||||
// to "gocryptfs.conf" in the plaintext dir.
|
||||
|
@ -77,6 +77,9 @@ func (fs *FS) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Stat
|
||||
target, _ := fs.Readlink(name, context)
|
||||
a.Size = uint64(len(target))
|
||||
}
|
||||
if fs.args.ForceOwner != nil {
|
||||
a.Owner = *fs.args.ForceOwner
|
||||
}
|
||||
return a, status
|
||||
}
|
||||
|
||||
|
@ -115,6 +115,9 @@ func (rfs *ReverseFS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr
|
||||
}
|
||||
var a fuse.Attr
|
||||
a.FromStat(&st)
|
||||
if rfs.args.ForceOwner != nil {
|
||||
a.Owner = *rfs.args.ForceOwner
|
||||
}
|
||||
return &a, fuse.OK
|
||||
}
|
||||
// Handle virtual files (gocryptfs.diriv, *.name)
|
||||
@ -136,6 +139,9 @@ func (rfs *ReverseFS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr
|
||||
}
|
||||
var a fuse.Attr
|
||||
status = f.GetAttr(&a)
|
||||
if rfs.args.ForceOwner != nil {
|
||||
a.Owner = *rfs.args.ForceOwner
|
||||
}
|
||||
return &a, status
|
||||
}
|
||||
// Decrypt path to "plaintext relative path"
|
||||
@ -177,6 +183,9 @@ func (rfs *ReverseFS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr
|
||||
|
||||
a.Size = uint64(len(linkTarget))
|
||||
}
|
||||
if rfs.args.ForceOwner != nil {
|
||||
a.Owner = *rfs.args.ForceOwner
|
||||
}
|
||||
return &a, fuse.OK
|
||||
}
|
||||
|
||||
|
22
main.go
22
main.go
@ -8,6 +8,7 @@ import (
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/configfile"
|
||||
@ -17,6 +18,7 @@ import (
|
||||
"github.com/rfjakob/gocryptfs/internal/speed"
|
||||
"github.com/rfjakob/gocryptfs/internal/stupidgcm"
|
||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
// GitVersion is the gocryptfs version according to git, set by build.bash
|
||||
@ -190,6 +192,26 @@ func main() {
|
||||
pprof.StartCPUProfile(f)
|
||||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
// "-force_owner"
|
||||
if args.force_owner != "" {
|
||||
var uidNum, gidNum int64
|
||||
ownerPieces := strings.SplitN(args.force_owner, ":", 2)
|
||||
if len(ownerPieces) != 2 {
|
||||
tlog.Fatal.Printf("force_owner must be in form UID:GID")
|
||||
os.Exit(exitcodes.Usage)
|
||||
}
|
||||
uidNum, err = strconv.ParseInt(ownerPieces[0], 0, 32)
|
||||
if err != nil || uidNum < 0 {
|
||||
tlog.Fatal.Printf("force_owner: Unable to parse UID %v as positive integer", ownerPieces[0])
|
||||
os.Exit(exitcodes.Usage)
|
||||
}
|
||||
gidNum, err = strconv.ParseInt(ownerPieces[1], 0, 32)
|
||||
if err != nil || gidNum < 0 {
|
||||
tlog.Fatal.Printf("force_owner: Unable to parse GID %v as positive integer", ownerPieces[1])
|
||||
os.Exit(exitcodes.Usage)
|
||||
}
|
||||
args._forceOwner = &fuse.Owner{Uid: uint32(uidNum), Gid: uint32(gidNum)}
|
||||
}
|
||||
// "-memprofile"
|
||||
if args.memprofile != "" {
|
||||
tlog.Info.Printf("Writing mem profile to %s", args.memprofile)
|
||||
|
6
mount.go
6
mount.go
@ -217,6 +217,11 @@ func initFuseFrontend(key []byte, args *argContainer, confFile *configfile.ConfF
|
||||
if args.aessiv {
|
||||
cryptoBackend = cryptocore.BackendAESSIV
|
||||
}
|
||||
// forceOwner implies allow_other, as documented.
|
||||
// Set this early, so args.allow_other can be relied on below this point.
|
||||
if args._forceOwner != nil {
|
||||
args.allow_other = true
|
||||
}
|
||||
frontendArgs := fusefrontend.Args{
|
||||
Cipherdir: args.cipherdir,
|
||||
Masterkey: key,
|
||||
@ -229,6 +234,7 @@ func initFuseFrontend(key []byte, args *argContainer, confFile *configfile.ConfF
|
||||
HKDF: args.hkdf,
|
||||
SerializeReads: args.serialize_reads,
|
||||
ForceDecode: args.forcedecode,
|
||||
ForceOwner: args._forceOwner,
|
||||
}
|
||||
// confFile is nil when "-zerokey" or "-masterkey" was used
|
||||
if confFile != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user