ssh-handler 1.0.2__tar.gz → 1.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ssh_handler-1.0.2/ssh_handler.egg-info → ssh_handler-1.0.3}/PKG-INFO +1 -1
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/pyproject.toml +1 -1
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler/__init__.py +1 -1
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler/core.py +26 -2
- {ssh_handler-1.0.2 → ssh_handler-1.0.3/ssh_handler.egg-info}/PKG-INFO +1 -1
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/tests/test_offline.py +11 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/LICENSE +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/README.md +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/setup.cfg +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler/__main__.py +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler/cli.py +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler/config.py +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler/credentials.py +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler/exceptions.py +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler/ftp.py +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler/pool.py +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler/pyqt_worker.py +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler/results.py +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler/winrm_bootstrap.py +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler.egg-info/SOURCES.txt +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler.egg-info/dependency_links.txt +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler.egg-info/entry_points.txt +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler.egg-info/requires.txt +0 -0
- {ssh_handler-1.0.2 → ssh_handler-1.0.3}/ssh_handler.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ssh-handler"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.3"
|
|
8
8
|
description = "Extensive SSH/SFTP/SCP/FTP handler built on Paramiko, for test automation, CLIs and PyQt5 tools."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -269,7 +269,12 @@ class SSHHandler:
|
|
|
269
269
|
if cfg.passwordless:
|
|
270
270
|
kwargs["allow_agent"] = True
|
|
271
271
|
kwargs["look_for_keys"] = True
|
|
272
|
-
elif empty_password:
|
|
272
|
+
elif empty_password or pw == "":
|
|
273
|
+
# Explicit empty-password authentication. An empty string means
|
|
274
|
+
# "log in with a blank password" (PermitEmptyPasswords hosts) - send
|
|
275
|
+
# it directly and don't waste the first attempt probing keys/agent,
|
|
276
|
+
# which would otherwise fail with "No authentication methods
|
|
277
|
+
# available" before the empty password is ever tried.
|
|
273
278
|
kwargs["password"] = ""
|
|
274
279
|
kwargs["look_for_keys"] = False
|
|
275
280
|
kwargs["allow_agent"] = False
|
|
@@ -308,9 +313,28 @@ class SSHHandler:
|
|
|
308
313
|
last_auth = exc
|
|
309
314
|
client.close()
|
|
310
315
|
self._emit(logging.DEBUG, f"Auth strategy '{label}' rejected.")
|
|
311
|
-
except
|
|
316
|
+
except paramiko.SSHException as exc:
|
|
312
317
|
client.close()
|
|
318
|
+
# "No authentication methods available" means paramiko had no
|
|
319
|
+
# credential the server would accept (no password/key/agent).
|
|
320
|
+
# That's an auth problem, not a transport one - try the next
|
|
321
|
+
# strategy, and if none are left raise a clear, guided error.
|
|
322
|
+
if "no authentication methods" in str(exc).lower():
|
|
323
|
+
last_auth = exc
|
|
324
|
+
self._emit(logging.DEBUG,
|
|
325
|
+
f"Auth strategy '{label}': {exc}")
|
|
326
|
+
continue
|
|
313
327
|
raise exc
|
|
328
|
+
except OSError as exc:
|
|
329
|
+
client.close()
|
|
330
|
+
raise exc
|
|
331
|
+
if last_auth and "no authentication methods" in str(last_auth).lower():
|
|
332
|
+
raise SSHAuthenticationError(
|
|
333
|
+
f"No usable credentials for {cfg.auth_username}@{cfg.host}. "
|
|
334
|
+
f"Provide one of: password=..., key_filename=..., "
|
|
335
|
+
f"passwordless=True (use your SSH key/agent), or password='' for a "
|
|
336
|
+
f"blank-password account (the server must allow PermitEmptyPasswords)."
|
|
337
|
+
)
|
|
314
338
|
raise SSHAuthenticationError(
|
|
315
339
|
f"All authentication strategies failed for "
|
|
316
340
|
f"{cfg.auth_username}@{cfg.host}: {last_auth}"
|
|
@@ -38,6 +38,17 @@ kw2 = h._build_connect_kwargs(empty_password=True, sock=None)
|
|
|
38
38
|
assert kw2["password"] == "" and kw2["allow_agent"] is False
|
|
39
39
|
print("empty-password strategy OK")
|
|
40
40
|
|
|
41
|
+
# explicit password="" must send a blank password on the PRIMARY attempt
|
|
42
|
+
# (regression guard: previously the primary probed keys and failed with
|
|
43
|
+
# "No authentication methods available" before the empty password was tried)
|
|
44
|
+
hp = SSHHandler.__new__(SSHHandler)
|
|
45
|
+
hp.config = SSHConfig(host="t", username="u", password="")
|
|
46
|
+
hp._jump = None; hp.log = logging.getLogger("x2"); hp._log_callback = None
|
|
47
|
+
kw3 = hp._build_connect_kwargs(empty_password=False, sock=None)
|
|
48
|
+
assert kw3["password"] == "" and kw3["allow_agent"] is False \
|
|
49
|
+
and kw3["look_for_keys"] is False
|
|
50
|
+
print("explicit empty-password (primary) OK")
|
|
51
|
+
|
|
41
52
|
# TransferResult math
|
|
42
53
|
tr = TransferResult("a", "b", "push", "sftp", 1048576, 2.0, 1)
|
|
43
54
|
assert abs(tr.speed_bps - 524288) < 1 and tr.human_size == "1.0MB"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|