asyncssh 2.14.2__tar.gz → 2.15.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.15.0}/.github/workflows/run_tests.yml +26 -10
- {asyncssh-2.14.2 → asyncssh-2.15.0}/PKG-INFO +13 -5
- {asyncssh-2.14.2 → asyncssh-2.15.0}/README.rst +1 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/__init__.py +18 -17
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/agent.py +3 -3
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/agent_unix.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/agent_win32.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/channel.py +75 -18
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/client.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/config.py +12 -5
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/connection.py +527 -149
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/dsa.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/ecdsa.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/editor.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/encryption.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/forward.py +33 -3
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/gss_unix.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/kex.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/kex_dh.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/kex_rsa.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/listener.py +3 -2
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/misc.py +26 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/process.py +115 -32
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/public_key.py +34 -7
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/rsa.py +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/scp.py +23 -9
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/server.py +122 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/session.py +41 -8
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/sftp.py +194 -81
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/stream.py +54 -12
- asyncssh-2.15.0/asyncssh/tuntap.py +431 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/version.py +2 -2
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh.egg-info/PKG-INFO +13 -5
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh.egg-info/SOURCES.txt +2 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh.egg-info/requires.txt +1 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/docs/api.rst +122 -339
- {asyncssh-2.14.2 → asyncssh-2.15.0}/docs/changes.rst +65 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/docs/index.rst +20 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/mypy.ini +0 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/setup.py +3 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_agent.py +2 -2
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_channel.py +44 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_config.py +12 -1
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_connection.py +10 -2
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_connection_auth.py +80 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_forward.py +30 -12
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_process.py +126 -30
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_sftp.py +158 -3
- asyncssh-2.15.0/tests/test_tuntap.py +703 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/util.py +9 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/.coveragerc +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/.gitignore +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/.readthedocs.yaml +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/CONTRIBUTING.rst +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/COPYRIGHT +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/LICENSE +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/MANIFEST.in +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/asn1.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/auth.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/auth_keys.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/compression.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/constants.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/__init__.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/chacha.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/cipher.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/dh.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/dsa.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/ec.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/ec_params.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/ed.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/kdf.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/misc.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/rsa.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/sntrup.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/umac.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/crypto/x509.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/eddsa.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/gss.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/gss_win32.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/keysign.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/known_hosts.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/logging.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/mac.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/packet.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/pattern.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/pbe.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/pkcs11.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/py.typed +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/saslprep.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/sk.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/sk_ecdsa.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/sk_eddsa.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/socks.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/subprocess.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh/x11.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh.egg-info/dependency_links.txt +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/asyncssh.egg-info/top_level.txt +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/docs/_templates/sidebarbottom.html +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/docs/_templates/sidebartop.html +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/docs/conf.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/docs/contributing.rst +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/docs/requirements.txt +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/docs/rftheme/layout.html +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/docs/rftheme/static/rftheme.css_t +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/docs/rftheme/theme.conf +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/docs/rtd-req.txt +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/callback_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/callback_client2.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/callback_client3.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/callback_math_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/chat_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/check_exit_status.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/chroot_sftp_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/direct_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/direct_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/editor.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/gather_results.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/listening_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/local_forwarding_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/local_forwarding_client2.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/local_forwarding_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/math_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/math_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/redirect_input.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/redirect_local_pipe.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/redirect_remote_pipe.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/redirect_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/remote_forwarding_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/remote_forwarding_client2.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/remote_forwarding_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/reverse_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/reverse_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/scp_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/set_environment.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/set_terminal.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/sftp_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/show_environment.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/show_terminal.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/simple_cert_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/simple_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/simple_keyed_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/simple_scp_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/simple_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/simple_sftp_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/stream_direct_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/stream_direct_server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/examples/stream_listening_client.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/pylintrc +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/setup.cfg +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/__init__.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/gss_stub.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/gssapi_stub.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/keysign_stub.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/pkcs11_stub.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/server.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/sk_stub.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/sspi_stub.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_asn1.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_auth.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_auth_keys.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_compression.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_editor.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_encryption.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_kex.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_known_hosts.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_logging.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_mac.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_packet.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_pkcs11.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_public_key.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_saslprep.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_sk.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_stream.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_subprocess.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_x11.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.0}/tests/test_x509.py +0 -0
- {asyncssh-2.14.2 → asyncssh-2.15.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 }}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: asyncssh
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.15.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,8 +320,9 @@ class SSHConfig:
|
|
|
320
320
|
self._error(str(exc))
|
|
321
321
|
|
|
322
322
|
args = []
|
|
323
|
+
loption = ''
|
|
323
324
|
|
|
324
|
-
for arg in split_args:
|
|
325
|
+
for i, arg in enumerate(split_args, 1):
|
|
325
326
|
if arg.startswith('='):
|
|
326
327
|
if len(arg) > 1:
|
|
327
328
|
args.append(arg[1:])
|
|
@@ -334,8 +335,11 @@ class SSHConfig:
|
|
|
334
335
|
else:
|
|
335
336
|
args.append(arg)
|
|
336
337
|
|
|
337
|
-
|
|
338
|
-
|
|
338
|
+
if i == 1:
|
|
339
|
+
loption = args.pop(0).lower()
|
|
340
|
+
elif i > 1 and loption not in self._conditionals:
|
|
341
|
+
args.extend(split_args[i:])
|
|
342
|
+
break
|
|
339
343
|
|
|
340
344
|
if loption in self._no_split:
|
|
341
345
|
args = [line.lstrip()[len(loption):].strip()]
|
|
@@ -447,6 +451,8 @@ class SSHClientConfig(SSHConfig):
|
|
|
447
451
|
return self._local_user
|
|
448
452
|
elif match == 'user':
|
|
449
453
|
return self._options.get('User', self._local_user)
|
|
454
|
+
elif match == 'tagged':
|
|
455
|
+
return self._options.get('Tag', '')
|
|
450
456
|
else:
|
|
451
457
|
return None
|
|
452
458
|
|
|
@@ -560,7 +566,8 @@ class SSHClientConfig(SSHConfig):
|
|
|
560
566
|
('SendEnv', SSHConfig._append_string_list),
|
|
561
567
|
('ServerAliveCountMax', SSHConfig._set_int),
|
|
562
568
|
('ServerAliveInterval', SSHConfig._set_int),
|
|
563
|
-
('SetEnv', SSHConfig.
|
|
569
|
+
('SetEnv', SSHConfig._set_string_list),
|
|
570
|
+
('Tag', SSHConfig._set_string),
|
|
564
571
|
('TCPKeepAlive', SSHConfig._set_bool),
|
|
565
572
|
('User', SSHConfig._set_string),
|
|
566
573
|
('UserKnownHostsFile', SSHConfig._set_string_list)
|