From 991adfc934d714897e3c0ad39d37fca3edf59bcb Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Mon, 13 May 2019 23:01:44 +0200 Subject: [PATCH] -passwd now takes a passed -scryptn flag into account https://github.com/rfjakob/gocryptfs/issues/400 --- README.md | 2 ++ cli_args.go | 21 ++++++++++++++++++++- main.go | 6 +++++- tests/cli/cli_test.go | 21 +++++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4ada2a1..24c75a9 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,8 @@ vNEXT, in progress Note: as a security precaution, the owner must still manually `chmod gocryptfs.conf 0440` to allow mounting. * Allow the `nofail` option in `/etc/fstab` +* `-passwd` can now change the `-scryptn` parameter for existing filesystems + ([#400](https://github.com/rfjakob/gocryptfs/issues/400)) v1.7, 2019-03-17 * **Fix possible symlink race attacks in forward mode** when using allow_other + plaintextnames diff --git a/cli_args.go b/cli_args.go index f1cefb4..cae7723 100644 --- a/cli_args.go +++ b/cli_args.go @@ -50,6 +50,8 @@ type argContainer struct { _ctlsockFd net.Listener // _forceOwner is, if non-nil, a parsed, validated Owner (as opposed to the string above) _forceOwner *fuse.Owner + // _explicitScryptn is true then the user passed "-scryptn=xyz" + _explicitScryptn bool } type multipleStrings []string @@ -205,7 +207,8 @@ func parseCliOpts() (args argContainer) { 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. "+ + const scryptn = "scryptn" + flagSet.IntVar(&args.scryptn, scryptn, configfile.ScryptDefaultLogN, "scrypt cost parameter logN. Possible values: 10-28. "+ "A lower value speeds up mounting and reduces its memory needs, but makes the password susceptible to brute-force attacks") flagSet.DurationVar(&args.idle, "i", 0, "Alias for -idle") @@ -227,6 +230,10 @@ func parseCliOpts() (args argContainer) { tlog.Fatal.Printf("Invalid command line: %s. Try '%s -help'.", prettyArgs(), tlog.ProgramName) os.Exit(exitcodes.Usage) } + // We want to know if -scryptn was passed explicitely + if isFlagPassed(flagSet, scryptn) { + args._explicitScryptn = true + } // "-openssl" needs some post-processing if opensslAuto == "auto" { args.openssl = prefer_openssl.PreferOpenSSL() @@ -311,3 +318,15 @@ func countOpFlags(args *argContainer) int { } return count } + +// isFlagPassed finds out if the flag was explictely passed on the command line. +// https://stackoverflow.com/a/54747682/1380267 +func isFlagPassed(flagSet *flag.FlagSet, name string) bool { + found := false + flagSet.Visit(func(f *flag.Flag) { + if f.Name == name { + found = true + } + }) + return found +} diff --git a/main.go b/main.go index 40fd8ac..b96ebf0 100644 --- a/main.go +++ b/main.go @@ -94,7 +94,11 @@ func changePassword(args *argContainer) { } tlog.Info.Println("Please enter your new password.") newPw := readpassword.Twice([]string(args.extpass), args.passfile) - confFile.EncryptKey(masterkey, newPw, confFile.ScryptObject.LogN()) + logN := confFile.ScryptObject.LogN() + if args._explicitScryptn { + logN = args.scryptn + } + confFile.EncryptKey(masterkey, newPw, logN) for i := range newPw { newPw[i] = 0 } diff --git a/tests/cli/cli_test.go b/tests/cli/cli_test.go index 7b6736a..da9d508 100644 --- a/tests/cli/cli_test.go +++ b/tests/cli/cli_test.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "os/exec" + "strconv" "syscall" "testing" "time" @@ -92,6 +93,9 @@ func TestInitReverse(t *testing.T) { } } +// testPasswd changes the password from "test" to "test" using +// the -extpass method, then from "test" to "newpasswd" using the +// stdin method. func testPasswd(t *testing.T, dir string, extraArgs ...string) { // Change password using "-extpass" args := []string{"-q", "-passwd", "-extpass", "echo test"} @@ -225,6 +229,23 @@ func TestPasswdReverse(t *testing.T) { testPasswd(t, dir, "-reverse") } +// Test -passwd with -scryptn +func TestPasswdScryptn(t *testing.T) { + dir := test_helpers.InitFS(t) + cf, err := configfile.Load(dir + "/gocryptfs.conf") + if err != nil { + t.Fatal(err) + } + testPasswd(t, dir, "-scryptn", strconv.Itoa(cf.ScryptObject.LogN()+1)) + cf2, err := configfile.Load(dir + "/gocryptfs.conf") + if err != nil { + t.Fatal(err) + } + if cf2.ScryptObject.LogN() != cf.ScryptObject.LogN()+1 { + t.Errorf("wrong logN value %d", cf2.ScryptObject.LogN()) + } +} + // Test -init & -config flag func TestInitConfig(t *testing.T) { config := test_helpers.TmpDir + "/TestInitConfig.conf"