[X2Go-Commits] python-x2go.git - build-main (branch) updated: 0.4.0.8-17-g5b8164d
X2Go dev team
git-admin at x2go.org
Wed Jan 8 15:15:17 CET 2014
The branch, build-main has been updated
via 5b8164de3596bd79e89de18e574252b2730b0916 (commit)
from e92d6b6be58800bc69d030d87a5ae9637dfe3e0b (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
-----------------------------------------------------------------------
Summary of changes:
debian/changelog | 2 ++
x2go/backends/control/_stdout.py | 44 ++++++++++++++++++++++++++++++++++----
x2go/client.py | 12 +++++++++++
x2go/session.py | 24 +++++++++++++++++++--
x2go/x2go_exceptions.py | 1 +
5 files changed, 77 insertions(+), 6 deletions(-)
The diff of changes is:
diff --git a/debian/changelog b/debian/changelog
index eb4b587..cee5b48 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -19,6 +19,8 @@ python-x2go (0.4.0.9-0~x2go1) UNRELEASED; urgency=low
- Implement two-factor authentication.
- Compat fix in _paramiko monkey patch module to also work with early Paramiko
versions.
+ - Handle echoing ~/.*shrc files gracefully via SSH client connections. Do not allow
+ data injections via ~/.*shrc files. (Fixes: #335).
[ Orion Poplawski ]
* debian/control:
diff --git a/x2go/backends/control/_stdout.py b/x2go/backends/control/_stdout.py
index 91e0a17..da9f9b7 100644
--- a/x2go/backends/control/_stdout.py
+++ b/x2go/backends/control/_stdout.py
@@ -38,6 +38,7 @@ import locale
import threading
import cStringIO
import base64
+import uuid
from gevent import socket
@@ -272,6 +273,13 @@ class X2GoControlSessionSTDOUT(paramiko.SSHClient):
"""
self.disconnect()
+ def test_sftpclient(self):
+ ssh_transport = self.get_transport()
+ try:
+ self.sftp_client = paramiko.SFTPClient.from_transport(ssh_transport)
+ except paramiko.SFTPError:
+ raise x2go_exceptions.X2GoSFTPClientException('failed to initialize SFTP channel')
+
def _x2go_sftp_put(self, local_path, remote_path):
"""
Put a local file on the remote server via sFTP.
@@ -290,7 +298,10 @@ class X2GoControlSessionSTDOUT(paramiko.SSHClient):
self._transport_lock.acquire()
if ssh_transport and ssh_transport.is_authenticated():
self.logger('sFTP-put: %s -> %s:%s' % (os.path.normpath(local_path), self.remote_peername(), remote_path), loglevel=log.loglevel_DEBUG)
- self.sftp_client = paramiko.SFTPClient.from_transport(ssh_transport)
+ try:
+ self.sftp_client = paramiko.SFTPClient.from_transport(ssh_transport)
+ except paramiko.SFTPError:
+ raise x2go_exceptions.X2GoSFTPClientException('failed to initialize SFTP channel')
try:
self.sftp_client.put(os.path.normpath(local_path), remote_path)
except (x2go_exceptions.SSHException, socket.error, IOError):
@@ -319,7 +330,10 @@ class X2GoControlSessionSTDOUT(paramiko.SSHClient):
self._transport_lock.acquire()
if ssh_transport and ssh_transport.is_authenticated():
self.logger('sFTP-write: opening remote file %s on host %s for writing' % (remote_path, self.remote_peername()), loglevel=log.loglevel_DEBUG)
- self.sftp_client = paramiko.SFTPClient.from_transport(ssh_transport)
+ try:
+ self.sftp_client = paramiko.SFTPClient.from_transport(ssh_transport)
+ except paramiko.SFTPError:
+ raise x2go_exceptions.X2GoSFTPClientException('failed to initialize SFTP channel')
try:
remote_fileobj = self.sftp_client.open(remote_path, 'w')
self.logger('sFTP-write: writing content: %s' % content, loglevel=log.loglevel_DEBUG_SFTPXFER)
@@ -349,7 +363,10 @@ class X2GoControlSessionSTDOUT(paramiko.SSHClient):
self._transport_lock.acquire()
if ssh_transport and ssh_transport.is_authenticated():
self.logger('sFTP-write: removing remote file %s on host %s' % (remote_path, self.remote_peername()), loglevel=log.loglevel_DEBUG)
- self.sftp_client = paramiko.SFTPClient.from_transport(ssh_transport)
+ try:
+ self.sftp_client = paramiko.SFTPClient.from_transport(ssh_transport)
+ except paramiko.SFTPError:
+ raise x2go_exceptions.X2GoSFTPClientException('failed to initialize SFTP channel')
try:
self.sftp_client.remove(remote_path)
except (x2go_exceptions.SSHException, socket.error, IOError):
@@ -387,7 +404,8 @@ class X2GoControlSessionSTDOUT(paramiko.SSHClient):
else:
cmd = cmd_line
- cmd = 'sh -c \"%s\"' % cmd
+ cmd_uuid = str(uuid.uuid1())
+ cmd = 'echo X2GODATABEGIN:%s; sh -c \"%s\"; echo X2GODATAEND:%s' % (cmd_uuid, cmd, cmd_uuid)
if self.session_died:
self.logger("control session seams to be dead, not executing command ,,%s'' on X2Go server %s" % (_rerewrite_blanks(cmd), self.profile_name,), loglevel=loglevel)
@@ -447,6 +465,24 @@ class X2GoControlSessionSTDOUT(paramiko.SSHClient):
raise x2go_exceptions.X2GoControlSessionException('the X2Go control session is not connected')
self._transport_lock.release()
+
+ # sanitized X2Go relevant data, protect against data injection via .bashrc files
+ (_stdin, _stdout, _stderr) = _retval
+ raw_stdout = _stdout.read()
+
+ sanitized_stdout = ''
+ is_x2go_data = False
+ for line in raw_stdout.split('\n'):
+ if line.startswith('X2GODATABEGIN:'+cmd_uuid):
+ is_x2go_data = True
+ continue
+ if not is_x2go_data: continue
+ if line.startswith('X2GODATAEND:'+cmd_uuid): break
+ sanitized_stdout += line + "\n"
+
+ _stdout_new = cStringIO.StringIO(sanitized_stdout)
+
+ _retval = (_stdin, _stdout_new, _stderr)
return _retval
@property
diff --git a/x2go/client.py b/x2go/client.py
index 21731eb..80bb160 100644
--- a/x2go/client.py
+++ b/x2go/client.py
@@ -501,6 +501,18 @@ class X2GoClient(object):
"""
self.logger('HOOK_on_control_session_death: the control session of profile %s has died unexpectedly' % profile_name, loglevel=log.loglevel_WARN)
+
+ def HOOK_on_failing_SFTP_client(self, profile_name, session_name):
+ """\
+ HOOK method: called SFTP client support is unavailable for the session.
+
+ @param profile_name: profile name of the session that experiences failing SFTP client support
+ @type profile_name: C{str}
+ @param session_name: name of session experiencing failing SFTP client support
+ @type session_name: C{str}
+
+ """
+ self.logger('HOOK_on_failing_SFTP_client: new session for profile %s will lack SFTP client support. Check your server setup. Avoid echoing ~/.bashrc files on server.' % profile_name, loglevel=log.loglevel_ERROR)
def HOOK_pulseaudio_not_supported_in_RDPsession(self):
"""HOOK method: called if trying to run the Pulseaudio daemon within an RDP session, which is not supported by Pulseaudio."""
diff --git a/x2go/session.py b/x2go/session.py
index 479cdff..0febe0d 100644
--- a/x2go/session.py
+++ b/x2go/session.py
@@ -448,6 +448,16 @@ class X2GoSession(object):
else:
self.logger('HOOK_on_control_session_death: the control session of profile %s has died unexpectedly' % self.profile_name, loglevel=log.loglevel_WARN)
+ def HOOK_on_failing_SFTP_client(self):
+ """\
+ HOOK method: called SFTP client support is unavailable for the session.
+
+ """
+ if self.client_instance:
+ self.client_instance.HOOK_on_failing_SFTP_client(profile_name=self.profile_name)
+ else:
+ self.logger('HOOK_on_failing_SFTP_client: new session for profile: %s will lack SFTP client support. Check your server setup. Avoid echoing ~/.bashrc files on server.' % self.profile_name, loglevel=log.loglevel_ERROR)
+
def HOOK_auto_connect(self):
"""\
HOOK method: called if the session demands to auto connect.
@@ -1815,6 +1825,15 @@ class X2GoSession(object):
# we do not have a possibility to really check if SSH has released port forwarding channels or
# sockets, thus we plainly have to wait a while
+ try:
+ _control.test_sftpclient()
+ except x2go_exceptions.X2GoSFTPClientException:
+ self.HOOK_on_failing_SFTP_client()
+ self.terminal_session = None
+ self._progress_status = -1
+ progress_event.set()
+ return False
+
if self.is_running():
try:
@@ -1834,6 +1853,7 @@ class X2GoSession(object):
except x2go_exceptions.X2GoSessionException:
pass
+
self._progress_status = 20
progress_event.set()
@@ -1911,7 +1931,7 @@ class X2GoSession(object):
try:
self.has_terminal_session() and not self.faulty and self.terminal_session.start_printing()
self.has_terminal_session() and not self.faulty and self.session_environment.update({'X2GO_SPOOLDIR': self.terminal_session.get_printing_spooldir(), })
- except x2go_exceptions.X2GoUserException, e:
+ except (x2go_exceptions.X2GoUserException, x2go_exceptions.X2GoSFTPClientException), e:
self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
self.HOOK_printing_not_available()
self._SUPPORTED_PRINTING = False
@@ -1923,7 +1943,7 @@ class X2GoSession(object):
try:
self.has_terminal_session() and not self.faulty and self.terminal_session.start_mimebox(mimebox_extensions=self.mimebox_extensions, mimebox_action=self.mimebox_action)
self.has_terminal_session() and self.session_environment.update({'X2GO_MIMEBOX': self.terminal_session.get_mimebox_spooldir(), })
- except x2go_exceptions.X2GoUserException, e:
+ except (x2go_exceptions.X2GoUserException, x2go_exceptions.X2GoSFTPClientException), e:
self.logger('%s' % str(e), loglevel=log.loglevel_WARN)
self.HOOK_mimebox_not_available()
self._SUPPORTED_MIMEBOX = False
diff --git a/x2go/x2go_exceptions.py b/x2go/x2go_exceptions.py
index 70a5e8c..30985b2 100644
--- a/x2go/x2go_exceptions.py
+++ b/x2go/x2go_exceptions.py
@@ -45,6 +45,7 @@ class X2GoClientPrintingException(_X2GoException): pass
class X2GoClientSettingsException(_X2GoException): pass
class X2GoSessionException(_X2GoException): pass
class X2GoControlSessionException(_X2GoException): pass
+class X2GoSFTPClientException(_X2GoException): pass
class X2GoRemoteHomeException(_X2GoException): pass
class X2GoHostKeyException(_X2GoException): pass
class X2GoSSHProxyPasswordRequiredException(_X2GoException): pass
hooks/post-receive
--
python-x2go.git (Python X2Go Client API)
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "python-x2go.git" (Python X2Go Client API).
More information about the x2go-commits
mailing list