view lisp/net/tramp-gw.el @ 110121:5a6b4fafaa52

Sync with Tramp 2.1.19. * net/tramp-cmds.el (tramp-cleanup-all-connections) (tramp-reporter-dump-variable, tramp-load-report-modules) (tramp-append-tramp-buffers): Use `tramp-compat-funcall'. (tramp-bug): Recommend setting of `tramp-verbose' to 9. * net/tramp-compat.el (top): Do not autoload `tramp-handle-file-remote-p'. Load tramp-util.el and tramp-vc.el only when `start-file-process' is not bound. (byte-compile-not-obsolete-vars): Define if not bound. (tramp-compat-funcall): New defmacro. (tramp-compat-line-beginning-position) (tramp-compat-line-end-position) (tramp-compat-temporary-file-directory) (tramp-compat-make-temp-file, tramp-compat-file-attributes) (tramp-compat-copy-file, tramp-compat-copy-directory) (tramp-compat-delete-file, tramp-compat-delete-directory) (tramp-compat-number-sequence, tramp-compat-process-running-p): Use it. (tramp-advice-file-expand-wildcards): Do not use `tramp-handle-file-remote-p'. (tramp-compat-make-temp-file): Simplify fallback implementation. (tramp-compat-copy-file): Add PRESERVE-SELINUX-CONTEXT. (tramp-compat-copy-tree): Remove function. (tramp-compat-delete-file): New defun. (tramp-compat-delete-directory): Provide implementation for older Emacsen. (tramp-compat-file-attributes): Handle only `wrong-number-of-arguments' error. * net/tramp-fish.el (tramp-fish-handle-copy-file): Add PRESERVE_SELINUX_CONTEXT. (tramp-fish-handle-delete-file): Add TRASH arg. (tramp-fish-handle-directory-files-and-attributes): Do not use `tramp-fish-handle-file-attributes. (tramp-fish-handle-file-local-copy) (tramp-fish-handle-insert-file-contents) (tramp-fish-maybe-open-connection): Use `with-progress-reporter'. * net/tramp-gvfs.el (top): Require url-util. (tramp-gvfs-mount-point): Remove. (tramp-gvfs-file-name-handler-alist): Add `file-selinux-context' and `set-file-selinux-context'. (tramp-gvfs-stringify-dbus-message, tramp-gvfs-send-command) (tramp-gvfs-handle-file-selinux-context) (tramp-gvfs-handle-set-file-selinux-context): New defuns. (with-tramp-dbus-call-method): Format trace message. (tramp-gvfs-handle-copy-file): Handle PRESERVE-SELINUX-CONTEXT. (tramp-gvfs-handle-copy-file, tramp-gvfs-handle-rename-file): Implement backup call, when operation on local files fails. Use progress reporter. Flush properties of changed files. (tramp-gvfs-handle-delete-file): Add TRASH arg. Use `tramp-compat-delete-file'. (tramp-gvfs-handle-expand-file-name): Expand "~/". (tramp-gvfs-handle-make-directory): Make more traces. (tramp-gvfs-handle-write-region): Protect deleting tmpfile. (tramp-gvfs-url-file-name): Hexify file name in url. (tramp-gvfs-fuse-file-name): Take also prefix (like dav shares) into account for the resulting file name. (tramp-gvfs-handler-askquestion): Preserve current message, in order to let progress reporter continue afterwards. (Bug#6257) Return dummy mountpoint, when the answer is "no". See `tramp-gvfs-maybe-open-connection'. (tramp-gvfs-handler-mounted-unmounted) (tramp-gvfs-connection-mounted-p): Test also for new mountspec attribute "default_location". Set "prefix" property. Handle default-location. (tramp-gvfs-mount-spec): Return both prefix and mountspec. (tramp-gvfs-maybe-open-connection): Test, whether mountpoint exists. Raise an error, if not (due to a corresponding answer "no" in interactive questions, for example). Use `tramp-compat-funcall'. * net/tramp-imap.el (top): Autoload `epg-make-context'. (tramp-imap-handle-copy-file): Add PRESERVE-SELINUX-CONTEXT. (tramp-imap-do-copy-or-rename-file) (tramp-imap-handle-insert-file-contents) (tramp-imap-handle-file-local-copy): Use `with-progress-reporter'. (tramp-imap-handle-delete-file): Add TRASH arg. * net/tramp-smb.el (tramp-smb-handle-copy-file): Add PRESERVE-SELINUX-CONTEXT. (tramp-smb-handle-copy-file) (tramp-smb-handle-file-local-copy, tramp-smb-handle-rename-file) (tramp-smb-handle-write-region, tramp-smb-maybe-open-connection): Use `with-progress-reporter'. (tramp-smb-handle-delete-file): Add TRASH arg. * net/tramp.el (tramp-methods): Move hostname to the end in all ssh `tramp-login-args'. Add `tramp-async-args' attribute where appropriate. (tramp-verbose): Describe verbose level 9. (tramp-completion-function-alist) (tramp-file-name-regexp, tramp-chunksize) (tramp-local-coding-commands, tramp-remote-coding-commands) (with-connection-property, tramp-completion-mode-p) (tramp-action-process-alive, tramp-action-out-of-band) (tramp-check-for-regexp, tramp-file-name-p, tramp-equal-remote) (tramp-exists-file-name-handler): Fix docstring. (tramp-remote-process-environment): Use `format' instead of `concat'. Protect version string by apostroph. (tramp-shell-prompt-pattern): Do not use a shy group in case of XEmacs. (tramp-file-name-regexp-unified) (tramp-completion-file-name-regexp-unified): On W32 systems, do not regard the volume letter as remote filename. (Bug#5447) (tramp-perl-file-attributes) (tramp-perl-directory-files-and-attributes): Don't pass "$3". (tramp-vc-registered-read-file-names): Read input as here-document, otherwise the command could exceed maximum length of command line. (tramp-file-name-handler-alist): Add `file-selinux-context' and `set-file-selinux-context'. (tramp-debug-message): Add `tramp-compat-funcall' to ignored backtrace functions. (tramp-error-with-buffer): Don't show the connection buffer when we are in completion mode. (tramp-progress-reporter-update, tramp-remote-selinux-p) (tramp-handle-file-selinux-context) (tramp-handle-set-file-selinux-context, tramp-process-sentinel) (tramp-connectable-p, tramp-open-shell, tramp-get-remote-trash): New defuns. (with-progress-reporter): New defmacro. (tramp-debug-outline-regexp): New defconst. (top, tramp-rfn-eshadow-setup-minibuffer) (tramp-rfn-eshadow-update-overlay, tramp-handle-set-file-times) (tramp-handle-dired-compress-file, tramp-handle-shell-command) (tramp-completion-mode-p, tramp-check-for-regexp) (tramp-open-connection-setup-interactive-shell) (tramp-compute-multi-hops, tramp-read-passwd, tramp-clear-passwd) (tramp-time-diff, tramp-coding-system-change-eol-conversion) (tramp-set-process-query-on-exit-flag, tramp-unload-tramp): Use `tramp-compat-funcall'. (tramp-handle-make-symbolic-link): Flush file properties. (tramp-handle-load, tramp-handle-file-local-copy) (tramp-handle-insert-file-contents, tramp-handle-write-region) (tramp-handle-vc-registered, tramp-maybe-send-script) (tramp-find-shell): Use `with-progress-reporter'. (tramp-do-file-attributes-with-stat): Add space in format string, in order to work around a bug in pdksh. Reported by Gilles Pion <gpion@lfdj.com>. (tramp-handle-verify-visited-file-modtime): Do not send a command when the connection is not established. (tramp-handle-set-file-times): Simplify the check for utc. (tramp-handle-directory-files-and-attributes) (tramp-get-remote-path): Use `copy-tree'. (tramp-completion-handle-file-name-all-completions): Ensure, that non remote files are still checked. Oops. (tramp-handle-copy-file, tramp-do-copy-or-rename-file): Handle PRESERVE-SELINUX-CONTEXT. (tramp-do-copy-or-rename-file): Add progress reporter. (tramp-do-copy-or-rename-file-directly): Do not use `tramp-handle-file-remote-p'. (tramp-do-copy-or-rename-file-out-of-band): Use `tramp-compat-delete-directory'. (tramp-do-copy-or-rename-file-out-of-band) (tramp-compute-multi-hops, tramp-maybe-open-connection): Use `format-spec-make'. (tramp-handle-delete-file): Add TRASH arg. (tramp-handle-dired-uncache): Flush directory cache, not only file cache. (tramp-handle-expand-file-name) (tramp-completion-handle-file-name-all-completions) (tramp-completion-handle-file-name-completion): Use `tramp-connectable-p'. (tramp-handle-start-file-process): Set connection property "vec". Use it, in order to invalidate file caches. Check only for `remote-tty' process property. Implement tty setting. (Bug#4604, Bug#6360) (tramp-file-name-for-operation): Add `call-process-region' and `set-file-selinux-context'. (tramp-find-foreign-file-name-handler) (tramp-advice-make-auto-save-file-name) (tramp-set-auto-save-file-modes): Remove superfluous check for `stringp'. This is done inside `tramp-tramp-file-p'. (tramp-file-name-handler): Trace 'quit. Catch the error for some operations when we are in completion mode. This gives the user the chance to correct the file name in the minibuffer. (tramp-completion-mode-p): Use `non-essential'. (tramp-handle-file-name-all-completions): Backward/ XEmacs compatibility: Use `completion-ignore-case' if `read-file-name-completion-ignore-case' does not exist. (tramp-get-debug-buffer): Use `tramp-debug-outline-regexp'. (tramp-find-shell, tramp-open-connection-setup-interactive-shell): `tramp-open-shell'. (tramp-action-password): Hide password prompt before next run. (tramp-process-actions): Widen connection buffer for the trace. (tramp-open-connection-setup-interactive-shell): Set `remote-tty' process property. Trace stty settings if `tramp-verbose' >= 9. Apply workaround for IRIX64 bug. Move argument of last `tramp-send-command' where it belongs to. (tramp-maybe-open-connection): Use `async-args' and `gw-args' in front of `login-args'. (tramp-get-ls-command, tramp-get-ls-command-with-dired): Run tests on "/dev/null" instead of "/". (tramp-get-ls-command-with-dired): Make test for "--dired" stronger. (tramp-set-auto-save-file-modes): Adapt version check. (tramp-set-process-query-on-exit-flag): Fix wrong parentheses. (tramp-handle-process-file): Call the program in a subshell, in order to preserve working directory. (tramp-handle-shell-command): Don't use hard-wired "/bin/sh" but `tramp-remote-sh' from `tramp-methods'. (tramp-get-ls-command): Make test for "--color=never" stronger. (tramp-check-for-regexp): Use (forward-line 1). * net/trampver.el: Update release number. * net/tramp-gvfs.el (tramp-gvfs-handle-copy-file): Do not pass empty argument to gvfs-copy. * net/tramp-compat.el (tramp-compat-delete-file): Rewrite to handle new TRASH arg of `delete-file'. * net/tramp.el (tramp-handle-insert-directory): Don't use `forward-word', its default syntax could be changed. Implement compression for inline methods. * net/tramp.el (tramp-inline-compress-start-size): New defcustom. (tramp-copy-size-limit): Allow also nil. (tramp-inline-compress-commands): New defconst. (tramp-find-inline-compress, tramp-get-inline-compress) (tramp-get-inline-coding): New defuns. (tramp-get-remote-coding, tramp-get-local-coding): Remove, replaced by `tramp-get-inline-coding'. (tramp-handle-file-local-copy, tramp-handle-write-region) (tramp-method-out-of-band-p): Use `tramp-get-inline-coding'. Detect ssh 'ControlMaster' argument automatically in some cases. * net/tramp.el (tramp-detect-ssh-controlmaster): New defun. (tramp-default-method): Use it. * net/tramp.el (tramp-file-name-for-operation): Add file-selinux-context.
author Michael Albinus <michael.albinus@gmx.de>
date Thu, 26 Aug 2010 21:23:02 +0200
parents 1d1d5d9bd884
children 280c8ae2476d 376148b31b5e
line wrap: on
line source

