pax_global_header00006660000000000000000000000064145603607630014524gustar00rootroot0000000000000052 comment=9ceba3e7ffaeaf79705c2abe3a3cc8aea86fd017 apache-mina-sshd-46fc8d6/000077500000000000000000000000001456036076300152545ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/.asf.yaml000066400000000000000000000010201456036076300167600ustar00rootroot00000000000000# See https://cwiki.apache.org/confluence/display/INFRA/Git+-+.asf.yaml+features github: description: "Apache MINA sshd is a comprehensive Java library for client- and server-side SSH." homepage: https://mina.apache.org/sshd-project/ labels: - ssh - library - java - apache features: issues: true dependabot_alerts: true dependabot_updates: true notifications: commits: commits@mina.apache.org issues: dev@mina.apache.org pullrequests: dev@mina.apache.org jira_options: link apache-mina-sshd-46fc8d6/.gitattributes000066400000000000000000000021351456036076300201500ustar00rootroot00000000000000# NOTE: see https://help.github.com/en/github/using-git/configuring-git-to-handle-line-endings#refreshing-a-repository-after-changing-line-endings # regarding the need to re-normalize the files after changing this one # Handle line endings automatically for files detected as text # and leave all files detected as binary untouched. * text=auto *.txt text eol=lf *.sh text eol=lf *.properties text eol=lf *.groovy text eol=lf *.scala text eol=lf *.java text eol=lf *.pl text eol=lf *.md text eol=lf *.awk text eol=lf *.xml text eol=lf *.html text eol=lf *.yaml text eol=lf *.json text eol=lf *.py text eol=lf *.js text eol=lf *.bat text eol=crlf *.vbs text eol=crlf # These files are binary and should be left untouched # (binary is macro for -text -diff) *.jpg binary *.gif binary *.png binary *.class binary *.pdf binary *.jar binary *.zip binary *.war binary apache-mina-sshd-46fc8d6/.github/000077500000000000000000000000001456036076300166145ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/.github/ISSUE_TEMPLATE/000077500000000000000000000000001456036076300207775ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/.github/ISSUE_TEMPLATE/bug_report.yml000066400000000000000000000031551456036076300236760ustar00rootroot00000000000000name: Bug Report description: File a bug report. body: - type: markdown attributes: value: | Thank you for taking the time to fill out this bug report! - type: input id: version attributes: label: Version description: With what version(s) of Apache MINA SSHD did you observe the bug? placeholder: a version, like 2.9.2, or a branch name, or a commit ID validations: required: true - type: textarea id: description attributes: label: Bug description description: Explain the buggy behavior, and how to reproduce it. validations: required: true - type: textarea id: actual attributes: label: Actual behavior description: What happened? placeholder: Enclose exception stack traces by backticks, or paste them in the "Relevant log output" field below. validations: required: true - type: textarea id: expected attributes: label: Expected behavior description: What did you expect? validations: required: true - type: textarea id: logs attributes: label: Relevant log output description: Please copy and paste any relevant log output or exception stack traces. This will be automatically formatted into code, so no need for backticks. render: Shell - type: textarea id: other attributes: label: Other information description: Any other relevant information. placeholder: "For instance, if the problem occurs in communication with an SSH peer, what kind of peer: OpenSSH (which version?), or also Apache MINA SSHD, or something else?" apache-mina-sshd-46fc8d6/.github/ISSUE_TEMPLATE/feature_request.yml000066400000000000000000000020201456036076300247170ustar00rootroot00000000000000name: Feature Request description: Suggest an enhancement or a new feature. body: - type: markdown attributes: value: | Thank you for helping making Apache MINA SSHD better! - type: textarea id: description attributes: label: Description description: What feature or enhancement you would like to have in Apache MINA SSHD? validations: required: true - type: textarea id: motivation attributes: label: Motivation description: Explain the use case for the new feature. placeholder: Explain why it would be good to have the new feature or enhancement. What problem would it solve? validations: required: true - type: textarea id: alternatives attributes: label: Alternatives considered description: What alternatives did you consider? What work-around, if any, are you using currently? - type: textarea id: other attributes: label: Additional context description: Any other information that may be relevant. apache-mina-sshd-46fc8d6/.github/workflows/000077500000000000000000000000001456036076300206515ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/.github/workflows/build.yml000066400000000000000000000051541456036076300225000ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # name: build on: pull_request: branches: - master workflow_call: jobs: compile: runs-on: ${{ matrix.os }} strategy: matrix: os: [ ubuntu-latest, windows-latest ] java: [ '8' ] steps: - uses: actions/checkout@v3 - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v3 with: distribution: temurin java-version: ${{ matrix.java }} - uses: actions/cache@v3 with: path: ~/.m2/repository key: ${{ matrix.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ matrix.os }}-maven- - name: Build with maven run: mvn -B --errors --activate-profiles ci --no-transfer-progress package -DskipTests test: needs: compile runs-on: ${{ matrix.os }} strategy: matrix: os: [ ubuntu-latest, windows-latest ] java: [ '8', '11', '17' ] steps: - uses: actions/checkout@v3 - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@v3 with: distribution: temurin java-version: ${{ matrix.java }} - uses: actions/cache@v3 with: path: ~/.m2/repository key: ${{ matrix.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ matrix.os }}-maven- - name: Build and test with maven # Skip all static checks, they were already done in the compile jobs run: mvn -B --errors --activate-profiles ci --no-transfer-progress package - name: Archive test results and logs # if: success() || failure() to also get the test results on successful runs. if: failure() uses: actions/upload-artifact@v3 with: name: test-results-${{ matrix.java }}-${{ matrix.os }} path: sshd-*/target/surefire-* apache-mina-sshd-46fc8d6/.github/workflows/master-build.yml000066400000000000000000000107531456036076300237720ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # name: master-build on: push: branches: - master jobs: build: uses: ./.github/workflows/build.yml deploy-snapshot: # Skip any commit from creating releases. The first snapshot after a new release # will thus be published on the first real change on the new snapshot version, but # there will be no snapshot release for just bumping the version. if: "!startsWith(github.event.head_commit.message ,'[maven-release-plugin]')" needs: build # Serialize these jobs from different workflow runs. We do not want concurrent # deployments. We don't cancel already running jobs because we do not want their # workflows to report a failure. Github does not guarantee order between jobs # that queue within 5 minutes, see https://docs.github.com/en/actions/using-jobs/using-concurrency . # We do check below that the job is operating on the latest origin/master, and # we skip deployment if not. concurrency: mina-sshd-snapshot-deploy runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up JDK uses: actions/setup-java@v3 with: distribution: temurin java-version: '8' # Create a ~/.m2/settings.xml referencing these environment variable names server-id: 'apache.snapshots.https' server-username: NEXUS_USERNAME server-password: NEXUS_PASSWORD - uses: actions/cache@v3 with: path: ~/.m2/repository key: ubuntu-latest-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ubuntu-latest-maven- - name: Check version (SNAPSHOT) # Only deploy SNAPSHOT versions. We do not use "exit 1" because we still want the workflow # to report success, we just want this job to do nothing. # # All subsequent steps are conditional. run: | export PROJECT_VERSION=$(mvn -B -q -DforceStdout -Dexpression=project.version help:evaluate) echo "Project version: $PROJECT_VERSION" [[ "$PROJECT_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+-SNAPSHOT$ ]] || { echo "**** Skipping deployment because not a snapshot version: $PROJECT_VERSION" 1>&2 echo "SKIP_DEPLOYMENT=true" >> "$GITHUB_ENV" } - name: Check HEAD is current # Must be quoted, ! is special in yaml if: "! env.SKIP_DEPLOYMENT" # Do not deploy if refs/heads/master has advanced in the meantime run : | export CURR_HEAD=$(git rev-parse -q origin/master) echo "Local: github.sha=${{ github.sha }} refs/heads/master=$(git rev-parse -q refs/heads/master)" echo "Origin: origin/master=$CURR_HEAD" [[ "${{ github.sha }}" == "$CURR_HEAD" ]] || { echo "**** Skipping deployment because master branch advanced: ${{ github.sha }} != origin/master $CURR_HEAD" 1>&2 echo "SKIP_DEPLOYMENT=true" >> "$GITHUB_ENV" } - name: Build and deploy with maven # Must be quoted, ! is special in yaml if: "! env.SKIP_DEPLOYMENT" # NEXUS_USERNAME and NEXUS_PASSWORD are used in ~/.m2/settings.xml created by # the setup-java action. The two secrets are organization-wide secrets that # were enabled by Apache Infra for our repository. env: NEXUS_USERNAME: ${{ secrets.NEXUS_USER }} NEXUS_PASSWORD: ${{ secrets.NEXUS_PW }} # Our root POM overwrites the release repository with an invalid value to prevent # accidental release deployments as an additional safety measure. The snapshot # repo from the Apache parent POM is not overridden. run: mvn -B --errors --activate-profiles ci --no-transfer-progress deploy -DskipTests -DdeployAtEnd apache-mina-sshd-46fc8d6/.gitignore000066400000000000000000000007311456036076300172450ustar00rootroot00000000000000target/ Servers/ .metadata/ .recommenders/ .settings/ RemoteSystemsTempFiles/ .classpath .project # Puthon related files .pydevproject *.pyc .checkstyle .eclipse-pmd .pmd *.iml *.ipr *.iws .idea .springBeans .externalToolBuilders # Maven formatter plugin */.cache/ .cache/ # Pre-release temporary files *.releaseBackup release.properties # VS Code .vscode/ *.code-workspace # Serialized objects *.ser # Locks and temporary files *~ .attach_pid* # OSX files .DS_Store apache-mina-sshd-46fc8d6/CHANGES.md000066400000000000000000000017101456036076300166450ustar00rootroot00000000000000# [Version 2.1.0 to 2.2.0](./docs/changes/2.2.0.md) # [Version 2.2.0 to 2.3.0](./docs/changes/2.3.0.md) # [Version 2.3.0 to 2.4.0](./docs/changes/2.4.0.md) # [Version 2.4.0 to 2.5.0](./docs/changes/2.5.0.md) # [Version 2.5.0 to 2.5.1](./docs/changes/2.5.1.md) # [Version 2.5.1 to 2.6.0](./docs/changes/2.6.0.md) # [Version 2.6.0 to 2.7.0](./docs/changes/2.7.0.md) # [Version 2.7.0 to 2.8.0](./docs/changes/2.8.0.md) # [Version 2.8.0 to 2.9.0](./docs/changes/2.9.0.md) # [Version 2.9.0 to 2.9.1](./docs/changes/2.9.1.md) # [Version 2.9.1 to 2.9.2](./docs/changes/2.9.2.md) # [Version 2.9.2 to 2.10.0](./docs/changes/2.10.0.md) # [Version 2.10.0 to 2.11.0](./docs/changes/2.11.0.md) # [Version 2.11.0 to 2.12.0](./docs/changes/2.12.0.md) # [Version 2.12.0 to 2.12.1](./docs/changes/2.12.1.md) # Planned for next version ## Bug Fixes ## New Features ## Behavioral changes and enhancements ## Potential compatibility issues ## Major Code Re-factoring apache-mina-sshd-46fc8d6/LICENSE.txt000066400000000000000000000261371456036076300171100ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. apache-mina-sshd-46fc8d6/NOTICE-bin.txt000066400000000000000000000010041456036076300175370ustar00rootroot00000000000000Apache MINA SSHD Copyright 2008-2021 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). Please refer to each LICENSE..txt file for the license terms of the components that Apache MINA depends on. Message logging is provided by the SLF4J library package, which is open source software, written by Ceki Gülcü, and copyright by SLF4J.ORG and QOS.ch. The original software is available from http://www.slf4j.org/ apache-mina-sshd-46fc8d6/NOTICE.txt000066400000000000000000000004421456036076300167760ustar00rootroot00000000000000Apache MINA SSHD Copyright 2008-2021 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). Please refer to each LICENSE..txt file for the license terms of the components that Apache MINA depends on. apache-mina-sshd-46fc8d6/README.md000066400000000000000000000115441456036076300165400ustar00rootroot00000000000000![Apache MINA SSHD](https://mina.apache.org/assets/img/header-sshd.png "Apache MINA SSHD") # Apache MINA SSHD Apache MINA SSHD is a 100% pure java library to support the SSH protocols on both the client and server side. It does not aim at being a replacement for the SSH client or SSH server from Unix operating systems, but rather provides support for Java based applications requiring SSH support. The library can leverage several I/O back-ends: * The default transport is built-in and uses Java's `AsynchronousSocketChannel`s. * [Apache MINA](https://mina.apache.org), a scalable and high performance asynchronous I/O library, can be used instead, or * the [Netty](https://netty.io) asynchronous event-driven network framework is also supported. # Releases Releases of Apache MINA sshd are available at [Maven Central](https://mvnrepository.com/artifact/org.apache.sshd). `tar.gz` and ZIP source and binary distributions are available at the [Apache MINA sshd](https://mina.apache.org/sshd-project/downloads.html) web site. *Snapshot* releases from the main branch are published on each push or merge on the main branch, if the tests pass successfully. These snapshot releases are available at the [Apache Snapshot](https://repository.apache.org/content/repositories/snapshots) maven repository. ## [Release notes](./CHANGES.md) # Issue reporting Bug reports and improvement or feature requests can be filed at the [GitHub issue tracker](https://github.com/apache/mina-sshd/issues) or at the [Apache issue tracker](https://issues.apache.org/jira/projects/SSHD). Sensitive issues such as security vulnerabilities must be reported through [private channels](./SECURITY.md), not via either issue tracker. # [Supported standards](./docs/standards.md) # Core requirements * Java 8+ (as of version 1.3) * [Slf4j](https://www.slf4j.org/) The code only requires the core abstract [slf4j-api](https://mvnrepository.com/artifact/org.slf4j/slf4j-api) module. The actual implementation of the logging API can be selected from the many existing adaptors. # Basic artifacts structure * *sshd-common* - contains basic classes used throughout the project as well as code that does not require client or server network support. * *sshd-core* - contains the basic SSH client/server code implementing the connection, transport, channels, forwarding, etc.. * *sshd-mina*, *sshd-netty* - replacements for the default NIO2 connector used to establish and manage network connections using [MINA](https://mina.apache.org/mina-project/index.html) and/or [Netty](https://netty.io/) libraries respectively. * *sshd-sftp* - contains the server side SFTP subsystem and the SFTP client code. * *sshd-spring-sftp* - contains a [Spring Integration](https://spring.io/projects/spring-integration) compatible SFTP adapter * *sshd-scp* - contains the server side SCP command handler and the SCP client code. * *sshd-ldap* - contains server-side password and public key authenticators that use an LDAP server. * *sshd-git* - contains replacements for [JGit](https://www.eclipse.org/jgit/) SSH session factory. * *sshd-osgi* - contains an artifact that combines *sshd-common* and *sshd-core* so it can be deployed in OSGi environments. * *sshd-putty* - contains code that can parse [PUTTY](https://www.putty.org/) key files. * *sshd-openpgp* - contains code that can parse [OpenPGP](https://www.openpgp.org/) key files (with some limitations - see relevant section) * *sshd-cli* - contains simple templates for command-line client/server - used to provide look-and-feel similar to the Linux *ssh/sshd* commands. * *sshd-contrib* - **experimental** code that is currently under review and may find its way into one of the other artifacts (or become an entirely new artifact - e.g., *sshd-putty* evolved this way). # [Optional dependencies](./docs/dependencies.md) # Quick reference ## Building the code Including tests ``` mvn clean install ``` Without tests ``` mvn -Pquick clean install ``` ## [Set up an SSH client in 5 minutes](./docs/client-setup.md) ## [Embedding an SSHD server instance in 5 minutes](./docs/server-setup.md) # SSH functionality breakdown ## [Security providers setup](./docs/security-providers.md) ## [Commands infrastructure](./docs/commands.md) ## [SCP](./docs/scp.md) ## [SFTP](./docs/sftp.md) ## [Port forwarding](./docs/port-forwarding.md) ## [Internal support classes](./docs/internals.md) ## [Event listeners and handlers](./docs/event-listeners.md) ## [Command line clients](./docs/cli.md) ## [GIT support](./docs/git.md) ## [Configuration/data files parsing support](./docs/files-parsing.md) ## [Extension modules](./docs/extensions.md) # [HOWTO(s)](./docs/howto.md) # Technical Documentation ## [SSH Key Exchange](./docs/technical/kex.md) ## [TCP/IP Port Forwarding](./docs/technical/tcpip-forwarding.md) ## [Global Requests](./docs/technical/global_requests.md) ## [Android support](./docs/android.md) apache-mina-sshd-46fc8d6/SECURITY.md000066400000000000000000000007331456036076300170500ustar00rootroot00000000000000# Security If you suspect you have found a security vulnerability in [Apache MINA sshd](./README.md) code, please read the [Apache Software Foundation Security Policy](https://www.apache.org/security/) for how to report the issue. Please do _not_ report the details publicly until the report is reviewed and a fixed version has been published. More details are in the description of the [ASF Security Vulnerability Process](https://www.apache.org/security/committers.html). apache-mina-sshd-46fc8d6/assembly/000077500000000000000000000000001456036076300170735ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/assembly/pom.xml000066400000000000000000000202601456036076300204100ustar00rootroot00000000000000 4.0.0 org.apache.sshd sshd 2.12.1 apache-sshd Apache Mina SSHD :: Assembly pom ${project.basedir}/.. org.apache.sshd sshd-common ${project.version} org.apache.sshd sshd-core ${project.version} org.apache.sshd sshd-scp ${project.version} org.apache.sshd sshd-sftp ${project.version} org.apache.sshd sshd-cli ${project.version} org.apache.sshd sshd-mina ${project.version} org.apache.sshd sshd-netty ${project.version} org.apache.sshd sshd-osgi ${project.version} org.apache.sshd sshd-git ${project.version} org.apache.sshd sshd-ldap ${project.version} org.apache.sshd sshd-contrib ${project.version} org.apache.sshd sshd-putty ${project.version} org.apache.sshd sshd-openpgp ${project.version} org.apache.sshd sshd-spring-sftp ${project.version} org.slf4j slf4j-jdk14 org.bouncycastle bcpg-jdk18on org.bouncycastle bcpkix-jdk18on net.i2p.crypto eddsa tomcat tomcat-apr org.apache.maven.plugins maven-assembly-plugin unix-bin package single src/main/descriptors/unix-bin.xml ${project.artifactId}-${project.version} false posix windows-bin package single src/main/descriptors/windows-bin.xml ${project.artifactId}-${project.version} false unix-src package single src/main/descriptors/unix-src.xml posix windows-src package single src/main/descriptors/windows-src.xml org.apache.felix maven-bundle-plugin bundle-manifest none apache-mina-sshd-46fc8d6/assembly/src/000077500000000000000000000000001456036076300176625ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/assembly/src/main/000077500000000000000000000000001456036076300206065ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/assembly/src/main/components/000077500000000000000000000000001456036076300227735ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/assembly/src/main/components/modules.xml000066400000000000000000000067741456036076300252030ustar00rootroot00000000000000 org.apache.sshd:sshd-osgi org.apache.sshd:sshd-git org.apache.sshd:sshd-ldap org.apache.sshd:sshd-contrib org.apache.sshd:sshd-putty org.apache.sshd:sshd-openpgp org.apache.sshd:sshd-spring-sftp org.springframework:* org.springframework.retry:* io.projectreactor:* org.reactivestreams:* commons-io:commons-io org.bouncycastle:* org.springframework.integration:* org.eclipse.jgit:* com.googlecode.javaewah:JavaEWAH org.c02e.jpgpj:jpgpj lib false org.apache.sshd:sshd-osgi org.apache.sshd:sshd-git org.apache.sshd:sshd-ldap org.apache.sshd:sshd-contrib org.apache.sshd:sshd-putty org.apache.sshd:sshd-spring-sftp org.apache.sshd:sshd-openpgp extras false org.springframework:* org.springframework.retry:* org.springframework.integration:* org.eclipse.jgit:* io.projectreactor:* org.reactivestreams:* commons-io:commons-io com.googlecode.javaewah:JavaEWAH org.bouncycastle:* org.c02e.jpgpj:jpgpj dependencies false apache-mina-sshd-46fc8d6/assembly/src/main/descriptors/000077500000000000000000000000001456036076300231475ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/assembly/src/main/descriptors/unix-bin.xml000066400000000000000000000065241456036076300254310ustar00rootroot00000000000000 bin tar.gz ${project.basedir}/src/main/components/modules.xml src/main/distribution unix bin/sshd.sh bin/ssh.sh bin/scp.sh bin/sftp.sh bin/ssh-keyscan.sh .. LICENSE.txt unix src/main/legal/licenses licenses unix ../NOTICE-bin.txt NOTICE.txt unix src/main/distribution/bin/sshd.sh bin/ 0755 unix src/main/distribution/bin/ssh.sh bin/ 0755 unix src/main/distribution/bin/scp.sh bin/ 0755 unix src/main/distribution/bin/sftp.sh bin/ 0755 unix src/main/distribution/bin/ssh-keyscan.sh bin/ 0755 unix apache-mina-sshd-46fc8d6/assembly/src/main/descriptors/unix-src.xml000066400000000000000000000072671456036076300254550ustar00rootroot00000000000000 src tar.gz .. **/*.jpeg **/*.jpg **/*.gif **/*.png **/*.exe **/*.dll **/*.jar **/*.so **/*.ks **/*.ts **/*.keystore **/*.bin **/*.jnilib **/*.cert sshd-openpgp/src/test/resources/**/* **/eclipse-classes/** **/target/** *RemoteSystemsTempFiles* .. **/* **/*.jpeg **/*.jpg **/*.gif **/*.png **/*.exe **/*.dll **/*.jar **/*.so **/*.ks **/*.ts **/*.keystore **/*.bin **/*.jnilib **/*.cert **/target/** **/build/** **/eclipse-classes/** *RemoteSystemsTempFiles* **/.* **/.*/** **/surefire* **/svn-commit* **/*.iml **/*.ipr **/*.iws **/*.ser **/key.pem sshd-core/src/docs/*.txt sshd-openpgp/src/test/resources/**/* unix apache-mina-sshd-46fc8d6/assembly/src/main/descriptors/windows-bin.xml000066400000000000000000000036771456036076300261460ustar00rootroot00000000000000 bin zip ${project.basedir}/src/main/components/modules.xml src/main/distribution dos .. LICENSE.txt dos src/main/legal/licenses licenses dos ../NOTICE-bin.txt NOTICE.txt dos apache-mina-sshd-46fc8d6/assembly/src/main/descriptors/windows-src.xml000066400000000000000000000073361456036076300261610ustar00rootroot00000000000000 src zip .. **/*.jpeg **/*.jpg **/*.gif **/*.png **/*.exe **/*.dll **/*.jar **/*.so **/*.ks **/*.ts **/*.keystore **/*.bin **/*.jnilib **/*.cert sshd-openpgp/src/test/resources/**/* **/eclipse-classes/** **/target/** *RemoteSystemsTempFiles* .. **/* **/*.jpeg **/*.jpg **/*.gif **/*.png **/*.exe **/*.dll **/*.jar **/*.so **/*.ks **/*.ts **/*.keystore **/*.bin **/*.jnilib **/*.cert **/target/** **/build/** **/eclipse-classes/** *RemoteSystemsTempFiles* **/.* **/.*/** **/*.gpg **/surefire* **/svn-commit* **/*.iml **/*.ipr **/*.iws **/*.ser **/key.pem sshd-core/src/docs/*.txt sshd-openpgp/src/test/resources/**/* dos apache-mina-sshd-46fc8d6/assembly/src/main/distribution/000077500000000000000000000000001456036076300233255ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/assembly/src/main/distribution/README.txt000066400000000000000000000040071456036076300250240ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ Welcome to Apache SSHD Apache SSHD is a library to support the SSH2 protocol on both client and server side using pure Java. This distribution provides a simple demonstration of a SSH server and client that you can launched using the shell scripts in the bin folder. By default, the port used is 8000 and the authentication will succeed if the username and password are the same. SCP and SFTP support are both enabled by default in this configuration. The artifacts are distributed as follows: * /bin - contains Linux and Windows scripts that can be used to run the code using the default settings. * /lib - contains all the JAR(s) necessary to run both SSH client and server - including the various supported I/O factories (default is the built-in NIO2), SCP, SFTP, SOCKS, ed25519 support. * /extras - contains various SSH-based or SSH-related extra functionality that is not part of SSH per-se. E.g., JGit, Putty, LDAP, Spring SFTP, various contributions. * /dependencies - contains various required 3rd party artifacts that are used by the extra(s). * /licenses - contains a copy of all the 3rd party artifacts' licenses that are used by this project Please send feedback to users@mina.apache.org. The Apache SSHD team.apache-mina-sshd-46fc8d6/assembly/src/main/distribution/bin/000077500000000000000000000000001456036076300240755ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/assembly/src/main/distribution/bin/scp.bat000066400000000000000000000060501456036076300253530ustar00rootroot00000000000000@echo off rem rem rem Licensed to the Apache Software Foundation (ASF) under one or more rem contributor license agreements. See the NOTICE file distributed with rem this work for additional information regarding copyright ownership. rem The ASF licenses this file to You under the Apache License, Version 2.0 rem (the "License"); you may not use this file except in compliance with rem the License. You may obtain a copy of the License at rem rem http://www.apache.org/licenses/LICENSE-2.0 rem rem Unless required by applicable law or agreed to in writing, software rem distributed under the License is distributed on an "AS IS" BASIS, rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. rem See the License for the specific language governing permissions and rem limitations under the License. rem rem if not "%ECHO%" == "" echo %ECHO% setlocal set DIRNAME=%~dp0% set PROGNAME=%~nx0% set ARGS=%* title scp goto BEGIN :warn echo %PROGNAME%: %* goto :EOF :BEGIN rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if not "%SSHD_HOME%" == "" ( call :warn Ignoring predefined value for SSHD_HOME ) set SSHD_HOME=%DIRNAME%.. if not exist "%SSHD_HOME%" ( call :warn SSHD_HOME is not valid: %SSHD_HOME% goto END ) set DEFAULT_JAVA_OPTS=-server -Xmx512M -Dcom.sun.management.jmxremote set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 rem Support for loading native libraries set PATH=%PATH%;%SSHD_HOME%\lib rem Setup the Java Virtual Machine if not "%JAVA%" == "" goto :Check_JAVA_END set JAVA=java if "%JAVA_HOME%" == "" call :warn JAVA_HOME not set; results may vary if not "%JAVA_HOME%" == "" set JAVA=%JAVA_HOME%\bin\java if not exist "%JAVA_HOME%" ( call :warn JAVA_HOME is not valid: "%JAVA_HOME%" goto END ) :Check_JAVA_END if "%JAVA_OPTS%" == "" set JAVA_OPTS=%DEFAULT_JAVA_OPTS% if "%SSHD_DEBUG%" == "" goto :SSHD_DEBUG_END rem Use the defaults if JAVA_DEBUG_OPTS was not set if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS% set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%" call :warn Enabling Java debug options: %JAVA_DEBUG_OPTS% :SSHD_DEBUG_END rem Setup the classpath set CLASSPATH=%LOCAL_CLASSPATH% pushd "%SSHD_HOME%\lib" for %%G in (*.*) do call:APPEND_TO_CLASSPATH %%G popd goto CLASSPATH_END : APPEND_TO_CLASSPATH set filename=%~1 set suffix=%filename:~-4% if %suffix% equ .jar set CLASSPATH=%CLASSPATH%;%SSHD_HOME%\lib\%filename% goto :EOF :CLASSPATH_END SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8 rem Execute the Java Virtual Machine cd %SSHD_HOME% "%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Dsshd.home="%SSHD_HOME%" org.apache.sshd.cli.client.ScpCommandMain %ARGS% rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # :END endlocal if not "%PAUSE%" == "" pause :END_NO_PAUSE apache-mina-sshd-46fc8d6/assembly/src/main/distribution/bin/scp.sh000066400000000000000000000154721456036076300252270ustar00rootroot00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # DIRNAME=`dirname $0` PROGNAME=`basename $0` # # Check/Set up some easily accessible MIN/MAX params for JVM mem usage # if [ "x$JAVA_MIN_MEM" = "x" ]; then JAVA_MIN_MEM=128M export JAVA_MIN_MEM fi if [ "x$JAVA_MAX_MEM" = "x" ]; then JAVA_MAX_MEM=512M export JAVA_MAX_MEM fi warn() { echo "${PROGNAME}: $*" } die() { warn "$*" exit 1 } maybeSource() { file="$1" if [ -f "$file" ] ; then . $file fi } detectOS() { # OS specific support (must be 'true' or 'false'). cygwin=false; darwin=false; aix=false; os400=false; case "`uname`" in CYGWIN*) cygwin=true ;; Darwin*) darwin=true ;; AIX*) aix=true ;; OS400*) os400=true ;; esac # For AIX, set an environment variable if $aix; then export LDR_CNTRL=MAXDATA=0xB0000000@DSA export IBM_JAVA_HEAPDUMP_TEXT=true echo $LDR_CNTRL fi } unlimitFD() { # Use the maximum available, or set MAX_FD != -1 to use that if [ "x$MAX_FD" = "x" ]; then MAX_FD="maximum" fi # Increase the maximum file descriptors if we can if [ "$os400" = "false" ] && [ "$cygwin" = "false" ]; then MAX_FD_LIMIT=`ulimit -H -n` if [ "$MAX_FD_LIMIT" != 'unlimited' ]; then if [ $? -eq 0 ]; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then # use the system max MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD > /dev/null # echo "ulimit -n" `ulimit -n` if [ $? -ne 0 ]; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query system maximum file descriptor limit: $MAX_FD_LIMIT" fi fi fi } locateHome() { if [ "x$SSHD_HOME" != "x" ]; then warn "Ignoring predefined value for SSHD_HOME" fi # In POSIX shells, CDPATH may cause cd to write to stdout (unset CDPATH) >/dev/null 2>&1 && unset CDPATH SSHD_HOME=`cd $DIRNAME/..; pwd` if [ ! -d "$SSHD_HOME" ]; then die "SSHD_HOME is not valid: $SSHD_HOME" fi } setupNativePath() { # Support for loading native libraries LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$SSHD_BASE/lib:$SSHD_HOME/lib" # For Cygwin, set PATH from LD_LIBRARY_PATH if $cygwin; then LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"` PATH="$PATH;$LD_LIBRARY_PATH" export PATH fi export LD_LIBRARY_PATH } locateJava() { # Setup the Java Virtual Machine if $cygwin ; then [ -n "$JAVA" ] && JAVA=`cygpath --unix "$JAVA"` [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` fi if [ "x$JAVA" = "x" ]; then if [ "x$JAVA_HOME" = "x" ] && [ "$darwin" = "true" ]; then JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home fi if [ "x$JAVA_HOME" != "x" ]; then if [ ! -d "$JAVA_HOME" ]; then die "JAVA_HOME is not valid: $JAVA_HOME" fi JAVA="$JAVA_HOME/bin/java" else warn "JAVA_HOME not set; results may vary" JAVA="java" fi fi } detectJVM() { #echo "`$JAVA -version`" # This service should call `java -version`, # read stdout, and look for hints if $JAVA -version 2>&1 | grep "^IBM" ; then JVM_VENDOR="IBM" # on OS/400, java -version does not contain IBM explicitly elif $os400; then JVM_VENDOR="IBM" else JVM_VENDOR="SUN" fi # echo "JVM vendor is $JVM_VENDOR" } setupDebugOptions() { if [ "x$JAVA_OPTS" = "x" ]; then JAVA_OPTS="$DEFAULT_JAVA_OPTS" fi export JAVA_OPTS # Set Debug options if enabled if [ "x$SSHD_DEBUG" != "x" ]; then # Use the defaults if JAVA_DEBUG_OPTS was not set if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS" fi JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS" warn "Enabling Java debug options: $JAVA_DEBUG_OPTS" fi } setupDefaults() { DEFAULT_JAVA_OPTS="-Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM " #Set the JVM_VENDOR specific JVM flags if [ "$JVM_VENDOR" = "SUN" ]; then DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote" elif [ "$JVM_VENDOR" = "IBM" ]; then if $os400; then DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS" elif $aix; then DEFAULT_JAVA_OPTS="-Xverify:none -Xlp $DEFAULT_JAVA_OPTS" else DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS" fi fi # Add the jars in the lib dir for file in $SSHD_HOME/lib/*.jar do if [ -z "$CLASSPATH" ]; then CLASSPATH="$file" else CLASSPATH="$CLASSPATH:$file" fi done DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" ## ## TODO: Move to conf/profiler/yourkit.{sh|cmd} ## # Uncomment to enable YourKit profiling #DEFAULT_JAVA_DEBUG_OPTS="-Xrunyjpagent" } init() { # Determine if there is special OS handling we must perform detectOS # Unlimit the number of file descriptors if possible unlimitFD # Locate the Sshd home directory locateHome # Setup the native library path setupNativePath # Locate the Java VM to execute locateJava # Determine the JVM vendor detectJVM # Setup default options setupDefaults # Install debug options setupDebugOptions } run() { if $cygwin; then SSHD_HOME=`cygpath --path --windows "$SSHD_HOME"` CLASSPATH=`cygpath --path --windows "$CLASSPATH"` fi cd $SSHD_BASE exec $JAVA $JAVA_OPTS -Dsshd.home="$SSHD_HOME" $OPTS -classpath "$CLASSPATH" org.apache.sshd.cli.client.ScpCommandMain "$@" } main() { init run "$@" } main "$@" apache-mina-sshd-46fc8d6/assembly/src/main/distribution/bin/sftp.bat000066400000000000000000000060501456036076300255420ustar00rootroot00000000000000@echo off rem rem rem Licensed to the Apache Software Foundation (ASF) under one or more rem contributor license agreements. See the NOTICE file distributed with rem this work for additional information regarding copyright ownership. rem The ASF licenses this file to You under the Apache License, Version 2.0 rem (the "License"); you may not use this file except in compliance with rem the License. You may obtain a copy of the License at rem rem http://www.apache.org/licenses/LICENSE-2.0 rem rem Unless required by applicable law or agreed to in writing, software rem distributed under the License is distributed on an "AS IS" BASIS, rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. rem See the License for the specific language governing permissions and rem limitations under the License. rem rem if not "%ECHO%" == "" echo %ECHO% setlocal set DIRNAME=%~dp0% set PROGNAME=%~nx0% set ARGS=%* title sftp goto BEGIN :warn echo %PROGNAME%: %* goto :EOF :BEGIN rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if not "%SSHD_HOME%" == "" ( call :warn Ignoring predefined value for SSHD_HOME ) set SSHD_HOME=%DIRNAME%.. if not exist "%SSHD_HOME%" ( call :warn SSHD_HOME is not valid: %SSHD_HOME% goto END ) set DEFAULT_JAVA_OPTS=-server -Xmx512M -Dcom.sun.management.jmxremote set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 rem Support for loading native libraries set PATH=%PATH%;%SSHD_HOME%\lib rem Setup the Java Virtual Machine if not "%JAVA%" == "" goto :Check_JAVA_END set JAVA=java if "%JAVA_HOME%" == "" call :warn JAVA_HOME not set; results may vary if not "%JAVA_HOME%" == "" set JAVA=%JAVA_HOME%\bin\java if not exist "%JAVA_HOME%" ( call :warn JAVA_HOME is not valid: "%JAVA_HOME%" goto END ) :Check_JAVA_END if "%JAVA_OPTS%" == "" set JAVA_OPTS=%DEFAULT_JAVA_OPTS% if "%SSHD_DEBUG%" == "" goto :SSHD_DEBUG_END rem Use the defaults if JAVA_DEBUG_OPTS was not set if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS% set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%" call :warn Enabling Java debug options: %JAVA_DEBUG_OPTS% :SSHD_DEBUG_END rem Setup the classpath set CLASSPATH=%LOCAL_CLASSPATH% pushd "%SSHD_HOME%\lib" for %%G in (*.*) do call:APPEND_TO_CLASSPATH %%G popd goto CLASSPATH_END : APPEND_TO_CLASSPATH set filename=%~1 set suffix=%filename:~-4% if %suffix% equ .jar set CLASSPATH=%CLASSPATH%;%SSHD_HOME%\lib\%filename% goto :EOF :CLASSPATH_END SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8 rem Execute the Java Virtual Machine cd %SSHD_HOME% "%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Dsshd.home="%SSHD_HOME%" org.apache.sshd.cli.client.SftpCommandMain %ARGS% rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # :END endlocal if not "%PAUSE%" == "" pause :END_NO_PAUSE apache-mina-sshd-46fc8d6/assembly/src/main/distribution/bin/sftp.sh000066400000000000000000000154731456036076300254170ustar00rootroot00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # DIRNAME=`dirname $0` PROGNAME=`basename $0` # # Check/Set up some easily accessible MIN/MAX params for JVM mem usage # if [ "x$JAVA_MIN_MEM" = "x" ]; then JAVA_MIN_MEM=128M export JAVA_MIN_MEM fi if [ "x$JAVA_MAX_MEM" = "x" ]; then JAVA_MAX_MEM=512M export JAVA_MAX_MEM fi warn() { echo "${PROGNAME}: $*" } die() { warn "$*" exit 1 } maybeSource() { file="$1" if [ -f "$file" ] ; then . $file fi } detectOS() { # OS specific support (must be 'true' or 'false'). cygwin=false; darwin=false; aix=false; os400=false; case "`uname`" in CYGWIN*) cygwin=true ;; Darwin*) darwin=true ;; AIX*) aix=true ;; OS400*) os400=true ;; esac # For AIX, set an environment variable if $aix; then export LDR_CNTRL=MAXDATA=0xB0000000@DSA export IBM_JAVA_HEAPDUMP_TEXT=true echo $LDR_CNTRL fi } unlimitFD() { # Use the maximum available, or set MAX_FD != -1 to use that if [ "x$MAX_FD" = "x" ]; then MAX_FD="maximum" fi # Increase the maximum file descriptors if we can if [ "$os400" = "false" ] && [ "$cygwin" = "false" ]; then MAX_FD_LIMIT=`ulimit -H -n` if [ "$MAX_FD_LIMIT" != 'unlimited' ]; then if [ $? -eq 0 ]; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then # use the system max MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD > /dev/null # echo "ulimit -n" `ulimit -n` if [ $? -ne 0 ]; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query system maximum file descriptor limit: $MAX_FD_LIMIT" fi fi fi } locateHome() { if [ "x$SSHD_HOME" != "x" ]; then warn "Ignoring predefined value for SSHD_HOME" fi # In POSIX shells, CDPATH may cause cd to write to stdout (unset CDPATH) >/dev/null 2>&1 && unset CDPATH SSHD_HOME=`cd $DIRNAME/..; pwd` if [ ! -d "$SSHD_HOME" ]; then die "SSHD_HOME is not valid: $SSHD_HOME" fi } setupNativePath() { # Support for loading native libraries LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$SSHD_BASE/lib:$SSHD_HOME/lib" # For Cygwin, set PATH from LD_LIBRARY_PATH if $cygwin; then LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"` PATH="$PATH;$LD_LIBRARY_PATH" export PATH fi export LD_LIBRARY_PATH } locateJava() { # Setup the Java Virtual Machine if $cygwin ; then [ -n "$JAVA" ] && JAVA=`cygpath --unix "$JAVA"` [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` fi if [ "x$JAVA" = "x" ]; then if [ "x$JAVA_HOME" = "x" ] && [ "$darwin" = "true" ]; then JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home fi if [ "x$JAVA_HOME" != "x" ]; then if [ ! -d "$JAVA_HOME" ]; then die "JAVA_HOME is not valid: $JAVA_HOME" fi JAVA="$JAVA_HOME/bin/java" else warn "JAVA_HOME not set; results may vary" JAVA="java" fi fi } detectJVM() { #echo "`$JAVA -version`" # This service should call `java -version`, # read stdout, and look for hints if $JAVA -version 2>&1 | grep "^IBM" ; then JVM_VENDOR="IBM" # on OS/400, java -version does not contain IBM explicitly elif $os400; then JVM_VENDOR="IBM" else JVM_VENDOR="SUN" fi # echo "JVM vendor is $JVM_VENDOR" } setupDebugOptions() { if [ "x$JAVA_OPTS" = "x" ]; then JAVA_OPTS="$DEFAULT_JAVA_OPTS" fi export JAVA_OPTS # Set Debug options if enabled if [ "x$SSHD_DEBUG" != "x" ]; then # Use the defaults if JAVA_DEBUG_OPTS was not set if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS" fi JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS" warn "Enabling Java debug options: $JAVA_DEBUG_OPTS" fi } setupDefaults() { DEFAULT_JAVA_OPTS="-Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM " #Set the JVM_VENDOR specific JVM flags if [ "$JVM_VENDOR" = "SUN" ]; then DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote" elif [ "$JVM_VENDOR" = "IBM" ]; then if $os400; then DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS" elif $aix; then DEFAULT_JAVA_OPTS="-Xverify:none -Xlp $DEFAULT_JAVA_OPTS" else DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS" fi fi # Add the jars in the lib dir for file in $SSHD_HOME/lib/*.jar do if [ -z "$CLASSPATH" ]; then CLASSPATH="$file" else CLASSPATH="$CLASSPATH:$file" fi done DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005" ## ## TODO: Move to conf/profiler/yourkit.{sh|cmd} ## # Uncomment to enable YourKit profiling #DEFAULT_JAVA_DEBUG_OPTS="-Xrunyjpagent" } init() { # Determine if there is special OS handling we must perform detectOS # Unlimit the number of file descriptors if possible unlimitFD # Locate the Sshd home directory locateHome # Setup the native library path setupNativePath # Locate the Java VM to execute locateJava # Determine the JVM vendor detectJVM # Setup default options setupDefaults # Install debug options setupDebugOptions } run() { if $cygwin; then SSHD_HOME=`cygpath --path --windows "$SSHD_HOME"` CLASSPATH=`cygpath --path --windows "$CLASSPATH"` fi cd $SSHD_BASE exec $JAVA $JAVA_OPTS -Dsshd.home="$SSHD_HOME" $OPTS -classpath "$CLASSPATH" org.apache.sshd.cli.client.SftpCommandMain "$@" } main() { init run "$@" } main "$@" apache-mina-sshd-46fc8d6/assembly/src/main/distribution/bin/ssh-keyscan.bat000066400000000000000000000060501456036076300270160ustar00rootroot00000000000000@echo off rem rem rem Licensed to the Apache Software Foundation (ASF) under one or more rem contributor license agreements. See the NOTICE file distributed with rem this work for additional information regarding copyright ownership. rem The ASF licenses this file to You under the Apache License, Version 2.0 rem (the "License"); you may not use this file except in compliance with rem the License. You may obtain a copy of the License at rem rem http://www.apache.org/licenses/LICENSE-2.0 rem rem Unless required by applicable law or agreed to in writing, software rem distributed under the License is distributed on an "AS IS" BASIS, rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. rem See the License for the specific language governing permissions and rem limitations under the License. rem rem if not "%ECHO%" == "" echo %ECHO% setlocal set DIRNAME=%~dp0% set PROGNAME=%~nx0% set ARGS=%* title scp goto BEGIN :warn echo %PROGNAME%: %* goto :EOF :BEGIN rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if not "%SSHD_HOME%" == "" ( call :warn Ignoring predefined value for SSHD_HOME ) set SSHD_HOME=%DIRNAME%.. if not exist "%SSHD_HOME%" ( call :warn SSHD_HOME is not valid: %SSHD_HOME% goto END ) set DEFAULT_JAVA_OPTS=-server -Xmx512M -Dcom.sun.management.jmxremote set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 rem Support for loading native libraries set PATH=%PATH%;%SSHD_HOME%\lib rem Setup the Java Virtual Machine if not "%JAVA%" == "" goto :Check_JAVA_END set JAVA=java if "%JAVA_HOME%" == "" call :warn JAVA_HOME not set; results may vary if not "%JAVA_HOME%" == "" set JAVA=%JAVA_HOME%\bin\java if not exist "%JAVA_HOME%" ( call :warn JAVA_HOME is not valid: "%JAVA_HOME%" goto END ) :Check_JAVA_END if "%JAVA_OPTS%" == "" set JAVA_OPTS=%DEFAULT_JAVA_OPTS% if "%SSHD_DEBUG%" == "" goto :SSHD_DEBUG_END rem Use the defaults if JAVA_DEBUG_OPTS was not set if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS% set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%" call :warn Enabling Java debug options: %JAVA_DEBUG_OPTS% :SSHD_DEBUG_END rem Setup the classpath set CLASSPATH=%LOCAL_CLASSPATH% pushd "%SSHD_HOME%\lib" for %%G in (*.*) do call:APPEND_TO_CLASSPATH %%G popd goto CLASSPATH_END : APPEND_TO_CLASSPATH set filename=%~1 set suffix=%filename:~-4% if %suffix% equ .jar set CLASSPATH=%CLASSPATH%;%SSHD_HOME%\lib\%filename% goto :EOF :CLASSPATH_END SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8 rem Execute the Java Virtual Machine cd %SSHD_HOME% "%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Dsshd.home="%SSHD_HOME%" org.apache.sshd.cli.client.SshKeyScanMain %ARGS% rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # :END endlocal if not "%PAUSE%" == "" pause :END_NO_PAUSE apache-mina-sshd-46fc8d6/assembly/src/main/distribution/bin/ssh-keyscan.sh000066400000000000000000000154721456036076300266720ustar00rootroot00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # DIRNAME=`dirname $0` PROGNAME=`basename $0` # # Check/Set up some easily accessible MIN/MAX params for JVM mem usage # if [ "x$JAVA_MIN_MEM" = "x" ]; then JAVA_MIN_MEM=128M export JAVA_MIN_MEM fi if [ "x$JAVA_MAX_MEM" = "x" ]; then JAVA_MAX_MEM=512M export JAVA_MAX_MEM fi warn() { echo "${PROGNAME}: $*" } die() { warn "$*" exit 1 } maybeSource() { file="$1" if [ -f "$file" ] ; then . $file fi } detectOS() { # OS specific support (must be 'true' or 'false'). cygwin=false; darwin=false; aix=false; os400=false; case "`uname`" in CYGWIN*) cygwin=true ;; Darwin*) darwin=true ;; AIX*) aix=true ;; OS400*) os400=true ;; esac # For AIX, set an environment variable if $aix; then export LDR_CNTRL=MAXDATA=0xB0000000@DSA export IBM_JAVA_HEAPDUMP_TEXT=true echo $LDR_CNTRL fi } unlimitFD() { # Use the maximum available, or set MAX_FD != -1 to use that if [ "x$MAX_FD" = "x" ]; then MAX_FD="maximum" fi # Increase the maximum file descriptors if we can if [ "$os400" = "false" ] && [ "$cygwin" = "false" ]; then MAX_FD_LIMIT=`ulimit -H -n` if [ "$MAX_FD_LIMIT" != 'unlimited' ]; then if [ $? -eq 0 ]; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then # use the system max MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD > /dev/null # echo "ulimit -n" `ulimit -n` if [ $? -ne 0 ]; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query system maximum file descriptor limit: $MAX_FD_LIMIT" fi fi fi } locateHome() { if [ "x$SSHD_HOME" != "x" ]; then warn "Ignoring predefined value for SSHD_HOME" fi # In POSIX shells, CDPATH may cause cd to write to stdout (unset CDPATH) >/dev/null 2>&1 && unset CDPATH SSHD_HOME=`cd $DIRNAME/..; pwd` if [ ! -d "$SSHD_HOME" ]; then die "SSHD_HOME is not valid: $SSHD_HOME" fi } setupNativePath() { # Support for loading native libraries LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$SSHD_BASE/lib:$SSHD_HOME/lib" # For Cygwin, set PATH from LD_LIBRARY_PATH if $cygwin; then LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"` PATH="$PATH;$LD_LIBRARY_PATH" export PATH fi export LD_LIBRARY_PATH } locateJava() { # Setup the Java Virtual Machine if $cygwin ; then [ -n "$JAVA" ] && JAVA=`cygpath --unix "$JAVA"` [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` fi if [ "x$JAVA" = "x" ]; then if [ "x$JAVA_HOME" = "x" ] && [ "$darwin" = "true" ]; then JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home fi if [ "x$JAVA_HOME" != "x" ]; then if [ ! -d "$JAVA_HOME" ]; then die "JAVA_HOME is not valid: $JAVA_HOME" fi JAVA="$JAVA_HOME/bin/java" else warn "JAVA_HOME not set; results may vary" JAVA="java" fi fi } detectJVM() { #echo "`$JAVA -version`" # This service should call `java -version`, # read stdout, and look for hints if $JAVA -version 2>&1 | grep "^IBM" ; then JVM_VENDOR="IBM" # on OS/400, java -version does not contain IBM explicitly elif $os400; then JVM_VENDOR="IBM" else JVM_VENDOR="SUN" fi # echo "JVM vendor is $JVM_VENDOR" } setupDebugOptions() { if [ "x$JAVA_OPTS" = "x" ]; then JAVA_OPTS="$DEFAULT_JAVA_OPTS" fi export JAVA_OPTS # Set Debug options if enabled if [ "x$SSHD_DEBUG" != "x" ]; then # Use the defaults if JAVA_DEBUG_OPTS was not set if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS" fi JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS" warn "Enabling Java debug options: $JAVA_DEBUG_OPTS" fi } setupDefaults() { DEFAULT_JAVA_OPTS="-Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM " #Set the JVM_VENDOR specific JVM flags if [ "$JVM_VENDOR" = "SUN" ]; then DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote" elif [ "$JVM_VENDOR" = "IBM" ]; then if $os400; then DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS" elif $aix; then DEFAULT_JAVA_OPTS="-Xverify:none -Xlp $DEFAULT_JAVA_OPTS" else DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS" fi fi # Add the jars in the lib dir for file in $SSHD_HOME/lib/*.jar do if [ -z "$CLASSPATH" ]; then CLASSPATH="$file" else CLASSPATH="$CLASSPATH:$file" fi done DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005" ## ## TODO: Move to conf/profiler/yourkit.{sh|cmd} ## # Uncomment to enable YourKit profiling #DEFAULT_JAVA_DEBUG_OPTS="-Xrunyjpagent" } init() { # Determine if there is special OS handling we must perform detectOS # Unlimit the number of file descriptors if possible unlimitFD # Locate the Sshd home directory locateHome # Setup the native library path setupNativePath # Locate the Java VM to execute locateJava # Determine the JVM vendor detectJVM # Setup default options setupDefaults # Install debug options setupDebugOptions } run() { if $cygwin; then SSHD_HOME=`cygpath --path --windows "$SSHD_HOME"` CLASSPATH=`cygpath --path --windows "$CLASSPATH"` fi cd $SSHD_BASE exec $JAVA $JAVA_OPTS -Dsshd.home="$SSHD_HOME" $OPTS -classpath "$CLASSPATH" org.apache.sshd.cli.client.SshKeyScanMain "$@" } main() { init run "$@" } main "$@" apache-mina-sshd-46fc8d6/assembly/src/main/distribution/bin/ssh.bat000066400000000000000000000060471456036076300253710ustar00rootroot00000000000000@echo off rem rem rem Licensed to the Apache Software Foundation (ASF) under one or more rem contributor license agreements. See the NOTICE file distributed with rem this work for additional information regarding copyright ownership. rem The ASF licenses this file to You under the Apache License, Version 2.0 rem (the "License"); you may not use this file except in compliance with rem the License. You may obtain a copy of the License at rem rem http://www.apache.org/licenses/LICENSE-2.0 rem rem Unless required by applicable law or agreed to in writing, software rem distributed under the License is distributed on an "AS IS" BASIS, rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. rem See the License for the specific language governing permissions and rem limitations under the License. rem rem if not "%ECHO%" == "" echo %ECHO% setlocal set DIRNAME=%~dp0% set PROGNAME=%~nx0% set ARGS=%* title ssh goto BEGIN :warn echo %PROGNAME%: %* goto :EOF :BEGIN rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if not "%SSHD_HOME%" == "" ( call :warn Ignoring predefined value for SSHD_HOME ) set SSHD_HOME=%DIRNAME%.. if not exist "%SSHD_HOME%" ( call :warn SSHD_HOME is not valid: %SSHD_HOME% goto END ) set DEFAULT_JAVA_OPTS=-server -Xmx512M -Dcom.sun.management.jmxremote set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 rem Support for loading native libraries set PATH=%PATH%;%SSHD_HOME%\lib rem Setup the Java Virtual Machine if not "%JAVA%" == "" goto :Check_JAVA_END set JAVA=java if "%JAVA_HOME%" == "" call :warn JAVA_HOME not set; results may vary if not "%JAVA_HOME%" == "" set JAVA=%JAVA_HOME%\bin\java if not exist "%JAVA_HOME%" ( call :warn JAVA_HOME is not valid: "%JAVA_HOME%" goto END ) :Check_JAVA_END if "%JAVA_OPTS%" == "" set JAVA_OPTS=%DEFAULT_JAVA_OPTS% if "%SSHD_DEBUG%" == "" goto :SSHD_DEBUG_END rem Use the defaults if JAVA_DEBUG_OPTS was not set if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS% set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%" call :warn Enabling Java debug options: %JAVA_DEBUG_OPTS% :SSHD_DEBUG_END rem Setup the classpath set CLASSPATH=%LOCAL_CLASSPATH% pushd "%SSHD_HOME%\lib" for %%G in (*.*) do call:APPEND_TO_CLASSPATH %%G popd goto CLASSPATH_END : APPEND_TO_CLASSPATH set filename=%~1 set suffix=%filename:~-4% if %suffix% equ .jar set CLASSPATH=%CLASSPATH%;%SSHD_HOME%\lib\%filename% goto :EOF :CLASSPATH_END SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8 rem Execute the Java Virtual Machine cd %SSHD_HOME% "%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Dsshd.home="%SSHD_HOME%" org.apache.sshd.cli.client.SshClientMain %ARGS% rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # :END endlocal if not "%PAUSE%" == "" pause :END_NO_PAUSE apache-mina-sshd-46fc8d6/assembly/src/main/distribution/bin/ssh.sh000066400000000000000000000154711456036076300252360ustar00rootroot00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # DIRNAME=`dirname $0` PROGNAME=`basename $0` # # Check/Set up some easily accessible MIN/MAX params for JVM mem usage # if [ "x$JAVA_MIN_MEM" = "x" ]; then JAVA_MIN_MEM=128M export JAVA_MIN_MEM fi if [ "x$JAVA_MAX_MEM" = "x" ]; then JAVA_MAX_MEM=512M export JAVA_MAX_MEM fi warn() { echo "${PROGNAME}: $*" } die() { warn "$*" exit 1 } maybeSource() { file="$1" if [ -f "$file" ] ; then . $file fi } detectOS() { # OS specific support (must be 'true' or 'false'). cygwin=false; darwin=false; aix=false; os400=false; case "`uname`" in CYGWIN*) cygwin=true ;; Darwin*) darwin=true ;; AIX*) aix=true ;; OS400*) os400=true ;; esac # For AIX, set an environment variable if $aix; then export LDR_CNTRL=MAXDATA=0xB0000000@DSA export IBM_JAVA_HEAPDUMP_TEXT=true echo $LDR_CNTRL fi } unlimitFD() { # Use the maximum available, or set MAX_FD != -1 to use that if [ "x$MAX_FD" = "x" ]; then MAX_FD="maximum" fi # Increase the maximum file descriptors if we can if [ "$os400" = "false" ] && [ "$cygwin" = "false" ]; then MAX_FD_LIMIT=`ulimit -H -n` if [ "$MAX_FD_LIMIT" != 'unlimited' ]; then if [ $? -eq 0 ]; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then # use the system max MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD > /dev/null # echo "ulimit -n" `ulimit -n` if [ $? -ne 0 ]; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query system maximum file descriptor limit: $MAX_FD_LIMIT" fi fi fi } locateHome() { if [ "x$SSHD_HOME" != "x" ]; then warn "Ignoring predefined value for SSHD_HOME" fi # In POSIX shells, CDPATH may cause cd to write to stdout (unset CDPATH) >/dev/null 2>&1 && unset CDPATH SSHD_HOME=`cd $DIRNAME/..; pwd` if [ ! -d "$SSHD_HOME" ]; then die "SSHD_HOME is not valid: $SSHD_HOME" fi } setupNativePath() { # Support for loading native libraries LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$SSHD_BASE/lib:$SSHD_HOME/lib" # For Cygwin, set PATH from LD_LIBRARY_PATH if $cygwin; then LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"` PATH="$PATH;$LD_LIBRARY_PATH" export PATH fi export LD_LIBRARY_PATH } locateJava() { # Setup the Java Virtual Machine if $cygwin ; then [ -n "$JAVA" ] && JAVA=`cygpath --unix "$JAVA"` [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` fi if [ "x$JAVA" = "x" ]; then if [ "x$JAVA_HOME" = "x" ] && [ "$darwin" = "true" ]; then JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home fi if [ "x$JAVA_HOME" != "x" ]; then if [ ! -d "$JAVA_HOME" ]; then die "JAVA_HOME is not valid: $JAVA_HOME" fi JAVA="$JAVA_HOME/bin/java" else warn "JAVA_HOME not set; results may vary" JAVA="java" fi fi } detectJVM() { #echo "`$JAVA -version`" # This service should call `java -version`, # read stdout, and look for hints if $JAVA -version 2>&1 | grep "^IBM" ; then JVM_VENDOR="IBM" # on OS/400, java -version does not contain IBM explicitly elif $os400; then JVM_VENDOR="IBM" else JVM_VENDOR="SUN" fi # echo "JVM vendor is $JVM_VENDOR" } setupDebugOptions() { if [ "x$JAVA_OPTS" = "x" ]; then JAVA_OPTS="$DEFAULT_JAVA_OPTS" fi export JAVA_OPTS # Set Debug options if enabled if [ "x$SSHD_DEBUG" != "x" ]; then # Use the defaults if JAVA_DEBUG_OPTS was not set if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS" fi JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS" warn "Enabling Java debug options: $JAVA_DEBUG_OPTS" fi } setupDefaults() { DEFAULT_JAVA_OPTS="-Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM " #Set the JVM_VENDOR specific JVM flags if [ "$JVM_VENDOR" = "SUN" ]; then DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote" elif [ "$JVM_VENDOR" = "IBM" ]; then if $os400; then DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS" elif $aix; then DEFAULT_JAVA_OPTS="-Xverify:none -Xlp $DEFAULT_JAVA_OPTS" else DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS" fi fi # Add the jars in the lib dir for file in $SSHD_HOME/lib/*.jar do if [ -z "$CLASSPATH" ]; then CLASSPATH="$file" else CLASSPATH="$CLASSPATH:$file" fi done DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005" ## ## TODO: Move to conf/profiler/yourkit.{sh|cmd} ## # Uncomment to enable YourKit profiling #DEFAULT_JAVA_DEBUG_OPTS="-Xrunyjpagent" } init() { # Determine if there is special OS handling we must perform detectOS # Unlimit the number of file descriptors if possible unlimitFD # Locate the Sshd home directory locateHome # Setup the native library path setupNativePath # Locate the Java VM to execute locateJava # Determine the JVM vendor detectJVM # Setup default options setupDefaults # Install debug options setupDebugOptions } run() { if $cygwin; then SSHD_HOME=`cygpath --path --windows "$SSHD_HOME"` CLASSPATH=`cygpath --path --windows "$CLASSPATH"` fi cd $SSHD_BASE exec $JAVA $JAVA_OPTS -Dsshd.home="$SSHD_HOME" $OPTS -classpath "$CLASSPATH" org.apache.sshd.cli.client.SshClientMain "$@" } main() { init run "$@" } main "$@" apache-mina-sshd-46fc8d6/assembly/src/main/distribution/bin/sshd.bat000066400000000000000000000060501456036076300255270ustar00rootroot00000000000000@echo off rem rem rem Licensed to the Apache Software Foundation (ASF) under one or more rem contributor license agreements. See the NOTICE file distributed with rem this work for additional information regarding copyright ownership. rem The ASF licenses this file to You under the Apache License, Version 2.0 rem (the "License"); you may not use this file except in compliance with rem the License. You may obtain a copy of the License at rem rem http://www.apache.org/licenses/LICENSE-2.0 rem rem Unless required by applicable law or agreed to in writing, software rem distributed under the License is distributed on an "AS IS" BASIS, rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. rem See the License for the specific language governing permissions and rem limitations under the License. rem rem if not "%ECHO%" == "" echo %ECHO% setlocal set DIRNAME=%~dp0% set PROGNAME=%~nx0% set ARGS=%* title sshd goto BEGIN :warn echo %PROGNAME%: %* goto :EOF :BEGIN rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # if not "%SSHD_HOME%" == "" ( call :warn Ignoring predefined value for SSHD_HOME ) set SSHD_HOME=%DIRNAME%.. if not exist "%SSHD_HOME%" ( call :warn SSHD_HOME is not valid: %SSHD_HOME% goto END ) set DEFAULT_JAVA_OPTS=-server -Xmx512M -Dcom.sun.management.jmxremote set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 rem Support for loading native libraries set PATH=%PATH%;%SSHD_HOME%\lib rem Setup the Java Virtual Machine if not "%JAVA%" == "" goto :Check_JAVA_END set JAVA=java if "%JAVA_HOME%" == "" call :warn JAVA_HOME not set; results may vary if not "%JAVA_HOME%" == "" set JAVA=%JAVA_HOME%\bin\java if not exist "%JAVA_HOME%" ( call :warn JAVA_HOME is not valid: "%JAVA_HOME%" goto END ) :Check_JAVA_END if "%JAVA_OPTS%" == "" set JAVA_OPTS=%DEFAULT_JAVA_OPTS% if "%SSHD_DEBUG%" == "" goto :SSHD_DEBUG_END rem Use the defaults if JAVA_DEBUG_OPTS was not set if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS% set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%" call :warn Enabling Java debug options: %JAVA_DEBUG_OPTS% :SSHD_DEBUG_END rem Setup the classpath set CLASSPATH=%LOCAL_CLASSPATH% pushd "%SSHD_HOME%\lib" for %%G in (*.*) do call:APPEND_TO_CLASSPATH %%G popd goto CLASSPATH_END : APPEND_TO_CLASSPATH set filename=%~1 set suffix=%filename:~-4% if %suffix% equ .jar set CLASSPATH=%CLASSPATH%;%SSHD_HOME%\lib\%filename% goto :EOF :CLASSPATH_END SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8 rem Execute the Java Virtual Machine cd %SSHD_HOME% "%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Dsshd.home="%SSHD_HOME%" org.apache.sshd.cli.server.SshServerMain %ARGS% rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # :END endlocal if not "%PAUSE%" == "" pause :END_NO_PAUSE apache-mina-sshd-46fc8d6/assembly/src/main/distribution/bin/sshd.sh000066400000000000000000000154711456036076300254020ustar00rootroot00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # DIRNAME=`dirname $0` PROGNAME=`basename $0` # # Check/Set up some easily accessible MIN/MAX params for JVM mem usage # if [ "x$JAVA_MIN_MEM" = "x" ]; then JAVA_MIN_MEM=128M export JAVA_MIN_MEM fi if [ "x$JAVA_MAX_MEM" = "x" ]; then JAVA_MAX_MEM=512M export JAVA_MAX_MEM fi warn() { echo "${PROGNAME}: $*" } die() { warn "$*" exit 1 } maybeSource() { file="$1" if [ -f "$file" ] ; then . $file fi } detectOS() { # OS specific support (must be 'true' or 'false'). cygwin=false; darwin=false; aix=false; os400=false; case "`uname`" in CYGWIN*) cygwin=true ;; Darwin*) darwin=true ;; AIX*) aix=true ;; OS400*) os400=true ;; esac # For AIX, set an environment variable if $aix; then export LDR_CNTRL=MAXDATA=0xB0000000@DSA export IBM_JAVA_HEAPDUMP_TEXT=true echo $LDR_CNTRL fi } unlimitFD() { # Use the maximum available, or set MAX_FD != -1 to use that if [ "x$MAX_FD" = "x" ]; then MAX_FD="maximum" fi # Increase the maximum file descriptors if we can if [ "$os400" = "false" ] && [ "$cygwin" = "false" ]; then MAX_FD_LIMIT=`ulimit -H -n` if [ "$MAX_FD_LIMIT" != 'unlimited' ]; then if [ $? -eq 0 ]; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then # use the system max MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD > /dev/null # echo "ulimit -n" `ulimit -n` if [ $? -ne 0 ]; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query system maximum file descriptor limit: $MAX_FD_LIMIT" fi fi fi } locateHome() { if [ "x$SSHD_HOME" != "x" ]; then warn "Ignoring predefined value for SSHD_HOME" fi # In POSIX shells, CDPATH may cause cd to write to stdout (unset CDPATH) >/dev/null 2>&1 && unset CDPATH SSHD_HOME=`cd $DIRNAME/..; pwd` if [ ! -d "$SSHD_HOME" ]; then die "SSHD_HOME is not valid: $SSHD_HOME" fi } setupNativePath() { # Support for loading native libraries LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$SSHD_BASE/lib:$SSHD_HOME/lib" # For Cygwin, set PATH from LD_LIBRARY_PATH if $cygwin; then LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"` PATH="$PATH;$LD_LIBRARY_PATH" export PATH fi export LD_LIBRARY_PATH } locateJava() { # Setup the Java Virtual Machine if $cygwin ; then [ -n "$JAVA" ] && JAVA=`cygpath --unix "$JAVA"` [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` fi if [ "x$JAVA" = "x" ]; then if [ "x$JAVA_HOME" = "x" ] && [ "$darwin" = "true" ]; then JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home fi if [ "x$JAVA_HOME" != "x" ]; then if [ ! -d "$JAVA_HOME" ]; then die "JAVA_HOME is not valid: $JAVA_HOME" fi JAVA="$JAVA_HOME/bin/java" else warn "JAVA_HOME not set; results may vary" JAVA="java" fi fi } detectJVM() { #echo "`$JAVA -version`" # This service should call `java -version`, # read stdout, and look for hints if $JAVA -version 2>&1 | grep "^IBM" ; then JVM_VENDOR="IBM" # on OS/400, java -version does not contain IBM explicitly elif $os400; then JVM_VENDOR="IBM" else JVM_VENDOR="SUN" fi # echo "JVM vendor is $JVM_VENDOR" } setupDebugOptions() { if [ "x$JAVA_OPTS" = "x" ]; then JAVA_OPTS="$DEFAULT_JAVA_OPTS" fi export JAVA_OPTS # Set Debug options if enabled if [ "x$SSHD_DEBUG" != "x" ]; then # Use the defaults if JAVA_DEBUG_OPTS was not set if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS" fi JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS" warn "Enabling Java debug options: $JAVA_DEBUG_OPTS" fi } setupDefaults() { DEFAULT_JAVA_OPTS="-Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM " #Set the JVM_VENDOR specific JVM flags if [ "$JVM_VENDOR" = "SUN" ]; then DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote" elif [ "$JVM_VENDOR" = "IBM" ]; then if $os400; then DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS" elif $aix; then DEFAULT_JAVA_OPTS="-Xverify:none -Xlp $DEFAULT_JAVA_OPTS" else DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS" fi fi # Add the jars in the lib dir for file in $SSHD_HOME/lib/*.jar do if [ -z "$CLASSPATH" ]; then CLASSPATH="$file" else CLASSPATH="$CLASSPATH:$file" fi done DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005" ## ## TODO: Move to conf/profiler/yourkit.{sh|cmd} ## # Uncomment to enable YourKit profiling #DEFAULT_JAVA_DEBUG_OPTS="-Xrunyjpagent" } init() { # Determine if there is special OS handling we must perform detectOS # Unlimit the number of file descriptors if possible unlimitFD # Locate the Sshd home directory locateHome # Setup the native library path setupNativePath # Locate the Java VM to execute locateJava # Determine the JVM vendor detectJVM # Setup default options setupDefaults # Install debug options setupDebugOptions } run() { if $cygwin; then SSHD_HOME=`cygpath --path --windows "$SSHD_HOME"` CLASSPATH=`cygpath --path --windows "$CLASSPATH"` fi cd $SSHD_BASE exec $JAVA $JAVA_OPTS -Dsshd.home="$SSHD_HOME" $OPTS -classpath "$CLASSPATH" org.apache.sshd.cli.server.SshServerMain "$@" } main() { init run "$@" } main "$@" apache-mina-sshd-46fc8d6/assembly/src/main/legal/000077500000000000000000000000001456036076300216725ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/assembly/src/main/legal/licenses/000077500000000000000000000000001456036076300234775ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/assembly/src/main/legal/licenses/bouncycastle.txt000066400000000000000000000021301456036076300267270ustar00rootroot00000000000000Copyright (c) 2000 - 2017 The Legion Of The Bouncy Castle (http://www.bouncycastle.org) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. apache-mina-sshd-46fc8d6/assembly/src/main/legal/licenses/eddsa.txt000066400000000000000000002140461456036076300253270ustar00rootroot00000000000000 ed25519-java/LICENSE.txt at master · str4d/ed25519-java · GitHub
Permalink
Switch branches/tags
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
124 lines (110 sloc) 6.97 KB
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
For more information, please see https://creativecommons.org/publicdomain/zero/1.0/
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.
apache-mina-sshd-46fc8d6/assembly/src/main/legal/licenses/jbcrypt.txt000066400000000000000000000015041456036076300257150ustar00rootroot00000000000000jBCrypt is subject to the following license: /* * Copyright (c) 2006 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ apache-mina-sshd-46fc8d6/assembly/src/main/legal/licenses/jgit.txt000066400000000000000000000032641456036076300252020ustar00rootroot00000000000000This program and the accompanying materials are made available under the terms of the Eclipse Distribution License v1.0 which accompanies this distribution, is reproduced below, and is available at http://www.eclipse.org/org/documents/edl-v10.php All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the Eclipse Foundation, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. apache-mina-sshd-46fc8d6/assembly/src/main/legal/licenses/jpam.txt000066400000000000000000000011411456036076300251640ustar00rootroot00000000000000/** * Copyright 2003-2006 Greg Luck * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ apache-mina-sshd-46fc8d6/assembly/src/main/legal/licenses/jpgpj.txt000066400000000000000000000020621456036076300253520ustar00rootroot00000000000000The MIT License Copyright (c) 2016 Justin Ludwig Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. apache-mina-sshd-46fc8d6/assembly/src/main/legal/licenses/mina.txt000066400000000000000000000261361456036076300251740ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. apache-mina-sshd-46fc8d6/assembly/src/main/legal/licenses/netty.txt000066400000000000000000005764321456036076300254240ustar00rootroot00000000000000 netty/LICENSE.txt at 4.1 · netty/netty · GitHub
Permalink
Switch branches/tags
netty-5.0.0.Alpha2 netty-5.0.0.Alpha1 netty-4.1.30.Final netty-4.1.29.Final netty-4.1.28.Final netty-4.1.27.Final netty-4.1.26.Final netty-4.1.25.Final netty-4.1.24.Final netty-4.1.23.Final netty-4.1.22.Final netty-4.1.21.Final netty-4.1.20.Final netty-4.1.19.Final netty-4.1.18.Final netty-4.1.17.Final netty-4.1.16.Final netty-4.1.15.Final netty-4.1.14.Final netty-4.1.13.Final netty-4.1.12.Final netty-4.1.11.Final netty-4.1.10.Final netty-4.1.9.Final netty-4.1.8.Final netty-4.1.7.Final netty-4.1.6.Final netty-4.1.5.Final netty-4.1.4.Final netty-4.1.3.Final netty-4.1.2.Final netty-4.1.1.Final netty-4.1.0.Final netty-4.1.0.CR7 netty-4.1.0.CR6 netty-4.1.0.CR5 netty-4.1.0.CR4 netty-4.1.0.CR3 netty-4.1.0.CR2 netty-4.1.0.CR1 netty-4.1.0.Beta8 netty-4.1.0.Beta7 netty-4.1.0.Beta6 netty-4.1.0.Beta5 netty-4.1.0.Beta4 netty-4.1.0.Beta3 netty-4.1.0.Beta2 netty-4.1.0.Beta1 netty-4.0.56.Final netty-4.0.55.Final netty-4.0.54.Final netty-4.0.53.Final netty-4.0.52.Final netty-4.0.51.Final netty-4.0.50.Final netty-4.0.49.Final netty-4.0.48.Final netty-4.0.47.Final netty-4.0.46.Final netty-4.0.45.Final netty-4.0.44.Final netty-4.0.43.Final netty-4.0.42.Final netty-4.0.41.Final netty-4.0.40.Final netty-4.0.39.Final netty-4.0.38.Final netty-4.0.37.Final netty-4.0.36.Final netty-4.0.35.Final netty-4.0.34.Final netty-4.0.33.Final netty-4.0.32.Final netty-4.0.31.Final netty-4.0.30.Final netty-4.0.29.Final netty-4.0.28.Final netty-4.0.27.Final netty-4.0.26.Final netty-4.0.25.Final netty-4.0.24.Final netty-4.0.23.Final netty-4.0.22.Final netty-4.0.21.Final netty-4.0.20.Final netty-4.0.19.Final netty-4.0.18.Final netty-4.0.17.Final netty-4.0.16.Final netty-4.0.15.Final netty-4.0.14.Final netty-4.0.14.Beta1 netty-4.0.13.Final netty-4.0.12.Final netty-4.0.11.Final netty-4.0.10.Final netty-4.0.9.Final netty-4.0.8.Final netty-4.0.7.Final netty-4.0.6.Final
Nothing to show
Find file Copy path

netty/netty is licensed under the

Apache License 2.0

A permissive license whose main conditions require preservation of copyright and license notices. Contributors provide an express grant of patent rights. Licensed works, modifications, and larger works may be distributed under different terms and without source code.

This is not legal advice. Learn more about repository licenses.

b11ef6c Aug 28, 2009
1 contributor

Users who have contributed to this file

203 lines (169 sloc) 11.1 KB
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.
apache-mina-sshd-46fc8d6/assembly/src/main/legal/licenses/slf4j.txt000066400000000000000000000021541456036076300252640ustar00rootroot00000000000000Copyright (c) 2004-2017 QOS.ch All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. apache-mina-sshd-46fc8d6/assembly/src/main/legal/licenses/spring.txt000066400000000000000000000261351456036076300255510ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. apache-mina-sshd-46fc8d6/assembly/src/main/legal/licenses/tomact-apr.txt000066400000000000000000000261361456036076300263170ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. apache-mina-sshd-46fc8d6/assembly/src/main/legal/notices.xml000066400000000000000000000167041456036076300240700ustar00rootroot00000000000000 bouncycastle bcprov-jdk18on Bouncy Castle Crypto APIs for Java The Legion of the Bouncy Castle http://www.bouncycastle.org Bouncy Castle License http://www.bouncycastle.org/licence.html org.slf4j slf4j-api SLF4J API Module Simple Logging Facade for Java https://www.slf4j.org/ MIT style http://www.slf4j.org/license.html net.sf.jpam jpam Java-PAM bridge JPAM project http://jpam.sourceforge.net/ The Apache Software License, Version 2.0 http://jpam.sourceforge.net/license.html org.apache.mina mina-core Apache MINA Project Apache MINA Project https://mina.apache.org/ The Apache Software License, Version 2.0 http://www.apache.org/licenses/ io.netty netty-transport Asynchronous event-driven network application framework Netty project https://netty.io/ The Apache Software License, Version 2.0 https://github.com/netty/netty/blob/4.1/LICENSE.txt net.i2p.crypto eddsa ed25519-java str4d https://github.com/str4d/ed25519-java Creative Commons https://github.com/str4d/ed25519-java/blob/master/LICENSE.txt org.eclipse.jgit org.eclipse.jgit JGit Eclipse Foundation https://git.eclipse.org/r/plugins/gitiles/jgit/jgit/ Eclipse Distribution License v1.0 https://git.eclipse.org/r/plugins/gitiles/jgit/jgit/+/refs/heads/master/LICENSE org.springframework.integration spring-integration-bom Spring integration Spring https://spring.io/ The Apache Software License, Version 2.0 https://github.com/spring-projects/spring-integration/blob/main/LICENSE.txt tomcat tomcat-apr Apache Tomcat Native Library Apache Tomcat http://tomcat.apache.org/native-doc/ The Apache Software License, Version 2.0 http://tomcat.apache.org/legal.html org.c02e.jpgpj jpgpj jpjpj jpgpj https://github.com/justinludwig/jpgpj MIT License https://raw.githubusercontent.com/justinludwig/jpgpj/master/LICENSE org.connectbot.jbcrypt jbcrypt jbcrypt mindrot http://http://mindrot.org/ Free https://github.com/kruton/jbcrypt/blob/master/LICENSE apache-mina-sshd-46fc8d6/docs/000077500000000000000000000000001456036076300162045ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/docs/android.md000066400000000000000000000247051456036076300201560ustar00rootroot00000000000000# Android support The SSHD team has not checked the compatibility and usability of the libraries for the Android O/S. Furthermore, at present it is not a stated goal of this project to actively support it, mainly because of the dire lack of available R&D resources and the relatively time consuming task of developing and testing code for Android. That being said, several "hooks" have been implemented aimed at facilitating the usage of these libraries on Android, though (as stated) no serious effort was made to thoroughly test them. The implemented support relies on feedback from users who have attempted this feat, the problems they discovered and how they tried (or failed) to overcome them. ## Specific issues ### O/S detection [OsUtils](../sshd-common/src/main/java/org/apache/sshd/common/util/OsUtils.java) has been enhanced to both automatically attempt to detect if currently runing in Android or being told so explicitly by the user - see `isAndroid/setAndroid` method(s). ### Accessing the current working directory Instead of accessing the `user.dir` system property directly (which is missing in Android) [OsUtils](../sshd-common/src/main/java/org/apache/sshd/common/util/OsUtils.java) has been enhanced to provide a `getCurrentWorkingDirectory` method - which by default still uses the `user.dir` system property. However, the user can use `setCurrentWorkingDirectoryResolver` to reigster a callback that will return some user-controlled location instead. This is most important for [ScpFileOpener](../sshd-scp/src/main/java/org/apache/sshd/scp/common/ScpFileOpener.java) `getMatchingFilesToSend` default implementation that uses the CWD as its base path if none provided by the caller. ### Detecting the user's home directory Instead of accessing the `user.home` system property directly (which is missing in Android) [PathUtils](../sshd-common/src/main/java/org/apache/sshd/common/util/io/PathUtils.java) now provides a `getUserHomeFolder` which by default still consults the `user.home` system property, unless the user has invoked `setUserHomeFolderResolver` to provide a replacement for it. Another aspect of this issue is the assignment of user "home" folder by a *server* that is running on Android. The [NativeFileSystemFactory](../sshd-common/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemFactory.java) auto-detects this folder for standard O/S, but for Android one needs to call its `setUsersHomeDir` method **explicitly** - or extend it and override `getUserHomeDir` method. It can also be helpful for an [SftpSubsystem](../sshd-sftp/src/main/java/org/apache/sshd/sftp/server/SftpSubsystem.java) or a [ShellFactory](../sshd-core/src/main/java/org/apache/sshd/server/shell/ShellFactory.java) implementation when they provide the concept of a user's "HOME" location. A similar mechanism has been implemented for [`PGPUtils#getDefaultPgpFolderPath`](../sshd-openpgp/src/main/java/org/apache/sshd/openpgp/PGPUtils.java), though it depends on the `PathUtils#getUserHomeFolder` mechanism, so if one manages `getUserHomeFolder` correctly, `PGPUtils#getDefaultPgpFolderPath` would align with it as well without need for further intervention. ### O/S dependenent code flow There are a few locations where special consideration was made if the code detects that it is running on Android - these choices were made based on our current understanding of Android and are **independent** of the device's O/S API level. E.g. the [KeyUtils](../sshd-common/src/main/java/org/apache/sshd/common/config/keys/KeyUtils.java) `validateStrictKeyFilePermissions` method returns an always valid result for Android. **Important notice:** if API-level dependent flows are required, then much deeper change may be required. ### [Security provider(s)](./security-providers.md) The SSHD code uses *Bouncycastle* if it detects it - however, on Android this can cause some issues - especially if the user's code also contains the BC libraries. It is not clear how to use it - especially since some articles suggest that BC is bundled into Android or has been so and now it is deprecated. Several [Stackoverflow](https://stackoverflow.com/) posts suggest that an **explicit** management is required - e.g.: ```java import java.security.Security; Security.removeProvider("BC" or "Bouncycastle"); Security.addProvider(new BouncycastleProvider()); ``` The *sshd-contrib* module contains a [AndroidOpenSSLSecurityProviderRegistrar](../sshd-contrib/src/main/java/org/apache/sshd/contrib/common/util/security/androidopenssl/AndroidOpenSSLSecurityProviderRegistrar.java) class that can supposedly be used via the [`SecurityUtils.registerSecurityProvider()`](../sshd-common/src/main/java/org/apache/sshd/common/util/security/SecurityUtils.java) call. **Note:** we do not know for sure if this works for all/part of the needed security requirements since the code was donated without any in-depth explanation other than that "is works". ### Using [MINA](../sshd-mina) or [Netty](../sshd-netty) I/O factories These factories have not been tested on Android and it is not clear if they work on it. ## Example code The following is a simple/naive/simplistic code sample demonstrating the required initializations for an Android application using the SSHD code. Users are of course invited to make the necessary adjustments for their specific needs. ```java import android.app.Application; public class MyApplication extends Application { public MyApplication() { OsUtils.setAndroid(Boolean.TRUE); // if don't trust the automatic detection System.setProperty("user.name", "....whatever..."); // just in case OsUtils.setCurrentUser("....whatever..."); } @Override public void onCreate() { super.onCreate(); // This is just an example - you are welcome to use whatever location you want File filesDir = getFilesDir(); Path filesPath = filesDir.toPath(); System.setProperty("user.home", filesPath.toString()); // just in case PathUtils.setUserHomeFolderResolver(() -> filesPath); System.setProperty("user.dir", filesPath.toString()); // just in case OsUtils.setCurrentWorkingDirectoryResolver(() -> filesPath); ...setup security provider(s)... } } ``` **Note:** these are the most *basic* settings - various extra adjustments might be required and they must be dealt with on a case-by-case manner. We do believe though that the code is flexible enough to provide the necessary solutions. As previously stated, even though we do not define Android as a goal, we would appreciate feedback on problems and solutions our users have encountered when running on Android (or iOs for that matter), and what suggestions they have for code changes that would facilitate this task - see [SSHD development mailing list](mailto:dev@mina.apache.org) or open an issue on this project - or better yet, a PR. ## Further possible features Several Android related features come to mind as being useful, but as stated, due to severe lack of R&D resources (and not much demand from the community) we cannot devote the necessary effort to implement them. They are listed here in case they spark interest and someone undertakes their implementation (and hopefully contributes back via a PR). ### [Uri](https://developer.android.com/reference/android/net/Uri?hl=en)-based [FileSystemProvider](https://developer.android.com/reference/java/nio/file/spi/FileSystemProvider) and [FileSystem](https://developer.android.com/reference/java/nio/file/FileSystem) The idea is to be able to wrap a [Uri](https://developer.android.com/reference/android/net/Uri?hl=en) that represents a files tree (e.g., obtained via [ACTION_OPEN_DOCUMENT_TREE](https://developer.android.com/reference/android/content/Intent#ACTION_OPEN_DOCUMENT_TREE)) into a [FileSystemProvider](https://developer.android.com/reference/java/nio/file/spi/FileSystemProvider) and [FileSystem](https://developer.android.com/reference/java/nio/file/FileSystem) so that it can be used to provide [Path](https://developer.android.com/reference/java/nio/file/Path.html)-like objects to SCP/SFTP client/server. The existing [DocumentFile](https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile) support object can be very helpful for this purpose. In this context, it would be helpful to have an Android specific library that provides API wrappers that use *Uri*-s instead of *Path*-s - e.g.: * Loading/Storing keys * Copy files/directories through SCP/SFTP * Accessing configuration files **Important note**: it may become necessary to enhance the existing core code to support these features (which is fine) - however, the limitation is that we cannot include references to Android-specific classes in our core code. Any such references must be contained entirely into **separate** dedicated library(ies) that may use "hooks" placed in the core code. Furthermore, these hooks must reference only Java 8 classes that are supported by Android (regardless of the API level). ## Using [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences?hl=en) for global [configuration](https://github.com/apache/mina-sshd/blob/master/docs/internals.md#properties-and-inheritance-model) The SSHD code contains a robust and flexible mechanism for [configuring](https://github.com/apache/mina-sshd/blob/master/docs/internals.md#properties-and-inheritance-model) various properties used internally to control performance, memory and resources allocation, behavior, etc.. This mechanism relies heavily on Java properties which cannot be controlled when an Android application is launched. Instead, one could use the [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences?hl=en) mechanism to store the user's choices, as well as editing and then using these properties to configure the SSHD code when application starts. ### Demo application(s) as part of the SSHD code It would be very helpful to have several Android demo applications as part of the delivered SSHD code. These applications can demonstrate to users how to integrate SSHD into Android applications as well as serve as a very useful platform for debugging existing code and implementating future features. E.g., * [WinSCP](https://winscp.net/eng/index.php)-like application to test SFTP/SCP code. * [Putty](https://www.putty.org/)-like application to test remote shell. * Basic server application - very interesting use-case in conjunction with Android - turning one's phone/tablet into a public SSH server via becoming a WiFi hotspot.apache-mina-sshd-46fc8d6/docs/changes/000077500000000000000000000000001456036076300176145ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/docs/changes/2.10.0.md000066400000000000000000000253761456036076300206710ustar00rootroot00000000000000# Introduced in 2.10.0 ## Bug fixes * [GH-268](https://github.com/apache/mina-sshd/issues/268) (Regression in 2.9.0) Heartbeat should throw an exception if no reply arrives within the timeout. * [GH-275](https://github.com/apache/mina-sshd/issues/275) SFTP: be more lenient when reading `SSH_FXP_STATUS` replies. * [GH-281](https://github.com/apache/mina-sshd/issues/281) Use OpenSSH first-match semantics for processing HostConfigEntries. * [GH-282](https://github.com/apache/mina-sshd/issues/282) Correct setting file permissions on newly written host key files on Windows. * [GH-283](https://github.com/apache/mina-sshd/issues/283) Fix handling of `CoreModuleProperties.PASSWORD_PROMPTS`. * [GH-285](https://github.com/apache/mina-sshd/issues/285) Fix compilation failure on Java 19. * [GH-293](https://github.com/apache/mina-sshd/issues/293) Handle SFTP buffer sizes larger than the server limit better. * [GH-294](https://github.com/apache/mina-sshd/issues/294) Fix memory leak in `SftpFileSystemProvider`. * [GH-297](https://github.com/apache/mina-sshd/issues/297) Auto-configure file password provider for reading encrypted SSH keys. * [GH-298](https://github.com/apache/mina-sshd/issues/298) Server side heartbeat not working. * [GH-300](https://github.com/apache/mina-sshd/issues/300) Read the channel id in `SSH_MSG_CHANNEL_OPEN_CONFIRMATION` as unsigned int. * [GH-313](https://github.com/apache/mina-sshd/issues/313) Log exceptions in the SFTP subsystem before sending a failure status reply. * [GH-322](https://github.com/apache/mina-sshd/issues/322) Add basic Android O/S awareness. * [GH-325](https://github.com/apache/mina-sshd/issues/325) `SftpFileSystemProvider`: fix deletions of symlinks through `Files.delete()`. * [GH-364](https://github.com/apache/mina-sshd/issues/364) `AbstractAgentClient`: respect flags for RSA signature requests. * [SSHD-1295](https://issues.apache.org/jira/browse/SSHD-1295) Fix cancellation of futures and add options to cancel futures on time-outs. * [SSHD-1315](https://issues.apache.org/jira/browse/SSHD-1315) Do not log sensitive data at log level `TRACE`. * [SSHD-1316](https://issues.apache.org/jira/browse/SSHD-1316) Possible OOM in `ChannelPipedInputStream` (fix channel window). * [SSHD-1319](https://issues.apache.org/jira/browse/SSHD-1319) Use position in `SftpRemotePathChannel.transferFrom()`. * [SSHD-1324](https://issues.apache.org/jira/browse/SSHD-1324) SFTP: Rooted file system can leak information. ## Major code re-factoring ## Potential compatibility issues ### Futures and cancellation or time-outs Apache MINA sshd is an asynchronous framework: for long-running operations, and in particular operations involving network communication, the API returns a future that client code can use to wait until the operation is complete. Waiting on a future is usually done with a `future.verify()` or `future.verify(timeout)` call. Futures can also be canceled. Previous versions did not implement cancellation correctly: while the future object itself was marked as "canceled", the underlying operation was not. The same problem also existed for time-outs: when `future.verify(timeout)` timed out, the underlying operation still continued to run asynchronously. This could lead to problems because if the underlying operation eventually succeeded, application code would be completely unaware. For instance in ``` ClientSession session = client.connect(user, host, port).verify(timeout).getSession(); ``` the application might get a time-out, but the underlying connect operation would continue to run, might succeed eventually, and then there would in fact be a `ClientSession` (and thus also a network connection, and a socket used up). But the application had no way to access that session to shut it down. The net effect was a socket leak. In this version, this has been corrected. By default, the future is canceled when a time-out occurs, and `future.cancel()` is propagated to the underlying operation and cancels it. Canceling an operation itself may not be possible immediately. For instance, an authentication attempt is a message exchange with the server. If the authentication request has already been sent when cancellation is requested, the sending of that request cannot be undone. The authentication can only be cancelled after the reply from the server has been received, and if that reply is an authentication success, cancellation isn't even possible anymore. Or consider requesting a port forwarding: that, too, is a request-reply message exchange. Once the request has been sent, there are two cases: if the server replies with a failure message, the port forwarding failed and since there is nothing to cancel, cancellation is not possible. If the reply indicates the tunnel was established, but `future.cancel()` had already been called, we have two options: either we shut down the just established tunnel again and say cancellation succeeded, or we say cancellation failed and report a successfully established tunnel. Because cancellations may be caused by time-outs, Apache MINA sshd chooses the first option and shuts down the tunnel again. Otherwise an application might get a time-out but still be left with an established tunnel. Cancellation is only possible while the operation has not completed yet. If a future is already done, it cannot be canceled anymore. The `cancel()` operation on a future is thus a _request_ to cancel the operation; it may or may not result in actually cancelling the operation. `cancel()` itself therefore returns a `CancelFuture` that client code can use to wait for the request having been handled, and then learn whether the operation was indeed canceled. Calls to `verify()` throw an `SshException` with a `java.util.concurrent.CancellationException` as cause if cancelled asynchronously via the `cancel()` method. Application code can control the behavior on time-outs. The `verify()` method takes besides a time-out duration newly also a number of `CancelOption`s as parameters. There are three possible values to cancel on a time-out, to cancel on an interruption, or not to cancel at all when either occurs. For backwards compatibility, the default behavior of `AuthFuture` and of `OpenFuture` is unchanged: to cancel on a time-out, client code must pass the `CancelOption.CANCEL_ON_TIMEOUT` flag. The default behavior of `ConnectFuture` _has_ been changed: by default, it _does_ cancel the connection attempt if a time-out occurs. To avoid this, client code would have to pass the `CancelOption.NO_CANCELLATION` flag expressly. This change in behavior was done to avoid socket leaks, and it was deemed acceptable since a difference in behavior could only occur if existing client code called `AuthFuture.verify()` in different threads on the same future instance, or sequentially on the same future instance again after the first time-out. Both cases are highly unlikely to occur in existing client code. If existing code needs this behavior, it needs to be adapted to pass `CancelOption`s as may be appropriate for the precise use case. ## Minor code helpers ## Behavioral changes and enhancements * Support for reading SSH keys from PEM files containing encrypted private keys [RFC 5958, EncryptedPrivateKeyInfo](https://www.rfc-editor.org/rfc/rfc5958) has been added. Such PEM files start with `-----BEGIN ENCRYPTED PRIVATE KEY-----`. Reading and decrypting keys from such files requires Bouncy Castle to be present. * Support reading SSH keys from PEM files starting with `-----BEGIN ED25519 PRIVATE KEY-----`. Some OpenSSL versions could produce such files when the user specified "traditional" PEM output. (Encrypted keys written using [RFC 1421](https://www.rfc-editor.org/rfc/rfc1421) encryption.) Modern OpenSSL refuses to create such PEM files; it always uses PKCS#8 (RFC 5958) style PEM files for EdDSA keys. * Support reading encrypted private keys in openSSH format that have been encrypted with an AEAD cipher. * `CoreModuleProperties.PASSWORD_PROMPTS` is now also used for password authentication. Previous versions used it only for keyboard-interactive authentication. The semantics has been clarified to be the equivalent of the OpenSSH configuration `NumberOfPasswordPrompts`, which is actually the number of authentication *attempts*. (In keyboard-interactive authentication, there may be several prompts per authentication attempt.) Only interactive authentication attempts using `UserInteraction` count towards the limit. Attempts fulfilled by explicitly provided passwords (via `session.addPasswordIdentity()` or `session.setPasswordIdentityProvider()`) are *not* counted. The default value of the property is unchanged and is 3, as in OpenSSH. The limit is applied independently for both authentication mechanisms: with the default setting, there can be three keyboard-interactive authentication attempts, plus three more password authentication attempts if both methods are configured and applicable. ### Connection time-outs Connection time-outs are normally handled in Apache MINA SSHD at the application level by passing a time-out to `ConnectFuture.verify()`: ``` ClientSession session = client.connect(user, host, port).verify(MY_TIMEOUT).getSession(); ``` However, the actual I/O library used might have its own connection time-out. With large time-outs, the behavior depended on the actual implementation of the I/O back-end used: * The default NIO2 back-end has no default connection time-out at all, so the `verify(MY_TIMEOUT)` call would always time-out after `MY_TIMEOUT` had elapsed. * Apache MINA has a default connection time-out of one minute, so even if `MY_TIMEOUT` was larger, the time-out would still occur after one minute. * Netty has a default connection time-out of 30 seconds. In this version, a new property `CoreModuleProperties.IO_CONNECTION_TIMEOUT` can be set to control this I/O connection time-out. It can be set on an `SshClient` or `SshServer`; if set (and > 0), the I/O back-end is configured to use that value as its I/O connection time-out, and `ConnectFuture.verify(MY_TIMEOUT)` will always time-out at `Math.min(CoreModuleProperties.IO_CONNECTION_TIMEOUT, MY_TIMEOUT)`. The property is also effective for the NIO2 back-end; the default value is 1 minute. `verify()` throws an `SshException` if it fails or times out. The _cause_ of that exception is a `java.net.ConnectException` if the I/O connection time-out expired, and a `java.util.concurrent.TimeoutException` if the application time-out expired. (And if the future was canceled explicitly before any time-out was reached, the cause is a `java.util.concurrent.CancellationException`; see above.) The new `CancelOption`s discussed above apply only if the application time-out expires. If the connection attempt times out at I/O level, it is the responsibility of the I/O library to ensure no resources such as sockets are consumed, and there is no SSH session created either. apache-mina-sshd-46fc8d6/docs/changes/2.11.0.md000066400000000000000000000135231456036076300206610ustar00rootroot00000000000000# Introduced in 2.11.0 ## Bug Fixes * [GH-328](https://github.com/apache/mina-sshd/issues/328) Added configurable timeout(s) to `DefaultSftpClient`. * [GH-370](https://github.com/apache/mina-sshd/issues/370) Also compare file keys in `ModifiableFileWatcher`. * [GH-371](https://github.com/apache/mina-sshd/issues/371) Fix channel pool in `SftpFileSystem`. * [GH-383](https://github.com/apache/mina-sshd/issues/383) Use correct default `OpenOption`s in `SftpFileSystemProvider.newFileChannel()`. * [GH-384](https://github.com/apache/mina-sshd/issues/384) Use correct lock modes for SFTP `FileChannel.lock()`. * [GH-388](https://github.com/apache/mina-sshd/issues/388) `ScpClient`: support issuing commands to a server that uses a non-UTF-8 locale. * [GH-398](https://github.com/apache/mina-sshd/issues/398) `SftpInputStreamAsync`: fix reporting EOF on zero-length reads. * [GH-403](https://github.com/apache/mina-sshd/issues/403) Work-around a bug in WS_FTP <= 12.9 SFTP clients. * [GH-407](https://github.com/apache/mina-sshd/issues/407) (Regression in 2.10.0) SFTP performance fix: override `FilterOutputStream.write(byte[], int, int)`. * [GH-410](https://github.com/apache/mina-sshd/issues/410) Fix a race condition to ensure `SSH_MSG_CHANNEL_EOF` is always sent before `SSH_MSG_CHANNEL_CLOSE`. * [GH-414](https://github.com/apache/mina-sshd/issues/414) Fix error handling while flushing queued packets at end of KEX. * [GH-420](https://github.com/apache/mina-sshd/issues/420) Fix wrong log level on closing an `Nio2Session`. * [SSHD-789](https://issues.apache.org/jira/browse/SSHD-789) Fix detection of Android O/S from system properties. * [SSHD-1259](https://issues.apache.org/jira/browse/SSHD-1259) Consider all applicable host keys from the known_hosts files. * [SSHD-1310](https://issues.apache.org/jira/browse/SSHD-1310) `SftpFileSystem`: do not close user session. * [SSHD-1327](https://issues.apache.org/jira/browse/SSHD-1327) `ChannelAsyncOutputStream`: remove write future when done. * [SSHD-1332](https://issues.apache.org/jira/browse/SSHD-1332) (Regression in 2.10.0) Resolve ~ in IdentityFile file names in `HostConfigEntry`. ## New Features * [SSHD-1330](https://issues.apache.org/jira/browse/SSHD-1330) Use `KeepAliveHandler` global request instance in client as well * [GH-356](https://github.com/apache/mina-sshd/issues/356) Publish snapshot maven artifacts to the [Apache Snapshots](https://repository.apache.org/content/repositories/snapshots) maven repository. * Bundle _sshd-contrib_ has support classes for the [HAProxy protocol V2](https://www.haproxy.org/download/2.7/doc/proxy-protocol.txt). # Behavioral changes and enhancements ### SFTP file handle size Previous versions of Apache MINA sshd used SFTP file handles that were twice as large as configured via `SftpModuleProperties.FILE_HANDLE_SIZE`. The reason for this was that the file handle bytes were stringified, representing each byte as two hex characters. This stringified file handle was then send over the wire. If `SftpModuleProperties.FILE_HANDLE_SIZE` was configured as 16, the actual file handle size was thus 32 bytes. This has been fixed in this version. Additionally, the default setting for the size of file handles has been changed from 16 to 4 bytes. OpenSSH also uses 4-byte SFTP file handles. Using the same size not only means that there is a little more space left in SSH packets for actual data transfer, it also completely avoids the WS_FTP bug mentioned in [GH-403](https://github.com/apache/mina-sshd/issues/403). ## Potential compatibility issues ### `KeepAliveHandler` global request handler moved from server to common global requests package Was previously only on server-side - now also for client (see [SSHD-1330](https://issues.apache.org/jira/browse/SSHD-1330)). This should be fully backward compatible since most servers do not send this request. However, if users have somehow added this handler to the client side independently, the code should be re-examined and the independent handler removed or make it replace the global one. ### Server-side SFTP file handle encoding The aforementioned fix for the size of SFTP file handles has the potential to have undesired effects on existing server-side code that assumed that such SFTP file handles contained only printable characters. This is no longer the case. For historical reasons, Apache MINA sshd stores these SFTP file handles as Java `String`s, and it's not possible to change this without breaking a lot of APIs. So this was kept, but the strings are now encoded as ISO-8859-1 and may contain arbitrary characters in the range from 0 to 255. This change *should* be transparent as SFTP file handles are supposed to be opaque, but there is one caveat: If you have implemented your own server and have subclassed `SftpSubsystem` or if you install an `SftpEventListener` that stores or logs raw SFTP file handles, your code may need to be adapted. There is a new method `String Handle.safe(String rawHandle)` that can be used to convert an SFTP file handle to a printable string. Otherwise the change is transparent to server implementors and to SFTP clients. (On the client side, Apache MINA sshd already used `byte[]` to represent SFTP file handles.) ### Major Code Re-factoring As part of the fix for [GH-371](https://github.com/apache/mina-sshd/issues/371) the channel pool in `SftpFileSystem` was rewritten completely. Previous code also used `ThreadLocal`s to store `SftpClient`s, which could cause memory leaks. These `ThreadLocal`s have been removed, and the channel pool has been rewritten to function similar to a Java `ThreadPool`: the pool has a maximum size; it has an expiration duration after which an idle channel is removed and closed, and it has a "core size" of channels to keep even if they are idle. If a channel is closed for any reason it is evicted from the pool. Properties to configure these pool parameters have been added to `SftpModuleProperties`. apache-mina-sshd-46fc8d6/docs/changes/2.12.0.md000066400000000000000000000040071456036076300206570ustar00rootroot00000000000000# Introduced in 2.12.0 ## Bug Fixes * [GH-428/GH-392](https://github.com/apache/mina-sshd/issues/428) SCP client fails silently when error signalled due to missing file or lacking permissions * [GH-434](https://github.com/apache/mina-sshd/issues/434) Ignore unknown key types from agent or in OpenSSH host keys extension ## New Features * [GH-429](https://github.com/apache/mina-sshd/issues/429) Support GIT protocol-v2 * [GH-445](https://github.com/apache/mina-sshd/issues/445) OpenSSH "strict key exchange" protocol extension ([CVE-2023-48795](https://nvd.nist.gov/vuln/detail/CVE-2023-48795) mitigation) ## Behavioral changes and enhancements ### New `ScpTransferEventListener` callback method Following [GH-428/GH-392](https://github.com/apache/mina-sshd/issues/428) a new `handleReceiveCommandAckInfo` method has been added to enable users to inspect acknowledgements of a `receive` related command. The user is free to inspect the command that was attempted as well as the response code and decide how to handle it - including even throwing an exception if OK status (if this makes sense for whatever reason). The default implementation checks for ERROR code and throws an exception if so. ### OpenSSH protocol extension: strict key exchange [GH-445](https://github.com/apache/mina-sshd/issues/445) implements an extension to the SSH protocol introduced in OpenSSH 9.6. This ["strict key exchange" extension](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL) hardens the SSH key exchange against the ["Terrapin attack"](https://www.terrapin-attack.com/) ([CVE-2023-48795](https://nvd.nist.gov/vuln/detail/CVE-2023-48795)). The extension is active if both parties announce their support for it at the start of the initial key exchange. If only one party announces support, it is not activated to ensure compatibility with SSH implementations that do not implement it. Apache MINA sshd clients and servers always announce their support for strict key exchange. ## Potential compatibility issues ## Major Code Re-factoring apache-mina-sshd-46fc8d6/docs/changes/2.12.1.md000066400000000000000000000005701456036076300206610ustar00rootroot00000000000000# Introduced in 2.12.1 ## Bug Fixes * [GH-458](https://github.com/apache/mina-sshd/issues/458) Singleton thread pool for kex message handler flushing * [SSHD-1338](https://issues.apache.org/jira/browse/SSHD-1338) Restore binary compatibility with 2.9.2 ## New Features ## Behavioral changes and enhancements ## Potential compatibility issues ## Major Code Re-factoring apache-mina-sshd-46fc8d6/docs/changes/2.2.0.md000066400000000000000000000233021456036076300205750ustar00rootroot00000000000000# Introduced in version 2.2.0 ## Major code re-factoring * `AttributeStore` "read" methods moved to (new class) `AttributeRepository`. * `AttributeKey` moved to `AttributeRepository`. * `getAttribute` and `resolveAttribute` moved to `AttributeRepository`. * Added `attributeKeys` enumeration method to `AttributeRepository`. * In this context, please note that all associated session/channel/client/server attributes are cleared when entity is closed. The clearing usually occurs as after all relevant registered event listeners have been invoked. * `DEFAULT_PORT` moved from `SshConfigFileReader` to `SshConstants`. * Moved some session "summary" related definitions from `Session` to `SessionContext` (which `Session` extends). * Added new `sessionDisconnect` method to `SessionListener`. * `ReservedSessionMessagesHandler#handleUnimplementedMessage` has an extra `cmd` argument and is called both for `SSH_MSG_UNIMPLEMENTED` as well as for any other unexpected/unrecognized command encountered during the session message processing loop. * `AttributeRepository` optional context propagated during initial connection establishment * `ClientSessionCreator` has extra `connect` methods with an `AttributeRepository` connection context argument * The context is also propagated to `HostConfigEntryResolver#resolveEffectiveHost` method * `connectionEstablished` and `abortEstablishedConnection` methods of `IoServiceEventListener` accept also an `AttributeRepository` connection context argument (propagated from the `ClientSessionCreator#connect` invocation). * `FilePasswordProvider` * Added an extra method (`handleDecodeAttemptResult`) that enables users to try and repeat an encrypted private key decoding using a different password. * The interface methods are also provided with a retry index that indicates the number of times they have been re-invoked for the same resource (including on success). * The available session context (if any) is also provided as an argument to the interface methods. * The interface methods use a `NamedResource` as the resource key instead of a plain string. * `SshAgent#getIdentities` returns an `Iterable` rather than a `List` * `SftpFileSystemProvider` and its associated helper classes have been moved to `org.apache.sshd.client.subsystem.sftp.fs` package. * `KeyPairProvider` accepts a `SessionContext` argument in its `getKeyTypes/loadKey` methods. * `KeyIdentityProvider` accepts a `SessionContext` argument in its `loadKeys` method. * `ClientIdentityProvider` accepts a `SessionContext` argument in its `getClientIdentity` method. * `ClientIdentityLoader` * Accepts a `SessionContext` argument in its `loadClientIdentity` method. * Uses a `NamedResource` as the identity location indicator instead of a plain old string. * `ApacheSshdSftpSessionFactory#get/setPrivateKey` has been renamed to `get/setPrivateKeyLocation`. * `SshClient` and `ClientSession` use a `KeyIdentityProvider` instead of a full blown `KeyPairProvider`. `KeyPairProvider` is used only in the context of an `SshServer` and/or `ServerSession`. * `SshClient#loadClientIdentities` has been renamed to `preloadClientIdentities` + it returns a `KeyIdentityProvider` instead of a collection of strings representing paths. * The various `ClientIdentitiesWatcher`(s) use a type-safe `ClientIdentityLoaderHolder` and `FilePasswordProviderHolder` instead of the generic `Supplier` definition. * Removed API(s) that used string file paths to create `FileInputStream`-s - using only `java.nio.file.Path`-s * Converted most of the key-pair identity loaders (e.g., `ClientIdentityLoader`, `ClientIdentityProvider`, etc.) to return an `Iterable` instead of single `KeyPair` instance. * Code that converts authorized keys entries into `PublicKey`-s has been renamed to `resolvePublicKeyEntries` and moved to `PublicKeyEntry` class. * Note that the parameters **order** has also been modified * `PublicKeyEntryResolver` (and its derived classes) accept an extra `SessionContext` parameter. * All methods `ScpTransferEventListener` accept an extra `Session` parameter indicating the SSH client/server session context for the listener's invocation. * Same applies for `ScpFileOpener` and `ScpReceiveLineHandler` * Re-provide expected SCP byte count transfer and permissions when invoking `ScpFileOpener#openRead/openWrite` * `CipherInformation#getBlockSize` has been renamed to `getKdfSize` in order to emphasize that its value represents the number of bytes used to derive the cipher's secret key value and not the cipher's underlying block size. * See [SSHD-873](https://issues.apache.org/jira/browse/SSHD-873) enhancement remark below for the cipher block size information. * `IdentityResourceLoader` exposes `getSupportedKeyTypes()` instead of `getSupportedTypeNames()` * This method is now also implemented by the `Identity` interface as well * `HostConfigEntryResolver#resolveEffectiveHost` accepts also an (optional) initial connection context and/or local peer binding address - propagated from the `ClientSessionCreator#connect` invocation. * `connectionAccepted/abortAcceptedConnection` methods of `IoServiceEventListener` accept an extra argument - the service listen endpoint through which the connection was accepted. ## Behavioral changes and enhancements * [SSHD-708](https://issues.apache.org/jira/browse/SSHD-708) - Add support for password encrypted OpenSSH private key files. * [SSHD-757](https://issues.apache.org/jira/browse/SSHD-757) - Added hooks and some initial code to allow (limited) usage of [OpenPGP](https://www.openpgp.org/) key files - e.g. in `authorized_keys` files or as client identities. * [SSHD-849](https://issues.apache.org/jira/browse/SSHD-849) - Data forwarding code makes sure all pending packets have been sent to the peer channel when closing the tunnel gracefully. * [SSHD-850](https://issues.apache.org/jira/browse/SSHD-850) - Add capability to retry a failed private key decryption. * [SSHD-857](https://issues.apache.org/jira/browse/SSHD-857) - Add session disconnect event signalling to SessionListener. * Also calling `ReservedSessionMessagesHandler#handleUnimplementedMessage` not only for `SSH_MSG_UNIMPLEMENTED` but also for any unexpected/unrecognized command encountered during the session message processing loop. * [SSHD-859](https://issues.apache.org/jira/browse/SSHD-859) - Provide client session connection context that is propagated to the SSH session. * Also added connection context argument (propagated from the `ClientSessionCreator#connect` invocation) to`connectionEstablished` and `abortEstablishedConnection` methods of `IoServiceEventListener`. * [SSHD-860](https://issues.apache.org/jira/browse/SSHD-860) - Use lazy loading of public key identities. * [SSHD-861](https://issues.apache.org/jira/browse/SSHD-861) - Fixed username/password encoding for `SftpFileSystem` URI(s). * Also added `SftpFileSystemClientSessionInitializer` support in `SftpFileSystemProvider` * [SSHD-862](https://issues.apache.org/jira/browse/SSHD-862) - Provide session context argument (if available) when key loading methods are invoked. * [SSHD-864](https://issues.apache.org/jira/browse/SSHD-864) - Using a `NamedResource` instead of plain old string in order to provide key file(s) location information * [SSHD-865](https://issues.apache.org/jira/browse/SSHD-865) - Key identities overrides specified in the [ssh_config](http://www.gsp.com/cgi-bin/man.cgi?topic=ssh_config) configuration file are also lazy loaded * [SSHD-866](https://issues.apache.org/jira/browse/SSHD-866) - Counting empty challenges separately when enforcing max. attempts during `keyboard-interactive` authentication * [SSHD-870](https://issues.apache.org/jira/browse/SSHD-870) - Added hooks and some initial code to allow (limited) usage of [OpenPGP](https://www.openpgp.org/) key rings in `authorized_keys` files * [SSHD-873](https://issues.apache.org/jira/browse/SSHD-873) - `CipherInformation#getCipherBlockSize` method has been added for exposing the cipher's block size. **Note:** for the time being we declare a virtual block size for stream ciphers as well (e.g., RC4) in order to facilitate the automatic re-keying mechanism described in [RFC 4253 - section 9](https://tools.ietf.org/html/rfc4253#section-9) and [RFC 4344 - section 3.2](https://tools.ietf.org/html/rfc4344#section-3.2). * [SSHD-876](https://issues.apache.org/jira/browse/SSHD-876) - Looking through the resolvable class-loaders "hierarchy" (thread-context => anchor => system) for `sshd-version.properties` file instead of just in the thread context class loader. * In this context, the default reported client/server SSH version string has been set to `APACHE-SSHD-...version...`. Reminder: the user can override this default via configuration properties set on the client/server instance (see `AbstractSession#resolveIdentificationString`, `ClientFactoryManager#CLIENT_IDENTIFICATION`, and `ServerFactoryManager#SERVER_IDENTIFICATION`). * [SSHD-878](https://issues.apache.org/jira/browse/SSHD-876) - The `File/DirectoryHandle`(s) used by the SFTP subsystem implement `AttributeStore` interface - which means that `SftpEventListener`(s) can now attach user-defined attributes to the generated handle(s). * [SSHD-886](https://issues.apache.org/jira/browse/SSHD-886) - Do not send `SSH_MSG_UNIMPLEMENTED` reply if registered `ReservedSessionMessagesHandler` signals that it has handled the unknown packet type. * `SftpCommandMain` shows by default `get/put` command progress using the hash sign (`#`) marker. The marker can be enabled/disabled via the `progress` command: ``` > progress ... reponse is whether it is 'on' or 'off' > progress on/off ... set the progress marker indicator ... ``` apache-mina-sshd-46fc8d6/docs/changes/2.3.0.md000066400000000000000000000212741456036076300206040ustar00rootroot00000000000000# Introduced in version 2.3.0 ## Major code re-factoring * The `ChannelSession` provides a mechanism for supporting non-standard extended data (a.k.a. STDERR data) in a similar manner as the "regular" data. Please read the relevant section in the main documentation page. * The user can use a registered `SessionDisconnectHandler` in order be informed and also intervene in cases where the code decides to disconnect the session due to various protocol or configuration parameters violations. * `ScpFileOpener#getMatchingFilesToSend` has been modified to accept a `Path` as the base directory and also return an `Iterable`. * The SFTP command line client provides a `kex` command that displays the KEX parameters of the current sesssion - client/server proposals and what has been negotiated. * The `Session` object provides a `KexExtensionHandler` for usage with [KEX extension negotiation](https://tools.wordtothewise.com/rfc/rfc8308) * The `SignalListener` accepts a `Channel` argument indicating the channel instance through which the signal was received. * When creating a client shell or command channel one can provide optional PTY and/or environment values in order to override the internal default ones. * In this context, the `PtyCapableChannelSession#setEnv` method has been modified to accept ANY object. When the environment values are sent to the server, the object's `toString()` will be used. Furthermore, if one provides a `null` value, the previous registered value (if any) is **removed**. * The `SftpFileSystemAccessor` callbacks are now provided with the relevant `Handle` they are servicing (*Note:* in special cases a `null` value is provided to indicate invocation outside the scope of such a handle). * Closing of file channel/directory streams created by the accessor are also closed via callbacks to the same accessor * When closing a file channel that may have been potentially modified, the default implementation forces a synchronization of the data with the file-system. This behavior can be modified by setting the `sftp-auto-fsync-on-close` property to *false*. * The `ScpFileOpener` methods are also invoked in order to close input/output streams created through it when they are no longer needed once data has been successfully copied. * The `CommandFactory` and `ShellFactory` have been modified to accept the server's `ChannelSession` instance through which they are being invoked. * The various implementations of public/private keys/pairs decoders/loaders are provided with a `Map` of any headers that may be available in the relevant data file. * `org.apache.sshd.agent.unix.AgentClient` constructor expects a non-*null* `FactoryManager` instance which it then exposes via its `getFactoryManager`. * `SftpEventListener#removing/removed` callbacks accept an `isDirectory` flag indicating the type of `Path` being removed - file or directory. ## Minor code helpers * The `Session` object provides a `isServerSession` method that can be used to distinguish between client/server instances without having to resort to `instanceof`. * When creating a CLI SSH client one can specify `-o KexExtensionHandler=XXX` option to initialize a client-side `KexExtensionHandler` using an FQCN. If `default` is specified as the option value, then the internal `DefaultClientKexExtensionHandler` is used. ## Behavioral changes and enhancements * [SSHD-782](https://issues.apache.org/jira/browse/SSHD-882) - Added session level heartbeat mechanism via `SSH_MSG_IGNORE` or customized user provided code. In order to support customized user code for this feature, the `ReservedSessionMessagesHandler` can be used to implement any kind of user-defined heartbeat. *Note:* if the user configured such a mechanism, then the `sendReservedHeartbeat` method **must** be implemented since the default throws `UnsupportedOperationException` which will cause the session to be terminated the 1st time the method is invoked. * [SSHD-882](https://issues.apache.org/jira/browse/SSHD-882) - Provide hooks to allow users to register a consumer for STDERR data sent via the `ChannelSession` - especially for the SFTP subsystem. * [SSHD-892](https://issues.apache.org/jira/browse/SSHD-882) - Inform user about possible session disconnect prior to disconnecting and allow intervention via `SessionDisconnectHandler`. * [SSHD-893](https://issues.apache.org/jira/browse/SSHD-893) - Using Path(s) instead of String(s) as DirectoryScanner results * [SSHD-895](https://issues.apache.org/jira/browse/SSHD-895) - Add support for RSA + SHA-256/512 signatures. **Note:** according to [RFC - 8332 - section 3.3](https://tools.ietf.org/html/rfc8332#section-3.3): >> Implementation experience has shown that there are servers that apply >> authentication penalties to clients attempting public key algorithms >> that the SSH server does not support. >> When authenticating with an RSA key against a server that does not >> implement the "server-sig-algs" extension, clients MAY default to an >> "ssh-rsa" signature to avoid authentication penalties. When the new >> rsa-sha2-* algorithms have been sufficiently widely adopted to >> warrant disabling "ssh-rsa", clients MAY default to one of the new >> algorithms. Therefore we do not include by default the "rsa-sha-*" signature factories in the `SshClient`. They can be easily added by using the relevant `BuiltinSignatures`: ```java SshClient client = SshClient.setUpDefaultClient(); client.setSignatureFactories( Arrays.asList( /* This is the full list in the recommended preference order, * but the initialization code can choose and/or re-order */ BuiltinSignatures.nistp256, BuiltinSignatures.nistp384, BuiltinSignatures.nistp521, BuiltinSignatures.ed25519, BuiltinSignatures.rsaSHA512, BuiltinSignatures.rsaSHA256, // should check if isSupported since not required by default for Java 8 BuiltinSignatures.rsa, BuiltinSignatures.dsa)); ``` * [SSHD-896](https://issues.apache.org/jira/browse/SSHD-896) - Added support for [KEX extension negotiation](https://tools.ietf.org/html/rfc8308) * [SSHD-870](https://issues.apache.org/jira/browse/SSHD-896) - Added support for GPGv2 public keyring (Note: requires upgraded [Bouncycastle](https://mvnrepository.com/artifact/org.bouncycastle/bcpg-jdk15on/1.61) and [jpgpj](https://mvnrepository.com/artifact/org.c02e.jpgpj/jpgpj/0.6.1) versions). * [SSHD-897](https://issues.apache.org/jira/browse/SSHD-897) - The default CLI code automatically tries to detect the PTY settings to use if opening a shell or command channel. * [SSHD-901](https://issues.apache.org/jira/browse/SSHD-901) - Added capability to request a reply for the `keepalive@...` heartbeat request in order to avoid client-side session timeout due to no traffic from server. * [SSHD-902](https://issues.apache.org/jira/browse/SSHD-902) - Shutdown output when receiving `SSH_MSG_CHANNEL_EOF` message via port forwarding channel. * [SSHD-903](https://issues.apache.org/jira/browse/SSHD-903) - Fixed the SFTP version negotiation behavior in case client proposed version is higher than server supported one. * [SSHD-904](https://issues.apache.org/jira/browse/SSHD-904) - Add option to enable/disable 'fsync' on modified file contents via SFTP (default=enabled). * [SSHD-905](https://issues.apache.org/jira/browse/SSHD-905) - Add option to enable/disable 'fsync' on modified file contents via SCP (default=enabled). * [SSHD-907](https://issues.apache.org/jira/browse/SSHD-907) - `StpEventListener` invokes (new) `exiting` method to inform about SFTP subsystem exiting and therefore closing all currently tracked file/directory handles. * [SSHD-909](https://issues.apache.org/jira/browse/SSHD-909) - SFTP versions extension handler ignores non-numerical versions when resolving the available ones. * [SSHD-913](https://issues.apache.org/jira/browse/SSHD-913) - Provide channel session instance to command and/or shell factories creators * [SSHD-912](https://issues.apache.org/jira/browse/SSHD-912) - Use separate locks for Future(s) and Session/Channel instances. * [SSHD-916](https://issues.apache.org/jira/browse/SSHD-916) - Avoid locking the session lock when signalling client session authentication failure. * [SSHD-917](https://issues.apache.org/jira/browse/SSHD-917) - Add support for SSH2 public key file format. * [SSHD-921](https://issues.apache.org/jira/browse/SSHD-921) - Do not send session disconnect message due to timeout expiration if already done so. * [SSHD-923](https://issues.apache.org/jira/browse/SSHD-923) - Added agent close detection mechanisms to avoid infinite waits on incoming messages. * [SSHD-929](https://issues.apache.org/jira/browse/SSHD-929) - Provide file/directory flag indicator to SFTP event listener callback for removal. apache-mina-sshd-46fc8d6/docs/changes/2.4.0.md000066400000000000000000000137341456036076300206070ustar00rootroot00000000000000# Introduced in version 2.4.0 ## Major code re-factoring * `SftpSubSystemFactory,ScpCommandFactory` and their respective `Builder`(s) as well as the `AbstractGitCommandFactory` use a `Supplier` instead of an executor instance in order to allow users to provide a "fresh" instance every time a new command instance is initiated and protect their instance from shutdown when session is destroyed: ```java CloseableExecutorService mySpecialExecutor = ...; SftpSubsystemFactory factory = new SftpSubsystemFactory.Builder() .withExecutorServiceProvider(() -> ThreadUtils.noClose(mySpecialExecutor)) .build(); server.setSubsystemFactories(Collections.singletonList(factory)); ``` * `SubsystemFactory` is a proper interface and it has been refactored to contain a `createSubsystem` method that accepts the `ChannelSession` through which the request has been made * `AbstractSftpSubsystemHelper#resolvePathResolutionFollowLinks` is consulted wherever the standard does not specifically specify the behavior regarding symbolic links handling. * `UserAuthFactory` is a proper interface and it has been refactored to contain a `createUserAuth` method that accepts the session instance through which the request is made. * `ChannelFactory` is a proper interface and it has been refactored to contain a `createChannel` method that accepts the session instance through which the request is made. * `KeyExchangeFactory` is a proper interface and it has been refactored to contain a `createKeyExchange` method that accepts the session instance through which the request is made. * `Signature` methods accept a `SessionContext` argument representing the session context of their invocation (if any). * Default MAC(s) list is set according to the [ssh_config(5)](https://www.freebsd.org/cgi/man.cgi?query=ssh_config&sektion=5) order as **first** ones, where the supported MAC(s) that do no appear in it come last. * `PasswordAuthenticator` has a `handleClientPasswordChangeRequest` method that is invoked if a password change has been indicated by the user during authentication via the "password" method - by default throws `UnsupportedOperationException`. ## Minor code helpers * `SessionListener` supports `sessionPeerIdentificationReceived` method that is invoked once successful peer version data is received. * `SessionListener` supports `sessionEstablished` method that is invoked when initial constructor is executed. * `ChannelIdTrackingUnknownChannelReferenceHandler` extends the functionality of the `DefaultUnknownChannelReferenceHandler` by tracking the initialized channels identifiers and being lenient only if command is received for a channel that was initialized in the past. * The internal moduli used in Diffie-Hellman group exchange are **cached** - lazy-loaded the 1st time such an exchange occurs. The cache can be invalidated (and thus force a re-load) by invoking `Moduli#clearInternalModuliCache`. * `DHGEXClient` implementation allows overriding the min./max. key sizes for a specific session Diffi-Helman group exchange via properties - see `DHGEXClient#PROP_DHGEX_CLIENT_MIN/MAX/PRF_KEY`. Similar applies for `DHGEXServer` but only for the message type=30 (old request). * `AbstractSignature#doInitSignature` is now provided also with the `Key` instance for which it is invoked. * The `MacInformation` interface has an extra `isEncryptThenMac` method (default=_false_) to enable distinction of this mode. * Provide configurable control over the client-side `ChannelSession` _stdin_ pump chunk size. * Client side `UserAuthKeyboardInteractive` allows configurable detection of plain-text password prompt. * Moved a few informative getters from `Session` to `SessionContext`. ## Behavioral changes and enhancements * [SSHD-926](https://issues.apache.org/jira/browse/SSHD-930) - Add support for OpenSSH 'lsetstat@openssh.com' SFTP protocol extension. * [SSHD-930](https://issues.apache.org/jira/browse/SSHD-930) - Added configuration allowing the user to specify whether client should wait for the server's identification before sending its own. * [SSHD-931](https://issues.apache.org/jira/browse/SSHD-931) - Using an executor supplier instead of a specific instance in `SftpSubsystemFactory` and `ScpCommandFactory`. * [SSHD-934](https://issues.apache.org/jira/browse/SSHD-934) - Fixed ECDSA public key encoding into OpenSSH format. * [SSHD-937](https://issues.apache.org/jira/browse/SSHD-937) - Provide session instance when creating a subsystem, user authentication, channel. * [SSHD-941](https://issues.apache.org/jira/browse/SSHD-941) - Allow user to override min./max. key sizes for a specific session Diffi-Helman group exchange via properties. * [SSHD-943](https://issues.apache.org/jira/browse/SSHD-943) - Provide session instance when KEX factory is invoked in order to create a KeyExchange instance. * [SSHD-945](https://issues.apache.org/jira/browse/SSHD-945) - Added sshd-contrib code that uses SHA1 with DSA regardless of its key length. * [SSHD-946](https://issues.apache.org/jira/browse/SSHD-946) - Supporting 'encrypt-then-MAC' mode. * [SSHD-947](https://issues.apache.org/jira/browse/SSHD-947) - Added configuration allowing the user to specify whether client should wait for the server's identification before sending KEX-INIT message. * [SSHD-948](https://issues.apache.org/jira/browse/SSHD-948) - Do not accept password authentication if the session is not encrypted. * [SSHD-949](https://issues.apache.org/jira/browse/SSHD-949) - Session should use cipher block size and not IV size to calculate padding. * [SSHD-953](https://issues.apache.org/jira/browse/SSHD-953) - Parse and strip quoted command arguments when executing a server-side command via local shell. * [SSHD-955](https://issues.apache.org/jira/browse/SSHD-955) - Provide configurable control over auto-detected password prompt in client-side `UserAuthKeyboardInteractive` implementation. * [SSHD-956](https://issues.apache.org/jira/browse/SSHD-956) - Using `System#nanoTime` to measure session idle/authentication timeouts apache-mina-sshd-46fc8d6/docs/changes/2.5.0.md000066400000000000000000000063611456036076300206060ustar00rootroot00000000000000# Introduced in version 2.5.0 ## Major code re-factoring * Reception of an `SSH_MSG_UNIMPLEMENTED` response to a `SSH_MSG_GLOBAL_REQUEST` is translated internally into same code flow as if an `SSH_MSH_REQUEST_FAILURE` has been received - see [SSHD-968](https://issues.apache.org/jira/browse/SSHD-968). * Server SFTP subsystem internal code dealing with the local files has been delegated to the `SftpFileSystemAccessor` in order to allow easier hooking into the SFTP subsystem. * Resolving a local file path for an SFTP remote one * Reading/Writing a file's attribute(s) * Creating files links * Copying / Renaming / Deleting files * `SftpVersionSelector` is now consulted when client sends initial command (as well as when session is re-negotiated) * `ScpCommandFactory` is also a `ShellFactory` that can be used to provide a minimalistic shell that is good enough for *WinSCP*. * Rework SFTP streams so that the client asks and receives as much data as possible - see [SSHD-979](https://issues.apache.org/jira/browse/SSHD-979). ## Minor code helpers * Handling of debug/ignore/unimplemented messages has been split into `handleXXX` and `doInvokeXXXMsgHandler` methods where the former validate the messages and deal with the idle timeout, and the latter execute the actual invcation. * Added overloaded methods that accept a `java.time.Duration` specifier for timeout value. * The argument representing the SFTP subsystem in invocations to `SftpFileSystemAccessor` has been enhanced to expose as much of the available functionality as possible. ## Behavioral changes and enhancements * [SSHD-964](https://issues.apache.org/jira/browse/SSHD-964) - Send SSH_MSG_CHANNEL_EOF when tunnel channel being closed. * [SSHD-967](https://issues.apache.org/jira/browse/SSHD-967) - Extra bytes written when `SftpRemotePathChannel#transferTo` is used. * [SSHD-968](https://issues.apache.org/jira/browse/SSHD-968) - Interpret SSH_MSG_UNIMPLEMENTED response to a heartbeat request as a liveness indicator * [SSHD-970](https://issues.apache.org/jira/browse/SSHD-970) - `transferTo` function of `SftpRemotePathChannel` will loop if count parameter is greater than file size * [SSHD-972](https://issues.apache.org/jira/browse/SSHD-972) - Add support for peers using OpenSSH "security key" key types * [SSHD-977](https://issues.apache.org/jira/browse/SSHD-977) - Apply consistent logging policy to caught exceptions * [SSHD-660](https://issues.apache.org/jira/browse/SSHD-660) - Added support for server-side signed certificate keys * [SSHD-984](https://issues.apache.org/jira/browse/SSHD-984) - Utility method to export KeyPair in OpenSSH format * [SSHD-992](https://issues.apache.org/jira/browse/SSHD-984) - Provide more hooks into the SFTP server subsystem via SftpFileSystemAccessor * [SSHD-997](https://issues.apache.org/jira/browse/SSHD-997) - Fixed OpenSSH private key decoders for RSA and Ed25519 * [SSHD-998](https://issues.apache.org/jira/browse/SSHD-998) - Take into account SFTP version preference when establishing initial channel * [SSHD-989](https://issues.apache.org/jira/browse/SSHD-989) - Read correctly ECDSA key pair from PKCS8 encoded data * [SSHD-1009](https://issues.apache.org/jira/browse/SSHD-1009) - Provide a minimalistic shell for supporting *WinSCP* SCP mode. apache-mina-sshd-46fc8d6/docs/changes/2.5.1.md000066400000000000000000000003141456036076300205770ustar00rootroot00000000000000# Introduced in version 2.5.1 ## Behavioral changes and enhancements * [SSHD-1022](https://issues.apache.org/jira/browse/SSHD-1022) NPE in `SftpOutputStreamAsync#flush()` if no data written in between. apache-mina-sshd-46fc8d6/docs/changes/2.6.0.md000066400000000000000000000133351456036076300206060ustar00rootroot00000000000000# Introduced in 2.6.0 ## Major code re-factoring * `SshServerMain` uses by default an ECDSA key instead of an RSA one. This can be overridden either by `-key-type / -key-size` or `-key-file` command line option. * [SSHD-1034](https://issues.apache.org/jira/browse/SSHD-1034) Rename `org.apache.sshd.common.ForwardingFilter` to `Forwarder`. * [SSHD-1035](https://issues.apache.org/jira/browse/SSHD-1035) Move property definitions to common locations. * [SSHD-1038](https://issues.apache.org/jira/browse/SSHD-1038) Refactor packages from a module into a cleaner hierarchy. * [SSHD-1080](https://issues.apache.org/jira/browse/SSHD-1080) Rework the PacketWriter to split according to the various semantics * [SSHD-1084](https://issues.apache.org/jira/browse/SSHD-1084) Revert the usage of asynchronous streams when forwarding ports. ## Minor code helpers * [SSHD-1004](https://issues.apache.org/jira/browse/SSHD-1004) Using a more constant time MAC validation to minimize timing side channel information leak. * [SSHD-1030](https://issues.apache.org/jira/browse/SSHD-1030) Added a NoneFileSystemFactory implementation * [SSHD-1042](https://issues.apache.org/jira/browse/SSHD-1042) Added more callbacks to SftpEventListener * [SSHD-1040](https://issues.apache.org/jira/browse/SSHD-1040) Make server key available after KEX completed. * [SSHD-1060](https://issues.apache.org/jira/browse/SSHD-1060) Do not store logger level in fields. * [SSHD-1064](https://issues.apache.org/jira/browse/SSHD-1064) Fixed `ClientSession#executeRemoteCommand` handling of STDERR in case of exception to behave according to its documentation * [SSHD-1076](https://issues.apache.org/jira/browse/SSHD-1076) Break down `ClientUserAuthService#auth` method into several to allow for flexible override * [SSHD-1077](https://issues.apache.org/jira/browse/SSHD-1077) Added command line option to request specific SFTP version in `SftpCommandMain` * [SSHD-1079](https://issues.apache.org/jira/browse/SSHD-1079) Experimental async mode on the local port forwarder * [SSHD-1086](https://issues.apache.org/jira/browse/SSHD-1086) Added SFTP aware directory scanning helper classes * [SSHD-1089](https://issues.apache.org/jira/browse/SSHD-1089) Added wrappers for one-time single session usage of SFTP/SCP clients * Propagate SCP file transfer ACK data to ScpTransferListener before validating it. ## Behavioral changes and enhancements * [SSHD-506](https://issues.apache.org/jira/browse/SSHD-506) Added support for AES-GCM ciphers. * [SSHD-954](https://issues.apache.org/jira/browse/SSHD-954) Improve validation of DH public key values. * [SSHD-1004](https://issues.apache.org/jira/browse/SSHD-1004) Deprecate DES, RC4 and Blowfish ciphers from default setup. * [SSHD-1004](https://issues.apache.org/jira/browse/SSHD-1004) Deprecate SHA-1 based key exchanges and signatures from default setup. * [SSHD-1004](https://issues.apache.org/jira/browse/SSHD-1004) Deprecate MD5-based and truncated HMAC algorithms from default setup. * [SSHD-1005](https://issues.apache.org/jira/browse/SSHD-1005) Added support for SCP remote-to-remote file transfer * [SSHD-1020](https://issues.apache.org/jira/browse/SSHD-1020) SSH connections getting closed abruptly with timeout exceptions. * [SSHD-1026](https://issues.apache.org/jira/browse/SSHD-1026) Improve build reproductibility. * [SSHD-1028](https://issues.apache.org/jira/browse/SSHD-1028) Fix SSH_MSG_DISCONNECT: Too many concurrent connections. * [SSHD-1032](https://issues.apache.org/jira/browse/SSHD-1032) Fix possible ArrayIndexOutOfBoundsException in ChannelAsyncOutputStream. * [SSHD-1033](https://issues.apache.org/jira/browse/SSHD-1033) Fix simultaneous usage of dynamic and local port forwarding. * [SSHD-1039](https://issues.apache.org/jira/browse/SSHD-1039) Fix support for some basic options in ssh/sshd cli. * [SSHD-1047](https://issues.apache.org/jira/browse/SSHD-1047) Support for SSH jumps. * [SSHD-1048](https://issues.apache.org/jira/browse/SSHD-1048) Wrap instead of rethrow IOException in Future. * [SSHD-1050](https://issues.apache.org/jira/browse/SSHD-1050) Fixed race condition in AuthFuture if exception caught before authentication started. * [SSHD-1053](https://issues.apache.org/jira/browse/SSHD-1053) Fixed handling of certified keys authentication. * [SSHD-1056](https://issues.apache.org/jira/browse/SSHD-1056) Added support for SCP remote-to-remote directory transfer - including '-3' option of SCP command CLI. * [SSHD-1057](https://issues.apache.org/jira/browse/SSHD-1057) Added capability to select a ShellFactory based on the current session + use it for "WinSCP" * [SSHD-1058](https://issues.apache.org/jira/browse/SSHD-1058) Improve exception logging strategy. * [SSHD-1059](https://issues.apache.org/jira/browse/SSHD-1059) Do not send heartbeat if KEX state not DONE * [SSHD-1063](https://issues.apache.org/jira/browse/SSHD-1063) Fixed known-hosts file server key verifier matching of same host with different ports * [SSHD-1066](https://issues.apache.org/jira/browse/SSHD-1066) Allow multiple binding to local port tunnel on different addresses * [SSHD-1070](https://issues.apache.org/jira/browse/SSHD-1070) OutOfMemoryError when use async port forwarding * [SSHD-1100](https://issues.apache.org/jira/browse/SSHD-1100) Updated used moduli for DH group KEX * [SSHD-1102](https://issues.apache.org/jira/browse/SSHD-1102) Provide filter support for SftpDirectoryStream * [SSHD-1104](https://issues.apache.org/jira/browse/SSHD-1104) Take into account possible key type aliases when using public key authentication * [SSHD-1107](https://issues.apache.org/jira/browse/SSHD-1107) Allow configuration of minimum DH group exchange key size via property or programmatically * [SSHD-1108](https://issues.apache.org/jira/browse/SSHD-1108) Increased minimum default DH group exchange key size to 2048 (but support 1024)apache-mina-sshd-46fc8d6/docs/changes/2.7.0.md000066400000000000000000000130041456036076300206000ustar00rootroot00000000000000# Introduced in 2.7.0 ## Major code re-factoring * [SSHD-1133](https://issues.apache.org/jira/browse/SSHD-1133) Re-factored locations and names of `ServerSession` and server-side `ChannelSession` related classes * Moved some helper methods and classes to more natural locations ## Minor code helpers * [SSHD-525](https://issues.apache.org/jira/browse/SSHD-525) Added support for SFTP `posix-rename@openssh.com` extension](http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=1.28&content-type=text/x-cvsweb-markup) - see section 3.3 * [SSHD-1083](https://issues.apache.org/jira/browse/SSHD-1083) Relaxed required `Nio2Connector/Acceptor` required constructor arguments * [SSHD-1085](https://issues.apache.org/jira/browse/SSHD-1085) Added `CliLogger` + more verbosity on `SshClientMain` * [SSHD-1109](https://issues.apache.org/jira/browse/SSHD-1109) Route tests JUL logging via SLF4JBridgeHandler * [SSHD-1109](https://issues.apache.org/jira/browse/SSHD-1109) Provide full slf4j logger capabilities to CliLogger + use it in all CLI classes * [SSHD-1110](https://issues.apache.org/jira/browse/SSHD-1110) Replace `Class#newInstance()` calls with `Class#getDefaultConstructor().newInstance()` * [SSHD-1111](https://issues.apache.org/jira/browse/SSHD-1111) Fixed SshClientCliSupport compression option detection * [SSHD-1116](https://issues.apache.org/jira/browse/SSHD-1116) Provide SessionContext argument to HostKeyIdentityProvider#loadHostKeys * [SSHD-1116](https://issues.apache.org/jira/browse/SSHD-1116) Provide SessionContext argument to PasswordIdentityProvider#loadPasswords * [SSHD-1116](https://issues.apache.org/jira/browse/SSHD-1116) Provide SessionContext argument to AuthenticationIdentitiesProvider#loadIdentities * [SSHD-1125](https://issues.apache.org/jira/browse/SSHD-1125) Added option to require immediate close of channel in command `ExitCallback` invocation * [SSHD-1127](https://issues.apache.org/jira/browse/SSHD-1127) Consolidated `SftpSubsystem` support implementations into `SftpSubsystemConfigurator` * [SSHD-1148](https://issues.apache.org/jira/browse/SSHD-1148) Generate a unique thread name for each `SftpSubsystem` instance ## Behavioral changes and enhancements * [SSHD-1085](https://issues.apache.org/jira/browse/SSHD-1085) Added more notifications related to channel state change for detecting channel closing or closed earlier. * [SSHD-1091](https://issues.apache.org/jira/browse/SSHD-1091) Renamed `sshd-contrib` top-level package in order to align naming convention. * [SSHD-1097](https://issues.apache.org/jira/browse/SSHD-1097) Added more `SessionListener` callbacks related to the initial version and key exchange * [SSHD-1097](https://issues.apache.org/jira/browse/SSHD-1097) Added more capability to send peer identification via `ReservedSessionMessagesHandler` * [SSHD-1097](https://issues.apache.org/jira/browse/SSHD-1097) Implemented [endless tarpit](https://nullprogram.com/blog/2019/03/22/) example in sshd-contrib * [SSHD-1109](https://issues.apache.org/jira/browse/SSHD-1109) Replace log4j with logback as the slf4j logger implementation for tests * [SSHD-1114](https://issues.apache.org/jira/browse/SSHD-1114) Added callbacks for client-side password authentication progress * [SSHD-1114](https://issues.apache.org/jira/browse/SSHD-1114) Added callbacks for client-side public key authentication progress * [SSHD-1114](https://issues.apache.org/jira/browse/SSHD-1114) Added callbacks for client-side host-based authentication progress * [SSHD-1114](https://issues.apache.org/jira/browse/SSHD-1114) Added capability for interactive password authentication participation via UserInteraction * [SSHD-1114](https://issues.apache.org/jira/browse/SSHD-1114) Added capability for interactive key based authentication participation via UserInteraction * [SSHD-1123](https://issues.apache.org/jira/browse/SSHD-1123) Add option to chunk data in ChannelAsyncOutputStream if window size is smaller than packet size * [SSHD-1125](https://issues.apache.org/jira/browse/SSHD-1125) Added mechanism to throttle pending write requests in BufferedIoOutputStream * [SSHD-1127](https://issues.apache.org/jira/browse/SSHD-1127) Added capability to register a custom receiver for SFTP STDERR channel raw or stream data * [SSHD-1132](https://issues.apache.org/jira/browse/SSHD-1132) Added SFTP client-side support for 'filename-charset' extension * [SSHD-1132](https://issues.apache.org/jira/browse/SSHD-1132) Added SFTP client-side support for 'filename-translation-control' extension * [SSHD-1132](https://issues.apache.org/jira/browse/SSHD-1132) Added SFTP servder-side support for non-UTF8 encoding of returned file names * [SSHD-1133](https://issues.apache.org/jira/browse/SSHD-1133) Added capability to specify a custom charset for parsing incoming commands to the `ScpShell` * [SSHD-1133](https://issues.apache.org/jira/browse/SSHD-1133) Added capability to specify a custom charset for returning environment variables related data from the `ScpShell` * [SSHD-1133](https://issues.apache.org/jira/browse/SSHD-1133) Added capability to specify a custom charset for handling the SCP protocol textual commands and responses * [SSHD-1136](https://issues.apache.org/jira/browse/SSHD-1136) Use configuration property to decide whether to allow fallback to DH group exchange using SHA-1 if no suitable primes found for SHA-256 * [SSHD-1137](https://issues.apache.org/jira/browse/SSHD-1137) Added capability to override LinkOption(s) when accessing a file/folder via SFTP * [SSHD-1147](https://issues.apache.org/jira/browse/SSHD-1147) SftpInputStreamAsync: get file size before SSH_FXP_OPENapache-mina-sshd-46fc8d6/docs/changes/2.8.0.md000066400000000000000000000054231456036076300206070ustar00rootroot00000000000000# Introduced in 2.8.0 ## Potential compatibility issues * Removed `ServerSession` argument from `SftpFileSystemAccessor` invocations since it can be retrieved from the provided `SftpSubsystemProxy` instance ## Minor code helpers * [SSHD-1193](https://issues.apache.org/jira/browse/SSHD-1193) Provide a more user-friendly text in case disconnecting due to timeout(s). * [SSHD-1196](https://issues.apache.org/jira/browse/SSHD-1196) Provide configurable support for SFTP output stream chunking behavior. * [SSHD-1226](https://issues.apache.org/jira/browse/SSHD-1226) Using literal constants for SFTP attributes key names ## Behavioral changes and enhancements * [SSHD-704](https://issues.apache.org/jira/browse/SSHD-704) Add support for RFC 8731 (curve25519 and curve448 key exchange algorithms) * [SSHD-1017](https://issues.apache.org/jira/browse/SSHD-1017) Add support for the chacha20-poly1305@openssh.com cipher * [SSHD-1161](https://issues.apache.org/jira/browse/SSHD-1161) Support OpenSSH client certificates for publickey authentication * [SSHD-1163](https://issues.apache.org/jira/browse/SSHD-1163) Wrong server key signature algorithm chosen in DH group key exchange * [SSHD-1164](https://issues.apache.org/jira/browse/SSHD-1164) Parsing of ~/.ssh/config Host patterns fails with extra whitespace * [SSHD-1166](https://issues.apache.org/jira/browse/SSHD-1166) Support creating signed OpenSSH certificates * [SSHD-1168](https://issues.apache.org/jira/browse/SSHD-1168) OpenSSH certificates: check certificate type * [SSHD-1172](https://issues.apache.org/jira/browse/SSHD-1172) Expiration of OpenSshCertificates needs to compare timestamps as unsigned long * [SSHD-1202](https://issues.apache.org/jira/browse/SSHD-1202) Provide SftpErrorDataHandler callback support for SFTP client. * [SSHD-1215](https://issues.apache.org/jira/browse/SSHD-1215) Treat ACE4_APPEND_DATA as a hint only in SFTP write mode determination * [SSHD-1216](https://issues.apache.org/jira/browse/SSHD-1216) Implement RFC 8332 server-sig-algs on the server * [SSHD-1217](https://issues.apache.org/jira/browse/SSHD-1217) Add special handling of SFTP directory entries listing if underlying file system is also SFTP * [SSHD-1218](https://issues.apache.org/jira/browse/SSHD-1218) SshAgentFactory.createClient() gets passed the session * [SSHD-1219](https://issues.apache.org/jira/browse/SSHD-1219) Obtaining rsa-sha2-256 or rsa-sha2-512 signatures from an SSH agent * [SSHD-1220](https://issues.apache.org/jira/browse/SSHD-1220) Reduce number of L(STAT) calls made by the SftpFileSystem * [SSHD-1221](https://issues.apache.org/jira/browse/SSHD-1221) Support key constraints when adding a key to an SSH agent * [SSHD-1226](https://issues.apache.org/jira/browse/SSHD-1226) Added SFTP server-side capability to provide file/folder custom extension attributes apache-mina-sshd-46fc8d6/docs/changes/2.9.0.md000066400000000000000000000155271456036076300206160ustar00rootroot00000000000000# Introduced in 2.9.0 ## Major code re-factoring ### Asynchronous API for making SSH global requests A new API in `Session` is introduced for making SSH global requests and handling the reply asynchronously. ```java public GlobalRequestFuture request(Buffer buffer, String request, ReplyHandler replyHandler) throws IOException; ``` The `Buffer` is supposed to contain the full request, including the `request` name (for instance, "tcpip-forward"), the `want-reply` flag, and any additional data needed. There are several possible ways to use it. * `want-reply == true` and `replyHandler != null`: the methods sends the request and returns a future that is fulfilled when the request was actually sent. The future is fulfilled with an exception if sending the request failed, or with `null` if it was sent successfully. Once the reply is received, the handler is invoked with the SSH command (`SSH_MSG_REQUEST_SUCCESS`, `SSH_MSG_REQUEST_FAILURE`, or `SSH_MSG_UNIMPLEMENTED`) and the buffer received. * `want-reply == true` and `replyHandler == null`: the method sends the request and returns a future that is fulfilled with an exception if sending it failed, or if a `SSH_MSG_REQUEST_FAILURE` or `SSH_MSG_UNIMPLEMENTED` reply was received. Otherwise the future is fulfilled with the received Buffer once the reply has been received. * `want-reply == false`: the method sends the request and returns a future that is fulfilled when the request was actually sent. The future is fulfilled with an exception if sending the request failed, or with an empty buffer if it was sent successfully. If `replyHandler != null`, it is invoked with an empty buffer once the request was sent. If the method throws an `IOException`, the request was not sent, and the handler will not be invoked. ## Potential compatibility issues Changes that may affect existing code ### A **new** SFTP configuration property has been introduced that limits the maximum amount of data that can be sent in a single *SSH_FXP_WRITE* packet - default=256KB ```java /** * Force the use of a max. packet length for {@link AbstractSftpSubsystemHelper#doWrite(Buffer, int)} protection * against malicious packets */ public static final Property MAX_WRITE_DATA_PACKET_LENGTH = Property.integer("sftp-max-writedata-packet-length", 256 * 1024); ``` This might cause SFTP write failures for clients that might have sent larger buffers and they have been accepted so far. If this happens, simply increase this value (though the choice of 256KB should be compatible with the vast majority of clients). ### SSH channel identifiers have been changed to use *long* instead of *int* in order to align them with the standard that required them to be *UINT32* values. The relevant API(s) have been modified accordingly - which may cause a few incompatibility issues with code that extends/implements existing `Channel` classes and interfaces. In this context, the *Channel* interface now extends *ChannelIdentifier* where *getId()* has been renamed to *getChannelId()* ### *long* used instead of *int* in most encoded/decoded packets that are specified as being *UINT32* There are several exceptions to this rule: * The SFTP packet *id* field - an "opaque" value anyway, not used for allocation or indexing anyway * Various flags and mask field - there is no reason to encapsulate them into a *long* value since they do not represent a cardinal number of 32 bits * Various status code fields - ditto. * Cases where the value serves as argument for allocation of other data structures based on its value - e.g., arrays, lists. This was done for *convenience* reasons since Java does not support unsigned array/list sizes. In such cases, special validation code was applied to make sure the requested value does not exceed `Integer#MAX_VALUE` (sometimes even less) in order to protect the code from malicious or malformed packets. It is important to bear in mind that in the vast majority of the cases we do not want to be able to allocate arrays or lists having billions of elements as it would almost definitely cause out-of-memory issues. ## User HOME directory resolution and usage have been moved to *PathUtils* Was originally in *HostConfigEntry*. ## Behavioral changes and enhancements * [SSHD-966](https://issues.apache.org/jira/browse/SSHD-966) Deadlock on disconnection at the end of key-exchange * [SSHD-1055](https://issues.apache.org/jira/browse/SSHD-1055) Shut down output on port-forwarded socket on EOF in tunnel * [SSHD-1231](https://issues.apache.org/jira/browse/SSHD-1231) Public key authentication: wrong signature algorithm used (ed25519 key with ssh-rsa signature) * [SSHD-1233](https://issues.apache.org/jira/browse/SSHD-1233) Added support for "limits@openssh.com" SFTP extension * [SSHD-1244](https://issues.apache.org/jira/browse/SSHD-1244) Fixed channel window adjustment handling of large UINT32 values * [SSHD-1244](https://issues.apache.org/jira/browse/SSHD-1244) Re-defined channel identifiers as `long` rather than `int` to align with protocol UINT32 definition * [SSHD-1246](https://issues.apache.org/jira/browse/SSHD-1246) Added SshKeyDumpMain utility * [SSHD-1247](https://issues.apache.org/jira/browse/SSHD-1247) Added support for Argon2id encrypted PUTTY keys * [SSHD-1254](https://issues.apache.org/jira/browse/SSHD-1254) Support host-based pubkey authentication in the client ("publickey-hostbound@openssh.com" KEX extension) * [SSHD-1253](https://issues.apache.org/jira/browse/SSHD-1253) Class loader fails to load org.apache.sshd.common.cipher.BaseGCMCipher * [SSHD-1256](https://issues.apache.org/jira/browse/SSHD-1256) PortForwardingTest.testRemoteForwardingSecondTimeInSameSession always fails in Github CI * [SSHD-1257](https://issues.apache.org/jira/browse/SSHD-1257) ChannelSession: don't flush out stream if already closed * [SSHD-1261](https://issues.apache.org/jira/browse/SSHD-1261) - Sometimes async write listener is not called * [SSHD-1262](https://issues.apache.org/jira/browse/SSHD-1262) TCP/IP port forwarding: don't buffer, and don't read from port before channel is open * [SSHD-1264](https://issues.apache.org/jira/browse/SSHD-1264) Create KEX negotiation proposal only once per session, not on every re-KEX * [SSHD-1266](https://issues.apache.org/jira/browse/SSHD-1266) Fix encoding/decoding critical options in OpenSSH certificates * [SSHD-1269](https://issues.apache.org/jira/browse/SSHD-1269) Fix TCP/IP remote port forwarding with wildcard addresses * [SSHD-1272](https://issues.apache.org/jira/browse/SSHD-1272) Use correct signature for RSA keys from SSH agent, and by default ignore keys for which there is no signature algorithm * [SSHD-1273](https://issues.apache.org/jira/browse/SSHD-1273) Add support to use env vars together with subsystem channels * [SSHD-1276](https://issues.apache.org/jira/browse/SSHD-1276) Added capability to redirect command/shell STDERR stream to STDOUT one apache-mina-sshd-46fc8d6/docs/changes/2.9.1.md000066400000000000000000000015041456036076300206050ustar00rootroot00000000000000# Introduced in 2.9.1 ## Bug fixes * [SSHD-1281](https://issues.apache.org/jira/browse/SSHD-1281) ClientSession.auth().verify() is terminated with timeout * [SSHD-1285](https://issues.apache.org/jira/browse/SSHD-1285) 2.9.0 release broken on Java 8 * [SSHD-1288](https://issues.apache.org/jira/browse/SSHD-1288) SFTP: fix reading files that are being written * [SSHD-1289](https://issues.apache.org/jira/browse/SSHD-1289) Deadlock during session exit * [SSHD-1290](https://issues.apache.org/jira/browse/SSHD-1290) Better logging in ChannelAsyncOutputStream ## Major code re-factoring ## Potential compatibility issues ## Minor code helpers ## Behavioral changes and enhancements * [SSHD-1283](https://issues.apache.org/jira/browse/SSHD-1283) Added configuration property to control whether *ScpShell* is enabled (default=true). apache-mina-sshd-46fc8d6/docs/changes/2.9.2.md000066400000000000000000000077371456036076300206240ustar00rootroot00000000000000# Introduced in 2.9.2 ## Bug fixes * [CVE-2022-45047](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-45047) Unsafe deserialization in `org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider` * [SSHD-1173](https://issues.apache.org/jira/browse/SSHD-1173) Not fully using up a channel window may lead to hangs (see [Channel windows](#channelwindows0) below) * [SSHD-1287](https://issues.apache.org/jira/browse/SSHD-1287) SFTP: reading with buffers larger than 126kB leads to data corruption * [SSHD-1293](https://issues.apache.org/jira/browse/SSHD-1293) ExplicitPortForwardingTracker does not unbind auto-allocated port * [SSHD-1294](https://issues.apache.org/jira/browse/SSHD-1294) Close MinaServiceFactory instances properly * [SSHD-1297](https://issues.apache.org/jira/browse/SSHD-1297) Avoid OutOfMemoryError when reading a public key from a corrupted Buffer * [SSHD-1302](https://issues.apache.org/jira/browse/SSHD-1302) Reading from Channel.getInvertedOut() after EOF was reached throws IOException instead of returning -1 * [SSHD-1303](https://issues.apache.org/jira/browse/SSHD-1303) Reading from redirected Channel.getInvertedErr() delivers stdout; should be at EOF * [SSHD-1307](https://issues.apache.org/jira/browse/SSHD-1307) [NIO2] TCP/IP port forwarding: shut down output stream only after pending writes have been written * [GH-263](https://github.com/apache/mina-sshd/issues/263) Race condition in BufferedIoOutputStream * [GH-266](https://github.com/apache/mina-sshd/issues/266) ChannelPipedOutputStream.flush() must be a no-op ## Major code re-factoring ## Potential compatibility issues ## Minor code helpers * New utility method `KeyUtils.loadPublicKey()` to read a public key file. ## Behavioral changes and enhancements * Netty I/O back-end: respect configurations for `CoreModuleProperties.SOCKET_BACKLOG` and `CoreModuleProperties.SOCKET_REUSEADDR`. * MINA I/O back-end: use `CoreModuleProperties.NIO2_READ_BUFFER_SIZE` for the initial read buffer size, if set. A new `CoreModuleProperties.MIN_READ_BUFFER_SIZE` can be set to control the minimum read buffer size (64 bytes by default in Apache MINA). * NIO2 I/O back-end: in TCP/IP port forwarding, shut down the output stream of a socket when a `SSH_MSG_CHANNEL_EOF` message is received on the SSH channel only after still pending writes have completed. See [SSHD-1307](https://issues.apache.org/jira/browse/SSHD-1307). The MINA and Netty I/O back-ends already did so. ### Channel windows Previous versions of Apache MINA sshd (from 2.6.0 to 2.9.1) did not always fully use up a channel window and waited for a `SSH_MSG_CHANNEL_WINDOW_ADJUST` message from the peer instead. They did so if the available window size was smaller than the packet size of the channel, and also smaller than the amount of data still to be written. There were settings to change this behavior and always fully use up a channel window: these settings were * `CoreModuleProperties.ASYNC_SERVER_STDOUT_CHUNK_BELOW_WINDOW_SIZE` * `CoreModuleProperties.ASYNC_SERVER_STDERR_CHUNK_BELOW_WINDOW_SIZE` * `SftpModuleProperties.CHUNK_IF_WINDOW_LESS_THAN_PACKET` By default, they were `false`; if set to `true`, the window would be used fully. Not using up a channel window may lead to hangs with peers that send the `SSH_MSG_CHANNEL_WINDOW_ADJUST` message only when the window size is very low, or even zero. The SSH RFCs do not mandate any particular point at which an implementation should adjust the window. OpenSSH and Apache MINA sshd itself do so when half of the window is used up, but there are other implementations that do so only when the available window size becomes zero. In this version, the above settings have been removed. Apache MINA sshd behaves always as if they were `true`, i.e., if there is some window space and there is data to write, data will be written. See Apache MINA sshd issues [SSHD-1123](https://issues.apache.org/jira/browse/SSHD-1123) and [SSHD-1173](https://issues.apache.org/jira/browse/SSHD-1173). apache-mina-sshd-46fc8d6/docs/cli.md000066400000000000000000000233301456036076300172760ustar00rootroot00000000000000## Command line clients The _apache-sshd.zip_ distribution provides `Windows/Linux` scripts that use the MINA SSHD code base to implement the common _ssh, scp, sftp_ commands. The clients accept most useful switches from the original commands they mimic, where the `-o Option=Value` arguments can be used to configure the client/server in addition to the system properties mechanism. For more details, consult the _main_ methods code in the respective `SshClientMain`, `SftpCommandMain` and `ScpClientMain` classes. The code also includes `SshKeyScanMain` that is a simple implementation for [ssh-keyscan(1)](https://www.freebsd.org/cgi/man.cgi?query=ssh-keyscan&sektion=1). The distribution also includes also an _sshd_ script that can be used to launch a server instance - see `SshServerMain#main` for activation command line arguments and options. In order to use this CLI code as part of another project, one needs to include the _sshd-cli_ module: ```xml org.apache.sshd sshd-cli ...same version as the core... ``` In general, the CLI clients accept most of their Linux counterpart arguments. Furthermore, one can use the `-o Option=Value` argument in order to provide **internal** SSHD code configurations (in addition to the ones specified as system properties via `-Dprop=value` JVM option. **Note:** not all options listed in [ssh_config](https://www.freebsd.org/cgi/man.cgi?query=ssh_config) or [sshd_config](https://linux.die.net/man/5/sshd_config) are supported, some of the `-o Option=Value` options have extra or special meaning, or are new altogether. Here are a few worth mentioning: #### `Ciphers` Comma-separated list of allowed/supported ciphers in their **order** of preference. #### `MACs` Comma-separated list of allowed/supported message authentication code algorithms in their **order** of preference. #### `KexAlgorithms` Comma-separated list of allowed/supported key exchange algorithms in their **order** of preference. #### `HostKeyAlgorithms` Comma-separated list of allowed/supported signature algorithms in their **order** of preference. #### `Compression` Whether to use compression, and if so which. #### `LogLevel` The verbosity level that is used when logging messages - **Note:** this is not the same as the internal logging configuration but rather an extra verbosity level of the CLI code itself - instructing it what extra data to display in STDOUT/STDERR. Each specific CLI (scp, sftp, ssh, sshd) has its own interpretation of this value. #### `PreferredAuthentications` The preferred user authentications factory names and their **order**: ``` # Allow only public key authentication -o PreferredAuthentications=publickey # Prefer keyboard-interactive BEFORE publickey -o PreferredAuthentications=keyboard-interactive,publickey ``` #### `ShellFactory` One can use it specify a non-default shell factory - including disabling it altogether - or *add* the SCP shell to an existing one: ``` # Disable shell entirely -o ShellFactory=none # Add the SCP shell to the default factory -o ShellFactory=+scp # Use ONLY the SCP shell -o ShellFactory=scp # Use a custom factory -o ShellFactory=com.demo.MyShellFactory # Add the SCP shell to a custom factory -o ShellFactory=scp+com.demo.MyShellFactory ``` #### `Subsystem` Can be used to specify built-in or custom subsystems to use in the server - or disable them altogether: ``` # Disable all subsystems -o Subsystem=none # Use the built-in SFTP subsystem -o Subsystem=sftp # Use one or more custom subsystems -o Subsystem=Sub1,Sub2,Sub3 ``` **Note:** Subsystems are automatically detected via `ServiceLoader#load(SubsystemFactory.class)` call - the option value simply states which ones to use - according to their *logical* name. #### Server/Client heartbeat Controlled by a combination of the `ServerAliveInterval`, `ClientAliveInterval`, `ClientAliveUseNullPackets` and `ClientAliveReplyWait` properties. #### Host keys and certificate `HostKey` and `HostCertificate` properties - enable specifying multiple paths to key files/certificates. #### `Banner` / `VisualHostKey` Controls the server's banner display. #### `AllowTcpForwarding` / `AllowAgentForwarding` / `X11Forwarding` Control server forwarding capabilities. ### `SftpCommandMain` A CLI client reminiscent of [sftp(1)](https://linux.die.net/man/1/sftp). By default uses an internal `SftpClientFactory`. This can be overridden as follows: 1. Provide a `-o SftpClientFactory=XXX` command line argument where the option specifies the fully-qualified name of the class that implements this interface. 2. Add a `META-INF\services\org.apache.sshd.sftp.client.SftpClientFactory` file containing the fully-qualified name of the class that implements this interface. **Note:** if more than one such instance is detected an exception is thrown. **Note:** The specified class(es) must be public and contain a public no-args constructor. The CLI client provides a few extra "commands" that can be used to view metadata information about the current session * `session` - Show current SSH session details - including ID, client/server identification line, peer, etc.. * `kex` - Show KEX details - client proposal, server one and negotiated parameters. * `info` - General details about the SFTP protocol - e.g., supported extensions by the server. * `version` - The negotiated SFTP protocol version. * `help` - List all available commands. * `exit` - Quit the SFTP session ### `SshClientMain` A CLI client compatible with the [ssh(1)](https://linux.die.net/man/1/ssh) command line options, with a few extra options: * `-io` - select a specific `IoServiceFactoryFactory`: ``` java -cp ... org.apache.sshd.cli.client.SshClientMain -io ``` Where value can be: * One of the default builtin values (NIO2, MINA, NETTY) * A fully qualified class name implementing this interface If no specific value provided NIO2 is used. * `-w ` - provide a password as part of the command instead of waiting to be prompted. ``` java -cp ... org.apache.sshd.cli.client.SshClientMain -l -w ...host... ``` * `SetEnv/SendEnv` - can be used to send specific environment variables to the server when executing a command or opening a shell. Example: ``` java -cp ... org.apache.sshd.cli.client.SshClientMain -o SetEnv=X=7,Y=8 # Can also be used as separate options java -cp ... org.apache.sshd.cli.client.SshClientMain -o SetEnv=X=7 -o SetEnv=Y=8 ``` * `RequestTTY` - can be `no`, `yes` or `auto` (default). If `auto` the CLI client will attempt to initialize the PTY options according to the O/S. In **addition** to the auto-detected PTY modes, one can override them by using the `PtyMode` option: ``` java -cp ... org.apache.sshd.cli.client.SshClientMain -o PtyMode=VINTR,TTY_OP_ISPEED=4200 # Can also be used as separate options java -cp ... org.apache.sshd.cli.client.SshClientMain -o PtyMode=VINTR -o PtyMode=TTY_OP_ISPEED=4200 ``` Any option that does not have a specific value specified for it is assumed to use `1` - therefore, in order to **disable** an option one must use `-o PtyMode=WHATEVER=0`. ### `ScpCommandMain` Reminiscent of the [scp(1)](https://man7.org/linux/man-pages/man1/scp.1.html) CLI client - including support for "3-way" copy (a.k.a. remote-to-remote) option: ``` scp -p -r -3 user1@server1:source user2@server2:destination ``` In this context, it is worth mentioning that the CLI also supports URI locations having the format `scp://[user@]host[:port][/path]` ``` # If port is omitted then 22 is assumed scp -p scp://user1@server1:2222/source/file /home/user2/destination # Note: same effect can be achieved with -P option scp -p -P 2222 user1@server1:source/file /home/user2/destination # the URI is better suited for remote-to-remote transfers scp -p -r -3 scp://user1@server1:2222/source scp://user2@server2:3333/destination ``` ### `SshServerMain` Command line SSH daemon * **Port** - by default the SSH server sets up to list on port 8000 in order to avoid conflicts with any running SSH O/S daemon. This can be modified by providing a `-p NNNN` or `-o Port=NNNN` command line option. * **Subsystem(s)** - the server automatically detects subsystems using the [Java ServiceLoader mechanism](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html). This can be overwritten as follows (in this order): 1. Provide a `org.apache.sshd.server.subsystem.SubsystemFactory` system property containing comma-separated fully-qualified names of classes implementing this interface. The implementations must be public and have a public no-args constructor for instantiating them. The order of the provided subsystems will be according to their order in the specified list. 2. Provide a `-o Subsystem=xxx,yyy` command line argument where value is a comma-separated list of the **name**(s) of the auto-detected factories via the `ServiceLoader` mechanism. The special value `none` may be used to indicate that no subsystem is to be configured. **Note:** no specific order is provided when subsystems are auto-detected and/or filtered. * **Shell** - unless otherwise instructed, the default SSH server uses an internal shell (see `InteractiveProcessShellFactory`). The shell can be overridden or disabled by specifying a `-o ShellFactory=XXX` option where the value can either be `none` to specify that no shell is to be used, or the fully-qualified name of a class that implements the `ShellFactory` interface. The implementation must be public and have a public no-args constructor for instantiating it. **Note:** A special value of `scp` can be used to use the built-in `ScpShell` instead of the interactive one (reminder: the SCP "shell" is a limited shell that provides a good enough functionality for *WinScp*). apache-mina-sshd-46fc8d6/docs/client-setup.md000066400000000000000000000620411456036076300211450ustar00rootroot00000000000000# Set up an SSH client in 5 minutes SSHD is designed to easily allow setting up and using an SSH client in a few simple steps. The client needs to be configured and then started before it can be used to connect to an SSH server. There are a few simple steps for creating a client instance - for more details refer to the `SshClient` class. ## Creating an instance of the `SshClient` class This is simply done by calling ```java SshClient client = SshClient.setUpDefaultClient(); ``` The call will create an instance with a default configuration suitable for most use cases - including ciphers, compression, MACs, key exchanges, signatures, etc... If your code requires some special configuration, one can look at the code for `setUpDefaultClient` and `checkConfig` as a reference for available options and configure the SSH client the way you need. ## Set up client side security The SSH client contains some security related configuration that one needs to consider ### `ServerKeyVerifier` `client.setServerKeyVerifier(...);` sets up the server key verifier. As part of the SSH connection initialization protocol, the server proves its "identity" by presenting a public key. The client can examine the key (e.g., present it to the user via some UI) and decide whether to trust the server and continue with the connection setup. By default the client is initialized with an `AcceptAllServerKeyVerifier` that simply logs a warning that an un-verified server key was accepted. There are other out-of-the-box verifiers available in the code: * `RejectAllServerKeyVerifier` - rejects all server key - usually used in tests or as a fallback verifier if none of it predecesors validated the server key * `RequiredServerKeyVerifier` - accepts only **one** specific server key (similar to certificate pinning for SSL) * `KnownHostsServerKeyVerifier` - uses the [known_hosts](https://en.wikibooks.org/wiki/OpenSSH/Client_Configuration_Files#Public_Keys_from_other_Hosts_.E2.80.93_.7E.2F.ssh.2Fknown_hosts) file to validate the server key. One can use this class + some existing code to **update** the file when new servers are detected and their keys are accepted. Of course, one can implement the verifier in whatever other manner is suitable for the specific code needs. ### `ClientIdentityLoader/KeyPairProvider` One can set up the public/private keys to be used in case a password-less authentication is needed. By default, the client is configured to automatically detect and use the identity files residing in the user's *~/.ssh* folder (e.g., *id_rsa*, *id_ecdsa*) and present them as part of the authentication process. **Note:** if the identity files are encrypted via a password, one must configure a `FilePasswordProvider` so that the code can decrypt them before using and presenting them to the server as part of the authentication process. Reading key files in PEM format (including encrypted ones) is supported by default for the standard keys and formats. Using additional non-standard special features requires that the [Bouncy Castle](https://www.bouncycastle.org/) supporting artifacts be available in the code's classpath. #### Loading key files In order to use password-less authentication the user needs to provide one or more `KeyPair`-s that are used to "prove" the client's identity for the server. The code supports most if not all of the currently used key file formats. See `SshKeyDumpMain` class for example of how to load files - basically: ```java KeyPairResourceLoader loader = SecurityUtils.getKeyPairResourceParser(); Collection keys = loader.loadKeyPairs(null, filePath, passwordProvider); ``` For *PUTTY* key files one needs to include the *sshd-putty* module and use a different loader: ```java Collection keys = PuttyKeyUtils.DEFAULT_INSTANCE.loadKeyPairs(null, filePath, passwordProvider); ``` **Note:** reminder - a user's "identity" is the file that contains the **private** key - there is no need to provide the public key file since the private key either already contains the public key in it, or it can be easily calculated from the private one. Once the keys are loaded, one simply needs to provide them to the client session: ```java try (ClientSession session = ...estblish initial session...) { for (KeyPair kp : keys) { session.addKeyIdentity(kp); } session.auth().await(...); } ``` Instead of doing this on every session, it is possible to load the keys only **once** and then wrap them inside a `KeyIdentityProvider` that is setup during *SshClient* setup: ```java Collection keys = ...load the keys ... SshClient client = ...setup client... client.setKeyIdentityProvider(KeyIdentityProvider.wrapKeyPairs(keys)); client.start(); ``` The provided keys will be used for **all* the sessions - *Note:* * One can **add** key identities to specific sessions. * A similar effect can be achiveved for **passwords** by registering a `PasswordIdentityProvider` with the *SshClient*, and thus forego the need to provide the password repeatedly for each session. In this context, one can go even one step forward and provide a **combined** `AuthenticationIdentitiesProvider` that provides **both** passwords and key pairs. Both type of providers are invoked with the established `SessionContext` so the user can actually pick which mechanism to use, what password/key to use according to the server's identity. #### Providing passwords for encrypted key files The `FilePasswordProvider` is required for all private key files that are encrypted and being loaded (not just the "identity" ones). If the user knows ahead of time that the file being currently decoded is not encrypted, a *null* provider may be used (if the file turns out to be encrypted though an exception will be thrown in this case). The `FilePasswordProvider`has support for a **retry mechanism** via its `handleDecodeAttemptResult`. When the code detects an encrypted private key, it will start a loop where it prompts for the password, attempts to decode the key using the provided password and then informs the provider of the outcome - success or failure. If failure is signaled, then the provider can decide whether to retry using a new password, abort (with exception) or ignore. If the provider chooses to ignore the failure, then the code will make a best effort to proceed without the (undecoded) key. The invoked methods are provided with a `NamedResource` that provides an indication of the key source "name" that is being attempted. This name can be used in order to prompt the user interactively and provide a useful "hint" as to the password that needs to be provided. Furthermore, the vast majority of the provided `NamedResource`-s also implement `IoResource` - which means that the code can find out what type of resource is being attempted - e.g., a file [Path](https://docs.oracle.com/javase/8/docs/api/index.html?java/nio/file/Path.html), a [URL](https://docs.oracle.com/javase/8/docs/api/java/net/URL.html), a [URI](https://docs.oracle.com/javase/8/docs/api/java/net/URI.html), etc. - and modify it's behavior accordingly. #### OpenSSH file format support The code supports [OpenSSH](http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?rev=1.1&content-type=text/x-cvsweb-markup) formatted files without any specific extra artifacts (although for reading _ed25519_ keys one needs to add the _EdDSA_ support artifacts). For **encrypted** files only the the `bcrypt` key derivation function (KDF) is [currently supported](https://issues.apache.org/jira/browse/SSHD-708). In this context, the maximum allowed number of rounds has been set to ~255 in order to protect the decryption process from malformed or malicious data. However, since the protocol allows for 2^31 values, it is possible to modify the default by calling `BCryptKdfOptions#setMaxAllowedRounds()` **programmatically** at any time - please note that * The setting is **global** - i.e., affects all decryption attempts from then on and not just for the current SSH session or thread. * The setting value is never allowed to be non-positive - any attempt to set such a value programmatically throws an exception. The usual _OpenSSH_ default seems to be 16, but users can ask for more (or less) by generating an encrypted key via [`ssh-keygen -a NNN`](http://man7.org/linux/man-pages/man1/ssh-keygen.1.html). However, this comes at a cost: >> -a rounds >> >> When saving a private key this option specifies the number of >> KDF (key derivation function) rounds used. Higher numbers >> result in slower passphrase verification Various discussions on the net seem to indicate that 64 is the value at which many computers start to slow down noticeably, so our default limit seems quite suitable (and beyond) for most cases we are likely to encounter "in the wild". ### `UserInteraction` This interface is required for full support of `keyboard-interactive` authentication protocol as described in [RFC-4252 section 9](https://tools.ietf.org/html/rfc4252#section-9). The client can handle a simple password request from the server, but if more complex challenge-response interaction is required, then this interface must be provided - including support for `SSH_MSG_USERAUTH_PASSWD_CHANGEREQ` as described in [RFC 4252 section 8](https://tools.ietf.org/html/rfc4252#section-8). While [RFC-4256](https://tools.ietf.org/html/rfc4256) support is the primary purpose of this interface, it can also be used to retrieve the server's welcome banner as described in [RFC 4252 section 5.4](https://tools.ietf.org/html/rfc4252#section-5.4) as well as its initial identification string as described in [RFC 4253 section 4.2](https://tools.ietf.org/html/rfc4253#section-4.2). In this context, regardless of whether such interaction is configured, the default implementation for the client side contains code that attempts to auto-detect a password prompt. If it detects it, then it attempts to use one of the registered passwords (if any) as the interactive response to the server's challenge - (see client-side implementation of `UserAuthKeyboardInteractive#useCurrentPassword` method). Basically, detection occurs by checking if the server sent **exactly one** challenge with no requested echo, and the challenge string looks like `"... password ...:"` (**Note:** the auto-detection and password prompt detection patterns are configurable). This interface can also be used to easily implement interactive password request from user for the `password` authentication protocol as described in [RFC-4252 section 8](https://tools.ietf.org/html/rfc4252#section-8) via the `resolveAuthPasswordAttempt` method. ```java /** * Invoked during password authentication when no more pre-registered passwords are available * * @param session The {@link ClientSession} through which the request was received * @return The password to use - {@code null} signals no more passwords available * @throws Exception if failed to handle the request - Note: may cause session termination */ String resolveAuthPasswordAttempt(ClientSession session) throws Exception; ``` The interface can also be used to implement interactive key based authentication as described in [RFC-4252 section 7](https://tools.ietf.org/html/rfc4252#section-7) via the `resolveAuthPublicKeyIdentityAttempt` method. ```java /** * Invoked during public key authentication when no more pre-registered keys are available * * @param session The {@link ClientSession} through which the request was received * @return The {@link KeyPair} to use - {@code null} signals no more keys available * @throws Exception if failed to handle the request - Note: may cause session termination */ KeyPair resolveAuthPublicKeyIdentityAttempt(ClientSession session) throws Exception; ``` ## Using the `SshClient` to connect to a server Once the `SshClient` instance is properly configured it needs to be `start()`-ed in order to connect to a server. **Note:** one can use a single `SshClient` instance to connnect to multiple servers as well as modifying the default configuration (ciphers, MACs, keys, etc.) on a per-session manner (see more in the *Advanced usage* section). Furthermore, one can change almost any configured `SshClient` parameter - although its influence on currently established sessions depends on the actual changed configuration. Here is how a typical usage would look like ```java SshClient client = SshClient.setUpDefaultClient(); // override any default configuration... client.setSomeConfiguration(...); client.setOtherConfiguration(...); client.start(); // using the client for multiple sessions... try (ClientSession session = client.connect(user, host, port) .verify(...timeout...) .getSession()) { session.addPasswordIdentity(...password..); // for password-based authentication // or session.addPublicKeyIdentity(...key-pair...); // for password-less authentication // Note: can add BOTH password AND public key identities - depends on the client/server security setup session.auth().verify(...timeout...); // start using the session to run commands, do SCP/SFTP, create local/remote port forwarding, etc... } // NOTE: this is just an example - one can open multiple concurrent sessions using the same client. // No need to close the previous session before establishing a new one try (ClientSession anotherSession = client.connect(otherUser, otherHost, port) .verify(...timeout...) .getSession()) { anotherSession.addPasswordIdentity(...password..); // for password-based authentication anotherSession.addPublicKeyIdentity(...key-pair...); // for password-less authentication anotherSession.auth().verify(...timeout...); // start using the session to run commands, do SCP/SFTP, create local/remote port forwarding, etc... } // exiting in an orderly fashion once the code no longer needs to establish SSH session // NOTE: this can/should be done when the application exits. client.stop(); ``` ## Configuring the protocol exchange phase [RFC 4253 section 4.2](https://tools.ietf.org/html/rfc4253#section-4.2) does not specify when the client/server should send their respective identification strings. All it states is that these strings must be available before KEX stage since they participate in it. By default, the client sends its identification string immediately upon session being established. However, this can be modified so that the client waits for the server's identification before sending its own. ```java SshClient client = ...setup client... PropertyResolverUtils.updateProperty( client, CoreModuleProperties.SEND_IMMEDIATE_IDENTIFICATION.getName(), false); client.start(); ``` A similar configuration can be applied to sending the initial `SSH_MSG_KEXINIT` message - i.e., the client can be configured to wait until the server's identification is received before sending the message. This is done in order to allow clients to customize the KEX phase according to the parsed server identification. ```java SshClient client = ...setup client... PropertyResolverUtils.updateProperty( client, CoreModuleProperties.SEND_IMMEDIATE_KEXINIT.getName(), false); client.start(); ``` **Note:** if immediate sending of the client's identification is disabled, `SSH_MSG_KEXINIT` message sending is also automatically delayed until after the server's identification is received. A viable configuration might be to send the client's identification immediately, but delay the client's `SSH_MSG_KEXINIT` message sending until the server's identification is received so that the client can customize the session based on the server's identity. This is a more likely configuration then delaying the client's own identification in order to be able to cope with port multiplexors such as [sslh](http://www.rutschle.net/tech/sslh/README.html). Such multiplexors usually require that the client send an initial packet immediately after connection is established so that they can analyze it and route it to the correct server (_ssh_ in this case). If we delay the client's identification, then obviously no server identification will ever be received since the multiplexor does not know how to route the connection. ## Keeping the session alive while no traffic The client-side implementation supports several mechanisms for maintaining the session alive as far as the **server** is concerned regardless of the user's own traffic: * Sending `SSH_MSG_IGNORE` messages every once in a while. This mechanism is along the lines of [PUTTY null packets configuration](https://patrickmn.com/aside/how-to-keep-alive-ssh-sessions/). It generates small [`SSH_MSG_IGNORE`](https://tools.ietf.org/html/rfc4253#section-11.2) messages. The way to set this mechanism up is via the `setSessionHeartbeat` API. *Note:* the same effect can also be achieved by setting the relevant properties documented in `SessionHeartbeatController`, but it is highly recommended to use the API - unless one needs to control these properties **externally** via `-Dxxx` JVM options. * Sending `keepalive@...` [global requests](https://tools.ietf.org/html/rfc4254#section-4). The feature is controlled via the `CoreModuleProperties#HEARTBEAT_REQUEST` and `HEARTBEAT_INTERVAL` properties - see the relevant documentation for these features. The simplest way to activate this feature is to set the `HEARTBEAT_INTERVAL` property value to the **milliseconds** value of the requested heartbeat interval. This configuration only ensures that the **server** does not terminate the session due to no traffic. If the incoming traffic from the server may also suffer from long "quiet" periods, one runs the risk of a **client** time-out. In order to avoid this, it is possible to activate the `wantReply` option for the global request. This way, there is bound to be some packet response (even if failure - which will be ignored by the heartbeat code). In order to activate this option one needs to set the `HEARTBEAT_REPLY_WAIT` property value to a **positive** value specifying the number of **milliseconds** the client is willing to wait for the server's reply to the global request. * Customized user code In order to support customized user code for this feature, the `ReservedSessionMessagesHandler` can be used to implement any kind of user-defined heartbeat. *Note:* if the user configured such a mechanism, then the `sendReservedHeartbeat` method **must** be implemented since the default throws `UnsupportedOperationException` which will cause the session to be terminated the 1st time the method is invoked. **Note(s):** * Mechanisms are disabled by default - they need to be activated explicitly. * Mechanisms can be activated either on the `SshClient` (for **global** setup) and/or the `ClientSession` (for specific session configuration). * The `keepalive@,,,,` mechanism **supersedes** the other mechanisms if activated. * If specified timeout expires for the `wantReply` option then session will be **closed**. * *Any* response - including [`SSH_MSH_REQUEST_FAILURE`](https://tools.ietf.org/html/rfc4254#page-4) is considered a "good" response for the heartbeat request. In this context, a special patch has been introduced in [SSHD-968](https://issues.apache.org/jira/browse/SSHD-968) that converts an `SSH_MSG_UNIMPLEMENTED` response to such a global request into a `SSH_MSH_REQUEST_FAILURE` since some servers have been found that violate the standard and reply with it to the request. * When using the CLI, these options can be configured using the following `-o key=value` properties: * `ClientAliveInterval` - if positive the defines the heartbeat interval in **seconds**. * `ClientAliveUseNullPackets` - *true* if use the `SSH_MSG_IGNORE` mechanism, *false* if use global request (default). * `ClientAliveReplyWait` - if positive, then activates the `wantReply` mechanism and specific the expected response timeout in **seconds**. ## Running a command or opening a shell ### Running a single non-interactive command ```java try (OutputStream stdout = ...create/obtain output stream...; OutputStream stderr = ...create/obtain output stream...; ClientChannel channel = session.createExecChannel(command)) { channel.setOut(stdout); channel.setErr(stderr); channel.open().verify(...some timeout...); // Wait (forever) for the channel to close - signalling command finished channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0L); } // Parse/handle the command's output/error streams ``` If all one needs is to run a non-interactive command and then look at its string output, one can use several of the available *ClientSession#executeRemoteCommand* overloaded methods. ### Running an interactive command/shell If one needs to parse the command/shell output and then respond by sending the correct input, the code must use **separate** thread(s) to read the STDOUT/STDERR and provide STDIN input. These threads must be up and running *before* opening the channel since data may start to pour in even before the *await/verify* call returns. If this data is not consumed at a reasonable pace, then channel may block and eventually even disconnect. Thus the thread(s) using the streams must be ready beforehand. ```java // The same code can be used when opening a ChannelExec in order to run a single interactive command try (ClientChannel channel = session.createShellChannel(/* use internal defaults */)) { channel.setIn(...stdin...); channel.setOut(...stdout...); channel.setErr(...stderr...); ...spawn the servicing thread(s).... try { channel.open().verify(...some timeout...); // Wait (forever) for the channel to close - signalling shell exited channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0L); } finally { // ... stop the pumping threads ... } } ``` In such cases it is recommended to use the inverted streams in the relevant threads ```java // The same code can be used when opening a ChannelExec in order to run a single interactive command try (ClientChannel channel = session.createShellChannel(/* use internal defaults */)) { try { channel.open().verify(...some timeout...); spawnStdinThread(channel.getInvertedIn()); spawnStdoutThread(channel.getInvertedOut()); spawnStderrThread(channel.getInvertedErr()); // Wait (forever) for the channel to close - signalling shell exited channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0L); } finally { // ... stop the pumping threads ... } } ``` ### Redirecting STDERR stream to STDOUT One can use a combined STDOUT/STDERR stream instead of separate ones: ```java ///////////////////////// Non-interactive /////////////////////////////// try (OutputStream mergedOutput = ...create/obtain output stream...; ClientChannel channel = session.createExecChannel(command)) { channel.setOut(mergedOutput); channel.redirectErrorStream(true); channel.open().verify(...some timeout...); // Wait (forever) for the channel to close - signalling command finished channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0L); } // Parse/handle the combined output/error streams ////////////////////////// Interactive //////////////////////////////////// try (ClientChannel channel = session.createShellChannel(/* use internal defaults */)) { try { channel.redirectErrorStream(true); channel.open().verify(...some timeout...); spawnStdinThread(channel.getInvertedIn()); spawnCombinedOutputThread(channel.getInvertedOut()); // Wait (forever) for the channel to close - signalling shell exited channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0L); } finally { // ... stop the pumping threads ... } } ``` **Note:** the call to *redirectErrorStream* must occur **before** channel is opened. Calling it afterwards has no effect - i.e., the last state before opening the stream determines the channel's behavior. ### PTY configuration When running a command or opening a shell, there is an extra concern regarding the PTY configuration and/or the reported environment variables. By default, unless specific instructions are provided, the code uses some internal defaults - which however, might not be adequate for the specific client/server. ```java // In order to override the PTY and/or environment Map env = ...some environment... PtyChannelConfiguration ptyConfig = ...some configuration... try (ClientChannel channel = session.createShellChannel(ptyConfig, env)) { ... same code as before ... } ``` One possible source of PTY configuration is code that provides some default initializations based on the detected O/S type - `PtyChannelConfigurationMutator#setupSensitiveDefaultPtyConfiguration`. Of course, the user may use whatever other considerations when opening such a channel. **Caveat Emptor:** If the detected O/S type is Unix/Linux, then the `setupSensitiveDefaultPtyConfiguration` code issues an `stty` command and parses the results (see `SttySupport` class). Since this involves using `System#exec` it is a source of concern as it may hang, throw an exception, provide corrupted data, etc... apache-mina-sshd-46fc8d6/docs/commands.md000066400000000000000000000210061456036076300203260ustar00rootroot00000000000000# Commands infrastucture ## `FileSystemFactory` usage This interface is used to provide "file"-related services/commands - e.g., SCP and SFTP - although it can be used for remote command execution as well (see the section about commands and the `Aware` interfaces). The default implementation is a `NativeFileSystemFactory` that simply exposes the [FileSystems.getDefault()](https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystems.html#getDefault) result. However, for "sandboxed" implementations one can use the `VirtualFileSystemFactory`. This implementation provides a way for deciding what is the logged-in user's file system view and then use a `RootedFileSystemProvider` in order to provide a "sandboxed" file system where the logged-in user can access only the files under the specified root and no others. ```java SshServer sshd = SshServer.setUpDefaultServer(); sshd.setFileSystemFactory(new VirtualFileSystemFactory() { @Override public Path getUserHomeDir(SessionContext session) throws IOException { ...use whatever information ... return somePath; } }); ``` The usage of a `FileSystemFactory` is not limited though to the server only - the `ScpClient` implementation also uses it in order to retrieve the *local* path for upload/download-ing files/folders. This means that the client side can also be tailored to present different views for different clients. A special "empty" `NoneFileSystemFactory` is provided in case no files are expected to be accessed by the server. ## `ExecutorService`-s The framework requires from time to time spawning some threads in order to function correctly - e.g., commands, SFTP subsystem, port forwarding (among others) require such support. By default, the framework will allocate an [ExecutorService](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html) for each specific purpose and then shut it down when the module has completed its work - e.g., session was closed. Note that SSHD uses the `CloseableExecutorService` interface instead of the usual `ExecutorService` in order to provide graceful shutdown. Users may provide their own `CloseableExecutorService`(s) instead of the internally auto-allocated ones - e.g., in order to control the max. spawned threads, stack size, track threads, etc... but they can leverage the `SshThreadPoolExecutor` implementation which should cover most use cases. Users who want to provide their own `ExecutorService` and not use `SshThreadPoolExecutor` should wrap it as a `NoCloseExecutor` and take care of shutting it down when SSHD is done with (provided, of course, that the user's own code does not need it to remain active afterwards...). ```java /* * An example user-provided executor service for SFTP - there are other such locations. * By default, the SftpSubsystem implementation creates a single-threaded executor * for each session, uses it to spawn the SFTP command handler and shuts * it down when the command is destroyed */ SftpSubsystemFactory factory = new SftpSubsystemFactory.Builder() .withExecutorServiceProvider(() -> new NoCloseExecutor(mySuperDuperExecutorService)) .build(); SshServer sshd = SshServer.setUpDefaultServer(); sshd.setSubsystemFactories(Collections.>singletonList(factory)); ``` If a single `CloseableExecutorService` is shared between several services, it needs to be wrapped with the `ThreadUtils.noClose(executor)` method. ```java CloseableExecutorService sharedService = ...obtain/create an instance...; SftpSubsystemFactory factory = new SftpSubsystemFactory.Builder() .withExecutorServiceProvider(() -> ThreadUtils.noClose(sharedService)) .build(); ChannelAgentForwarding forward = new ChannelAgentForwarding(ThreadUtils.noClose(sharedService)); ``` **Note:** Do not share the instance returned by `ThreadUtils.noClose` between services as it interferes with the graceful closing mechanism. Use a new wrapper instance for each service. ## Remote command execution All command execution - be it shell or single command - boils down to a `Command` instance being created, initialized and then started. In this context, it is **crucial** to notice that the command's `start()` method implementation **must spawn a new thread** - even for the simplest or most trivial command. Any attempt to communicate via the established session will most likely **fail** since the packets processing thread may be blocked by this call. **Note:** one might get away with executing some command in the context of the thread that called the `start()` method, but it is **extremely dangerous** and should not be attempted. The command execution code can communicate with the peer client via the input/output/error streams that are provided as part of the command initialization process. Once the command is done, it should call the `ExitCallback#onExit` method to indicate that it has finished. The framework will then take care of propagating the exit code, closing the session and (eventually) `destroy()`-ing the command. **Note**: the command may not assume that it is done until its `destroy()` method is called - i.e., it should not release or null-ify any of its internal state even if `onExit()` was called. Upon calling the `onExit` method the code sends an [SSH_MSG_CHANNEL_EOF](https://tools.ietf.org/html/rfc4254#section-5.3) message, and the provided result status code is sent as an `exit-status` message as described in [RFC4254 - section 6.10](https://tools.ietf.org/html/rfc4254#section-6.10). The provided message is simply logged at DEBUG level. ```java // A simple command implementation example class MyCommand implements Command, Runnable { private InputStream in; private OutputStream out, err; private ExitCallback callback; public MyCommand() { super(); } @Override public void setInputStream(InputStream in) { this.in = in; } @Override public void setOutputStream(OutputStream out) { this.out = out; } @Override public void setErrorStream(OutputStream err) { this.err = err; } @Override public void setExitCallback(ExitCallback callback) { this.callback = callback; } @Override public void start(Environment env) throws IOException { spawnHandlerThread(this); } @Override public void run() { while(true) { try { String cmd = readCommand(in); if ("exit".equals(cmd)) { break; } handleCommand(cmd, out); } catch (Exception e) { writeError(err, e); callback.onExit(-1, e.getMessage()); return; } callback.onExit(0); } @Override public void destroy() throws Exception { ...release any allocated resources... } } ``` ### `Aware` interfaces Once created, the `Command` instance is checked to see if it implements one of the `Aware` interfaces that enables injecting some dynamic data before the command is `start()`-ed. * `SessionAware` - Injects the `Session` instance through which the command request was received. * `ChannelSessionAware` - Injects the `ChannelSession` instance through which the command request was received. * `FileSystemAware` - Injects the result of consulting the `FileSystemFactory` as to the [FileSystem](https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystem.html) associated with this command. ### Data stream(s) sizing consideration Some commands may send/receive large amounts of data over their STDIN/STDOUT/STDERR streams. Since (by default) the sending mechanism in SSHD is **asynchronous** it may cause _Out of memory_ errors due to one side (client/server) generating `SSH_MSG_CHANNEL_DATA` or `SSH_MSG_CHANNEL_EXTENDED_DATA` at a much higher rate than the other side can consume. This leads to a build-up of a packets backlog that eventually consumes all available memory (as described in [SSHD-754](https://issues.apache.org/jira/browse/SSHD-754) and [SSHD-768](https://issues.apache.org/jira/browse/SSHD-768)). As of version 1.7 one can register a `ChannelStreamPacketWriterResolver` at the client/server/session/channel level that can enable the user to replace the raw channel with some throttling mechanism that will be used for stream packets. Such an (experimental) example is the `ThrottlingPacketWriter` available in the `sshd-contrib` module. **Note:** if the `ChannelStreamPacketWriterResolver` returns a wrapper instance instead of a `Channel` then it will be **closed** automatically when the stream using it is closed. apache-mina-sshd-46fc8d6/docs/dependencies.md000066400000000000000000000101571456036076300211600ustar00rootroot00000000000000# Optional dependencies ## [Bouncy Castle](https://www.bouncycastle.org/) Required mainly for writing keys to PEM files or for special keys/ciphers/etc. that are not part of the standard [Java Cryptography Extension](https://en.wikipedia.org/wiki/Java_Cryptography_Extension). See [Java Cryptography Architecture (JCA) Reference Guide](https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html) for key classes and explanations as to how _Bouncy Castle_ is plugged in (other security providers). **Caveat**: If _Bouncy Castle_ modules are registered, then the code will use its implementation of the ciphers, keys, signatures, etc. rather than the default JCE provided in the JVM. **Note:** - The security provider can also be registered for keys/ciphers/etc. that are already supported by the standard JCE as a **replacement** for them. - The _BouncyCastle_ code can also be used to load keys from PEM files instead or in parallel with the built-in code that already parses the standard PEM formats for the default JCE supported key types. - One can use the `BouncyCastleKeyPairResourceParser` to load standard PEM files instead of the core one - either directly or via `SecurityUtils#setKeyPairResourceParser` for **global** usage - even without registering or enabling the provider. - The required _Maven_ module(s) are defined as `optional` so must be added as an **explicit** dependency in order to be included in the classpath: ```xml org.bouncycastle bcpg-jdk15on org.bouncycastle bcpkix-jdk15on org.bouncycastle bcprov-jdk15on ``` ## NIO2 default socket factory replacements Optional dependency to enable choosing between NIO asynchronous sockets (the default - for improved performance), and "legacy" sockets. **Note:** the required Maven module(s) are defined as `optional` so must be added as an **explicit** dependency in order to be included in the classpath. ### [MINA core](https://mina.apache.org/mina-project/) ```xml org.apache.mina mina-core 2.0.17 org.apache.sshd sshd-mina ...same as sshd-core... ``` ### [Netty](https://netty.io/) Another a NIO client server framework option that can be used as a replacement for the default NIO asynchronous sockets core implementation. This is also an **optional** dependency and must be add explicitly via the `sshd-netty` artifact. ```xml io.netty netty-transport ...Netty version... io.netty netty-handler ...Netty version... org.apache.sshd sshd-netty ...same as sshd-core... ``` ## [ed25519-java](https://github.com/str4d/ed25519-java) Required for supporting [ssh-ed25519](https://tools.ietf.org/html/draft-bjh21-ssh-ed25519-02) keys and [ed25519-sha-512](https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-02) signatures. **Note:** the required Maven module(s) are defined as `optional` so must be added as an **explicit** dependency in order to be included in the classpath: ```xml net.i2p.crypto eddsa ``` The code contains support for reading _ed25519_ [OpenSSH formatted private keys](https://issues.apache.org/jira/browse/SSHD-703). apache-mina-sshd-46fc8d6/docs/event-listeners.md000066400000000000000000000253321456036076300216620ustar00rootroot00000000000000## Event listeners The code supports registering many types of event listeners that enable receiving notifications about important events as well as sometimes intervening in the way these events are handled. All listener interfaces extend `SshdEventListener` so they can be easily detected and distinguished from other `EventListener`(s). In general, event listeners are **cumulative** - e.g., any channel event listeners registered on the `SshClient/Server` are automatically added to all sessions, *in addition* to any such listeners registered on the `Session`, as well as any specific listeners registered on a specific `Channel` - e.g., ```java // Any channel event will be signalled to ALL the registered listeners sshClient/Server.addChannelListener(new Listener1()); sshClient/Server.addSessionListener(new SessionListener() { @Override public void sessionCreated(Session session) { session.addChannelListener(new Listener2()); session.addChannelListener(new ChannelListener() { @Override public void channelInitialized(Channel channel) { channel.addChannelListener(new Listener3()); } }); } }); ``` ### `IoServiceEventListener` This listener provides low-level events regarding connection establishment (by the client) or acceptance (by the server). The listener is registered on the `IoServiceFactory` via the `FactoryManager`-s (i.e., `SshClient/Server#setIoServiceEventListener`). Unlike other listeners defined in this section, it is **not cumulative** - i.e., one can `setIoServiceEventListener` but not `addIoServiceEventListener` - thus **replacing** any previously registered listener. ### `SessionListener` Informs about session related events. One can modify the session - although the modification effect depends on the session's **state**. E.g., if one changes the ciphers *after* the key exchange (KEX) phase, then they will take effect only if the keys are re-negotiated. Furthermore, invoking some session API(s) - event `getSomeValue` at the wrong time might yield unexpected results. It is important to read the documentation very carefully and understand at which stage each listener method is invoked, what are the limitations and what are the repercussions of changes at that stage. In this context, it is worth mentioning that one can attach to sessions **arbitrary attributes** that can be retrieved by the user's code later on: ```java public static final AttributeKey STR_KEY = new AttributeKey<>(); public static final AttributeKey LONG_KEY = new AttributeKey<>(); sshClient/Server.addSessionListener(new SessionListener() { @Override public void sessionEstablished(Session session) { // examine the peer address or the connection context and set some attributes } @Override public void sessionCreated(Session session) { session.setAttribute(STR_KEY, "Some string value"); session.setAttribute(LONG_KEY, 3777347L); // ...etc... } @Override public void sessionClosed(Session session) { String str = session.getAttribute(STR_KEY); Long l = session.getAttribute(LONG_KEY); // ... do something with the retrieved attributes ... } }); ``` The attributes cache is automatically cleared once the session is closed. ### `ChannelListener` Informs about channel related events - as with sessions, once can influence the channel to some extent, depending on the channel's **state**. The ability to influence channels is much more limited than sessions. In this context, it is worth mentioning that one can attach to channels **arbitrary attributes** that can be retrieved by the user's code later on and are cleared when channel is closed - same was as it is done for sessions. ### `UnknownChannelReferenceHandler` Invoked whenever a message intended for an unknown channel is received. By default, the code **ignores** the vast majority of such messages and logs them at DEBUG level. For a select few types of messages the code generates an `SSH_CHANNEL_MSG_FAILURE` packet that is sent to the peer session - see `DefaultUnknownChannelReferenceHandler` implementation. The user may register handlers at any level - client/server, session and/or connection service - the one registered "closest" to connection service will be used. An **experimental** `ChannelIdTrackingUnknownChannelReferenceHandler` is available in _sshd-contrib_ package that applies the "leniency" of the `DefaultUnknownChannelReferenceHandler` only if the unknown channel is one that has been assigned in the past - otherwise it throws an exception. In order to use it, the handler instance needs to be registered as **both** an `UnknownChannelReferenceHandler` and a `ChannelListener`. ### `KexExtensionHandler` Provides hooks for implementing [KEX extension negotiation](https://tools.ietf.org/html/rfc8308). **Note:** it can be used for monitoring the KEX mechanism and intervene in a more general case for other purposes as well. In any case, it is highly recommended though to read the interface documentation and also review the code that invokes it before attempting to use it. An **experimental** implementation example is available for the client side - see `DefaultClientKexExtensionHandler`. ### `ReservedSessionMessagesHandler` Can be used to handle the following cases: * Intervene during the initial identification and KEX * [SSH_MSG_IGNORE](https://tools.ietf.org/html/rfc4253#section-11.2) * [SSH_MSG_DEBUG](https://tools.ietf.org/html/rfc4253#section-11.3) * [SSH_MSG_UNIMPLEMENTED](https://tools.ietf.org/html/rfc4253#section-11.4) * Implementing a custom session heartbeat mechanism - for **both** [client](./client-setup.md#keeping-the-session-alive-while-no-traffic) or [server](./server-setup.md#providing-server-side-heartbeat). * Any other unrecognized message received in the session. **Note:** The `handleUnimplementedMessage` method serves both for handling `SSH_MSG_UNIMPLEMENTED` and any other unrecognized message received in the session as well. ```java class MyClientSideReservedSessionMessagesHandler implements ReservedSessionMessagesHandler { @Override public boolean handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception { switch(cmd) { case MY_SPECIAL_CMD1: .... return true; case MY_SPECIAL_CMD2: .... return true; default: return false; // send SSH_MSG_UNIMPLEMENTED reply if necessary } } } // client side SshClient client = SshClient.setUpDefaultClient(); // This is the default for ALL sessions unless specifically overridden client.setReservedSessionMessagesHandler(new MyClientSideReservedSessionMessagesHandler()); // Adding it via a session listener client.setSessionListener(new SessionListener() { @Override public void sessionCreated(Session session) { // Overrides the one set at the client level. if (isSomeSessionOfInterest(session)) { session.setReservedSessionMessagesHandler(new MyClientSessionReservedSessionMessagesHandler(session)); } } }); try (ClientSession session = client.connect(user, host, port).verify(...timeout...).getSession()) { // setting it explicitly session.setReservedSessionMessagesHandler(new MyOtherClientSessionReservedSessionMessagesHandler(session)); session.addPasswordIdentity(password); session.auth().verify(...timeout...); ...use the session... } // server side SshServer server = SshServer.setUpDefaultServer(); // This is the default for ALL sessions unless specifically overridden server.setReservedSessionMessagesHandler(new MyServerSideReservedSessionMessagesHandler()); // Adding it via a session listener server.setSessionListener(new SessionListener() { @Override public void sessionCreated(Session session) { // Overrides the one set at the server level. if (isSomeSessionOfInterest(session)) { session.setReservedSessionMessagesHandler(new MyServerSessionReservedSessionMessagesHandler(session)); } } }); ``` **NOTE:** Unlike "regular" event listeners, the handler is not cumulative - i.e., setting it overrides the previous instance rather than being accumulated. However, one can use the `EventListenerUtils` and create a cumulative listener - see how `SessionListener` or `ChannelListener` proxies were implemented. ### `SessionDisconnectHandler` This handler can be registered in order to monitor session disconnect initiated by the internal code due to various protocol requirements - e.g., unknown service, idle timeout, etc.. In many cases the implementor can intervene and cancel the disconnect by handling the problem somehow and then signaling to the code that there is no longer any need to disconnect. The handler can be registered globally at the `SshClient/Server` instance or per-session (via a `SessionListener`). **NOTE(s):** * This handler is non-cumulative - i.e., setting it replaces any existing previous handler instance. * If any exception is thrown from one of the invoked callback methods then session disconnect proceeds as if the handler decided not to intervene. ### `SignalListener` Informs about signal requests as described in [RFC 4254 - section 6.9](https://tools.ietf.org/html/rfc4254#section-6.9), "break" requests (sent as SIGINT) as described in [RFC 4335](https://tools.ietf.org/html/rfc4335) and "window-change" (sent as SIGWINCH) requests as described in [RFC 4254 - section 6.7](https://tools.ietf.org/html/rfc4254#section-6.7) ### `PasswordAuthenticationReporter` Used to inform about the progress of the client-side password based authentication as described in [RFC-4252 section 8](https://tools.ietf.org/html/rfc4252#section-8). Can be registered globally on the `SshClient` and also for a specific `ClientSession` after it is established but before its `auth()` method is called - thus overriding any globally registered instance. ### `PublicKeyAuthenticationReporter` Used to inform about the progress of the client-side public key authentication as described in [RFC-4252 section 7](https://tools.ietf.org/html/rfc4252#section-7). Can be registered globally on the `SshClient` and also for a specific `ClientSession` after it is established but before its `auth()` method is called - thus overriding any globally registered instance. ### `HostBasedAuthenticationReporter` Used to inform about the progress of the client-side host-based authentication as described in [RFC-4252 section 9](https://tools.ietf.org/html/rfc4252#section-9). Can be registered globally on the `SshClient` and also for a specific `ClientSession` after it is established but before its `auth()` method is called - thus overriding any globally registered instance. apache-mina-sshd-46fc8d6/docs/extensions.md000066400000000000000000000102151456036076300207240ustar00rootroot00000000000000# Extension modules There are several extension modules available - specifically, the _sshd-contrib_ module contains some of them. **Note:** the module contains experimental code that may find its way some time in the future to a standard artifact. It is also subject to changes and/or deletion without any prior announcement. Therefore, any code that relies on it should also store a copy of the sources in case the classes it used it are modified or deleted. ## LDAP adaptors The _sshd-ldap_ artifact contains an [LdapPasswordAuthenticator](https://issues.apache.org/jira/browse/SSHD-607) and an [LdapPublicKeyAuthenticator](https://issues.apache.org/jira/browse/SSHD-608) that have been written along the same lines as the [openssh-ldap-publickey](https://github.com/AndriiGrytsenko/openssh-ldap-publickey) project. The authenticators can be easily configured to match most LDAP schemes, or alternatively serve as base classes for code that extends them and adds proprietary logic. ## Useful extra components in _sshd-contrib_ * `InteractivePasswordIdentityProvider` - helps implement a `PasswordIdentityProvider` by delegating calls to `UserInteraction#getUpdatedPassword`. The way to use it would be as follows: ```java try (ClientSession session = client.connect(login, host, port).await().getSession()) { session.setUserInteraction(...); // this can also be set at the client level PasswordIdentityProvider passwordIdentityProvider = InteractivePasswordIdentityProvider.providerOf(session, "My prompt"); session.setPasswordIdentityProvider(passwordIdentityProvider); session.auth.verify(...timeout...); ... continue with the authenticated session ... } ``` or ```java UserInteraction ui = ....; try (ClientSession session = client.connect(login, host, port).await().getSession()) { PasswordIdentityProvider passwordIdentityProvider = InteractivePasswordIdentityProvider.providerOf(session, ui, "My prompt"); session.setPasswordIdentityProvider(passwordIdentityProvider); session.auth.verify(...timeout...); ... continue with the authenticated session ... } ``` **Note:** `UserInteraction#isInteractionAllowed` is consulted prior to invoking `getUpdatedPassword` - if it returns _false_ then password retrieval method is not invoked, and it is assumed that no more passwords are available * `SimpleAccessControlScpEventListener` - Provides a simple access control by making a distinction between methods that upload data and ones that download it via SCP. In order to use it, simply extend it and override its `isFileUpload/DownloadAllowed` methods * `SimpleAccessControlSftpEventListener` - Provides a simple access control by making a distinction between methods that provide SFTP file information - including reading data - and those that modify it * `ProxyProtocolAcceptor` - A working prototype to support the PROXY protocol as described in [HAProxy Documentation](http://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) * `ProxyProtocolV2Acceptor` - A working prototype to support the PROXY protocol V1 and V2 as described in [HAProxy Documentation](http://www.haproxy.org/download/2.7/doc/proxy-protocol.txt). This acceptor extends the `ProxyProtocolAcceptor` for V1 Protocol. * `ThrottlingPacketWriter` - An example of a way to overcome big window sizes when sending data - as described in [SSHD-754](https://issues.apache.org/jira/browse/SSHD-754) and [SSHD-768](https://issues.apache.org/jira/browse/SSHD-768) * `AndroidOpenSSLSecurityProviderRegistrar` - A security registrar that uses the [AndroidOpenSSL](https://github.com/guardianproject/openssl-android) security provider * `LegacyDSASigner` - A `java.security.Signature` that applies SHA-1 with DSA keys regardless of their key length - i.e., despite FIPS186-3 section 4.2 that mandates usage of SHA-2 for keys greater than 1024 bits. This is in accordance with RFC 4253 that was never amended to specify any other digest for such keys. The signer can be use to provide a custom implementation of `SignatureDSA` (and its factory) that uses this signer instead of the JCE or _Bouncycastle_ one - see comments on issue [SSHD-945](https://issues.apache.org/jira/browse/SSHD-945). apache-mina-sshd-46fc8d6/docs/files-parsing.md000066400000000000000000000143631456036076300213000ustar00rootroot00000000000000## Configuration/data files parsing support Most of the configuration data files parsing support resides in the _sshd-common_ artfiact: ```xml org.apache.sshd sshd-common ...same version as the rest of the artifacts... ``` The code contains support for parsing the [_authorized_keys_](http://man.openbsd.org/sshd.8#AUTHORIZED_KEYS_FILE_FORMAT), [_known\_hosts_](http://www.manpagez.com/man/8/sshd/), [_ssh\_config_, _sshd\_config_](https://www.freebsd.org/cgi/man.cgi?query=ssh_config&sektion=5), and [_~/config_](http://www.gsp.com/cgi-bin/man.cgi?topic=ssh_config) files. The code resides in the _sshd-common_ artifact - specifically the `KeyUtils#getPublicKeyEntryDecoder`, `AuthorizedKeyEntry#readAuthorizedKeys`, `KnownHostEntry#readKnownHostEntries` and `HostConfigEntry#readHostConfigEntries`. ### PEM/OpenSSH The common code contains built-in support for parsing PEM and/or _OpenSSH_ formatted key files and using them for authentication purposes. As mentioned previously, it can leverage _Bouncycastle_ if available, but can do most of the work without it as well. For _ed25519_ support, one must provide the _eddsa_ artifact dependency. ### [PUTTY](https://www.putty.org/) The code contains built-in support for parsing PUTTY key files (usually _.ppk_) and using them same as SSH ones as key-pair providers for autentication purposes. The PUTTY key file(s) readers are contained in the `org.apache.sshd.common.config.keys.loader.putty` package (specifically `PuttyKeyUtils#DEFAULT_INSTANCE KeyPairResourceParser`) of the _sshd-putty_ artifact. **Note:** the artifact should be included as an extra dependency: ```xml org.apache.sshd sshd-putty ...same version as the rest of the artifacts... ``` ### [OpenPGP](https://www.openpgp.org/) The code contains the _sshd-openpgp_ module that enables using _OpenPGP_ private key files as identity providers. ```xml org.apache.sshd sshd-openpgp ...same version as the rest of the artifacts... ``` The [support](https://issues.apache.org/jira/browse/SSHD-757) for it is currently still in its infancy, and therefore this feature should be considered **experimental** for the time being. However, within its limitations it supports * RSA keys * DSA keys * ECDSA keys (*) For now `ed25519` keys are not supported by this module. The code reads **all** the available key pairs in the key file without any distinction between encryption, decryption, authentication or signature ones. This code relies on the [jpgpj](https://github.com/justinludwig/jpgpj) support module ```xml org.c02e.jpgpj jpgpj ... ``` (which in turn automatically uses _Bouncycastle_ - so if one does not want _Bouncycastle_ one cannot use this module). #### Using OpenPGP authorized keys entries In order to be able to read `authorized_keys` files that may contain _OpenPGP_ keys references, one needs to register the relevant `PublicKeyEntryDataResolver`-s. This is done by calling `PGPPublicKeyEntryDataResolver#registerDefaultKeyEntryDataResolvers` once during the _main_ code setup. This will enable the code to safely read authorized keys entries having the format specified in the [OpenSSH PGP configuration](https://www.red-bean.com/~nemo/openssh-gpg/): ``` pgp-sign-dss 87C36E60187451050A4F26B134824FC95C781A18 with-comment pgp-sign-rsa 87C36E60187451050A4F26B134824FC95C781A18 ``` Where the key data following the key type specification is the fingerprint value of the referenced key. In order to use a "mixed mode" file (i.e., one that has both SSH and _OpenPGP_ keys) one needs to replace the default `AuthorizedKeysAuthenticator` instance with one that is derived from it and overrides the `createDelegateAuthenticator` method in a manner similar as shown below: ```java // Using PGPAuthorizedEntriesTracker public class MyAuthorizedKeysAuthenticatorWithBothPGPAndSsh extends AuthorizedKeysAuthenticator { ... constructor(s) ... @Override protected PublickeyAuthenticator createDelegateAuthenticator( String username, ServerSession session, Path path, Collection entries, PublicKeyEntryResolver fallbackResolver) throws IOException, GeneralSecurityException { PGPAuthorizedEntriesTracker tracker = ... obtain an instance ... // Note: need to catch the PGPException and transform it into either an IOException or a GeneralSecurityException Collection keys = tracker.resolveAuthorizedEntries(session, entries, fallbackResolver); if (GenericUtils.isEmpty(keys)) { return RejectAllPublickeyAuthenticator.INSTANCE; } else { return new KeySetPublickeyAuthenticator(id, keys); } } } // Using PGPPublicRingWatcher public class MyAuthorizedKeysAuthenticatorWithBothPGPAndSsh extends AuthorizedKeysAuthenticator { ... constructor(s) ... @Override protected PublickeyAuthenticator createDelegateAuthenticator( String username, ServerSession session, Path path, Collection entries, PublicKeyEntryResolver fallbackResolver) throws IOException, GeneralSecurityException { PGPPublicRingWatcher watcher = ... obtain an instance ... // Note: need to catch the PGPException and transform it into either an IOException or a GeneralSecurityException Collection keys = watcher.resolveAuthorizedEntries(session, entries, fallbackResolver); if (GenericUtils.isEmpty(keys)) { return RejectAllPublickeyAuthenticator.INSTANCE; } else { return new KeySetPublickeyAuthenticator(id, keys); } } } ``` **Note:** in order to support GPG v2 `.kbx` files one requires up-to-date [Bouncycastle](https://mvnrepository.com/artifact/org.bouncycastle/bcpg-jdk15on/1.61) and [jpgpj](https://mvnrepository.com/artifact/org.c02e.jpgpj/jpgpj/0.6.1) versions. apache-mina-sshd-46fc8d6/docs/git.md000066400000000000000000000064061456036076300173170ustar00rootroot00000000000000## GIT support The _sshd-git_ artifact contains both client and server-side command factories for issuing and handling some _git_ commands. The code is based on [JGit](https://github.com/eclipse/jgit) and iteracts with it smoothly. ### Client-side This module provides SSHD-based replacements for the SSH and SFTP transports used by the JGIT client - see `GitSshdSessionFactory` - it can be used as a drop-in replacement for the [JSCH](http://www.jcraft.com/jsch/) based built-in session factory provided by _jgit_. In this context, it is worth noting that the `GitSshdSessionFactory` has been tailored so as to provide flexible control over which `SshClient` instance to use, and even which `ClientSession`. The default instance allocates a **new** client every time a new `GitSshdSession` is created - which is started and stopped as necessary. However, this can be pretty wasteful, so if one intends to issue several commands that access GIT repositories via SSH, one should maintain a **single** client instance and re-use it: ```java SshClient client = ...create and setup the client... try { client.start(); GitSshdSessionFactory sshdFactory = new GitSshdSessionFactory(client); // re-use the same client for all SSH sessions org.eclipse.jgit.transport.SshSessionFactory.setInstance(sshdFactory); // replace the JSCH-based factory ... issue GIT commands that access remote repositories via SSH .... } finally { client.stop(); } ``` ### Server-side See `GitPackCommandFactory` and `GitPgmCommandFactory` - in order for the various commands to function correctly, they require a `GitLocationResolver` that is invoked in order to allow the user to decide which is the correct GIT repository root location for a given command. The resolver is provided with all the relevant details - including the command and server session through which the command was received: ```java GitLocationResolver resolver = (cmd, session, fs) -> ...consult some code - perhaps based on the authenticated username... sshd.setCommandFactory(new GitPackCommandFactory().withGitLocationResolver(resolver)); ``` These command factories also accept a delegate to which non-_git_ commands are routed: ```java sshd.setCommandFactory(new GitPackCommandFactory() .withDelegate(new MyCommandFactory()) .withGitLocationResolver(resolver)); // Here is how it looks if SCP is also requested sshd.setCommandFactory(new GitPackCommandFactory() .withDelegate(new ScpCommandFactory() .withDelegate(new MyCommandFactory())) .withGitLocationResolver(resolver)); // or sshd.setCommandFactory(new ScpCommandFactory() .withDelegate(new GitPackCommandFactory() .withDelegate(new MyCommandFactory()) .withGitLocationResolver(resolver))); // or any other combination ... ``` as with all other built-in commands, the factories allow the user to provide an `ExecutorService` in order to control the spawned threads for servicing the commands. If none provided, an internal single-threaded "pool" is created ad-hoc and destroyed once the command execution is completed (regardless of whether successful or not): ```java sshd.setCommandFactory(new GitPackCommandFactory(resolver) .withDelegate(new MyCommandFactory()) .withExecutorService(myService) .withShutdownOnExit(false)); ``` apache-mina-sshd-46fc8d6/docs/howto.md000066400000000000000000000060111456036076300176640ustar00rootroot00000000000000# HOWTO(s) This section contains some useful "cookbook recipes" for getting the most out of the code. Please note that it does **not** covers code samples that already appear in the previous sections - such as creating sessions, managing authentication, 3-way SCP, mounting file systems via SFTP, etc... Instead, it focuses on more "exotic" implementations that are not usually part of the normal SSH flow. ## [Endless tarpit](https://nullprogram.com/blog/2019/03/22/) In order to achieve this one needs to use a `ReservedSessionMessagesHandler` on the server side that overrides the session identification and KEX message callbacks as follows: * When `sendIdentification` callback is invoked * Check if you wish to trap the peer into the endless tarpit - if not, then return `null` * Spawn a thread that will feed the peer session with periodic infinite data. * Return a never succeeding `IoWriteFuture` - see `EndlessWriteFuture` in *sshd-contrib* package for such an implementation * When `sendKexInitRequest` callback is invoked * Check if you wish to trap the peer into the endless tarpit - if not, then return `null` * Return an `IoWriteFuture` that "succeeds" immediately - see `ImmediateWriteFuture` in *sshd-contrib* package for such an implementation. The idea is to prevent the normal session establish flow by taking over the initial handshake identification and blocking the initial KEX message from the server. A sample implementation can be found in the `EndlessTarpitSenderSupportDevelopment` class in the *sshd-contrib* package *test* section. ## Disabling strict KEX The current code implements the [strict-kex](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL) extension by default. If users want/need to disable it, then this can be done *programmatically* as follows (the example is for the client, but a similar approach can be implemented for the server): ```java class NoStrictKexSession extends ClientSessionImpl { NoStrictKexSession(ClientFactoryManager client, IoSession ioSession) throws Exception { super(client, ioSession); } @Override protected Map doStrictKexProposal(Map proposal) { return proposal; } } class NoStrictKexSessionFactory extends SessionFactory { NoStrictKexSessionFactory(ClientFactoryManager client) { super(client); } @Override protected ClientSessionImpl doCreateSession(IoSession ioSession) throws Exception { return new NoStrictKexSession(getClient(), ioSession); } } SshClient client = ...; SessionFactory factory = new NoStrictKexSessionFactory(client); client.setSessionFactory(factory); client.start(); ``` If one needs to disable the protocol on a per-session basis, then it is possible to examine the peer's address (e.g., or anything else for that matter) in the `doCreateSession` or the `doStrictKexProposal` overrides and then invoke the super-class (for continuing with strict KEX) or return immediately (for disabling it).apache-mina-sshd-46fc8d6/docs/internals.md000066400000000000000000000451441456036076300205350ustar00rootroot00000000000000# Selecting an `IoServiceFactoryFactory` As part of the their initialization, both client and server code require the specification of a `IoServiceFactoryFactory` that is used to initialize network connections. ```java SshServer server = ...create server instance... server.setIoServiceFactoryFactory(new MyIoServiceFactoryFactory()); SshClient client = ... create client instance ... client.setIoServiceFactoryFactory(new MyIoServiceFactoryFactory()); ``` If not set explicitly during the client/server setup code, then a factory is automatically detected and selected when the client/server is `#start()`-ed. The used `IoServiceFactoryFactory` is a **singleton** that is lazy created the 1st time `DefaultIoServiceFactoryFactory#create` is invoked. The selection process is as follows: * The `org.apache.sshd.common.io.IoServiceFactoryFactory` system property is examined for a factory specification. The specification can be either a **fully-qualified** class name or one of the `BuiltinIoServiceFactoryFactories` values. * If no specific factory is specified, then the [ServiceLoader#load](https://docs.oracle.com/javase/tutorial/ext/basics/spi.html#register-service-providers) mechanism is used to detect and instantiate any registered services in any `META-INF\services\org.apache.sshd.common.io.IoServiceFactoryFactory` location in the classpath. If **exactly one** implementation was instantiated, then it is used. If several such implementations are found then an exception is thrown. * Otherwise, the built-in `Nio2ServiceFactoryFactory` is used. **Note:** the default command line scripts for SSH/SCP/SFTP client/server are set up to use NIO2 as their default provider, unless overridden via the `-io` command line option. The `org.apache.sshd.common.io.IoServiceFactoryFactory` system property does not apply for the command line wrappers since they look only for the `-io` option and use it to initialize the client/server **explicitly** before starting the client/server. Therefore, the default selection process described in this section does not apply for them. # Advanced configuration and interaction ## Properties and inheritance model The code's behavior is highly customizable not only via non-default implementations of interfaces but also as far as the **parameters** that govern its behavior - e.g., timeouts, min./max. values, allocated memory size, etc... All the customization related code flow implements a **hierarchical** `PropertyResolver` inheritance model where the "closest" entity is consulted first, and then its "owner", and so on until the required value is found. If the entire hierarchy yielded no specific result, then some pre-configured default is used. E.g., if a channel requires some parameter in order to decide how to behave, then the following configuration hierarchy is consulted: * The channel-specific configuration * The "owning" session configuration * The "owning" client/server instance configuration * The system properties - **Note:** any configuration value required by the code can be provided via a system property bearing the `org.apache.sshd.config` prefix - see `SyspropsMapWrapper` for the implementation details. The easiest way to configure a target instance (client/server/session/channel) is via one of the (many) available `PropertyResolverUtils` `updateProperty` methods: ```java PropertyResolverUtils.updateProperty(client, "prop1", 5L); PropertyResolverUtils.updateProperty(server, "prop2", someInteger); PropertyResolverUtils.updateProperty(session, "prop3", "hello world"); PropertyResolverUtils.updateProperty(channel, "prop4", false); ``` **Note**: the `updateProperty` method(s) accept **any** `Object` so care must be taken to provide the expected type. However, at least for **primitive** values, the various `getXXXProperty` methods automatically convert compatible types: ```java PropertyResolverUtils.updateProperty(client, "prop1", 7365L); // all will yield 7365 converted to the relevant type Long value = PropertyResolverUtils.getLongProperty(client, "prop1"); Integer value = PropertyResolverUtils.getLongProperty(client, "prop1"); ``` including strings ```java PropertyResolverUtils.updateProperty(client, "prop1", "7365"); // all will yield 7365 Long value = PropertyResolverUtils.getLongProperty(client, "prop1"); Integer value = PropertyResolverUtils.getLongProperty(client, "prop1"); ``` ### Using the inheritance model for fine-grained/targeted configuration As previously mentioned, this hierarchical lookup model is not limited to "simple" configuration values (strings, integers, etc.), but used also for **interfaces/implementations** such as cipher/MAC/compression/authentication/etc. factories - the exception being that the system properties are not consulted in such a case. This code behavior provides highly customizable fine-grained/targeted control of the code's behavior - e.g., one could impose usage of specific ciphers/authentication methods/etc. or present different public key "identities"/welcome banner behavior/etc., based on address, username or whatever other decision parameter is deemed relevant by the user's code. This can be done on __both__ sides of the connection - client or server. E.g., the client could present different keys based on the server's address/identity string/welcome banner, or the server could accept only specific types of authentication methods based on the client's address/username/etc... This can be done in conjunction with the usage of the various `EventListener`-s provided by the code (see below). One of the code locations where this behavior can be leveraged is when the server provides __file-based__ services (SCP, SFTP) in order to provide a different/limited view of the available files based on the username - see the section dealing with `FileSystemFactory`-ies. ## Welcome banner configuration According to [RFC 4252 - section 5.4](https://tools.ietf.org/html/rfc4252#section-5.4) the server may send a welcome banner message during the authentication process. Both the message contents and the phase at which it is sent can be configured/customized. ### Welcome banner content customization The welcome banner contents are controlled by the `CoreModuleProperties#WELCOME_BANNER` configuration key - there are several possible values for this key: * A simple string - in which case its contents are the welcome banner. * A file [URI](https://docs.oracle.com/javase/8/docs/api/java/net/URI.html) - or a string starting with `"file:/"` followed by the file path - see below. * A [URL](https://docs.oracle.com/javase/8/docs/api/java/net/URL.html) - or a string containing "://" - in which case the [URL#openStream()](https://docs.oracle.com/javase/8/docs/api/java/net/URL.html#openStream) method is invoked and its contents are read. * A [File](https://docs.oracle.com/javase/8/docs/api/java/io/File.html) or a [Path](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html) - in this case, the file's contents are __re-loaded__ every time it is required and sent as the banner contents. * The special value `CoreModuleProperties#AUTO_WELCOME_BANNER_VALUE` which generates a combined "random art" of all the server's keys as described in `Perrig A.` and `Song D.`-s article [Hash Visualization: a New Technique to improve Real-World Security](http://sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf) - _International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99)_ * One can also override the `ServerUserAuthService#resolveWelcomeBanner` method and use whatever other content customization one sees fit. **Note:** 1. If any of the sources yields an empty string or is missing (in the case of a resource) then no welcome banner message is sent. 2. If the banner is loaded from a file or URL resource, then one can configure the [Charset](https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html) used to convert the file's contents into a string via the `ServerAuthenticationManager.WELCOME_BANNER_CHARSET` configuration key (default=`UTF-8`). 3. In this context, see also the `CoreModuleProperties#WELCOME_BANNER_LANGUAGE` configuration key - which provides control over the declared language tag, although most clients seem to ignore it. ### Welcome banner sending phase According to [RFC 4252 - section 5.4](https://tools.ietf.org/html/rfc4252#section-5.4): > The SSH server may send an SSH_MSG_USERAUTH_BANNER message at any time after this authentication protocol starts and before authentication is successful. The code contains a `WelcomeBannerPhase` enumeration that can be used to configure via the `CoreModuleProperties#WELCOME_BANNER_PHASE` configuration key the authentication phase at which the welcome banner is sent (see also the `CoreModuleProperties#DEFAULT_BANNER_PHASE` value). In this context, note that if the `NEVER` phase is configured, no banner will be sent even if one has been configured via one of the methods mentioned previously. ## `HostConfigEntryResolver` This interface provides the ability to intervene during the connection and authentication phases and "re-write" the user's original parameters. The `DefaultConfigFileHostEntryResolver` instance used to set up the default client instance follows the [SSH config file](https://www.digitalocean.com/community/tutorials/how-to-configure-custom-connection-options-for-your-ssh-client) standards, but the interface can be replaced so as to implement whatever proprietary logic is required. ```java SshClient client = SshClient.setUpDefaultClient(); client.setHostConfigEntryResolver(new MyHostConfigEntryResolver()); client.start(); /* * The resolver might decide to connect to some host2/port2 using user2 and password2 * (or maybe using some key instead of the password). */ try (ClientSession session = client.connect(user1, host1, port1).verify(...timeout...).getSession()) { session.addPasswordIdentity(...password1...); session.auth().verify(...timeout...); } ``` ### SSH Jumps The SSH client can be configured to use [SSH proxy jumps](https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Proxies_and_Jump_Hosts). A *jump host* (also known as a *jump server*) is an intermediary host or an SSH gateway to a remote network, through which a connection can be made to another host in a dissimilar security zone, for example a demilitarized zone (DMZ). It bridges two dissimilar security zones and offers controlled access between them. Starting from SSHD version 2.6.0, the *ProxyJump* host configuration entry is honored when using the `SshClient` to connect to a host. The `SshClient` built by default reads the `~/.ssh/config` file. The various CLI clients also honor the `-J` command line option to specify one or more jumps. In order to manually configure jumps, you need to build a `HostConfigEntry` with a `proxyJump` and use it to connect to the server: ```java ConnectFuture future = client.connect(new HostConfigEntry( "", host, port, user, proxyUser + "@" + proxyHost + ":" + proxyPort)); ``` The configuration options specified in the configuration file for the jump hosts are also honored. ## `SshConfigFileReader` Can be used to read various standard SSH [client](http://linux.die.net/man/5/ssh_config) or [server](http://manpages.ubuntu.com/manpages/precise/en/man5/sshd_config.5.html) configuration files and initialize the client/server respectively. Including (among other things), bind address, ciphers, signature, MAC(s), KEX protocols, compression, welcome banner, etc.. ### Reserved messages The implementation can be used to intercept and process the [SSH_MSG_IGNORE](https://tools.ietf.org/html/rfc4253#section-11.2), [SSH_MSG_DEBUG](https://tools.ietf.org/html/rfc4253#section-11.3) and [SSH_MSG_UNIMPLEMENTED](https://tools.ietf.org/html/rfc4253#section-11.4) messages. The handler can be registered on either side - server or client, as well as on the session. A special [patch](https://issues.apache.org/jira/browse/SSHD-699) has been introduced that automatically ignores such messages if they are malformed - i.e., they never reach the handler. #### SSH message stream "stuffing" and keys re-exchange [RFC 4253 - section 9](https://tools.ietf.org/html/rfc4253#section-9) recommends re-exchanging keys every once in a while based on the amount of traffic and the selected cipher - the matter is further clarified in [RFC 4251 - section 9.3.2](https://tools.ietf.org/html/rfc4251#section-9.3.2). These recommendations are mirrored in the code via the `CoreModuleProperties` related `REKEY_TIME_LIMIT`, `REKEY_PACKETS_LIMIT` and `REKEY_BLOCKS_LIMIT` configuration properties that can be used to configure said behavior - please be sure to read the relevant _Javadoc_ as well as the aforementioned RFC section(s) when manipulating them. This behavior can also be controlled programmatically by overriding the `AbstractSession#isRekeyRequired()` method. As an added security mechanism [RFC 4251 - section 9.3.1](https://tools.ietf.org/html/rfc4251#section-9.3.1) recommends adding "spurious" [SSH_MSG_IGNORE](https://tools.ietf.org/html/rfc4253#section-11.2) messages. This functionality is mirrored in the `CoreModuleProperties` related `IGNORE_MESSAGE_FREQUENCY`, `IGNORE_MESSAGE_VARIANCE` and `IGNORE_MESSAGE_SIZE` configuration properties that can be used to configure said behavior - please be sure to read the relevant _Javadoc_ as well as the aforementioned RFC section when manipulating them. This behavior can also be controlled programmatically by overriding the `AbstractSession#resolveIgnoreBufferDataLength()` method. ### `RequestHandler`(s) The code supports both [global](https://tools.ietf.org/html/rfc4254#section-4) and [channel-specific](https://tools.ietf.org/html/rfc4254#section-5.4) requests via the registration of `RequestHandler`(s). The global handlers are derived from `ConnectionServiceRequestHandler`(s) whereas the channel-specific ones are derived from `ChannelRequestHandler`(s). In order to add a handler one need only register the correct implementation and handle the request when it is detected. For global request handlers this is done by registering them on the server: ```java // NOTE: the following code can be employed on BOTH client and server - the example is for the server SshServer server = SshServer.setUpDefaultServer(); List> oldGlobals = server.getGlobalRequestHandlers(); // Create a copy in case current one is null/empty/un-modifiable List> newGlobals = new ArrayList<>(); if (GenericUtils.size(oldGlobals) > 0) { newGlobals.addAll(oldGLobals); } newGlobals.add(new MyGlobalRequestHandler()); server.setGlobalRequestHandlers(newGlobals); ``` For channel-specific requests, one uses the channel's `add/removeRequestHandler` method to manage its handlers. The way request handlers are invoked when a global/channel-specific request is received is as follows: * All currently registered handlers' `process` method is invoked with the request type string parameter (among others). The implementation should examine the request parameters and decide whether it is able to process it. * If the handler returns `Result.Unsupported` then the next registered handler is invoked. In other words, processing stops at the **first** handler that returned a valid response. Thus the importance of the `List>` that defines the **order** in which the handlers are invoked. **Note**: while it is possible to register multiple handlers for the same request and rely on their order, it is highly recommended to avoid this situation as it makes debugging the code and diagnosing problems much more difficult. * If no handler reported a valid result value then a failure message is sent back to the peer. Otherwise, the returned result is translated into the appropriate success/failure response (if the sender asked for a response). In this context, the handler may choose to build and send the response within its own code, in which case it should return the `Result.Replied` value indicating that it has done so. ```java public class MySpecialChannelRequestHandler implements ChannelRequestHandler { ... @Override public Result process(Channel channel, String request, boolean wantReply, Buffer buffer) throws Exception { if (!"my-special-request".equals(request)) { return Result.Unsupported; // Not mine - maybe someone else can handle it } ...handle the request - can read more parameters from the message buffer... return Result.ReplySuccess/Failure/Replied; // signal processing result } } ``` #### Default registered handlers * `exit-signal`, `exit-status` - As described in [RFC4254 section 6.10](https://tools.ietf.org/html/rfc4254#section-6.10) * `*@putty.projects.tartarus.org` - As described in [Appendix F: SSH-2 names specified for PuTTY](http://tartarus.org/~simon/putty-snapshots/htmldoc/AppendixF.html) * `hostkeys-prove-00@openssh.com`, `hostkeys-00@openssh.com` - As described in [OpenSSH protocol - section 2.5](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL) * `tcpip-forward`, `cancel-tcpip-forward` - As described in [RFC4254 section 7](https://tools.ietf.org/html/rfc4254#section-7) * `keepalive@*` - Used by many client implementations (including this one) to "ping" the server and keep/make sure the connection is still alive. In this context, the SSHD code allows the user to configure both the frequency and content of the heartbeat request (including whether to send this request at all) via the `ClientFactoryManager`-s `HEARTBEAT_INTERVAL`, `HEARTBEAT_REQUEST` and `DEFAULT_KEEP_ALIVE_HEARTBEAT_STRING` configuration properties. * `no-more-sessions@*` - As described in [OpenSSH protocol section 2.2](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL). In this context, the code consults the `ServerFactoryManagder.MAX_CONCURRENT_SESSIONS` server-side configuration property in order to decide whether to accept a successfully authenticated session. ## PROXY / SSLH protocol hooks The code contains [support for "wrapper" protocols](https://issues.apache.org/jira/browse/SSHD-656) such as [PROXY](http://www.haproxy.org/download/1.6/doc/proxy-protocol.txt) or [sslh](http://www.rutschle.net/tech/sslh.shtml). The idea is that one can register either a `ClientProxyConnector` or `ServerProxyAcceptor` and intercept the 1st packet being sent/received (respectively) **before** it reaches the SSHD code. This gives the programmer the capability to write a front-end that routes outgoing/incoming packets: * `SshClient/ClientSesssion#setClientProxyConnector` - sets a proxy that intercepts the 1st packet before being relayed to the server * `SshServer/ServerSession#setServerProxyAcceptor` - sets a proxy that intercepts the 1st incoming packet before being processed by the server apache-mina-sshd-46fc8d6/docs/port-forwarding.md000066400000000000000000000067611456036076300216640ustar00rootroot00000000000000## Port forwarding ### `PortForwardingEventListener` Informs and allows tracking of port forwarding events as described in [RFC 4254 - section 7](https://tools.ietf.org/html/rfc4254#section-7) as well as the (simple) [SOCKS](https://en.wikipedia.org/wiki/SOCKS) protocol (versions 4, 5). In this context, one can create a `PortForwardingTracker` that can be used in a `try-with-resource` block so that the set up forwarding is automatically torn down when the tracker is `close()`-d: ```java client.addPortForwardingEventListener(new MySuperDuperListener()); try (ClientSession session = client.connect(user, host, port).verify(...timeout...).getSession()) { session.addPasswordIdentity(password); session.auth().verify(...timeout...); try (PortForwardingTracker tracker = session.createLocal/RemotePortForwardingTracker(...)) { ...do something that requires the tunnel... } // Tunnel is torn down when code reaches this point } ``` ### Standard port forwarding Port forwarding as specified in [RFC 4254 - section 7](https://tools.ietf.org/html/rfc4254#section-7) is fully supported by the client and server. From the client side, this capability is exposed via the `start/stopLocal/RemotePortForwarding` method. The key player in this capability is the configured `ForwardingFilter` that controls this feature - on **both** sides - client and server. By default, this capability is **disabled** - i.e., the user must provide an implementation and call the appropriate `setForwardingFilter` method on the client/server. ```java SshClient client = ...create/obtain an instance... client.setForwardingFilter(...filter instance...); SshServer server = ...create/obtain an instance... server.setForwardingFilter(...filter instance...); ``` The code contains 2 simple implementations - an `AcceptAllForwardingFilter` and a `RejectAllForwardingFilter` one that can be used for these trivial policies. **Note:** setting a _null_ filter is equivalent to rejecting all such attempts. In order to help with the forwarding policy, the filter is actually made up of 3 "groups" of forwarding: * `AgentForwardingFilter` * `X11ForwardingFilter` * `TcpForwardingFilter` It is possible to implement each and every one separately and then combine them via `ForwardingFilter#asForwardingFilter`. In this context, one does not have to implement all 3 - any implementation not provided is assumed to be disabled. Furthermore, there are reasonable default implementations for all 3, so one can override only a specific group policy and provide defaults for the rest. ### SOCKS The code implements a [SOCKS](https://en.wikipedia.org/wiki/SOCKS) proxy for versions 4 and 5. The proxy capability is invoked via the `start/stopDynamicPortForwarding` methods. ### Proxy agent The code provides to some extent an SSH proxy agent via the available `SshAgentFactory` implementations. As of latest version both [Secure Shell Authentication Agent Protocol Draft 02](https://tools.ietf.org/html/draft-ietf-secsh-agent-02) and its [OpenSSH](https://www.libssh.org/features/) equivalent are supported. **Note:** in order to support this feature the [Apache Portable Runtime Library](https://apr.apache.org/) needs to be added to the Maven dependencies: ```xml tomcat tomcat-apr ``` **Note:** Since the portable runtime library uses **native** code, one needs to also make sure that the appropriate _.dll/.so_ library is available in the LD\_LIBRARY\_PATH. apache-mina-sshd-46fc8d6/docs/scp.md000066400000000000000000000301151456036076300173130ustar00rootroot00000000000000# SCP Both client-side and server-side SCP are supported. Starting from version 2.0, the SCP related code is located in the `sshd-scp` module, so you need to add this additional dependency to your maven project: ```xml org.apache.sshd sshd-scp ...same as sshd-core... ``` ## `ScpTransferEventListener` Callback to inform about SCP related events. `ScpTransferEventListener`(s) can be registered on *both* client and server side: ```java // Server side ScpCommandFactory factory = new ScpCommandFactory(...with/out delegate..); factory.addEventListener(new MyServerSideScpTransferEventListener()); sshd.setCommandFactory(factory); // Client side try (ClientSession session = client.connect(user, host, port) .verify(...timeout...) .getSession()) { session.addPasswordIdentity(password); session.auth().verify(...timeout...); ScpClientCreator creator = ... obtain an instance ... ScpClient client = creator.createScpClient(session, new MySuperDuperListener()); ...scp.upload/download... } ``` ### General text encoding/decoding The basic SCP protocol is text-based and therefore subject to character encoding/decoding of the data being exchanged. By default, the exchange is supposed to use the UTF-8 encoding which is the default/standard one for SSH. However, there are clients/servers "in the wild" that do not conform to this convention. For this purpose, it is possible to define a different character encoding via the `SCP_INCOMING/OUTGOING_ENCODING` properties - e.g.: ```java SshServer sshd = ...setup server... // Can also use the character name string rather than the object instance itself ScpModuleProperties.SCP_INCOMING_ENCODING.set(sshd, Charset.forName("US-ASCII")); ScpModuleProperties.SCP_OUTGOING_ENCODING.set(sshd, Charset.forName("US-ASCII")); ``` **Caveat emptor:** the code does not enforce "symmetry" of the chosen character sets - in other words, users can either by design or error cause different encoding to be used for the incoming commands vs. the outgoing responses. It is important to bear in mind that if the text to be encoded/decoded contains characters that cannot be safely handled by the chosen encoder/decoder than the result might not be correctly parsed/understood by the peer. ## Client-side SCP In order to obtain an `ScpClient` one needs to use an `ScpClientCreator`: ```java try (ClientSession session = ... obtain an instance ...) { ScpClientCreator creator = ... obtain an instance ... ScpClient client = creator.createScpClient(session); ... use client ... } ``` A default `ScpClientCreator` instance is provided as part of the module - see `ScpClientCreator.instance()` If the intended use of the client instance is "one-shot" - i.e., the client session should be closed when the SCP client instance is closed, then it is possible to obtain a special wrapper that implements this functionality: ```java // The underlying session will also be closed when the client is try (CloseableScpClient client = createScpClient(...)) { ... use client ... } CloseableScpClient createScpClient(...) { ClientSession session = ... obtain an instance ...; ScpClientCreator creator = ... obtain an instance ... ScpClient client = creator.createScpClient(session); return CloseableScpClient.singleSessionInstance(client); } ``` The `ScpClientCreator` can also be used to attach a default `ScpTransferEventListener` that will be automatically add to **all** created SCP client instances through that creator - unless specifically overridden: ```java ClientSession session = ... obtain an instance ... ScpClientCreator creator = ... obtain an instance ... creator.setScpTransferEventListener(new MySuperDuperListener()); ScpClient client1 = creator.createScpClient(session); // <<== automatically uses MySuperDuperListener ScpClient client2 = creator.createScpClient(session, new SomeOtherListener()); // <<== uses SomeOtherListener instead of MySuperDuperListener ``` ## ScpFileOpener(s) As part of the `ScpClientCreator`, the SCP module also uses a `ScpFileOpener` instance in order to access the local files. The default implementation simply opens an [InputStream](https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html) or [OutputStream](https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html) on the requested local path. However, the user may replace it and intercept the calls - e.g., for logging, monitoring transfer progess, wrapping/filtering the streams, etc... The user may attach a default opener that will be automatically attached to **all** clients created unless specifically overridden: ```java /** * Example of using a non-default opener for monitoring and reporting on transfer progress */ public class ScpTransferProgressMonitor extends DefaultScpFileOpener { public static final ScpTransferProgressMonitor MONITOR = new ScpTransferProgressMonitor(); public ScpTransferProgressMonitor() { super(); } @Override public InputStream openRead( Session session, Path file, long size, Set permissions, OpenOption... options) throws IOException { return new MyProgressReportingInputStream(super.openRead(session, file, size, permissions, options), size /* how much is expected */); } @Override public OutputStream openWrite( Session session, Path file, long size, Set permissions, OpenOption... options) throws IOException { return new MyProgressReportingOutputStream(super.openWrite(session, file, size, permissions, options), size /* how much is expected */); } } ClientSession session = ... obtain an instance ... ScpClientCreator creator = ... obtain an instance ... creator.setScpFileOpener(ScpTransferProgressMonitor.INSTANCE); ScpClient client1 = creator.createScpClient(session); // <<== automatically uses ScpTransferProgressMonitor ScpClient client2 = creator.createScpClient(session, new SomeOtherOpener()); // <<== uses SomeOtherOpener instead of ScpTransferProgressMonitor ``` **Note(s):** * Due to SCP protocol limitations one cannot change the **size** of the input/output since it is passed as part of the command **before** the file opener is invoked - so there are a few limitations on what one can do within this interface implementation. * By default, SCP synchronizes the local copied file data with the file system using the [Java SYNC open option](https://docs.oracle.com/javase/8/docs/api/java/nio/file/StandardOpenOption.html#SYNC). This behavior can be controlled by setting the `scp-auto-sync-on-write` (a.k.a. `ScpModuleProperties#PROP_AUTO_SYNC_FILE_ON_WRITE`) property to _false_ or overriding the `DefaultScpFileOpener#resolveOpenOptions`, or even overriding the `ScpFileOpener#openWrite` method altogether. * Patterns used in `ScpFileOpener#getMatchingFilesToSend` are matched using case sensitivity derived from the O/S as detected by the internal `OsUtils`. If a different behavior is required, then one needs to replace the default opener with one that uses a different sensitivity via `DirectoryScanner#setCaseSensitive` call (or executes the pattern matching in another way). * `Windows` - case insensitive * `Unix` - case sensitive ## Server-side SCP Setting up SCP support on the server side is straightforward - simply initialize a `ScpCommandFactory` and set it as the **primary** command factory. If support for commands other than SCP is also required then provide the extra commands factory as a **delegate** of the `ScpCommandFactory`. The SCP factory will intercept the SCP command and execute it, while propagating all other commands to the delegate. If no delegate configured then the non-SCP command is deemed as having failed (same as if it were rejected by the delegate). ```java ScpCommandFactory factory = new ScpCommandFactory.Builder() .withDelegate(new MyCommandDelegate()) .build(); SshServer sshd = ...create an instance... sshd.setCommandFactory(factory); ``` The `ScpCommandFactory` allows users to attach an `ScpFileOpener` and/or `ScpTransferEventListener` having the same behavior as the client - i.e., monitoring and intervention on the accessed local files. Furthermore, the factory can also be configured with a custom executor service for executing the requested copy commands as well as controlling the internal buffer sizes used to copy files. ## The SCP "shell" Some SCP clients (e.g. [WinSCP](https://winscp.net/)) open a shell connection even if configured to use pure SCP in order to retrieve information about the remote server's files and potentially navigate through them. In other words, SCP is only used as the **transfer** protocol, but the application relies on "out-of-band" information (shell in this case) in order to provide the user with the available files list on the remote server. Due to various considerations, some users might not want or be able to provide a full blown shell interface on the server side. For this purpose SSHD provides an `ScpShell` class that provides a good enough implementation of the **limited** command types that an SCP client is likely to require. For this purpose, the `ScpCommandFactory` also implements `ShellFactory` which spawns the limited `ScpShell` support. ```java ScpCommandFactory factory = new ScpCommandFactory.Builder() .with(...) .with(...) .build() ; sshd.setCommandFactory(factory); sshd.setShellFactory(factory); ``` **Note:** a similar result can be achieved if activating SSHD from the command line by specifying `-o ShellFactory=scp`. In any case, even if the shell is configured, it can be enabled/disabled via setting the `scp-enable-scp-shell` property to the desired value (default=*true*) - on the server, the session or even the specific channel (as with any other property). This way, one can control the shell's availability per-session. ### Text encoding/decoding The SCP "shell" is text-based and therefore subject to character encoding/decoding of the data being exchanged. By default, the exchange is supposed to use the UTF-8 encoding which is the default/standard one for SSH. However, there are clients/servers "in the wild" that do not conform to this convention. For this purpose, it is possible to define a different character encoding via the `SHELL_NAME_EN/DECODING_CHARSET` properties - e.g.: ```java SshServer sshd = ...setup server... // Can also use the character name string rather than the object instance itself ScpModuleProperties.SHELL_NAME_ENCODING_CHARSET.set(sshd, Charset.forName("US-ASCII")); ScpModuleProperties.SHELL_NAME_DECODING_CHARSET.set(sshd, Charset.forName("US-ASCII")); ``` **Caveat emptor:** the code does not enforce "symmetry" of the chosen character sets - in other words, users can either by design or error cause different encoding to be used for the incoming commands vs. the outgoing responses. It is important to bear in mind that if the text to be encoded/decoded contains characters that cannot be safely handled by the chosen encoder/decoder than the result might not be correctly parsed/understood by the peer. A similar behavior is controlled via `SHELL_ENVVARS_ENCODING_CHARSET` which controls responses from the `ScpShell` regarding environment variables - the main difference being that the default is US-ASCII rather than UTF-8. ## Remote-to-remote transfer The code provides an `ScpTransferHelper` class that enables copying files between 2 remote accounts without going through the local file system. ```java ClientSession src = ...; ClientSession dst = ...; // Can also provide a listener in the constructor in order to be informed of the actual transfer progress ScpRemote2RemoteTransferHelper helper = new ScpRemote2RemoteTransferHelper(src, dst); // can be repeated for as many files as necessary using the same helper helper.transferFile("remote/src/path/file1", "remote/dst/path/file2"); ``` ## References * [How the SCP protocol works](https://chuacw.ath.cx/development/b/chuacw/archive/2019/02/04/how-the-scp-protocol-works.aspx) * [scp.c](https://github.com/cloudsigma/illumos-omnios/blob/master/usr/src/cmd/ssh/scp/scp.c) apache-mina-sshd-46fc8d6/docs/security-providers.md000066400000000000000000000172331456036076300224160ustar00rootroot00000000000000## Security providers setup While the code supports _BouncyCastle_ and _EdDSA_ security providers out-of-the-box, it also provides a way to [add security providers](https://issues.apache.org/jira/browse/SSHD-713) via the `SecurityProviderRegistrar` interface implementation. In order to add support for a new security provider one needs to implement the registrar interface and make the code aware of it. ### Default/built-in security provider registrars The code contains built-in security provider registrars for _BouncyCastle_ and _EdDSA_ (a.k.a. `ed25519`). It automatically detects the existence of the required artifacts (since they are optional dependencies) and executes the respective security provider registration. This behavior is controlled by the `org.apache.sshd.security.registrars` system property. This property contains a comma-separated list of **fully-qualified** class names implementing the `SecurityProviderRegistrar` interface and assumed to contain a default **public** no-arguments constructor. The code automatically parses the list and attempts to instantiate and invoke the registrar. **Note:** - The registration code automatically parses the configured registrars list and instantiates them. In this context, one can use the special `none` value to indicate that the code should not attempt to automatically register the default providers. - A registrar instance might be created but eventually discarded and not invoked if it is disabled, unsupported or already registered programmatically via `SecurityUtils#registerSecurityProvider`. - The registration attempt is a **one-shot** deal - i.e., once the registrars list is parsed and successfully resolved, any modifications to the registered security providers must be done **programatically**. One can call `SecurityUtils#isRegistrationCompleted()` to find out if the registration phase has already been executed. - The registrars are consulted in the same **order** as they were initially registered - either programmatically or via the system property configuration. Therefore, if two or more registrars support the same algorithm, then the earlier registered one will be used. - If no matching registrar was found, then the default security provider is used. If none set, the JCE defaults are invoked. The default security provider can be configured either via the `org.apache.sshd.security.defaultProvider` system property or by programmatically invoking `SecurityUtils#setDefaultProviderChoice`. **Note:** if the system property option is used, then it is assumed to contain a security provider's **name** (rather than its `Provider` class name...). - If programmatic selection of the default security provider choice is required, then the code flow must ensure that `SecurityUtils#setDefaultProviderChoice` is called before **any** security entity (e.g., ciphers, keys, etc...) are required. Theoretically, one could change the choice after ciphers have been been requested but before keys were generated (e.g....), but it is dangerous and may yield unpredictable behavior. ### Implementing a new security provider registrar See `AbstractSecurityProviderRegistrar` helper class for a default implementation of most of the required functionality, as well as the existing implementations for _BouncyCastle_ and _EdDSA_ for examples of how to implement it. The most important issues to consider when adding such an implementation are: * Try using reflection API to detect the existence of the registered provider class and/or instantiate it. The main reason for this recommendation is that it isolates the code from a direct dependency on the provider's classes and makes class loading issue less likely. * Decide whether to use the provider's name or instance when creating security related entities such as ciphers, keys, etc... **Note:** the default preference is to use the provider name, thus registering via `Security.addProvider` call. In order to change that, either register the instance yourself or override the `isNamedProviderUsed` method. In this context, **cache** the generated `Provider` instance if the instance rather than the name is used. **Note:** using only the provider instance instead of the name is a rather new feature and has not been fully tested. It is possible though to decide and use it anyway as long as it can be configurably disabled. * The default implementation provides fine-grained control over the declared supported security entities - ciphers, signatures, key generators, etc... By default, it is done via consulting a system property composed of `org.apache.sshd.security.provider`, followed by the security provider name and the relevant security entity - e.g., `org.apache.sshd.security.provider.BC.KeyFactory` is assumed to contain a comma-separated list of supported `KeyFactory` algorithms. **Note:** * The same naming convention can be used to enable/disable the registrar - even if supported - e.g., `org.apache.sshd.security.provider.BC.enabled=false` disables the _BouncyCastle_ registrar. * One can use `all` or `*` to specify that all entities of the specified type are supported - e.g., `org.apache.sshd.security.provider.BC.MessageDigest=all`. In this context, one can override the `getDefaultSecurityEntitySupportValue` method if no fine-grained configuration is required per-entity type, * The result of an `isXxxSupported` call is/should be **cached** (see `AbstractSecurityProviderRegistrar`). * For ease of implementation, all support query calls are routed to the `isSecurityEntitySupported` method so that one can concentrate all the configuration in a single method. This is done for **convenience** reasons - the code will invoke the correct support query as per the type of entity it needs. E.g., if it needs a cipher, it will invoke `isCipherSupported` - which by default will invoke `isSecurityEntitySupported` with the `Cipher` class as its argument. * Specifically for **ciphers** the argument to the support query contains a **transformation** (e.g., `AES/CBC/NoPadding`) so one should take that into account when parsing the input argument to decide which cipher is referenced - see `SecurityProviderRegistrar.getEffectiveSecurityEntityName(Class, String)` helper method ## Diff-Hellman group exchange configuration The [RFC 4419 - Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol](https://tools.ietf.org/html/rfc4419) specifies in section 3: >> Servers and clients SHOULD support groups with a modulus length of k bits, where 1024 <= k <= 8192. >> The recommended values for min and max are 1024 and 8192, respectively. This was subsequently amended in [RFC 8270 - Increase the Secure Shell Minimum Recommended Diffie-Hellman Modulus Size to 2048 Bits](https://tools.ietf.org/html/rfc8270). In any case, the values are auto-detected by the code but the user can intervene in 2 ways: 1. Programmatically - by invoking `SecurityUtils#setMin/MaxDHGroupExchangeKeySize` respectively 2. Via system property - by setting `org.apache.sshd.min/maxDHGexKeySize` system property respectively **Note(s)** * The value should be a multiple of 1024 (not enforced) * The value should be between 2048 and 8192 (not enforced - allows users to make an **explicit** decision to use shorter keys - especially the minimum). * The minimum must be less or equal to the maximum (enforced - if reversed then group exchange is **disabled**) * If a **negative** value is set in either one then group exchange is **disabled** * Setting a value of zero indicates a **lazy** auto-detection of the supported range the next time these values are needed. Furthermore, if all possible primes have been exhausted the code no longer falls back to DH group exchange using SHA-1 unless the `ALLOW_DHG1_KEX_FALLBACK` core module property is set.apache-mina-sshd-46fc8d6/docs/server-setup.md000066400000000000000000000212021456036076300211670ustar00rootroot00000000000000# Embedding an SSHD server instance in 5 minutes SSHD is designed to be easily embedded in your application as an SSH server. The embedded SSH server needs to be configured before it can be started. Essentially, there are a few simple steps for creating the server - for more details refer to the `SshServer` class. ## Creating an instance of the `SshServer` class Creating an instance of `SshServer` is as simple as creating a new object ```java SshServer sshd = SshServer.setUpDefaultServer(); ``` It will configure the server with sensible defaults for ciphers, macs, key exchange algorithm, etc... If different behavior is required, one should consult the code of the `setUpDefaultServer` as well as `checkConfig` methods as a reference for available options and configure the SSH server the way it is needed. ## Configuring the server instance There are a few things that need to be configured on the server before being able to actually use it: * Port - `sshd.setPort(22);` - sets the listen port for the server instance. If not set explicitly then a **random** free port is selected by the O/S. In any case, once the server is `start()`-ed one can query the instance as to the assigned port via `sshd.getPort()`. In this context, the listen bind address can also be specified explicitly via `sshd.setHost(...some IP address...)` that causes the server to bind to a specific network address rather than **all** addresses (the default). Using `"0.0.0.0"` as the bind address is also tantamount to binding to all addresses. * `KeyPairProvider` - `sshd.setKeyPairProvider(...);` - sets the host's private keys used for key exchange with clients as well as representing the host's "identities". There are several choices - one can load keys from standard PEM files or generate them in the code. It's usually a good idea to save generated keys, so that if the SSHD server is restarted, the same keys will be used to authenticate the server and avoid the warning the clients might get if the host keys are modified. **Note**: saving key files in PEM format requires that the [Bouncy Castle](https://www.bouncycastle.org/) supporting artifacts be available in the code's classpath. * `HostKeyCertificateProvider` - used for OpenSSH public-key certificate authentication system as defined in [this document](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.certkeys) * `ShellFactory` - That's the part one usually has to write to customize the SSHD server. The shell factory will be used to create a new shell each time a user logs in and wants to run an interactive shell. SSHD provides a simple implementation that you can use if you want. This implementation will create a process and delegate everything to it, so it's mostly useful to launch the OS native shell. E.g., ```java sshd.setShellFactory(new ProcessShellFactory(new String[] { "/bin/sh", "-i", "-l" })); ``` There is an out-of-the-box `InteractiveProcessShellFactory` that detects the O/S and spawns the relevant shell. Note that the `ShellFactory` is not required. If none is configured, any request for an interactive shell will be denied to clients. Furthermore, one can select a specific factory based on the current session by using an `AggregateShellFactory` that wraps a group of `ShellFactorySelector` - each one tailored for a specific set of criteria. The simplest use-case is one the detects the client and provides a specially tailored shell for it - e.g., [the way we do for "WinSCP"](https://issues.apache.org/jira/browse/SSHD-1009) based on the peer client version string. * `CommandFactory` - The `CommandFactory` provides the ability to run a **single** direct command at a time instead of an interactive session (it also uses a **different** channel type than shells). It can be used **in addition** to the `ShellFactory`. SSHD provides a `CommandFactory` to support SCP that can be configured in the following way: ```java sshd.setCommandFactory(new ScpCommandFactory()); ``` One can also use the `ScpCommandFactory` on top of one's own `CommandFactory` by placing the command factory as a **delegate** of the `ScpCommandFactory`. The `ScpCommandFactory` will intercept SCP commands and execute them by itself, while passing all other commands to the delegate `CommandFactory` ```java sshd.setCommandFactory(new ScpCommandFactory(myCommandFactory)); ``` Note that using a `CommandFactory` is also **optional**. If none is configured, any direct command sent by clients will be rejected. ## Server side security setup The SSHD server security layer has to be customized to suit your needs. This layer is pluggable and uses the following interfaces: * `PasswordAuthenticator` for password based authentication - [RFC 4252 section 8](https://www.ietf.org/rfc/rfc4252.txt) * `PublickeyAuthenticator` for key based authentication - [RFC 4252 section 7](https://www.ietf.org/rfc/rfc4252.txt) * `HostBasedAuthenticator` for host based authentication - [RFC 4252 section 9](https://www.ietf.org/rfc/rfc4252.txt) * `KeyboardInteractiveAuthenticator` for user interactive authentication - [RFC 4256](https://www.ietf.org/rfc/rfc4256.txt) These custom classes can be configured on the SSHD server using the respective setter methods: ```java sshd.setPasswordAuthenticator(new MyPasswordAuthenticator()); sshd.setPublickeyAuthenticator(new MyPublickeyAuthenticator()); sshd.setKeyboardInteractiveAuthenticator(new MyKeyboardInteractiveAuthenticator()); ...etc... ``` Several useful implementations are available that can be used as-is or extended in order to provide some custom behavior. In any case, the default initializations are: * `DefaultAuthorizedKeysAuthenticator` - uses the _authorized_keys_ file the same way as the SSH daemon does * `DefaultKeyboardInteractiveAuthenticator` - for password-based or interactive authentication. **Note:** this authenticator requires a `PasswordAuthenticator` to be configured since it delegates some of the functionality to it. ## Configuring ciphers, macs, digest... SSH supports pluggable factories to define various configuration parts such as ciphers, digests, key exchange, etc... The list of supported implementations can be changed to suit one's needs, or one can also implement one's own factories. Configuring supported factories can be done with the following code: ```java sshd.setCipherFactories(Arrays.asList(BuiltinCiphers.aes256ctr, BuiltinCiphers.aes192ctr, BuiltinCiphers.aes128ctr)); sshd.setKeyExchangeFactories(Arrays.asList(new MyKex1(), new MyKex2(), BuiltinKeyExchange.A, ...etc...)); ``` One can configure other security components using built-in factories the same way. It is important to remember though that the **order** of the factories is important as it affects the key exchange phase where the client and server decide what options to use out of each peer's reported preferences. ## Starting the Server Once we have configured the server, one need only call `sshd.start();`. **Note**: once the server is started, all of the configurations (except the port) can still be *overridden* while the server is running (caveat emptor). In such cases, only **new** clients that connect to the server after the change will be affected - with the exception of the negotiation options (keys, macs, ciphers, etc...) which take effect the next time keys are re-exchanged, that can affect live sessions and not only new ones. ## Providing server-side heartbeat The server can generate [`SSH_MSG_IGNORE`](https://tools.ietf.org/html/rfc4253#section-11.2) messages towards its client sessions in order to make sure that the client does not time out on waiting for traffic if no user generated data is available. By default, this feature is **disabled** - however it can be enabled by invoking the `setSessionHeartbeat` API either on the server (for **global** setting) or a specific session (for targeted control of the feature). *Note:* the same effect can also be achieved by setting the relevant properties documented in `SessionHeartbeatController`, but it is highly recommended to use the API - unless one needs to control these properties **externally** via `-Dxxx` JVM options. If one is using the SSHD CLI code, then these options are controlled via `-o ServerAliveInterval=NNNN` where the value is the requested **global** interval in **seconds**. *Note*: any non-positive value is treated as if the feature is disabled. In order to support customized user code for this feature, the `ReservedSessionMessagesHandler` can be used to implement any kind of user-defined heartbeat. *Note:* if the user configured such a mechanism, then the `sendReservedHeartbeat` method **must** be implemented since the default throws `UnsupportedOperationException` which will cause the session to be terminated the 1st time the method is invoked. apache-mina-sshd-46fc8d6/docs/sftp.md000066400000000000000000001071121456036076300175040ustar00rootroot00000000000000# SFTP Both client-side and server-side SFTP are supported. Starting from version 2.0, the SFTP related code is located in the `sshd-sftp` artifact, so one needs to add this additional dependency to one's maven project: ```xml org.apache.sshd sshd-sftp ...same as sshd-core... ``` ## Server-side SFTP On the server side, the following code needs to be added: ```java SftpSubsystemFactory factory = new SftpSubsystemFactory.Builder() ...with... ...with... .build(); server.setSubsystemFactories(Collections.singletonList(factory)); ``` **Note:** the factory uses an ad-hoc `CloseableExecutorService` in order to spawn the necessary threads for processing the protocol messages. The user can provide a custom `Supplier` of such a service - however, it must be protected from shutdown if the user needs it to remain active between successive SFTP session. This can be done via the `ThreadUtils#noClose` utility: ```java CloseableExecutorService mySpecialExecutor = ...; SftpSubsystemFactory factory = new SftpSubsystemFactory.Builder() .withExecutorServiceProvider(() -> ThreadUtils.noClose(mySpecialExecutor)) .build(); server.setSubsystemFactories(Collections.singletonList(factory)); ``` ### `SftpEventListener` Provides information about major SFTP protocol events. The provided `File/DirectoryHandle` to the various callbacks can also be used to store user-defined attributes via its `AttributeStore` implementation. The listener is registered at the `SftpSubsystemFactory`: ```java public class MySfpEventListener implements SftpEventListener { private static final AttributeKey MY_SPECIAL_KEY = new Attribute(); ... @Override public void opening(ServerSession session, String remoteHandle, Handle localHandle) throws IOException { localHandle.setAttribute(MY_SPECIAL_KEY, instanceOfSomeType); } @Override public void writing( ServerSession session, String remoteHandle, FileHandle localHandle, long offset, byte[] data, int dataOffset, int dataLen) throws IOException { SomeType myData = localHandle.getAttribute(MY_SPECIAL_KEY); ...do something based on my data... } } SftpSubsystemFactory factory = new SftpSubsystemFactory(); factory.addSftpEventListener(new MySftpEventListener()); sshd.setSubsystemFactories(Collections.>singletonList(factory)); ``` **Note:** the attached attributes are automatically removed once handle has been closed - regardless of whether the close attempt was successful or not. In other words, after `SftpEventListener#closed` has been called, all attributes associated with the handle are cleared. ### `SftpFileSystemAccessor` This is the abstraction providing the SFTP server subsystem access to files and directories. The SFTP subsystem uses this abstraction to obtain file channels and/or directory streams. One can override the default implementation and thus be able to track and/or intervene in all opened files and folders throughout the SFTP server subsystem code. The accessor is registered/overwritten in via the `SftpSubSystemFactory`: ```java SftpSubsystemFactory factory = new SftpSubsystemFactory.Builder() .withFileSystemAccessor(new MySftpFileSystemAccessor()) .build(); server.setSubsystemFactories(Collections.singletonList(factory)); ``` **Note:** * Closing of file channel/directory streams created by the accessor are also closed via callbacks to the same accessor * When closing a file channel that may have been potentially modified, the default implementation forces a synchronization of the data with the file-system. This behavior can be modified by setting the `sftp-auto-fsync-on-close` property to *false* (or by providing a customized implementation that involves other considerations as well). ### Internal exceptions and error message handling If an exception is thrown during processing of an SFTP command, then the exception is translated into a `SSH_FXP_STATUS` message using a registered `SftpErrorStatusDataHandler`. The default implementation provides a short description of the failure based on the thrown exception type. However, users may override it when creating the `SftpSubsystemFactory` and provide their own codes and/or messages - e.g., for debugging one can register a `DetailedSftpErrorStatusDataHandler` (see `sshd-contrib`) that "leaks" more information in the generated message. ### Intercepting data sent via STDERR channel data from the client If the registered handler implements `ChannelSessionAware` then it will also be informed of the registered `ChannelSession` when it is provided to the `SftpSubsystem` itself. This can be used to register an extended data writer that override the default (which ignores such data) and can handle data sent via the STDERR channel. **Note:** this feature is allowed according to [SFTP version 4 - section 3.1](https://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-3.1): >> Packets are sent and received on stdout and stdin. Data sent on stderr by the server SHOULD be considered free format debug or supplemental error information, and MAY be displayed to the user. however, the current code provides no built-in support for this feature other than ignoring any such sent data. If registering an extended data writer one should take care of any race conditions that may occur where (extended) data may arrive before the handler is informed of the existence of the `ChannelSession`. For this purpose one should configure a reasonable buffer size by setting the `channel-session-max-extdata-bufsize` property. This way, if any data arrives before the extended data handler is registered it will be buffered (up to the specified max. size). **Note:** if a buffer size is configured but no extended data handler is registered when channel is spawning the command then an exception will occur. ### Sending custom data via STDERR channel data to the client Same logic as the STDERR incoming data applies to the outgoing error I/O streams provided to the `SftpSubsystem`. If the handler implements the relevant `CommandDirectErrorStreamAware` and/or `AsyncCommandErrorStreamAware` interface then it will be provided with the relevant error stream when the SFTP subsystem is initialized. **Note**: the current `SftpSubsystem`implementation uses *asynchronous* streams so `AsyncCommandErrorStreamAware` is the interface that will be invoked. However, in order to support possible future changes it is highly recommended that any custom code implement **both** interfaces. ### Symbolic links handling Whenever the server needs to execute a command that may behave differently if applied to a symbolic link instead of its target it consults the `AbstractSftpSubsystemHelper#resolvePathResolutionFollowLinks` method. By default, this method simply consultsthe value of the `sftp-auto-follow-links` configuration property (default=*true*). **Note:** the property is consulted only for cases where there is no clear indication in the standard how to behave for the specific command. E.g., the `lsetstat@openssh.com` command specifically specifies that symbolic links should not be followed, so the implementation does not consult the aforementioned property. However, the final decision what `LinkOption`(s) to use is left to the `SftpFileSystemAccessor#resolveFileAccessLinkOptions` method (which by default does not interfere in the decision). ## Client-side SFTP In order to obtain an `SftpClient` instance one needs to use an `SftpClientFactory`: ```java try (ClientSession session = ...obtain session...) { SftpClientFactory factory = ...obtain factory... try (SftpClient client = factory.createSftpClient(session)) { ... use the SFTP client... } // NOTE: session is still alive here... } ``` A default client factory implementations is provided in the module - see `SftpClientFactory.instance()` If the intended use of the client instance is "one-shot" - i.e., the client session should be closed when the SFTP client instance is closed, then it is possible to obtain a special wrapper that implements this functionality: ```java // The underlying session will also be closed when the client is try (SftpClient client = createSftpClient(....)) { ... use the SFTP client... } SftpClient createSftpClient(...) { ClientSession session = ...obtain session... SftpClientFactory factory = ...obtain factory... SftpClient client = factory.createSftpClient(session); return client.singleSessionInstance(); } ``` ### Using a custom `SftpClientFactory` The code creates `SftpClient`-s and `SftpFileSystem`-s using a default built-in `SftpClientFactory` instance (see `DefaultSftpClientFactory`). Users may choose to use a custom factory in order to provide their own implementations - e.g., in order to override some default behavior - e.g.: ```java SshClient client = ... setup client... try (ClientSession session = client.connect(user, host, port).verify(timeout).getSession()) { session.addPasswordIdentity(password); session.auth.verify(timeout); // User-specific factory try (SftpClient sftp = MySpecialSessionSftpClientFactory.INSTANCE.createSftpClient(session)) { ... instance created through SpecialSessionSftpClientFactory ... } } ``` ### Version selection via `SftpVersionSelector` The SFTP subsystem code supports versions 3-6 (inclusive), and by default attempts to negotiate the highest possible one - on both client and server code. The user can intervene and force a specific version or a narrower range. ```java SftpVersionSelector myVersionSelector = new SftpVersionSelector() { @Override public int selectVersion(ClientSession session, boolean initial, int current, List available) { int selectedVersion = ...run some logic to decide...; return selectedVersion; } }; try (ClientSession session = client.connect(user, host, port).verify(timeout).getSession()) { session.addPasswordIdentity(password); session.auth.verify(timeout); SftpClientFactory factory = SftpClientFactory.instance(); try (SftpClient sftp = factory.createSftpClient(session, myVersionSelector)) { ... do SFTP related stuff... } } ``` **Note:** the version selector is invoked **twice** - the first time in order to retrieve the initial version to be used when estabilishing the SFTP channel, and the second after having done so after receiving the server's version. The invocations are distinguished by the `initial` parameter value. On the server side, version selection restriction is more complex - please remember that according to the protocol specification >> The server responds with a SSH_FXP_VERSION packet, supplying the lowest (!) of its own and the client's version number Currently at the server we support requiring a **specific** version via the `SftpSubsystem#SFTP_VERSION` configuration key. The same can be achieved for the CLI SSHD code by specifying `-o sftp-version=N` option. For more advanced restrictions one needs to sub-class `SftpSubSystem` and provide a non-default `SftpSubsystemFactory` that uses the sub-classed code. ### Intercepting data sent via STDERR channel data from the server According to [SFTP version 4 - section 3.1](https://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-3.1) the server MAY send error data through the STDERR pipeline. By default, the code ignores such data - however, users may register a `SftpErrorDataHandler` that will be invoked whenever such data is received from the server. ```java ClientSession session = ...establish a session... SftpClientFactory factory = ...obtain a factory instance... try (SftpClient client = factory.createSftpClient(session, new MySftpErrorDataHandler())) { ... } ``` The same applies to the `SftpFileSystem` - users may provide a custom error data handler that will be invoked whenever such data is received from the server. **Note:** * Error data handling must be **short** or it will cause the SSH session to hang - any long/blocking processing must be done in a separate thread. * The provided data buffer contents must be **copied** if they need to be used after the callback returns as the buffer contents might be re-used by the caller code. * Any exception thrown during handling of the data will cause the SFTP session to terminate. ### Using `SftpFileSystemProvider` to create an `SftpFileSystem` The code automatically registers the `SftpFileSystemProvider` as the handler for `sftp://` URL(s). Such URLs are interpreted as remote file locations and automatically exposed to the user as [Path](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html) objects. In effect, this allows the code to "mount" a remote directory via SFTP and treat it as if it were local using standard [java.nio](https://docs.oracle.com/javase/8/docs/api/java/nio/package-frame.html) calls like any "ordinary" file system. ```java // "Mounting" a file system URI uri = SftpFileSystemProvider.createFileSystemURI(host, port, username, password); try (FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap())) { Path remotePath = fs.getPath("/some/remote/path"); ... } // Full programmatic control SshClient client = ...setup and start the SshClient instance... SftpFileSystemProvider provider = new SftpFileSystemProvider(client); URI uri = SftpFileSystemProvider.createFileSystemURI(host, port, username, password); try (FileSystem fs = provider.newFileSystem(uri, Collections.emptyMap())) { Path remotePath = fs.getPath("/some/remote/path"); } ``` The obtained `Path` instance can be used in exactly the same way as any other "regular" one: ```java try (InputStream input = Files.newInputStream(remotePath)) { ...read from remote file... } try (DirectoryStream ds = Files.newDirectoryStream(remoteDir)) { for (Path remoteFile : ds) { if (Files.isRegularFile(remoteFile)) { System.out.println("Delete " + remoteFile + " size=" + Files.size(remoteFile)); Files.delete(remoteFile); } else if (Files.isDirectory(remoteFile)) { System.out.println(remoteFile + " - directory"); } } } ``` It is highly recommended to `close()` the mounted file system once no longer necessary in order to release the associated SFTP session sooner rather than later - e.g., via a `try-with-resource` code block. **Caveat:** Due to URI encoding of the username/password as a basic authentication, the system currently does not allow colon (`:`) in either one in order to avoid parsing confusion. See [RFC 3986 - section 3.2.1](https://tools.ietf.org/html/rfc3986#section-3.2.1): >> Use of the format "user:password" in the userinfo field is >> deprecated ... Applications may choose to ignore or reject such >> data when it is received as part of a reference... See also the technical notes on the [SftpFileSystem](./technical/sftp_filesystem.md). #### Configuring the `SftpFileSystemProvider` When "mounting" a new file system one can provide extra configuration parameters using either the environment map in the [FileSystems#newFileSystem](https://docs.oracle.com/javase/8/docs/api/java/nio/file/FileSystems.html#newFileSystem) method or via the URI query parameters. See the `SftpFileSystemProvider` for the available configuration keys and values. ```java // Using explicit parameters Map params = new HashMap<>(); params.put("param1", value1); params.put("param2", value2); ...etc... URI uri = SftpFileSystemProvider.createFileSystemURI(host, port, username, password); try (FileSystem fs = FileSystems.newFileSystem(uri, params)) { Path remotePath = fs.getPath("/some/remote/path"); ... work with the remote path... } // Using URI parameters Path remotePath = Paths.get(new URI("sftp://user:password@host/some/remote/path?param1=value1¶m2=value2...")); // Releasing the file-system once no longer necessary try (FileSystem fs = remotePath.getFileSystem()) { ... work with the remote path... } ``` **Note**: if **both** options are used then the URI parameters **override** the environment ones ```java Map params = new HashMap<>(); params.put("param1", value1); params.put("param2", value2); // The value of 'param1' is overridden in the URI try (FileSystem fs = FileSystems.newFileSystem( new URI("sftp://user:password@host/some/remote/path?param1=otherValue1", params)) { Path remotePath = fs.getPath("/some/remote/path"); ... work with the remote path... } ``` ### Configuring the client session used to create an `SftpFileSystem` It is possible to register a `SftpFileSystemClientSessionInitializer` with the provider instead of the default one and thus better control the `ClientSession` used to generate the file-system instance. The default implementation simply connects and authenticates before creating a default `SftpFileSystem` instance. Users may wish to override some options or provide their own - e.g., execute a password-less authentication instead of the (default) password-based one: ```java SftpFileSystemProvider provider = ... obtain/create a provider ... provider.setSftpFileSystemClientSessionInitializer(new SftpFileSystemClientSessionInitializer() { @Override public void authenticateClientSession( SftpFileSystemProvider provider, SftpFileSystemInitializationContext context, ClientSession session) throws IOException { /* * Set up password-less login instead of password-based using the specified key * * Note: if SSH client and/or session already have a KeyPairProvider set up and the code * knows that these keys are already registered with the remote server, then no need to * add the public key identitiy - can simply call sesssion.auth().verify(context.getMaxAuthTime()). */ KeyPair kp = ... obtain a registered key-pair... session.addPublicKeyIdentity(kp); sesssion.auth().verify(context.getMaxAuthTime()); } }); ``` ### SFTP sent/received names encoding By default, the SFTP client uses UTF-8 to encode/decode any referenced file/folder name. However, some servers do not properly encode such names, and thus the "visible" names by the client become corrupted, or even worse - cause an exception upon decoding attempt. The `SftpClient` exposes a `get/setNameDecodingCharset` method which enables the user to modify the charset - even while the SFTP session is in progress - e.g.: ```java try (SftpClient client = ...obtain an instance...) { client.setNameDecodingCharset(Charset.forName("ISO-8859-8")); for (DirEntry entry : client.readDir(...some path...)) { ...handle entry assuming ISO-8859-8 encoded names... } client.setNameDecodingCharset(Charset.forName("ISO-8859-4")); for (DirEntry entry : client.readDir(...some other path...)) { ...handle entry assuming ISO-8859-4 encoded names... } } ``` The initial charset can be pre-configured on the client/session by using the `sftp-name-decoding-charset` property - if none specified then UTF-8 is used. **Note:** the value can be a charset name or a `java.nio.charset.Charset` instance - e.g.: ```java SshClient client = ... setup/obtain an instance... // default for ALL SFTP clients obtained through this client PropertyResolverUtils.updateProperty(client, SftpModuleProperties.NAME_DECODING_CHARSET.getName(), "ISO-8859-8"); try (ClientSession session = client.connect(...)) { session.addPasswordIdentity(password); session.auth().verify(timeout); // default for ALL SFTP clients obtained through the session - overrides client setting PropertyResolverUtils.updateProperty(session, SftpModuleProperties.NAME_DECODING_CHARSET.getName(), "ISO-8859-4"); SftpClientFactory factory = SftpClientFactory.instance(); try (SftpClient sftp = factory.createSftpClient(session)) { for (DirEntry entry : sftp.readDir(...some path...)) { ...handle entry assuming ISO-8859-4 (inherited from the session) encoded names... } // override the inherited default from the session sftp.setNameDecodingCharset(Charset.forName("ISO-8859-1")); for (DirEntry entry : sftp.readDir(...some other path...)) { ...handle entry assuming ISO-8859-1 encoded names... } } } ``` On the server side, one can use the `SftpFileSystemAccessor#putRemoteFileName` to encode the returned file name/path using non-UTF8 encoding. However, this might break clients that expect UTF-8 - i.e., as long as both the client and server are somehow "aligned" on the encoding being used it will work. In this context, one might also need to consider implementing the `filename-charset` , `filename-translation-control` extensions as described in [DRAFT 13 - section 6](https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-6) on the server side - though it is not supported out-of-the-box in version 3 (which what most clients run). ### Listing SFTP directories Listing directories can be done in Java in various ways. With the Java NIO framework, a common approach is ```java public void processDirectory(Path directoryPath, Consumer process) throws IOException { try (DirectoryStream dir = Files.newDirectoryStream(directoryPath)) { for (Path path : dir) { process.accept(path); // Do whatever needs to be done with 'path' } } } ``` This also works fine if the `Path` is an `SftpPath` obtained from an `SftpFileSystem`. But what if you also need the file _attributes_ ? Again, in plain Java NIO, one might do ```java public void processDirectory(Path directoryPath, BiConsumer process) throws IOException { try (DirectoryStream dir = Files.newDirectoryStream(directoryPath)) { for (Path path : dir) { BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class); process.accept(path, attributes); } } } ``` This gets all the Paths of the files inside the directory, then reads their attributes one-by-one. On Unix, there is variation using `Files.walkFileTree` that may have much better performance: ```java public void processDirectory(Path directoryPath, BiConsumer process) throws IOException { Files.walkFileTree(directoryPath, EnumSet.noneOf(FileVisitOption.class), 1, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path path, BasicFileAttributes attributes) { // Beware this is also called for the directory itself process.accept(path, attributes); return FileVisitResult.CONTINUE; } }); } ``` This typically performs better on Unix because the file system can deliver the file attributes together with the paths, and the standard Java implementation of `FileTreeWalker` takes advantage of this. On Windows you'll typically not see any improvement because the file system stores attributes differently and has to fetch them extra anyway. This is important when remote file systems come into play. With an `SftpFileSystem`, the call to `Files.readAttributes()` is a _remote call_ to the SFTP server, hence it's an expensive operation. Thus the first variant is slow, which may make processing a directory with many files excruciatingly slow. SFTP has a directory model similar to Unix: a request for a directory listing always returns the file names _and_ the file attributes. But Java's `FileVisitor` doesn't know this, and doesn't know about `SftpFileSystem` at all -- it's just a normal `java.nio.file.FileSystem` for it. Hence it doesn't use its internal optimization for Unix file systems and instead also calls `Files.readAttributes()` for each file under the hood. This makes the second variant also slow with an `SftpFileSystem`. To get paths and attributes in an _efficient_ way from an `SftpFileSystem`, one has to bypass the `FileSystem` abstraction. One can do it all manually using SFTP commands directly: ```java public void processSftpDirectory(SftpPath directoryPath, BiConsumer process) throws IOException { try (SftpClient client = directoryPath.getFileSystem().getClient()) { for (SftpClient.DirEntry directoryEntry : client.readDir(directoryPath.toString()) { SftpClient.Attributes attributes = directoryEntry.getAttributes(); String file = directoryEntry.getFilename(); if (".".equals(file)) { // The directory itself. process(directoryPath, attributes); } else if ("..".equals(file)) { // The parent directory, if any process(directoryPath.getParent(), attributes); } else { process(directoryPath.resolve(file), attributes); } } } } ``` Alternatively, one can also use the fact that Apache MINA sshd caches the SFTP file attributes it received from the server on the `SftpPath` objects it returns from a `DirectoryStream`: ```java public void processSftpDirectory(SftpPath directoryPath, BiConsumer process) throws IOException { try (DirectoryStream dir = Files.newDirectoryStream(directoryPath)) { for (Path path : dir) { if (path instanceof SftpPath) { SftpClient.Attributes attributes = ((SftpPath) path).getAttributes(); process.accept(path, attributes); } else { // A DirectoryStream on a directory given by an SftpPath always returns SftpPath instances as elements. throw new IllegalStateException("Path " + path + " has unexpected type " + path.getClass().getName()); } } } } ``` In either case, the behavior is undefined if files in the directory or their attributes are changed during the iteration. File attributes, whether cached or not, and irrespective of the type of `FileSystem`, represent a snapshot taken at the time they were obtained; they do not reflect any changes made to the files after that. The cached attributes Apache MINA sshd provides through the `SftpFileSystem` reflect the state when the directory listing was obtained. Calling `Files.readAttributes()` on an `SftpPath` always is a remote call fetching a fresh snapshot. Note: the same is true for any other operation that implicitly calls `Files.readAttributes()`, like `Files.size()`, `Files.exists()`, `Files.getOwner()`, `Files.isDirectory()`, and so on. Even if an `SftpFileSystem` fulfills the general contract of a `FileSystem`, a client still has to be aware that it is a _remote file system_ that may have quite different performance characteristics than a local file system. ### SFTP aware directory scanners The framework provides special SFTP aware directory scanners that look for files/folders matching specific patterns. The scanners support *recursive* scanning of the directories based on the selected patterns. E.g. - let's assume the layout present below ``` root + --- a1.txt + --- a2.csv + sub1 +--- b1.txt +--- b2.csv + sub2 + --- c1.txt + --- c2.csv ``` Then scan results from `root` are expected as follows for the given patterns * "**/*" - all the files/folders - `[a1.txt, a2.csv, sub1, sub2, b1.txt, b2.csv, c1.txt, c2.csv]` * "**/*.txt" - only the ".txt" files - `[a1.txt, b1.txt, c1.txt]` * "*" - only the files/folders at the root - `[a1.txt, a2.csv, sub1, sub2]` * "*.csv" - only `a2.csv` at the root **Note:** the scanner supports various patterns - including *regex* - see `DirectoryScanner` and `SelectorUtils` classes for supported patterns and matching - include case sensitive vs. insensitive match. ```java // Using an SftpPathDirectoryScanner FileSystem fs = ... obtain an SFTP file system instance ... Path basedir = fs.getPath("/some/remote/path"); DirectoryScanner ds = new SftpPathDirectoryScanner(basedir, ...pattern...); Collection matches = ds.scan(); // Using an SftpClientDirectoryScanner SftpClient client = ... obtain a client instance ... Strinng basedir = "/some/remote/path"; SftpClientDirectoryScanner ds = new SftpClientDirectoryScanner(basedir, ...pattern...); Collection matches = ds.scan(client); ``` ## Extensions & custom file/folder attributes Extending the SFTP protocol and/or the reported file/folder attributes ### SFTP protocol extensions Both client and server support several of the SFTP extensions specified in various drafts: * `supported` - [DRAFT 05 - section 4.4](http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-05.tx) * `supported2` - [DRAFT 13 section 5.4](https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#page-10) * `versions` - [DRAFT 09 Section 4.6](http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-09.txt) * `vendor-id` - [DRAFT 09 - section 4.4](http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-09.txt) * `acl-supported` - [DRAFT 11 - section 5.4](https://tools.ietf.org/html/draft-ietf-secsh-filexfer-11) * `newline` - [DRAFT 09 Section 4.3](http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-09.txt) * `md5-hash`, `md5-hash-handle` - [DRAFT 09 - section 9.1.1](http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-09.txt) * `check-file-handle`, `check-file-name` - [DRAFT 09 - section 9.1.2](http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-09.txt) * `copy-file`, `copy-data` - [DRAFT 00 - sections 6, 7](http://tools.ietf.org/id/draft-ietf-secsh-filexfer-extensions-00.txt) * `space-available` - [DRAFT 09 - section 9.3](http://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/draft-ietf-secsh-filexfer-09.txt) * `filename-charset`, `filename-translation-control` - [DRAFT 13 - section 6](https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-6) - only client side Furthermore several [OpenSSH SFTP extensions](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL) are also supported: * `fsync@openssh.com` * `fstatvfs@openssh.com` * `hardlink@openssh.com` * `posix-rename@openssh.com` - only client side * `statvfs@openssh.com` * `lsetstat@openssh.com` * `limits@openssh.com` On the server side, the reported standard extensions are configured via the `SftpModuleProperties.CLIENT_EXTENSIONS` configuration key, and the _OpenSSH_ ones via the `SftpModuleProperties.OPENSSH_EXTENSIONS`. On the client side, all the supported extensions are classes that implement `SftpClientExtension`. These classes can be used to query the client whether the remote server supports the specific extension and then obtain a parser for its contents. Users can easily add support for more extensions in a similar manner as the existing ones by implementing an appropriate `ExtensionParser` and then registering it at the `ParserUtils` - see the existing ones for details how this can be achieved. ```java // properietary/special extension parser ParserUtils.registerExtension(new MySpecialExtension()); try (ClientSession session = client.connect(username, host, port).verify(timeout).getSession()) { session.addPasswordIdentity(password); session.auth().verify(timeout); SftpClientFactory factory = SftpClientFactory.instance(); try (SftpClient sftp = factory.createSftpClient(session)) { Map extensions = sftp.getServerExtensions(); // Key=extension name, value=registered parser instance Map data = ParserUtils.parse(extensions); for (Map.Entry de : data.entrySet()) { String extName = de.getKey(); Object extValue = de.getValue(); if (SftpConstants.EXT_ACL_SUPPORTED.equalsIgnoreCase(extName)) { AclCapabilities capabilities = (AclCapabilities) extValue; ...see what other information can be gleaned from it... } else if (SftpConstants.EXT_VERSIONS.equalsIgnoreCase(extName)) { Versions versions = (Versions) extValue; ...see what other information can be gleaned from it... } else if ("my-special-extension".equalsIgnoreCase(extName)) { MySpecialExtension special = (MySpecialExtension) extValue; ...see what other information can be gleaned from it... } // ...etc.... } } } ``` One can skip all the conditional code if a specific known extension is required: ```java try (ClientSession session = client.connect(username, host, port).verify(timeout).getSession()) { session.addPasswordIdentity(password); session.auth().verify(timeout); SftpClientFactory factory = SftpClientFactory.instance(); try (SftpClient sftp = factory.createSftpClient(session)) { // Returns null if extension is not supported by remote server SpaceAvailableExtension space = sftp.getExtension(SpaceAvailableExtension.class); if (space != null) { ...use it... } } } ``` #### Contributing support for a new SFTP extension * Add the code to handle the new extension in `AbstractSftpSubsystemHelper#executeExtendedCommand` * Declare the extension name in `DEFAULT_SUPPORTED_CLIENT_EXTENSIONS` or `DEFAULT_OPEN_SSH_EXTENSIONS` (same class) - according to the extension type (generic or *OpenSSH* one). * In the `org.apache.sshd.sftp.client.extensions.helpers` package implement an extension of `AbstractSftpClientExtension` for sending and receiving the newly added extension. * Add a relevant parser for reported extension data initial report (if necessary) in `ParserUtils#BUILT_IN_PARSERS` See how other extensions are implemented and follow their example ### Providing/processing file/folder custom attributes According to [SFTP - File Attributes](https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-02#section-5) it is possible to provide custom attributes for a referenced file/folder. The client-side code supports this via the `Attributes#getExtensions` call. On the server-side one needs to provide a custom `SftpFileSystemAccessor` that overrides the `resolveReportedFileAttributes` method (which by default simply returns the original attrbiutes as-is. A similar hook method has been provided in case a client attempts to apply custom attributes - simply need to provide a implementation that obverrides `applyExtensionFileAttributes` (which by default ignores the attributes). ```java class MyCustomSftpFileSystemAccessor implements SftpFileSystemAccessor { @Override public NavigableMap resolveReportedFileAttributes( SftpSubsystemProxy subsystem, Path file, int flags, NavigableMap attrs, LinkOption... options) throws IOException { Map extra = (Map) attrs.get(IoUtils.EXTENDED_VIEW_ATTR); if (extra == null) { extra = new HashMap<>(); attrs.put(IoUtils.EXTENDED_VIEW_ATTR, extra) } extra.put("custom1", ...some string...); extra.put("custom", ...some byte[]...) } @Override public void applyExtensionFileAttributes( SftpSubsystemProxy subsystem, Path file, Map extensions, LinkOption... options) throws IOException { if (MapEntryUtils.isNotEmpty(extensions)) { ...process the extensions... } } } SftpSubsystemFactory factory = new SftpSubsystemFactory.Builder() .withFileSystemAccessor(new MyCustomSftpFileSystemAccessor()) .build(); SshdServer sshd = ...setup... sshd.setSubsystemFactories(Collections.singletonList(factory)); ``` **Note:** * The code assumes that the extension name is a **string** - the draft specification actually allows an array of bytes as well, but we chose simplicity. * The value can be either a string or an array of bytes. If the value is neither (e.g., an integer) then the value's *toString()* will be used. ## References * [SFTP drafts for the various versions](https://tools.ietf.org/wg/secsh/draft-ietf-secsh-filexfer/) apache-mina-sshd-46fc8d6/docs/standards.md000066400000000000000000000242741456036076300205220ustar00rootroot00000000000000# Supported standards ## Reference implementation documentation * [RFC 4251 - The Secure Shell (SSH) Protocol Architecture](https://tools.ietf.org/html/rfc4251) * [RFC 4252 - The Secure Shell (SSH) Authentication Protocol](https://tools.ietf.org/html/rfc4252) * [RFC 4253 - The Secure Shell (SSH) Transport Layer Protocol](https://tools.ietf.org/html/rfc4253) * [RFC 4254 - The Secure Shell (SSH) Connection Protocol](https://tools.ietf.org/html/rfc4254) * [RFC 4256 - Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)](https://tools.ietf.org/html/rfc4256) * [RFC 4335 - The Secure Shell (SSH) Session Channel Break Extension](https://tools.ietf.org/html/rfc4335) * [RFC 4344 - The Secure Shell (SSH) Transport Layer Encryption Modes](https://tools.ietf.org/html/rfc4344) * [RFC 4345 - Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol](https://tools.ietf.org/html/rfc4345) * [RFC 4419 - Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol](https://tools.ietf.org/html/rfc4419) * [RFC 4716 - The Secure Shell (SSH) Public Key File Format](https://tools.ietf.org/html/rfc4716) * [RFC 5208 - Public-Key Cryptography Standards (PKCS) #8 - version 1.2](https://tools.ietf.org/html/rfc5208) * [RFC 5480 - Elliptic Curve Cryptography Subject Public Key Information](https://tools.ietf.org/html/rfc5480) * [RFC 5647 - AES Galois Counter Mode for the Secure Shell Transport Layer Protocol](https://tools.ietf.org/html/rfc5647) * [RFC 5656 - Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer](https://tools.ietf.org/html/rfc5656) * [RFC 5915 - Elliptic Curve Private Key Structure](https://tools.ietf.org/html/rfc5915) * [RFC 5958 - EncryptedPrivateKeyInfo](https://www.rfc-editor.org/rfc/rfc5958) * [RFC 6668 - SHA-2 Data Integrity Verification for the Secure Shell (SSH) Transport Layer Protocol](https://tools.ietf.org/html/rfc6668) * [RFC 8160 - IUTF8 Terminal Mode in Secure Shell (SSH)](https://tools.ietf.org/html/rfc8160) * [RFC 8268 - More Modular Exponentiation (MODP) Diffie-Hellman (DH) Key Exchange (KEX) Groups for Secure Shell (SSH)](https://tools.ietf.org/html/rfc8268) * [RFC 8308 - Extension Negotiation in the Secure Shell (SSH) Protocol](https://tools.ietf.org/html/rfc8308) * **Note:** - the code contains [**hooks**](./event-listeners.md#kexextensionhandler) for implementing the RFC and also provides default client and server implementation for `server-sig-algs` extensions. * [RFC 8332 - Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell (SSH) Protocol](https://tools.ietf.org/html/rfc8332) * **Note:** - the server side supports these signatures by default. The client side requires specific initialization - see [section 3.3](https://tools.ietf.org/html/rfc8332#section-3.3) and also the above mentioned hooks for [RFC 8308](https://tools.ietf.org/html/rfc8308). * [RFC 8731 - Secure Shell (SSH) Key Exchange Method Using Curve25519 and Curve448](https://tools.ietf.org/html/rfc8731) * [Key Exchange (KEX) Method Updates and Recommendations for Secure Shell](https://tools.ietf.org/html/draft-ietf-curdle-ssh-kex-sha2-03) ### OpenSSH * [OpenSSH support for U2F/FIDO security keys](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.u2f) * **Note:** the server side supports these keys by default. The client side requires specific initialization * [OpenSSH public-key certificate authentication system for use by SSH](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.certkeys) * [OpenSSH 1.9 transport: strict key exchange extension](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL) * [(Some) OpenSSH SFTP extensions](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL) **Note:** some implementations may be limited to client-side - i.e., we provide a capability for the client to detect if the server supports the extension and then use it, but our server does not publish it as being supported. | Section | Extension | Client | Server | | ------- | -------------------------- | ------ | ------ | | 4.3 | `posix-rename@openssh.com` | Yes | Yes | | 4.4 | `statvfs@openssh.com` | Yes | Yes | | 4.4 | `fstatvfs@openssh.com` | Yes | Yes | | 4.5 | `hardlink@openssh.com` | Yes | Yes | | 4.6 | `fsync@openssh.com` | Yes | Yes | | 4.7 | `lsetstat@openssh.com` | Yes | Yes | | 4.8 | `limits@openssh.com` | Yes | Yes | | 4.10 | `copy-data` | Yes | Yes | ### SFTP version 3-6 + extensions * `supported` - [DRAFT 05 - section 4.4](https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-05#section-4.4) * `supported2` - [DRAFT 13 section 5.4](https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-5.4) * `versions` - [DRAFT 09 Section 4.6](https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-09#section-4.6) * `vendor-id` - [DRAFT 09 - section 4.4](https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-09#section-4.4) * `acl-supported` - [DRAFT 11 - section 5.4](https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-11#section-5.4) * `newline` - [DRAFT 09 Section 4.3](https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-09#section-4.3) * `md5-hash`, `md5-hash-handle` - [DRAFT 09 - section 9.1.1](https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-09#section-9.1.1) * `check-file-handle`, `check-file-name` - [DRAFT 09 - section 9.1.2](https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-09#section-9.1.2) * `copy-file`, `copy-data` - [DRAFT 00 - sections 6, 7](https://tools.ietf.org/id/draft-ietf-secsh-filexfer-extensions-00.txt) * `space-available` - [DRAFT 09 - section 9.2](https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-09#section-9.2) * `filename-charset`, `filename-translation-control` - [DRAFT 13 - section 6](https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-6) - only client side ### Miscellaneous * [SSH proxy jumps](./internals.md#ssh-jumps) * [Endless tarpit](https://nullprogram.com/blog/2019/03/22/) - see [HOWTO(s)](./howto.md) section. ## Implemented/available support ### Authentication methods * hostbased, publickey, [OpenSSH host-based public-key](https://github.com/openssh/openssh-portable/blob/1781f507c11/PROTOCOL#L349), keyboard-interactive, password ### Ciphers * aes128cbc, aes128ctr, aes192cbc, aes192ctr, aes256cbc, aes256ctr, arcfour128, arcfour256, blowfish-cbc, aes128-gcm@openssh.com, aes256-gcm@openssh.com, chacha20-poly1305@openssh.com, 3des-cbc ### Digests * md5, sha1, sha224, sha256, sha384, sha512 ### Macs * hmacmd5, hmacmd596, hmacsha1, hmacsha196, hmacsha256, hmacsha512, hmac-sha2-256-etm@openssh.com , hmac-sha2-512-etm@openssh.com, hmac-sha1-etm@openssh.com ### Key exchange * diffie-hellman-group1-sha1, diffie-hellman-group-exchange-sha256, diffie-hellman-group14-sha1, diffie-hellman-group14-sha256 , diffie-hellman-group15-sha512, diffie-hellman-group16-sha512, diffie-hellman-group17-sha512, diffie-hellman-group18-sha512 , ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, curve25519-sha256, curve25519-sha256@libssh.org, curve448-sha512 * On Java versions before Java 11, [Bouncy Castle](./dependencies.md#bouncy-castle) is required for curve25519-sha256, curve25519-sha256@libssh.org, or curve448-sha512. ### Compressions * none, zlib, zlib@openssh.com ### Signatures/Keys * ssh-dss, ssh-rsa, rsa-sha2-256, rsa-sha2-512, nistp256, nistp384, nistp521 , ssh-ed25519 (requires `eddsa` optional module), sk-ecdsa-sha2-nistp256@openssh.com, sk-ssh-ed25519@openssh.com , ssh-rsa-cert-v01@openssh.com, ssh-dss-cert-v01@openssh.com, ssh-ed25519-cert-v01@openssh.com , ecdsa-sha2-nistp256-cert-v01@openssh.com, ecdsa-sha2-nistp384-cert-v01@openssh.com, ecdsa-sha2-nistp521-cert-v01@openssh.com **Note:** The above list contains all the supported security settings in the code. However, in accordance with the latest recommendations the default client/server setup includes only the security settings that are currently considered safe to use. Users who wish to include the unsafe settings must do so **explicitly**. The following settings have been deprecated and are no longer included in the default setup: * [RFC 8758 - Deprecating RC4 in Secure Shell (SSH)](https://tools.ietf.org/html/rfc8758) * [RFC 8429 - Deprecate Triple-DES (3DES) and RC4 in Kerberos](https://tools.ietf.org/html/rfc8429) * While it refers to Kerberos, it mentions weaknesses in DES as well. * [OpenSSH release notes](https://www.openssh.com/releasenotes.html) - usually a good indicator of de-facto practices * SHA-1 based key exchanges and signatures * MD5-based and truncated HMAC algorithms * [RFC 8270 - Increase the Secure Shell Minimum Recommended Diffie-Hellman Modulus Size to 2048 Bits](https://tools.ietf.org/html/rfc8270) **Note:** it still possible to use 1024 by initializing the value *programmatically* or via system property - see [Security providers setup](./security-providers.md#diff-hellman-group-exchange-configuration). The code still contains moduli for 1024 and will use them if user **explicitly** lowers the default minimum to it. **Caveat:**: According to [RFC 8332 - section 3.31](https://tools.ietf.org/html/rfc8332#section-3.3) >> >> Implementation experience has shown that there are servers that apply authentication penalties to clients >> attempting public key algorithms that the SSH server does not support. >> >> When authenticating with an RSA key against a server that does not implement the "server-sig-algs" extension, >> clients MAY default to an "ssh-rsa" signature to avoid authentication penalties. When the new rsa-sha2-* >> algorithms have been sufficiently widely adopted to warrant disabling "ssh-rsa", clients MAY default to one of >> the new algorithms. This means that users that encounter this (and related) problems must modify the supported security settings **explicitly** in order to avoid the issue. **Special notice:** `ssh-rsa` was left in as part of the default setup since there are still a lot of systems / users using it. However, in future version it will be removed from the default. We therefore strongly encourage users to migrate to other keys (e.g. ECDSA, ED25519) as soon as possible. apache-mina-sshd-46fc8d6/docs/technical/000077500000000000000000000000001456036076300201365ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/docs/technical/forward_dynamic_interaction.svg000066400000000000000000001267541456036076300264450ustar00rootroot00000000000000
Client SSH
Client SSH
Server SSH
Server SSH
Whatever
on host "faraway"
Whatever...
connectTo(faraway:B)
connectTo(faraway:B)
SSH_MSG_CHANNEL_OPEN
"direct-tcpip" faraway:B
SSH_MSG_CHANNEL_OPEN...
connect(B)
connect(B)
connectionSuccess
connectionSuccess
R
R
W
W
R
R
W
W
create
create
create
create
create
create
create
create
read(data)
read(dat...
write(B, data)
write(B, data)
read(B, data)
read(B,...
write(data)
write(data)
read(data)
read(data)
write(A, data)
write(A, data)
read(A, data)
read(A,...
write(data)
write(data)
Channel
Channel
SSH_MSG_CHANNEL_OPEN_SUCCESS
SSH_MSG_CHANNEL_OPEN_SUCCESS
TcpipClientChannel
TcpipCli...
TcpipServerChannel
TcpipSer...
startDynamicForwarding(A)
startDynamicForwarding(A)
SOCKS
SOCKS
create
create
listen(A)
listen(A)
connectTo(faraway:B)
connectTo(faraway:B)
success
success
success
success
Text is not SVG - cannot display
apache-mina-sshd-46fc8d6/docs/technical/forward_dynamic_overview.svg000066400000000000000000000362361456036076300257670ustar00rootroot00000000000000
Client
Client
Server
Server
faraway
faraway
A
A
22
22
B
B
listen
listen
SSH
SSH
Whatever
Whatever
SSH
SSH
SOCKS
SOCKS
connectTo(faraway:B)
connectTo(faraway...
Text is not SVG - cannot display
apache-mina-sshd-46fc8d6/docs/technical/forward_local_interaction.svg000066400000000000000000001177171456036076300261120ustar00rootroot00000000000000
Client SSH
Client SSH
Server SSH
Server SSH
Whatever
on host "faraway"
Whatever...
startLocalForwarding(A, faraway:B)
startLocalForwarding(A, faraway:B)
listen(A)
listen(A)
connectionAccepted(A)
connectionAccepted(A)
store(A, faraway:B)
store(A, faraway:B)
read(A, faraway:B)
read(A, faraway:B)
SSH_MSG_CHANNEL_OPEN
"direct-tcpip" faraway:B
SSH_MSG_CHANNEL_OPEN...
connect(B)
connect(B)
connectionSuccess
connectionSuccess
R
R
W
W
R
R
W
W
create
create
create
create
create
create
create
create
read(data)
read(dat...
write(B, data)
write(B, data)
read(B, data)
read(B,...
write(data)
write(data)
read(data)
read(data)
write(A, data)
write(A, data)
read(A, data)
read(A,...
write(data)
write(data)
Channel
Channel
SSH_MSG_CHANNEL_OPEN_SUCCESS
SSH_MSG_CHANNEL_OPEN_SUCCESS
TcpipClientChannel
TcpipCli...
TcpipServerChannel
TcpipSer...
Text is not SVG - cannot display
apache-mina-sshd-46fc8d6/docs/technical/forward_local_overview.svg000066400000000000000000000313011456036076300254210ustar00rootroot00000000000000
Client
Client
Server
Server
faraway
faraway
A
A
22
22
SSH
SSH
B
B
listen
listen
SSH
SSH
Whatever
Whatever
Text is not SVG - cannot display
apache-mina-sshd-46fc8d6/docs/technical/forward_remote_interaction.svg000066400000000000000000001211421456036076300262760ustar00rootroot00000000000000
Client SSH
Client SSH
Server SSH
Server SSH
Whatever
on host "near"
Whatever...
SSH_MSG_GLOBAL_REQUEST
"tcpip-forward" A
SSH_MSG_GLOBAL_REQUEST...
store(A, near:B)
store(A, near:B)
read(A, near:B)
read(A, near:B)
listen(A)
listen(A)
connectionAccepted(A)
connectionAccepted(A)
SSH_MSG_CHANNEL_OPEN
"forwarded-tcpip" A
SSH_MSG_CHANNEL_OPEN...
connect(B)
connect(B)
connectionSuccess
connectionSuccess
R
R
create
create
R
R
create
create
Channel
Channel
SSH_MSG_CHANNEL_OPEN_SUCCESS
SSH_MSG_CHANNEL_OPEN_SUCCESS
W
W
create
create
W
W
create
create
read(A, data)
read(A,...
write(data)
write(data)
read(data)
read(data)
write(B, data)
write(B, data)
read(B, data)
read(B,...
write(data)
write(data)
read(data)
read(dat...
write(A, data)
write(A, data)
TcpipServerChannel
TcpipSer...
TcpipClientChannel
TcpipCli...
Text is not SVG - cannot display
apache-mina-sshd-46fc8d6/docs/technical/forward_remote_overview.svg000066400000000000000000000316301456036076300256270ustar00rootroot00000000000000
near
near
Client
Client
Server
Server
B
B
Whatever
Whatever
A
A
SSH
SSH
SSH
SSH
22
22
listen
listen
Text is not SVG - cannot display
apache-mina-sshd-46fc8d6/docs/technical/global_requests.md000066400000000000000000000215001456036076300236510ustar00rootroot00000000000000## Global Requests **Global requests** are messages sent between an SSH client and an SSH server that are independent of any SSH channel. Such messages may just provide information to the peer, or they may instruct it to initiate certain actions. For example, starting or cancelling a [TCP/IP remote port forwarding](./tcpip-forwarding.md) is done with global requests. The OpenSSH host key update and rotation extension to the SSH protocol also uses global requests. Global requests are specified in [RFC 4254](https://tools.ietf.org/html/rfc4254#section-4). ### Request kinds Global requests are identified by a request name, and the sender may indicate whether it wants a reply from the recipient. So there are two different kinds of global requests: * `want-reply=false`: asynchronous, "fire-and-forget" one-way messages. * `want-reply=true`: messages to which there is a reply, similar to a remote procedure call (RPC) Other than the request name, a global request does not carry any request identifier. So a crucial piece of a normal RPC protocol is missing in the SSH protocol. In RPC, a request normally carries a unique identifier (some sequence number), which is repeated in the reply, so that the sender can know which request the reply belongs to. In the SSH protocol, this request identifier is missing in the reply. All SSH packets are globally numbered in a session; so each message *does* have a unique identifier. If that sequence number were included in the reply to a global request, the sender could know easily which request a certain reply belonged to. RFC 4254 specifies instead that *"it is REQUIRED that replies to SSH_MSG_GLOBAL_REQUESTS MUST be sent in the same order as the corresponding request messages"*. In other words, if one party sends two global requests ``` SSH_MSG_GLOBAL_REQUEST "a" want-reply=true ... SSH_MSG_GLOBAL_REQUEST "b" want-reply=true ... ``` the other party must reply first to "a" and then to "b". (Note that in the two requests the request-name might also be the same, for instance two "tcpip-forward" requests.) The reply can be either a `SSH_MSG_REQUEST_SUCCESS` message, possibly with additional data, or a `SSH_MSG_REQUEST_FAILURE` message, which carries no additional data. To implement such RPC-style requests without request identifiers in the reply, the sender must keep a list of requests it made (per session), and when it receives a reply associate it with the frontmost request made. ### Unknown requests If a recipient receives a global request with a request name it doesn't recognize, it is supposed to reply with a `SSH_MSG_REQUEST_FAILURE` message *if it was an RPC request* (`want-reply=true`). However, some SSH implementations respond with an `SSH_MSG_UNIMPLEMENTED` message instead. This may indicate that the recipient doesn't implement global requests at all. Replying on a global request with an unknown *request name* with an "unimplemented" message is not covered by the SSH RFCs. These "unimplemented" messages include the packet sequence number of the original message they refer to. [RFC 4253](https://tools.ietf.org/html/rfc4253#section-11.4) specifies that *"An implementation MUST respond to all unrecognized messages with an SSH_MSG_UNIMPLEMENTED message in the order in which the messages were received."* It is unspecified, though, whether this order and the order of global request replies from RFC 4254 are independent, or whether there must one single global order. To handle this, a sender must remember for each RPC-style request it makes also the packet sequence number so that it can remove the correct request from its list of global requests. ### API Prior to version 2.9.0, `Session.request()` was the only way to make an RPC-style global request (`want-reply=true`). There was no support for making "fire-and-forget" global requests (`want-reply=false`), such requests had to be sent directly via `Session.writePacket()`. Also, the implementation of `Session.request()` was *synchronous*: it sent the request and then waited until the reply was received, blocking the thread executing the call. There could be only one pending RPC-style request. (Some other SSH libraries also use such a simplistic implementation, for instance JSch 0.1.55.) Synchronous requests, however, are not a good idea with the asynchronous I/O frameworks (NIO2, Mina, Netty) that Apache MINA sshd uses. If the request was executed on an I/O thread, that thread would be blocked and couldn't handle any other message. Moreover, if the request was made on an I/O thread, this means it runs as part of handling some message in an SSH session, and Apache MINA sshd handles all messages in an SSH session sequentially and holds a session-global lock: any other thread that might receive the reply would not be able to deliver it because that lock would still be held by the blocked thread waiting for the reply. The blocking `Session.request()` implementation still exists in Apache MINA sshd 2.9.0. It provides a simple interface and may be useful in cases where one knows that the invocation happens in an application thread, not in an I/O thread handling some other incoming message. But Apache MINA 2.9.0 adds another variant that associates a callback to handle the reply with the request. That version of `Session.request()` does *not* block waiting for the reply. It just sends the request and records the request together with the callback handler in its list of global requests, and when the reply arrives invokes that handler on whatever I/O thread received the reply. Both versions of `Session.request()` in Apache MINA 2.9.0 can also be used to send "fire-and-forget" global requests. The asynchronous version of `Session.request()` has the interface ```java public GlobalRequestFuture request(Buffer buffer, String request, ReplyHandler replyHandler) throws IOException; ``` The `Buffer` is supposed to contain the full request, including the `request` name (for instance, "tcpip-forward"), the `want-reply` flag, and any additional data needed. This can be used to make RPC-style or "fire-and-forget" requests, and there are several possible ways to use it. * `want-reply=true` and `replyHandler != null`: the methods sends the request and returns a future that is fulfilled when the request was actually sent. The future is fulfilled with an exception if sending the request failed, or with `null` if it was sent successfully. Once the reply is received, the handler is invoked with the SSH command (`SSH_MSG_REQUEST_SUCCESS`, `SSH_MSG_REQUEST_FAILURE`, or `SSH_MSG_UNIMPLEMENTED`) and the buffer received. * `want-reply=true` and `replyHandler == null`: the method sends the request and returns a future that is fulfilled with an exception if sending it failed, or if a `SSH_MSG_REQUEST_FAILURE` or `SSH_MSG_UNIMPLEMENTED` reply was received. Otherwise the future is fulfilled with the received Buffer once the reply has been received. * `want-reply=false`: the method sends the request and returns a future that is fulfilled when the request was actually sent. The future is fulfilled with an exception if sending the request failed, or with an empty buffer if it was sent successfully. If `replyHandler != null`, it is invoked with an empty buffer once the request was sent. If the method throws an `IOException`, the request was not sent, and the handler will not be invoked. ### Implementation Global requests are implemented in Apache MINA sshd in [`AbstractSession`](../../sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java). The asynchronous `Session.request()` implementation uses a FIFO queue of requests sent, and in `AbstractSession.requestSuccess()` and `AbstractSession.requestFailure` associates a reply with the front-most request in that FIFO list. Only RPC-style requests with `want-reply=true` go onto this list. The FIFO list stores the [`GlobalRequestFuture`](../../sshd-core/src/main/java/org/apache/sshd/common/future/GlobalRequestFuture.java)) of the requests made. Futures are put onto the tail of the FIFO list before actually sending the request to avoid a possible race condition between registering the future and a reply coming in very quickly. If the request cannot be sent, such a future for a request that never went out is removed again from the tail of the FIFO queue. The implementation also keeps track of the SSH packet sequence number of each request made so that it can remove the correct request from the FIFO list when a `SSH_MSG_UNIMPLEMENTED` is received. This sequence number is determined when the request message packet is encrypted, and is set on the `GlobalRequestFuture` of the global request via a callback. When an "unimplemented" message is received and the FIFO list contains a request future with a matching sequence number, that request is removed from the list irrespective of its position in the list, and the request is failed as if a `SSH_MSG_REQUEST_FAILURE` message had been received. apache-mina-sshd-46fc8d6/docs/technical/kex.md000066400000000000000000000206231456036076300212520ustar00rootroot00000000000000## SSH Key Exchange **Key Exchange** (or **KEX** for short) is a sub-protocol in the SSH protocol enabling the two parties in a connection to exchange information and compute a shared secret that will then be used for encrypting all following messages. A key exchange runs initially, after the network connection is established, but before authentication. Later on, KEX may be repeated; when exactly, depends on various settings: * it is re-run when a certain amount of bytes have been sent since the last KEX. * it may be re-run when a certain number of SSH packets have been sent since the last KEX. * it may be re-run when a certain time has elapsed since the last KEX. The purpose of re-running KEX is to establish a new shared secret from time to time, changing the encryption for all subsequent messages, until the next KEX. This mitigates possible attacks against the encryption when a lot of data is sent using the same encryption with the same shared secret. KEX is specified in [RFC 4253, section 7](https://tools.ietf.org/html/rfc4253#section-7). ### Basic KEX message exchange A key exchange starts with both parties sending a SSH_MSG_KEX_INIT message, passing along information about available cryptographic algorithms. Both parties can decide from this information what kind of key exchange to perform. They then run the cryptographic key exchange protocol, which may incur several message exchanges. Once that protocol ends, both sides know the shared secret. At that point they both send a SSH_MSG_NEW_KEYS message to tell the other side they're ready, and use the new encryption for any subsequent outgoing message. The SSH_MSG_NEW_KEYS message itself is still sent with the old encryption. On receiving a SSH_MSG_NEW_KEYS message, each side starts using the new encryption to decrypt any subsequent incoming messages. Note that the SSH_MSG_NEW_KEYS message does not contain the new encryption key or the shared secret; it is just a marker message telling the other side that from now on, the new encryption will be used. Apache MINA sshd maintains internally in [`AbstractSession`](../../sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractSession.java) a *KEX state* (in Java [`KexState`](../../sshd-common/src/main/java/org/apache/sshd/common/kex/KexState.java)). This models the key exchange on one side of the connection as a state machine going through the states `DONE`, `INIT`, `RUN`, `KEYS`, `DONE`. ![KEX state machine](./kex_states.svg) These states mark important points in the key exchange sub-protocol: * `DONE` means no key exchange is ongoing, this side has received the peer's SSH_MSG_NEW_KEYS message, and both sides have a shared secret that they use for encryption. * `INIT` means this side of the connection has requested a new KEX; it has sent it's SSH_MSG_KEX_INIT message. * `RUN` means this side has received the peer's SSH_MSG_KEX_INIT message, and key exchange is running now to determine a new shared secret. * `KEYS` means the key exchange has been done; both sides know the shared secret, and this side has sent its SSH_MS_NEW_KEYS message. * When the peer's SSH_MSG_NEW_KEYS message is received, the state changes back to `DONE`. In Apache MINA sshd, there are methods in `AbstractSession` for each of the KEX messages: * `requestNewKeyExchange`: switches from `DONE` to `INIT` and calls `sendKexInit` to send the SSH_MSG_KEX_INIT message. * `handleKexInit`: receives the peer's SSH_MSG_KEX_INIT message; switches to `RUN`. * `sendNewKeys`: switches from `RUN` to `KEYS` and sends this side's SSH_MS_NEW_KEYS message. * `handleNewKeys`: receives the peer's SSH_MSG_KEX_INIT message; switches from `KEYS` to `DONE`. ![KEX interactions](./kex_interaction_1.svg) Because both sides may request a new key exchange at any time, it's also possible that they both do so simultaneously, and their initial SSH_MSG_KEX_INIT messages cross: ![KEX interactions](./kex_interaction_2.svg) The protocol is symmetric, so "client" and "server" could also be inverted. ### Message sending KEX can run *at any time* during an SSH connection. Either side can request a new key exchange anytime. While a key exchange is ongoing, some messages must *not* be sent. But after having sent its own SSH_MSG_KEX_INIT message, each side must still handle incoming non-KEX messages until it receives the peer's SSH_MSG_KEX_INIT message. How does Apache MINA sshd avoid sending non-KEX messages while a KEX is ongoing? There may be application threads pumping out data, or one may receive, after having sent one's own SSH_MSG_KEX_INIT message non-KEX messages that might require sending back an answer. The answer lies in the [`KeyExchangeMessageHandler`](../../sshd-core/src/main/java/org/apache/sshd/common/session/helpers/KeyExchangeMessageHandler.java). Each session funnels all SSH packets it sends, before encryption, through this per-session object. The `KeyExchangeMessageHandler` then looks at the current KEX state and at the packet that is to be sent and decides what to do with it: * If the packet is a low-level packet allowed during KEX, it is encrypted and sent directly. * If no KEX is ongoing, the message is encrypted and sent directly. * Otherwise, the packet is queued. Once KEX is done, the queue is flushed, i.e., all the queued packets are encrypted (with the new encryption) and sent. This mechanism has one drawback: if there are data pumping threads sending data through a channel (and there is a large channel window), arbitrarily many packets may be queued, and sending them may itself trigger another key exchange. If the queue is flushed synchronously from `handleNewKeys` (or from `sendNewKeys`), this side will not be able to react to a new key exchange request from the peer. (Or to a disconnection message.) Therefore the queue is flushed *asynchronously*. To avoid that application threads create a huge queue, Apache MINA sshd actually does *not* queue packets written in application threads. Instead, when the `KeyExchangeMessageHandler` detects a SSH_MSG_CHANNEL_DATA or SSH_MSG_CHANNEL_EXTENDED_DATA packet written by an application thread, it *blocks* that thread until KEX is done and the queue is flushed. Only then the thread is resumed and the packet is written. ![KEX flush](./kex_flush.svg) The queue thus should never contain many packets (unless internal Apache MINA sshd threads should be writing lots of channel data). Flushing the queue and enqueuing new packets is a classic producer-consumer problem, but there is a twist: because of the current architecture of the framework, the queue cannot be bounded, and producers should not block. But there is only a single consumer: the flushing thread. The implementation contains a number of measures that should ensure that the flushing thread is not overrun by producers and actually can finish. 1. Application threads trying to enqueue packets may indeed be blocked until the queue is flushed; see above. 2. The flushing thread (the consumer) gets priority over the producers. 3. The flushing thread flushes a number of packets (a chunk) at a time. It starts off with a chunk size of two. If it detects on the next chunk of packets to write that more packets were enqueued than were written in the last chunk, the chunk size is increased. 4. While a chunk is written, new enqueue attempts wait. 5. It should be rare that more than one new packet gets enqueued in between chunks, because of (2). Again, "client" and "server" could also be inverted. For instance, a client uploading files via SFTP might have an application thread pumping data through a channel, which might be blocked during KEX. ### Strict Key Exchange "Strict KEX" is an SSH protocol extension introduced in 2023 to harden the protocol against a particular form of attack. For details, see ["Terrapin attack"](https://www.terrapin-attack.com/) and [CVE-2023-48795](https://nvd.nist.gov/vuln/detail/CVE-2023-48795). The "strict KEX" counter-measures are active if both peers indicate support for it at the start of the initial key exchange. By default, Apache MINA sshd always supports "strict kex" and advertises it, and thus it will always be active if the other party also supports it. If for whatever reason you want to disable using "strict KEX", this can be achieved by setting a custom session factory on the `SshClient` or `SshServer`. This custom session factory would create custom sessions subclassed from `ClientSessionImpl`or `ServerSessionImpl` that do not do anything in method `doStrictKexProposal()` (just return the proposal unchanged). apache-mina-sshd-46fc8d6/docs/technical/kex_flush.svg000066400000000000000000002032631456036076300226550ustar00rootroot00000000000000
ServerSession
ServerSession
requestNewKeyExchange
requestNew...
KEX_INIT
KEX_INIT
handleKexInit
handleKexI...
sendNewKeys
sendNewKeys
handleNewKeys
handleNewK...
DONE
DONE
INIT
INIT
KEYS
KEYS
DONE
DONE
Server
Application Thread
Server...
KEX_INIT
KEX_INIT
NEW_KEYS
NEW_KEYS
NEW_KEYS
NEW_KEYS
KEX messages
KEX messages
KEX messages
KEX messages
writePacket
writePacket
1
1
enqueue
enqueue
2
2
ClientSession
ClientSession
dequeue
dequeue
packet 1
packet 1
packet 2
packet 2
packet 3
packet 3
1
1
2
2
packet
packet
create
create
SSH message
SSH message
RUN
RUN
SSH message
SSH message
SSH message
SSH message
FlushThread
FlushThread
writePacket
writePacket
1
1
enqueue
enqueue
writePacket
writePacket
3
3
2
2
enqueue
enqueue
writePacket
writePacket
3
3
dequeue
dequeue
dequeue
dequeue
signal "Flush done"
signal "Flush done"
Blocked until KEX state DONE and "Flush done"
Blocked until KEX state DONE and "Flush done"
Text is not SVG - cannot display
apache-mina-sshd-46fc8d6/docs/technical/kex_interaction_1.svg000066400000000000000000001150531456036076300242720ustar00rootroot00000000000000
ClientSession
ClientSession
ServerSession
ServerSession
KEX_INIT
KEX_INIT
handleKexInit
handleKexI...
KEX_INIT
KEX_INIT
sendKexInit
sendKexInit
KEX messages
KEX messages
KEX messages
KEX messages
KEX messages
KEX messages
KEX messages
KEX messages
requestNewKeyExchange
requestNew...
sendKexInit
sendKexInit
handleKexInit
handleKexI...
sendNewKeys
sendNewKeys
KEX messages
KEX messages
NEW_KEYS
NEW_KEYS
NEW_KEYS
NEW_KEYS
sendNewKeys
sendNewKeys
handleNewKeys
handleNewK...
handleNewKeys
handleNewK...
DONE
DONE
INIT
INIT
RUN
RUN
KEYS
KEYS
DONE
DONE
DONE
DONE
RUN
RUN
KEYS
KEYS
DONE
DONE
Text is not SVG - cannot display
apache-mina-sshd-46fc8d6/docs/technical/kex_interaction_2.svg000066400000000000000000001221311456036076300242660ustar00rootroot00000000000000
ClientSession
ClientSession
ServerSession
ServerSession
KEX_INIT
KEX_INIT
handleKexInit
handleKexI...
KEX_INIT
KEX_INIT
KEX messages
KEX messages
KEX messages
KEX messages
KEX messages
KEX messages
KEX messages
KEX messages
requestNewKeyExchange
requestNew...
sendKexInit
sendKexInit
handleKexInit
handleKexI...
sendNewKeys
sendNewKeys
KEX messages
KEX messages
NEW_KEYS
NEW_KEYS
NEW_KEYS
NEW_KEYS
sendNewKeys
sendNewKeys
handleNewKeys
handleNewK...
handleNewKeys
handleNewK...
DONE
DONE
INIT
INIT
RUN
RUN
KEYS
KEYS
DONE
DONE
DONE
DONE
RUN
RUN
KEYS
KEYS
DONE
DONE
requestNewKeyExchange
requestNew...
sendKexInit
sendKexInit
INIT
INIT
Text is not SVG - cannot display
apache-mina-sshd-46fc8d6/docs/technical/kex_states.svg000066400000000000000000000510661456036076300230410ustar00rootroot00000000000000
DONE
DONE
requestNewKeyExchange
requestNewKeyExchange
RUN
RUN
exchange KEX messages
exchange KEX messages
INIT
prepare KEX data
send KEX_INIT
stop flushing
start queuing
prepare KEX data...
handleKexInit
handleKexInit
handleKexInit
handleKexInit
RUN
prepare KEX data
send KEX_INIT
stop flushing
start queuing
prepare KEX data...
KEYS
send NEW_KEYS
send NEW_KEYS
handleNewKeys
handleNewKeys
KEX finished?
KEX finished?
no
no
yes
yes
sendKexInit
sendKexInit
UNKNOWN
Text is not SVG - cannot display
apache-mina-sshd-46fc8d6/docs/technical/sftp_filesystem.md000066400000000000000000000160451456036076300237060ustar00rootroot00000000000000# The `SftpFileSystem` Class `SftpFileSystem` is an implementation of `java.nio.file.FileSystem` and lets client code treat an SFTP server like any other file system. It is a *remote* file system, though, and that has some effects that clients have to aware of. Because operations are *remote* operations involving network requests and answers, the performance characteristics are different than most other file systems. # Creating an `SftpFileSystem` An `SftpFileSystem` needs an SSH session to be able to talk to the SFTP server. There are two ways to create an `SftpFileSystem`: 1. If you already have an SSH `ClientSession`, you can create the file system off that session using `SftpClientFactory.instance().createSftpFileSystem()`. The file system remains valid until it is closed, or until the session is closed. When the file system is closed, the session will *not* be closed. When the session closes, so will the file system. 2. You can create an `SftpFileSystem` with a `sftp://` URI using the standard Java factory `java.nio.file.FileSystems.newFileSystem()`. This will automatically create an `SshClient` with default settings, and the file system will open an SSH session itself. This session has heartbeats enabled to keep it open for as long as the file system is open. The file system remains valid until closed, at which point it will close the session it had created. If the session closes while the file system is not closed, the next operation on such a file system will open a new session. # SSH Resource Management Most operations on an `SftpFileSystem`, or on streams returned, produce SFTP requests over the network, and wait for a reply to be received. This works internally by using `SftpClient` to talk to the SFTP server. An `SftpClient` is the client-side implementation of the SFTP protocol over an SSH channel (a `ChannelSession`). The SSH channel and the `SftpClient` are tightly coupled: the channel is opened when the `SftpClient`is initialized, and the channel is closed when the `SftpClient` is closed, and when the channel closes, so is the `SftpClient`. For `SftpFileSystem` it would be rather inefficient to use a new `SftpClient` for each new operation. That would create a new channel every time, and tear it down after the operation. But channels have a setup cost, and the SFTP protocol also has to initialized, both of which involve exchanging messages over the network. This is not efficient if one wants to perform multiple operations, such as transferring multiple files with `java.nio.file.Files.copy()`. ## The Channel Pool The `SftpFileSystem` thus employs a *pool* of `SftpClient`s. This pool is initially empty. The first operation will create an `SftpClient`, initialize it, and then perform its operation. But then it will add the still open `SftpClient` to the pool for use by subsequent operations instead of closing it. The next operation can then simply grab this already initialized `SftpClient` with its open channel and perform its operation. The pool is limited by a maximum size of `SftpModuleProperties.POOL_SIZE` (by default 8). The pool can grow to this size if there are that many threads that perform operations on the `SftpFileSystem` concurrently. `SftpClient`s in the pool need to be closed at some point. Consider an application that has a burst of file transfers and uses 8 threads to perform them. Afterwards, the pool will contain 8 `SftpClient`s: that's 8 open SSH channels, each with an SFTP subsystem at the server's end. If the application then does only little, like transferring a few files sequentially over the next few hours, until the next burst (which may never come), then we don't want to keep all 8 channels open and consuming resources not only in the client but also on the server side. (This assumes that the whole SSH session remains open for that long, which can be accomplished by using heartbeats on the session.) The `SftpFileSystem` handles this by expiring inactive clients from the pool. If a client has been in the pool for `SftpModuleProperties.POOL_LIFE_TIME` (default is 10 seconds), it is removed from the pool and closed. (If it was in the pool for that time, this means it was idle for that time: no operation was performed on it.) If no operation on the `SftpFileSystem` occurs at all for this time, it's possible that the pool is emptied, and the next operation has to create and initialize a new `SftpClient`and channel. If an application doesn't want this, it can define `SftpModuleProperties.POOL_CORE_SIZE`, which must be smaller than `POOL_SIZE`. By default, it is zero. If greater than zero, that many `SftpClient`s are kept in the pool (and that many channels are kept open) even if they are idle. It should be noted that the SFTP server may also decide to close channels whenever it wants. This will close the channel and the `SftpClient`on the client side. If it happens while a client-side operation is ongoing, the operation will fail with an exception; it it happens on an idle `SftpClient` in the pool, the `SftpClient` is simply removed from the pool. If the whole SSH session is closed, the `SftpFileSystem` is closed. When a `SftpFileSystem` is closed, all `SftpClient`s in the pool are closed, and no new clients will be added to the pool. ## Choosing the Pool Size If there are more then `POOL_SIZE` threads using the same `SftpFileSystem`, it is possible that all `POOL_SIZE` clients are already in use when a thread tries to do a file system operation. In this case, a new `SftpClient` is created, which will be closed after the operation. This is a sign of the `POOL_SIZE` being too small for the application, or that the application is badly designed. Using too many threads for remote file operations is not a good idea in SFTP: all traffic in the end goes over a single network connection anyway. Using a limited number of threads may bring some speedup compared to strictly sequential operations because the handling of the data received is offloaded to these threads, while the next message can already be sent or received. But copying 1000 files using 1000 threads and SSH channels is nonsense; it's far better to handle that many files in batches with a smaller number of threads (maybe 8). In any case, `SftpModuleProperties.POOL_SIZE` should be large enough to accommodate the number of threads the client application is going to use for operations on the `SftpFileSystem`. If there are more threads, performance may degrade. Versions of Apache MINA sshd <= 2.10.0 tried to mitigate this performance drop for such "extra" threads by keeping the `SftpClient` in a `ThreadLocal`, so that such "extra" threads could re-use the `SftpClient`. This mechanism has been *removed* because it sometimes caused memory leaks. The mechanism was also flawed because there were use cases where it just could not work correctly. Design your application such that is uses a small maximum number of threads that perform operations on a `SftpFileSystem`instance. Set `SftpModuleProperties.POOL_SIZE` such that it is >= the maximum number of threads that operate concurrently on the file system. The default pool size is 8. apache-mina-sshd-46fc8d6/docs/technical/src/000077500000000000000000000000001456036076300207255ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/docs/technical/src/forwarding.drawio000066400000000000000000000301631456036076300243010ustar00rootroot000000000000007V1dc+O2kv01rpr7YBXBD5B8tJ1JpnYnN9koqdw8TdESZauikbyUHNv765eUCIrsBkUQAkBQdl5i0zbHBrpPd5/+uvLuvr/+lCVPjz9v5unqynXmr1feD1eu65IoyP9XPHk7PIk97/DgIVvOD4/I8cF0+X9p+dApnz4v5+m28Y27zWa1Wz41H84263U62zWeJVm2eWl+22Kzav6rT8lDih5MZ8kKP/1zOd89Hp5GgXN8/iVdPjyyf5k45Ve+J+ybywfbx2S+eak98j5feXfZZrM7fPT99S5dFYfHzuXwcz+2fLX6xbJ0vRP5gW+R/1/L6PaHu/XL9vqX8Ifp798erl326/6TrJ7LP7n8dXdv7AyyzfN6nhavca6825fH5S6dPiWz4qsv+a3nzx5331f5ZyT/cLFZ78prJH7x+XK1utusNtn+Xd48SaPFLH++3WWbv1P2lfVmnf/ELf6byj/znzTbpa+1R+Xf+FO6+Z7usrf8W8qvBrT8i0qBI15cPng53p8blc8ea3fns0tNSpl5qF5+PNb8g/Jke5wyiWOzp7xYLNyZzlOuDpCdcnV4XadcXYfyU479Cz9kn4pKsqvtjInZM9YHF+xMveHRoc+Rku4jVSB5flPwInxGJOScEdEmd659Z+RR2w7Js++QaGTbIQWcQ6KrXQlFjdOi//u8YV+43u5B6ib/BuI/ve5Ph309/+ih/P/+Rffswd1qWRxd+Tj/de/ht+bPDv8sewzuKz/mXfNSuEBYR83yUbJaPqzzT2f5b5Dmz2+LS1vmju1N+YXvy/m8+Ge4UtDEcAWCEANThuWA8pwFXVJADUrBNM3yc/qQguLaiV1iEBoUg0WSJS/J24cc5F8JPbvkIEJycIMOv8NYJtunA/+wWL4WRyXp2eZfobMovV8oclJAmOZyvF3OQeuLH9BBc5yUc09axbkFlh0cA87ayU2nX9DRbR+Tp+LD/I9PVqt0tXnIku/5kTyl2TL/RQrVb37t1+MXOkO14rjZOes5dgLsQ8Wm1Y6dF5yF2o5dIDgb+Zn7bmDZmeNgD5tCxWjcwuUUOE3vaUAVRUOhbagiEDKm6/lNQaQX3sMq2W6Xs+ZRN50DeM75YWVv/ym/df/JX+V37j/54bXx2Rv77HW5+0/t479qHx9/pPiE/cQ82T5WcW3rVW03z9ksFYDZXZI9pLtujyGdN9IH+OZrNxtwbpY9y9JVslv+kzZ+W951l//Cr5vl3j9lOgz9Kaichz+8/Kmj0OAXQcoRit7hYNCL9tJX/dlnCCTmcFfL7S5dY7HMT/5rcp+ugOILO7pZmnvxyf3+fYUEPRV/0/6vDG6vgh+EwPa0UkFcqLJU5b96VU8E8fDCmTgO+9G3xotk5YV9y2ax2KZ6bpBHsIhAyjYXrd05SFNiBqljxiQMTsJGBU9OA54mQQdAySNMJAgwDIlsQRhHFcIEAyMMj/oxKZ8NmzaRE89Qn3wyj7dbQN0PAdUioDxSqiXkWKzS11Ikbw2Cqn1CK+q2xf1ltoqHGvkJR43UeiAiCBxZqQUv8uGLdEstptBsk1rrXIFYFGmJZVJLQDaH+IGc1MIcKnqRZqll0N7BqtnBu+vgfvxu7scoEe9ivu3Px2SX7hNol8W7wRzI4LwbQ2zznrFq5O1EVFcCUTX6rhTiqSeJp7DcwjieYj6R1UA4PGA9q1RMgQ4C88PLQxIeIUu16SDmv1j5gJUH6EXWnWB7gc98+Q9LrR+NSpV5r32V8wObdfEHbLaFJNeKAaqc/jH7z32fZdcWOtZdWz9apnSvGqy/hL05mpi/rmopihZ707BzXSWond6/K+r+M1C1xFhVcsFK+mBhrHDICl7kQ69St7ESIFouS+R8KipyvlUi53vxpBmoRLCLQFjo0Ks837DYCTAlQ4tdq4h1S05gleSEwMOLpfk1wAp7xLDU6O4gUuBVwOodT7C8QZtTwQzKhaqaBJlt0C+QVjX4Is8wle1hDmpvhr9uZsnqx032kmTz5frh082Vm/8DDosBvJvbfyHpuljmkHgteFjXdY8jbdqoQ093+18DF4pPfk12+dWs909cR1VbETjXcGgMla3nGKJErCvH03o/6qI1zy7X2QOtfFWBV+9UDezgMRyteZggOFSGfbrBsGtvcVilTkqKw3ylxWHli6+BG1fldvUXj3kCIbltXi63g5hXxKutgdjrF1EqSqiTk0jbktORdYY78ZnBbjc+h3bhMyTBZMuWYCWJ6bIlDweoJaAtN+ub2Sx92qXzkWE106uzsframbgem3xzpsQEYROd4T3rQ2fmSojU+MzeVsscUDKvG6PvD9Dz9b56kMz+ftgD0i/Pu/w1afl8W15hoAfYkevNGbfBi2i04bqPA1EDuC5Z3ncC2UlFiNQqMEz540xobcF76I9L4z30xw3jve9yhLNn77TT0ju93W2ylM+viDVK22tT/DZYkrIpAXPNK2OgxsR4zbcS8AaNJkZ/QxrjDSZFcYyIO3vtTzz2nRDAjtzFpMleTLp4X8V4yGBldP7vxeAhj35UhIdZmswvFA4V9sp5vtekQxSBISih0wh+WqnWOmlaolXl8RFCNUTzPMBE/dU//ujk/50X+4eiviC1C/tUde0i7IPZAN3YxyOgUAmdstE60+mXbz9Pf/p29+Xm3//+/PXbL79+/ncrFArW96mc+1M+mS+zHL+ud7On5VP9++oQXk0JyjpnAQkVFhpGer7engY3JY6vQwELoob6BgYkNob8AtWPQ/PeaMYAbxopj/fWNr3CH0EBX+vBj81Y+cBRl6+kAi8yXd7hC1RSqQox43qE6Uwcv4Na4zhM8m6RZQLkwbwZdFJEBQjW9CG3SbMAsfPAmY5PnAogi2MvpghKLLIfqAm3WJZEv9EN9NPr/MqWzsY2sWFGlug1UseoqrA+e/QCfpVu3XbbdHu5WU+fZ7N0ux2RigfK2GZnQgIW5p3dPd64ZGPccoDpld/QXQ7tZROgTQGn/s/nKLO2ssrg3TVmhaIjmgK7eh0I6MWMoUwIF2DDRDhsttENwjiu+9M6RQVRDB1cT0fQVqRWTyPRbrbArpQXbEmSVlPA+lLDLUkBDqTts6dwwszg9pTi6PHC9ZSdeLee2tXQBGcbSCsqzPOYtqeUM1THOkWFk2cHN6gUh4KXrqiiNdTULgYicBQpKvWGtagUVz/NsjTZpacEz3jZZ1NEu4oADgl/tjvTPUtAhRP9wpFZxW74xG2W0rE5scO0AQSq2gACwTIokyOiKS6Vek9iPhqhhHQshaVQokIJAZoKZmyMCiVmB7UK5bUzcZrZwdjxDYmm2jyjOCqLxuFHBXBgmYdRBSCA5AmopALAUD2AXbidCgDqXAzoA+Z9P/Shp/T6PhTf0Ch+A3c2YFx+b6ciatZFIe/EBvzuMTbddHNattklRQIx/zw+KVs9mtWAwxhypscSXrca0RcwYz5wX7g+T3YJpy7iLNRo6jCp4UjRaQmKm4MOHDnV19EseNY4DJyKWlGme6I4lANrHEfNjh7OYCatdc7NiWshDKvFcQgIveAMCpM4xK7H5lJOGCSGvOE9HHmAk/KUQUfYrxRnZJWcwho7EK8tW8kJX0QNV3KGbi+pUWpm+nAK8kbBNskBJZzSLBWsGRMFcmWSg4nWlyxH4U+3hya7FpfF2jqvShMU1Hnl1gE0FavprSCE+1YDFln3YDgFFtkHBEHIGcht1iL360Ucm0W2a0gbSmDJWmT4otC0Rcak0T4EPA2rik10q1iIMzeOj7TPYAV1KNsZEZCOF9kQH/Vr2lLLDcglgnzqNlkASrp4AMXTHcQz83aVuilzGFEZl+HpDsw8I4dxdJ4iUz8VTT8kYvmYc+UE3KZG+BEokx3aGSSQngmGdgb7tUyOzRm0a5c7KuOXnqM+MD0TYczUb+lbOu7cToNdpQ9Ka38cKU3j3ukDeUsvngawS2ovxtKzVKdgFstaQ19pnwpKyGEB0ZlSwrZ8sXImY2Y/ctGt6scibtThauOK7QIEuI89hHosCggw0W14tlHURhXfjJMqrjTBYqrYb2arjTHFEWaK66P3RkJfsUtg3SblhZtRe6itslofdLynk8lihwFqoBjuGxCmEcx0gqc8dB1AdNETnSK7BvKoWo0H2WvTYab27RdDVwFYJjfIs4NwIBzqwRcZrgKIMK01TlI3UraoQp9PV2G78fx/jI3K3WOSH8sKXfHFruuDlj7ilAtTDmToG1ehf9B7CxUY+VQmeVfrU2jyg5F7EvZNDUEW3u1s2wB42GQm27wLzZJoj42ycRg4eOQNKv42/ePu7vN0OiLzEigc0u7GcdMOaGEMDBoXAe+zajt5zlZvt1ky+7tQ0K5w74hu++BvtXz6csUPBOvmaA8md/l/V1raTuBoqDASixjdMGi/0rMMSSyQm7ygC/Bhic/gF0AY7tZu4Pdi5vndapn/ne/O1YL7IWPOfkijrhZxeN0VaAL+/s6maZb/pdWdCc2cv9ibhGsVLLhJtxvsmrDVgXHnnFKVxOMcS1XC0mg91DYJPv8dLDqYlpkedhxUr2J4MwdFfRsPilcA39wRckCb42oPwt0Gctjv0TjhvjtF1mmS1cD4vnNXiJUIrUBSQKwYx4MDMi/Jo26TDJOdw4ODQ/UhCFe4g9UCSeClrgbCi4MX9yEohRBAH254QcGMAT7/DqObbJ/SWfGbLpavxWl1RaSLxcKdzXjM45ze04AqinwotOOiwam2w2axWH305WOyS/fq0cIS5GeQrFbpavOQJd8LHq3G3ja+VqN1O3P3xT2xC9IUrcDD51SNR5zDh4WaCg9foKt/7IceBdadOo4Rb3TjyzxJowUXX+gsSu8Xag47cuzDl37bEY5prMbkVkOzDVuvoDO5VBktS5JGPgytXThSWXblDHEMD2cmpMfgqsUqfS2F5laPWLXMPQrF+yeigDZlkvonpVJt/0RldPpIakVhN7gFR42sBtAwk0hyiiAcTzyArOJky3T6BYmrHdGDlqUfAubebDjhYg/30pwsGMNZ4GS5Aq6tXQDdeg+dBSOVR2mJ8YfjEnIYlAVURDzDN+kGVCY27xVQQ5Qj4ai20bUPxMWpJI5ynxtAqYBF5A4MHg65Atklc74sN0QKJWMka/xJiiIWVsfcewobiqdN+5OubPh8tr3sbAhvNJXwRUlbK2fl1I3PNkdtmHRm2yd+kXbZxHH5arndpWssodZWbh4VTEHppuOwH1Vbutl45zUxtv+5Wq5hjROv0Ye3jMAjnaZHFCeuYUnqAEiBWRGWqnd43vzQXZ8eDHsIx3EkPM8R9t6r8xzZJdYDoTKLbeUZUhiE2nCGQnWex/wnv7oT/cBmXfwFm20hzsdag7Im6Vh5IFIqOvStQafChkvDDMApI2RXy7Ml1gQ6nZHsAE34ItTprtuUeP3a4i5g6STx7NqiDtvISCTb3ozeZF6aBOiYS5Om2CppQvymtDShN5mXJoGR4EMbeNiyQSrL3cGJwphBoYHvx3FdghKyhtHusPQD/PWpq9ZB2/WaDzIBC7cIqwDpGq3doD86ZFRRI70tkkagfEjvUnEi+CYycWr/uYbljseqoaBSWZcE67H/6esvtzdfv/32+X/++Dz9vbXOXTDmVdnEUT7ZFf2V14tN9pJk8/o3OjdV1X/WWacvFGYbJqT5+taBSirmj7sO5Q+VOXuYbeOtIL2mkZH2MJNonYsVIuQa3MVipvU9uVjCzP9HRKTN1Pk9GhxM75xVoOlwpjfxOH25vB2zgT5Nd3tp+hlVI82pzcK7YqJAeBe1P/Gq71VYAM1Cqm5k8C13iT3ZUVAUdIcS3/BMSuLzeNyeLqXT4lJud5usGj+9T8N4N7f/Eu3stLhYoVJuJb5hQMAcQ1eJlF4zd7ByOUHJqEb30O/H556DfgzISgQkrfh3zWCsxxZth/oncLF1BN8ZoOgLu0uMu7IEFCl0cnxoXIWnrbqgd8E37i51j9SQBsX6nPaLwkSm8goKuDwfBLaKEJHC4XtArnQiou4h640gsfjk12SXC8N6/ySXR0UxNUw88zxts3UJvvY9jfI0sMHGVxY9C3jTdk3pjmCBkie9R4zAejGPGm6T8TGnfKjF/XQzpjndR6VSUo7rN9FcDfdJml5C/jubA/N+awbVzYTugJxW+BDwJu0KsbGdkS27xfBCgyGzTuyAarJTatRys76ZzdKnXTofG1owfVASD3ustuxcmqYZ/8JmMo34EAjQrdZlRzzOwCluU54+0jRwu89t6PTIBWEsSnDIVqOiN3mmI3aRLQ1Daxwq+aqGw3RpnL4+WM4ugIvSOLs4Mly1Jatx6E3mNU6gyFJN1Vaxv71O8eafumJZrl7Os6n9Jz0y4raJL3IZlJWCecOWggXt03F1loLV161YWAhWloCl8+t9Sdi7LQWroM7mUjCY7jNXCxZoJ2ARDB9A4urkMmtY6xt11Pqqne5mGXS7kBlFPqVs55lveM01CTDFWmrhp9tRsSaBSo41pu55gmICKLTTpr2A4hiOOM1SqIlHoi5nkZf2b4RFrdgxOrcPabwsFevCAJhA/1E3djCs4pKv0+fZLN1uRwUhKolXEtKmV34morBbB768RoChFpe5alixFkASoBoTWJ8SwKt7Jfqm0jE7VLuD39AlDE3FoXmKAetAHmyaH31/DfVUuACYCZUlFhHNVIlikHwWLgBGlEoA3qTdJGIGeJalyS49JX1nFGxeM3erisxih329s2hduGQdu3yMMhSO8TplrXK+fd+HIX2I0ERnIgcKUSAb3FFmQREudoij0TiCjqC/Hw2/pCG2MLxkD+TxFVqYEfT3t568gI2wq0Mf2wjZXA96U0BN2wjM8Nnn0/nYpwuQxhn26frNbbwEn45F9AL6Glqlrz726SSHteM0WWC4CpViok2rT9enxFmdN3eOrRCVvaOPVw1hrQw6AheTqVd5Fw86Jj7c8mKDi8dgxGYXD21kCgk2OGZdvFCAABva4JyhtkwqrDUZ0uU82MUzbDJCF0nO3WOyXqcrJEAXu+MDLcAKOXyq2aVJIWZnVNvwltbXSKrzVaJganR1s8gWU9mGpWuXzdw7vqqYUWZW8zGbwqtP+jb94+7u83SKxc/e9FilPQoy7G4cN0k+RWU7Pmxjar5Bp4+F+aA/0e0O7WShHVrUHzqqD/vVO11EVC/cXBra1VyK+shiRzKqj1EEJhg3qdNXTuHTO4rqRxOrh9CNpLLjgZD0VuBnVaw+hlmAcNDS8LE6u1ubzUjryQsYAsum+SlbvYCVMjRsCCLM8tjnuHmwJ5AOXmITYY7DOo1T7LhFvqi+RnYF2Wj1k3SJjQ+hPwjBm7TrKy7t+iixUSyVR+fPgbU4Rp0/j+04rWBPNlGD5dYXk9vjm8xzCgxvbPYFPeSfD16aE/Vrph2bL8ikwlrbIusLojdR06U5ESbx6hMG58ku4TRFKWiy4bbSkInjRQ0DMvGoJ5NIOEPahCMPRsE2ax6vme4Z6q6BfnIoyxZc48y+WHtN50pj15z9MNRLyu0YleO7fOo2JZ6SrvW4/STeEtQMaTyBKRBpWQ2C3Ed10csmDjUMn5hTfclyh+RTC3Dam+uKVO4ryf1uqkRooMukEzoMdZfyDV8TAtxOBKi61Ev4qHAnV7PTyKO0h8EMdASFZjdn73K1XTo0QjikGzdYJyt0u8YHG8o6SIvRFo6vRF7cZlWEycn1cb8KOo0OiCs5KtgSncfVkbK+AuTbzSu72+Ik3J4MsuxV+riNM5FRei8E6ysUFcYQ0IpmDgIwXbvH9tO3rcuzAGV5UlV5rVihkLqpBILZgGGGU1Dp4RSIyoFvsiHXzpIgQ5gnJYPsLbFOHmrPlJWboFMCtZsnTB6PNIatpNtmuxTxx7eZUP4WrteQRapC1mLtaGO0WtCRXeyxcakrcJYHliO7EcdRMxjlzOHV2RnsxJMYFqjFxwj57I4uOy3XgMzuJVkutDJQ2nJFqI/BuOVqY19PZ68sNmAKR/ppM2DuUAbMdQRmHFXzuZ6z1dttlsz+LgKUrjKBIzLsiwZWy6cv7GNwlfW2tH1/0l3+35WW+VyoUYjXT8Yd+A4rCpVVGriOQABxQVdA4chBG64A++u/F/OVp2mW/2HvrusSrUWIOItIjHZduo7QOPD9pd2tlvmfXl2a0Kjri71K5JtYcJUCbudZBWkAzBaLhTubtV2pgjOGjJfr8/b2RJxDrtaNaDhlgUE3Kk95nqTRQucpe/CQKeeQeV4+2nqr8JB79dmQ7kNW4eLA9jrOOVVjGxoTSPUJI/O6bDonD7axWnFQArlO0wdFUcOmDQfltvoDKtZtHPZosAcHj6LmStx3Ltiw0r9QIAzQM4w5RJ1Zd4LwIlhdknAICD4k4YoTSlsgCrxIWpcoLJIseUnePmThitNfbYEs4JD+Bl1Ah/FMtk/prPhNF8vX4rgkfeD8K3QWpfcLPY6w44r1TWs0xjg45/gt5x62iqML4Nk5nCDC7NkJRMOM/cv/9mS1Slebhyz5np/IUy2D1/haLbXXGdYVp82OWc+pE2QpInzqvPAY7iJReOoC0fHIT913A+tOHYfL2CgqxuQW9qdAa3pPA6qHZrMAWNibDcyp67XUU9FKpsrAW5IEhiB3NMu9S+khnejBYXaak8BH+T+Kzmq53aVrLEDWJn6P8q8g8es47EeVTpoDc+ZA64XGrC+Dgt7Y0JiFoWiQFfu4s63PcWgDaCax29Uh3a/2tnN4RwU6AvBk2Sx1B4IKZMVF4YnAN1XIZwye+u1lUi+9cm2pTdkNpcvqBKQ0EpZSu0ZCqZNS2OsygBHtUdaxWKWvpVzeGsNdKyU3FJZciamWFXQ1khSOGtn1YAjgwV5/2V7KY5hmTHYFhp8MLLuhnPDqlF0qLLuRZbJLYlXBC8yq4jdpl11MRk6nX5D42sG9a1m6JMD7mOXiXcxx/vmY7NJ9Ku2yWDecCRmcdXP7rbxSCNyqMbgbWV27oi5Y6+o6sG9euKMEkkLmcRWTt6wuwuEB7NAz5aAhIpyUJOFRsnDymDpNZNhQN01lQYGVR+hBobPhDHkVUqgQ+Ghe+OW/6Ac26+Iv2GwLaa4VB1Q5/mM1gEg58dAXFyKOxoKLc3uZoQsY9eux5hoBu2UXD1OJBpOfSDqWhW/yoYTptlveu9vi7gbC/hKzSJbIne/Fk2b04sYwQyosefhdHnSytctev9kQIxsiW9liS6QHLiZyY9n5Rpg9hlPztEvORW8GryyjJZKD7J205KA3+aazY36vFoJh/FNULMFt5uGVy+jr5fH7+afnpA+P5HWf/HeDRNFGY3uOaPLQY+XWligxxGzkaQpz2DD/gjrItOswZz3FoWbl980nFpR6N7djmsRwVDAV43Bzt95TIzVg9AJ0NzVW4fhax+PWZ9oWG0wb44EI1QA6vKFCEttnu+MbX9hDtWxPLdxzkb9XFqMgs+wbnhRTHclpIk5Z/w1vAW5rn40g6aeyOah8Ml9mOZBd74pBBPXvc2qoXbUSZZ0NQ0Jso2HM5ytvB8QpwXyH8ufknKuVzdrO2JgBCEbgqvuo75433IDnqusrbQ/6ueojC45tM1q+ryo4Rm8KTdMqgWzpqESQFzcXvjl+R8VSny0C4hywJULkoYhfdkYeYvmQD6VdiDCrWxqzT+OKyCptUGKdfQbLZzvJ5gxwvyVv6nqkOmtgxLqkLFFurJKkyr2cTb1z3qVdwTH5XurDcrOePs9m6XY7Kj1nYq6gFYoEfqREaFjrwRv353UqPa5G/A3d5tBuN4EqRTkNpUZ3NbtBvzrCS0iks6oHAZ/drsJDAiu3YlkynKD4D8Z12tEY06T27VZHkY03tLqyC39P6ircPcRkyhJ1RYULssERauSgpkteKOa07LOuqEtleOtKR8BpKVbXUJgRo3bFO6guWtq6ooSQcetKMSNmoXWFB26BeR1BaZ9qfRUefkDtKu8KYDm8tH2lUF/N21dMWc2yNNmlp6TPeMd4U067Cgeaa2Lc86S0R3GAaMxWkR8+ceGWIARDOu0OLC6k0uUDsMQpECxxMrmgyKUcHu4dybpCnLVFghG7SyNJnhhheiiYBjIrwZhr1CrB187EaaYdY8c3JMeKE5g9cFw0mD8mq4hDgRrEJtWAQLooiCXVAAf8gvXmZtUAU8cfatATuH0fFj+FRpEblS5GYF6dsO8RNeutsBdjhcgKFOdWW7neVstcKjOvOzi+P8jv1/vqQTL7+2Ev1b887/LXpOXzbSnWAUfMNWzlcqFrGfKWPHgc+SL6YmzmpH5sV5WyoEyEuy1o2BOOht/Y6nmgtzOEgbg4HEHJt3BXa3VDNpeKoqCyupOOUlFYBagQQdzuYxuapWs9eYV6OxQvLlspit5ETY8NCLVXimpejiyef7FFemCJKJWVHlSPJgrp6qQHZwcOa5Rvx7lG+agOCkrIdK1RJoT7VhPWWaCOdGjr7EOmIBJcUaDROl/0kINKKizBV5wFk8VXzL0at86YV91HhqfhVbG5bhUNcVaH7f4eqE47kh2uE0Bbjd5kRdAkO/lSBWsgl0vyqdvkByjpYghSxTsOeqT57aqiU+dAovqwwPQE7hDTjwcHcnyeI1NCFU1GJGL5ynNlBdynRhRiomOzc0ggdRORoZ3DSIDxGrFzyKTCEuzEDQPSE7AGp24idwCz39Ln53Za7yrLUJr+44aD3LwabBgWzxZYJrqXZPYjzDqeynjZa/UrHVTBFzksTDpTUthqCFbzYdAH6FctrDEScbXRyZbBAtolFcrOML5GzpHpIv0I84uHaOBmpHRypQ8W08nXQZNPNtiiHGFidG8GTl+3bfRWHq951Zg+gLlmMABprjQGwLpV9CIb+K5IYJf40JEmOsjBawSiEfS1tx68gLduV2e6shndKMdrPMzUOr7TigoBy2QHuXSRdP8Lcg5NVwiwf2/8BG+lBzb7chF/cqQBoxxjHvPuMcnPZYUu+WJ3EiKrH3Gqi83uJIxddC2K0buNEoz8ao15n4xerbehyRNG7kn4NzaVWXzrjC8aSBgiEFFTmmw7PzJQot046tAGE4i8ycnfpn/c3X2eTsdkZyqNVWFn4rhpENSYGb8Z7Jq0MgIEY9Wu8pyt3m6zZPZ3oaZdMeAR5PYR4Wr59OWKHx3W7dIeU+7y/660tKsQn05c0AEQucdnXbOJfRfOFFRoWXosz76Aq/BRKZBg6rgqNNFwBZg/+72YyH5YWPru3C/iYm2Jh/fAeGwVmtG/v7fDltTq3oSm4l/sbaLVDxZcJabQ3tXOdTgkkbv1m+fBarwSzE5Nf7n7b+zxXe6lwJZWR7BFUdulVKyTbsqwZvodp4zs1JCJNQLb8UFgG0ZSgW3rVXeHnES4VJXYxWQSGHI6ML8hGnK6DoQew0ym5/AK9Xou1iEti3Xatp61rMt5L9AGcx8Om0bXtd4b0hEKoa0fn9aRRSue/5rs8rNf75/kIsKFsPaTBh38jWkgJxFOHo4qTbAEZGAhpgNnfAmn2ih4kQdGf2iHGIFm3KET22inqSvYXwfJRoU6iZmI/UjIH97Wyffl7MdN9pJk8+X64dMNzjhdLHiiieaEs9GqqmI25BhiwoLvrUtL+cmKHvHDu4aTq1zOJFau6dEo5h9D1vjX2mO6lAPzo0bHAmLsJJLDpdikaCSewnVaxrn7auOyNuvW8LL4rpUKaIDFdh4n3jaMDNpLdFqSvF1xMLc0O9RVx+OR8s/u3unNZHFoF7aSIUdyMCLyfj3Dk5qrtpSa8K2W21265nlb9uZdj0qkIO/qOH4ToBWV9wCq75pExtCb8OgP6cB3DIPg+8AJtQNOKrKsiQmx7NA4FEO4xtFFgG8ZPCSGECwYEWvbHOyRflO9LkJZfVFlZSJ1acoKX+SaZsjZFYxKVzkZTJ6uetoaMzzSbzur/coqoIK+3Soo26yBpgsbXvztkX6jxs6JBJsDfjvkR15WrKuiBVfsS2+chEW0+ZsmTu0/s9uAPcKhF1vSkuMJ6ip9UDGVx626PM+Vobhx89fQEdQZxmmdFYbTJ6dLMxpGjMcWsefqqSK7LNA19EtCWROEe4ENd/F7hMdG9iyU8FsKJbZsK7lYZYRhZOIzzB2KqIJuCs4TwjcghAZwiAnlO8ch27wb5MBKzxiCLzLcIeS5PL6yJwo5F49ClRpagEJVD2vTOVIBSvmn2aa4wuO3Z8nT48+beXEpn/8fapache-mina-sshd-46fc8d6/docs/technical/src/kex.drawio000066400000000000000000000223511456036076300227260ustar00rootroot000000000000007V1dd9s20v41vrQPAfBLl2nivNtN1s1p2tP2velRLMbWVhFdiU7i/voFJYISMSA5pPBBkcpNLEqCJM7MMzMPBjNX7PWX7/+3mT89/iddJKsr6i2+X7E3V5QSxgL+X37lZX9lFrH9hYfNclG86HDh4/KfpLjoFVefl4tkW3lhlqarbPlUvXifrtfJfVa5Nt9s0m/Vl31OV9VPfZo/JODCx/v5Cl79bbnIHvdX48A7XP9Xsnx4FJ9MvOKZL3Px4uLC9nG+SL8dXWK3V+z1Jk2z/V9fvr9OVvnNE/dl/763Nc+WX2yTrDPMG/6f/nj/6/Jr8u3fnz5s5yvv47t/Xl0Xq3ydr56LH3xFwxVf74dP/I+H/I83P93diot89fJ68auyF3GrNunzepHkn0b4098el1ny8Wl+nz/7jSsHv/aYfVkVT88394WwfY8//Jyus9fpKt3slmLe7l9+fblaHV3/zP/d59e32Sb9K6k8U7yj+EHJJku+194pUt5/rrhJ+iXJNi/8JcUbqJBuobNx8fDbQQGIkOrjkfD94tq80LmHcuWDWPgfhWQ6SIkCKW2Sv5+TbXaXfHuXvNx+v3+cr7keyxJJFlyXi4fpJntMH9L1fHV7uHoskfyWLbniv1otH9b82qc0y9Iv/IlkvXiVW1K+yFOy3l8phBc3yuKgEd7uXfxe/J4/uAnEwz+On3vzvfLopXi0/1n5b6nIc5s+b+6Tdt0GcucIMt88JFnTW5sVxLuJwv1Km2Q1z/i7q7ijkH+x1od0yb9LuRAjVU2jnqRC+29avOvYuMVC4oXp58/bJAOaVn73/soXtEPEz7/eTRshmHOICBVSGjQa9LXqAC0rzbbpz3C2qcvuaAREmpRA7727/T0PMpLtlkcgW6Ws388/8WCsalOFNO/5vUs2CjF/WS4WO1XYJNvlP/NPu/VycT3lP3P3w4MfroI3TWZUhGLFmw8B0LHI6nUYyvGlsnpfqZoHSgKDqR/vfvwFyGb7bfllNV8nBagJk+wmn/vH5Wrxfv6SPud3dJvN7/8Sj354TDfLf/jKcyF2/vQmK2yUeZVXfMzfWch4J/PkgxDT4dL7+TYrlrrP37Vc51/uTRMs36er1fxpuzxoUBX8D+jOmtG6Ft+Lu/i25vnFJn36Rfh5TbDv+zXu+hj2QwXsy9ChDfYJDA2FJ14svwpH/LRJ8h9ZwsZins1LJ745uOvShR+9V7HcliP+fq0/9wqOfV+WPuU52Op5+7hcP5zyDXKF5kvxIPi500qSKXJVyKoIWVXEdbo30yMdKy7hLXXLIxz+Hd8nn3Nl8A9Xfi70w6+JhVK+5OfVztM+8sV2vnaTZvPsCJbrzA+l7J1CXxHpIDU+NKbx7NwinTLvIZWs55AE6c57Tkh8AiOhlC+HUsg0h9/++cvRy4ogpPZzAqr+nIO+7VfU6/Z9oJA8SOO2/y75/uN6mY0jNtubXa1nvPZu/KprPC1aE8vSyqLXLKquYDCYU6W9w4aZ78vsiF3hj/4QmMP/PmBM/kBAjGZKRoE4WJamnZKJjUCTnOWRuCsDIzAukmJDeaH9neiAcdoTSpifjBGoalxYSd35Pg0sQNVeX61AVQzkuiPkLmnnSNLOMugeTto5U3jHTmnnJcmcdJJZ48yHkmQKb3NG0Z/tzbW4NuRzlGTKkRyTtaNzkqk9AINk3bvbPz5ePPVoPXWg2he0i2SQLis8693tb38q1e/ir2os92R/xYxJGXJQZ+OvrqyQouKG9KoGseKvQmqGFAWfE0p1YtLrSXDa64kN0pXCeoc9l7GviBrJhvjerBu4DBKRKu164ia5SDBp9R3muAsKuYt9rvh5uV5uH3O4eAtkuXlMv3x63tZ4iCPpuqkNCqv2UNaNHHsHT+EdAmPeAWbr6/Q0/yDsZrVz4CN0F/rTm8NOSRyeaqeCc5agNyBmXAil8ucEjS5Bfn3jPpzNEh0G8/qXmuopXaaQ01Hnm+afYgd1QbMwBD02IIc3QYSzAW0qpSqhl/VptVo+bSW92T7On/Ln97k3z2DkpOo4dTHqsUKprEnhsJjNbIZBnuQ0E3VV4tFilH12bPsaMqvTCkz+U2PIJ1puJHmJ3luvYVDd0COyZnbeesV9jrAAo5kOUxM4o9qzZS2eghsICWanuQsLwQUkYX69e3f3029wL7ag2IBUZLoXyZ8xyJ+xOtpOJsuq8v2Bi+x1jkdc0vQ1f0wOj3fCf+Jg+zpd86Xny51Mk/k2+5ZsM02uiFRNLIKuKFa4IkEHaHdFPrS+16sl/zEfk+12ma6BZKt+oSU/1XDDiJRthgrGWXXHjB1E8aEVfEw2/DcO5Y7JRYLu7xim1OwQqBR2vJjv6ZHdbTm6Q7h8oYxTakKTXVAqfWJN6NGn6EuYdWvo4deUHR7JKmigUk6MUMpCCxFYEHmfpiaygCtJG0MxsgJWl2/yMefDxqVj/gyrYzUsqx0dC0JdOsakCsTIcibsQ5rRPdjLR7l9CPZWz2mK7zMhQ4yxeeZegc7fEOWVImQlijZDhCdHm3TsfjXnkdk9TrP68RuzY4KDP5zRRpIjf/Ah2Sz5jSjrSHRGH/5ZKKTMbMbyBjHaMcxaFjKtj8pNvj+Vh2PPkr/YG1wTf5G3A6iiixYVEXmv4L6r7zfYE6LrUQIbNUWqaELVc+C0gCKuEhSxovbHaulPQLWDfQnbXsyOiekbz4s743Y/alwj2gvSthXto5r+A3bQ3peChhmSxIaYELQsZBjtA0iZjQvt9xbXhPYe8eLTlMIChPtKaTTvqVWB4vCa92m+y72T3X+TLHspttDmz1lalazGLS+znEBN5IeW52mYjmAEj24qVPqnIxA+SOkImvVsG0uuUEGk2s2tIcnVtFXWcYP40yrNC+EbciG1GyWnKnp7wVFdTyS0RWjf2w0iSTfko2jOT8MGMCk5MW6qkDT5gw/zjBvbeneFeqQDlA2F8J4hxdZOpniWCe8AkpFjbJkV1BykG23mKfTqYraN1iYXgqKTB3nHy7PMFYWQWRij3e4F5sBur6VV7Rmudp5iBIYLza1v1g8hQA6zTRuuMu0fn+G2Jv9jc7iYo4VTs1tobfLhnf4O1/JmYQi5hlHabfNRujE6XESCa71aUdqJPOyxu+KMQkTRiu16DCz6IaihsCY/dBTeADn2hckYedJNlzGJUqohG1PkurYpwhyFGlltE0MaYlST8LnKM3oXskorRZb5gQimkbhZKKOpQIglAbguQIgQCYL7zSoq1W1ErjerIhh3j2Gzqk+QEtXE5qeCnlQ/Fw2uI2uEqMp3HVXMnEcVsJp1IrVmRFLgmXOohylljll1PXdGKwjiKbyHXUl0S1unwcrBKFc+AdOfTUeeTdflGcTHjZyVi2qqT0bLpseIFNn1GSniKRqAWHX5MUzymtBtDETCDBssx8Pa+OjN6MkrxbYRFjFHyHXsPQBL7Lb7NwZLFPsm7ZY4sLPpfYMdQOnZtsRu/Q86nGDBsxn9Djhq1Do0kTwbFv4TXfgPj9uaVjtIvtS2xD7L4DpubURpass7rkbX5UQ6C/G1/qPP4sRKdyxxdeINfeDe8e6w3P+tP5ZEbb7QNJZAYmxkWOLqhHNcXbQc/2kBSiDFNgmyMwBJiGuyU3whdLP30cgCEM9ls31nsjgHAst5VdlsgAQWPsA4txxEGwdFQOdYw3HDDJJQE0E24GXcIxukut78dHfbgG6kHd0OU6z8/MbVTSZyMqhC6vodKaZKKnutGhPA2Y1cRuyZ1qF1z3SwfR/BPwHWaxqgnNrnW9Iz+UyxaYyFPI+yF8lo7Vqxh2DXriEno5pPPNb7P1M4Nrv3X9V+TUFMjFUApMyinEkAUgmTCi0IcY1B5cCtS3BxzGm76cIkPHJ7QFLDOp4YkMjtMJGtSdrWiZBnt3UFNsTDnLeZik7j9bNd7Wq2RfSq3Qy53wkpcWkd5L6/PrXDkFtTUTvXUIotVpmZ6fMFWBzkcTA4RRaUsyBJPX1qPTX+J5QTc9cEEPEuDJCRgoBSt9tHvXlmQq5IPotlmQQqftd0SAjZuGPFlphl454aDSGLwD0PQbypERFQBs6ZCHLJ2myFzwh3F6NdqCHHSDVlhbKHtZ4WivKvi167TwtLvUZYgJnEEAz37Z0ZRsx1ZkjObQgooa5nWnIhgXs27DGgQ7hn0xsESliEBSoyrONWYKhb31GgHM4s58JkesNASYTdcyqQazDFjb31TB4HSpjlQxGEIA7jOK8V9l33tyGk2ySKUZijj4f9mrzr3MwRrMQsn3ckRHvPmH6nZoc6FrTMK4aulPJgUOLrmgwKVzKtlOLzRjstrjC7Wodk8BiuVIV1HVVXMHd0jlDIcU6kZ5s8H5T4rpu2EQHzBnC/0wlngfu7AYlRFfmjwCnyi3Zq7cjvU5fIH4LcsS/yy1NCSWD56BOhY58TWhheE/KfPihU1ITFVai313GBUF8prnEPEi1z2/6xop1RooRq74gxxk6RgczB9U7rAsuTCQhV1VWMr1VkocgO4mhXvSIJvTR5xRhc7xAIgIDtEIgpk98Rmq6zFNjV8CXCMFU+U7NdaHHaOjeUvL4124VZ9ShtlzXzHSN0uwzRGXZypgsNTtcEIRLY3pdksDZlnKZbUzExZreLKKFx3tW5LEp2tuXMBlgBgkVADOfCalqfuqoV0jYdltnen2MDrOEABsWc13CwKdZwoDdNmNPtcmBEobbQxb45Qkpo2uMPeZDjen9VoMp5DUDkkOUaNH3IkUx1BGKhRCfsEtUgllwqxAY3BLHYUh94iOG+TNSv6xU6+poa0AXZfU2NDymESTQHB6IIFOdpLYtC+/iYEdB1kGRD4j6C+LPdusGHZMUo6Trf1bwWZ0y7P0ByARwQCRVtcSx7/gmSCwG6vsof2AGRvlwfPCBiHWgR9SbOA3H35igEPCVzFPsqCHOsqfVwxfX1jXvAStS2OQbaS0jOcC5iB5Y5GJYjCLU5gtD2BnkAGZlxjTMrbMvF1ri72Ygk0F7YcobDETscPXa8iyw3KOkPKHInAOAUjQMKpMvGBiiuam3cDUgkAWTeJkGCgtlV7knQAHJkExkkBhjpUNHp1LIwzoLWcl6EFgyQ1sIHGmeXj+gjpkJZJ4yHD5CYmgi6AVfjHt3Ep02mh7A8zIg575MfYpihqbRaxUN2e24odLsd3EOq1hm9sxLt7wGEkPqZ1LTEwx13Z92Qphn1qAJZAr7zUQWh6oDQmEcVyCIIqXMRQG5hWlGG+2k8IeaQ0FSiDNf9ZoRfRkQmNUyk5klf2K7FrQsx22MTQ0xHnKnoNV5HEZpX0zlZt+Yht0PbBicSH1kboE/zMIzXVDTPOaKiZ6KFNfuAmvU6RLafaZ+diN0p1KfYk58r5Z4UEt/oAi5X5uvhYrRTjGoUSfNARftMUQRJyFHTFMDk3fMUESTrxs1TABm4JyoiyNZNzPW5ZyoiyNdN1/W5jqsjvGukZlyjXDgHWlX1nakIW1WZDqyjy0TsAWk2moOLzHBwQLN7p4xgqKL1lDFCsMvOi6TcNxaKurXvHsVhI3xv9b0SDabEytfWztR6Y6EIUpMTaywUErlBjvMuExGk1cD9d99ZKPQH11lIfIGxdxbSHmGAoyIsmt0w6UhB75ZBcJ4NUB3Fx5mGvhgSWeMueYLktfOaJ3GKxWqeU/ihweU5OmMpsTPTHkvFlohqX1s2DoIk0zlLDLm+YQ019+UqohjJzRl0xRhubmQJTIxOYGKnQ819qSLioBudExjZNme2E5h4gJ2/fcnRUlVKYTkyHmDn79PMEWFkAdJwWd2gGkfm2LtRsbwSmdluIREP8AykbI7cGJyb4wDPQBr2jsxH9xKKnZ6gBOZI+npHYI6x7ROU8eT7hrNQohriABq/XXpvBomH2gm4PSmq7jlr544uGqGh1uALGXo3PH2sSFHP9FzQZG6GHAfag/LyZVDpXEdfdvqovs9go48Zgp1x7cwpUZQC2XXms8l26GYzWRjEObhOtEM3EAV1L4pzSM2p2P5rg4/A2G0aXWqOcPjoXGDmtBkbyAWYPOa7f2pumymbwZxzIt1UmDQDhzJFzGAZG6d2cgaUusSuS7jLTr+XIkvN6C6UuxXd86+sVJpTyxlAYifDtmGwLX7YhIoLoH0rqoEs2zfMy8Z9TEaWwSHpdScDmI5Ny89RpuAbLcvgcphgMIcJSseA8I3UiG8M+27Zt68UWz5MQL1Lqxpr2+mlO0XouC3NRZ59hitJnROohyT+9WnupRnNgDCZoW3ATKsbWbN77A6Jlai8kuViSeqpDi+Eq5xJWiy/8j8f8j/39ZPiCf5JR88pXv7q6WnFtTvbFVt6vzxukvlCvOzTRn6jvJxjzhkc31NVZxKre1bl5sB4SGeE8Tqt8opkKjno25gb6pPluR6UQHbDbAVD/ZGbJoXSONAVtVVhJuwBlQPILYgeRQqBHBZZVywKFKt2YIzL0hjvJhKhivnqmLotMM3VL4cu1OarX8BHGVcsyAWaVSxjiGWnaro2mLnmTl2uqSuHD2lGOmauHAsqf+dc0nwBVln1NqQKimhw1dRlCQd+Urgt34E1TP1BAyhitgfuoF7aOLh3nhQ/fPmXpa9e2RejRNvACNoSGQE1agg4cNaZ37CBtt0OZWDmZPaaeum0FrvwOa6y5FD2y1hmVjFSpa242zgsQSbs24a75w/z+78SWBV8lgMwC6NpwC/GmJ7oUEZBSZoGgUHcDQWlme89V8QY/v2ciieutzua/RV/wezp++E5wUySI8Jyv9BAGEsmF3PMFJvYqhhPFoq+GI8iNrHvnzdfS4fsCqkPmxhqrG6JGqheOGcBNvEr5OkK+OHcwr6n7kIwUgUZj9YHNnUBlGwlxSfXfTO5Rl9+A/9j/x00w5dql7wbfEUq+ErWfz8nfMWmfZhGWDtPj0ebCRIesXvi2OVL5SP7WkipLdYcHlPxDhocHj0Xh0c9P8dxty5PMSj39WrJf5GWtjMVP3TKLRxMzxmqGFEKMcfypib/vLfL/HfALc6Uf09xrXiN5i0pGjjd8qRSt1kaIIsR4ErysS3QctN0MoeZvWobtahc7KE616LELJnq0WiDtuL0G49Wi4xuvICetr1Svv2oU2Z9nG+LkWGC3mw397BGX+yYOwP7N0jOGSYD8kY0dupc1xCeAQtqCeEBEDFGJKMxEcIrZjIukiL6HkVQXTdry1hQXf3iJalkrbkCVbT4fyqIQVEj7rLYQcBryWp4YTMHnT+QcVMjCtZi20FDmJizV0hTzzYJkWszDe5KAwCVS8SGsE2i6JtbKi709bYV9xpqLmGhMc1t0kffq5ZJ6NFHEPT5zLsRs03Nq6Tvk5sQ16nZrlbCAh/oGnvmfqqSG8c164w6HYEAi1l7b9OB5oeWt+mY4nhciWcM6NCE8cyMf+XJ6I3UnsEPrSJatKvmHBqiMUVVy8h3HeWsjyEry4xRsIyojmlNighXHV+2KwOKKILsRiJhaaDO5bs2J35YcvTySclA7omDdvQycwJWMu3oFSUET+pSnDMqD4yCKoWhxymHIL5DMvca/HH3sY0WnLFyD90xVqssqoybWuA6gPN2NCJ2t+F1CMTOfWRxZnl2Jc4s/1b8xApen0+lZdkfcejbeLC1ZN/+9BS000MSXPrsGO6p32+SeeaER5e0uhYSetPqhSXWIghPLgkVoyFO1JLyEJDg561R6cX4hmGBM2g06iv6sVo9JlMOIRlSeQQeT1tRcnBTPPpSYrDpqOXTkmJPszLw6uO/rsoDNUBthn1k0oaSHRA1CqWQ/NrMeR3s7nqPkBx4fL9zjygLsM96NU7uF2Oelq1ZOjsDkra+uTpcyXL/TMZ6zb8er2w18jBgJeuy7TX86CLbPnZrm2NjiFAcH2NCd86UEm5UiKGLvx1s+4rfeo/5sgLwIv4TrL+v+OGJV+vipzrF3xHmB5CCFkc2nKWg2jJQWSdBF0Hj/dOhJv386x1QpvG2jVaNtbLaNpr5mIqqy2z2Hn0IqVoVTo0jgNGGXata6lay3R6X+XDP/0JAHY9RbSSgorAiPj38Phgxb49+6tGi3AL95J/BeLPDnXO26+BPb7wZ8+NTrdnVqGN5zF3/8Wa2y3h9yBhOwWW4dwQzeQ9fY2mQvIkKApFBOAIEn+naERzuXFthkDlHoJUaPAtHgC/xKZRojI7AcolPUSxV0bO3q+fto5ga4Ngy69suu+qbUfaIGhSAgWEvillmKgAzR4gEkJNqArCz7A/ZDlSBU7YcJjisPD7UGapAJBODtUxHrYGKZNPQm6vSaHLE3bgKo6yFEY39J4W1W4gog8uRF1yi7RaMiBzrxFF/MALAFtgHIxWjNeoTh6DtW+C87RsLEITZpdOp4r5hSbeivaEr1ICTkiOvL2qAXqeKtQx1O6UeEx+FLiMFb7ky0i6JBacf2710PJURqSHGOvuOp0zRa9O5d5JT4CPzcZgEd2PxxpoEu2XrALnbt2BUToGtT3xjyp6tlwS4Azg3H0g5zwQY0231kgA7ByKQAM/6dvyEkGb7ZHBITwYiZfLLzib55c4A2z7AXPYbnk6InlnHHdDrNhiCGBAM5IWEUNw3bK/mAm+GQkLku5DYnmutLIRyMVM0xFH7S/xxVvAeQ0SEshv6hYjoG+uGNcTdiIgIRadv5y4KEBE+vtGQOSYi1N5l6ByZiNBpH1jY5YRrBunpRgAZ4cdwMeNpgIoIvPARHTC6ueXQmfIR2lnPkfIRbuFI5iPyHin94QhgW2AfjiJDTYCHy0qAdDj2b0RQ5Cwdji7tSDp2Gujfs8D2wZHo0o6kKpHZ7Cams8M/XZJuWde63HudRxix3Fst0fjo9a5kkDwtvvwgs6yOYgIO0JzLjDvnCt3IrHduXXsYCFsuR8lNIDFDpubSIVhOOCOTfz8rLGdMgT2MajpdYfAWecfqFy/WtDidjmHGKV0gboAQd5Qt6YC4ILgRpXHGIS4svzoe4vj3q77HFMTB/dCRQRybHMR1a0xx6pSC46FeeG5OMaXd7DhNS/sGALfk063n06o2Pr3YnFAVR7fluDDPP//w1O4gM7+yyJPR4zcMZUPB/EiDuLkYPR9p4DOqx7tSe2AESagf8oYj3Pap97zOlvkS725/3wl0N67Ce/PT3W3+5dYLlIpIusAFklXVoNplraA7jpvhFZfw6qJiixt2QSTd2aT8hy7TfMXrmdekTB3a7MloQVVTGcQQpWPgkyusEdwyf7hJ87t/0BR+Dx7/ky5yC7z9Hw==apache-mina-sshd-46fc8d6/docs/technical/tcpip-forwarding.md000066400000000000000000000170071456036076300237440ustar00rootroot00000000000000## TCP/IP Port Forwarding **TCP/IP port forwarding** (also known as **tunneling**) is a functionality of SSH to proxy a TCP/IP connection through an encrypted SSH channel. SSH provides three different TCP/IP forwarding modes: * *Local port forwarding* to forward connections coming to a port on the client host through SSH to an SSH server, and there to some port on a host reachable from the SSH server. * *Remote port forwarding* to make an SSH server forward connections coming to a port on the server back to the client, and there to some port on a host reachable from the client. * *Dynamic port forwarding* is a variation of local port forwarding: the SSH client starts a SOCKS proxy listening on the local port, and initiates a local port forwarding whenever that SOCKS proxy gets a request to connect to some port on some remote host reachable from the SSH server. TCP/IP port forwarding is specified in [RFC 4254](https://tools.ietf.org/html/rfc4254#section-7). ### Local Port Forwarding Local port forwarding can be set up with OpenSSH with the `-L` command-line option on the client: ``` ssh -L A:faraway:B server ``` This results in the client SSH process listening on port A for incoming connections. When a connection arrives, the client SSH process opens an SSH channel to the server, and tells the server to connect to port B on host "faraway". If the SSH server can make that connection to "faraway", it confirms the channel creation. ![Local Port Forwarding Overview](./forward_local_overview.svg) The SSH client then starts reading data from port A and sends it encrypted through the channel. Any data arriving on the channel from the SSH server is decrypted and written to port A. The server decrypts any data arriving on its end of the SSH channel and writes it to port B on host "faraway", and starts reading data from that port and sends it encrypted through the channel to the SSH client. Note that "faraway" is resolved on the SSH server. If "faraway" is "localhost", this means that port B is on the SSH server itself. The following interaction diagram illustrates the process of setting up a local port forward in a little more detail: ![Local Port Forwarding Interactions](./forward_local_interaction.svg) In Apache MINA sshd, the part of this interaction running on the SSH client (listening on the local port, and requesting the channel to be opened; highlighted with a blue background) is implemented in [`TcpipClientChannel`](../../sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java) and in [`DefaultForwarder`](../../sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultForwarder.java). The part running on the server (connecting to port B on host "faraway", confirming the channel creation; highlighted with a yellow background) is implemented in [`TcpipServerChannel`](../../sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java). (The diagram shows the message forwarding from/to the ports through the channel via two threads on each side; an "R" thread reading from the channel and writing to the port, and a "W" thread reading from the port and writing to the channel. The actual implementation is a little different and uses asynchronous I/O for both.) ### Remote Port Forwarding Remote port forwarding can be set up with OpenSSH with the `-R` command-line option on the client: ``` ssh -R A:near:B server ``` This makes the *SSH server* listen on a local port on the server for incoming connections. When a connection arrives, the server SSH process opens an SSH channel to the *client*. The client connects to port B on host "near", and if that connection is successful, it confirms the channel creation. ![Remote Port Forwarding Overview](./forward_remote_overview.svg) Note that "near" is resolved on the client. If "near" is "localhost", port B will be on the SSH client host. Remote port forwarding is basically the inverse of local port forwarding. Basically the only difference is that the client first has to send a message to the SSH server telling it to play the "client" role in this forwarding: ![Remote Port Forwarding Interactions](./forward_remote_interaction.svg) Note how similar this diagram is to the interactions shown for local port forwarding above. Much of it is just a mirror image, and this symmetry also shows in the code: the SSH server part of Apache MINA sshd uses a `TcpipClientChannel` for the server-side part, while the client code uses a `TcpipServerChannel`. Some details specified in RFC 4254 have been omitted from this diagram. For instance, the client will accept the "forwarded-tcpip A" request only if it had previously indeed requested a remote forwarding for that port (the initial "tcpip-forward A" global request). A client can also cancel a previously made "tcpip-forward" request. ### Dynamic Port Forwarding Dynamic port forwarding can be set up with OpenSSH with the `-D` command-line option on the client: ``` ssh -D A server ``` This makes the SSH client start a SOCKS proxy listening on port A. Whenever this SOCKS proxy gets a request to connect to a port B on a host "faraway" (reachable from the SSH server), it sets up a local port forward. ![Dynamic Port Forwarding Overview](./forward_dynamic_overview.svg) The interactions for setting up the forwarding are the same as in local port forwarding, but at the beginning the SOCKS protocol runs to establish where to connect to. ![Dynamic Port Forwarding Interactions](./forward_dynamic_interaction.svg) ### Buffering The tunnel has on each end two handlers: * A "read" handler (marked "R" in the interaction diagrams) that reads from the SSH connection between the SSH client and the SSH server, and that writes any data read to a port. * A "write" handler (marked "W" in the interaction diagrams) that reads from a port and writes to the SSH connection between the SSH client and the SSH server. There is *no* buffering in either handler. Each reads a fixed-size buffer, and then writes out that buffer. Only once that single buffer has been written the handler initiates the next read. This keeps memory usage constant in the handlers; there is only a single read buffer that needs to get read and written. It also automatically throttles the throughput to the slowest part of the connection. If data is being produced at port A faster than it can be written to the channel, data doesn't pile up in some buffer chain inside the SSH client or server's "write" handler. Instead we "push back" on the producer by not reading faster than we can write. At some point, the lower-level transport buffers will be full, and the producer will wait with sending more data until SSH has forwarded the previously produced data. The size of the read buffers can influence the performance of the forwarding. SSH transfers data in packets, which have a certain maximum size (which in turn is limited by the network packet size of the underlying TCP/IP transport). Best results can be expected if these buffer sizes match, or if the read buffers for the ports are a multiple of the SSH packet payload size. If the read buffer is larger than the SSH packet payload size, writing it to the SSH channel will break it up into several SSH packets, and the next read on the port will occur only when all packets have been written. Note that the SSH channel is subject to the normal channel windowing mechanism defined in RFC 4254. If the sending window (the "remote window") is exhausted, the sender needs to wait until the receiver increases the window size again. (I.e., until it has received an SSH_MSG_CHANNEL_WINDOW_ADJUST message from the receiving side.) apache-mina-sshd-46fc8d6/java-checkstyle-license-header.txt000066400000000000000000000014421456036076300237410ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ apache-mina-sshd-46fc8d6/pom.xml000066400000000000000000002223241456036076300165760ustar00rootroot00000000000000 4.0.0 org.apache apache 30 org.apache.sshd sshd 2.12.1 Apache Mina SSHD pom 2008 Apache 2.0 License https://www.apache.org/licenses/LICENSE-2.0 repo Users mailing list users-subscribe@mina.apache.org users-unsubscribe@mina.apache.org users@mina.apache.org https://mail-archives.apache.org/mod_mbox/mina-users/ MINA Development mailing list dev-subscribe@mina.apache.org dev-unsubscribe@mina.apache.org dev@mina.apache.org https://mail-archives.apache.org/mod_mbox/mina-dev/ https://www.nabble.com/Apache-MINA-f16868.html MINA Commit mailing list commits-subscribe@mina.apache.org commits-unsubscribe@mina.apache.org https://mail-archives.apache.org/mod_mbox/mina-commits/ JIRA https://issues.apache.org/jira/browse/SSHD scm:git:https://gitbox.apache.org/repos/asf/mina-sshd.git scm:git:https://gitbox.apache.org/repos/asf/mina-sshd.git https://github.com/apache/mina-sshd/tree/${project.scm.tag} sshd-2.12.1 ${project.basedir} UTF-8 2024-02-06T06:50:58Z 1 8 8 1.0 ${java.major.version}.${java.minor.version} ${javac.source} ${javac.source} 1.10.12 ${javac.source} 3.2.0 ${javac.source} [${javac.target},) ${javac.target} ${javac.target} ${javac.target} 3.5.0 4.0.17 1.77 1.7.32 3 1.2.13 5.3.28 5.13.3.202401111512-r 4.13.2 1.12.6 1.16.2 1.27.2 5.8.0 3.6.1 4.8.0 6.47.0 1.0 2 true release [1.8,1.9) ci 4.0 4 quick true true findbugs org.codehaus.mojo findbugs-maven-plugin true false true ${workspace.root.dir}${file.separator}sshd-findbugs.xml run-findbugs compile check owasp org.owasp dependency-check-maven 7.1.1 false ${workspace.root.dir}${file.separator}sshd-owasp-suppressions.xml true true false false false run-owasp-dependency-check check javac-errorprone org.apache.maven.plugins maven-compiler-plugin javac-with-errorprone true true org.codehaus.plexus plexus-compiler-javac-errorprone 2.8.1 com.google.errorprone error_prone_core 2.0.15 javac-jdk9+ [9,) org.apache.maven.plugins maven-compiler-plugin ${java.sdk.version} only-eclipse m2e.version org.eclipse.m2e lifecycle-mapping 1.0.0 org.apache.maven.plugins maven-dependency-plugin [1.0,) copy copy-dependencies org.codehaus.gmavenplus gmavenplus-plugin [1.0,) compile execute testCompile org.apache.rat apache-rat-plugin [0.1,) check org.apache.maven.plugins maven-checkstyle-plugin [1.0,) check org.apache.maven.plugins maven-pmd-plugin [3.9.0,) check org.apache.felix maven-bundle-plugin [1.0,) manifest org.apache.maven.plugins maven-antrun-plugin [1.8,) run org.apache.groovy groovy ${groovy.version} org.apache.groovy groovy-ant ${groovy.version} org.apache.ant ant-junit org.apache.mina mina-core 2.0.23 tomcat tomcat-apr 5.5.23 net.i2p.crypto eddsa 0.3.0 org.bouncycastle bcpg-jdk18on ${bouncycastle.version} org.bouncycastle bcpkix-jdk18on ${bouncycastle.version} org.bouncycastle bcprov-jdk18on ${bouncycastle.version} org.bouncycastle bcutil-jdk18on ${bouncycastle.version} org.slf4j slf4j-api ${slf4j.version} org.slf4j jcl-over-slf4j ${slf4j.version} org.slf4j jul-to-slf4j ${slf4j.version} org.slf4j slf4j-jdk14 ${slf4j.version} org.slf4j slf4j-simple ${slf4j.version} ch.qos.logback logback-core ${logback.version} ch.qos.logback logback-classic ${logback.version} com.jcraft jsch 0.1.55 com.jcraft jzlib 1.1.3 commons-io commons-io 2.11.0 commons-lang commons-lang 2.6 commons-collections commons-collections 3.2.2 org.springframework spring-core ${spring.version} org.springframework spring-jcl org.springframework spring-framework-bom ${spring.version} pom import junit junit ${junit.version} org.mockito mockito-core 4.2.0 com.google.code.findbugs jsr305 3.0.2 net.bytebuddy byte-buddy ${bytebuddy.version} net.bytebuddy byte-buddy-agent ${bytebuddy.version} net.sf.jpam jpam 1.1 commons-httpclient commons-httpclient 3.1 commons-logging commons-logging org.apache.httpcomponents httpclient 4.5.14 commons-logging commons-logging org.apache.httpcomponents httpcore 4.4.16 ch.ethz.ganymed ganymed-ssh2 262 org.eclipse.jgit org.eclipse.jgit ${jgit.version} org.eclipse.jgit org.eclipse.jgit.ssh.apache ${jgit.version} org.apache.sshd sshd-core org.apache.sshd sshd-sftp org.eclipse.jgit org.eclipse.jgit.pgm ${jgit.version} org.slf4j slf4j-log4j12 log4j log4j org.apache.servicemix.bundles org.apache.servicemix.bundles.not-yet-commons-ssl 0.3.11_1 org.slf4j slf4j-api org.slf4j jcl-over-slf4j org.slf4j jul-to-slf4j test ch.qos.logback logback-core test ch.qos.logback logback-classic test junit junit test org.mockito mockito-core test org.apache.rat apache-rat-plugin true .asf.yaml *.md .github/** docs/** sshd-sources/** src/test/resources/** **/stty-output-*.txt **/target/** **/.cache/** *checkstyle* *findbugs* *suppressions* **/big-msg.txt **/BCrypt.java LICENSE* NOTICE* security.txt *pmd* *.ser *.iml .metadata/** .recommenders/** RemoteSystemsTempFiles/** **/licenses/*.txt .project .classpath .springBeans .pydevproject *.pyc .settings/** .repository/** .gitignore .gitattributes .git/** .attach_pid* org.codehaus.mojo animal-sniffer-maven-plugin 1.20 org.codehaus.mojo.signature java${java.major.version}${java.minor.version} ${sniffer.signatures.version} org.codehaus.mojo.signature java${java.major.version}${java.minor.version} ${sniffer.signatures.version} pom org.apache.maven.plugins maven-scm-plugin org.apache.maven.scm maven-scm-provider-gitexe ${version.maven-scm-plugin} org.apache.maven.scm maven-scm-provider-svnexe ${version.maven-scm-plugin} org.apache.maven.plugins maven-release-plugin true org.apache.maven.plugins maven-source-plugin org.apache.maven maven-archiver ${maven.archiver.version} org.codehaus.plexus plexus-archiver ${plexus.archiver.version} org.apache.maven.plugins maven-resources-plugin ISO-8859-1 org.apache.maven.plugins maven-javadoc-plugin -Xdoclint:-missing ${project.build.sourceEncoding} true http://docs.oracle.com/javase/${java.sdk.version}/docs/api org.apache.maven maven-archiver ${maven.archiver.version} org.codehaus.plexus plexus-archiver ${plexus.archiver.version} org.codehaus.gmavenplus gmavenplus-plugin 3.0.2 org.apache.ant ant ${ant.version} org.apache.ant ant-launcher ${ant.version} org.apache.ant ant-junit4 ${ant.version} org.apache.ant ant-antlr ${ant.version} junit junit ${junit.version} org.apache.groovy groovy ${groovy.version} org.apache.groovy groovy-ant ${groovy.version} org.apache.ant ant-junit org.apache.maven.plugins maven-checkstyle-plugin 3.3.0 true true **/*.properties org.codehaus.mojo findbugs-maven-plugin 3.0.5 Max Low true ${project.build.directory}/findbugs com.google.code.findbugs findbugs 3.0.1 org.apache.ant ant ${ant.version} org.apache.ant ant-junit4 ${ant.version} org.apache.ant ant-antlr ${ant.version} org.apache.ant ant-launcher ${ant.version} org.codehaus.groovy groovy ${groovy.version} org.codehaus.groovy groovy-xml ${groovy.version} org.codehaus.groovy groovy-groovydoc ${groovy.version} org.codehaus.groovy groovy-templates ${groovy.version} org.codehaus.groovy groovy-ant ${groovy.version} org.apache.ant ant-junit org.apache.maven.plugins maven-pmd-plugin 3.17.0 ${javac.target} true false true false target/generated-sources/java **/BCrypt.java net.sourceforge.pmd pmd-core ${pmd.version} net.sourceforge.pmd pmd-java ${pmd.version} net.sourceforge.pmd pmd-javascript ${pmd.version} net.sourceforge.pmd pmd-jsp ${pmd.version} org.apache.maven.plugins maven-dependency-plugin org.codehaus.plexus plexus-archiver ${plexus.archiver.version} org.apache.maven.plugins maven-antrun-plugin org.apache.ant ant ${ant.version} net.revelc.code.formatter formatter-maven-plugin 2.16.0 true true true ${workspace.root.dir}${file.separator}sshd-eclipse-formatter-config.xml LF net.revelc.code impsort-maven-plugin 1.6.2 org.codehaus.plexus plexus-utils 3.0.24 LF java.,javax.,org.w3c.,org.xml.,junit. true true java.,javax.,org.w3c.,org.xml.,junit. org.codehaus.mojo build-helper-maven-plugin ${build-helper-maven-plugin.version} org.codehaus.gmavenplus gmavenplus-plugin detect-workspace-root-dir validate execute net.revelc.code.formatter formatter-maven-plugin format process-sources format net.revelc.code impsort-maven-plugin sort-imports process-sources sort org.apache.maven.plugins maven-checkstyle-plugin ${workspace.root.dir}${file.separator}sshd-checkstyle.xml ${workspace.root.dir}${file.separator}java-checkstyle-license-header.txt samedir=${workspace.root.dir} true verify-style process-sources check org.apache.maven.plugins maven-pmd-plugin ${workspace.root.dir}${file.separator}sshd-pmd-ruleset.xml true pmd-checker process-test-classes check org.codehaus.mojo animal-sniffer-maven-plugin check-java-api compile check org.apache.maven.plugins maven-enforcer-plugin enforce-maven-version enforce ${min.required.maven.version} ${required.java.version} true No Snapshot Dependencies Allowed org.apache.maven.plugins maven-clean-plugin auto-clean-key-files initialize clean true ${projects.basedir} *.ser *.pem org.apache.maven.plugins maven-compiler-plugin ${javac.source} ${javac.target} -g -Xlint:-serial -Xlint:unchecked org.apache.maven.plugins maven-dependency-plugin download-sources install sources org.apache.sshd ${settings.localRepository}/org/apache/sshd/dependency-maven-plugin-markers ${dependency.download.silent} download-javadoc install resolve org.apache.sshd ${settings.localRepository}/org/apache/sshd/dependency-maven-plugin-markers javadoc ${dependency.download.silent} org.apache.maven.plugins maven-remote-resources-plugin process org.apache:apache-jar-resource-bundle:1.4 ${workspace.root.dir}${file.separator}assembly${file.separator}src${file.separator}main${file.separator}legal${file.separator}notices.xml Apache MINA SSHD true true ${project.build.outputTimestamp} org.apache.rat apache-rat-plugin check-apache-license-header validate check org.apache.maven.plugins maven-assembly-plugin source-release-assembly none org.apache.felix maven-bundle-plugin 5.1.8 true true bundle-manifest process-classes manifest true $(maven-symbolicname) >", org.slf4j*;version="$", ${bnd.extraImports} * ]]> *;-noimport:=true pom org.apache.maven.plugins maven-jar-plugin true ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.apache.maven maven-archiver ${maven.archiver.version} org.codehaus.plexus plexus-archiver ${plexus.archiver.version} org.apache.maven.plugins maven-surefire-plugin **/*Test.java alphabetical 1 true false 1 true System.out ${sshd.tests.timeout.factor} ${workspace.root.folder}${file.separator}sshd-common${file.separator}src${file.separator}test${file.separator}resources${file.separator}logback-test.xml false ${sshd.tests.rerun.count} junit junit ${junit.version} org.apache.maven.surefire surefire-junit47 ${version.maven-surefire} org.codehaus.mojo build-helper-maven-plugin remove-previous-artifact clean remove-project-artifact false dummy Dummy to avoid accidental deploys org.apache.maven.plugins maven-jxr-plugin 3.1.1 sshd-common sshd-putty sshd-openpgp sshd-core sshd-mina sshd-netty sshd-scp sshd-sftp sshd-ldap sshd-git sshd-contrib sshd-spring-sftp sshd-cli sshd-osgi assembly apache-mina-sshd-46fc8d6/security.txt000066400000000000000000000016171456036076300176710ustar00rootroot00000000000000# RFC 9116 format specifications for security contacts for Apache MINA sshd # The ASF policy page on dealing with security vulnerabilities Policy: https://www.apache.org/security/ # A more detailed description of the whole process Policy: https://www.apache.org/security/committers.html # Where to report sensitive issues Contact: security@apache.org # The canonical locations of this file Canonical: https://gitbox.apache.org/repos/asf?p=mina-sshd.git;a=blob_plain;f=security.txt;hb=HEAD Canonical: https://github.com/apache/mina-sshd/blob/master/security.txt Canonical: https://raw.githubusercontent.com/apache/mina-sshd/master/security.txt # OpenPGP keys Encryption: https://www.apache.org/security/KEYS.txt # Please use English Preferred-Languages: en # No expiration. All data is maintained and updated at the apache.org web site. RFC 9116 mandates this field, though. Expires: 2999-12-31T23:59:59Z apache-mina-sshd-46fc8d6/sshd-checkstyle-suppressions.xml000066400000000000000000000010361456036076300236460ustar00rootroot00000000000000 apache-mina-sshd-46fc8d6/sshd-checkstyle.xml000066400000000000000000000356041456036076300211030ustar00rootroot00000000000000 apache-mina-sshd-46fc8d6/sshd-cli/000077500000000000000000000000001456036076300167625ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/sshd-cli/pom.xml000066400000000000000000000107641456036076300203070ustar00rootroot00000000000000 4.0.0 org.apache.sshd sshd 2.12.1 sshd-cli Apache Mina SSHD :: CLI jar 2018 ${project.basedir}/.. org.apache.sshd sshd-core ${project.version} org.apache.sshd sshd-scp ${project.version} org.apache.sshd sshd-sftp ${project.version} org.apache.sshd sshd-putty ${project.version} net.i2p.crypto eddsa true org.apache.sshd sshd-core ${project.version} test-jar test org.apache.sshd sshd-common ${project.version} test-jar test org.apache.sshd sshd-mina ${project.version} test org.apache.sshd sshd-netty ${project.version} test com.jcraft jsch test com.jcraft jzlib test src/main/filtered-resources true org.apache.maven.plugins maven-surefire-plugin true org.apache.maven.plugins maven-javadoc-plugin apache-mina-sshd-46fc8d6/sshd-cli/src/000077500000000000000000000000001456036076300175515ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/sshd-cli/src/main/000077500000000000000000000000001456036076300204755ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/sshd-cli/src/main/java/000077500000000000000000000000001456036076300214165ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/sshd-cli/src/main/java/org/000077500000000000000000000000001456036076300222055ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/sshd-cli/src/main/java/org/apache/000077500000000000000000000000001456036076300234265ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/sshd-cli/src/main/java/org/apache/sshd/000077500000000000000000000000001456036076300243675ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/sshd-cli/src/main/java/org/apache/sshd/cli/000077500000000000000000000000001456036076300251365ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/sshd-cli/src/main/java/org/apache/sshd/cli/CliLogger.java000066400000000000000000000167201456036076300276560ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.sshd.cli; import java.io.PrintStream; import java.io.PrintWriter; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Objects; import java.util.logging.Level; import org.apache.sshd.common.PropertyResolver; import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.config.ConfigFileReaderSupport; import org.apache.sshd.common.config.LogLevelValue; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.io.output.NullPrintStream; import org.apache.sshd.common.util.logging.SimplifiedLog; import org.apache.sshd.common.util.logging.SimplifiedLoggerSkeleton; import org.slf4j.Logger; /** * @author Apache MINA SSHD Project */ public class CliLogger extends SimplifiedLoggerSkeleton { public static final DateFormat LOG_TIME_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS"); private static final long serialVersionUID = -3785762030194772776L; private static final NullPrintStream NULL_PRINT_STREAM = new NullPrintStream(); protected final Level threshold; protected final PrintStream logStream; protected CliLogger(String name, Level threshold, PrintStream logStream) { super(name); this.threshold = threshold; this.logStream = logStream; } @Override public boolean isEnabledLevel(Level level) { return SimplifiedLog.isLoggable(level, threshold); } @Override public void log(Level level, Object msg, Throwable err) { if (isEnabledLevel(level)) { log(logStream, level, msg, err); } } public static void log(PrintStream logStream, Level level, Object msg) { log(logStream, level, msg, null); } public static void log(PrintStream logStream, Level level, Object msg, Throwable err) { Date now = new Date(); String time; synchronized (LOG_TIME_FORMATTER) { time = LOG_TIME_FORMATTER.format(now); } logStream.append(time) .append(' ').append(level.getName()) .append(' ').append(Thread.currentThread().getName()) .append(' ').append(Objects.toString(msg)) .println(); printStackTrace(logStream, err); } /** * Looks for the {@link ConfigFileReaderSupport#LOG_LEVEL_CONFIG_PROP} in the options. If found, then uses it as the * result. Otherwise, invokes {@link #resolveLoggingVerbosity(String...)} * * @param resolver The {@code -o} options specified by the user * @param args The command line arguments * @return The resolved verbosity level */ public static Level resolveLoggingVerbosity(PropertyResolver resolver, String... args) { String levelValue = PropertyResolverUtils.getString( resolver, ConfigFileReaderSupport.LOG_LEVEL_CONFIG_PROP); if (GenericUtils.isEmpty(levelValue)) { return resolveLoggingVerbosity(args); } LogLevelValue level = LogLevelValue.fromName(levelValue); if (level == null) { throw new IllegalArgumentException( "Unknown " + ConfigFileReaderSupport.LOG_LEVEL_CONFIG_PROP + " option value: " + levelValue); } return level.getLoggingLevel(); } public static Level resolveLoggingVerbosity(String... args) { return resolveLoggingVerbosity(args, GenericUtils.length(args)); } public static Level resolveLoggingVerbosity(String[] args, int maxIndex) { for (int index = 0; index < maxIndex; index++) { String argName = args[index]; if ("-v".equals(argName)) { return Level.INFO; } else if ("-vv".equals(argName)) { return Level.FINE; } else if ("-vvv".equals(argName)) { return Level.FINEST; } } return Level.CONFIG; } public static Logger resolveSystemLogger(Class clazz, Level threshold) { return resolveSystemLogger(clazz.getName(), threshold); } public static Logger resolveSystemLogger(String name, Level threshold) { return resolveLogger(name, threshold, System.out, System.err); } public static Logger resolveLogger(Class clazz, Level threshold, PrintStream stdout, PrintStream stderr) { return resolveLogger(clazz.getSimpleName(), threshold, stdout, stderr); } public static Logger resolveLogger(String name, Level threshold, PrintStream stdout, PrintStream stderr) { PrintStream logStream = resolvePrintStream(threshold, stdout, stderr); return getLogger(name, threshold, logStream); } public static boolean showError(PrintStream stderr, String message) { stderr.append("ERROR: ").println(message); return true; } public static boolean isEnabledVerbosityLogging(Level level) { if ((level == null) || Level.OFF.equals(level) || Level.CONFIG.equals(level) || Level.SEVERE.equals(level) || Level.WARNING.equals(level)) { return false; } return true; } public static PrintStream resolvePrintStream(Level threshold, PrintStream stdout, PrintStream stderr) { if (isEnabledVerbosityLogging(threshold)) { return Level.INFO.equals(threshold) ? stderr : stdout; } else { return NULL_PRINT_STREAM; } } public static T printStackTrace(Appendable out, T reason) { if ((reason == null) || (out == null)) { return reason; } if (out instanceof PrintStream) { reason.printStackTrace((PrintStream) out); } else if (out instanceof PrintWriter) { reason.printStackTrace((PrintWriter) out); } return reason; } public static Logger getSystemLogger(Class clazz, Level threshold) { return getSystemLogger(clazz.getName(), threshold); } public static Logger getSystemLogger(String name, Level threshold) { return getLogger(name, threshold, resolveSystemPrintStream(threshold)); } public static PrintStream resolveSystemPrintStream(Level threshold) { return resolvePrintStream(threshold, System.out, System.err); } public static Logger getLogger(Class clazz, Level threshold, PrintStream logStream) { return getLogger(clazz.getSimpleName(), threshold, logStream); } public static Logger getLogger(String name, Level threshold, PrintStream logStream) { return ((threshold == null) || Level.OFF.equals(threshold)) ? SimplifiedLoggerSkeleton.EMPTY : new CliLogger(name, threshold, logStream); } } apache-mina-sshd-46fc8d6/sshd-cli/src/main/java/org/apache/sshd/cli/CliSupport.java000066400000000000000000000417731456036076300301210ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.sshd.cli; import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.net.SocketAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.logging.Level; import org.apache.sshd.common.AttributeRepository; import org.apache.sshd.common.NamedFactory; import org.apache.sshd.common.NamedResource; import org.apache.sshd.common.PropertyResolver; import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.auth.UserAuthFactoriesManager; import org.apache.sshd.common.auth.UserAuthInstance; import org.apache.sshd.common.auth.UserAuthMethodFactory; import org.apache.sshd.common.cipher.BuiltinCiphers; import org.apache.sshd.common.cipher.Cipher; import org.apache.sshd.common.compression.BuiltinCompressions; import org.apache.sshd.common.compression.Compression; import org.apache.sshd.common.config.CompressionConfigValue; import org.apache.sshd.common.config.ConfigFileReaderSupport; import org.apache.sshd.common.helpers.AbstractFactoryManager; import org.apache.sshd.common.io.BuiltinIoServiceFactoryFactories; import org.apache.sshd.common.io.IoAcceptor; import org.apache.sshd.common.io.IoConnector; import org.apache.sshd.common.io.IoServiceEventListener; import org.apache.sshd.common.io.IoServiceFactoryFactory; import org.apache.sshd.common.kex.KexProposalOption; import org.apache.sshd.common.mac.BuiltinMacs; import org.apache.sshd.common.mac.Mac; import org.apache.sshd.common.session.Session; import org.apache.sshd.common.session.SessionContext; import org.apache.sshd.common.session.SessionListener; import org.apache.sshd.common.util.GenericUtils; import org.slf4j.Logger; /** * Provides common utilities for SSH client/server execution from the CLI * * @author Apache MINA SSHD Project */ public abstract class CliSupport { public static final BuiltinIoServiceFactoryFactories DEFAULT_IO_SERVICE_FACTORY = BuiltinIoServiceFactoryFactories.NIO2; protected CliSupport() { super(); } public static < S extends SessionContext, M extends UserAuthInstance, F extends UserAuthMethodFactory, I extends UserAuthFactoriesManager> void setupUserAuthFactories( I manager, PropertyResolver options) { String methods = options.getString(ConfigFileReaderSupport.PREFERRED_AUTHS_CONFIG_PROP); if (GenericUtils.isNotEmpty(methods)) { manager.setUserAuthFactoriesNameList(methods); return; } } /** * Scans the arguments for the "-io" command line option and sets the I/O service accordingly. If no * specific option specified then {@link #DEFAULT_IO_SERVICE_FACTORY} is used. * * @param stderr Error stream for output of error messages * @param args The arguments to scan * @return The resolved I/O service factory - {@code null} if errors encountered */ public static BuiltinIoServiceFactoryFactories resolveIoServiceFactory(PrintStream stderr, String... args) { int numArgs = GenericUtils.length(args); BuiltinIoServiceFactoryFactories factory = null; for (int index = 0; index < numArgs; index++) { String argName = args[index]; if (!"-io".equals(argName)) { continue; } if (factory != null) { stderr.println("I/O factory re-specified - already set as " + factory); return null; } index++; if (index >= numArgs) { stderr.println("option requires an argument: " + argName); return null; } String provider = args[index]; factory = resolveBuiltinIoServiceFactory(stderr, argName, provider); if (factory == null) { return null; } } if (factory == null) { factory = DEFAULT_IO_SERVICE_FACTORY; } System.setProperty(IoServiceFactoryFactory.class.getName(), factory.getFactoryClassName()); return factory; } public static BuiltinIoServiceFactoryFactories resolveBuiltinIoServiceFactory( PrintStream stderr, String argName, String provider) { BuiltinIoServiceFactoryFactories factory = BuiltinIoServiceFactoryFactories.fromFactoryName(provider); if (factory == null) { System.err.println(argName + " - unknown provider (" + provider + ")" + " should be one of " + BuiltinIoServiceFactoryFactories.VALUES); } return factory; } public static M setupIoServiceFactory( M manager, PropertyResolver resolver, Level level, PrintStream stdout, PrintStream stderr, String... args) { BuiltinIoServiceFactoryFactories factory = resolveIoServiceFactory(stderr, args); if (factory == null) { return null; } manager.setIoServiceFactoryFactory(factory.create()); Logger logger = CliLogger.resolveLogger(CliSupport.class, level, stdout, stderr); if (logger.isInfoEnabled()) { manager.setIoServiceEventListener(createLoggingIoServiceEventListener(logger)); manager.addSessionListener(createLoggingSessionListener(logger)); } return manager; } @SuppressWarnings("checkstyle:anoninnerlength") public static IoServiceEventListener createLoggingIoServiceEventListener(Logger logger) { return new IoServiceEventListener() { @Override public void connectionEstablished( IoConnector connector, SocketAddress local, AttributeRepository context, SocketAddress remote) throws IOException { logger.info("Connection established via {} - local={}, remote={}", connector, local, remote); } @Override public void abortEstablishedConnection( IoConnector connector, SocketAddress local, AttributeRepository context, SocketAddress remote, Throwable reason) throws IOException { logger.info("Abort established connection {} - local={}, remote={}", connector, local, remote); if (reason != null) { logger.warn(" {}: {}", reason.getClass().getSimpleName(), reason.getMessage()); logger.error(reason.getClass().getSimpleName(), reason); } } @Override public void connectionAccepted( IoAcceptor acceptor, SocketAddress local, SocketAddress remote, SocketAddress service) throws IOException { logger.info("Connection accepted via {} - local={}, remote={}, service={}", acceptor, local, remote, service); } @Override public void abortAcceptedConnection( IoAcceptor acceptor, SocketAddress local, SocketAddress remote, SocketAddress service, Throwable reason) throws IOException { logger.info("Abort accepted connection {} - local={}, remote={}, service={}", acceptor, local, remote, service); if (reason != null) { logger.warn(" {}: {}", reason.getClass().getSimpleName(), reason.getMessage()); logger.error(reason.getClass().getSimpleName(), reason); } } }; } @SuppressWarnings("checkstyle:anoninnerlength") public static SessionListener createLoggingSessionListener(Logger logger) { return new SessionListener() { @Override public void sessionPeerIdentificationReceived( Session session, String version, List extraLines) { logger.info("{} peer identification={}", session, version); if (GenericUtils.isNotEmpty(extraLines)) { for (String l : extraLines) { logger.info(" => {}", l); } } } @Override public void sessionNegotiationEnd( Session session, Map clientProposal, Map serverProposal, Map negotiatedOptions, Throwable reason) { if (reason != null) { return; } logger.info("{} KEX negotiation results:", session); for (KexProposalOption opt : KexProposalOption.VALUES) { logger.info(" {}: {}", opt.getDescription(), negotiatedOptions.get(opt)); } } @Override public void sessionException(Session session, Throwable t) { logger.error("{} {}: {}", session, t.getClass().getSimpleName(), t.getMessage()); logger.error(t.getClass().getSimpleName(), t); } @Override public void sessionClosed(Session session) { logger.info("{} closed", session); } }; } public static List> setupCompressions(PropertyResolver options, PrintStream stderr) { String argVal = PropertyResolverUtils.getString( options, ConfigFileReaderSupport.COMPRESSION_PROP); if (GenericUtils.isEmpty(argVal)) { return Collections.emptyList(); } NamedFactory value = CompressionConfigValue.fromName(argVal); if (value == null) { CliLogger.showError(stderr, "Unknown compression configuration value: " + argVal); return null; } return Collections.singletonList(value); } public static List> setupCompressions( String argName, String argVal, List> current, PrintStream stderr) { if (GenericUtils.size(current) > 0) { CliLogger.showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current)); return null; } BuiltinCompressions.ParseResult result = BuiltinCompressions.parseCompressionsList(argVal); Collection> available = result.getParsedFactories(); if (GenericUtils.isEmpty(available)) { CliLogger.showError(stderr, "No known compressions in " + argVal); return null; } Collection unsupported = result.getUnsupportedFactories(); if (GenericUtils.size(unsupported) > 0) { stderr.append("WARNING: Ignored unsupported compressions: ") .println(GenericUtils.join(unsupported, ',')); } return new ArrayList<>(available); } public static List> setupMacs(PropertyResolver options, PrintStream stderr) { String argVal = PropertyResolverUtils.getString( options, ConfigFileReaderSupport.MACS_CONFIG_PROP); return GenericUtils.isEmpty(argVal) ? Collections.emptyList() : CliSupport.setupMacs(ConfigFileReaderSupport.MACS_CONFIG_PROP, argVal, null, stderr); } public static List> setupMacs( String argName, String argVal, List> current, PrintStream stderr) { if (GenericUtils.size(current) > 0) { CliLogger.showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current)); return null; } BuiltinMacs.ParseResult result = BuiltinMacs.parseMacsList(argVal); Collection> available = result.getParsedFactories(); if (GenericUtils.isEmpty(available)) { CliLogger.showError(stderr, "No known MACs in " + argVal); return null; } Collection unsupported = result.getUnsupportedFactories(); if (GenericUtils.size(unsupported) > 0) { stderr.append("WARNING: Ignored unsupported MACs: ") .println(GenericUtils.join(unsupported, ',')); } return new ArrayList<>(available); } public static List> setupCiphers(PropertyResolver options, PrintStream stderr) { String argVal = PropertyResolverUtils.getString( options, ConfigFileReaderSupport.CIPHERS_CONFIG_PROP); return GenericUtils.isEmpty(argVal) ? Collections.emptyList() : CliSupport.setupCiphers(ConfigFileReaderSupport.CIPHERS_CONFIG_PROP, argVal, null, stderr); } // returns null - e.g., re-specified or no supported cipher found public static List> setupCiphers( String argName, String argVal, List> current, PrintStream stderr) { if (GenericUtils.size(current) > 0) { CliLogger.showError(stderr, argName + " option value re-specified: " + NamedResource.getNames(current)); return null; } BuiltinCiphers.ParseResult result = BuiltinCiphers.parseCiphersList(argVal); Collection> available = result.getParsedFactories(); if (GenericUtils.isEmpty(available)) { CliLogger.showError(stderr, "WARNING: No known ciphers in " + argVal); return null; } Collection unsupported = result.getUnsupportedFactories(); if (GenericUtils.size(unsupported) > 0) { stderr.append("WARNING: Ignored unsupported ciphers: ") .println(GenericUtils.join(unsupported, ',')); } return new ArrayList<>(available); } public static String[] splitCommandLineArguments(String line) { line = GenericUtils.trimToEmpty(line); if (GenericUtils.isBlank(line)) { return GenericUtils.EMPTY_STRING_ARRAY; } Collection args = Collections.emptyList(); for (int index = 0; index < GenericUtils.QUOTES.length(); index++) { char delim = GenericUtils.QUOTES.charAt(index); int startPos = line.indexOf(delim); int endPos = -1; if (startPos >= 0) { endPos = line.indexOf(delim, startPos + 1); } if ((startPos >= 0) && (endPos > startPos)) { if (GenericUtils.isEmpty(args)) { args = new LinkedList<>(); } String prefix = (startPos > 0) ? line.substring(0, startPos).trim() : ""; String[] extra = GenericUtils.split(prefix, ' '); if (!GenericUtils.isEmpty(extra)) { args.addAll(Arrays.asList(extra)); } String value = line.substring(startPos + 1, endPos); args.add(value); line = (endPos < (line.length() - 1)) ? line.substring(endPos + 1).trim() : ""; if (GenericUtils.isBlank(line)) { break; } index = -1; // start delimiters again } } // see if any leftovers String[] extra = GenericUtils.split(line, ' '); if (GenericUtils.isEmpty(args)) { return extra; } if (!GenericUtils.isEmpty(extra)) { if (GenericUtils.isEmpty(args)) { args = new LinkedList<>(); } args.addAll(Arrays.asList(extra)); } return args.toArray(GenericUtils.EMPTY_STRING_ARRAY); } public static void printFieldsValues(Object info, PrintStream stdout) throws Exception { Field[] fields = info.getClass().getFields(); for (Field f : fields) { String name = f.getName(); int mod = f.getModifiers(); if (Modifier.isStatic(mod)) { continue; } Object value = f.get(info); stdout.append(" ").append(name).append(": ").println(value); } } } apache-mina-sshd-46fc8d6/sshd-cli/src/main/java/org/apache/sshd/cli/client/000077500000000000000000000000001456036076300264145ustar00rootroot00000000000000CliClientModuleProperties.java000066400000000000000000000040051456036076300342700ustar00rootroot00000000000000apache-mina-sshd-46fc8d6/sshd-cli/src/main/java/org/apache/sshd/cli/client/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.sshd.cli.client; import java.time.Duration; import org.apache.sshd.common.Property; /** * @author Apache MINA SSHD Project */ public final class CliClientModuleProperties { /** * Key used to retrieve the value of the timeout after which it will abort the connection if the connection has not * been established - in milliseconds. */ public static final Property CONECT_TIMEOUT = Property.duration("cli-connect-timeout", Duration.ofMinutes(2)); /** * Key used to retrieve the value of the timeout after which it will close the connection if the other side has not * been authenticated - in milliseconds. */ public static final Property AUTH_TIMEOUT = Property.duration("cli-auth-timeout", Duration.ofMinutes(2)); /** * Key used to retrieve the value of the timeout for opening an EXEC or SHELL channel - in msec. */ public static final Property CHANNEL_OPEN_TIMEOUT = Property.duration("cli-channel-open-timeout", Duration.ofSeconds(30)); private CliClientModuleProperties() { throw new UnsupportedOperationException("No instance"); } } apache-mina-sshd-46fc8d6/sshd-cli/src/main/java/org/apache/sshd/cli/client/ScpCommandMain.java000066400000000000000000000533251456036076300321200ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.sshd.cli.client; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.attribute.PosixFilePermission; import java.security.KeyPair; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.logging.Level; import org.apache.sshd.cli.CliLogger; import org.apache.sshd.client.ClientFactoryManager; import org.apache.sshd.client.auth.AuthenticationIdentitiesProvider; import org.apache.sshd.client.config.hosts.HostConfigEntry; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.session.Session; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.ReflectionUtils; import org.apache.sshd.common.util.io.input.NoCloseInputStream; import org.apache.sshd.common.util.threads.ThreadUtils; import org.apache.sshd.scp.client.ScpClient; import org.apache.sshd.scp.client.ScpClient.Option; import org.apache.sshd.scp.client.ScpClientCreator; import org.apache.sshd.scp.client.ScpRemote2RemoteTransferHelper; import org.apache.sshd.scp.client.ScpRemote2RemoteTransferListener; import org.apache.sshd.scp.common.ScpLocation; import org.apache.sshd.scp.common.ScpTransferEventListener; import org.apache.sshd.scp.common.helpers.ScpAckInfo; import org.apache.sshd.scp.common.helpers.ScpReceiveDirCommandDetails; import org.apache.sshd.scp.common.helpers.ScpReceiveFileCommandDetails; import org.apache.sshd.scp.common.helpers.ScpTimestampCommandDetails; import org.slf4j.Logger; /** * @see SCP(1) - manual page * @author Apache MINA SSHD Project */ public class ScpCommandMain extends SshClientCliSupport { /** * Command line option used to indicate a non-default port */ public static final String SCP_PORT_OPTION = "-P"; /** * Copies between two remote hosts are transferred through the local host */ public static final String SCP_REMOTE_TO_REMOTE_OPTION = "-3"; public ScpCommandMain() { super(); // in case someone wants to extend it } /* -------------------------------------------------------------------------------- */ public static String[] normalizeCommandArguments(PrintStream stdout, PrintStream stderr, String... args) { int numArgs = GenericUtils.length(args); if (numArgs <= 0) { return args; } List effective = new ArrayList<>(numArgs); boolean error = false; boolean threeWay = false; for (int index = 0; (index < numArgs) && (!error); index++) { String argName = args[index]; // handled by 'setupClientSession' if (isArgumentedOption(SCP_PORT_OPTION, argName) || "-creator".equals(argName)) { index++; if (index >= numArgs) { error = CliLogger.showError(stderr, "option requires an argument: " + argName); break; } effective.add(argName); effective.add(args[index]); } else if ("-r".equals(argName) || "-p".equals(argName) || "-q".equals(argName) || "-C".equals(argName) || "-v".equals(argName) || "-vv".equals(argName) || "-vvv".equals(argName)) { effective.add(argName); } else if (SCP_REMOTE_TO_REMOTE_OPTION.equals(argName)) { threeWay = true; effective.add(argName); } else if (argName.charAt(0) == '-') { error = CliLogger.showError(stderr, "Unknown option: " + argName); break; } else { index++; if (index >= numArgs) { error = CliLogger.showError(stderr, "Not enough arguments"); break; } ScpLocation source = new ScpLocation(argName); ScpLocation target = new ScpLocation(args[index]); if (index < (numArgs - 1)) { error = CliLogger.showError(stderr, "Unexpected extra arguments"); break; } if (threeWay) { if (source.isLocal() || target.isLocal()) { error = CliLogger.showError(stderr, "Both targets must be remote for the 3-way copy option"); break; } adjustRemoteTargetArguments(source, source, target, effective); } else { if (source.isLocal() == target.isLocal()) { error = CliLogger.showError(stderr, "Both targets are either remote or local"); break; } ScpLocation remote = source.isLocal() ? target : source; adjustRemoteTargetArguments(remote, source, target, effective); } break; } } if (error) { return null; } return effective.toArray(new String[effective.size()]); } /* -------------------------------------------------------------------------------- */ private static void adjustRemoteTargetArguments( ScpLocation remote, ScpLocation source, ScpLocation target, Collection effective) { int port = remote.resolvePort(); if (port != SshConstants.DEFAULT_PORT) { effective.add(SCP_PORT_OPTION); effective.add(Integer.toString(port)); } effective.add(remote.resolveUsername() + "@" + remote.getHost()); effective.add(source.toString()); effective.add(target.toString()); } /* -------------------------------------------------------------------------------- */ public static ScpClientCreator resolveScpClientCreator(PrintStream stderr, String... args) { String className = null; for (int index = 0, numArgs = GenericUtils.length(args); index < numArgs; index++) { String argName = args[index]; if ("-creator".equals(argName)) { index++; if (index >= numArgs) { CliLogger.showError(stderr, "option requires an argument: " + argName); return null; } className = args[index]; } } if (GenericUtils.isEmpty(className)) { className = System.getProperty(ScpClientCreator.class.getName()); } if (GenericUtils.isEmpty(className)) { return ScpClientCreator.instance(); } try { ClassLoader cl = ThreadUtils.resolveDefaultClassLoader(ScpClientCreator.class); Class clazz = cl.loadClass(className); return ReflectionUtils.newInstance(clazz, ScpClientCreator.class); } catch (Exception e) { stderr.append("WARNING: Failed (").append(e.getClass().getSimpleName()).append(')') .append(" to instantiate ").append(className) .append(": ").println(e.getMessage()); stderr.flush(); return null; } } /* -------------------------------------------------------------------------------- */ public static Set