diff options
| author | Michael Albinus | 2020-06-10 19:36:53 +0200 |
|---|---|---|
| committer | Michael Albinus | 2020-06-10 19:36:53 +0200 |
| commit | b19259c8412ee2e715c4bd145711e23729411fd0 (patch) | |
| tree | 6e79f2d9bc1dd3ab3533380faa441e5564eb7149 | |
| parent | ee8b2742d7f6d03daea37f1bac48c2746f7ca789 (diff) | |
| download | emacs-b19259c8412ee2e715c4bd145711e23729411fd0.tar.gz emacs-b19259c8412ee2e715c4bd145711e23729411fd0.zip | |
Futher tramp-crypt implementation and documentation
* doc/misc/tramp.texi (Top, Configuration): Insert section
`Keeping files encrypted' in menu.
(Keeping files encrypted): New node.
* lisp/net/tramp-crypt.el (tramp-crypt-file-name-handler-alist):
Add `tramp-set-file-uid-gid'.
(tramp-crypt-maybe-open-connection): Simplify.
(tramp-crypt-do-encrypt-or-decrypt-file): Use `binary' coding system.
(tramp-crypt-handle-set-file-uid-gid): New defun.
* test/lisp/net/tramp-tests.el (tramp-test09-insert-file-contents):
Adapt test.
| -rw-r--r-- | doc/misc/tramp.texi | 118 | ||||
| -rw-r--r-- | lisp/net/tramp-crypt.el | 19 | ||||
| -rw-r--r-- | test/lisp/net/tramp-tests.el | 25 |
3 files changed, 144 insertions, 18 deletions
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index d1688deb1b7..176d3a5b1e0 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi | |||
| @@ -141,6 +141,7 @@ Configuring @value{tramp} for use | |||
| 141 | * Remote shell setup:: Remote shell setup hints. | 141 | * Remote shell setup:: Remote shell setup hints. |
| 142 | * Android shell setup:: Android shell setup hints. | 142 | * Android shell setup:: Android shell setup hints. |
| 143 | * Auto-save and Backup:: Auto-save and Backup. | 143 | * Auto-save and Backup:: Auto-save and Backup. |
| 144 | * Keeping files encrypted:: Protect remote files by encryption. | ||
| 144 | * Windows setup hints:: Issues with Cygwin ssh. | 145 | * Windows setup hints:: Issues with Cygwin ssh. |
| 145 | 146 | ||
| 146 | Using @value{tramp} | 147 | Using @value{tramp} |
| @@ -667,6 +668,7 @@ might be used in your init file: | |||
| 667 | * Remote shell setup:: Remote shell setup hints. | 668 | * Remote shell setup:: Remote shell setup hints. |
| 668 | * Android shell setup:: Android shell setup hints. | 669 | * Android shell setup:: Android shell setup hints. |
| 669 | * Auto-save and Backup:: Auto-save and Backup. | 670 | * Auto-save and Backup:: Auto-save and Backup. |
| 671 | * Keeping files encrypted:: Protect remote files by encryption. | ||
| 670 | * Windows setup hints:: Issues with Cygwin ssh. | 672 | * Windows setup hints:: Issues with Cygwin ssh. |
| 671 | @end menu | 673 | @end menu |
| 672 | 674 | ||
| @@ -2648,6 +2650,114 @@ auto-saved files to the same directory as the original file. | |||
| 2648 | Alternatively, set the user option @code{tramp-auto-save-directory} | 2650 | Alternatively, set the user option @code{tramp-auto-save-directory} |
| 2649 | to direct all auto saves to that location. | 2651 | to direct all auto saves to that location. |
| 2650 | 2652 | ||
| 2653 | |||
| 2654 | @node Keeping files encrypted | ||
| 2655 | @section Protect remote files by encryption | ||
| 2656 | @cindex Encrypt remote directories | ||
| 2657 | |||
| 2658 | Sometimes, it is desirable to protect files located on remote | ||
| 2659 | directories, like cloud storages. In order to do this, you might | ||
| 2660 | instruct @value{tramp} to encrypt all files copied to a given remote | ||
| 2661 | directory, and to decrypt such files when accessing. This includes | ||
| 2662 | both file contents and file names. | ||
| 2663 | |||
| 2664 | @value{tramp} does this transparently. Although both files and file | ||
| 2665 | names are encrypted on the remote side, they are accessible inside | ||
| 2666 | Emacs as they wouldn't be transformed as such. | ||
| 2667 | |||
| 2668 | @cindex @command{encfs} | ||
| 2669 | @cindex @command{encfsctl} | ||
| 2670 | Internally, @value{tramp} uses the @command{encfs} package. | ||
| 2671 | Therefore, this feature is available only if this package is installed | ||
| 2672 | on the local host. @value{tramp} does not keep and @samp{encfs | ||
| 2673 | mountpoint} permanently. Instead, it encrypts / decrypts files and | ||
| 2674 | file names on the fly, using @command{encfsctl}. | ||
| 2675 | |||
| 2676 | @deffn Command tramp-crypt-add-directory name | ||
| 2677 | This command marks the existing remote directory @var{name} for | ||
| 2678 | encryption. Files in that directory and all subdirectories will be | ||
| 2679 | encrypted before copying to, and decrypted after copying from that | ||
| 2680 | directory. File and directory names will be also encrypted. | ||
| 2681 | @end deffn | ||
| 2682 | |||
| 2683 | @defopt tramp-crypt-encfs-option | ||
| 2684 | If a remote directory is marked for encryption, it is initialized via | ||
| 2685 | @command{encfs} the very first time a file in this directory is | ||
| 2686 | accessed. This user option controls, which default @command{encfs} | ||
| 2687 | configuration option will be selected, it can be @t{"--standard"} | ||
| 2688 | or @t{"--paranoia"}. See the @samp{encfs(1)} man page for details. | ||
| 2689 | |||
| 2690 | However, @value{tramp} must adapt these configuration sets. The | ||
| 2691 | @code{chainedNameIV} configuration option must be disabled; otherwise | ||
| 2692 | @value{tramp} couldn't handle file name encryption transparently. | ||
| 2693 | @end defopt | ||
| 2694 | |||
| 2695 | A password protected @option{encfs} configuration file is created the | ||
| 2696 | very first time you access an encrypted remote directory. It is kept | ||
| 2697 | in your @code{user-emacs-directory} with the url-encoded directory | ||
| 2698 | name as part of the basename, and @file{encfs6.xml} as suffix. If | ||
| 2699 | you, for example, mark the remote directory | ||
| 2700 | @file{@trampfn{nextcloud,user@@host,/path/to/dir}} for encryption, the | ||
| 2701 | configuration file is saved as | ||
| 2702 | @file{tramp-%2Fnextcloud%3Auser%40host%3A%2Fpath%2Fto%2Fdir%2F.encfs6.xml} | ||
| 2703 | in @code{user-emacs-directory}. Do not loose this file and the | ||
| 2704 | corresponding password; otherwise there is no way to decrypt your | ||
| 2705 | encrypted files. | ||
| 2706 | |||
| 2707 | @defopt tramp-crypt-save-encfs-config-remote | ||
| 2708 | If this user option is non-nil (the default), the @option{encfs} | ||
| 2709 | configuration file @file{.encfs6.xml} is also kept in the encrypted | ||
| 2710 | remote directory. It depends on you, whether you regard the password | ||
| 2711 | protection of this file as sufficient. The advantage would be, that | ||
| 2712 | such a remote directory could be accessed by different Emacs sessions, | ||
| 2713 | different users, without presharing the configuration file between the | ||
| 2714 | users. | ||
| 2715 | @end defopt | ||
| 2716 | |||
| 2717 | The command @command{encfsctl}, the workhorse for encryption / | ||
| 2718 | decryption, needs the configuration file password every call. | ||
| 2719 | Therefore, it is recommend to cache this password in Emacs. This can | ||
| 2720 | be done using @code{auth-sources}, @ref{Using an authentication file}. | ||
| 2721 | An entry needs the url-encoded directory name as machine, your local | ||
| 2722 | user name as user, and the password. The port is optional, if given | ||
| 2723 | it must be the string @t{"crypt"}. The example above would require | ||
| 2724 | the following entry in the authentication file (@t{"yourname"} is the | ||
| 2725 | result of @code{(user-login-name)}): | ||
| 2726 | |||
| 2727 | @example | ||
| 2728 | machine %2Fnextcloud%3Auser%40host%3A%2Fpath%2Fto%2Fdir%2F \ | ||
| 2729 | login yourname port crypt password geheim | ||
| 2730 | @end example | ||
| 2731 | |||
| 2732 | If you use a remote file name with a quoted localname part, this | ||
| 2733 | localname and the corresponding file will not be encrypted / | ||
| 2734 | decrypted. If you have an encrypted remote directory | ||
| 2735 | @file{@trampfn{nextcloud,user@@host,/path/to/dir}}, the command | ||
| 2736 | |||
| 2737 | @example | ||
| 2738 | @kbd{C-x d @trampfn{nextcloud,user@@host,/path/to/dir}} | ||
| 2739 | @end example | ||
| 2740 | |||
| 2741 | @noindent | ||
| 2742 | will show the directory listing with the plain file names, and the | ||
| 2743 | command | ||
| 2744 | |||
| 2745 | @example | ||
| 2746 | @kbd{C-x d @trampfn{nextcloud,user@@host,/:/path/to/dir}} | ||
| 2747 | @end example | ||
| 2748 | |||
| 2749 | @noindent | ||
| 2750 | will show the directory listing with the encrypted file names, and | ||
| 2751 | visiting a file will show its encrypted contents. However, it is | ||
| 2752 | highly discouraged to mix encrypted and not encrypted files in the | ||
| 2753 | same directory. | ||
| 2754 | |||
| 2755 | @deffn Command tramp-crypt-add-directory name | ||
| 2756 | If a remote directory shall not include encrypted files anymore, it | ||
| 2757 | must be indicated by this command. | ||
| 2758 | @end deffn | ||
| 2759 | |||
| 2760 | |||
| 2651 | @node Windows setup hints | 2761 | @node Windows setup hints |
| 2652 | @section Issues with Cygwin ssh | 2762 | @section Issues with Cygwin ssh |
| 2653 | @cindex cygwin, issues | 2763 | @cindex cygwin, issues |
| @@ -2681,10 +2791,10 @@ Wiki} it is explained how to use the helper program | |||
| 2681 | @cindex @option{scpx} method with cygwin | 2791 | @cindex @option{scpx} method with cygwin |
| 2682 | 2792 | ||
| 2683 | When using the @option{scpx} access method, Emacs may call | 2793 | When using the @option{scpx} access method, Emacs may call |
| 2684 | @command{scp} with MS Windows file naming, such as @code{c:/foo}. But | 2794 | @command{scp} with MS Windows file naming, such as @file{c:/foo}. But |
| 2685 | the version of @command{scp} that is installed with Cygwin does not | 2795 | the version of @command{scp} that is installed with Cygwin does not |
| 2686 | know about MS Windows file naming, which causes it to incorrectly look | 2796 | know about MS Windows file naming, which causes it to incorrectly look |
| 2687 | for a host named @code{c}. | 2797 | for a host named @samp{c}. |
| 2688 | 2798 | ||
| 2689 | A workaround: write a wrapper script for @option{scp} to convert | 2799 | A workaround: write a wrapper script for @option{scp} to convert |
| 2690 | Windows file names to Cygwin file names. | 2800 | Windows file names to Cygwin file names. |
| @@ -4158,8 +4268,8 @@ Host * | |||
| 4158 | @end group | 4268 | @end group |
| 4159 | @end example | 4269 | @end example |
| 4160 | 4270 | ||
| 4161 | Check @command{man ssh_config} whether these options are supported on | 4271 | Check the @samp{ssh_config(5)} man page whether these options are |
| 4162 | your proxy host. | 4272 | supported on your proxy host. |
| 4163 | 4273 | ||
| 4164 | 4274 | ||
| 4165 | @item | 4275 | @item |
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el index d9ba2e49f76..664f4413473 100644 --- a/lisp/net/tramp-crypt.el +++ b/lisp/net/tramp-crypt.el | |||
| @@ -44,11 +44,11 @@ | |||
| 44 | 44 | ||
| 45 | ;; If the user option `tramp-crypt-save-encfs-config-remote' is | 45 | ;; If the user option `tramp-crypt-save-encfs-config-remote' is |
| 46 | ;; non-nil (the default), the encfs configuration file ".encfs6.xml" | 46 | ;; non-nil (the default), the encfs configuration file ".encfs6.xml" |
| 47 | ;; is also be kept in the crypted remote directory. It depends, | 47 | ;; is also kept in the crypted remote directory. It depends on you, |
| 48 | ;; whether you regard the password protection of this file as | 48 | ;; whether you regard the password protection of this file as |
| 49 | ;; sufficient. | 49 | ;; sufficient. |
| 50 | 50 | ||
| 51 | ;; If you apply an operation with a quoted localname part, this | 51 | ;; If you use a remote file name with a quoted localname part, this |
| 52 | ;; localname and the corresponding file will not be encrypted/ | 52 | ;; localname and the corresponding file will not be encrypted/ |
| 53 | ;; decrypted. For example, if you have a crypted remote directory | 53 | ;; decrypted. For example, if you have a crypted remote directory |
| 54 | ;; "/nextcloud:user@host:/crypted_dir", the command | 54 | ;; "/nextcloud:user@host:/crypted_dir", the command |
| @@ -213,7 +213,7 @@ If NAME doesn't belong to a crypted remote directory, retun nil." | |||
| 213 | (start-file-process . ignore) | 213 | (start-file-process . ignore) |
| 214 | ;; `substitute-in-file-name' performed by default handler. | 214 | ;; `substitute-in-file-name' performed by default handler. |
| 215 | ;; (temporary-file-directory . tramp-crypt-handle-temporary-file-directory) | 215 | ;; (temporary-file-directory . tramp-crypt-handle-temporary-file-directory) |
| 216 | ;; `tramp-set-file-uid-gid' performed by default handler. | 216 | (tramp-set-file-uid-gid . tramp-crypt-handle-set-file-uid-gid) |
| 217 | ;; (unhandled-file-name-directory . ignore) | 217 | ;; (unhandled-file-name-directory . ignore) |
| 218 | (vc-registered . ignore) | 218 | (vc-registered . ignore) |
| 219 | (verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime) | 219 | (verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime) |
| @@ -334,7 +334,6 @@ connection if a previous connection has died for some reason." | |||
| 334 | (with-temp-file local-config | 334 | (with-temp-file local-config |
| 335 | (insert-file-contents | 335 | (insert-file-contents |
| 336 | (expand-file-name tramp-crypt-encfs-config tmpdir1)) | 336 | (expand-file-name tramp-crypt-encfs-config tmpdir1)) |
| 337 | (goto-char (point-min)) | ||
| 338 | (when (search-forward | 337 | (when (search-forward |
| 339 | "<chainedNameIV>1</chainedNameIV>" nil 'noerror) | 338 | "<chainedNameIV>1</chainedNameIV>" nil 'noerror) |
| 340 | (replace-match "<chainedNameIV>0</chainedNameIV>"))) | 339 | (replace-match "<chainedNameIV>0</chainedNameIV>"))) |
| @@ -427,9 +426,9 @@ If OP ist `decrypt', the basename of INFILE must be an encrypted file name." | |||
| 427 | (dir (tramp-crypt-file-name-p root)) | 426 | (dir (tramp-crypt-file-name-p root)) |
| 428 | (crypt-vec (tramp-crypt-dissect-file-name dir))) | 427 | (crypt-vec (tramp-crypt-dissect-file-name dir))) |
| 429 | (let ((coding-system-for-read | 428 | (let ((coding-system-for-read |
| 430 | (if (eq op 'decrypt) 'raw-text coding-system-for-read)) | 429 | (if (eq op 'decrypt) 'binary coding-system-for-read)) |
| 431 | (coding-system-for-write | 430 | (coding-system-for-write |
| 432 | (if (eq op 'encrypt) 'raw-text coding-system-for-write))) | 431 | (if (eq op 'encrypt) 'binary coding-system-for-write))) |
| 433 | (tramp-crypt-send-command | 432 | (tramp-crypt-send-command |
| 434 | crypt-vec "cat" (and (eq op 'encrypt) "--reverse") | 433 | crypt-vec "cat" (and (eq op 'encrypt) "--reverse") |
| 435 | (file-name-directory infile) | 434 | (file-name-directory infile) |
| @@ -759,6 +758,14 @@ absolute file names." | |||
| 759 | (tramp-compat-set-file-times | 758 | (tramp-compat-set-file-times |
| 760 | (tramp-crypt-encrypt-file-name filename) time flag)))) | 759 | (tramp-crypt-encrypt-file-name filename) time flag)))) |
| 761 | 760 | ||
| 761 | (defun tramp-crypt-handle-set-file-uid-gid (filename &optional uid gid) | ||
| 762 | "Like `tramp-set-file-uid-gid' for Tramp files." | ||
| 763 | (with-parsed-tramp-file-name filename nil | ||
| 764 | (tramp-flush-file-properties v localname) | ||
| 765 | (let (tramp-crypt-enabled) | ||
| 766 | (tramp-set-file-uid-gid | ||
| 767 | (tramp-crypt-encrypt-file-name filename) uid gid)))) | ||
| 768 | |||
| 762 | (add-hook 'tramp-unload-hook | 769 | (add-hook 'tramp-unload-hook |
| 763 | (lambda () | 770 | (lambda () |
| 764 | (unload-feature 'tramp-crypt 'force))) | 771 | (unload-feature 'tramp-crypt 'force))) |
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index d578c359d79..578da4171c7 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el | |||
| @@ -2294,16 +2294,25 @@ This checks also `file-name-as-directory', `file-name-directory', | |||
| 2294 | (unwind-protect | 2294 | (unwind-protect |
| 2295 | (with-temp-buffer | 2295 | (with-temp-buffer |
| 2296 | (write-region "foo" nil tmp-name) | 2296 | (write-region "foo" nil tmp-name) |
| 2297 | (insert-file-contents tmp-name) | 2297 | (let ((point (point))) |
| 2298 | (should (string-equal (buffer-string) "foo")) | 2298 | (insert-file-contents tmp-name) |
| 2299 | (insert-file-contents tmp-name) | 2299 | (should (string-equal (buffer-string) "foo")) |
| 2300 | (should (string-equal (buffer-string) "foofoo")) | 2300 | (should (= point (point)))) |
| 2301 | (goto-char (1+ (point))) | ||
| 2302 | (let ((point (point))) | ||
| 2303 | (insert-file-contents tmp-name) | ||
| 2304 | (should (string-equal (buffer-string) "ffoooo")) | ||
| 2305 | (should (= point (point)))) | ||
| 2301 | ;; Insert partly. | 2306 | ;; Insert partly. |
| 2302 | (insert-file-contents tmp-name nil 1 3) | 2307 | (let ((point (point))) |
| 2303 | (should (string-equal (buffer-string) "oofoofoo")) | 2308 | (insert-file-contents tmp-name nil 1 3) |
| 2309 | (should (string-equal (buffer-string) "foofoooo")) | ||
| 2310 | (should (= point (point)))) | ||
| 2304 | ;; Replace. | 2311 | ;; Replace. |
| 2305 | (insert-file-contents tmp-name nil nil nil 'replace) | 2312 | (let ((point (point))) |
| 2306 | (should (string-equal (buffer-string) "foo")) | 2313 | (insert-file-contents tmp-name nil nil nil 'replace) |
| 2314 | (should (string-equal (buffer-string) "foo")) | ||
| 2315 | (should (= point (point)))) | ||
| 2307 | ;; Error case. | 2316 | ;; Error case. |
| 2308 | (delete-file tmp-name) | 2317 | (delete-file tmp-name) |
| 2309 | (should-error | 2318 | (should-error |