Revision 19e7c7f6 ncclient/transport/ssh.py
b/ncclient/transport/ssh.py | ||
---|---|---|
32 | 32 |
TICK = 0.1 |
33 | 33 |
|
34 | 34 |
def default_unknown_host_cb(host, fingerprint): |
35 |
"""An `unknown host callback` returns :const:`True` if it finds the key acceptable, and |
|
36 |
:const:`False` if not. |
|
35 |
"""An unknown host callback returns `True` if it finds the key acceptable, and `False` if not. |
|
37 | 36 |
|
38 |
This default callback always returns :const:`False`, which would lead to :meth:`connect` raising |
|
39 |
a :exc:`SSHUnknownHost` exception. |
|
37 |
This default callback always returns `False`, which would lead to :meth:`connect` raising a :exc:`SSHUnknownHost` exception. |
|
40 | 38 |
|
41 | 39 |
Supply another valid callback if you need to verify the host key programatically. |
42 | 40 |
|
43 |
:arg host: the hostname that needs to be verified |
|
44 |
:type host: `string` |
|
41 |
*host* is the hostname that needs to be verified |
|
45 | 42 |
|
46 |
:arg fingerprint: a hex string representing the host key fingerprint, colon-delimited e.g. *4b:69:6c:72:6f:79:20:77:61:73:20:68:65:72:65:21* |
|
47 |
:type fingerprint: `string` |
|
43 |
*fingerprint* is a hex string representing the host key fingerprint, colon-delimited e.g. `"4b:69:6c:72:6f:79:20:77:61:73:20:68:65:72:65:21"` |
|
48 | 44 |
""" |
49 | 45 |
return False |
50 | 46 |
|
... | ... | |
70 | 66 |
self._parsing_pos = 0 |
71 | 67 |
|
72 | 68 |
def _parse(self): |
73 |
"""Messages ae delimited by MSG_DELIM. The buffer could have grown by a |
|
74 |
maximum of BUF_SIZE bytes everytime this method is called. Retains state |
|
75 |
across method calls and if a byte has been read it will not be |
|
76 |
considered again. |
|
77 |
""" |
|
69 |
"Messages ae delimited by MSG_DELIM. The buffer could have grown by a maximum of BUF_SIZE bytes everytime this method is called. Retains state across method calls and if a byte has been read it will not be considered again." |
|
78 | 70 |
delim = MSG_DELIM |
79 | 71 |
n = len(delim) - 1 |
80 | 72 |
expect = self._parsing_state |
... | ... | |
115 | 107 |
self._parsing_pos = self._buffer.tell() |
116 | 108 |
|
117 | 109 |
def load_known_hosts(self, filename=None): |
118 |
"""Load host keys from a :file:`known_hosts`-style file. Can be called multiple times. |
|
110 |
"""Load host keys from an openssh :file:`known_hosts`-style file. Can be called multiple times.
|
|
119 | 111 |
|
120 |
If *filename* is not specified, looks in the default locations i.e. |
|
121 |
:file:`~/.ssh/known_hosts` and :file:`~/ssh/known_hosts` for Windows. |
|
112 |
If *filename* is not specified, looks in the default locations i.e. :file:`~/.ssh/known_hosts` and :file:`~/ssh/known_hosts` for Windows. |
|
122 | 113 |
""" |
123 | 114 |
if filename is None: |
124 | 115 |
filename = os.path.expanduser('~/.ssh/known_hosts') |
... | ... | |
139 | 130 |
self._transport.close() |
140 | 131 |
self._connected = False |
141 | 132 |
|
142 |
def connect(self, host, port=830, timeout=None, |
|
143 |
unknown_host_cb=default_unknown_host_cb, |
|
144 |
username=None, password=None, |
|
145 |
key_filename=None, allow_agent=True, look_for_keys=True): |
|
146 |
"""Connect via SSH and initialize the NETCONF session. First attempts the publickey |
|
147 |
authentication method and then password authentication. |
|
133 |
# REMEMBER to update transport.rst if sig. changes, since it is hardcoded there |
|
134 |
def connect(self, host, port=830, timeout=None, unknown_host_cb=default_unknown_host_cb, |
|
135 |
username=None, password=None, key_filename=None, allow_agent=True, look_for_keys=True): |
|
136 |
"""Connect via SSH and initialize the NETCONF session. First attempts the publickey authentication method and then password authentication. |
|
148 | 137 |
|
149 |
To disable attemting publickey authentication altogether, call with *allow_agent* and |
|
150 |
*look_for_keys* as :const:`False`. |
|
138 |
To disable attempting publickey authentication altogether, call with *allow_agent* and *look_for_keys* as `False`. |
|
151 | 139 |
|
152 | 140 |
:arg host: the hostname or IP address to connect to |
153 |
:type host: `string`
|
|
141 |
:type host: string
|
|
154 | 142 |
|
155 | 143 |
:arg port: by default 830, but some devices use the default SSH port of 22 so this may need to be specified |
156 |
:type port: `int`
|
|
144 |
:type port: int
|
|
157 | 145 |
|
158 | 146 |
:arg timeout: an optional timeout for socket connect |
159 |
:type timeout: `int`
|
|
147 |
:type timeout: int
|
|
160 | 148 |
|
161 | 149 |
:arg unknown_host_cb: called when the server host key is not recognized |
162 |
:type unknown_host_cb: see :meth:`signature <ssh.default_unknown_host_cb>`
|
|
150 |
:type unknown_host_cb: see the signature of :func:`default_unknown_host_cb`
|
|
163 | 151 |
|
164 | 152 |
:arg username: the username to use for SSH authentication |
165 |
:type username: `string`
|
|
153 |
:type username: string
|
|
166 | 154 |
|
167 | 155 |
:arg password: the password used if using password authentication, or the passphrase to use for unlocking keys that require it |
168 |
:type password: `string`
|
|
156 |
:type password: string
|
|
169 | 157 |
|
170 | 158 |
:arg key_filename: a filename where a the private key to be used can be found |
171 |
:type key_filename: `string`
|
|
159 |
:type key_filename: string
|
|
172 | 160 |
|
173 | 161 |
:arg allow_agent: enables querying SSH agent (if found) for keys |
174 |
:type allow_agent: `bool`
|
|
162 |
:type allow_agent: bool
|
|
175 | 163 |
|
176 | 164 |
:arg look_for_keys: enables looking in the usual locations for ssh keys (e.g. :file:`~/.ssh/id_*`) |
177 |
:type look_for_keys: `bool`
|
|
165 |
:type look_for_keys: bool
|
|
178 | 166 |
""" |
179 |
|
|
180 | 167 |
if username is None: |
181 | 168 |
username = getpass.getuser() |
182 | 169 |
|
... | ... | |
306 | 293 |
q = self._q |
307 | 294 |
try: |
308 | 295 |
while True: |
309 |
# select on a paramiko ssh channel object does not ever return |
|
310 |
# it in the writable list, so it channel's don't exactly emulate |
|
311 |
# the socket api |
|
296 |
# select on a paramiko ssh channel object does not ever return it in the writable list, so channels don't exactly emulate the socket api |
|
312 | 297 |
r, w, e = select([chan], [], [], TICK) |
313 |
# will wakeup evey TICK seconds to check if something |
|
314 |
# to send, more if something to read (due to select returning |
|
315 |
# chan in readable list) |
|
298 |
# will wakeup evey TICK seconds to check if something to send, more if something to read (due to select returning chan in readable list) |
|
316 | 299 |
if r: |
317 | 300 |
data = chan.recv(BUF_SIZE) |
318 | 301 |
if data: |
... | ... | |
335 | 318 |
|
336 | 319 |
@property |
337 | 320 |
def transport(self): |
338 |
"""Underlying `paramiko.Transport |
|
339 |
<http://www.lag.net/paramiko/docs/paramiko.Transport-class.html>`_ |
|
340 |
object. This makes it possible to call methods like set_keepalive on it. |
|
341 |
""" |
|
321 |
"Underlying `paramiko.Transport <http://www.lag.net/paramiko/docs/paramiko.Transport-class.html>`_ object. This makes it possible to call methods like set_keepalive on it." |
|
342 | 322 |
return self._transport |
Also available in: Unified diff