Revision 216bb34c ncclient/transport/ssh.py

b/ncclient/transport/ssh.py
34 34
    """An `unknown host callback` returns :const:`True` if it finds the key
35 35
    acceptable, and :const:`False` if not.
36 36

  
37
    :arg host: the hostname/address which needs to be verified
37
    This default callback always returns :const:`False`, which would lead to
38
    :meth:`connect` raising a :exc:`SSHUnknownHost` exception.
38 39

  
39
    :arg key: a hex string representing the host key fingerprint
40
    Supply another valid callback if you need to verify the host key
41
    programatically.
42

  
43
    :arg host: the host for whom key needs to be verified
44
    :type host: string
40 45

  
41
    :returns: this default callback always returns :const:`False`
46
    :arg key: a hex string representing the host key fingerprint
47
    :type key: string
42 48
    """
43 49
    return False
44 50

  
......
50 56
    def __init__(self, capabilities):
51 57
        Session.__init__(self, capabilities)
52 58
        self._host_keys = paramiko.HostKeys()
53
        self._system_host_keys = paramiko.HostKeys()
54 59
        self._transport = None
55 60
        self._connected = False
56 61
        self._channel = None
......
103 108
        self._parsing_state = expect
104 109
        self._parsing_pos = self._buffer.tell()
105 110

  
106
    def load_system_host_keys(self, filename=None):
111
    def load_known_hosts(self, filename=None):
112
        """Load host keys from a :file:`known_hosts`-style file. Can be called multiple
113
        times.
114

  
115
        If *filename* is not specified, looks in the default locations i.e.
116
        :file:`~/.ssh/known_hosts` and :file:`~/ssh/known_hosts` for Windows.
117
        """
107 118
        if filename is None:
108 119
            filename = os.path.expanduser('~/.ssh/known_hosts')
109 120
            try:
110
                self._system_host_keys.load(filename)
121
                self._host_keys.load(filename)
111 122
            except IOError:
112 123
                # for windows
113 124
                filename = os.path.expanduser('~/ssh/known_hosts')
114 125
                try:
115
                    self._system_host_keys.load(filename)
126
                    self._host_keys.load(filename)
116 127
                except IOError:
117 128
                    pass
118
            return
119
        self._system_host_keys.load(filename)
120

  
121
    def load_host_keys(self, filename):
122
        self._host_keys.load(filename)
123

  
124
    def add_host_key(self, key):
125
        self._host_keys.add(key)
126

  
127
    def save_host_keys(self, filename):
128
        f = open(filename, 'w')
129
        for host, keys in self._host_keys.iteritems():
130
            for keytype, key in keys.iteritems():
131
                f.write('%s %s %s\n' % (host, keytype, key.get_base64()))
132
        f.close()
129
        else:
130
            self._host_keys.load(filename)
133 131

  
134 132
    def close(self):
135 133
        self._expecting_close = True
......
144 142
        """Connect via SSH and initialize the NETCONF session. First attempts
145 143
        the publickey authentication method and then password authentication.
146 144

  
147
        To disable publickey authentication, call with *allow_agent* and
148
        *look_for_keys* as :const:`False`
145
        To disable attemting publickey authentication altogether, call with
146
        *allow_agent* and *look_for_keys* as :const:`False`. This may be needed
147
        for Cisco devices which immediately disconnect on an incorrect
148
        authentication attempt.
149 149

  
150 150
        :arg host: the hostname or IP address to connect to
151
        :type host: `string`
151 152

  
152 153
        :arg port: by default 830, but some devices use the default SSH port of 22 so this may need to be specified
154
        :type port: `int`
153 155

  
154 156
        :arg timeout: an optional timeout for the TCP handshake
157
        :type timeout: `int`
155 158

  
156
        :arg unknown_host_cb: called when a host key is not known. See :func:`unknown_host_cb` for details on signature
159
        :arg unknown_host_cb: called when a host key is not recognized
160
        :type unknown_host_cb: see :meth:`signature <ssh.default_unknown_host_cb>`
157 161

  
158 162
        :arg username: the username to use for SSH authentication
163
        :type username: `string`
159 164

  
160
        :arg password: the password used if using password authentication, or the passphrase to use in order to unlock keys that require it
165
        :arg password: the password used if using password authentication, or the passphrase to use for unlocking keys that require it
166
        :type password: `string`
161 167

  
162 168
        :arg key_filename: a filename where a the private key to be used can be found
169
        :type key_filename: `string`
163 170

  
164 171
        :arg allow_agent: enables querying SSH agent (if found) for keys
172
        :type allow_agent: `bool`
165 173

  
166 174
        :arg look_for_keys: enables looking in the usual locations for ssh keys (e.g. :file:`~/.ssh/id_*`)
175
        :type look_for_keys: `bool`
167 176
        """
168 177

  
169 178
        assert(username is not None)
......
189 198

  
190 199
        # host key verification
191 200
        server_key = t.get_remote_server_key()
192
        known_host = self._host_keys.check(host, server_key) or \
193
                        self._system_host_keys.check(host, server_key)
201
        known_host = self._host_keys.check(host, server_key)
202

  
203
        fingerprint = hexlify(server_key.get_fingerprint())
194 204

  
195
        fp = hexlify(server_key.get_fingerprint())
196
        if not known_host and not unknown_host_cb(host, fp):
197
            raise SSHUnknownHostError(host, fp)
205
        if not known_host and not unknown_host_cb(host, fingerprint):
206
            raise SSHUnknownHostError(host, fingerprint)
198 207

  
199 208
        if key_filename is None:
200 209
            key_filenames = []
......
318 327

  
319 328
    @property
320 329
    def transport(self):
321
        """The underlying `paramiko.Transport
330
        """Underlying `paramiko.Transport
322 331
        <http://www.lag.net/paramiko/docs/paramiko.Transport-class.html>`_
323 332
        object. This makes it possible to call methods like set_keepalive on it.
324 333
        """

Also available in: Unified diff