diff options
| author | Jakob Unterwurzacher | 2016-11-01 18:43:22 +0100 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2016-11-01 18:43:22 +0100 | 
| commit | 2b991c9743caa5edf38fbcdadb129ca61ffa702f (patch) | |
| tree | 307059774772110a6aa63fbd35e00ac2747ab4f9 | |
| parent | 964e0e6b3634973fb9512858b4ae8707c825aaaf (diff) | |
Add support for unpadded base64 filenames, "-raw64"
Through base64.RawURLEncoding.
New command-line parameter "-raw64".
| -rw-r--r-- | cli_args.go | 3 | ||||
| -rw-r--r-- | init_dir.go | 2 | ||||
| -rw-r--r-- | internal/configfile/config_file.go | 5 | ||||
| -rw-r--r-- | internal/configfile/config_test.go | 19 | ||||
| -rw-r--r-- | internal/configfile/feature_flags.go | 3 | ||||
| -rw-r--r-- | internal/fusefrontend/args.go | 3 | ||||
| -rw-r--r-- | internal/fusefrontend/fs.go | 2 | ||||
| -rw-r--r-- | internal/fusefrontend_reverse/rfs.go | 2 | ||||
| -rw-r--r-- | internal/nametransform/names.go | 13 | ||||
| -rw-r--r-- | mount.go | 2 | 
10 files changed, 43 insertions, 11 deletions
| diff --git a/cli_args.go b/cli_args.go index 7cc4090..ad65fef 100644 --- a/cli_args.go +++ b/cli_args.go @@ -16,7 +16,7 @@ import (  type argContainer struct {  	debug, init, zerokey, fusedebug, openssl, passwd, foreground, version,  	plaintextnames, quiet, nosyslog, wpanic, -	longnames, allow_other, ro, reverse, aessiv, nonempty bool +	longnames, allow_other, ro, reverse, aessiv, nonempty, raw64 bool  	masterkey, mountpoint, cipherdir, cpuprofile, extpass,  	memprofile, ko, passfile string  	// Configuration file name override @@ -103,6 +103,7 @@ func parseCliOpts() (args argContainer) {  	flagSet.BoolVar(&args.reverse, "reverse", false, "Reverse mode")  	flagSet.BoolVar(&args.aessiv, "aessiv", false, "AES-SIV encryption")  	flagSet.BoolVar(&args.nonempty, "nonempty", false, "Allow mounting over non-empty directories") +	flagSet.BoolVar(&args.raw64, "raw64", false, "Use unpadded base64 for file names")  	flagSet.StringVar(&args.masterkey, "masterkey", "", "Mount with explicit master key")  	flagSet.StringVar(&args.cpuprofile, "cpuprofile", "", "Write cpu profile to specified file")  	flagSet.StringVar(&args.memprofile, "memprofile", "", "Write memory profile to specified file") diff --git a/init_dir.go b/init_dir.go index c12a8dc..89af495 100644 --- a/init_dir.go +++ b/init_dir.go @@ -37,7 +37,7 @@ func initDir(args *argContainer) {  	}  	password := readpassword.Twice(args.extpass)  	creator := tlog.ProgramName + " " + GitVersion -	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, args.raw64)  	if err != nil {  		tlog.Fatal.Println(err)  		os.Exit(ErrExitInit) diff --git a/internal/configfile/config_file.go b/internal/configfile/config_file.go index 603f276..0bee16f 100644 --- a/internal/configfile/config_file.go +++ b/internal/configfile/config_file.go @@ -49,7 +49,7 @@ type ConfFile struct {  // CreateConfFile - create a new config with a random key encrypted with  // "password" and write it to "filename".  // Uses scrypt with cost parameter logN. -func CreateConfFile(filename string, password string, plaintextNames bool, logN int, creator string, aessiv bool) error { +func CreateConfFile(filename string, password string, plaintextNames bool, logN int, creator string, aessiv bool, raw64 bool) error {  	var cf ConfFile  	cf.filename = filename  	cf.Creator = creator @@ -70,6 +70,9 @@ func CreateConfFile(filename string, password string, plaintextNames bool, logN  		cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagDirIV])  		cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagEMENames])  		cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagLongNames]) +		if raw64 { +			cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagRaw64]) +		}  	}  	if aessiv {  		cf.FeatureFlags = append(cf.FeatureFlags, knownFlags[FlagAESSIV]) diff --git a/internal/configfile/config_test.go b/internal/configfile/config_test.go index 81984fe..f993803 100644 --- a/internal/configfile/config_test.go +++ b/internal/configfile/config_test.go @@ -60,7 +60,7 @@ func TestLoadV2StrangeFeature(t *testing.T) {  }  func TestCreateConfFile(t *testing.T) { -	err := CreateConfFile("config_test/tmp.conf", "test", false, 10, "test", false) +	err := CreateConfFile("config_test/tmp.conf", "test", false, 10, "test", false, false)  	if err != nil {  		t.Fatal(err)  	} @@ -68,11 +68,10 @@ func TestCreateConfFile(t *testing.T) {  	if err != nil {  		t.Fatal(err)  	} -  }  func TestCreateConfFileAESSIV(t *testing.T) { -	err := CreateConfFile("config_test/tmp.conf", "test", false, 10, "test", true) +	err := CreateConfFile("config_test/tmp.conf", "test", false, 10, "test", true, false)  	if err != nil {  		t.Fatal(err)  	} @@ -85,6 +84,20 @@ func TestCreateConfFileAESSIV(t *testing.T) {  	}  } +func TestCreateConfFileRaw64(t *testing.T) { +	err := CreateConfFile("config_test/tmp.conf", "test", false, 10, "test", false, true) +	if err != nil { +		t.Fatal(err) +	} +	_, c, err := LoadConfFile("config_test/tmp.conf", "test") +	if err != nil { +		t.Fatal(err) +	} +	if !c.IsFeatureFlagSet(FlagRaw64) { +		t.Error("FlagRaw64 flag should be set but is not") +	} +} +  func TestIsFeatureFlagKnown(t *testing.T) {  	// Test a few hardcoded values  	testKnownFlags := []string{"DirIV", "PlaintextNames", "EMENames", "GCMIV128", "LongNames", "AESSIV"} diff --git a/internal/configfile/feature_flags.go b/internal/configfile/feature_flags.go index d3601b1..8d4aa6e 100644 --- a/internal/configfile/feature_flags.go +++ b/internal/configfile/feature_flags.go @@ -17,6 +17,8 @@ const (  	FlagLongNames  	// FlagAESSIV selects an AES-SIV based crypto backend.  	FlagAESSIV +	// FlagRaw64 enables raw (unpadded) base64 encoding for file names +	FlagRaw64  )  // knownFlags stores the known feature flags and their string representation @@ -27,6 +29,7 @@ var knownFlags = map[flagIota]string{  	FlagGCMIV128:       "GCMIV128",  	FlagLongNames:      "LongNames",  	FlagAESSIV:         "AESSIV", +	FlagRaw64:          "Raw64",  }  // Filesystems that do not have these feature flags set are deprecated. diff --git a/internal/fusefrontend/args.go b/internal/fusefrontend/args.go index 204647d..d8b0304 100644 --- a/internal/fusefrontend/args.go +++ b/internal/fusefrontend/args.go @@ -18,4 +18,7 @@ type Args struct {  	// location. If it is false, reverse mode maps ".gocryptfs.reverse.conf"  	// to "gocryptfs.conf" in the plaintext dir.  	ConfigCustom bool +	// Raw64 is true when RawURLEncoding (without padding) should be used for +	// file names +	Raw64 bool  } diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go index 33053de..e9e6113 100644 --- a/internal/fusefrontend/fs.go +++ b/internal/fusefrontend/fs.go @@ -42,7 +42,7 @@ var _ pathfs.FileSystem = &FS{} // Verify that interface is implemented.  func NewFS(args Args) *FS {  	cryptoCore := cryptocore.New(args.Masterkey, args.CryptoBackend, contentenc.DefaultIVBits)  	contentEnc := contentenc.New(cryptoCore, contentenc.DefaultBS) -	nameTransform := nametransform.New(cryptoCore, args.LongNames) +	nameTransform := nametransform.New(cryptoCore, args.LongNames, args.Raw64)  	return &FS{  		FileSystem:    pathfs.NewLoopbackFileSystem(args.Cipherdir), diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go index 35e9e50..87a2602 100644 --- a/internal/fusefrontend_reverse/rfs.go +++ b/internal/fusefrontend_reverse/rfs.go @@ -56,7 +56,7 @@ func NewFS(args fusefrontend.Args) pathfs.FileSystem {  	initLongnameCache()  	cryptoCore := cryptocore.New(args.Masterkey, args.CryptoBackend, contentenc.DefaultIVBits)  	contentEnc := contentenc.New(cryptoCore, contentenc.DefaultBS) -	nameTransform := nametransform.New(cryptoCore, args.LongNames) +	nameTransform := nametransform.New(cryptoCore, args.LongNames, args.Raw64)  	return &reverseFS{  		// pathfs.defaultFileSystem returns ENOSYS for all operations diff --git a/internal/nametransform/names.go b/internal/nametransform/names.go index 05ae75e..9b1639f 100644 --- a/internal/nametransform/names.go +++ b/internal/nametransform/names.go @@ -17,13 +17,20 @@ type NameTransform struct {  	cryptoCore *cryptocore.CryptoCore  	longNames  bool  	DirIVCache dirIVCache +	// b64 = either base64.URLEncoding or base64.RawURLEncoding +	b64 *base64.Encoding  }  // New returns a new NameTransform instance. -func New(c *cryptocore.CryptoCore, longNames bool) *NameTransform { +func New(c *cryptocore.CryptoCore, longNames bool, raw64 bool) *NameTransform { +	b64 := base64.URLEncoding +	if raw64 { +		b64 = base64.RawURLEncoding +	}  	return &NameTransform{  		cryptoCore: c,  		longNames:  longNames, +		b64:        b64,  	}  } @@ -32,7 +39,7 @@ func New(c *cryptocore.CryptoCore, longNames bool) *NameTransform {  // This function is exported because it allows for a very efficient readdir  // implementation (read IV once, decrypt all names using this function).  func (n *NameTransform) DecryptName(cipherName string, iv []byte) (string, error) { -	bin, err := base64.URLEncoding.DecodeString(cipherName) +	bin, err := n.b64.DecodeString(cipherName)  	if err != nil {  		return "", err  	} @@ -63,6 +70,6 @@ func (n *NameTransform) EncryptName(plainName string, iv []byte) (cipherName64 s  	bin := []byte(plainName)  	bin = pad16(bin)  	bin = eme.Transform(n.cryptoCore.BlockCipher, iv, bin, eme.DirectionEncrypt) -	cipherName64 = base64.URLEncoding.EncodeToString(bin) +	cipherName64 = n.b64.EncodeToString(bin)  	return cipherName64  } @@ -143,11 +143,13 @@ func initFuseFrontend(key []byte, args *argContainer, confFile *configfile.ConfF  		LongNames:      args.longnames,  		CryptoBackend:  cryptoBackend,  		ConfigCustom:   args._configCustom, +		Raw64:          args.raw64,  	}  	// 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) +		frontendArgs.Raw64 = confFile.IsFeatureFlagSet(configfile.FlagRaw64)  		if confFile.IsFeatureFlagSet(configfile.FlagAESSIV) {  			frontendArgs.CryptoBackend = cryptocore.BackendAESSIV  		} else if args.reverse { | 
