asyncssh 2.14.2__tar.gz → 2.16.0__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.
- {asyncssh-2.14.2 → asyncssh-2.16.0}/.github/workflows/run_tests.yml +26 -10
- {asyncssh-2.14.2 → asyncssh-2.16.0}/CONTRIBUTING.rst +9 -10
- {asyncssh-2.14.2 → asyncssh-2.16.0}/PKG-INFO +13 -5
- {asyncssh-2.14.2 → asyncssh-2.16.0}/README.rst +1 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/__init__.py +18 -17
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/agent.py +3 -3
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/agent_unix.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/agent_win32.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/channel.py +75 -18
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/client.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/config.py +16 -7
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/connection.py +716 -170
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/cipher.py +48 -30
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/x509.py +2 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/dsa.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/ecdsa.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/editor.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/encryption.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/forward.py +33 -3
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/gss_unix.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/kex.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/kex_dh.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/kex_rsa.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/listener.py +3 -2
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/logging.py +22 -12
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/misc.py +39 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/process.py +115 -32
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/public_key.py +34 -7
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/rsa.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/saslprep.py +4 -2
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/scp.py +23 -9
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/server.py +122 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/session.py +41 -8
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/sftp.py +205 -94
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/stream.py +54 -12
- asyncssh-2.16.0/asyncssh/tuntap.py +431 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/version.py +2 -2
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh.egg-info/PKG-INFO +13 -5
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh.egg-info/SOURCES.txt +2 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh.egg-info/requires.txt +1 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/docs/api.rst +122 -339
- {asyncssh-2.14.2 → asyncssh-2.16.0}/docs/changes.rst +102 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/docs/index.rst +20 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/mypy.ini +0 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/setup.py +3 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_agent.py +2 -2
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_channel.py +44 -1
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_config.py +19 -2
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_connection.py +141 -3
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_connection_auth.py +80 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_forward.py +30 -12
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_process.py +126 -30
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_sftp.py +158 -3
- asyncssh-2.16.0/tests/test_tuntap.py +703 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/util.py +9 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/.coveragerc +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/.gitignore +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/.readthedocs.yaml +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/COPYRIGHT +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/LICENSE +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/MANIFEST.in +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/asn1.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/auth.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/auth_keys.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/compression.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/constants.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/__init__.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/chacha.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/dh.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/dsa.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/ec.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/ec_params.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/ed.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/kdf.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/misc.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/rsa.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/sntrup.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/crypto/umac.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/eddsa.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/gss.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/gss_win32.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/keysign.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/known_hosts.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/mac.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/packet.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/pattern.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/pbe.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/pkcs11.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/py.typed +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/sk.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/sk_ecdsa.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/sk_eddsa.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/socks.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/subprocess.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh/x11.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh.egg-info/dependency_links.txt +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/asyncssh.egg-info/top_level.txt +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/docs/_templates/sidebarbottom.html +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/docs/_templates/sidebartop.html +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/docs/conf.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/docs/contributing.rst +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/docs/requirements.txt +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/docs/rftheme/layout.html +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/docs/rftheme/static/rftheme.css_t +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/docs/rftheme/theme.conf +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/docs/rtd-req.txt +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/callback_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/callback_client2.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/callback_client3.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/callback_math_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/chat_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/check_exit_status.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/chroot_sftp_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/direct_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/direct_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/editor.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/gather_results.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/listening_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/local_forwarding_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/local_forwarding_client2.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/local_forwarding_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/math_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/math_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/redirect_input.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/redirect_local_pipe.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/redirect_remote_pipe.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/redirect_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/remote_forwarding_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/remote_forwarding_client2.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/remote_forwarding_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/reverse_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/reverse_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/scp_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/set_environment.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/set_terminal.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/sftp_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/show_environment.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/show_terminal.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/simple_cert_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/simple_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/simple_keyed_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/simple_scp_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/simple_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/simple_sftp_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/stream_direct_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/stream_direct_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/examples/stream_listening_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/pylintrc +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/setup.cfg +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/__init__.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/gss_stub.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/gssapi_stub.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/keysign_stub.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/pkcs11_stub.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/sk_stub.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/sspi_stub.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_asn1.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_auth.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_auth_keys.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_compression.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_editor.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_encryption.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_kex.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_known_hosts.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_logging.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_mac.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_packet.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_pkcs11.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_public_key.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_saslprep.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_sk.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_stream.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_subprocess.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_x11.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tests/test_x509.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.16.0}/tox.ini +0 -0
|
@@ -20,6 +20,10 @@ jobs:
|
|
|
20
20
|
python-version: "3.12"
|
|
21
21
|
openssl-version: "3"
|
|
22
22
|
exclude:
|
|
23
|
+
# having trouble with arch arm64 on macos-ltest on Python 3.7
|
|
24
|
+
- os: macos-latest
|
|
25
|
+
python-version: "3.7"
|
|
26
|
+
|
|
23
27
|
# test hangs on these combination
|
|
24
28
|
- os: windows-latest
|
|
25
29
|
python-version: "3.8"
|
|
@@ -39,19 +43,19 @@ jobs:
|
|
|
39
43
|
|
|
40
44
|
steps:
|
|
41
45
|
- name: Checkout asyncssh
|
|
42
|
-
uses: actions/checkout@
|
|
46
|
+
uses: actions/checkout@v4
|
|
43
47
|
with:
|
|
44
48
|
path: asyncssh
|
|
45
49
|
|
|
46
50
|
- name: Checkout liboqs
|
|
47
51
|
if: ${{ runner.os != 'macOS' }}
|
|
48
|
-
uses: actions/checkout@
|
|
52
|
+
uses: actions/checkout@v4
|
|
49
53
|
with:
|
|
50
54
|
repository: open-quantum-safe/liboqs
|
|
51
55
|
ref: ${{ env.liboqs_version }}
|
|
52
56
|
path: liboqs
|
|
53
57
|
|
|
54
|
-
- uses: actions/setup-python@
|
|
58
|
+
- uses: actions/setup-python@v5
|
|
55
59
|
with:
|
|
56
60
|
python-version: ${{ matrix.python-version }}
|
|
57
61
|
cache: pip
|
|
@@ -122,23 +126,34 @@ jobs:
|
|
|
122
126
|
check=True)
|
|
123
127
|
|
|
124
128
|
- name: Upload coverage data
|
|
125
|
-
uses: actions/upload-artifact@
|
|
129
|
+
uses: actions/upload-artifact@v4
|
|
126
130
|
with:
|
|
127
|
-
name: coverage
|
|
131
|
+
name: coverage-${{ matrix.os }}-${{ matrix.python-version }}
|
|
128
132
|
path: asyncssh/.coverage.*
|
|
129
133
|
retention-days: 1
|
|
130
134
|
|
|
135
|
+
merge-coverage:
|
|
136
|
+
runs-on: ubuntu-latest
|
|
137
|
+
needs: run-tests
|
|
138
|
+
if: ${{ always() }}
|
|
139
|
+
steps:
|
|
140
|
+
- name: Merge coverage
|
|
141
|
+
uses: actions/upload-artifact/merge@v4
|
|
142
|
+
with:
|
|
143
|
+
name: coverage
|
|
144
|
+
pattern: coverage-*
|
|
145
|
+
|
|
131
146
|
report-coverage:
|
|
132
147
|
name: Report coverage
|
|
133
148
|
runs-on: ubuntu-latest
|
|
134
|
-
needs:
|
|
149
|
+
needs: merge-coverage
|
|
135
150
|
if: ${{ always() }}
|
|
136
151
|
steps:
|
|
137
|
-
- uses: actions/checkout@
|
|
138
|
-
- uses: actions/setup-python@
|
|
152
|
+
- uses: actions/checkout@v4
|
|
153
|
+
- uses: actions/setup-python@v5
|
|
139
154
|
with:
|
|
140
155
|
python-version: "3.7"
|
|
141
|
-
- uses: actions/download-artifact@
|
|
156
|
+
- uses: actions/download-artifact@v4
|
|
142
157
|
with:
|
|
143
158
|
name: coverage
|
|
144
159
|
- name: Install dependencies
|
|
@@ -152,6 +167,7 @@ jobs:
|
|
|
152
167
|
sqlite3 "$f" "update file set path = replace(path, '\\', '/');"
|
|
153
168
|
done
|
|
154
169
|
tox -e report
|
|
155
|
-
- uses: codecov/codecov-action@
|
|
170
|
+
- uses: codecov/codecov-action@v4
|
|
156
171
|
with:
|
|
157
172
|
files: coverage.xml
|
|
173
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
@@ -68,19 +68,18 @@ contributors list.
|
|
|
68
68
|
Branches
|
|
69
69
|
--------
|
|
70
70
|
|
|
71
|
-
There are two long-lived branches in AsyncSSH
|
|
71
|
+
There are two long-lived branches in AsyncSSH:
|
|
72
72
|
|
|
73
73
|
* The master branch is intended to contain the latest stable version
|
|
74
74
|
of the code. All official versions of AsyncSSH are released from
|
|
75
75
|
this branch, and each release has a corresponding tag added
|
|
76
|
-
matching its release number.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
APIs in the develop branch may be subject to change until they
|
|
83
|
-
are migrated back to master, and there's no guarantee of backward
|
|
76
|
+
matching its release number.
|
|
77
|
+
|
|
78
|
+
* The develop branch is intended to contain new features and bug fixes
|
|
79
|
+
ready to be tested before being added to an official release. APIs
|
|
80
|
+
in the develop branch may be subject to change until they are
|
|
81
|
+
migrated back to master, and there's no guarantee of backward
|
|
84
82
|
compatibility in this branch. However, pulling from this branch
|
|
85
83
|
will provide early access to new functionality and a chance to
|
|
86
|
-
influence this functionality before it is released.
|
|
84
|
+
influence this functionality before it is released. Also, all
|
|
85
|
+
pull requests should be submitted against this branch.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: asyncssh
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.16.0
|
|
4
4
|
Summary: AsyncSSH: Asynchronous SSHv2 client and server library
|
|
5
5
|
Home-page: http://asyncssh.timeheart.net
|
|
6
6
|
Author: Ron Frederick
|
|
@@ -27,14 +27,23 @@ Classifier: Topic :: Security :: Cryptography
|
|
|
27
27
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
28
28
|
Classifier: Topic :: System :: Networking
|
|
29
29
|
Requires-Python: >= 3.6
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: cryptography>=39.0
|
|
32
|
+
Requires-Dist: typing_extensions>=4.0.0
|
|
30
33
|
Provides-Extra: bcrypt
|
|
34
|
+
Requires-Dist: bcrypt>=3.1.3; extra == "bcrypt"
|
|
31
35
|
Provides-Extra: fido2
|
|
36
|
+
Requires-Dist: fido2>=0.9.2; extra == "fido2"
|
|
32
37
|
Provides-Extra: gssapi
|
|
38
|
+
Requires-Dist: gssapi>=1.2.0; extra == "gssapi"
|
|
33
39
|
Provides-Extra: libnacl
|
|
40
|
+
Requires-Dist: libnacl>=1.4.2; extra == "libnacl"
|
|
34
41
|
Provides-Extra: pkcs11
|
|
35
|
-
|
|
42
|
+
Requires-Dist: python-pkcs11>=0.7.0; extra == "pkcs11"
|
|
43
|
+
Provides-Extra: pyopenssl
|
|
44
|
+
Requires-Dist: pyOpenSSL>=23.0.0; extra == "pyopenssl"
|
|
36
45
|
Provides-Extra: pywin32
|
|
37
|
-
|
|
46
|
+
Requires-Dist: pywin32>=227; extra == "pywin32"
|
|
38
47
|
|
|
39
48
|
.. image:: https://readthedocs.org/projects/asyncssh/badge/?version=latest
|
|
40
49
|
:target: https://asyncssh.readthedocs.io/en/latest/?badge=latest
|
|
@@ -79,6 +88,7 @@ Features
|
|
|
79
88
|
* Environment variables, terminal type, and window size
|
|
80
89
|
* Direct and forwarded TCP/IP channels
|
|
81
90
|
* OpenSSH-compatible direct and forwarded UNIX domain socket channels
|
|
91
|
+
* OpenSSH-compatible TUN/TAP channels and packet forwarding
|
|
82
92
|
* Local and remote TCP/IP port forwarding
|
|
83
93
|
* Local and remote UNIX domain socket forwarding
|
|
84
94
|
* Dynamic TCP/IP port forwarding via SOCKS
|
|
@@ -266,5 +276,3 @@ Three mailing lists are available for AsyncSSH:
|
|
|
266
276
|
__ http://groups.google.com/d/forum/asyncssh-announce
|
|
267
277
|
__ http://groups.google.com/d/forum/asyncssh-dev
|
|
268
278
|
__ http://groups.google.com/d/forum/asyncssh-users
|
|
269
|
-
|
|
270
|
-
|
|
@@ -41,6 +41,7 @@ Features
|
|
|
41
41
|
* Environment variables, terminal type, and window size
|
|
42
42
|
* Direct and forwarded TCP/IP channels
|
|
43
43
|
* OpenSSH-compatible direct and forwarded UNIX domain socket channels
|
|
44
|
+
* OpenSSH-compatible TUN/TAP channels and packet forwarding
|
|
44
45
|
* Local and remote TCP/IP port forwarding
|
|
45
46
|
* Local and remote UNIX domain socket forwarding
|
|
46
47
|
* Dynamic TCP/IP port forwarding via SOCKS
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2013-
|
|
1
|
+
# Copyright (c) 2013-2024 by Ron Frederick <ronf@timeheart.net> and others.
|
|
2
2
|
#
|
|
3
3
|
# This program and the accompanying materials are made available under
|
|
4
4
|
# the terms of the Eclipse Public License v2.0 which accompanies this
|
|
@@ -34,7 +34,7 @@ from .auth_keys import SSHAuthorizedKeys
|
|
|
34
34
|
from .auth_keys import import_authorized_keys, read_authorized_keys
|
|
35
35
|
|
|
36
36
|
from .channel import SSHClientChannel, SSHServerChannel
|
|
37
|
-
from .channel import SSHTCPChannel, SSHUNIXChannel
|
|
37
|
+
from .channel import SSHTCPChannel, SSHUNIXChannel, SSHTunTapChannel
|
|
38
38
|
|
|
39
39
|
from .client import SSHClient
|
|
40
40
|
|
|
@@ -92,7 +92,7 @@ from .rsa import set_default_skip_rsa_key_validation
|
|
|
92
92
|
from .scp import scp
|
|
93
93
|
|
|
94
94
|
from .session import DataType, SSHClientSession, SSHServerSession
|
|
95
|
-
from .session import SSHTCPSession, SSHUNIXSession
|
|
95
|
+
from .session import SSHTCPSession, SSHUNIXSession, SSHTunTapSession
|
|
96
96
|
|
|
97
97
|
from .server import SSHServer
|
|
98
98
|
|
|
@@ -154,18 +154,19 @@ __all__ = [
|
|
|
154
154
|
'SSHServerSessionFactory', 'SSHSocketSessionFactory',
|
|
155
155
|
'SSHSubprocessProtocol', 'SSHSubprocessReadPipe',
|
|
156
156
|
'SSHSubprocessTransport', 'SSHSubprocessWritePipe', 'SSHTCPChannel',
|
|
157
|
-
'SSHTCPSession', '
|
|
158
|
-
'
|
|
159
|
-
'
|
|
160
|
-
'
|
|
161
|
-
'
|
|
162
|
-
'
|
|
163
|
-
'
|
|
164
|
-
'
|
|
165
|
-
'
|
|
166
|
-
'
|
|
167
|
-
'
|
|
168
|
-
'
|
|
169
|
-
'
|
|
170
|
-
'
|
|
157
|
+
'SSHTCPSession', 'SSHTunTapChannel', 'SSHTunTapSession',
|
|
158
|
+
'SSHUNIXChannel', 'SSHUNIXSession', 'SSHWriter',
|
|
159
|
+
'STDOUT', 'ServiceNotAvailable', 'SignalReceived', 'TerminalSizeChanged',
|
|
160
|
+
'TimeoutError', 'connect', 'connect_agent', 'connect_reverse',
|
|
161
|
+
'create_connection', 'create_server', 'generate_private_key',
|
|
162
|
+
'get_server_auth_methods', 'get_server_host_key',
|
|
163
|
+
'import_authorized_keys', 'import_certificate', 'import_known_hosts',
|
|
164
|
+
'import_private_key', 'import_public_key', 'listen', 'listen_reverse',
|
|
165
|
+
'load_certificates', 'load_keypairs', 'load_pkcs11_keys',
|
|
166
|
+
'load_public_keys', 'load_resident_keys', 'logger', 'match_known_hosts',
|
|
167
|
+
'read_authorized_keys', 'read_certificate', 'read_certificate_list',
|
|
168
|
+
'read_known_hosts', 'read_private_key', 'read_private_key_list',
|
|
169
|
+
'read_public_key', 'read_public_key_list', 'run_client', 'run_server',
|
|
170
|
+
'scp', 'set_debug_level', 'set_default_skip_rsa_key_validation',
|
|
171
|
+
'set_log_level', 'set_sftp_log_level'
|
|
171
172
|
]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2016-
|
|
1
|
+
# Copyright (c) 2016-2024 by Ron Frederick <ronf@timeheart.net> and others.
|
|
2
2
|
#
|
|
3
3
|
# This program and the accompanying materials are made available under
|
|
4
4
|
# the terms of the Eclipse Public License v2.0 which accompanies this
|
|
@@ -26,7 +26,7 @@ import os
|
|
|
26
26
|
import sys
|
|
27
27
|
from types import TracebackType
|
|
28
28
|
from typing import TYPE_CHECKING, List, Optional, Sequence, Tuple, Type, Union
|
|
29
|
-
from typing_extensions import Protocol
|
|
29
|
+
from typing_extensions import Protocol, Self
|
|
30
30
|
|
|
31
31
|
from .listener import SSHForwardListener
|
|
32
32
|
from .misc import async_context_manager, maybe_wait_closed
|
|
@@ -198,7 +198,7 @@ class SSHAgentClient:
|
|
|
198
198
|
self._writer: Optional[AgentWriter] = None
|
|
199
199
|
self._lock = asyncio.Lock()
|
|
200
200
|
|
|
201
|
-
async def __aenter__(self) ->
|
|
201
|
+
async def __aenter__(self) -> Self:
|
|
202
202
|
"""Allow SSHAgentClient to be used as an async context manager"""
|
|
203
203
|
|
|
204
204
|
return self
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2016-
|
|
1
|
+
# Copyright (c) 2016-2024 by Ron Frederick <ronf@timeheart.net> and others.
|
|
2
2
|
#
|
|
3
3
|
# This program and the accompanying materials are made available under
|
|
4
4
|
# the terms of the Eclipse Public License v2.0 which accompanies this
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2016-
|
|
1
|
+
# Copyright (c) 2016-2024 by Ron Frederick <ronf@timeheart.net> and others.
|
|
2
2
|
#
|
|
3
3
|
# This program and the accompanying materials are made available under
|
|
4
4
|
# the terms of the Eclipse Public License v2.0 which accompanies this
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2013-
|
|
1
|
+
# Copyright (c) 2013-2024 by Ron Frederick <ronf@timeheart.net> and others.
|
|
2
2
|
#
|
|
3
3
|
# This program and the accompanying materials are made available under
|
|
4
4
|
# the terms of the Eclipse Public License v2.0 which accompanies this
|
|
@@ -46,18 +46,22 @@ from .editor import SSHLineEditorChannel, SSHLineEditorSession
|
|
|
46
46
|
from .logging import SSHLogger
|
|
47
47
|
|
|
48
48
|
from .misc import ChannelOpenError, MaybeAwait, ProtocolError
|
|
49
|
+
from .misc import TermModes, TermSize, TermSizeArg
|
|
49
50
|
from .misc import get_symbol_names, map_handler_name
|
|
50
51
|
|
|
51
52
|
from .packet import Boolean, Byte, String, UInt32, SSHPacket, SSHPacketHandler
|
|
52
53
|
|
|
53
|
-
from .session import TermModes, TermSize, TermSizeArg
|
|
54
54
|
from .session import SSHSession, SSHClientSession, SSHServerSession
|
|
55
|
-
from .session import SSHTCPSession, SSHUNIXSession
|
|
55
|
+
from .session import SSHTCPSession, SSHUNIXSession, SSHTunTapSession
|
|
56
56
|
from .session import SSHSessionFactory, SSHClientSessionFactory
|
|
57
57
|
from .session import SSHTCPSessionFactory, SSHUNIXSessionFactory
|
|
58
|
+
from .session import SSHTunTapSessionFactory
|
|
58
59
|
|
|
59
60
|
from .stream import DataType
|
|
60
61
|
|
|
62
|
+
from .tuntap import SSH_TUN_MODE_POINTTOPOINT, SSH_TUN_UNIT_ANY
|
|
63
|
+
from .tuntap import SSH_TUN_AF_INET, SSH_TUN_AF_INET6
|
|
64
|
+
|
|
61
65
|
|
|
62
66
|
if TYPE_CHECKING:
|
|
63
67
|
# pylint: disable=cyclic-import
|
|
@@ -225,7 +229,7 @@ class SSHChannel(Generic[AnyStr], SSHPacketHandler):
|
|
|
225
229
|
|
|
226
230
|
self._close_event.set()
|
|
227
231
|
|
|
228
|
-
if self._conn: # pragma: no branch
|
|
232
|
+
if self._conn and self._recv_state == 'closed': # pragma: no branch
|
|
229
233
|
self.logger.info('Channel closed%s',
|
|
230
234
|
': ' + str(exc) if exc else '')
|
|
231
235
|
|
|
@@ -259,7 +263,8 @@ class SSHChannel(Generic[AnyStr], SSHPacketHandler):
|
|
|
259
263
|
# If recv is close_pending, we know send is already closed
|
|
260
264
|
if self._recv_state == 'close_pending':
|
|
261
265
|
self._recv_state = 'closed'
|
|
262
|
-
|
|
266
|
+
|
|
267
|
+
self._loop.call_soon(self._cleanup)
|
|
263
268
|
|
|
264
269
|
async def _start_reading(self) -> None:
|
|
265
270
|
"""Start processing data on a new connection"""
|
|
@@ -394,19 +399,6 @@ class SSHChannel(Generic[AnyStr], SSHPacketHandler):
|
|
|
394
399
|
if self._send_state in {'close_pending', 'closed'}:
|
|
395
400
|
return
|
|
396
401
|
|
|
397
|
-
datalen = len(data)
|
|
398
|
-
|
|
399
|
-
if datalen > self._recv_window:
|
|
400
|
-
raise ProtocolError('Window exceeded')
|
|
401
|
-
|
|
402
|
-
if datatype:
|
|
403
|
-
typename = ' from %s' % _data_type_names[datatype]
|
|
404
|
-
else:
|
|
405
|
-
typename = ''
|
|
406
|
-
|
|
407
|
-
self.logger.debug2('Received %d data byte%s%s', datalen,
|
|
408
|
-
's' if datalen > 1 else '', typename)
|
|
409
|
-
|
|
410
402
|
if self._recv_paused:
|
|
411
403
|
self._recv_buf.append((data, datatype))
|
|
412
404
|
else:
|
|
@@ -579,6 +571,14 @@ class SSHChannel(Generic[AnyStr], SSHPacketHandler):
|
|
|
579
571
|
data = packet.get_string()
|
|
580
572
|
packet.check_end()
|
|
581
573
|
|
|
574
|
+
datalen = len(data)
|
|
575
|
+
|
|
576
|
+
if datalen > self._recv_window:
|
|
577
|
+
raise ProtocolError('Window exceeded')
|
|
578
|
+
|
|
579
|
+
self.logger.debug2('Received %d data byte%s', datalen,
|
|
580
|
+
's' if datalen > 1 else '')
|
|
581
|
+
|
|
582
582
|
self._accept_data(data)
|
|
583
583
|
|
|
584
584
|
def _process_extended_data(self, _pkttype: int, _pktid: int,
|
|
@@ -595,6 +595,15 @@ class SSHChannel(Generic[AnyStr], SSHPacketHandler):
|
|
|
595
595
|
if datatype not in self._read_datatypes:
|
|
596
596
|
raise ProtocolError('Invalid extended data type')
|
|
597
597
|
|
|
598
|
+
datalen = len(data)
|
|
599
|
+
|
|
600
|
+
if datalen > self._recv_window:
|
|
601
|
+
raise ProtocolError('Window exceeded')
|
|
602
|
+
|
|
603
|
+
self.logger.debug2('Received %d data byte%s from %s', datalen,
|
|
604
|
+
's' if datalen > 1 else '',
|
|
605
|
+
_data_type_names[datatype])
|
|
606
|
+
|
|
598
607
|
self._accept_data(data, datatype)
|
|
599
608
|
|
|
600
609
|
def _process_eof(self, _pkttype: int, _pktid: int,
|
|
@@ -2080,6 +2089,54 @@ class SSHUNIXChannel(SSHForwardChannel, Generic[AnyStr]):
|
|
|
2080
2089
|
self.set_extra_info(local_peername=dest_path, remote_peername='')
|
|
2081
2090
|
|
|
2082
2091
|
|
|
2092
|
+
class SSHTunTapChannel(SSHForwardChannel[bytes]):
|
|
2093
|
+
"""SSH TunTap channel"""
|
|
2094
|
+
|
|
2095
|
+
def __init__(self, conn: 'SSHConnection',
|
|
2096
|
+
loop: asyncio.AbstractEventLoop, encoding: Optional[str],
|
|
2097
|
+
errors: str, window: int, max_pktsize: int):
|
|
2098
|
+
super().__init__(conn, loop, encoding, errors, window, max_pktsize)
|
|
2099
|
+
|
|
2100
|
+
self._mode: Optional[int] = None
|
|
2101
|
+
|
|
2102
|
+
def _accept_data(self, data: bytes, datatype: DataType = None) -> None:
|
|
2103
|
+
"""Strip off address family on incoming packets in TUN mode"""
|
|
2104
|
+
|
|
2105
|
+
if self._mode == SSH_TUN_MODE_POINTTOPOINT:
|
|
2106
|
+
data = data[4:]
|
|
2107
|
+
|
|
2108
|
+
super()._accept_data(data, datatype)
|
|
2109
|
+
|
|
2110
|
+
def write(self, data: bytes, datatype: DataType = None) -> None:
|
|
2111
|
+
"""Add address family in outbound packets in TUN mode"""
|
|
2112
|
+
|
|
2113
|
+
if self._mode == SSH_TUN_MODE_POINTTOPOINT:
|
|
2114
|
+
version = data[0] >> 4
|
|
2115
|
+
family = SSH_TUN_AF_INET if version == 4 else SSH_TUN_AF_INET6
|
|
2116
|
+
data = UInt32(family) + data
|
|
2117
|
+
|
|
2118
|
+
super().write(data, datatype)
|
|
2119
|
+
|
|
2120
|
+
async def open(self, session_factory: SSHTunTapSessionFactory,
|
|
2121
|
+
mode: int, unit: Optional[int]) -> SSHTunTapSession:
|
|
2122
|
+
"""Open a TUN/TAP channel"""
|
|
2123
|
+
|
|
2124
|
+
self._mode = mode
|
|
2125
|
+
|
|
2126
|
+
if unit is None:
|
|
2127
|
+
unit = SSH_TUN_UNIT_ANY
|
|
2128
|
+
|
|
2129
|
+
return cast(SSHTunTapSession,
|
|
2130
|
+
await self._open_forward(session_factory,
|
|
2131
|
+
b'tun@openssh.com',
|
|
2132
|
+
UInt32(mode), UInt32(unit)))
|
|
2133
|
+
|
|
2134
|
+
def set_mode(self, mode: int) -> None:
|
|
2135
|
+
"""Set mode for inbound connections"""
|
|
2136
|
+
|
|
2137
|
+
self._mode = mode
|
|
2138
|
+
|
|
2139
|
+
|
|
2083
2140
|
class SSHX11Channel(SSHForwardChannel[bytes]):
|
|
2084
2141
|
"""SSH X11 channel"""
|
|
2085
2142
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2013-
|
|
1
|
+
# Copyright (c) 2013-2023 by Ron Frederick <ronf@timeheart.net> and others.
|
|
2
2
|
#
|
|
3
3
|
# This program and the accompanying materials are made available under
|
|
4
4
|
# the terms of the Eclipse Public License v2.0 which accompanies this
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c) 2020-
|
|
1
|
+
# Copyright (c) 2020-2024 by Ron Frederick <ronf@timeheart.net> and others.
|
|
2
2
|
#
|
|
3
3
|
# This program and the accompanying materials are made available under
|
|
4
4
|
# the terms of the Eclipse Public License v2.0 which accompanies this
|
|
@@ -320,11 +320,16 @@ class SSHConfig:
|
|
|
320
320
|
self._error(str(exc))
|
|
321
321
|
|
|
322
322
|
args = []
|
|
323
|
+
loption = ''
|
|
324
|
+
allow_equal = True
|
|
323
325
|
|
|
324
|
-
for arg in split_args:
|
|
326
|
+
for i, arg in enumerate(split_args, 1):
|
|
325
327
|
if arg.startswith('='):
|
|
326
328
|
if len(arg) > 1:
|
|
327
329
|
args.append(arg[1:])
|
|
330
|
+
elif not allow_equal:
|
|
331
|
+
args.extend(split_args[i-1:])
|
|
332
|
+
break
|
|
328
333
|
elif arg.endswith('='):
|
|
329
334
|
args.append(arg[:-1])
|
|
330
335
|
elif '=' in arg:
|
|
@@ -334,8 +339,9 @@ class SSHConfig:
|
|
|
334
339
|
else:
|
|
335
340
|
args.append(arg)
|
|
336
341
|
|
|
337
|
-
|
|
338
|
-
|
|
342
|
+
if i == 1:
|
|
343
|
+
loption = args.pop(0).lower()
|
|
344
|
+
allow_equal = loption in self._conditionals
|
|
339
345
|
|
|
340
346
|
if loption in self._no_split:
|
|
341
347
|
args = [line.lstrip()[len(loption):].strip()]
|
|
@@ -419,7 +425,7 @@ class SSHClientConfig(SSHConfig):
|
|
|
419
425
|
"""Settings from an OpenSSH client config file"""
|
|
420
426
|
|
|
421
427
|
_conditionals = {'host', 'match'}
|
|
422
|
-
_no_split = {'remotecommand'}
|
|
428
|
+
_no_split = {'proxycommand', 'remotecommand'}
|
|
423
429
|
_percent_expand = {'CertificateFile', 'IdentityAgent',
|
|
424
430
|
'IdentityFile', 'ProxyCommand', 'RemoteCommand'}
|
|
425
431
|
|
|
@@ -447,6 +453,8 @@ class SSHClientConfig(SSHConfig):
|
|
|
447
453
|
return self._local_user
|
|
448
454
|
elif match == 'user':
|
|
449
455
|
return self._options.get('User', self._local_user)
|
|
456
|
+
elif match == 'tagged':
|
|
457
|
+
return self._options.get('Tag', '')
|
|
450
458
|
else:
|
|
451
459
|
return None
|
|
452
460
|
|
|
@@ -551,7 +559,7 @@ class SSHClientConfig(SSHConfig):
|
|
|
551
559
|
('PKCS11Provider', SSHConfig._set_string),
|
|
552
560
|
('PreferredAuthentications', SSHConfig._set_string),
|
|
553
561
|
('Port', SSHConfig._set_int),
|
|
554
|
-
('ProxyCommand', SSHConfig.
|
|
562
|
+
('ProxyCommand', SSHConfig._set_string),
|
|
555
563
|
('ProxyJump', SSHConfig._set_string),
|
|
556
564
|
('PubkeyAuthentication', SSHConfig._set_bool),
|
|
557
565
|
('RekeyLimit', SSHConfig._set_rekey_limits),
|
|
@@ -560,7 +568,8 @@ class SSHClientConfig(SSHConfig):
|
|
|
560
568
|
('SendEnv', SSHConfig._append_string_list),
|
|
561
569
|
('ServerAliveCountMax', SSHConfig._set_int),
|
|
562
570
|
('ServerAliveInterval', SSHConfig._set_int),
|
|
563
|
-
('SetEnv', SSHConfig.
|
|
571
|
+
('SetEnv', SSHConfig._set_string_list),
|
|
572
|
+
('Tag', SSHConfig._set_string),
|
|
564
573
|
('TCPKeepAlive', SSHConfig._set_bool),
|
|
565
574
|
('User', SSHConfig._set_string),
|
|
566
575
|
('UserKnownHostsFile', SSHConfig._set_string_list)
|