main: accept multiple -passfile options
Each file will be read and then concatenated for the effictive password. This can be used as a kind of multi-factor authenticiton. Fixes https://github.com/rfjakob/gocryptfs/issues/288
This commit is contained in:
parent
ded4bbe645
commit
416080203b
|
@ -109,7 +109,7 @@ See also `-exclude`, `-exclude-wildcard` and the [EXCLUDING FILES](#excluding-fi
|
||||||
Enable (`-exec`) or disable (`-noexec`) executables in a gocryptfs mount
|
Enable (`-exec`) or disable (`-noexec`) executables in a gocryptfs mount
|
||||||
(default: `-exec`). If both are specified, `-noexec` takes precedence.
|
(default: `-exec`). If both are specified, `-noexec` takes precedence.
|
||||||
|
|
||||||
#### -extpass string
|
#### -extpass CMD [-extpass ARG1 ...]
|
||||||
Use an external program (like ssh-askpass) for the password prompt.
|
Use an external program (like ssh-askpass) for the password prompt.
|
||||||
The program should return the password on stdout, a trailing newline is
|
The program should return the password on stdout, a trailing newline is
|
||||||
stripped by gocryptfs. If you just want to read from a password file, see `-passfile`.
|
stripped by gocryptfs. If you just want to read from a password file, see `-passfile`.
|
||||||
|
@ -302,14 +302,23 @@ built-in crypto is 4x slower unless your CPU has AES instructions and
|
||||||
you are using Go 1.6+. In mode "auto", gocrypts chooses the faster
|
you are using Go 1.6+. In mode "auto", gocrypts chooses the faster
|
||||||
option.
|
option.
|
||||||
|
|
||||||
#### -passfile string
|
#### -passfile FILE [-passfile FILE2 ...]
|
||||||
Read password from the specified file. A warning will be printed if there
|
Read password from the specified plain text file. The file should contain exactly
|
||||||
is more than one line, and only the first line will be used. A single
|
one line (do not use binary files!).
|
||||||
|
A warning will be printed if there is more than one line, and only
|
||||||
|
the first line will be used. A single
|
||||||
trailing newline is allowed and does not cause a warning.
|
trailing newline is allowed and does not cause a warning.
|
||||||
|
|
||||||
Before gocryptfs v1.7, using `-passfile` was equivant to writing
|
Pass this option multiple times to read the first line from multiple
|
||||||
`-extpass="/bin/cat -- FILE"`.
|
files. They are concatenated for the effective password.
|
||||||
gocryptfs v1.7 and later directly read the file without invoking `cat`.
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
echo hello > hello.txt
|
||||||
|
echo word > world.txt
|
||||||
|
gocryptfs -passfile hello.txt -passfile world.txt
|
||||||
|
|
||||||
|
The effective password will be "helloworld".
|
||||||
|
|
||||||
#### -passwd
|
#### -passwd
|
||||||
Change the password. Will ask for the old password, check if it is
|
Change the password. Will ask for the old password, check if it is
|
||||||
|
|
14
cli_args.go
14
cli_args.go
|
@ -32,9 +32,9 @@ type argContainer struct {
|
||||||
// Mount options with opposites
|
// Mount options with opposites
|
||||||
dev, nodev, suid, nosuid, exec, noexec, rw, ro bool
|
dev, nodev, suid, nosuid, exec, noexec, rw, ro bool
|
||||||
masterkey, mountpoint, cipherdir, cpuprofile,
|
masterkey, mountpoint, cipherdir, cpuprofile,
|
||||||
memprofile, ko, passfile, ctlsock, fsname, force_owner, trace string
|
memprofile, ko, ctlsock, fsname, force_owner, trace string
|
||||||
// -extpass and -badname can be passed multiple times
|
// -extpass, -badname, -passfile can be passed multiple times
|
||||||
extpass, badname multipleStrings
|
extpass, badname, passfile multipleStrings
|
||||||
// For reverse mode, several ways to specify exclusions. All can be specified multiple times.
|
// For reverse mode, several ways to specify exclusions. All can be specified multiple times.
|
||||||
exclude, excludeWildcard, excludeFrom multipleStrings
|
exclude, excludeWildcard, excludeFrom multipleStrings
|
||||||
// Configuration file name override
|
// Configuration file name override
|
||||||
|
@ -184,7 +184,6 @@ func parseCliOpts() (args argContainer) {
|
||||||
flagSet.StringVar(&args.cpuprofile, "cpuprofile", "", "Write cpu profile to specified file")
|
flagSet.StringVar(&args.cpuprofile, "cpuprofile", "", "Write cpu profile to specified file")
|
||||||
flagSet.StringVar(&args.memprofile, "memprofile", "", "Write memory profile to specified file")
|
flagSet.StringVar(&args.memprofile, "memprofile", "", "Write memory profile to specified file")
|
||||||
flagSet.StringVar(&args.config, "config", "", "Use specified config file instead of CIPHERDIR/gocryptfs.conf")
|
flagSet.StringVar(&args.config, "config", "", "Use specified config file instead of CIPHERDIR/gocryptfs.conf")
|
||||||
flagSet.StringVar(&args.passfile, "passfile", "", "Read password from file")
|
|
||||||
flagSet.StringVar(&args.ko, "ko", "", "Pass additional options directly to the kernel, comma-separated list")
|
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.ctlsock, "ctlsock", "", "Create control socket at specified path")
|
||||||
flagSet.StringVar(&args.fsname, "fsname", "", "Override the filesystem name")
|
flagSet.StringVar(&args.fsname, "fsname", "", "Override the filesystem name")
|
||||||
|
@ -198,9 +197,10 @@ func parseCliOpts() (args argContainer) {
|
||||||
flagSet.Var(&args.excludeWildcard, "exclude-wildcard", "Exclude path from reverse view, supporting wildcards")
|
flagSet.Var(&args.excludeWildcard, "exclude-wildcard", "Exclude path from reverse view, supporting wildcards")
|
||||||
flagSet.Var(&args.excludeFrom, "exclude-from", "File from which to read exclusion patterns (with -exclude-wildcard syntax)")
|
flagSet.Var(&args.excludeFrom, "exclude-from", "File from which to read exclusion patterns (with -exclude-wildcard syntax)")
|
||||||
|
|
||||||
// -extpass
|
// multipleStrings options ([]string)
|
||||||
flagSet.Var(&args.extpass, "extpass", "Use external program for the password prompt")
|
flagSet.Var(&args.extpass, "extpass", "Use external program for the password prompt")
|
||||||
flagSet.Var(&args.badname, "badname", "Glob pattern invalid file names that should be shown")
|
flagSet.Var(&args.badname, "badname", "Glob pattern invalid file names that should be shown")
|
||||||
|
flagSet.Var(&args.passfile, "passfile", "Read password from file")
|
||||||
|
|
||||||
flagSet.IntVar(&args.notifypid, "notifypid", 0, "Send USR1 to the specified process after "+
|
flagSet.IntVar(&args.notifypid, "notifypid", 0, "Send USR1 to the specified process after "+
|
||||||
"successful mount - used internally for daemonization")
|
"successful mount - used internally for daemonization")
|
||||||
|
@ -267,11 +267,11 @@ func parseCliOpts() (args argContainer) {
|
||||||
args.allow_other = false
|
args.allow_other = false
|
||||||
args.ko = "noexec"
|
args.ko = "noexec"
|
||||||
}
|
}
|
||||||
if !args.extpass.Empty() && args.passfile != "" {
|
if !args.extpass.Empty() && len(args.passfile) != 0 {
|
||||||
tlog.Fatal.Printf("The options -extpass and -passfile cannot be used at the same time")
|
tlog.Fatal.Printf("The options -extpass and -passfile cannot be used at the same time")
|
||||||
os.Exit(exitcodes.Usage)
|
os.Exit(exitcodes.Usage)
|
||||||
}
|
}
|
||||||
if args.passfile != "" && args.masterkey != "" {
|
if len(args.passfile) != 0 && args.masterkey != "" {
|
||||||
tlog.Fatal.Printf("The options -passfile and -masterkey cannot be used at the same time")
|
tlog.Fatal.Printf("The options -passfile and -masterkey cannot be used at the same time")
|
||||||
os.Exit(exitcodes.Usage)
|
os.Exit(exitcodes.Usage)
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ func main() {
|
||||||
|
|
||||||
func dumpMasterKey(fn string) {
|
func dumpMasterKey(fn string) {
|
||||||
tlog.Info.Enabled = false
|
tlog.Info.Enabled = false
|
||||||
pw := readpassword.Once(nil, "", "")
|
pw := readpassword.Once(nil, nil, "")
|
||||||
masterkey, _, err := configfile.LoadAndDecrypt(fn, pw)
|
masterkey, _, err := configfile.LoadAndDecrypt(fn, pw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
|
2
help.go
2
help.go
|
@ -33,7 +33,7 @@ Common Options (use -hh to show all):
|
||||||
-masterkey Mount with explicit master key instead of password
|
-masterkey Mount with explicit master key instead of password
|
||||||
-nonempty Allow mounting over non-empty directory
|
-nonempty Allow mounting over non-empty directory
|
||||||
-nosyslog Do not redirect log messages to syslog
|
-nosyslog Do not redirect log messages to syslog
|
||||||
-passfile Read password from file
|
-passfile Read password from plain text file(s)
|
||||||
-passwd Change password
|
-passwd Change password
|
||||||
-plaintextnames Do not encrypt file names (with -init)
|
-plaintextnames Do not encrypt file names (with -init)
|
||||||
-q, -quiet Silence informational messages
|
-q, -quiet Silence informational messages
|
||||||
|
|
|
@ -71,7 +71,7 @@ func initDir(args *argContainer) {
|
||||||
tlog.Info.Printf("Choose a password for protecting your files.")
|
tlog.Info.Printf("Choose a password for protecting your files.")
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
password := readpassword.Twice([]string(args.extpass), args.passfile)
|
password := readpassword.Twice([]string(args.extpass), []string(args.passfile))
|
||||||
creator := tlog.ProgramName + " " + GitVersion
|
creator := tlog.ProgramName + " " + GitVersion
|
||||||
err = configfile.Create(args.config, password, args.plaintextnames,
|
err = configfile.Create(args.config, password, args.plaintextnames,
|
||||||
args.scryptn, creator, args.aessiv, args.devrandom)
|
args.scryptn, creator, args.aessiv, args.devrandom)
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestExtpass(t *testing.T) {
|
||||||
|
|
||||||
func TestOnceExtpass(t *testing.T) {
|
func TestOnceExtpass(t *testing.T) {
|
||||||
p1 := "lkadsf0923rdfi48rqwhdsf"
|
p1 := "lkadsf0923rdfi48rqwhdsf"
|
||||||
p2 := string(Once([]string{"echo " + p1}, "", ""))
|
p2 := string(Once([]string{"echo " + p1}, nil, ""))
|
||||||
if p1 != p2 {
|
if p1 != p2 {
|
||||||
t.Errorf("p1=%q != p2=%q", p1, p2)
|
t.Errorf("p1=%q != p2=%q", p1, p2)
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ func TestOnceExtpass(t *testing.T) {
|
||||||
// extpass with two arguments
|
// extpass with two arguments
|
||||||
func TestOnceExtpass2(t *testing.T) {
|
func TestOnceExtpass2(t *testing.T) {
|
||||||
p1 := "foo"
|
p1 := "foo"
|
||||||
p2 := string(Once([]string{"echo", p1}, "", ""))
|
p2 := string(Once([]string{"echo", p1}, nil, ""))
|
||||||
if p1 != p2 {
|
if p1 != p2 {
|
||||||
t.Errorf("p1=%q != p2=%q", p1, p2)
|
t.Errorf("p1=%q != p2=%q", p1, p2)
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ func TestOnceExtpass2(t *testing.T) {
|
||||||
// extpass with three arguments
|
// extpass with three arguments
|
||||||
func TestOnceExtpass3(t *testing.T) {
|
func TestOnceExtpass3(t *testing.T) {
|
||||||
p1 := "foo bar baz"
|
p1 := "foo bar baz"
|
||||||
p2 := string(Once([]string{"echo", "foo", "bar", "baz"}, "", ""))
|
p2 := string(Once([]string{"echo", "foo", "bar", "baz"}, nil, ""))
|
||||||
if p1 != p2 {
|
if p1 != p2 {
|
||||||
t.Errorf("p1=%q != p2=%q", p1, p2)
|
t.Errorf("p1=%q != p2=%q", p1, p2)
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ func TestOnceExtpass3(t *testing.T) {
|
||||||
|
|
||||||
func TestOnceExtpassSpaces(t *testing.T) {
|
func TestOnceExtpassSpaces(t *testing.T) {
|
||||||
p1 := "mypassword"
|
p1 := "mypassword"
|
||||||
p2 := string(Once([]string{"cat", "passfile_test_files/file with spaces.txt"}, "", ""))
|
p2 := string(Once([]string{"cat", "passfile_test_files/file with spaces.txt"}, nil, ""))
|
||||||
if p1 != p2 {
|
if p1 != p2 {
|
||||||
t.Errorf("p1=%q != p2=%q", p1, p2)
|
t.Errorf("p1=%q != p2=%q", p1, p2)
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ func TestOnceExtpassSpaces(t *testing.T) {
|
||||||
|
|
||||||
func TestTwiceExtpass(t *testing.T) {
|
func TestTwiceExtpass(t *testing.T) {
|
||||||
p1 := "w5w44t3wfe45srz434"
|
p1 := "w5w44t3wfe45srz434"
|
||||||
p2 := string(Once([]string{"echo " + p1}, "", ""))
|
p2 := string(Once([]string{"echo " + p1}, nil, ""))
|
||||||
if p1 != p2 {
|
if p1 != p2 {
|
||||||
t.Errorf("p1=%q != p2=%q", p1, p2)
|
t.Errorf("p1=%q != p2=%q", p1, p2)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,16 @@ import (
|
||||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
"github.com/rfjakob/gocryptfs/internal/tlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// readPassFileConcatenate reads the first line from each file name and
|
||||||
|
// concatenates the results. The result does not contain any newlines.
|
||||||
|
func readPassFileConcatenate(passfileSlice []string) (result []byte) {
|
||||||
|
for _, e := range passfileSlice {
|
||||||
|
result = append(result, readPassFile(e)...)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// readPassFile reads the first line from the passed file name.
|
||||||
func readPassFile(passfile string) []byte {
|
func readPassFile(passfile string) []byte {
|
||||||
tlog.Info.Printf("passfile: reading from file %q", passfile)
|
tlog.Info.Printf("passfile: reading from file %q", passfile)
|
||||||
f, err := os.Open(passfile)
|
f, err := os.Open(passfile)
|
||||||
|
@ -36,7 +46,7 @@ func readPassFile(passfile string) []byte {
|
||||||
os.Exit(exitcodes.ReadPassword)
|
os.Exit(exitcodes.ReadPassword)
|
||||||
}
|
}
|
||||||
if len(lines) > 1 && len(lines[1]) > 0 {
|
if len(lines) > 1 && len(lines[1]) > 0 {
|
||||||
tlog.Warn.Printf("passfile: ignoring trailing garbage (%d bytes) after first line",
|
tlog.Warn.Printf("warning: passfile: ignoring trailing garbage (%d bytes) after first line",
|
||||||
len(lines[1]))
|
len(lines[1]))
|
||||||
}
|
}
|
||||||
return lines[0]
|
return lines[0]
|
||||||
|
|
|
@ -21,13 +21,20 @@ func TestPassfile(t *testing.T) {
|
||||||
if string(pw) != tc.want {
|
if string(pw) != tc.want {
|
||||||
t.Errorf("Wrong result: want=%q have=%q", tc.want, pw)
|
t.Errorf("Wrong result: want=%q have=%q", tc.want, pw)
|
||||||
}
|
}
|
||||||
|
// Calling readPassFileConcatenate with only one element should give the
|
||||||
|
// same result
|
||||||
|
pw = readPassFileConcatenate([]string{"passfile_test_files/" + tc.file})
|
||||||
|
if string(pw) != tc.want {
|
||||||
|
t.Errorf("Wrong result: want=%q have=%q", tc.want, pw)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// readPassFile() should exit instead of returning an empty string.
|
// readPassFile() should exit instead of returning an empty string.
|
||||||
//
|
//
|
||||||
// The TEST_SLAVE magic is explained at
|
// The TEST_SLAVE magic is explained at
|
||||||
// https://talks.golang.org/2014/testing.slide#23 .
|
// https://talks.golang.org/2014/testing.slide#23 , mirror:
|
||||||
|
// http://web.archive.org/web/20200426174352/https://talks.golang.org/2014/testing.slide#23
|
||||||
func TestPassfileEmpty(t *testing.T) {
|
func TestPassfileEmpty(t *testing.T) {
|
||||||
if os.Getenv("TEST_SLAVE") == "1" {
|
if os.Getenv("TEST_SLAVE") == "1" {
|
||||||
readPassFile("passfile_test_files/empty.txt")
|
readPassFile("passfile_test_files/empty.txt")
|
||||||
|
@ -46,7 +53,8 @@ func TestPassfileEmpty(t *testing.T) {
|
||||||
// readPassFile() should exit instead of returning an empty string.
|
// readPassFile() should exit instead of returning an empty string.
|
||||||
//
|
//
|
||||||
// The TEST_SLAVE magic is explained at
|
// The TEST_SLAVE magic is explained at
|
||||||
// https://talks.golang.org/2014/testing.slide#23 .
|
// https://talks.golang.org/2014/testing.slide#23 , mirror:
|
||||||
|
// http://web.archive.org/web/20200426174352/https://talks.golang.org/2014/testing.slide#23
|
||||||
func TestPassfileNewline(t *testing.T) {
|
func TestPassfileNewline(t *testing.T) {
|
||||||
if os.Getenv("TEST_SLAVE") == "1" {
|
if os.Getenv("TEST_SLAVE") == "1" {
|
||||||
readPassFile("passfile_test_files/newline.txt")
|
readPassFile("passfile_test_files/newline.txt")
|
||||||
|
@ -65,7 +73,8 @@ func TestPassfileNewline(t *testing.T) {
|
||||||
// readPassFile() should exit instead of returning an empty string.
|
// readPassFile() should exit instead of returning an empty string.
|
||||||
//
|
//
|
||||||
// The TEST_SLAVE magic is explained at
|
// The TEST_SLAVE magic is explained at
|
||||||
// https://talks.golang.org/2014/testing.slide#23 .
|
// https://talks.golang.org/2014/testing.slide#23 , mirror:
|
||||||
|
// http://web.archive.org/web/20200426174352/https://talks.golang.org/2014/testing.slide#23
|
||||||
func TestPassfileEmptyFirstLine(t *testing.T) {
|
func TestPassfileEmptyFirstLine(t *testing.T) {
|
||||||
if os.Getenv("TEST_SLAVE") == "1" {
|
if os.Getenv("TEST_SLAVE") == "1" {
|
||||||
readPassFile("passfile_test_files/empty_first_line.txt")
|
readPassFile("passfile_test_files/empty_first_line.txt")
|
||||||
|
@ -79,3 +88,15 @@ func TestPassfileEmptyFirstLine(t *testing.T) {
|
||||||
}
|
}
|
||||||
t.Fatal("should have exited")
|
t.Fatal("should have exited")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestPassFileConcatenate tests readPassFileConcatenate
|
||||||
|
func TestPassFileConcatenate(t *testing.T) {
|
||||||
|
files := []string{
|
||||||
|
"passfile_test_files/file with spaces.txt",
|
||||||
|
"passfile_test_files/mypassword_garbage.txt",
|
||||||
|
}
|
||||||
|
res := string(readPassFileConcatenate(files))
|
||||||
|
if res != "mypasswordmypassword" {
|
||||||
|
t.Errorf("wrong result: %q", res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -20,11 +20,11 @@ const (
|
||||||
maxPasswordLen = 2048
|
maxPasswordLen = 2048
|
||||||
)
|
)
|
||||||
|
|
||||||
// Once tries to get a password from the user, either from the terminal, extpass
|
// Once tries to get a password from the user, either from the terminal, extpass, passfile
|
||||||
// or stdin. Leave "prompt" empty to use the default "Password: " prompt.
|
// or stdin. Leave "prompt" empty to use the default "Password: " prompt.
|
||||||
func Once(extpass []string, passfile string, prompt string) []byte {
|
func Once(extpass []string, passfile []string, prompt string) []byte {
|
||||||
if passfile != "" {
|
if len(passfile) != 0 {
|
||||||
return readPassFile(passfile)
|
return readPassFileConcatenate(passfile)
|
||||||
}
|
}
|
||||||
if len(extpass) != 0 {
|
if len(extpass) != 0 {
|
||||||
return readPasswordExtpass(extpass)
|
return readPasswordExtpass(extpass)
|
||||||
|
@ -40,9 +40,9 @@ func Once(extpass []string, passfile string, prompt string) []byte {
|
||||||
|
|
||||||
// Twice is the same as Once but will prompt twice if we get the password from
|
// Twice is the same as Once but will prompt twice if we get the password from
|
||||||
// the terminal.
|
// the terminal.
|
||||||
func Twice(extpass []string, passfile string) []byte {
|
func Twice(extpass []string, passfile []string) []byte {
|
||||||
if passfile != "" {
|
if len(passfile) != 0 {
|
||||||
return readPassFile(passfile)
|
return readPassFileConcatenate(passfile)
|
||||||
}
|
}
|
||||||
if len(extpass) != 0 {
|
if len(extpass) != 0 {
|
||||||
return readPasswordExtpass(extpass)
|
return readPasswordExtpass(extpass)
|
||||||
|
|
4
main.go
4
main.go
|
@ -50,7 +50,7 @@ func loadConfig(args *argContainer) (masterkey []byte, cf *configfile.ConfFile,
|
||||||
if masterkey != nil {
|
if masterkey != nil {
|
||||||
return masterkey, cf, nil
|
return masterkey, cf, nil
|
||||||
}
|
}
|
||||||
pw := readpassword.Once([]string(args.extpass), args.passfile, "")
|
pw := readpassword.Once([]string(args.extpass), []string(args.passfile), "")
|
||||||
tlog.Info.Println("Decrypting master key")
|
tlog.Info.Println("Decrypting master key")
|
||||||
masterkey, err = cf.DecryptMasterKey(pw)
|
masterkey, err = cf.DecryptMasterKey(pw)
|
||||||
for i := range pw {
|
for i := range pw {
|
||||||
|
@ -79,7 +79,7 @@ func changePassword(args *argContainer) {
|
||||||
log.Panic("empty masterkey")
|
log.Panic("empty masterkey")
|
||||||
}
|
}
|
||||||
tlog.Info.Println("Please enter your new password.")
|
tlog.Info.Println("Please enter your new password.")
|
||||||
newPw := readpassword.Twice([]string(args.extpass), args.passfile)
|
newPw := readpassword.Twice([]string(args.extpass), []string(args.passfile))
|
||||||
logN := confFile.ScryptObject.LogN()
|
logN := confFile.ScryptObject.LogN()
|
||||||
if args._explicitScryptn {
|
if args._explicitScryptn {
|
||||||
logN = args.scryptn
|
logN = args.scryptn
|
||||||
|
|
|
@ -39,7 +39,7 @@ func unhexMasterKey(masterkey string, fromStdin bool) []byte {
|
||||||
func handleArgsMasterkey(args *argContainer) (masterkey []byte) {
|
func handleArgsMasterkey(args *argContainer) (masterkey []byte) {
|
||||||
// "-masterkey=stdin"
|
// "-masterkey=stdin"
|
||||||
if args.masterkey == "stdin" {
|
if args.masterkey == "stdin" {
|
||||||
in := string(readpassword.Once(nil, "", "Masterkey"))
|
in := string(readpassword.Once(nil, nil, "Masterkey"))
|
||||||
return unhexMasterKey(in, true)
|
return unhexMasterKey(in, true)
|
||||||
}
|
}
|
||||||
// "-masterkey=941a6029-3adc6a1c-..."
|
// "-masterkey=941a6029-3adc6a1c-..."
|
||||||
|
|
|
@ -741,3 +741,25 @@ func TestBadname(t *testing.T) {
|
||||||
t.Errorf("did not find invalid name %s in %v", invalid_file_name, names)
|
t.Errorf("did not find invalid name %s in %v", invalid_file_name, names)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestPassfile tests the `-passfile` option
|
||||||
|
func TestPassfile(t *testing.T) {
|
||||||
|
dir := test_helpers.InitFS(t)
|
||||||
|
mnt := dir + ".mnt"
|
||||||
|
passfile1 := mnt + ".1.txt"
|
||||||
|
ioutil.WriteFile(passfile1, []byte("test"), 0600)
|
||||||
|
test_helpers.MountOrFatal(t, dir, mnt, "-passfile="+passfile1)
|
||||||
|
defer test_helpers.UnmountPanic(mnt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestPassfileX2 tests that the `-passfile` option can be passed twice
|
||||||
|
func TestPassfileX2(t *testing.T) {
|
||||||
|
dir := test_helpers.InitFS(t)
|
||||||
|
mnt := dir + ".mnt"
|
||||||
|
passfile1 := mnt + ".1.txt"
|
||||||
|
passfile2 := mnt + ".2.txt"
|
||||||
|
ioutil.WriteFile(passfile1, []byte("te"), 0600)
|
||||||
|
ioutil.WriteFile(passfile2, []byte("st"), 0600)
|
||||||
|
test_helpers.MountOrFatal(t, dir, mnt, "-passfile="+passfile1, "-passfile="+passfile2)
|
||||||
|
defer test_helpers.UnmountPanic(mnt)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue