exitcodes: pull all exit code definitions into the package

This commit defines all exit codes in one place in the exitcodes
package.

Also, it adds a test to verify the exit code on incorrect
password, which is what SiriKali cares about the most.

Fixes https://github.com/rfjakob/gocryptfs/issues/77 .
This commit is contained in:
Jakob Unterwurzacher 2017-05-07 22:15:01 +02:00
parent ad7942f434
commit d5adde1eeb
11 changed files with 106 additions and 66 deletions

View File

@ -9,6 +9,7 @@ import (
"strings" "strings"
"github.com/rfjakob/gocryptfs/internal/configfile" "github.com/rfjakob/gocryptfs/internal/configfile"
"github.com/rfjakob/gocryptfs/internal/exitcodes"
"github.com/rfjakob/gocryptfs/internal/prefer_openssl" "github.com/rfjakob/gocryptfs/internal/prefer_openssl"
"github.com/rfjakob/gocryptfs/internal/stupidgcm" "github.com/rfjakob/gocryptfs/internal/stupidgcm"
"github.com/rfjakob/gocryptfs/internal/tlog" "github.com/rfjakob/gocryptfs/internal/tlog"
@ -56,7 +57,7 @@ func prefixOArgs(osArgs []string) []string {
// Last argument? // Last argument?
if i+1 >= len(osArgs) { if i+1 >= len(osArgs) {
tlog.Fatal.Printf("The \"-o\" option requires an argument") tlog.Fatal.Printf("The \"-o\" option requires an argument")
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
oOpts = strings.Split(osArgs[i+1], ",") oOpts = strings.Split(osArgs[i+1], ",")
// Skip over the arguments to "-o" // Skip over the arguments to "-o"
@ -76,7 +77,7 @@ func prefixOArgs(osArgs []string) []string {
} }
if o == "o" || o == "-o" { if o == "o" || o == "-o" {
tlog.Fatal.Printf("You can't pass \"-o\" to \"-o\"") tlog.Fatal.Printf("You can't pass \"-o\" to \"-o\"")
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
newArgs = append(newArgs, "-"+o) newArgs = append(newArgs, "-"+o)
} }
@ -153,7 +154,7 @@ func parseCliOpts() (args argContainer) {
if err != nil { if err != nil {
tlog.Warn.Printf("You passed: %s", prettyArgs()) tlog.Warn.Printf("You passed: %s", prettyArgs())
tlog.Fatal.Printf("%v", err) tlog.Fatal.Printf("%v", err)
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
// "-openssl" needs some post-processing // "-openssl" needs some post-processing
if opensslAuto == "auto" { if opensslAuto == "auto" {
@ -162,27 +163,27 @@ func parseCliOpts() (args argContainer) {
args.openssl, err = strconv.ParseBool(opensslAuto) args.openssl, err = strconv.ParseBool(opensslAuto)
if err != nil { if err != nil {
tlog.Fatal.Printf("Invalid \"-openssl\" setting: %v", err) tlog.Fatal.Printf("Invalid \"-openssl\" setting: %v", err)
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
} }
// "-forcedecode" only works with openssl. Check compilation and command line parameters // "-forcedecode" only works with openssl. Check compilation and command line parameters
if args.forcedecode == true { if args.forcedecode == true {
if stupidgcm.BuiltWithoutOpenssl == true { if stupidgcm.BuiltWithoutOpenssl == true {
tlog.Fatal.Printf("The -forcedecode flag requires openssl support, but gocryptfs was compiled without it!") tlog.Fatal.Printf("The -forcedecode flag requires openssl support, but gocryptfs was compiled without it!")
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
if args.aessiv == true { if args.aessiv == true {
tlog.Fatal.Printf("The -forcedecode and -aessiv flags are incompatible because they use different crypto libs (openssl vs native Go)") tlog.Fatal.Printf("The -forcedecode and -aessiv flags are incompatible because they use different crypto libs (openssl vs native Go)")
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
if args.reverse == true { if args.reverse == true {
tlog.Fatal.Printf("The reverse mode and the -forcedecode option are not compatible") tlog.Fatal.Printf("The reverse mode and the -forcedecode option are not compatible")
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
// Has the user explicitely disabled openssl using "-openssl=false/0"? // Has the user explicitely disabled openssl using "-openssl=false/0"?
if !args.openssl && opensslAuto != "auto" { if !args.openssl && opensslAuto != "auto" {
tlog.Fatal.Printf("-forcedecode requires openssl, but is disabled via command-line option") tlog.Fatal.Printf("-forcedecode requires openssl, but is disabled via command-line option")
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
args.openssl = true args.openssl = true
@ -197,7 +198,7 @@ func parseCliOpts() (args argContainer) {
} }
if args.extpass != "" && args.masterkey != "" { if args.extpass != "" && args.masterkey != "" {
tlog.Fatal.Printf("The options -extpass and -masterkey cannot be used at the same time") tlog.Fatal.Printf("The options -extpass and -masterkey cannot be used at the same time")
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
return args return args
} }

View File

@ -7,6 +7,7 @@ import (
"os/signal" "os/signal"
"syscall" "syscall"
"github.com/rfjakob/gocryptfs/internal/exitcodes"
"github.com/rfjakob/gocryptfs/internal/tlog" "github.com/rfjakob/gocryptfs/internal/tlog"
) )
@ -36,7 +37,7 @@ func forkChild() int {
err := c.Start() err := c.Start()
if err != nil { if err != nil {
tlog.Fatal.Printf("forkChild: starting %s failed: %v\n", name, err) tlog.Fatal.Printf("forkChild: starting %s failed: %v\n", name, err)
return 1 return exitcodes.ForkChild
} }
err = c.Wait() err = c.Wait()
if err != nil { if err != nil {
@ -46,7 +47,7 @@ func forkChild() int {
} }
} }
tlog.Fatal.Printf("forkChild: wait returned an unknown error: %v\n", err) tlog.Fatal.Printf("forkChild: wait returned an unknown error: %v\n", err)
return 1 return exitcodes.ForkChild
} }
// The child exited with 0 - let's do the same. // The child exited with 0 - let's do the same.
return 0 return 0

View File

@ -6,6 +6,7 @@ import (
"strings" "strings"
"github.com/rfjakob/gocryptfs/internal/configfile" "github.com/rfjakob/gocryptfs/internal/configfile"
"github.com/rfjakob/gocryptfs/internal/exitcodes"
"github.com/rfjakob/gocryptfs/internal/nametransform" "github.com/rfjakob/gocryptfs/internal/nametransform"
"github.com/rfjakob/gocryptfs/internal/readpassword" "github.com/rfjakob/gocryptfs/internal/readpassword"
"github.com/rfjakob/gocryptfs/internal/tlog" "github.com/rfjakob/gocryptfs/internal/tlog"
@ -22,13 +23,13 @@ func initDir(args *argContainer) {
_, err = os.Stat(args.config) _, err = os.Stat(args.config)
if err == nil { if err == nil {
tlog.Fatal.Printf("Config file %q already exists", args.config) tlog.Fatal.Printf("Config file %q already exists", args.config)
os.Exit(ErrExitInit) os.Exit(exitcodes.Init)
} }
} else { } else {
err = checkDirEmpty(args.cipherdir) err = checkDirEmpty(args.cipherdir)
if err != nil { if err != nil {
tlog.Fatal.Printf("Invalid cipherdir: %v", err) tlog.Fatal.Printf("Invalid cipherdir: %v", err)
os.Exit(ErrExitInit) os.Exit(exitcodes.Init)
} }
} }
// Choose password for config file // Choose password for config file
@ -41,7 +42,7 @@ func initDir(args *argContainer) {
err = configfile.CreateConfFile(args.config, password, args.plaintextnames, args.scryptn, creator, args.aessiv) err = configfile.CreateConfFile(args.config, password, args.plaintextnames, args.scryptn, creator, args.aessiv)
if err != nil { if err != nil {
tlog.Fatal.Println(err) tlog.Fatal.Println(err)
os.Exit(ErrExitInit) os.Exit(exitcodes.Init)
} }
// Forward mode with filename encryption enabled needs a gocryptfs.diriv // Forward mode with filename encryption enabled needs a gocryptfs.diriv
// in the root dir // in the root dir
@ -49,7 +50,7 @@ func initDir(args *argContainer) {
err = nametransform.WriteDirIV(args.cipherdir) err = nametransform.WriteDirIV(args.cipherdir)
if err != nil { if err != nil {
tlog.Fatal.Println(err) tlog.Fatal.Println(err)
os.Exit(ErrExitInit) os.Exit(exitcodes.Init)
} }
} }
mountArgs := "" mountArgs := ""

View File

@ -8,6 +8,7 @@ import (
"golang.org/x/crypto/scrypt" "golang.org/x/crypto/scrypt"
"github.com/rfjakob/gocryptfs/internal/cryptocore" "github.com/rfjakob/gocryptfs/internal/cryptocore"
"github.com/rfjakob/gocryptfs/internal/exitcodes"
"github.com/rfjakob/gocryptfs/internal/tlog" "github.com/rfjakob/gocryptfs/internal/tlog"
) )
@ -84,22 +85,22 @@ func (s *ScryptKDF) validateParams() {
minN := 1 << scryptMinLogN minN := 1 << scryptMinLogN
if s.N < minN { if s.N < minN {
tlog.Fatal.Println("Fatal: scryptn below 10 is too low to make sense") tlog.Fatal.Println("Fatal: scryptn below 10 is too low to make sense")
os.Exit(1) os.Exit(exitcodes.ScryptParams)
} }
if s.R < scryptMinR { if s.R < scryptMinR {
tlog.Fatal.Printf("Fatal: scrypt parameter R below minimum: value=%d, min=%d", s.R, scryptMinR) tlog.Fatal.Printf("Fatal: scrypt parameter R below minimum: value=%d, min=%d", s.R, scryptMinR)
os.Exit(1) os.Exit(exitcodes.ScryptParams)
} }
if s.P < scryptMinP { if s.P < scryptMinP {
tlog.Fatal.Printf("Fatal: scrypt parameter P below minimum: value=%d, min=%d", s.P, scryptMinP) tlog.Fatal.Printf("Fatal: scrypt parameter P below minimum: value=%d, min=%d", s.P, scryptMinP)
os.Exit(1) os.Exit(exitcodes.ScryptParams)
} }
if len(s.Salt) < scryptMinSaltLen { if len(s.Salt) < scryptMinSaltLen {
tlog.Fatal.Printf("Fatal: scrypt salt length below minimum: value=%d, min=%d", len(s.Salt), scryptMinSaltLen) tlog.Fatal.Printf("Fatal: scrypt salt length below minimum: value=%d, min=%d", len(s.Salt), scryptMinSaltLen)
os.Exit(1) os.Exit(exitcodes.ScryptParams)
} }
if s.KeyLen < cryptocore.KeyLen { if s.KeyLen < cryptocore.KeyLen {
tlog.Fatal.Printf("Fatal: scrypt parameter KeyLen below minimum: value=%d, min=%d", len(s.Salt), cryptocore.KeyLen) tlog.Fatal.Printf("Fatal: scrypt parameter KeyLen below minimum: value=%d, min=%d", len(s.Salt), cryptocore.KeyLen)
os.Exit(1) os.Exit(exitcodes.ScryptParams)
} }
} }

View File

@ -8,12 +8,39 @@ import (
) )
const ( const (
// Usage error: cli syntax etc
Usage = 1
// 2 is reserved because it is used by Go panic
// Mount is an error on mount
Mount = 3
// CipherDir means that the CIPHERDIR does not exist
CipherDir = 6
// Init is an error on filesystem init
Init = 7
// LoadConf is an error while loading gocryptfs.conf
LoadConf = 8
// ReadPassword means something went wrong reading the password
ReadPassword = 9
// MountPoint error means that the mountpoint is invalid (not empty etc).
MountPoint = 10
// Other error - please inspect the message // Other error - please inspect the message
Other = 11 Other = 11
// PasswordIncorrect - the password was incorrect // PasswordIncorrect - the password was incorrect
PasswordIncorrect = 12 PasswordIncorrect = 12
// TODO several other exit codes are defined in main.go. These will be // ScryptParams means that scrypt was called with invalid parameters
// ported over here. ScryptParams = 13
// MasterKey means that something went wrong when parsing the "-masterkey"
// command line option
MasterKey = 14
// SigInt means we got SIGINT
SigInt = 15
// PanicLog means the panic log was not empty when we were unmounted
PanicLog = 16
// ForkChild means forking the worker child failed
ForkChild = 17
// OpenSSL means you tried to enable OpenSSL, but we were compiled without it.
OpenSSL = 18
) )
// Err wraps an error with an associated numeric exit code // Err wraps an error with an associated numeric exit code

View File

@ -12,11 +12,11 @@ import (
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
"github.com/rfjakob/gocryptfs/internal/exitcodes"
"github.com/rfjakob/gocryptfs/internal/tlog" "github.com/rfjakob/gocryptfs/internal/tlog"
) )
const ( const (
exitCode = 9
// 2kB limit like EncFS // 2kB limit like EncFS
maxPasswordLen = 2048 maxPasswordLen = 2048
) )
@ -46,7 +46,7 @@ func Twice(extpass string) string {
p2 := readPasswordTerminal("Repeat: ") p2 := readPasswordTerminal("Repeat: ")
if p1 != p2 { if p1 != p2 {
tlog.Fatal.Println("Passwords do not match") tlog.Fatal.Println("Passwords do not match")
os.Exit(exitCode) os.Exit(exitcodes.ReadPassword)
} }
return p1 return p1
} }
@ -60,12 +60,12 @@ func readPasswordTerminal(prompt string) string {
p, err := terminal.ReadPassword(fd) p, err := terminal.ReadPassword(fd)
if err != nil { if err != nil {
tlog.Fatal.Printf("Could not read password from terminal: %v\n", err) tlog.Fatal.Printf("Could not read password from terminal: %v\n", err)
os.Exit(exitCode) os.Exit(exitcodes.ReadPassword)
} }
fmt.Fprintf(os.Stderr, "\n") fmt.Fprintf(os.Stderr, "\n")
if len(p) == 0 { if len(p) == 0 {
tlog.Fatal.Println("Password is empty") tlog.Fatal.Println("Password is empty")
os.Exit(exitCode) os.Exit(exitcodes.ReadPassword)
} }
return string(p) return string(p)
} }
@ -77,7 +77,7 @@ func readPasswordStdin() string {
p := readLineUnbuffered(os.Stdin) p := readLineUnbuffered(os.Stdin)
if len(p) == 0 { if len(p) == 0 {
tlog.Fatal.Println("Got empty password from stdin") tlog.Fatal.Println("Got empty password from stdin")
os.Exit(exitCode) os.Exit(exitcodes.ReadPassword)
} }
return p return p
} }
@ -102,23 +102,23 @@ func readPasswordExtpass(extpass string) string {
pipe, err := cmd.StdoutPipe() pipe, err := cmd.StdoutPipe()
if err != nil { if err != nil {
tlog.Fatal.Printf("extpass pipe setup failed: %v", err) tlog.Fatal.Printf("extpass pipe setup failed: %v", err)
os.Exit(exitCode) os.Exit(exitcodes.ReadPassword)
} }
err = cmd.Start() err = cmd.Start()
if err != nil { if err != nil {
tlog.Fatal.Printf("extpass cmd start failed: %v", err) tlog.Fatal.Printf("extpass cmd start failed: %v", err)
os.Exit(exitCode) os.Exit(exitcodes.ReadPassword)
} }
p := readLineUnbuffered(pipe) p := readLineUnbuffered(pipe)
pipe.Close() pipe.Close()
err = cmd.Wait() err = cmd.Wait()
if err != nil { if err != nil {
tlog.Fatal.Printf("extpass program returned an error: %v", err) tlog.Fatal.Printf("extpass program returned an error: %v", err)
os.Exit(exitCode) os.Exit(exitcodes.ReadPassword)
} }
if len(p) == 0 { if len(p) == 0 {
tlog.Fatal.Println("extpass: password is empty") tlog.Fatal.Println("extpass: password is empty")
os.Exit(exitCode) os.Exit(exitcodes.ReadPassword)
} }
return p return p
} }
@ -130,7 +130,7 @@ func readLineUnbuffered(r io.Reader) (l string) {
for { for {
if len(l) > maxPasswordLen { if len(l) > maxPasswordLen {
tlog.Fatal.Printf("fatal: maximum password length of %d bytes exceeded", maxPasswordLen) tlog.Fatal.Printf("fatal: maximum password length of %d bytes exceeded", maxPasswordLen)
os.Exit(exitCode) os.Exit(exitcodes.ReadPassword)
} }
n, err := r.Read(b) n, err := r.Read(b)
if err == io.EOF { if err == io.EOF {
@ -138,7 +138,7 @@ func readLineUnbuffered(r io.Reader) (l string) {
} }
if err != nil { if err != nil {
tlog.Fatal.Printf("readLineUnbuffered: %v", err) tlog.Fatal.Printf("readLineUnbuffered: %v", err)
os.Exit(exitCode) os.Exit(exitcodes.ReadPassword)
} }
if n == 0 { if n == 0 {
continue continue
@ -170,7 +170,7 @@ func CheckTrailingGarbage() {
n, _ := os.Stdin.Read(b) n, _ := os.Stdin.Read(b)
if n > 0 { if n > 0 {
tlog.Fatal.Printf("Received trailing garbage after the password") tlog.Fatal.Printf("Received trailing garbage after the password")
os.Exit(exitCode) os.Exit(exitcodes.ReadPassword)
} }
}() }()
// Wait for the goroutine to start up plus one millisecond for the read to // Wait for the goroutine to start up plus one millisecond for the read to

View File

@ -5,6 +5,8 @@ package stupidgcm
import ( import (
"fmt" "fmt"
"os" "os"
"github.com/rfjakob/gocryptfs/internal/exitcodes"
) )
type stupidGCM struct{} type stupidGCM struct{}
@ -16,7 +18,7 @@ const (
func errExit() { func errExit() {
fmt.Fprintln(os.Stderr, "gocryptfs has been compiled without openssl support but you are still trying to use openssl") fmt.Fprintln(os.Stderr, "gocryptfs has been compiled without openssl support but you are still trying to use openssl")
os.Exit(2) os.Exit(exitcodes.OpenSSL)
} }
func New(_ []byte, _ bool) stupidGCM { func New(_ []byte, _ bool) stupidGCM {

33
main.go
View File

@ -12,22 +12,13 @@ import (
"github.com/rfjakob/gocryptfs/internal/configfile" "github.com/rfjakob/gocryptfs/internal/configfile"
"github.com/rfjakob/gocryptfs/internal/contentenc" "github.com/rfjakob/gocryptfs/internal/contentenc"
"github.com/rfjakob/gocryptfs/internal/exitcodes"
"github.com/rfjakob/gocryptfs/internal/readpassword" "github.com/rfjakob/gocryptfs/internal/readpassword"
"github.com/rfjakob/gocryptfs/internal/speed" "github.com/rfjakob/gocryptfs/internal/speed"
"github.com/rfjakob/gocryptfs/internal/stupidgcm" "github.com/rfjakob/gocryptfs/internal/stupidgcm"
"github.com/rfjakob/gocryptfs/internal/tlog" "github.com/rfjakob/gocryptfs/internal/tlog"
) )
// Exit codes
const (
ErrExitUsage = 1
ErrExitMount = 3
ErrExitCipherDir = 6
ErrExitInit = 7
ErrExitLoadConf = 8
ErrExitMountPoint = 10
)
// GitVersion is the gocryptfs version according to git, set by build.bash // GitVersion is the gocryptfs version according to git, set by build.bash
var GitVersion = "[GitVersion not set - please compile using ./build.bash]" var GitVersion = "[GitVersion not set - please compile using ./build.bash]"
@ -85,7 +76,7 @@ func loadConfig(args *argContainer) (masterkey []byte, confFile *configfile.Conf
func changePassword(args *argContainer) { func changePassword(args *argContainer) {
masterkey, confFile, err := loadConfig(args) masterkey, confFile, err := loadConfig(args)
if err != nil { if err != nil {
os.Exit(ErrExitLoadConf) os.Exit(exitcodes.LoadConf)
} }
tlog.Info.Println("Please enter your new password.") tlog.Info.Println("Please enter your new password.")
newPw := readpassword.Twice(args.extpass) newPw := readpassword.Twice(args.extpass)
@ -96,7 +87,7 @@ func changePassword(args *argContainer) {
err = os.Link(args.config, bak) err = os.Link(args.config, bak)
if err != nil { if err != nil {
tlog.Fatal.Printf("Could not create backup file: %v", err) tlog.Fatal.Printf("Could not create backup file: %v", err)
os.Exit(ErrExitInit) os.Exit(exitcodes.Init)
} }
tlog.Info.Printf(tlog.ColorGrey+ tlog.Info.Printf(tlog.ColorGrey+
"A copy of the old config file has been created at %q.\n"+ "A copy of the old config file has been created at %q.\n"+
@ -106,7 +97,7 @@ func changePassword(args *argContainer) {
err = confFile.WriteFile() err = confFile.WriteFile()
if err != nil { if err != nil {
tlog.Fatal.Println(err) tlog.Fatal.Println(err)
os.Exit(ErrExitInit) os.Exit(exitcodes.Init)
} }
tlog.Info.Printf(tlog.ColorGreen + "Password changed." + tlog.ColorReset) tlog.Info.Printf(tlog.ColorGreen + "Password changed." + tlog.ColorReset)
os.Exit(0) os.Exit(0)
@ -169,11 +160,11 @@ func main() {
err = checkDir(args.cipherdir) err = checkDir(args.cipherdir)
if err != nil { if err != nil {
tlog.Fatal.Printf("Invalid cipherdir: %v", err) tlog.Fatal.Printf("Invalid cipherdir: %v", err)
os.Exit(ErrExitCipherDir) os.Exit(exitcodes.CipherDir)
} }
} else { } else {
usageText() usageText()
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
// "-q" // "-q"
if args.quiet { if args.quiet {
@ -188,7 +179,7 @@ func main() {
args.config, err = filepath.Abs(args.config) args.config, err = filepath.Abs(args.config)
if err != nil { if err != nil {
tlog.Fatal.Printf("Invalid \"-config\" setting: %v", err) tlog.Fatal.Printf("Invalid \"-config\" setting: %v", err)
os.Exit(ErrExitInit) os.Exit(exitcodes.Init)
} }
tlog.Info.Printf("Using config file at custom location %s", args.config) tlog.Info.Printf("Using config file at custom location %s", args.config)
args._configCustom = true args._configCustom = true
@ -204,7 +195,7 @@ func main() {
f, err = os.Create(args.cpuprofile) f, err = os.Create(args.cpuprofile)
if err != nil { if err != nil {
tlog.Fatal.Println(err) tlog.Fatal.Println(err)
os.Exit(ErrExitInit) os.Exit(exitcodes.Init)
} }
pprof.StartCPUProfile(f) pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile() defer pprof.StopCPUProfile()
@ -216,7 +207,7 @@ func main() {
f, err = os.Create(args.memprofile) f, err = os.Create(args.memprofile)
if err != nil { if err != nil {
tlog.Fatal.Println(err) tlog.Fatal.Println(err)
os.Exit(ErrExitInit) os.Exit(exitcodes.Init)
} }
defer func() { defer func() {
pprof.WriteHeapProfile(f) pprof.WriteHeapProfile(f)
@ -238,7 +229,7 @@ func main() {
if args.init { if args.init {
if flagSet.NArg() > 1 { if flagSet.NArg() > 1 {
tlog.Fatal.Printf("Usage: %s -init [OPTIONS] CIPHERDIR", tlog.ProgramName) tlog.Fatal.Printf("Usage: %s -init [OPTIONS] CIPHERDIR", tlog.ProgramName)
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
initDir(&args) // does not return initDir(&args) // does not return
} }
@ -246,7 +237,7 @@ func main() {
if args.passwd { if args.passwd {
if flagSet.NArg() > 1 { if flagSet.NArg() > 1 {
tlog.Fatal.Printf("Usage: %s -passwd [OPTIONS] CIPHERDIR", tlog.ProgramName) tlog.Fatal.Printf("Usage: %s -passwd [OPTIONS] CIPHERDIR", tlog.ProgramName)
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
changePassword(&args) // does not return changePassword(&args) // does not return
} }
@ -256,7 +247,7 @@ func main() {
tlog.Info.Printf("Wrong number of arguments (have %d, want 2). You passed: %s", tlog.Info.Printf("Wrong number of arguments (have %d, want 2). You passed: %s",
flagSet.NArg(), prettyArgs) flagSet.NArg(), prettyArgs)
tlog.Fatal.Printf("Usage: %s [OPTIONS] CIPHERDIR MOUNTPOINT [-o COMMA-SEPARATED-OPTIONS]", tlog.ProgramName) tlog.Fatal.Printf("Usage: %s [OPTIONS] CIPHERDIR MOUNTPOINT [-o COMMA-SEPARATED-OPTIONS]", tlog.ProgramName)
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
ret := doMount(&args) ret := doMount(&args)
if ret != 0 { if ret != 0 {

View File

@ -8,6 +8,7 @@ import (
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
"github.com/rfjakob/gocryptfs/internal/cryptocore" "github.com/rfjakob/gocryptfs/internal/cryptocore"
"github.com/rfjakob/gocryptfs/internal/exitcodes"
"github.com/rfjakob/gocryptfs/internal/tlog" "github.com/rfjakob/gocryptfs/internal/tlog"
) )
@ -50,11 +51,11 @@ func parseMasterKey(masterkey string) []byte {
key, err := hex.DecodeString(masterkey) key, err := hex.DecodeString(masterkey)
if err != nil { if err != nil {
tlog.Fatal.Printf("Could not parse master key: %v", err) tlog.Fatal.Printf("Could not parse master key: %v", err)
os.Exit(1) os.Exit(exitcodes.MasterKey)
} }
if len(key) != cryptocore.KeyLen { if len(key) != cryptocore.KeyLen {
tlog.Fatal.Printf("Master key has length %d but we require length %d", len(key), cryptocore.KeyLen) tlog.Fatal.Printf("Master key has length %d but we require length %d", len(key), cryptocore.KeyLen)
os.Exit(1) os.Exit(exitcodes.MasterKey)
} }
tlog.Info.Printf("Using explicit master key.") tlog.Info.Printf("Using explicit master key.")
tlog.Info.Printf(tlog.ColorYellow + tlog.Info.Printf(tlog.ColorYellow +

View File

@ -36,14 +36,14 @@ func doMount(args *argContainer) int {
args.mountpoint, err = filepath.Abs(flagSet.Arg(1)) args.mountpoint, err = filepath.Abs(flagSet.Arg(1))
if err != nil { if err != nil {
tlog.Fatal.Printf("Invalid mountpoint: %v", err) tlog.Fatal.Printf("Invalid mountpoint: %v", err)
os.Exit(ErrExitMountPoint) os.Exit(exitcodes.MountPoint)
} }
// We cannot mount "/home/user/.cipher" at "/home/user" because the mount // We cannot mount "/home/user/.cipher" at "/home/user" because the mount
// will hide ".cipher" also for us. // will hide ".cipher" also for us.
if args.cipherdir == args.mountpoint || strings.HasPrefix(args.cipherdir, args.mountpoint+"/") { if args.cipherdir == args.mountpoint || strings.HasPrefix(args.cipherdir, args.mountpoint+"/") {
tlog.Fatal.Printf("Mountpoint %q would shadow cipherdir %q, this is not supported", tlog.Fatal.Printf("Mountpoint %q would shadow cipherdir %q, this is not supported",
args.mountpoint, args.cipherdir) args.mountpoint, args.cipherdir)
os.Exit(ErrExitMountPoint) os.Exit(exitcodes.MountPoint)
} }
if args.nonempty { if args.nonempty {
err = checkDir(args.mountpoint) err = checkDir(args.mountpoint)
@ -52,7 +52,7 @@ func doMount(args *argContainer) int {
} }
if err != nil { if err != nil {
tlog.Fatal.Printf("Invalid mountpoint: %v", err) tlog.Fatal.Printf("Invalid mountpoint: %v", err)
os.Exit(ErrExitMountPoint) os.Exit(exitcodes.MountPoint)
} }
// Open control socket early so we can error out before asking the user // Open control socket early so we can error out before asking the user
// for the password // for the password
@ -64,7 +64,7 @@ func doMount(args *argContainer) int {
sock, err = net.Listen("unix", args.ctlsock) sock, err = net.Listen("unix", args.ctlsock)
if err != nil { if err != nil {
tlog.Fatal.Printf("ctlsock: %v", err) tlog.Fatal.Printf("ctlsock: %v", err)
os.Exit(ErrExitMount) os.Exit(exitcodes.Mount)
} }
args._ctlsockFd = sock args._ctlsockFd = sock
// Close also deletes the socket file // Close also deletes the socket file
@ -118,7 +118,7 @@ func doMount(args *argContainer) int {
paniclog, err = ioutil.TempFile("", "gocryptfs_paniclog.") paniclog, err = ioutil.TempFile("", "gocryptfs_paniclog.")
if err != nil { if err != nil {
tlog.Fatal.Printf("Failed to create gocryptfs_paniclog: %v", err) tlog.Fatal.Printf("Failed to create gocryptfs_paniclog: %v", err)
os.Exit(ErrExitMount) os.Exit(exitcodes.Mount)
} }
// Switch all of our logs and the generic logger to syslog // Switch all of our logs and the generic logger to syslog
tlog.Info.SwitchToSyslog(syslog.LOG_USER | syslog.LOG_INFO) tlog.Info.SwitchToSyslog(syslog.LOG_USER | syslog.LOG_INFO)
@ -165,6 +165,7 @@ func doMount(args *argContainer) int {
} else if fi.Size() > 0 { } else if fi.Size() > 0 {
tlog.Warn.Printf("paniclog at %q is not empty (size %d). Not deleting it.", tlog.Warn.Printf("paniclog at %q is not empty (size %d). Not deleting it.",
paniclog.Name(), fi.Size()) paniclog.Name(), fi.Size())
return exitcodes.PanicLog
} else { } else {
syscall.Unlink(paniclog.Name()) syscall.Unlink(paniclog.Name())
} }
@ -227,7 +228,7 @@ func initFuseFrontend(key []byte, args *argContainer, confFile *configfile.ConfF
frontendArgs.CryptoBackend = cryptocore.BackendAESSIV frontendArgs.CryptoBackend = cryptocore.BackendAESSIV
} else if args.reverse { } else if args.reverse {
tlog.Fatal.Printf("AES-SIV is required by reverse mode, but not enabled in the config file") tlog.Fatal.Printf("AES-SIV is required by reverse mode, but not enabled in the config file")
os.Exit(ErrExitUsage) os.Exit(exitcodes.Usage)
} }
} }
// If allow_other is set and we run as root, try to give newly created files to // If allow_other is set and we run as root, try to give newly created files to
@ -306,7 +307,7 @@ func initFuseFrontend(key []byte, args *argContainer, confFile *configfile.ConfF
srv, err := fuse.NewServer(conn.RawFS(), args.mountpoint, &mOpts) srv, err := fuse.NewServer(conn.RawFS(), args.mountpoint, &mOpts)
if err != nil { if err != nil {
tlog.Fatal.Printf("Mount failed: %v", err) tlog.Fatal.Printf("Mount failed: %v", err)
os.Exit(ErrExitMount) os.Exit(exitcodes.Mount)
} }
srv.SetDebug(args.fusedebug) srv.SetDebug(args.fusedebug)
@ -336,6 +337,6 @@ func handleSigint(srv *fuse.Server, mountpoint string) {
cmd.Run() cmd.Run()
} }
} }
os.Exit(1) os.Exit(exitcodes.SigInt)
}() }()
} }

View File

@ -10,6 +10,7 @@ import (
"testing" "testing"
"github.com/rfjakob/gocryptfs/internal/configfile" "github.com/rfjakob/gocryptfs/internal/configfile"
"github.com/rfjakob/gocryptfs/internal/exitcodes"
"github.com/rfjakob/gocryptfs/tests/test_helpers" "github.com/rfjakob/gocryptfs/tests/test_helpers"
) )
@ -316,3 +317,16 @@ func TestInitTrailingGarbage(t *testing.T) {
} }
} }
} }
// TestPasswordIncorrect makes sure the correct exit code is used when the password
// was incorrect
func TestPasswordIncorrect(t *testing.T) {
cDir := test_helpers.InitFS(t)
pDir := cDir + ".mnt"
err := test_helpers.Mount(cDir, pDir, false, "-extpass", "echo WRONG", "-wpanic=false")
// vvvvvvvvvvvvvv OMG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
exitCode := err.(*exec.ExitError).Sys().(syscall.WaitStatus).ExitStatus()
if exitCode != exitcodes.PasswordIncorrect {
t.Errorf("want=%d, got=%d", exitcodes.PasswordIncorrect, exitCode)
}
}