This file is indexed.

/usr/share/pyshared/x2go/sshproxy.py is in python-x2go 0.1.1.8-0ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# -*- coding: utf-8 -*-

# Copyright (C) 2010-2011 by Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
#
# Python X2go 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.
#
# Python X2go 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 this program; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

"""\
L{X2goSSHProxy} class - providing a forwarding tunnel for connecting to servers behind firewalls.

"""
__NAME__ = 'x2gosshproxy-pylib'

# modules
import gevent
import os
import copy
import paramiko
import threading
import socket

import string
import random

# Python X2go modules
import x2go.forward as forward
import x2go.checkhosts as checkhosts
import x2go.log as log
import x2go.utils as utils
from x2go.x2go_exceptions import *

from x2go.defaults import CURRENT_LOCAL_USER as _CURRENT_LOCAL_USER
from x2go.defaults import LOCAL_HOME as _LOCAL_HOME
from x2go.defaults import X2GO_SSH_ROOTDIR as _X2GO_SSH_ROOTDIR

from monkey_patch_paramiko import monkey_patch_paramiko
monkey_patch_paramiko()

class X2goSSHProxy(paramiko.SSHClient, threading.Thread):
    """\
    X2goSSHProxy can be used to proxy X2go connections through a firewall via SSH.

    """
    fw_tunnel = None

    def __init__(self, hostname=None, port=22, username=None, password=None, key_filename=None,
                 local_host='localhost', local_port=22022, remote_host='localhost', remote_port=22,
                 known_hosts=None, add_to_known_hosts=False, pkey=None,
                 sshproxy_host=None, sshproxy_port=22, sshproxy_user=None, 
                 sshproxy_password=None, sshproxy_key_filename=None, sshproxy_pkey=None,
                 sshproxy_tunnel=None,
                 ssh_rootdir=os.path.join(_LOCAL_HOME, _X2GO_SSH_ROOTDIR), 
                 session_instance=None,
                 logger=None, loglevel=log.loglevel_DEFAULT, ):
        """\
        Initialize an X2goSSHProxy instance. Use an instance of this class to tunnel X2go requests through
        a proxying SSH server (i.e. to subLANs that are separated by firewalls or to private IP subLANs that
        are NATted behind routers).

        @param username: login user name to be used on the SSH proxy host
        @type username: C{str}
        @param password: user's password on the SSH proxy host
        @type password: C{str}
        @param key_filename: name of a SSH private key file
        @type key_filename: C{str}
        @param pkey: a private DSA/RSA key object (as provided by Paramiko/SSH)
        @type pkey: C{RSA/DSA key instance}
        @param local_host: bind SSH tunnel to the C{local_host} IP socket address (default: localhost)
        @type local_host: C{str}
        @param local_port: IP socket port to bind the SSH tunnel to (default; 22022)
        @type local_port: C{int}
        @param remote_host: remote endpoint of the SSH proxying/forwarding tunnel (default: localhost)
        @type remote_host: C{str}
        @param remote_port: remote endpoint's IP socket port for listening SSH daemon (default: 22)
        @type remote_port: C{int}
        @param known_hosts: full path to a custom C{known_hosts} file
        @type known_hosts: C{str}
        @param add_to_known_hosts: automatically add host keys of unknown SSH hosts to the C{known_hosts} file
        @type add_to_known_hosts: C{bool}
        @param hostname: alias for C{local_host}
        @type hostname: C{str}
        @param port: alias for C{local_port}
        @type port: C{int}
        @param sshproxy_host: alias for C{remote_host}
        @type sshproxy_host: C{str}
        @param sshproxy_port: alias for C{remote_port}
        @type sshproxy_port: C{int}
        @param sshproxy_user: alias for C{username}
        @type sshproxy_user: C{str}
        @param sshproxy_password: alias for C{password}
        @type sshproxy_password: C{str}
        @param sshproxy_key_filename: alias for C{key_filename}
        @type sshproxy_key_filename: C{str}
        @param sshproxy_pkey: alias for C{pkey}
        @type sshproxy_pkey: C{RSA/DSA key instance} (Paramiko)

        @param sshproxy_tunnel: a string of the format <local_host>:<local_port>:<remote_host>:<remote_port> 
            which will override---if used---the options: C{local_host}, C{local_port}, C{remote_host} and C{remote_port}
        @type sshproxy_tunnel: C{str}

        @param ssh_rootdir: local user's SSH base directory (default: ~/.ssh)
        @type ssh_rootdir: C{str}
        @param session_instance: the L{X2goSession} instance that builds up this SSH proxying tunnel
        @type session_instance: L{X2goSession} instance
        @param logger: you can pass an L{X2goLogger} object to the
            L{X2goSSHProxy} constructor
        @type logger: L{X2goLogger} instance
        @param loglevel: if no L{X2goLogger} object has been supplied a new one will be
            constructed with the given loglevel
        @type loglevel: int

        """
        if logger is None:
            self.logger = log.X2goLogger(loglevel=loglevel)
        else:
            self.logger = copy.deepcopy(logger)
        self.logger.tag = __NAME__

        self.hostname, self.port, self.username = hostname, port, username

        # translate between X2goSession options and paramiko.SSHCLient.connect() options
        if sshproxy_host:
            if sshproxy_host.find(':'):
                self.hostname = sshproxy_host.split(':')[0]
                try: self.port = int(sshproxy_host.split(':')[1])
                except IndexError: pass
            else:
                self.hostname = sshproxy_host

        if sshproxy_user: self.username = sshproxy_user
        if sshproxy_password: password = sshproxy_password
        if sshproxy_key_filename: key_filename = sshproxy_key_filename
        if sshproxy_pkey: pkey = sshproxy_pkey
        if sshproxy_tunnel:
            self.local_host, self.local_port, self.remote_host, self.remote_port = sshproxy_tunnel.split(':')
            self.local_port = int(self.local_port)
            self.remote_port = int(self.remote_port)
        else:
            self.local_host = local_host
            self.local_port = int(local_port)
            self.remote_host = remote_host
            self.remote_port = int(remote_port)

        # allow more trailing whitespace tolerance in hostnames
        self.hostname = self.hostname.strip()
        self.local_host = self.local_host.strip()
        self.remote_host = self.remote_host.strip()

        # enforce IPv4 for localhost addresses!!!
        _hostname = self.hostname
        if _hostname in ('localhost', 'localhost.localdomain'):
            _hostname = '127.0.0.1'
        if self.local_host in ('localhost', 'localhost.localdomain'):
            self.local_host = '127.0.0.1'
        if self.remote_host in ('localhost', 'localhost.localdomain'):
            self.remote_host = '127.0.0.1'

        if username is None:
            username = _CURRENT_LOCAL_USER

        self._keepalive = True

        self.ssh_rootdir = ssh_rootdir
        paramiko.SSHClient.__init__(self)

        self.known_hosts = known_hosts
        if self.known_hosts:
            utils.touch_file(self.known_hosts)
            self.load_host_keys(self.known_hosts)

        if not add_to_known_hosts and session_instance:
            self.set_missing_host_key_policy(checkhosts.X2goInteractiveAddPolicy(caller=self, session_instance=session_instance))

        if add_to_known_hosts:
            self.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        try:
            if (key_filename and os.path.exists(os.path.normpath(key_filename))) or pkey:
                try:
                    self.connect(_hostname, port=self.port, 
                                 username=self.username, 
                                 key_filename=key_filename,
                                 pkey=pkey,
                                 look_for_keys=False,
                                 allow_agent=False,
                                )
                except AuthenticationException, e:
                    self.close()
                    raise X2goSSHProxyAuthenticationException('pubkey auth mechanisms both failed')
                except:
                    self.close()
                    raise

            # if there is not private key, we will use the given password, if any
            else:
                # create a random password if password is empty to trigger host key validity check
                if not password:
                    password = "".join([random.choice(string.letters+string.digits) for x in range(1, 20)])
                try:
                    self.connect(_hostname, port=self.port,
                                 username=self.username,
                                 password=password,
                                 look_for_keys=False,
                                 allow_agent=False,
                                )
                except AuthenticationException:
                    self.close()
                    raise X2goSSHProxyAuthenticationException('interactive auth mechanisms failed')
                except:
                    self.close()
                    raise

        except paramiko.SSHException, e:
            self.close()
            raise X2goSSHProxyException(str(e))
        except:
            self.close()
            raise

        self.set_missing_host_key_policy(paramiko.RejectPolicy())
        threading.Thread.__init__(self)
        self.daemon = True

    def check_host(self):
        """\
        Wraps around a Paramiko/SSH host key check.

        """

        # hostname rewrite for localhost, force to IPv4
        _hostname = self.hostname

        # force into IPv4 for localhost connections
        if _hostname in ('localhost', 'localhost.localdomain'):
            _hostname = '127.0.0.1'

        _valid = False
        (_valid, _hostname, _port, _fingerprint, _fingerprint_type) = checkhosts.check_ssh_host_key(self, _hostname, port=self.port)
        if not _valid and self.session_instance:
            _valid = self.session_instance.HOOK_check_host_dialog(_hostname, _port, fingerprint=_fingerprint, fingerprint_type=_fingerprint_type)
        return _valid

    def run(self):
        """\
        Start the SSH proxying tunnel...

        """
        if self.get_transport() is not None and self.get_transport().is_authenticated():
            self.local_port = utils.detect_unused_port(bind_address=self.local_host, preferred_port=self.local_port)
            self.fw_tunnel = forward.start_forward_tunnel(local_host=self.local_host,
                                                          local_port=self.local_port,
                                                          remote_host=self.remote_host,
                                                          remote_port=self.remote_port,
                                                          ssh_transport=self.get_transport(),
                                                          logger=self.logger, )
            self.logger('SSH proxy tunnel via [%s]:%s has been set up' % (self.hostname, self.port), loglevel=log.loglevel_NOTICE)
            self.logger('SSH proxy tunnel startpoint is [%s]:%s, endpoint is [%s]:%s' % (self.local_host, self.local_port, self.remote_host, self.remote_port), loglevel=log.loglevel_NOTICE)

            while self._keepalive:
                gevent.sleep(.1)

        else:
            raise X2goSSHProxyException('SSH proxy connection could not retrieve an SSH transport')

    def get_local_proxy_port(self):
        """\
        Retrieve the local IP socket port this SSH proxying tunnel is (about to) bind/bound to.

        @return: local IP socket port
        @rtype: C{int}
        """
        return self.local_port

    def stop_thread(self):
        """\
        Tear down the SSH proxying tunnel.

        """
        if self.fw_tunnel is not None and self.fw_tunnel.is_active:
            self.logger('taking down SSH proxy tunnel via [%s]:%s' % (self.hostname, self.port), loglevel=log.loglevel_NOTICE)
        try: forward.stop_forward_tunnel(self.fw_tunnel)
        except: pass
        self.fw_tunnel = None
        self._keepalive = False
        if self.get_transport() is not None:
            self.logger('closing SSH proxy connection to [%s]:%s' % (self.hostname, self.port), loglevel=log.loglevel_NOTICE)
        self.close()
        self.password = self.sshproxy_password = None

    def __del__(self):
        """\
        Class desctructor.

        """
        self.stop_thread()