diff options
Diffstat (limited to 'main.go')
-rw-r--r-- | main.go | 210 |
1 files changed, 3 insertions, 207 deletions
@@ -1,29 +1,17 @@ package main import ( - "encoding/json" "fmt" - "log/syslog" "os" - "os/exec" - "os/signal" + "path/filepath" "runtime" "runtime/pprof" "strconv" - "strings" - "syscall" "time" - "github.com/hanwen/go-fuse/fuse" - "github.com/hanwen/go-fuse/fuse/nodefs" - "github.com/hanwen/go-fuse/fuse/pathfs" - "github.com/rfjakob/gocryptfs/internal/configfile" "github.com/rfjakob/gocryptfs/internal/contentenc" - "github.com/rfjakob/gocryptfs/internal/cryptocore" - "github.com/rfjakob/gocryptfs/internal/fusefrontend" - "github.com/rfjakob/gocryptfs/internal/fusefrontend_reverse" "github.com/rfjakob/gocryptfs/internal/readpassword" "github.com/rfjakob/gocryptfs/internal/stupidgcm" "github.com/rfjakob/gocryptfs/internal/tlog" @@ -62,7 +50,7 @@ Options: flagSet.PrintDefaults() } -// loadConfig - load the config file "filename", prompting the user for the password +// loadConfig loads the config file "args.config", prompting the user for the password func loadConfig(args *argContainer) (masterkey []byte, confFile *configfile.ConfFile) { // Check if the file can be opened at all before prompting for a password fd, err := os.Open(args.config) @@ -78,7 +66,6 @@ func loadConfig(args *argContainer) (masterkey []byte, confFile *configfile.Conf tlog.Fatal.Println(err) os.Exit(ErrExitLoadConf) } - return masterkey, confFile } @@ -227,196 +214,5 @@ func main() { changePassword(&args) // does not return } // Mount - // Check mountpoint - if flagSet.NArg() != 2 { - tlog.Fatal.Printf("Usage: %s [OPTIONS] CIPHERDIR MOUNTPOINT", tlog.ProgramName) - os.Exit(ErrExitUsage) - } - args.mountpoint, err = filepath.Abs(flagSet.Arg(1)) - if err != nil { - tlog.Fatal.Printf("Invalid mountpoint: %v", err) - os.Exit(ErrExitMountPoint) - } - if args.nonempty { - err = checkDir(args.mountpoint) - } else { - err = checkDirEmpty(args.mountpoint) - } - if err != nil { - tlog.Fatal.Printf("Invalid mountpoint: %v", err) - os.Exit(ErrExitMountPoint) - } - // Get master key - var masterkey []byte - var confFile *configfile.ConfFile - if args.masterkey != "" { - // "-masterkey" - tlog.Info.Printf("Using explicit master key.") - masterkey = parseMasterKey(args.masterkey) - tlog.Info.Printf(tlog.ColorYellow + - "THE MASTER KEY IS VISIBLE VIA \"ps ax\" AND MAY BE STORED IN YOUR SHELL HISTORY!\n" + - "ONLY USE THIS MODE FOR EMERGENCIES." + tlog.ColorReset) - } else if args.zerokey { - // "-zerokey" - tlog.Info.Printf("Using all-zero dummy master key.") - tlog.Info.Printf(tlog.ColorYellow + - "ZEROKEY MODE PROVIDES NO SECURITY AT ALL AND SHOULD ONLY BE USED FOR TESTING." + - tlog.ColorReset) - masterkey = make([]byte, cryptocore.KeyLen) - } else { - // Load master key from config file - masterkey, confFile = loadConfig(&args) - printMasterKey(masterkey) - } - // Initialize FUSE server - tlog.Debug.Printf("cli args: %v", args) - srv := initFuseFrontend(masterkey, args, confFile) - tlog.Info.Println(tlog.ColorGreen + "Filesystem mounted and ready." + tlog.ColorReset) - // We have been forked into the background, as evidenced by the set - // "notifypid". - if args.notifypid > 0 { - // Chdir to the root directory so we don't block unmounting the CWD - os.Chdir("/") - // Switch to syslog - if !args.nosyslog { - tlog.Info.SwitchToSyslog(syslog.LOG_USER | syslog.LOG_INFO) - tlog.Debug.SwitchToSyslog(syslog.LOG_USER | syslog.LOG_DEBUG) - tlog.Warn.SwitchToSyslog(syslog.LOG_USER | syslog.LOG_WARNING) - tlog.SwitchLoggerToSyslog(syslog.LOG_USER | syslog.LOG_WARNING) - // Daemons should close all fds (and we don't want to get killed by - // SIGPIPE if any of those get closed on the other end) - os.Stderr.Close() - os.Stdout.Close() - os.Stdin.Close() - } - // Send SIGUSR1 to our parent - sendUsr1(args.notifypid) - } - // Wait for SIGINT in the background and unmount ourselves if we get it. - // This prevents a dangling "Transport endpoint is not connected" - // mountpoint if the user hits CTRL-C. - handleSigint(srv, args.mountpoint) - // Jump into server loop. Returns when it gets an umount request from the kernel. - srv.Serve() - // main exits with code 0 -} - -// initFuseFrontend - initialize gocryptfs/fusefrontend -// Calls os.Exit on errors -func initFuseFrontend(key []byte, args argContainer, confFile *configfile.ConfFile) *fuse.Server { - // Reconciliate CLI and config file arguments into a fusefrontend.Args struct - // that is passed to the filesystem implementation - cryptoBackend := cryptocore.BackendGoGCM - if args.openssl { - cryptoBackend = cryptocore.BackendOpenSSL - } - if args.aessiv { - cryptoBackend = cryptocore.BackendAESSIV - } - frontendArgs := fusefrontend.Args{ - Cipherdir: args.cipherdir, - Masterkey: key, - PlaintextNames: args.plaintextnames, - LongNames: args.longnames, - CryptoBackend: cryptoBackend, - } - // confFile is nil when "-zerokey" or "-masterkey" was used - if confFile != nil { - // Settings from the config file override command line args - frontendArgs.PlaintextNames = confFile.IsFeatureFlagSet(configfile.FlagPlaintextNames) - if confFile.IsFeatureFlagSet(configfile.FlagAESSIV) { - frontendArgs.CryptoBackend = cryptocore.BackendAESSIV - } else if args.reverse { - tlog.Fatal.Printf("AES-SIV is required by reverse mode, but not enabled in the config file") - os.Exit(ErrExitUsage) - } - } - // If allow_other is set and we run as root, try to give newly created files to - // the right user. - if args.allow_other && os.Getuid() == 0 { - frontendArgs.PreserveOwner = true - } - jsonBytes, _ := json.MarshalIndent(frontendArgs, "", "\t") - tlog.Debug.Printf("frontendArgs: %s", string(jsonBytes)) - var finalFs pathfs.FileSystem - if args.reverse { - finalFs = fusefrontend_reverse.NewFS(frontendArgs) - } else { - finalFs = fusefrontend.NewFS(frontendArgs) - } - pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: true} - pathFs := pathfs.NewPathNodeFs(finalFs, pathFsOpts) - fuseOpts := &nodefs.Options{ - // These options are to be compatible with libfuse defaults, - // making benchmarking easier. - NegativeTimeout: time.Second, - AttrTimeout: time.Second, - EntryTimeout: time.Second, - } - conn := nodefs.NewFileSystemConnector(pathFs.Root(), fuseOpts) - var mOpts fuse.MountOptions - mOpts.AllowOther = false - if args.allow_other { - tlog.Info.Printf(tlog.ColorYellow + "The option \"-allow_other\" is set. Make sure the file " + - "permissions protect your data from unwanted access." + tlog.ColorReset) - mOpts.AllowOther = true - // Make the kernel check the file permissions for us - mOpts.Options = append(mOpts.Options, "default_permissions") - } - if args.nonempty { - mOpts.Options = append(mOpts.Options, "nonempty") - } - // Set values shown in "df -T" and friends - // First column, "Filesystem" - mOpts.Options = append(mOpts.Options, "fsname="+args.cipherdir) - // Second column, "Type", will be shown as "fuse." + Name - mOpts.Name = "gocryptfs" - if args.reverse { - mOpts.Name += "-reverse" - } - - // The kernel enforces read-only operation, we just have to pass "ro". - // Reverse mounts are always read-only - if args.ro || args.reverse { - mOpts.Options = append(mOpts.Options, "ro") - } - // Add additional mount options (if any) after the stock ones, so the user has - // a chance to override them. - if args.o != "" { - parts := strings.Split(args.o, ",") - tlog.Debug.Printf("Adding -o mount options: %v", parts) - mOpts.Options = append(mOpts.Options, parts...) - } - srv, err := fuse.NewServer(conn.RawFS(), args.mountpoint, &mOpts) - if err != nil { - tlog.Fatal.Printf("Mount failed: %v", err) - os.Exit(ErrExitMount) - } - srv.SetDebug(args.fusedebug) - - // All FUSE file and directory create calls carry explicit permission - // information. We need an unrestricted umask to create the files and - // directories with the requested permissions. - syscall.Umask(0000) - - return srv -} - -func handleSigint(srv *fuse.Server, mountpoint string) { - ch := make(chan os.Signal, 1) - signal.Notify(ch, os.Interrupt) - signal.Notify(ch, syscall.SIGTERM) - go func() { - <-ch - err := srv.Unmount() - if err != nil { - tlog.Warn.Print(err) - tlog.Info.Printf("Trying lazy unmount") - cmd := exec.Command("fusermount", "-u", "-z", mountpoint) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Run() - } - os.Exit(1) - }() + os.Exit(doMount(&args)) } |