Package x2go :: Module checkhosts
[frames] | no frames]

Source Code for Module x2go.checkhosts

  1  # -*- coding: utf-8 -*- 
  2   
  3  # Copyright (C) 2010-2011 by Mike Gabriel <mike.gabriel@das-netzwerkteam.de> 
  4  # 
  5  # Python X2go is free software; you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation; either version 3 of the License, or 
  8  # (at your option) any later version. 
  9  # 
 10  # Python X2go is distributed in the hope that it will be useful, 
 11  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 13  # GNU General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with this program; if not, write to the 
 17  # Free Software Foundation, Inc., 
 18  # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 
 19   
 20  """\ 
 21  Providing mechanisms to C{X2goControlSession*} backends for checking host validity. 
 22   
 23  """ 
 24  __NAME__ = 'x2gocheckhosts-pylib' 
 25   
 26  # modules 
 27  import paramiko 
 28  import binascii 
 29   
 30  # Python X2go modules 
 31  import sshproxy 
 32  import log 
 33  import x2go_exceptions 
 34   
35 -class X2goInteractiveAddPolicy(paramiko.MissingHostKeyPolicy):
36 """\ 37 Policy for making host key information available to Python X2go after a 38 Paramiko/SSH connect has been attempted. This class needs information 39 about the associated L{X2goSession} instance. 40 41 Once called, the L{missing_host_key} method of this class will try to call 42 L{X2goSession.HOOK_check_host_dialog()}. This hook method---if not re-defined 43 in your application---will then try to call the L{X2goClient.HOOK_check_host_dialog()}, 44 which then will return C{True} by default if not customized in your application. 45 46 To accept host key checks, make sure to either customize the 47 L{X2goClient.HOOK_check_host_dialog()} method or the L{X2goSession.HOOK_check_host_dialog()} 48 method and hook some interactive user dialog to either of them. 49 50 """
51 - def __init__(self, caller=None, session_instance=None):
52 """\ 53 @param caller: calling instance 54 @type caller: C{class} 55 @param session_instance: an X2go session instance 56 @type session_instance: L{X2goSession} instance 57 58 """ 59 self.caller = caller 60 self.session_instance = session_instance
61
62 - def missing_host_key(self, client, hostname, key):
63 """\ 64 Handle a missing host key situation. This method calls 65 66 Once called, the L{missing_host_key} method will try to call 67 L{X2goSession.HOOK_check_host_dialog()}. This hook method---if not re-defined 68 in your application---will then try to call the L{X2goClient.HOOK_check_host_dialog()}, 69 which then will return C{True} by default if not customized in your application. 70 71 To accept host key checks, make sure to either customize the 72 L{X2goClient.HOOK_check_host_dialog()} method or the L{X2goSession.HOOK_check_host_dialog()} 73 method and hook some interactive user dialog to either of them. 74 75 @param client: SSH client (C{X2goControlSession*}) instance 76 @type client: C{X2goControlSession*} instance 77 @param hostname: remote hostname 78 @type hostname: C{str} 79 @param key: host key to validate 80 @type key: Paramiko/SSH key instance 81 82 """ 83 self.client = client 84 self.hostname = hostname 85 if (self.hostname.find(']') == -1) and (self.hostname.find(':') == -1): 86 # if hostname is an IPv4 quadruple with standard SSH port... 87 self.hostname = '[%s]:22' % self.hostname 88 self.key = key 89 client._log(paramiko.common.DEBUG, 'Interactively Checking %s host key for %s: %s' % 90 (self.key.get_name(), self.hostname, binascii.hexlify(self.key.get_fingerprint()))) 91 if self.session_instance: 92 self.session_instance.logger('SSH host key verification for host %s with %s fingerprint ,,%s\'\' initiated. We are seeing this X2go server for the first time.' % (self.get_hostname(), self.get_key_name(), self.get_key_fingerprint_with_colons()), loglevel=log.loglevel_NOTICE) 93 _valid = self.session_instance.HOOK_check_host_dialog(self.get_hostname_name(), 94 port=self.get_hostname_port(), 95 fingerprint=self.get_key_fingerprint_with_colons(), 96 fingerprint_type=self.get_key_name(), 97 ) 98 if _valid: 99 paramiko.AutoAddPolicy().missing_host_key(client, hostname, key) 100 else: 101 if type(self.caller) in (sshproxy.X2goSSHProxy, ): 102 raise x2go_exceptions.X2goSSHProxyHostKeyException('Invalid host %s is not authorized for access. Add the host to Paramiko/SSH\'s known_hosts file.' % hostname) 103 else: 104 raise x2go_exceptions.X2goHostKeyException('Invalid host %s is not authorized for access. Add the host to Paramiko/SSH\'s known_hosts file.' % hostname) 105 else: 106 raise x2go_exceptions.SSHException('Policy has collected host key information on %s for further introspection' % hostname)
107
108 - def get_client(self):
109 """\ 110 Retrieve the Paramiko SSH/Client. 111 112 @return: the associated X2go control session instance. 113 @rtype: C{X2goControlSession*} instance 114 115 """ 116 return self.client
117
118 - def get_hostname(self):
119 """\ 120 Retrieve the server hostname:port expression of the server to be validated. 121 122 @return: hostname:port 123 @rtype: C{str} 124 125 """ 126 return self.hostname
127
128 - def get_hostname_name(self):
129 """\ 130 Retrieve the server hostname string of the server to be validated. 131 132 @return: hostname 133 @rtype: C{str} 134 135 """ 136 return self.get_hostname().split(':')[0].lstrip('[').rstrip(']')
137
138 - def get_hostname_port(self):
139 """\ 140 Retrieve the server port of the server to be validated. 141 142 @return: port 143 @rtype: C{str} 144 145 """ 146 return self.get_hostname().split(':')[1]
147
148 - def get_key(self):
149 """\ 150 Retrieve the host key of the server to be validated. 151 152 @return: host key 153 @rtype: Paramiko/SSH key instance 154 155 """ 156 return self.key
157
158 - def get_key_name(self):
159 """\ 160 Retrieve the host key name of the server to be validated. 161 162 @return: host key name (RSA, DSA, ...) 163 @rtype: C{str} 164 165 """ 166 return self.key.get_name().upper()
167
168 - def get_key_fingerprint(self):
169 """\ 170 Retrieve the host key fingerprint of the server to be validated. 171 172 @return: host key fingerprint 173 @rtype: C{str} 174 175 """ 176 return binascii.hexlify(self.key.get_fingerprint())
177
179 """\ 180 Retrieve the (colonized) host key fingerprint of the server 181 to be validated. 182 183 @return: host key fingerprint (with colons) 184 @rtype: C{str} 185 186 """ 187 _fingerprint = self.get_key_fingerprint() 188 _colon_fingerprint = '' 189 idx = 0 190 for char in _fingerprint: 191 idx += 1 192 _colon_fingerprint += char 193 if idx % 2 == 0: 194 _colon_fingerprint += ':' 195 return _colon_fingerprint.rstrip(':')
196 197
198 -def check_ssh_host_key(x2go_sshclient_instance, hostname, port=22):
199 """\ 200 Perform a Paramiko/SSH host key check by connecting to the host and 201 validating the results (i.e. by validating raised exceptions during the 202 connect process). 203 204 @param x2go_sshclient_instance: a Paramiko/SSH client instance to be used for testing host key validity. 205 @type x2go_sshclient_instance: C{X2goControlSession*} instance 206 @param hostname: hostname of server to validate 207 @type hostname: C{str} 208 @param port: port of server to validate 209 @type port: C{int} 210 @return: returns a tuple with the following components (<host_ok>, <hostname>, <port>, <fingerprint>, <fingerprint_type>) 211 @rtype: C{tuple} 212 213 """ 214 _hostname = hostname 215 _port = port 216 _fingerprint = 'NO-FINGERPRINT' 217 _fingerprint_type = 'SOME-KEY-TYPE' 218 219 _check_policy = X2goInteractiveAddPolicy() 220 x2go_sshclient_instance.set_missing_host_key_policy(_check_policy) 221 222 host_ok = False 223 try: 224 paramiko.SSHClient.connect(x2go_sshclient_instance, hostname=hostname, port=port, username='foo', password='bar') 225 except x2go_exceptions.AuthenticationException: 226 host_ok = True 227 x2go_sshclient_instance.logger('SSH host key verification for host [%s]:%s succeeded. Host is already known to the client\'s Paramiko/SSH sub-system.' % (_hostname, _port), loglevel=log.loglevel_NOTICE) 228 except x2go_exceptions.SSHException, e: 229 msg = str(e) 230 if msg.startswith('Policy has collected host key information on '): 231 _hostname = _check_policy.get_hostname().split(':')[0].lstrip('[').rstrip(']') 232 _port = _check_policy.get_hostname().split(':')[1] 233 _fingerprint = _check_policy.get_key_fingerprint_with_colons() 234 _fingerprint_type = _check_policy.get_key_name() 235 else: 236 raise(e) 237 x2go_sshclient_instance.set_missing_host_key_policy(paramiko.RejectPolicy()) 238 except: 239 # let any other error be handled by subsequent algorithms 240 pass 241 242 return (host_ok, _hostname, _port, _fingerprint, _fingerprint_type)
243