aboutsummaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go210
1 files changed, 3 insertions, 207 deletions
diff --git a/main.go b/main.go
index 9fc9b6b..467a143 100644
--- a/main.go
+++ b/main.go
@@ -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))
}