diff options
Diffstat (limited to 'lisp/server.el')
| -rw-r--r-- | lisp/server.el | 144 |
1 files changed, 96 insertions, 48 deletions
diff --git a/lisp/server.el b/lisp/server.el index 404bebc4747..1e2f458ac9c 100644 --- a/lisp/server.el +++ b/lisp/server.el | |||
| @@ -139,6 +139,32 @@ directory residing in a NTFS partition instead." | |||
| 139 | ;;;###autoload | 139 | ;;;###autoload |
| 140 | (put 'server-auth-dir 'risky-local-variable t) | 140 | (put 'server-auth-dir 'risky-local-variable t) |
| 141 | 141 | ||
| 142 | (defcustom server-auth-key nil | ||
| 143 | "Server authentication key. | ||
| 144 | |||
| 145 | Normally, the authentication key is randomly generated when the | ||
| 146 | server starts, which guarantees some level of security. It is | ||
| 147 | recommended to leave it that way. Using a long-lived shared key | ||
| 148 | will decrease security (especially since the key is transmitted as | ||
| 149 | plain text). | ||
| 150 | |||
| 151 | In some situations however, it can be difficult to share randomly | ||
| 152 | generated passwords with remote hosts (eg. no shared directory), | ||
| 153 | so you can set the key with this variable and then copy the | ||
| 154 | server file to the remote host (with possible changes to IP | ||
| 155 | address and/or port if that applies). | ||
| 156 | |||
| 157 | The key must consist of 64 ASCII printable characters except for | ||
| 158 | space (this means characters from ! to ~; or from code 33 to 126). | ||
| 159 | |||
| 160 | You can use \\[server-generate-key] to get a random authentication | ||
| 161 | key." | ||
| 162 | :group 'server | ||
| 163 | :type '(choice | ||
| 164 | (const :tag "Random" nil) | ||
| 165 | (string :tag "Password")) | ||
| 166 | :version "24.2") | ||
| 167 | |||
| 142 | (defcustom server-raise-frame t | 168 | (defcustom server-raise-frame t |
| 143 | "If non-nil, raise frame when switching to a buffer." | 169 | "If non-nil, raise frame when switching to a buffer." |
| 144 | :group 'server | 170 | :group 'server |
| @@ -494,41 +520,62 @@ Creates the directory if necessary and makes sure: | |||
| 494 | ;; Check that it's safe for use. | 520 | ;; Check that it's safe for use. |
| 495 | (let* ((uid (nth 2 attrs)) | 521 | (let* ((uid (nth 2 attrs)) |
| 496 | (w32 (eq system-type 'windows-nt)) | 522 | (w32 (eq system-type 'windows-nt)) |
| 497 | (safe (catch :safe | 523 | (safe (cond |
| 498 | (unless (eq t (car attrs)) ; is a dir? | 524 | ((not (eq t (car attrs))) nil) ; is a dir? |
| 499 | (throw :safe nil)) | 525 | ((and w32 (zerop uid)) ; on FAT32? |
| 500 | (when (and w32 (zerop uid)) ; on FAT32? | 526 | (display-warning |
| 501 | (display-warning | 527 | 'server |
| 502 | 'server | 528 | (format "Using `%s' to store Emacs-server authentication files. |
| 503 | (format "Using `%s' to store Emacs-server authentication files. | ||
| 504 | Directories on FAT32 filesystems are NOT secure against tampering. | 529 | Directories on FAT32 filesystems are NOT secure against tampering. |
| 505 | See variable `server-auth-dir' for details." | 530 | See variable `server-auth-dir' for details." |
| 506 | (file-name-as-directory dir)) | 531 | (file-name-as-directory dir)) |
| 507 | :warning) | 532 | :warning) |
| 508 | (throw :safe t)) | 533 | t) |
| 509 | (unless (or (= uid (user-uid)) ; is the dir ours? | 534 | ((and (/= uid (user-uid)) ; is the dir ours? |
| 510 | (and w32 | 535 | (or (not w32) |
| 511 | ;; Files created on Windows by | 536 | ;; Files created on Windows by Administrator |
| 512 | ;; Administrator (RID=500) have | 537 | ;; (RID=500) have the Administrators (RID=544) |
| 513 | ;; the Administrators (RID=544) | 538 | ;; group recorded as the owner. |
| 514 | ;; group recorded as the owner. | 539 | (/= uid 544) (/= (user-uid) 500))) |
| 515 | (= uid 544) (= (user-uid) 500))) | 540 | nil) |
| 516 | (throw :safe nil)) | 541 | (w32 t) ; on NTFS? |
| 517 | (when w32 ; on NTFS? | 542 | (t ; else, check permissions |
| 518 | (throw :safe t)) | 543 | (zerop (logand ?\077 (file-modes dir))))))) |
| 519 | (unless (zerop (logand ?\077 (file-modes dir))) | ||
| 520 | (throw :safe nil)) | ||
| 521 | t))) | ||
| 522 | (unless safe | 544 | (unless safe |
| 523 | (error "The directory `%s' is unsafe" dir))))) | 545 | (error "The directory `%s' is unsafe" dir))))) |
| 524 | 546 | ||
| 547 | (defun server-generate-key () | ||
| 548 | "Generate and return a random authentication key. | ||
| 549 | The key is a 64-byte string of random chars in the range `!'..`~'. | ||
| 550 | If called interactively, also inserts it into current buffer." | ||
| 551 | (interactive) | ||
| 552 | (let ((auth-key | ||
| 553 | (loop repeat 64 | ||
| 554 | collect (+ 33 (random 94)) into auth | ||
| 555 | finally return (concat auth)))) | ||
| 556 | (if (called-interactively-p 'interactive) | ||
| 557 | (insert auth-key)) | ||
| 558 | auth-key)) | ||
| 559 | |||
| 560 | (defun server-get-auth-key () | ||
| 561 | "Return server's authentication key. | ||
| 562 | |||
| 563 | If `server-auth-key' is nil, just call `server-generate-key'. | ||
| 564 | Otherwise, if `server-auth-key' is a valid key, return it. | ||
| 565 | If the key is not valid, signal an error." | ||
| 566 | (if server-auth-key | ||
| 567 | (if (string-match-p "^[!-~]\\{64\\}$" server-auth-key) | ||
| 568 | server-auth-key | ||
| 569 | (error "The key '%s' is invalid" server-auth-key)) | ||
| 570 | (server-generate-key))) | ||
| 571 | |||
| 525 | ;;;###autoload | 572 | ;;;###autoload |
| 526 | (defun server-start (&optional leave-dead inhibit-prompt) | 573 | (defun server-start (&optional leave-dead inhibit-prompt) |
| 527 | "Allow this Emacs process to be a server for client processes. | 574 | "Allow this Emacs process to be a server for client processes. |
| 528 | This starts a server communications subprocess through which | 575 | This starts a server communications subprocess through which client |
| 529 | client \"editors\" can send your editing commands to this Emacs | 576 | \"editors\" can send your editing commands to this Emacs job. |
| 530 | job. To use the server, set up the program `emacsclient' in the | 577 | To use the server, set up the program `emacsclient' in the Emacs |
| 531 | Emacs distribution as your standard \"editor\". | 578 | distribution as your standard \"editor\". |
| 532 | 579 | ||
| 533 | Optional argument LEAVE-DEAD (interactively, a prefix arg) means just | 580 | Optional argument LEAVE-DEAD (interactively, a prefix arg) means just |
| 534 | kill any existing server communications subprocess. | 581 | kill any existing server communications subprocess. |
| @@ -615,13 +662,7 @@ server or call `M-x server-force-delete' to forcibly disconnect it.") | |||
| 615 | (unless server-process (error "Could not start server process")) | 662 | (unless server-process (error "Could not start server process")) |
| 616 | (process-put server-process :server-file server-file) | 663 | (process-put server-process :server-file server-file) |
| 617 | (when server-use-tcp | 664 | (when server-use-tcp |
| 618 | (let ((auth-key | 665 | (let ((auth-key (server-get-auth-key))) |
| 619 | (loop | ||
| 620 | ;; The auth key is a 64-byte string of random chars in the | ||
| 621 | ;; range `!'..`~'. | ||
| 622 | repeat 64 | ||
| 623 | collect (+ 33 (random 94)) into auth | ||
| 624 | finally return (concat auth)))) | ||
| 625 | (process-put server-process :auth-key auth-key) | 666 | (process-put server-process :auth-key auth-key) |
| 626 | (with-temp-file server-file | 667 | (with-temp-file server-file |
| 627 | (set-buffer-multibyte nil) | 668 | (set-buffer-multibyte nil) |
| @@ -780,10 +821,6 @@ This handles splitting the command if it would be bigger than | |||
| 780 | (select-frame frame) | 821 | (select-frame frame) |
| 781 | (process-put proc 'frame frame) | 822 | (process-put proc 'frame frame) |
| 782 | (process-put proc 'terminal (frame-terminal frame)) | 823 | (process-put proc 'terminal (frame-terminal frame)) |
| 783 | |||
| 784 | ;; Display *scratch* by default. | ||
| 785 | (switch-to-buffer (get-buffer-create "*scratch*") 'norecord) | ||
| 786 | |||
| 787 | frame)) | 824 | frame)) |
| 788 | 825 | ||
| 789 | (defun server-create-window-system-frame (display nowait proc parent-id | 826 | (defun server-create-window-system-frame (display nowait proc parent-id |
| @@ -816,9 +853,6 @@ This handles splitting the command if it would be bigger than | |||
| 816 | (select-frame frame) | 853 | (select-frame frame) |
| 817 | (process-put proc 'frame frame) | 854 | (process-put proc 'frame frame) |
| 818 | (process-put proc 'terminal (frame-terminal frame)) | 855 | (process-put proc 'terminal (frame-terminal frame)) |
| 819 | |||
| 820 | ;; Display *scratch* by default. | ||
| 821 | (switch-to-buffer (get-buffer-create "*scratch*") 'norecord) | ||
| 822 | frame))) | 856 | frame))) |
| 823 | 857 | ||
| 824 | (defun server-goto-toplevel (proc) | 858 | (defun server-goto-toplevel (proc) |
| @@ -1042,8 +1076,9 @@ The following commands are accepted by the client: | |||
| 1042 | 1076 | ||
| 1043 | ;; -window-system: Open a new X frame. | 1077 | ;; -window-system: Open a new X frame. |
| 1044 | (`"-window-system" | 1078 | (`"-window-system" |
| 1045 | (setq dontkill t) | 1079 | (if (fboundp 'x-create-frame) |
| 1046 | (setq tty-name 'window-system)) | 1080 | (setq dontkill t |
| 1081 | tty-name 'window-system))) | ||
| 1047 | 1082 | ||
| 1048 | ;; -resume: Resume a suspended tty frame. | 1083 | ;; -resume: Resume a suspended tty frame. |
| 1049 | (`"-resume" | 1084 | (`"-resume" |
| @@ -1071,7 +1106,8 @@ The following commands are accepted by the client: | |||
| 1071 | (setq dontkill t) | 1106 | (setq dontkill t) |
| 1072 | (pop args-left)) | 1107 | (pop args-left)) |
| 1073 | 1108 | ||
| 1074 | ;; -tty DEVICE-NAME TYPE: Open a new tty frame at the client. | 1109 | ;; -tty DEVICE-NAME TYPE: Open a new tty frame. |
| 1110 | ;; (But if we see -window-system later, use that.) | ||
| 1075 | (`"-tty" | 1111 | (`"-tty" |
| 1076 | (setq tty-name (pop args-left) | 1112 | (setq tty-name (pop args-left) |
| 1077 | tty-type (pop args-left) | 1113 | tty-type (pop args-left) |
| @@ -1133,6 +1169,13 @@ The following commands are accepted by the client: | |||
| 1133 | ;; Unknown command. | 1169 | ;; Unknown command. |
| 1134 | (arg (error "Unknown command: %s" arg)))) | 1170 | (arg (error "Unknown command: %s" arg)))) |
| 1135 | 1171 | ||
| 1172 | ;; If both -no-wait and -tty are given with file or sexp | ||
| 1173 | ;; arguments, use an existing frame. | ||
| 1174 | (and nowait | ||
| 1175 | (not (eq tty-name 'window-system)) | ||
| 1176 | (or files commands) | ||
| 1177 | (setq use-current-frame t)) | ||
| 1178 | |||
| 1136 | (setq frame | 1179 | (setq frame |
| 1137 | (cond | 1180 | (cond |
| 1138 | ((and use-current-frame | 1181 | ((and use-current-frame |
| @@ -1182,12 +1225,17 @@ The following commands are accepted by the client: | |||
| 1182 | ;; including code that needs to wait. | 1225 | ;; including code that needs to wait. |
| 1183 | (with-local-quit | 1226 | (with-local-quit |
| 1184 | (condition-case err | 1227 | (condition-case err |
| 1185 | (let* ((buffers | 1228 | (let ((buffers (server-visit-files files proc nowait))) |
| 1186 | (when files | ||
| 1187 | (server-visit-files files proc nowait)))) | ||
| 1188 | |||
| 1189 | (mapc 'funcall (nreverse commands)) | 1229 | (mapc 'funcall (nreverse commands)) |
| 1190 | 1230 | ||
| 1231 | ;; If we were told only to open a new client, obey | ||
| 1232 | ;; `initial-buffer-choice' if it specifies a file. | ||
| 1233 | (unless (or files commands) | ||
| 1234 | (if (stringp initial-buffer-choice) | ||
| 1235 | (find-file initial-buffer-choice) | ||
| 1236 | (switch-to-buffer (get-buffer-create "*scratch*") | ||
| 1237 | 'norecord))) | ||
| 1238 | |||
| 1191 | ;; Delete the client if necessary. | 1239 | ;; Delete the client if necessary. |
| 1192 | (cond | 1240 | (cond |
| 1193 | (nowait | 1241 | (nowait |