;;; tramp-gw.el --- Tramp utility functions for HTTP tunnels and SOCKS gateways

;; Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.

;; Author: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes

;; This file is part of GNU Emacs.

;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; Access functions for HTTP tunnels and SOCKS gateways from Tramp.
;; SOCKS functionality is implemented by socks.el from the w3 package.
;; HTTP tunnels are partly implemented in socks.el and url-http.el;
;; both implementations are not complete.  Therefore, it is
;; implemented in this package.

;;; Code:

(require 'tramp)

;; Pacify byte-compiler
(eval-when-compile
  (require 'cl)
  (require 'custom))

;; Autoload the socks library.  It is used only when we access a SOCKS server.
(autoload 'socks-open-network-stream "socks")
(defvar socks-username (user-login-name))
(defvar socks-server (list "Default server" "socks" 1080 5))

;; Avoid byte-compiler warnings if the byte-compiler supports this.
;; Currently, XEmacs supports this.
(eval-when-compile
  (when (featurep 'xemacs)
      (byte-compiler-options (warnings (- unused-vars)))))

;; Define HTTP tunnel method ...
(defvar tramp-gw-tunnel-method "tunnel"
  "*Method to connect HTTP gateways.")

;; ... and port.
(defvar tramp-gw-default-tunnel-port 8080
  "*Default port for HTTP gateways.")

;; Define SOCKS method ...
(defvar tramp-gw-socks-method "socks"
  "*Method to connect SOCKS servers.")

;; ... and port.
(defvar tramp-gw-default-socks-port 1080
  "*Default port for SOCKS servers.")

;; Add a default for `tramp-default-user-alist'.  Default is the local user.
(add-to-list 'tramp-default-user-alist
	     `(,tramp-gw-tunnel-method nil ,(user-login-name)))
(add-to-list 'tramp-default-user-alist
	     `(,tramp-gw-socks-method nil ,(user-login-name)))

;; Internal file name functions and variables.

(defvar tramp-gw-vector nil
  "Keeps the remote host identification.  Needed for Tramp messages.")

(defvar tramp-gw-gw-vector nil
  "Current gateway identification vector.")

(defvar tramp-gw-gw-proc nil
  "Current gateway process.")

;; This variable keeps the listening process, in order to reuse it for
;; new processes.
(defvar tramp-gw-aux-proc nil
  "Process listening on local port, as mediation between SSH and the gateway.")

(defun tramp-gw-gw-proc-sentinel (proc event)
  "Delete auxiliary process when we are deleted."
  (unless (memq (process-status proc) '(run open))
    (tramp-message
     tramp-gw-vector 4 "Deleting auxiliary process `%s'" tramp-gw-gw-proc)
    (let* (tramp-verbose
	   (p (tramp-get-connection-property proc "process" nil)))
      (when (processp p) (delete-process p)))))

(defun tramp-gw-aux-proc-sentinel (proc event)
  "Activate the different filters for involved gateway and auxiliary processes."
  (when (memq (process-status proc) '(run open))
    ;; A new process has been spawned from `tramp-gw-aux-proc'.
    (tramp-message
     tramp-gw-vector 4
     "Opening auxiliary process `%s', speaking with process `%s'"
     proc tramp-gw-gw-proc)
    (tramp-set-process-query-on-exit-flag proc nil)
    ;; We don't want debug messages, because the corresponding debug
    ;; buffer might be undecided.
    (let (tramp-verbose)
      (tramp-set-connection-property tramp-gw-gw-proc "process" proc)
      (tramp-set-connection-property proc "process" tramp-gw-gw-proc))
    ;; Set the process-filter functions for both processes.
    (set-process-filter proc 'tramp-gw-process-filter)
    (set-process-filter tramp-gw-gw-proc 'tramp-gw-process-filter)
    ;; There might be already some output from the gateway process.
    (with-current-buffer (process-buffer tramp-gw-gw-proc)
      (unless (= (point-min) (point-max))
	(let ((s (buffer-string)))
	  (delete-region (point) (point-max))
	  (tramp-gw-process-filter tramp-gw-gw-proc s))))))

(defun tramp-gw-process-filter (proc string)
  (let (tramp-verbose)
    (process-send-string
     (tramp-get-connection-property proc "process" nil) string)))

(defun tramp-gw-open-connection (vec gw-vec target-vec)
  "Open a remote connection to VEC (see `tramp-file-name' structure).
Take GW-VEC as SOCKS or HTTP gateway, i.e. its method must be a
gateway method.  TARGET-VEC identifies where to connect to via
the gateway, it can be different from VEC when there are more
hops to be applied.

It returns a string like \"localhost#port\", which must be used
instead of the host name declared in TARGET-VEC."

  ;; Remember vectors for property retrieval.
  (setq tramp-gw-vector vec
	tramp-gw-gw-vector gw-vec)

  ;; Start listening auxiliary process.
  (unless (and (processp tramp-gw-aux-proc)
	       (memq (process-status tramp-gw-aux-proc) '(listen)))
    (let ((aux-vec
	   (vector "aux" (tramp-file-name-user gw-vec)
		   (tramp-file-name-host gw-vec) nil)))
      (setq tramp-gw-aux-proc
	    (make-network-process
	     :name (tramp-buffer-name aux-vec) :buffer nil :host 'local
	     :server t :noquery t :service t :coding 'binary))
      (set-process-sentinel tramp-gw-aux-proc 'tramp-gw-aux-proc-sentinel)
      (tramp-set-process-query-on-exit-flag tramp-gw-aux-proc nil)
      (tramp-message
       vec 4 "Opening auxiliary process `%s', listening on port %d"
       tramp-gw-aux-proc (process-contact tramp-gw-aux-proc :service))))

  (let* ((gw-method
	  (intern
	   (tramp-find-method
	    (tramp-file-name-method gw-vec)
	    (tramp-file-name-user gw-vec)
	    (tramp-file-name-host gw-vec))))
	 (socks-username
	  (tramp-find-user
	   (tramp-file-name-method gw-vec)
	   (tramp-file-name-user gw-vec)
	   (tramp-file-name-host gw-vec)))
	 ;; Declare the SOCKS server to be used.
	 (socks-server
	  (list "Tramp tempory socks server list"
		;; Host name.
		(tramp-file-name-real-host gw-vec)
		;; Port number.
		(or (tramp-file-name-port gw-vec)
		    (case gw-method
		      (tunnel tramp-gw-default-tunnel-port)
		      (socks tramp-gw-default-socks-port)))
		;; Type.  We support only http and socks5, NO socks4.
		;; 'http could be used when HTTP tunnel works in socks.el.
		5))
	 ;; The function to be called.
	 (socks-function
	  (case gw-method
	    (tunnel 'tramp-gw-open-network-stream)
	    (socks 'socks-open-network-stream)))
	 socks-noproxy)

    ;; Open SOCKS process.
    (setq tramp-gw-gw-proc
	  (funcall
	   socks-function
	   (tramp-buffer-name gw-vec)
	   (tramp-get-buffer gw-vec)
	   (tramp-file-name-real-host target-vec)
	   (tramp-file-name-port target-vec)))
    (set-process-sentinel tramp-gw-gw-proc 'tramp-gw-gw-proc-sentinel)
    (tramp-set-process-query-on-exit-flag tramp-gw-gw-proc nil)
    (tramp-message
     vec 4 "Opened %s process `%s'"
     (case gw-method ('tunnel "HTTP tunnel") ('socks "SOCKS"))
     tramp-gw-gw-proc)

    ;; Return the new host for gateway access.
    (format "localhost#%d" (process-contact tramp-gw-aux-proc :service))))

(defun tramp-gw-open-network-stream (name buffer host service)
  "Open stream to proxy server HOST:SERVICE.
Resulting process has name NAME and buffer BUFFER.  If
authentication is requested from proxy server, provide it."
  (let ((command (format (concat
			  "CONNECT %s:%d HTTP/1.1\r\n"
			  "Host: %s:%d\r\n"
			  "Connection: keep-alive\r\n"
			  "User-Agent: Tramp/%s\r\n")
			 host service host service tramp-version))
	(authentication "")
	(first t)
	found proc)

    (while (not found)
      ;; Clean up.
      (when (processp proc) (delete-process proc))
      (with-current-buffer buffer (erase-buffer))
      ;; Open network stream.
      (setq proc (open-network-stream
		  name buffer (nth 1 socks-server) (nth 2 socks-server)))
      (set-process-coding-system proc 'binary 'binary)
      (tramp-set-process-query-on-exit-flag proc nil)
      ;; Send CONNECT command.
      (process-send-string proc (format "%s%s\r\n" command authentication))
      (tramp-message
       tramp-gw-vector 6 "\n%s"
       (format
	"%s%s\r\n" command
	(replace-regexp-in-string ;; no password in trace!
	 "Basic [^\r\n]+" "Basic xxxxx" authentication t)))
      (with-current-buffer buffer
	;; Trap errors to be traced in the right trace buffer.  Often,
	;; proxies have a timeout of 60".  We wait 65" in order to
	;; receive an answer this case.
	(condition-case nil
	    (let (tramp-verbose)
	      (tramp-wait-for-regexp proc 65 "\r?\n\r?\n"))
	  (error nil))
	;; Check return code.
	(goto-char (point-min))
	(narrow-to-region
	 (point-min)
	 (or (search-forward-regexp "\r?\n\r?\n" nil t) (point-max)))
	(tramp-message tramp-gw-vector 6 "\n%s" (buffer-string))
	(goto-char (point-min))
	(search-forward-regexp "^HTTP/[1-9]\\.[0-9]" nil t)
	(case (condition-case nil (read (current-buffer)) (error))
	  ;; Connected.
	  (200 (setq found t))
	  ;; We need basic authentication.
	  (401 (setq authentication (tramp-gw-basic-authentication nil first)))
	  ;; Target host not found.
	  (404 (tramp-error-with-buffer
		(current-buffer) tramp-gw-vector 'file-error
		"Host %s not found." host))
	  ;; We need basic proxy authentication.
	  (407 (setq authentication (tramp-gw-basic-authentication t first)))
	  ;; Connection failed.
	  (503 (tramp-error-with-buffer
		(current-buffer) tramp-gw-vector 'file-error
		"Connection to %s:%d failed." host service))
	  ;; That doesn't work at all.
	  (t (tramp-error-with-buffer
	      (current-buffer) tramp-gw-vector 'file-error
	      "Access to HTTP server %s:%d failed."
	      (nth 1 socks-server) (nth 2 socks-server))))
	;; Remove HTTP headers.
	(delete-region (point-min) (point-max))
	(widen)
	(setq first nil)))
    ;; Return the process.
    proc))

(defun tramp-gw-basic-authentication (proxy pw-cache)
  "Return authentication header for CONNECT, based on server request.
PROXY is an indication whether we need a Proxy-Authorization header
or an Authorization header.  If PW-CACHE is non-nil, check for
password in password cache.  This is done for the first try only."

  ;; `tramp-current-*' must be set for `tramp-read-passwd'.
  (let ((tramp-current-method (tramp-file-name-method tramp-gw-gw-vector))
	(tramp-current-user (tramp-file-name-user tramp-gw-gw-vector))
	(tramp-current-host (tramp-file-name-host tramp-gw-gw-vector)))
    (unless pw-cache (tramp-clear-passwd tramp-gw-gw-vector))
    ;; We are already in the right buffer.
    (tramp-message
     tramp-gw-vector 5 "%s required"
     (if proxy "Proxy authentication" "Authentication"))
    ;; Search for request header.  We accept only basic authentication.
    (goto-char (point-min))
    (search-forward-regexp
     "^\\(Proxy\\|WWW\\)-Authenticate:\\s-*Basic\\s-+realm=")
    ;; Return authentication string.
    (format
     "%s: Basic %s\r\n"
     (if proxy "Proxy-Authorization" "Authorization")
     (base64-encode-string
      (format
       "%s:%s"
       socks-username
       (tramp-read-passwd
	nil
	(format
	 "Password for %s@[%s]: " socks-username (read (current-buffer)))))))))


(provide 'tramp-gw)

;;; TODO:

;; * Provide descriptive Commentary.
;; * Enable it for several gateway processes in parallel.

;; arch-tag: 277e3a81-fdee-40cf-9e6b-59626292a5e0
;;; tramp-gw.el ends here