github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/backend/crypt/crypt.go (about)

     1  // Package crypt provides wrappers for Fs and Object which implement encryption
     2  package crypt
     3  
     4  import (
     5  	"context"
     6  	"fmt"
     7  	"io"
     8  	"path"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/pkg/errors"
    13  	"github.com/rclone/rclone/fs"
    14  	"github.com/rclone/rclone/fs/accounting"
    15  	"github.com/rclone/rclone/fs/config/configmap"
    16  	"github.com/rclone/rclone/fs/config/configstruct"
    17  	"github.com/rclone/rclone/fs/config/obscure"
    18  	"github.com/rclone/rclone/fs/fspath"
    19  	"github.com/rclone/rclone/fs/hash"
    20  )
    21  
    22  // Globals
    23  // Register with Fs
    24  func init() {
    25  	fs.Register(&fs.RegInfo{
    26  		Name:        "crypt",
    27  		Description: "Encrypt/Decrypt a remote",
    28  		NewFs:       NewFs,
    29  		CommandHelp: commandHelp,
    30  		Options: []fs.Option{{
    31  			Name:     "remote",
    32  			Help:     "Remote to encrypt/decrypt.\nNormally should contain a ':' and a path, eg \"myremote:path/to/dir\",\n\"myremote:bucket\" or maybe \"myremote:\" (not recommended).",
    33  			Required: true,
    34  		}, {
    35  			Name:    "filename_encryption",
    36  			Help:    "How to encrypt the filenames.",
    37  			Default: "standard",
    38  			Examples: []fs.OptionExample{
    39  				{
    40  					Value: "standard",
    41  					Help:  "Encrypt the filenames see the docs for the details.",
    42  				}, {
    43  					Value: "obfuscate",
    44  					Help:  "Very simple filename obfuscation.",
    45  				}, {
    46  					Value: "off",
    47  					Help:  "Don't encrypt the file names.  Adds a \".bin\" extension only.",
    48  				},
    49  			},
    50  		}, {
    51  			Name: "directory_name_encryption",
    52  			Help: `Option to either encrypt directory names or leave them intact.
    53  
    54  NB If filename_encryption is "off" then this option will do nothing.`,
    55  			Default: true,
    56  			Examples: []fs.OptionExample{
    57  				{
    58  					Value: "true",
    59  					Help:  "Encrypt directory names.",
    60  				},
    61  				{
    62  					Value: "false",
    63  					Help:  "Don't encrypt directory names, leave them intact.",
    64  				},
    65  			},
    66  		}, {
    67  			Name:       "password",
    68  			Help:       "Password or pass phrase for encryption.",
    69  			IsPassword: true,
    70  			Required:   true,
    71  		}, {
    72  			Name:       "password2",
    73  			Help:       "Password or pass phrase for salt. Optional but recommended.\nShould be different to the previous password.",
    74  			IsPassword: true,
    75  		}, {
    76  			Name: "show_mapping",
    77  			Help: `For all files listed show how the names encrypt.
    78  
    79  If this flag is set then for each file that the remote is asked to
    80  list, it will log (at level INFO) a line stating the decrypted file
    81  name and the encrypted file name.
    82  
    83  This is so you can work out which encrypted names are which decrypted
    84  names just in case you need to do something with the encrypted file
    85  names, or for debugging purposes.`,
    86  			Default:  false,
    87  			Hide:     fs.OptionHideConfigurator,
    88  			Advanced: true,
    89  		}},
    90  	})
    91  }
    92  
    93  // newCipherForConfig constructs a Cipher for the given config name
    94  func newCipherForConfig(opt *Options) (*Cipher, error) {
    95  	mode, err := NewNameEncryptionMode(opt.FilenameEncryption)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	if opt.Password == "" {
   100  		return nil, errors.New("password not set in config file")
   101  	}
   102  	password, err := obscure.Reveal(opt.Password)
   103  	if err != nil {
   104  		return nil, errors.Wrap(err, "failed to decrypt password")
   105  	}
   106  	var salt string
   107  	if opt.Password2 != "" {
   108  		salt, err = obscure.Reveal(opt.Password2)
   109  		if err != nil {
   110  			return nil, errors.Wrap(err, "failed to decrypt password2")
   111  		}
   112  	}
   113  	cipher, err := newCipher(mode, password, salt, opt.DirectoryNameEncryption)
   114  	if err != nil {
   115  		return nil, errors.Wrap(err, "failed to make cipher")
   116  	}
   117  	return cipher, nil
   118  }
   119  
   120  // NewCipher constructs a Cipher for the given config
   121  func NewCipher(m configmap.Mapper) (*Cipher, error) {
   122  	// Parse config into Options struct
   123  	opt := new(Options)
   124  	err := configstruct.Set(m, opt)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	return newCipherForConfig(opt)
   129  }
   130  
   131  // NewFs constructs an Fs from the path, container:path
   132  func NewFs(name, rpath string, m configmap.Mapper) (fs.Fs, error) {
   133  	// Parse config into Options struct
   134  	opt := new(Options)
   135  	err := configstruct.Set(m, opt)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	cipher, err := newCipherForConfig(opt)
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  	remote := opt.Remote
   144  	if strings.HasPrefix(remote, name+":") {
   145  		return nil, errors.New("can't point crypt remote at itself - check the value of the remote setting")
   146  	}
   147  	wInfo, wName, wPath, wConfig, err := fs.ConfigFs(remote)
   148  	if err != nil {
   149  		return nil, errors.Wrapf(err, "failed to parse remote %q to wrap", remote)
   150  	}
   151  	// Make sure to remove trailing . reffering to the current dir
   152  	if path.Base(rpath) == "." {
   153  		rpath = strings.TrimSuffix(rpath, ".")
   154  	}
   155  	// Look for a file first
   156  	remotePath := fspath.JoinRootPath(wPath, cipher.EncryptFileName(rpath))
   157  	wrappedFs, err := wInfo.NewFs(wName, remotePath, wConfig)
   158  	// if that didn't produce a file, look for a directory
   159  	if err != fs.ErrorIsFile {
   160  		remotePath = fspath.JoinRootPath(wPath, cipher.EncryptDirName(rpath))
   161  		wrappedFs, err = wInfo.NewFs(wName, remotePath, wConfig)
   162  	}
   163  	if err != fs.ErrorIsFile && err != nil {
   164  		return nil, errors.Wrapf(err, "failed to make remote %s:%q to wrap", wName, remotePath)
   165  	}
   166  	f := &Fs{
   167  		Fs:     wrappedFs,
   168  		name:   name,
   169  		root:   rpath,
   170  		opt:    *opt,
   171  		cipher: cipher,
   172  	}
   173  	// the features here are ones we could support, and they are
   174  	// ANDed with the ones from wrappedFs
   175  	f.features = (&fs.Features{
   176  		CaseInsensitive:         cipher.NameEncryptionMode() == NameEncryptionOff,
   177  		DuplicateFiles:          true,
   178  		ReadMimeType:            false, // MimeTypes not supported with crypt
   179  		WriteMimeType:           false,
   180  		BucketBased:             true,
   181  		CanHaveEmptyDirectories: true,
   182  		SetTier:                 true,
   183  		GetTier:                 true,
   184  	}).Fill(f).Mask(wrappedFs).WrapsFs(f, wrappedFs)
   185  
   186  	return f, err
   187  }
   188  
   189  // Options defines the configuration for this backend
   190  type Options struct {
   191  	Remote                  string `config:"remote"`
   192  	FilenameEncryption      string `config:"filename_encryption"`
   193  	DirectoryNameEncryption bool   `config:"directory_name_encryption"`
   194  	Password                string `config:"password"`
   195  	Password2               string `config:"password2"`
   196  	ShowMapping             bool   `config:"show_mapping"`
   197  }
   198  
   199  // Fs represents a wrapped fs.Fs
   200  type Fs struct {
   201  	fs.Fs
   202  	wrapper  fs.Fs
   203  	name     string
   204  	root     string
   205  	opt      Options
   206  	features *fs.Features // optional features
   207  	cipher   *Cipher
   208  }
   209  
   210  // Name of the remote (as passed into NewFs)
   211  func (f *Fs) Name() string {
   212  	return f.name
   213  }
   214  
   215  // Root of the remote (as passed into NewFs)
   216  func (f *Fs) Root() string {
   217  	return f.root
   218  }
   219  
   220  // Features returns the optional features of this Fs
   221  func (f *Fs) Features() *fs.Features {
   222  	return f.features
   223  }
   224  
   225  // String returns a description of the FS
   226  func (f *Fs) String() string {
   227  	return fmt.Sprintf("Encrypted drive '%s:%s'", f.name, f.root)
   228  }
   229  
   230  // Encrypt an object file name to entries.
   231  func (f *Fs) add(entries *fs.DirEntries, obj fs.Object) {
   232  	remote := obj.Remote()
   233  	decryptedRemote, err := f.cipher.DecryptFileName(remote)
   234  	if err != nil {
   235  		fs.Debugf(remote, "Skipping undecryptable file name: %v", err)
   236  		return
   237  	}
   238  	if f.opt.ShowMapping {
   239  		fs.Logf(decryptedRemote, "Encrypts to %q", remote)
   240  	}
   241  	*entries = append(*entries, f.newObject(obj))
   242  }
   243  
   244  // Encrypt a directory file name to entries.
   245  func (f *Fs) addDir(ctx context.Context, entries *fs.DirEntries, dir fs.Directory) {
   246  	remote := dir.Remote()
   247  	decryptedRemote, err := f.cipher.DecryptDirName(remote)
   248  	if err != nil {
   249  		fs.Debugf(remote, "Skipping undecryptable dir name: %v", err)
   250  		return
   251  	}
   252  	if f.opt.ShowMapping {
   253  		fs.Logf(decryptedRemote, "Encrypts to %q", remote)
   254  	}
   255  	*entries = append(*entries, f.newDir(ctx, dir))
   256  }
   257  
   258  // Encrypt some directory entries.  This alters entries returning it as newEntries.
   259  func (f *Fs) encryptEntries(ctx context.Context, entries fs.DirEntries) (newEntries fs.DirEntries, err error) {
   260  	newEntries = entries[:0] // in place filter
   261  	for _, entry := range entries {
   262  		switch x := entry.(type) {
   263  		case fs.Object:
   264  			f.add(&newEntries, x)
   265  		case fs.Directory:
   266  			f.addDir(ctx, &newEntries, x)
   267  		default:
   268  			return nil, errors.Errorf("Unknown object type %T", entry)
   269  		}
   270  	}
   271  	return newEntries, nil
   272  }
   273  
   274  // List the objects and directories in dir into entries.  The
   275  // entries can be returned in any order but should be for a
   276  // complete directory.
   277  //
   278  // dir should be "" to list the root, and should not have
   279  // trailing slashes.
   280  //
   281  // This should return ErrDirNotFound if the directory isn't
   282  // found.
   283  func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err error) {
   284  	entries, err = f.Fs.List(ctx, f.cipher.EncryptDirName(dir))
   285  	if err != nil {
   286  		return nil, err
   287  	}
   288  	return f.encryptEntries(ctx, entries)
   289  }
   290  
   291  // ListR lists the objects and directories of the Fs starting
   292  // from dir recursively into out.
   293  //
   294  // dir should be "" to start from the root, and should not
   295  // have trailing slashes.
   296  //
   297  // This should return ErrDirNotFound if the directory isn't
   298  // found.
   299  //
   300  // It should call callback for each tranche of entries read.
   301  // These need not be returned in any particular order.  If
   302  // callback returns an error then the listing will stop
   303  // immediately.
   304  //
   305  // Don't implement this unless you have a more efficient way
   306  // of listing recursively that doing a directory traversal.
   307  func (f *Fs) ListR(ctx context.Context, dir string, callback fs.ListRCallback) (err error) {
   308  	return f.Fs.Features().ListR(ctx, f.cipher.EncryptDirName(dir), func(entries fs.DirEntries) error {
   309  		newEntries, err := f.encryptEntries(ctx, entries)
   310  		if err != nil {
   311  			return err
   312  		}
   313  		return callback(newEntries)
   314  	})
   315  }
   316  
   317  // NewObject finds the Object at remote.
   318  func (f *Fs) NewObject(ctx context.Context, remote string) (fs.Object, error) {
   319  	o, err := f.Fs.NewObject(ctx, f.cipher.EncryptFileName(remote))
   320  	if err != nil {
   321  		return nil, err
   322  	}
   323  	return f.newObject(o), nil
   324  }
   325  
   326  type putFn func(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) (fs.Object, error)
   327  
   328  // put implements Put or PutStream
   329  func (f *Fs) put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options []fs.OpenOption, put putFn) (fs.Object, error) {
   330  	// Encrypt the data into wrappedIn
   331  	wrappedIn, encrypter, err := f.cipher.encryptData(in)
   332  	if err != nil {
   333  		return nil, err
   334  	}
   335  
   336  	// Find a hash the destination supports to compute a hash of
   337  	// the encrypted data
   338  	ht := f.Fs.Hashes().GetOne()
   339  	var hasher *hash.MultiHasher
   340  	if ht != hash.None {
   341  		hasher, err = hash.NewMultiHasherTypes(hash.NewHashSet(ht))
   342  		if err != nil {
   343  			return nil, err
   344  		}
   345  		// unwrap the accounting
   346  		var wrap accounting.WrapFn
   347  		wrappedIn, wrap = accounting.UnWrap(wrappedIn)
   348  		// add the hasher
   349  		wrappedIn = io.TeeReader(wrappedIn, hasher)
   350  		// wrap the accounting back on
   351  		wrappedIn = wrap(wrappedIn)
   352  	}
   353  
   354  	// Transfer the data
   355  	o, err := put(ctx, wrappedIn, f.newObjectInfo(src, encrypter.nonce), options...)
   356  	if err != nil {
   357  		return nil, err
   358  	}
   359  
   360  	// Check the hashes of the encrypted data if we were comparing them
   361  	if ht != hash.None && hasher != nil {
   362  		srcHash := hasher.Sums()[ht]
   363  		var dstHash string
   364  		dstHash, err = o.Hash(ctx, ht)
   365  		if err != nil {
   366  			return nil, errors.Wrap(err, "failed to read destination hash")
   367  		}
   368  		if srcHash != "" && dstHash != "" && srcHash != dstHash {
   369  			// remove object
   370  			err = o.Remove(ctx)
   371  			if err != nil {
   372  				fs.Errorf(o, "Failed to remove corrupted object: %v", err)
   373  			}
   374  			return nil, errors.Errorf("corrupted on transfer: %v crypted hash differ %q vs %q", ht, srcHash, dstHash)
   375  		}
   376  	}
   377  
   378  	return f.newObject(o), nil
   379  }
   380  
   381  // Put in to the remote path with the modTime given of the given size
   382  //
   383  // May create the object even if it returns an error - if so
   384  // will return the object and the error, otherwise will return
   385  // nil and the error
   386  func (f *Fs) Put(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) (fs.Object, error) {
   387  	return f.put(ctx, in, src, options, f.Fs.Put)
   388  }
   389  
   390  // PutStream uploads to the remote path with the modTime given of indeterminate size
   391  func (f *Fs) PutStream(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) (fs.Object, error) {
   392  	return f.put(ctx, in, src, options, f.Fs.Features().PutStream)
   393  }
   394  
   395  // Hashes returns the supported hash sets.
   396  func (f *Fs) Hashes() hash.Set {
   397  	return hash.Set(hash.None)
   398  }
   399  
   400  // Mkdir makes the directory (container, bucket)
   401  //
   402  // Shouldn't return an error if it already exists
   403  func (f *Fs) Mkdir(ctx context.Context, dir string) error {
   404  	return f.Fs.Mkdir(ctx, f.cipher.EncryptDirName(dir))
   405  }
   406  
   407  // Rmdir removes the directory (container, bucket) if empty
   408  //
   409  // Return an error if it doesn't exist or isn't empty
   410  func (f *Fs) Rmdir(ctx context.Context, dir string) error {
   411  	return f.Fs.Rmdir(ctx, f.cipher.EncryptDirName(dir))
   412  }
   413  
   414  // Purge all files in the root and the root directory
   415  //
   416  // Implement this if you have a way of deleting all the files
   417  // quicker than just running Remove() on the result of List()
   418  //
   419  // Return an error if it doesn't exist
   420  func (f *Fs) Purge(ctx context.Context) error {
   421  	do := f.Fs.Features().Purge
   422  	if do == nil {
   423  		return fs.ErrorCantPurge
   424  	}
   425  	return do(ctx)
   426  }
   427  
   428  // Copy src to this remote using server side copy operations.
   429  //
   430  // This is stored with the remote path given
   431  //
   432  // It returns the destination Object and a possible error
   433  //
   434  // Will only be called if src.Fs().Name() == f.Name()
   435  //
   436  // If it isn't possible then return fs.ErrorCantCopy
   437  func (f *Fs) Copy(ctx context.Context, src fs.Object, remote string) (fs.Object, error) {
   438  	do := f.Fs.Features().Copy
   439  	if do == nil {
   440  		return nil, fs.ErrorCantCopy
   441  	}
   442  	o, ok := src.(*Object)
   443  	if !ok {
   444  		return nil, fs.ErrorCantCopy
   445  	}
   446  	oResult, err := do(ctx, o.Object, f.cipher.EncryptFileName(remote))
   447  	if err != nil {
   448  		return nil, err
   449  	}
   450  	return f.newObject(oResult), nil
   451  }
   452  
   453  // Move src to this remote using server side move operations.
   454  //
   455  // This is stored with the remote path given
   456  //
   457  // It returns the destination Object and a possible error
   458  //
   459  // Will only be called if src.Fs().Name() == f.Name()
   460  //
   461  // If it isn't possible then return fs.ErrorCantMove
   462  func (f *Fs) Move(ctx context.Context, src fs.Object, remote string) (fs.Object, error) {
   463  	do := f.Fs.Features().Move
   464  	if do == nil {
   465  		return nil, fs.ErrorCantMove
   466  	}
   467  	o, ok := src.(*Object)
   468  	if !ok {
   469  		return nil, fs.ErrorCantMove
   470  	}
   471  	oResult, err := do(ctx, o.Object, f.cipher.EncryptFileName(remote))
   472  	if err != nil {
   473  		return nil, err
   474  	}
   475  	return f.newObject(oResult), nil
   476  }
   477  
   478  // DirMove moves src, srcRemote to this remote at dstRemote
   479  // using server side move operations.
   480  //
   481  // Will only be called if src.Fs().Name() == f.Name()
   482  //
   483  // If it isn't possible then return fs.ErrorCantDirMove
   484  //
   485  // If destination exists then return fs.ErrorDirExists
   486  func (f *Fs) DirMove(ctx context.Context, src fs.Fs, srcRemote, dstRemote string) error {
   487  	do := f.Fs.Features().DirMove
   488  	if do == nil {
   489  		return fs.ErrorCantDirMove
   490  	}
   491  	srcFs, ok := src.(*Fs)
   492  	if !ok {
   493  		fs.Debugf(srcFs, "Can't move directory - not same remote type")
   494  		return fs.ErrorCantDirMove
   495  	}
   496  	return do(ctx, srcFs.Fs, f.cipher.EncryptDirName(srcRemote), f.cipher.EncryptDirName(dstRemote))
   497  }
   498  
   499  // PutUnchecked uploads the object
   500  //
   501  // This will create a duplicate if we upload a new file without
   502  // checking to see if there is one already - use Put() for that.
   503  func (f *Fs) PutUnchecked(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) (fs.Object, error) {
   504  	do := f.Fs.Features().PutUnchecked
   505  	if do == nil {
   506  		return nil, errors.New("can't PutUnchecked")
   507  	}
   508  	wrappedIn, encrypter, err := f.cipher.encryptData(in)
   509  	if err != nil {
   510  		return nil, err
   511  	}
   512  	o, err := do(ctx, wrappedIn, f.newObjectInfo(src, encrypter.nonce))
   513  	if err != nil {
   514  		return nil, err
   515  	}
   516  	return f.newObject(o), nil
   517  }
   518  
   519  // CleanUp the trash in the Fs
   520  //
   521  // Implement this if you have a way of emptying the trash or
   522  // otherwise cleaning up old versions of files.
   523  func (f *Fs) CleanUp(ctx context.Context) error {
   524  	do := f.Fs.Features().CleanUp
   525  	if do == nil {
   526  		return errors.New("can't CleanUp")
   527  	}
   528  	return do(ctx)
   529  }
   530  
   531  // About gets quota information from the Fs
   532  func (f *Fs) About(ctx context.Context) (*fs.Usage, error) {
   533  	do := f.Fs.Features().About
   534  	if do == nil {
   535  		return nil, errors.New("About not supported")
   536  	}
   537  	return do(ctx)
   538  }
   539  
   540  // UnWrap returns the Fs that this Fs is wrapping
   541  func (f *Fs) UnWrap() fs.Fs {
   542  	return f.Fs
   543  }
   544  
   545  // WrapFs returns the Fs that is wrapping this Fs
   546  func (f *Fs) WrapFs() fs.Fs {
   547  	return f.wrapper
   548  }
   549  
   550  // SetWrapper sets the Fs that is wrapping this Fs
   551  func (f *Fs) SetWrapper(wrapper fs.Fs) {
   552  	f.wrapper = wrapper
   553  }
   554  
   555  // EncryptFileName returns an encrypted file name
   556  func (f *Fs) EncryptFileName(fileName string) string {
   557  	return f.cipher.EncryptFileName(fileName)
   558  }
   559  
   560  // DecryptFileName returns a decrypted file name
   561  func (f *Fs) DecryptFileName(encryptedFileName string) (string, error) {
   562  	return f.cipher.DecryptFileName(encryptedFileName)
   563  }
   564  
   565  // computeHashWithNonce takes the nonce and encrypts the contents of
   566  // src with it, and calculates the hash given by HashType on the fly
   567  //
   568  // Note that we break lots of encapsulation in this function.
   569  func (f *Fs) computeHashWithNonce(ctx context.Context, nonce nonce, src fs.Object, hashType hash.Type) (hashStr string, err error) {
   570  	// Open the src for input
   571  	in, err := src.Open(ctx)
   572  	if err != nil {
   573  		return "", errors.Wrap(err, "failed to open src")
   574  	}
   575  	defer fs.CheckClose(in, &err)
   576  
   577  	// Now encrypt the src with the nonce
   578  	out, err := f.cipher.newEncrypter(in, &nonce)
   579  	if err != nil {
   580  		return "", errors.Wrap(err, "failed to make encrypter")
   581  	}
   582  
   583  	// pipe into hash
   584  	m, err := hash.NewMultiHasherTypes(hash.NewHashSet(hashType))
   585  	if err != nil {
   586  		return "", errors.Wrap(err, "failed to make hasher")
   587  	}
   588  	_, err = io.Copy(m, out)
   589  	if err != nil {
   590  		return "", errors.Wrap(err, "failed to hash data")
   591  	}
   592  
   593  	return m.Sums()[hashType], nil
   594  }
   595  
   596  // ComputeHash takes the nonce from o, and encrypts the contents of
   597  // src with it, and calculates the hash given by HashType on the fly
   598  //
   599  // Note that we break lots of encapsulation in this function.
   600  func (f *Fs) ComputeHash(ctx context.Context, o *Object, src fs.Object, hashType hash.Type) (hashStr string, err error) {
   601  	// Read the nonce - opening the file is sufficient to read the nonce in
   602  	// use a limited read so we only read the header
   603  	in, err := o.Object.Open(ctx, &fs.RangeOption{Start: 0, End: int64(fileHeaderSize) - 1})
   604  	if err != nil {
   605  		return "", errors.Wrap(err, "failed to open object to read nonce")
   606  	}
   607  	d, err := f.cipher.newDecrypter(in)
   608  	if err != nil {
   609  		_ = in.Close()
   610  		return "", errors.Wrap(err, "failed to open object to read nonce")
   611  	}
   612  	nonce := d.nonce
   613  	// fs.Debugf(o, "Read nonce % 2x", nonce)
   614  
   615  	// Check nonce isn't all zeros
   616  	isZero := true
   617  	for i := range nonce {
   618  		if nonce[i] != 0 {
   619  			isZero = false
   620  		}
   621  	}
   622  	if isZero {
   623  		fs.Errorf(o, "empty nonce read")
   624  	}
   625  
   626  	// Close d (and hence in) once we have read the nonce
   627  	err = d.Close()
   628  	if err != nil {
   629  		return "", errors.Wrap(err, "failed to close nonce read")
   630  	}
   631  
   632  	return f.computeHashWithNonce(ctx, nonce, src, hashType)
   633  }
   634  
   635  // MergeDirs merges the contents of all the directories passed
   636  // in into the first one and rmdirs the other directories.
   637  func (f *Fs) MergeDirs(ctx context.Context, dirs []fs.Directory) error {
   638  	do := f.Fs.Features().MergeDirs
   639  	if do == nil {
   640  		return errors.New("MergeDirs not supported")
   641  	}
   642  	out := make([]fs.Directory, len(dirs))
   643  	for i, dir := range dirs {
   644  		out[i] = fs.NewDirCopy(ctx, dir).SetRemote(f.cipher.EncryptDirName(dir.Remote()))
   645  	}
   646  	return do(ctx, out)
   647  }
   648  
   649  // DirCacheFlush resets the directory cache - used in testing
   650  // as an optional interface
   651  func (f *Fs) DirCacheFlush() {
   652  	do := f.Fs.Features().DirCacheFlush
   653  	if do != nil {
   654  		do()
   655  	}
   656  }
   657  
   658  // PublicLink generates a public link to the remote path (usually readable by anyone)
   659  func (f *Fs) PublicLink(ctx context.Context, remote string) (string, error) {
   660  	do := f.Fs.Features().PublicLink
   661  	if do == nil {
   662  		return "", errors.New("PublicLink not supported")
   663  	}
   664  	o, err := f.NewObject(ctx, remote)
   665  	if err != nil {
   666  		// assume it is a directory
   667  		return do(ctx, f.cipher.EncryptDirName(remote))
   668  	}
   669  	return do(ctx, o.(*Object).Object.Remote())
   670  }
   671  
   672  // ChangeNotify calls the passed function with a path
   673  // that has had changes. If the implementation
   674  // uses polling, it should adhere to the given interval.
   675  func (f *Fs) ChangeNotify(ctx context.Context, notifyFunc func(string, fs.EntryType), pollIntervalChan <-chan time.Duration) {
   676  	do := f.Fs.Features().ChangeNotify
   677  	if do == nil {
   678  		return
   679  	}
   680  	wrappedNotifyFunc := func(path string, entryType fs.EntryType) {
   681  		// fs.Debugf(f, "ChangeNotify: path %q entryType %d", path, entryType)
   682  		var (
   683  			err       error
   684  			decrypted string
   685  		)
   686  		switch entryType {
   687  		case fs.EntryDirectory:
   688  			decrypted, err = f.cipher.DecryptDirName(path)
   689  		case fs.EntryObject:
   690  			decrypted, err = f.cipher.DecryptFileName(path)
   691  		default:
   692  			fs.Errorf(path, "crypt ChangeNotify: ignoring unknown EntryType %d", entryType)
   693  			return
   694  		}
   695  		if err != nil {
   696  			fs.Logf(f, "ChangeNotify was unable to decrypt %q: %s", path, err)
   697  			return
   698  		}
   699  		notifyFunc(decrypted, entryType)
   700  	}
   701  	do(ctx, wrappedNotifyFunc, pollIntervalChan)
   702  }
   703  
   704  var commandHelp = []fs.CommandHelp{
   705  	{
   706  		Name:  "encode",
   707  		Short: "Encode the given filename(s)",
   708  		Long: `This encodes the filenames given as arguments returning a list of
   709  strings of the encoded results.
   710  
   711  Usage Example:
   712  
   713      rclone backend encode crypt: file1 [file2...]
   714      rclone rc backend/command command=encode fs=crypt: file1 [file2...]
   715  `,
   716  	},
   717  	{
   718  		Name:  "decode",
   719  		Short: "Decode the given filename(s)",
   720  		Long: `This decodes the filenames given as arguments returning a list of
   721  strings of the decoded results. It will return an error if any of the
   722  inputs are invalid.
   723  
   724  Usage Example:
   725  
   726      rclone backend decode crypt: encryptedfile1 [encryptedfile2...]
   727      rclone rc backend/command command=decode fs=crypt: encryptedfile1 [encryptedfile2...]
   728  `,
   729  	},
   730  }
   731  
   732  // Command the backend to run a named command
   733  //
   734  // The command run is name
   735  // args may be used to read arguments from
   736  // opts may be used to read optional arguments from
   737  //
   738  // The result should be capable of being JSON encoded
   739  // If it is a string or a []string it will be shown to the user
   740  // otherwise it will be JSON encoded and shown to the user like that
   741  func (f *Fs) Command(ctx context.Context, name string, arg []string, opt map[string]string) (out interface{}, err error) {
   742  	switch name {
   743  	case "decode":
   744  		out := make([]string, 0, len(arg))
   745  		for _, encryptedFileName := range arg {
   746  			fileName, err := f.DecryptFileName(encryptedFileName)
   747  			if err != nil {
   748  				return out, errors.Wrap(err, fmt.Sprintf("Failed to decrypt : %s", encryptedFileName))
   749  			}
   750  			out = append(out, fileName)
   751  		}
   752  		return out, nil
   753  	case "encode":
   754  		out := make([]string, 0, len(arg))
   755  		for _, fileName := range arg {
   756  			encryptedFileName := f.EncryptFileName(fileName)
   757  			out = append(out, encryptedFileName)
   758  		}
   759  		return out, nil
   760  	default:
   761  		return nil, fs.ErrorCommandNotFound
   762  	}
   763  }
   764  
   765  // Object describes a wrapped for being read from the Fs
   766  //
   767  // This decrypts the remote name and decrypts the data
   768  type Object struct {
   769  	fs.Object
   770  	f *Fs
   771  }
   772  
   773  func (f *Fs) newObject(o fs.Object) *Object {
   774  	return &Object{
   775  		Object: o,
   776  		f:      f,
   777  	}
   778  }
   779  
   780  // Fs returns read only access to the Fs that this object is part of
   781  func (o *Object) Fs() fs.Info {
   782  	return o.f
   783  }
   784  
   785  // Return a string version
   786  func (o *Object) String() string {
   787  	if o == nil {
   788  		return "<nil>"
   789  	}
   790  	return o.Remote()
   791  }
   792  
   793  // Remote returns the remote path
   794  func (o *Object) Remote() string {
   795  	remote := o.Object.Remote()
   796  	decryptedName, err := o.f.cipher.DecryptFileName(remote)
   797  	if err != nil {
   798  		fs.Debugf(remote, "Undecryptable file name: %v", err)
   799  		return remote
   800  	}
   801  	return decryptedName
   802  }
   803  
   804  // Size returns the size of the file
   805  func (o *Object) Size() int64 {
   806  	size, err := o.f.cipher.DecryptedSize(o.Object.Size())
   807  	if err != nil {
   808  		fs.Debugf(o, "Bad size for decrypt: %v", err)
   809  	}
   810  	return size
   811  }
   812  
   813  // Hash returns the selected checksum of the file
   814  // If no checksum is available it returns ""
   815  func (o *Object) Hash(ctx context.Context, ht hash.Type) (string, error) {
   816  	return "", hash.ErrUnsupported
   817  }
   818  
   819  // UnWrap returns the wrapped Object
   820  func (o *Object) UnWrap() fs.Object {
   821  	return o.Object
   822  }
   823  
   824  // Open opens the file for read.  Call Close() on the returned io.ReadCloser
   825  func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (rc io.ReadCloser, err error) {
   826  	var openOptions []fs.OpenOption
   827  	var offset, limit int64 = 0, -1
   828  	for _, option := range options {
   829  		switch x := option.(type) {
   830  		case *fs.SeekOption:
   831  			offset = x.Offset
   832  		case *fs.RangeOption:
   833  			offset, limit = x.Decode(o.Size())
   834  		default:
   835  			// pass on Options to underlying open if appropriate
   836  			openOptions = append(openOptions, option)
   837  		}
   838  	}
   839  	rc, err = o.f.cipher.DecryptDataSeek(ctx, func(ctx context.Context, underlyingOffset, underlyingLimit int64) (io.ReadCloser, error) {
   840  		if underlyingOffset == 0 && underlyingLimit < 0 {
   841  			// Open with no seek
   842  			return o.Object.Open(ctx, openOptions...)
   843  		}
   844  		// Open stream with a range of underlyingOffset, underlyingLimit
   845  		end := int64(-1)
   846  		if underlyingLimit >= 0 {
   847  			end = underlyingOffset + underlyingLimit - 1
   848  			if end >= o.Object.Size() {
   849  				end = -1
   850  			}
   851  		}
   852  		newOpenOptions := append(openOptions, &fs.RangeOption{Start: underlyingOffset, End: end})
   853  		return o.Object.Open(ctx, newOpenOptions...)
   854  	}, offset, limit)
   855  	if err != nil {
   856  		return nil, err
   857  	}
   858  	return rc, nil
   859  }
   860  
   861  // Update in to the object with the modTime given of the given size
   862  func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) error {
   863  	update := func(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) (fs.Object, error) {
   864  		return o.Object, o.Object.Update(ctx, in, src, options...)
   865  	}
   866  	_, err := o.f.put(ctx, in, src, options, update)
   867  	return err
   868  }
   869  
   870  // newDir returns a dir with the Name decrypted
   871  func (f *Fs) newDir(ctx context.Context, dir fs.Directory) fs.Directory {
   872  	newDir := fs.NewDirCopy(ctx, dir)
   873  	remote := dir.Remote()
   874  	decryptedRemote, err := f.cipher.DecryptDirName(remote)
   875  	if err != nil {
   876  		fs.Debugf(remote, "Undecryptable dir name: %v", err)
   877  	} else {
   878  		newDir.SetRemote(decryptedRemote)
   879  	}
   880  	return newDir
   881  }
   882  
   883  // UserInfo returns info about the connected user
   884  func (f *Fs) UserInfo(ctx context.Context) (map[string]string, error) {
   885  	do := f.Fs.Features().UserInfo
   886  	if do == nil {
   887  		return nil, fs.ErrorNotImplemented
   888  	}
   889  	return do(ctx)
   890  }
   891  
   892  // Disconnect the current user
   893  func (f *Fs) Disconnect(ctx context.Context) error {
   894  	do := f.Fs.Features().Disconnect
   895  	if do == nil {
   896  		return fs.ErrorNotImplemented
   897  	}
   898  	return do(ctx)
   899  }
   900  
   901  // ObjectInfo describes a wrapped fs.ObjectInfo for being the source
   902  //
   903  // This encrypts the remote name and adjusts the size
   904  type ObjectInfo struct {
   905  	fs.ObjectInfo
   906  	f     *Fs
   907  	nonce nonce
   908  }
   909  
   910  func (f *Fs) newObjectInfo(src fs.ObjectInfo, nonce nonce) *ObjectInfo {
   911  	return &ObjectInfo{
   912  		ObjectInfo: src,
   913  		f:          f,
   914  		nonce:      nonce,
   915  	}
   916  }
   917  
   918  // Fs returns read only access to the Fs that this object is part of
   919  func (o *ObjectInfo) Fs() fs.Info {
   920  	return o.f
   921  }
   922  
   923  // Remote returns the remote path
   924  func (o *ObjectInfo) Remote() string {
   925  	return o.f.cipher.EncryptFileName(o.ObjectInfo.Remote())
   926  }
   927  
   928  // Size returns the size of the file
   929  func (o *ObjectInfo) Size() int64 {
   930  	size := o.ObjectInfo.Size()
   931  	if size < 0 {
   932  		return size
   933  	}
   934  	return o.f.cipher.EncryptedSize(size)
   935  }
   936  
   937  // Hash returns the selected checksum of the file
   938  // If no checksum is available it returns ""
   939  func (o *ObjectInfo) Hash(ctx context.Context, hash hash.Type) (string, error) {
   940  	var srcObj fs.Object
   941  	var ok bool
   942  	// Get the underlying object if there is one
   943  	if srcObj, ok = o.ObjectInfo.(fs.Object); ok {
   944  		// Prefer direct interface assertion
   945  	} else if do, ok := o.ObjectInfo.(fs.ObjectUnWrapper); ok {
   946  		// Otherwise likely is an operations.OverrideRemote
   947  		srcObj = do.UnWrap()
   948  	} else {
   949  		return "", nil
   950  	}
   951  	// if this is wrapping a local object then we work out the hash
   952  	if srcObj.Fs().Features().IsLocal {
   953  		// Read the data and encrypt it to calculate the hash
   954  		fs.Debugf(o, "Computing %v hash of encrypted source", hash)
   955  		return o.f.computeHashWithNonce(ctx, o.nonce, srcObj, hash)
   956  	}
   957  	return "", nil
   958  }
   959  
   960  // ID returns the ID of the Object if known, or "" if not
   961  func (o *Object) ID() string {
   962  	do, ok := o.Object.(fs.IDer)
   963  	if !ok {
   964  		return ""
   965  	}
   966  	return do.ID()
   967  }
   968  
   969  // SetTier performs changing storage tier of the Object if
   970  // multiple storage classes supported
   971  func (o *Object) SetTier(tier string) error {
   972  	do, ok := o.Object.(fs.SetTierer)
   973  	if !ok {
   974  		return errors.New("crypt: underlying remote does not support SetTier")
   975  	}
   976  	return do.SetTier(tier)
   977  }
   978  
   979  // GetTier returns storage tier or class of the Object
   980  func (o *Object) GetTier() string {
   981  	do, ok := o.Object.(fs.GetTierer)
   982  	if !ok {
   983  		return ""
   984  	}
   985  	return do.GetTier()
   986  }
   987  
   988  // Check the interfaces are satisfied
   989  var (
   990  	_ fs.Fs              = (*Fs)(nil)
   991  	_ fs.Purger          = (*Fs)(nil)
   992  	_ fs.Copier          = (*Fs)(nil)
   993  	_ fs.Mover           = (*Fs)(nil)
   994  	_ fs.DirMover        = (*Fs)(nil)
   995  	_ fs.Commander       = (*Fs)(nil)
   996  	_ fs.PutUncheckeder  = (*Fs)(nil)
   997  	_ fs.PutStreamer     = (*Fs)(nil)
   998  	_ fs.CleanUpper      = (*Fs)(nil)
   999  	_ fs.UnWrapper       = (*Fs)(nil)
  1000  	_ fs.ListRer         = (*Fs)(nil)
  1001  	_ fs.Abouter         = (*Fs)(nil)
  1002  	_ fs.Wrapper         = (*Fs)(nil)
  1003  	_ fs.MergeDirser     = (*Fs)(nil)
  1004  	_ fs.DirCacheFlusher = (*Fs)(nil)
  1005  	_ fs.ChangeNotifier  = (*Fs)(nil)
  1006  	_ fs.PublicLinker    = (*Fs)(nil)
  1007  	_ fs.UserInfoer      = (*Fs)(nil)
  1008  	_ fs.Disconnecter    = (*Fs)(nil)
  1009  	_ fs.ObjectInfo      = (*ObjectInfo)(nil)
  1010  	_ fs.Object          = (*Object)(nil)
  1011  	_ fs.ObjectUnWrapper = (*Object)(nil)
  1012  	_ fs.IDer            = (*Object)(nil)
  1013  	_ fs.SetTierer       = (*Object)(nil)
  1014  	_ fs.GetTierer       = (*Object)(nil)
  1015  )