mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-06 15:20:54 +03:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
936c6c8008 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -12,9 +12,6 @@
|
||||
# Output dirs
|
||||
target/
|
||||
build/
|
||||
docs/
|
||||
.gradle/
|
||||
sshj.jar
|
||||
|
||||
# MacOS X
|
||||
.DS_Store
|
||||
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
language: java
|
||||
sudo: false
|
||||
jdk:
|
||||
- oraclejdk7
|
||||
- oraclejdk8
|
||||
language: java
|
||||
@@ -1,13 +0,0 @@
|
||||
Copyright (C)2009 - SSHJ Contributors
|
||||
|
||||
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.
|
||||
71
README.adoc
71
README.adoc
@@ -1,13 +1,10 @@
|
||||
= sshj - SSHv2 library for Java
|
||||
Jeroen van Erp
|
||||
:sshj_groupid: com.hierynomus
|
||||
:sshj_version: 0.18.0
|
||||
:sshj_version: 0.11.0
|
||||
:source-highlighter: pygments
|
||||
|
||||
image:https://travis-ci.org/hierynomus/sshj.svg?branch=master[link="https://travis-ci.org/hierynomus/sshj"]
|
||||
image:https://api.codacy.com/project/badge/Grade/14a0a316bb9149739b5ea26dbfa8da8a["Codacy code quality", link="https://www.codacy.com/app/jeroen_2/sshj?utm_source=github.com&utm_medium=referral&utm_content=hierynomus/sshj&utm_campaign=Badge_Grade"]
|
||||
image:https://maven-badges.herokuapp.com/maven-central/com.hierynomus/sshj/badge.svg["Maven Central",link="https://maven-badges.herokuapp.com/maven-central/com.hierynomus/sshj"]
|
||||
image:https://javadoc-emblem.rhcloud.com/doc/com.hierynomus/sshj/badge.svg["Javadoc",link="http://www.javadoc.io/doc/com.hierynomus/sshj"]
|
||||
image::https://travis-ci.org/hierynomus/sshj.svg?branch=master[]
|
||||
|
||||
To get started, have a look at one of the examples. Hopefully you will find the API pleasant to work with :)
|
||||
|
||||
@@ -62,15 +59,13 @@ In the `examples` directory, there is a separate Maven project that shows how th
|
||||
Implementations / adapters for the following algorithms are included:
|
||||
|
||||
ciphers::
|
||||
`aes{128,192,256}-{cbc,ctr}`, `blowfish-{cbc,ctr}`, `3des-{cbc,ctr}`, `twofish{128,192,256}-{cbc,ctr}`, `twofish-cbc`, `serpent{128,192,256}-{cbc,ctr}`, `idea-{cbc,ctr}`, `cast128-{cbc,ctr}`, `arcfour`, `arcfour{128,256}`
|
||||
SSHJ also supports the following extended (non official) ciphers: `camellia{128,192,256}-{cbc,ctr}`, `camellia{128,192,256}-{cbc,ctr}@openssh.org`
|
||||
`aes{128,192,256}-{cbc,ctr}`, `blowfish-cbc`, `3des-cbc`
|
||||
|
||||
key exchange::
|
||||
`diffie-hellman-group1-sha1`, `diffie-hellman-group14-sha1`, `diffie-hellman-group-exchange-sha1`, `diffie-hellman-group-exchange-sha256`,
|
||||
`ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `curve25519-sha256@libssh.org`
|
||||
`diffie-hellman-group1-sha1`, `diffie-hellman-group14-sha1`
|
||||
|
||||
signatures::
|
||||
`ssh-rsa`, `ssh-dss`, `ecdsa-sha2-nistp256`, `ssh-ed25519`
|
||||
`ssh-rsa`, `ssh-dss`
|
||||
|
||||
mac::
|
||||
`hmac-md5`, `hmac-md5-96`, `hmac-sha1`, `hmac-sha1-96`, `hmac-sha2-256`, `hmac-sha2-512`
|
||||
@@ -83,8 +78,6 @@ private key files::
|
||||
|
||||
If you need something that is not included, it shouldn't be too hard to add (do contribute it!)
|
||||
|
||||
== Comparing to other implementations
|
||||
http://ssh-comparison.quendi.de/comparison.html[SSH Implementation Comparison]
|
||||
|
||||
== Dependencies
|
||||
Java 6+. http://www.slf4j.org/download.html[slf4j] is required. http://www.bouncycastle.org/java.html[bouncycastle] is highly recommended and required for using some of the crypto algorithms. http://www.jcraft.com/jzlib/[jzlib] is required for using zlib compression.
|
||||
@@ -99,58 +92,8 @@ Google Group: http://groups.google.com/group/sshj-users
|
||||
Fork away!
|
||||
|
||||
== Release history
|
||||
SSHJ 0.18.0 (2016-09-30)::
|
||||
* Fixed Android compatibility
|
||||
* Upgrade to Gradle 3.0
|
||||
* Merged https://github.com/hierynomus/sshj/pulls/271[#271]: Load known_hosts without requiring BouncyCastle
|
||||
* Merged https://github.com/hierynomus/sshj/pulls/269[#269]: Brought back Java6 support by popular demand
|
||||
* Merged https://github.com/hierynomus/sshj/pulls/267[#267]: Added support for per connection logging (Fixes https://github.com/hierynomus/sshj/issues/264[#264])
|
||||
* Merged https://github.com/hierynomus/sshj/pulls/262[#262], https://github.com/hierynomus/sshj/pulls/265[#265] and https://github.com/hierynomus/sshj/pulls/266[#266]: Added PKCS5 key file support
|
||||
* Fixed toString of sftp FileAttributes (Fixes https://github.com/hierynomus/sshj/pulls/258[#258])
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/255[#255]: No longer depending on 'privately marked' classes in `net.i2p.crypto.eddsa.math` package, fixes OSGI dependencies
|
||||
SSHJ 0.17.2 (2016-07-07)::
|
||||
* Treating SSH Server identification line ending in '\n' instead of '\r\n' leniently.
|
||||
SSHJ 0.17.1 (2016-07-06)::
|
||||
* Improved parsing of the SSH Server identification. Too long header lines now no longer break the protocol.
|
||||
SSHJ 0.17.0 (2016-07-05)::
|
||||
* *Introduced breaking change in SFTP copy behaviour*: Previously an SFTP copy operation would behave differently if both source and target were folders with different names.
|
||||
In this case instead of copying the contents of the source into the target directory, the directory itself was copied as a sub directory of the target directory.
|
||||
This behaviour has been removed in favour of the default behaviour which is to copy the contents of the source into the target. Bringing the behaviour in line with how SCP works.
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/252[#252] (via: https://github.com/hierynomus/sshj/pulls/253[#253]): Same name subdirs are no longer merged by accident
|
||||
SSHJ 0.16.0 (2016-04-11)::
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/239[#239]: Remote port forwards did not work if you used the empty string as address, or a catch-all address.
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/242[#242]: Added OSGI headers to sources jar manifest
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/236[#236]: Remote Port forwarding with dynamic port allocation fails with BufferUnderflowException
|
||||
* Upgraded gradle distribution to 2.12
|
||||
* Closed https://github.com/hierynomus/sshj/issues/234[#234]: Dropped Java6 support (0.15.0 was already Java6 incompatible due to Java7 dependency)
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/118[#118]: Added configuration switch for waiting on a server ident before sending the client ident.
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/114[#114]: Added javadoc that you always need to call close() on a Command before inspecting the exit codes.
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/237[#237]: Fixed race condition if a `hostkeys-00@openssh.com` global request is received directly after a successful auth.
|
||||
SSHJ 0.15.0 (2015-11-20)::
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/220[#220]: Added support for `ssh-ed25519` host keys
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/225[#225]: Fixed bug in ECDSA fingerprint calculation that sometimes produced an incorrect fingerprint
|
||||
* Added `arcfour` Stream Ciphers from RFC4253 and RFC4345
|
||||
* Added all Block Ciphers from RFC4344 and RFC4253
|
||||
SSHJ 0.14.0 (2015-11-04)::
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/171[#171]: Added support for `curve25519-sha256@libssh.org` key exchange algorithm
|
||||
* Added support for `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384` and `ecdh-sha2-nistp521` key exchange algorithms
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/167[#167]: Added support for `diffie-hellman-group-exchange-sha1` and `diffie-hellman-group-exchange-sha256` key exchange methods
|
||||
* Fixed https://github.com/hierynomus/sshj/issues/212[#212]: Configure path escaping to enable shell expansion to work correctly
|
||||
* Merged https://github.com/hierynomus/sshj/issues/210[#210]: RemoteFileInputStream.skip returns wrong value (Fixes https://github.com/hierynomus/sshj/issues/209[#209])
|
||||
* Merged https://github.com/hierynomus/sshj/issues/208[#208]: Added SCP bandwidth limitation support
|
||||
* Merged https://github.com/hierynomus/sshj/issues/211[#211]: Made keyfile format detection more robust
|
||||
SSHJ 0.13.0 (2015-08-18)::
|
||||
* Merged https://github.com/hierynomus/sshj/issues/199[#199]: Fix for IndexOutOfBoundsException in ReadAheadRemoteFileInputStream, fixes https://github.com/hierynomus/sshj/issues/183[#183]
|
||||
* Merged https://github.com/hierynomus/sshj/issues/195[#195]: New authentication supported: `gssapi-with-mic`
|
||||
* Merged https://github.com/hierynomus/sshj/issues/201[#201]: New option to verify negotiated key exchange algorithms
|
||||
* Merged https://github.com/hierynomus/sshj/issues/196[#196]: Fix for looking up complete hostname in known hosts file
|
||||
SSHJ 0.12.0 (2015-04-14)::
|
||||
* Added support for HTTP proxies when running JDK6 or JDK7, fixes: https://github.com/hierynomus/sshj/issues/170[#170]
|
||||
* Merged https://github.com/hierynomus/sshj/issues/186[#186]: Fix for detecting end-of-stream
|
||||
* Compiling to JDK6, fixes https://github.com/hierynomus/sshj/issues/179[#179] and https://github.com/hierynomus/sshj/issues/185[#185]
|
||||
* Correctly close socket and channel when LocalPortForwarder fails to open and start the channel (Fixes https://github.com/hierynomus/sshj/issues/175[#175] and https://github.com/hierynomus/sshj/issues/176[#176])
|
||||
* Merged https://github.com/hierynomus/sshj/issues/181[#181]: Invalid write packet length when reading with offset (Fixes https://github.com/hierynomus/sshj/issues/180[#180])
|
||||
SSHJ 0.11.0 (2015-01-23)::
|
||||
|
||||
SSHJ 0.11.0 (No date set yet)::
|
||||
* New maven coordinates `com.hierynomus:sshj:0.11.0` as https://github.com/hierynomus[@hierynomus] took over as maintainer of SSHJ
|
||||
* Migrated build system to Gradle 2.2.1
|
||||
* Merged https://github.com/hierynomus/sshj/issues/150[#150]: Fix for incorrect file handle on some SSH servers, fixes: https://github.com/hierynomus/sshj/issues/54[#54], https://github.com/hierynomus/sshj/issues/119[#119], https://github.com/hierynomus/sshj/issues/168[#168], https://github.com/hierynomus/sshj/issues/169[#169]
|
||||
|
||||
253
build.gradle
253
build.gradle
@@ -1,28 +1,34 @@
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
plugins {
|
||||
id "java"
|
||||
id "groovy"
|
||||
id "osgi"
|
||||
id "maven-publish"
|
||||
id "org.ajoberstar.release-opinion" version "1.4.2"
|
||||
id "com.github.hierynomus.license" version "0.12.1"
|
||||
id "com.jfrog.bintray" version "1.7"
|
||||
id 'ru.vyarus.pom' version '1.0.3'
|
||||
id 'ru.vyarus.github-info' version '1.1.0'
|
||||
}
|
||||
apply plugin: "java"
|
||||
apply plugin: "maven"
|
||||
apply plugin: "signing"
|
||||
apply plugin: "osgi"
|
||||
|
||||
group = "com.hierynomus"
|
||||
defaultTasks "build"
|
||||
version = "0.11.0"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.6
|
||||
targetCompatibility = 1.6
|
||||
configurations {
|
||||
compile {
|
||||
transitive = false
|
||||
}
|
||||
}
|
||||
|
||||
configurations.compile.transitive = false
|
||||
test {
|
||||
include "**/*Test.*"
|
||||
afterSuite { descriptor, result ->
|
||||
if (descriptor.className != null) {
|
||||
def indicator = "\u001B[32m✓\u001b[0m"
|
||||
if (result.failedTestCount > 0) {
|
||||
indicator = "\u001B[31m✘\u001b[0m"
|
||||
}
|
||||
logger.lifecycle("$indicator Test ${descriptor.name}; Executed: ${result.testCount}/\u001B[32m${result.successfulTestCount}\u001B[0m/\u001B[31m${result.failedTestCount}\u001B[0m")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def bouncycastleVersion = "1.51"
|
||||
|
||||
@@ -32,36 +38,10 @@ dependencies {
|
||||
compile "org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion"
|
||||
compile "com.jcraft:jzlib:1.1.3"
|
||||
|
||||
compile "net.i2p.crypto:eddsa:0.1.0"
|
||||
|
||||
testCompile "junit:junit:4.11"
|
||||
testCompile 'org.spockframework:spock-core:1.0-groovy-2.4'
|
||||
testCompile "org.mockito:mockito-core:1.9.5"
|
||||
testCompile "org.apache.sshd:sshd-core:1.1.0"
|
||||
testCompile "org.apache.sshd:sshd-core:0.11.0"
|
||||
testRuntime "ch.qos.logback:logback-classic:1.1.2"
|
||||
testCompile 'org.glassfish.grizzly:grizzly-http-server:2.3.17'
|
||||
testCompile 'org.apache.httpcomponents:httpclient:4.5.2'
|
||||
|
||||
}
|
||||
|
||||
license {
|
||||
header rootProject.file('LICENSE_HEADER')
|
||||
strictCheck true
|
||||
mapping {
|
||||
java = 'SLASHSTAR_STYLE'
|
||||
}
|
||||
excludes(['**/djb/Curve25519.java', '**/sshj/common/Base64.java'])
|
||||
}
|
||||
|
||||
release {
|
||||
grgit = org.ajoberstar.grgit.Grgit.open(project.projectDir)
|
||||
}
|
||||
|
||||
// This disables the pedantic doclint feature of JDK8
|
||||
if (JavaVersion.current().isJava8Compatible()) {
|
||||
tasks.withType(Javadoc) {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
@@ -70,7 +50,6 @@ jar {
|
||||
instruction "Bundle-License", "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
instruction "Import-Package", "!net.schmizz.*"
|
||||
instruction "Import-Package", "javax.crypto*"
|
||||
instruction "Import-Package", "net.i2p*"
|
||||
instruction "Import-Package", "com.jcraft.jzlib*;version=\"[1.1,2)\";resolution:=optional"
|
||||
instruction "Import-Package", "org.slf4j*;version=\"[1.7,5)\""
|
||||
instruction "Import-Package", "org.bouncycastle*"
|
||||
@@ -87,123 +66,93 @@ task javadocJar(type: Jar) {
|
||||
task sourcesJar(type: Jar) {
|
||||
classifier = 'sources'
|
||||
from sourceSets.main.allSource
|
||||
manifest {
|
||||
attributes(
|
||||
// Add the needed OSGI attributes
|
||||
"Bundle-ManifestVersion": "2",
|
||||
"Bundle-Name": "${project.jar.manifest.name} Source",
|
||||
"Bundle-Version": project.jar.manifest.version,
|
||||
"Eclipse-SourceBundle": "${project.jar.manifest.symbolicName};version=\"${project.jar.manifest.version}\";roots:=\".\"",
|
||||
"Bundle-SymbolicName": "${project.jar.manifest.symbolicName}.source"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(Test) {
|
||||
testLogging {
|
||||
exceptionFormat = 'full'
|
||||
}
|
||||
include "**/*Test.*"
|
||||
include "**/*Spec.*"
|
||||
if (!project.hasProperty("allTests")) {
|
||||
useJUnit {
|
||||
excludeCategories 'com.hierynomus.sshj.test.SlowTests'
|
||||
excludeCategories 'com.hierynomus.sshj.test.KnownFailingTests'
|
||||
}
|
||||
}
|
||||
artifacts {
|
||||
archives javadocJar, sourcesJar
|
||||
}
|
||||
|
||||
afterSuite { descriptor, result ->
|
||||
if (descriptor.className != null) {
|
||||
def indicator = "\u001B[32m✓\u001b[0m"
|
||||
if (result.failedTestCount > 0) {
|
||||
indicator = "\u001B[31m✘\u001b[0m"
|
||||
signing {
|
||||
required { !version.contains("SNAPSHOT") && gradle.taskGraph.hasTask("uploadArchives") }
|
||||
sign configurations.archives
|
||||
}
|
||||
|
||||
// This disables the pedantic doclint feature of JDK8
|
||||
if (JavaVersion.current().isJava8Compatible()) {
|
||||
tasks.withType(Javadoc) {
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
}
|
||||
}
|
||||
|
||||
uploadArchives {
|
||||
if(project.hasProperty('sonatypeUsername')) {
|
||||
repositories.mavenDeployer {
|
||||
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
|
||||
|
||||
configuration = configurations.archives
|
||||
|
||||
repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2') {
|
||||
authentication(userName: sonatypeUsername, password: sonatypePassword)
|
||||
}
|
||||
logger.lifecycle("$indicator Test ${descriptor.name}; Executed: ${result.testCount}/\u001B[32m${result.successfulTestCount}\u001B[0m/\u001B[31m${result.failedTestCount}\u001B[0m")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
project.tasks.compileGroovy.onlyIf { false }
|
||||
|
||||
github {
|
||||
user 'hierynomus'
|
||||
license 'Apache'
|
||||
}
|
||||
|
||||
pom {
|
||||
description "SSHv2 library for Java"
|
||||
url "https://github.com/hierynomus/sshj"
|
||||
inceptionYear "2009"
|
||||
developers {
|
||||
developer {
|
||||
id "hierynomus"
|
||||
name "Jeroen van Erp"
|
||||
email "jeroen@javadude.nl"
|
||||
roles {
|
||||
role "Lead developer"
|
||||
snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots/') {
|
||||
authentication(userName: sonatypeUsername, password: sonatypePassword)
|
||||
}
|
||||
}
|
||||
developer {
|
||||
id "shikhar"
|
||||
name "Shikhar Bhushan"
|
||||
email "shikhar@schmizz.net"
|
||||
url "http://schmizz.net"
|
||||
roles {
|
||||
role "Previous lead developer"
|
||||
}
|
||||
}
|
||||
developer {
|
||||
id "iterate"
|
||||
name "David Kocher"
|
||||
email "dkocher@iterate.ch"
|
||||
organization "iterage GmbH"
|
||||
organizationUrl "https://iterate.ch"
|
||||
roles {
|
||||
role "Developer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
publishing.publications {
|
||||
Sshj(MavenPublication) {
|
||||
from components.java
|
||||
artifact sourcesJar
|
||||
artifact javadocJar
|
||||
}
|
||||
}
|
||||
pom.project {
|
||||
name "sshj"
|
||||
description "SSHv2 library for Java"
|
||||
url "https://github.com/hierynomus/sshj"
|
||||
inceptionYear "2009"
|
||||
|
||||
|
||||
if (project.hasProperty("bintrayUsername") && project.hasProperty("bintrayApiKey")) {
|
||||
bintray {
|
||||
user = project.property("bintrayUsername")
|
||||
key = project.property("bintrayApiKey")
|
||||
publish = true
|
||||
publications = ["Sshj"]
|
||||
pkg {
|
||||
repo = "maven"
|
||||
name = project.name
|
||||
licenses = ["Apache-2.0"]
|
||||
vcsUrl = "https://github.com/hierynomus/sshj.git"
|
||||
labels = ["ssh", "sftp", "secure-shell", "network", "file-transfer"]
|
||||
githubRepo = "hierynomus/sshj"
|
||||
version {
|
||||
name = project.version.toString()
|
||||
vcsTag = "v${project.version}"
|
||||
released = new SimpleDateFormat('yyyy-MM-dd\'T\'HH:mm:ss.SSSZZ').format(new Date())
|
||||
gpg {
|
||||
sign = true
|
||||
passphrase = project.property("signing.password")
|
||||
issueManagement {
|
||||
system "github"
|
||||
url "https://github.com/hierynomus/sshj/issues"
|
||||
}
|
||||
mavenCentralSync {
|
||||
sync = true
|
||||
user = project.property("sonatypeUsername")
|
||||
password = project.property("sonatypePassword")
|
||||
close = 1
|
||||
|
||||
scm {
|
||||
connection "scm:git:git://github.com/hierynomus/sshj.git"
|
||||
developerConnection "scm:git:git@github.com:hierynomus/sshj.git"
|
||||
url "https://github.com/hierynomus/sshj.git"
|
||||
}
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name "Apache 2"
|
||||
url "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||
distribution "repo"
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
id "hierynomus"
|
||||
name "Jeroen van Erp"
|
||||
email "jeroen@javadude.nl"
|
||||
roles {
|
||||
role "Lead developer"
|
||||
}
|
||||
}
|
||||
developer {
|
||||
id "shikhar"
|
||||
name "Shikhar Bhushan"
|
||||
email "shikhar@schmizz.net"
|
||||
url "http://schmizz.net"
|
||||
roles {
|
||||
role "Previous lead developer"
|
||||
}
|
||||
}
|
||||
developer {
|
||||
id "iterate"
|
||||
name "David Kocher"
|
||||
email "dkocher@iterate.ch"
|
||||
organization "iterage GmbH"
|
||||
organizationUrl "https://iterate.ch"
|
||||
roles {
|
||||
role "Developer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
project.tasks.release.dependsOn([project.tasks.build, project.tasks.bintrayUpload])
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.hierynomus</groupId>
|
||||
<artifactId>sshj-examples</artifactId>
|
||||
<groupId>net.schmizz</groupId>
|
||||
<artifactId>sshj</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>0.14.0</version>
|
||||
<version>0.10.0</version>
|
||||
|
||||
<name>sshj-examples</name>
|
||||
<description>Examples for SSHv2 library for Java</description>
|
||||
@@ -53,9 +53,9 @@
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.hierynomus</groupId>
|
||||
<groupId>net.schmizz</groupId>
|
||||
<artifactId>sshj</artifactId>
|
||||
<version>0.15.0</version>
|
||||
<version>0.10.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package net.schmizz.sshj.examples;
|
||||
|
||||
import net.schmizz.sshj.SSHClient;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package net.schmizz.sshj.examples;
|
||||
|
||||
import net.schmizz.keepalive.KeepAliveProvider;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package net.schmizz.sshj.examples;
|
||||
|
||||
import net.schmizz.sshj.SSHClient;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package net.schmizz.sshj.examples;
|
||||
|
||||
import net.schmizz.sshj.SSHClient;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package net.schmizz.sshj.examples;
|
||||
|
||||
import net.schmizz.sshj.SSHClient;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package net.schmizz.sshj.examples;
|
||||
|
||||
import net.schmizz.sshj.SSHClient;
|
||||
@@ -22,4 +37,4 @@ public class SCPDownload {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package net.schmizz.sshj.examples;
|
||||
|
||||
import net.schmizz.sshj.SSHClient;
|
||||
@@ -27,4 +42,4 @@ public class SCPUpload {
|
||||
ssh.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package net.schmizz.sshj.examples;
|
||||
|
||||
import net.schmizz.sshj.SSHClient;
|
||||
@@ -27,4 +42,4 @@ public class SFTPDownload {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package net.schmizz.sshj.examples;
|
||||
|
||||
import net.schmizz.sshj.SSHClient;
|
||||
@@ -29,4 +44,4 @@ public class SFTPUpload {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package net.schmizz.sshj.examples;
|
||||
|
||||
import net.schmizz.sshj.SSHClient;
|
||||
@@ -52,4 +67,4 @@ public class X11 {
|
||||
ssh.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
#Fri Mar 18 11:26:35 CET 2016
|
||||
#Wed Jan 21 09:17:25 CET 2015
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.0-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-bin.zip
|
||||
|
||||
344
pom.xml
Normal file
344
pom.xml
Normal file
@@ -0,0 +1,344 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright 2009 sshj contributors
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>net.schmizz</groupId>
|
||||
<artifactId>sshj</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
<version>0.10.1-SNAPSHOT</version>
|
||||
|
||||
<name>sshj</name>
|
||||
<description>SSHv2 library for Java</description>
|
||||
<url>http://github.com/hierynomus/sshj</url>
|
||||
|
||||
<inceptionYear>2009</inceptionYear>
|
||||
|
||||
<issueManagement>
|
||||
<system>github</system>
|
||||
<url>http://github.com/hierynomus/sshj/issues</url>
|
||||
</issueManagement>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com/hierynomus/sshj.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:hierynomus/sshj.git</developerConnection>
|
||||
<url>http://github.com/hierynomus/sshj</url>
|
||||
</scm>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache 2</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<parent>
|
||||
<groupId>org.sonatype.oss</groupId>
|
||||
<artifactId>oss-parent</artifactId>
|
||||
<version>7</version>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>1.51</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
<version>1.51</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jzlib</artifactId>
|
||||
<version>1.1.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
<version>1.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.1.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jzlib</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.sshd</groupId>
|
||||
<artifactId>sshd-core</artifactId>
|
||||
<version>0.11.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>hierynomus</id>
|
||||
<name>Jeroen van Erp</name>
|
||||
<email>jeroen@hierynomus.com</email>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>shikhar</id>
|
||||
<name>Shikhar Bhushan</name>
|
||||
<email>shikhar@schmizz.net</email>
|
||||
<url>http://schmizz.net</url>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>iterate</id>
|
||||
<name>David Kocher</name>
|
||||
<email>dkocher@iterate.ch</email>
|
||||
<organization>iterate GmbH</organization>
|
||||
<organizationUrl>https://iterate.ch</organizationUrl>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.9.1</version>
|
||||
<configuration>
|
||||
<encoding>${project.build.sourceEncoding}</encoding>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>2.4.0</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Import-Package>
|
||||
!net.schmizz.*,
|
||||
javax.crypto*,
|
||||
com.jcraft.jzlib*;version="[1.1,2)";resolution:=optional,
|
||||
org.slf4j*;version="[1.7,5)",
|
||||
org.bouncycastle*,
|
||||
*
|
||||
</Import-Package>
|
||||
<Export-Package>net.schmizz.*</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>clirr-maven-plugin</artifactId>
|
||||
<version>2.6.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.mycila</groupId>
|
||||
<artifactId>license-maven-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<header>src/etc/license-header</header>
|
||||
<properties>
|
||||
<owner>sshj contributors</owner>
|
||||
<email>sshj-users@googlegroups.com</email>
|
||||
</properties>
|
||||
<excludes>
|
||||
<exclude>**/README</exclude>
|
||||
<exclude>src/test/resources/**</exclude>
|
||||
<exclude>src/main/resources/**</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- <plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.plugins</groupId>
|
||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||
<version>1.6.2</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<serverId>ossrh</serverId>
|
||||
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||
</configuration>
|
||||
</plugin>
|
||||
--> </plugins>
|
||||
</build>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>sonatype-nexus-staging</id>
|
||||
<name>Nexus Release Repository</name>
|
||||
<url>http://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>sonatype-nexus-snapshots</id>
|
||||
<name>Sonatype Nexus Snapshots</name>
|
||||
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>full-deps</id>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jzlib</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>doclint-java8-disable</id>
|
||||
<activation>
|
||||
<jdk>[1.8,)</jdk>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<additionalparam>-Xdoclint:none</additionalparam>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>clirr-maven-plugin</artifactId>
|
||||
<version>2.6.1</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
</project>
|
||||
@@ -1 +0,0 @@
|
||||
rootProject.name = "sshj"
|
||||
@@ -0,0 +1,39 @@
|
||||
package nl.javadude.sshj.connection.channel;
|
||||
|
||||
import net.schmizz.sshj.SSHClient;
|
||||
import net.schmizz.sshj.connection.channel.direct.Session;
|
||||
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
public class ChannelCloseEofTest {
|
||||
|
||||
private SSHClient sshClient;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
sshClient = new SSHClient();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws IOException {
|
||||
sshClient.disconnect();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCorrectlyHandleSessionChannelEof() throws IOException, InterruptedException {
|
||||
sshClient.addHostKeyVerifier(new PromiscuousVerifier());
|
||||
sshClient.connect("172.16.37.129");
|
||||
sshClient.authPassword("jeroen", "jeroen");
|
||||
Session session = sshClient.startSession();
|
||||
session.allocateDefaultPTY();
|
||||
session.close();
|
||||
Thread.sleep(1000);
|
||||
assertThat("Should still be connected", sshClient.isConnected());
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.hierynomus.sshj.backport;
|
||||
|
||||
public class JavaVersion {
|
||||
public static boolean isJava7OrEarlier() {
|
||||
String property = System.getProperty("java.specification.version");
|
||||
float diff = Float.parseFloat(property) - 1.7f;
|
||||
|
||||
return diff < 0.01;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.hierynomus.sshj.backport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.*;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class Jdk7HttpProxySocket extends Socket {
|
||||
|
||||
private Proxy httpProxy = null;
|
||||
|
||||
public Jdk7HttpProxySocket(Proxy proxy) {
|
||||
super(proxy.type() == Proxy.Type.HTTP ? Proxy.NO_PROXY : proxy);
|
||||
if (proxy.type() == Proxy.Type.HTTP) {
|
||||
this.httpProxy = proxy;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(SocketAddress endpoint, int timeout) throws IOException {
|
||||
if (httpProxy != null) {
|
||||
connectHttpProxy(endpoint, timeout);
|
||||
} else {
|
||||
super.connect(endpoint, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
private void connectHttpProxy(SocketAddress endpoint, int timeout) throws IOException {
|
||||
super.connect(httpProxy.address(), timeout);
|
||||
|
||||
if (!(endpoint instanceof InetSocketAddress)) {
|
||||
throw new SocketException("Expected an InetSocketAddress to connect to, got: " + endpoint);
|
||||
}
|
||||
InetSocketAddress isa = (InetSocketAddress) endpoint;
|
||||
String httpConnect = "CONNECT " + isa.getHostName() + ":" + isa.getPort() + " HTTP/1.0\n\n";
|
||||
getOutputStream().write(httpConnect.getBytes(Charset.forName("UTF-8")));
|
||||
checkAndFlushProxyResponse();
|
||||
}
|
||||
|
||||
private void checkAndFlushProxyResponse()throws IOException {
|
||||
InputStream socketInput = getInputStream();
|
||||
byte[] tmpBuffer = new byte[512];
|
||||
int len = socketInput.read(tmpBuffer, 0, tmpBuffer.length);
|
||||
|
||||
if (len == 0) {
|
||||
throw new SocketException("Empty response from proxy");
|
||||
}
|
||||
|
||||
String proxyResponse = new String(tmpBuffer, 0, len, "UTF-8");
|
||||
|
||||
// Expecting HTTP/1.x 200 OK
|
||||
if (proxyResponse.contains("200")) {
|
||||
// Flush any outstanding message in buffer
|
||||
if (socketInput.available() > 0) {
|
||||
socketInput.skip(socketInput.available());
|
||||
}
|
||||
// Proxy Connect Successful
|
||||
} else {
|
||||
throw new SocketException("Fail to create Socket\nResponse was:" + proxyResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.hierynomus.sshj.backport;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
|
||||
public class Sockets {
|
||||
|
||||
/**
|
||||
* Java 7 and up have Socket implemented as Closeable, whereas Java6 did not have this inheritance.
|
||||
* @param socket The socket to wrap as Closeable
|
||||
* @return The (potentially wrapped) Socket as a Closeable.
|
||||
*/
|
||||
public static Closeable asCloseable(final Socket socket) {
|
||||
if (Closeable.class.isAssignableFrom(socket.getClass())) {
|
||||
return Closeable.class.cast(socket);
|
||||
} else {
|
||||
return new Closeable() {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
socket.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.hierynomus.sshj.secg;
|
||||
|
||||
import net.schmizz.sshj.common.SSHRuntimeException;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.spec.ECPoint;
|
||||
import java.security.spec.EllipticCurve;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class SecgUtils {
|
||||
/**
|
||||
* SECG 2.3.4 Octet String to ECPoint
|
||||
*/
|
||||
public static ECPoint getDecoded(byte[] M, EllipticCurve curve) {
|
||||
int elementSize = getElementSize(curve);
|
||||
if (M.length != 2 * elementSize + 1 || M[0] != 0x04) {
|
||||
throw new SSHRuntimeException("Invalid 'f' for Elliptic Curve " + curve.toString());
|
||||
}
|
||||
byte[] xBytes = new byte[elementSize];
|
||||
byte[] yBytes = new byte[elementSize];
|
||||
System.arraycopy(M, 1, xBytes, 0, elementSize);
|
||||
System.arraycopy(M, 1 + elementSize, yBytes, 0, elementSize);
|
||||
return new ECPoint(new BigInteger(1, xBytes), new BigInteger(1, yBytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* SECG 2.3.3 ECPoint to Octet String
|
||||
*/
|
||||
public static byte[] getEncoded(ECPoint point, EllipticCurve curve) {
|
||||
int elementSize = getElementSize(curve);
|
||||
byte[] M = new byte[2 * elementSize + 1];
|
||||
M[0] = 0x04;
|
||||
|
||||
byte[] xBytes = stripLeadingZeroes(point.getAffineX().toByteArray());
|
||||
byte[] yBytes = stripLeadingZeroes(point.getAffineY().toByteArray());
|
||||
System.arraycopy(xBytes, 0, M, 1 + elementSize - xBytes.length, xBytes.length);
|
||||
System.arraycopy(yBytes, 0, M, 1 + 2 * elementSize - yBytes.length, yBytes.length);
|
||||
return M;
|
||||
}
|
||||
|
||||
private static byte[] stripLeadingZeroes(byte[] bytes) {
|
||||
int start = 0;
|
||||
while (bytes[start] == 0x0) {
|
||||
start++;
|
||||
}
|
||||
|
||||
return Arrays.copyOfRange(bytes, start, bytes.length);
|
||||
}
|
||||
|
||||
private static int getElementSize(EllipticCurve curve) {
|
||||
int fieldSize = curve.getField().getFieldSize();
|
||||
return (fieldSize + 7) / 8;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.hierynomus.sshj.signature;
|
||||
|
||||
import net.i2p.crypto.eddsa.EdDSAPublicKey;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
|
||||
import net.schmizz.sshj.common.SSHRuntimeException;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Our own extension of the EdDSAPublicKey that comes from ECC-25519, as that class does not implement equality.
|
||||
* The code uses the equality of the keys as an indicator whether they're the same during host key verification.
|
||||
*/
|
||||
public class Ed25519PublicKey extends EdDSAPublicKey {
|
||||
|
||||
public Ed25519PublicKey(EdDSAPublicKeySpec spec) {
|
||||
super(spec);
|
||||
|
||||
EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable.getByName("ed25519-sha-512");
|
||||
if (!spec.getParams().getCurve().equals(ed25519.getCurve())) {
|
||||
throw new SSHRuntimeException("Cannot create Ed25519 Public Key from wrong spec");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof Ed25519PublicKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Ed25519PublicKey otherKey = (Ed25519PublicKey) other;
|
||||
return Arrays.equals(getAbyte(), otherKey.getAbyte());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getA().hashCode();
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.hierynomus.sshj.signature;
|
||||
|
||||
import net.i2p.crypto.eddsa.EdDSAEngine;
|
||||
import net.schmizz.sshj.common.Buffer;
|
||||
import net.schmizz.sshj.common.KeyType;
|
||||
import net.schmizz.sshj.common.SSHRuntimeException;
|
||||
import net.schmizz.sshj.signature.Signature;
|
||||
|
||||
import java.security.*;
|
||||
|
||||
public class SignatureEdDSA implements Signature {
|
||||
public static class Factory implements net.schmizz.sshj.common.Factory.Named<Signature> {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return KeyType.ED25519.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Signature create() {
|
||||
return new SignatureEdDSA();
|
||||
}
|
||||
}
|
||||
|
||||
final EdDSAEngine engine;
|
||||
|
||||
protected SignatureEdDSA() {
|
||||
try {
|
||||
engine = new EdDSAEngine(MessageDigest.getInstance("SHA-512"));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(PublicKey pubkey, PrivateKey prvkey) {
|
||||
try {
|
||||
if (pubkey != null) {
|
||||
engine.initVerify(pubkey);
|
||||
}
|
||||
|
||||
if (prvkey != null) {
|
||||
engine.initSign(prvkey);
|
||||
}
|
||||
} catch (InvalidKeyException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(byte[] H) {
|
||||
update(H, 0, H.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(byte[] H, int off, int len) {
|
||||
try {
|
||||
engine.update(H, off, len);
|
||||
} catch (SignatureException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] sign() {
|
||||
try {
|
||||
return engine.sign();
|
||||
} catch (SignatureException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encode(byte[] signature) {
|
||||
return signature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean verify(byte[] sig) {
|
||||
try {
|
||||
Buffer.PlainBuffer plainBuffer = new Buffer.PlainBuffer(sig);
|
||||
String algo = plainBuffer.readString();
|
||||
if (!"ssh-ed25519".equals(algo)) {
|
||||
throw new SSHRuntimeException("Expected 'ssh-ed25519' key algorithm, but was: " + algo);
|
||||
}
|
||||
byte[] bytes = plainBuffer.readBytes();
|
||||
return engine.verify(bytes);
|
||||
} catch (SignatureException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
} catch (Buffer.BufferException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.hierynomus.sshj.transport;
|
||||
|
||||
import net.schmizz.sshj.common.Buffer;
|
||||
import net.schmizz.sshj.common.ByteArrayUtils;
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
import net.schmizz.sshj.transport.TransportException;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class IdentificationStringParser {
|
||||
private final Logger log;
|
||||
private final Buffer.PlainBuffer buffer;
|
||||
|
||||
private byte[] EXPECTED_START_BYTES = new byte[] {'S', 'S', 'H', '-'};
|
||||
|
||||
public IdentificationStringParser(Buffer.PlainBuffer buffer) {
|
||||
this(buffer, LoggerFactory.DEFAULT);
|
||||
}
|
||||
|
||||
public IdentificationStringParser(Buffer.PlainBuffer buffer, LoggerFactory loggerFactory) {
|
||||
this.log = loggerFactory.getLogger(IdentificationStringParser.class);
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
public String parseIdentificationString() throws IOException {
|
||||
for (;;) {
|
||||
Buffer.PlainBuffer lineBuffer = new Buffer.PlainBuffer();
|
||||
int lineStartPos = buffer.rpos();
|
||||
for (;;) {
|
||||
if (buffer.available() == 0) {
|
||||
buffer.rpos(lineStartPos);
|
||||
return "";
|
||||
}
|
||||
byte b = buffer.readByte();
|
||||
lineBuffer.putByte(b);
|
||||
if (b == '\n') {
|
||||
if (checkForIdentification(lineBuffer)) {
|
||||
return readIdentification(lineBuffer);
|
||||
} else {
|
||||
logHeaderLine(lineBuffer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void logHeaderLine(Buffer.PlainBuffer lineBuffer) {
|
||||
|
||||
}
|
||||
|
||||
private String readIdentification(Buffer.PlainBuffer lineBuffer) throws Buffer.BufferException, TransportException {
|
||||
byte[] bytes = new byte[lineBuffer.available()];
|
||||
lineBuffer.readRawBytes(bytes);
|
||||
if (bytes.length > 255) {
|
||||
log.error("Incorrect identification String received, line was longer than expected: {}", new String(bytes));
|
||||
log.error("Just for good measure, bytes were: {}", ByteArrayUtils.printHex(bytes, 0, bytes.length));
|
||||
throw new TransportException("Incorrect identification: line too long: " + ByteArrayUtils.printHex(bytes, 0, bytes.length));
|
||||
}
|
||||
if (bytes[bytes.length - 2] != '\r') {
|
||||
String ident = new String(bytes, 0, bytes.length - 1);
|
||||
log.warn("Server identification has bad line ending, was expecting a '\\r\\n' however got: '{}' (hex: {})", (char) (bytes[bytes.length - 2] & 0xFF), Integer.toHexString(bytes[bytes.length - 2] & 0xFF));
|
||||
log.warn("Will treat the identification of this server '{}' leniently", ident);
|
||||
return ident;
|
||||
// log.error("Data received up til here was: {}", new String(bytes));
|
||||
// throw new TransportException("Incorrect identification: bad line ending: " + ByteArrayUtils.toHex(bytes, 0, bytes.length));
|
||||
}
|
||||
|
||||
// Strip off the \r\n
|
||||
return new String(bytes, 0, bytes.length - 2);
|
||||
}
|
||||
|
||||
private boolean checkForIdentification(Buffer.PlainBuffer lineBuffer) throws Buffer.BufferException {
|
||||
if (lineBuffer.available() < 4) {
|
||||
return false;
|
||||
}
|
||||
byte[] buf = new byte[4];
|
||||
lineBuffer.readRawBytes(buf);
|
||||
// Reset
|
||||
lineBuffer.rpos(0);
|
||||
return Arrays.equals(EXPECTED_START_BYTES, buf);
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.hierynomus.sshj.transport.cipher;
|
||||
|
||||
import net.schmizz.sshj.transport.cipher.BlockCipher;
|
||||
import net.schmizz.sshj.transport.cipher.Cipher;
|
||||
|
||||
/**
|
||||
* All BlockCiphers supported by SSH according to the following RFCs
|
||||
*
|
||||
* - https://tools.ietf.org/html/rfc4344#section-3.1
|
||||
* - https://tools.ietf.org/html/rfc4253#section-6.3
|
||||
*
|
||||
* TODO: https://tools.ietf.org/html/rfc5647
|
||||
*
|
||||
* Some of the Ciphers are still implemented in net.schmizz.sshj.transport.cipher.*. These are scheduled to be migrated to here.
|
||||
*/
|
||||
public class BlockCiphers {
|
||||
|
||||
public static final String COUNTER_MODE = "CTR";
|
||||
public static final String CIPHER_BLOCK_CHAINING_MODE = "CBC";
|
||||
|
||||
public static Factory BlowfishCTR() {
|
||||
return new Factory(8, 256, "blowfish-ctr", "Blowfish", COUNTER_MODE);
|
||||
}
|
||||
public static Factory Twofish128CTR() {
|
||||
return new Factory(16, 128, "twofish128-ctr", "Twofish", COUNTER_MODE);
|
||||
}
|
||||
public static Factory Twofish192CTR() {
|
||||
return new Factory(16, 192, "twofish192-ctr", "Twofish", COUNTER_MODE);
|
||||
}
|
||||
public static Factory Twofish256CTR() {
|
||||
return new Factory(16, 256, "twofish256-ctr", "Twofish", COUNTER_MODE);
|
||||
}
|
||||
public static Factory Twofish128CBC() {
|
||||
return new Factory(16, 128, "twofish128-cbc", "Twofish", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static Factory Twofish192CBC() {
|
||||
return new Factory(16, 192, "twofish192-cbc", "Twofish", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static Factory Twofish256CBC() {
|
||||
return new Factory(16, 256, "twofish256-cbc", "Twofish", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static Factory TwofishCBC() {
|
||||
return new Factory(16, 256, "twofish-cbc", "Twofish", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static Factory Serpent128CTR() {
|
||||
return new Factory(16, 128, "serpent128-ctr", "Serpent", COUNTER_MODE);
|
||||
}
|
||||
public static Factory Serpent192CTR() {
|
||||
return new Factory(16, 192, "serpent192-ctr", "Serpent", COUNTER_MODE);
|
||||
}
|
||||
public static Factory Serpent256CTR() {
|
||||
return new Factory(16, 256, "serpent256-ctr", "Serpent", COUNTER_MODE);
|
||||
}
|
||||
public static Factory Serpent128CBC() {
|
||||
return new Factory(16, 128, "serpent128-cbc", "Serpent", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static Factory Serpent192CBC() {
|
||||
return new Factory(16, 192, "serpent192-cbc", "Serpent", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static Factory Serpent256CBC() {
|
||||
return new Factory(16, 256, "serpent256-cbc", "Serpent", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static Factory IDEACTR() {
|
||||
return new Factory(8, 128, "idea-ctr", "IDEA", COUNTER_MODE);
|
||||
}
|
||||
public static Factory IDEACBC() {
|
||||
return new Factory(8, 128, "idea-cbc", "IDEA", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static Factory Cast128CTR() {
|
||||
return new Factory(8, 128, "cast128-ctr", "CAST5", COUNTER_MODE);
|
||||
}
|
||||
public static Factory Cast128CBC() {
|
||||
return new Factory(8, 128, "cast128-cbc", "CAST5", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static Factory TripleDESCTR() {
|
||||
return new Factory(8, 192, "3des-ctr", "DESede", COUNTER_MODE);
|
||||
}
|
||||
|
||||
/** Named factory for BlockCipher */
|
||||
public static class Factory
|
||||
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
|
||||
|
||||
private int keysize;
|
||||
private String cipher;
|
||||
private String mode;
|
||||
private String name;
|
||||
private int ivsize;
|
||||
|
||||
/**
|
||||
* @param ivsize
|
||||
* @param keysize The keysize used in bits.
|
||||
* @param name
|
||||
* @param cipher
|
||||
* @param mode
|
||||
*/
|
||||
public Factory(int ivsize, int keysize, String name, String cipher, String mode) {
|
||||
this.name = name;
|
||||
this.keysize = keysize;
|
||||
this.cipher = cipher;
|
||||
this.mode = mode;
|
||||
this.ivsize = ivsize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cipher create() {
|
||||
return new BlockCipher(ivsize, keysize / 8, cipher, cipher + "/" + mode + "/NoPadding");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.hierynomus.sshj.transport.cipher;
|
||||
|
||||
import static com.hierynomus.sshj.transport.cipher.BlockCiphers.CIPHER_BLOCK_CHAINING_MODE;
|
||||
import static com.hierynomus.sshj.transport.cipher.BlockCiphers.COUNTER_MODE;
|
||||
|
||||
/**
|
||||
* Set of Block Ciphers that are (not yet) part of any of the official RFCs for SSH, but
|
||||
* that are either supported by other SSH implementations, or are being pushed for to be
|
||||
* included in a new RFC.
|
||||
*
|
||||
* - http://tools.ietf.org/id/draft-kanno-secsh-camellia-01.txt
|
||||
*/
|
||||
public class ExtendedBlockCiphers {
|
||||
public static BlockCiphers.Factory Camellia128CTR() {
|
||||
return new BlockCiphers.Factory(16, 128, "camellia128-ctr", "Camellia", COUNTER_MODE);
|
||||
}
|
||||
public static BlockCiphers.Factory Camellia128CTROpenSSHOrg() {
|
||||
return new BlockCiphers.Factory(16, 128, "camellia128-ctr@openssh.org", "Camellia", COUNTER_MODE);
|
||||
}
|
||||
public static BlockCiphers.Factory Camellia192CTR() {
|
||||
return new BlockCiphers.Factory(16, 192, "camellia192-ctr", "Camellia", COUNTER_MODE);
|
||||
}
|
||||
public static BlockCiphers.Factory Camellia192CTROpenSSHOrg() {
|
||||
return new BlockCiphers.Factory(16, 192, "camellia192-ctr@openssh.org", "Camellia", COUNTER_MODE);
|
||||
}
|
||||
public static BlockCiphers.Factory Camellia256CTR() {
|
||||
return new BlockCiphers.Factory(16, 256, "camellia256-ctr", "Camellia", COUNTER_MODE);
|
||||
}
|
||||
public static BlockCiphers.Factory Camellia256CTROpenSSHOrg() {
|
||||
return new BlockCiphers.Factory(16, 256, "camellia256-ctr@openssh.org", "Camellia", COUNTER_MODE);
|
||||
}
|
||||
public static BlockCiphers.Factory Camellia128CBC() {
|
||||
return new BlockCiphers.Factory(16, 128, "camellia128-cbc", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static BlockCiphers.Factory Camellia128CBCOpenSSHOrg() {
|
||||
return new BlockCiphers.Factory(16, 128, "camellia128-cbc@openssh.org", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static BlockCiphers.Factory Camellia192CBC() {
|
||||
return new BlockCiphers.Factory(16, 192, "camellia192-cbc", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static BlockCiphers.Factory Camellia192CBCOpenSSHOrg() {
|
||||
return new BlockCiphers.Factory(16, 192, "camellia192-cbc@openssh.org", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static BlockCiphers.Factory Camellia256CBC() {
|
||||
return new BlockCiphers.Factory(16, 256, "camellia256-cbc", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
public static BlockCiphers.Factory Camellia256CBCOpenSSHOrg() {
|
||||
return new BlockCiphers.Factory(16, 256, "camellia256-cbc@openssh.org", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.hierynomus.sshj.transport.cipher;
|
||||
|
||||
import net.schmizz.sshj.transport.cipher.BaseCipher;
|
||||
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
public class StreamCipher extends BaseCipher {
|
||||
|
||||
public StreamCipher(int bsize, String algorithm, String transformation) {
|
||||
super(0, bsize, algorithm, transformation);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initCipher(javax.crypto.Cipher cipher, Mode mode, byte[] key, byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||
cipher.init(getMode(mode), getKeySpec(key), new SecureRandom());
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.hierynomus.sshj.transport.cipher;
|
||||
|
||||
import net.schmizz.sshj.transport.cipher.Cipher;
|
||||
|
||||
/**
|
||||
* Implementations of the Stream Ciphers that are defined in the RFCs
|
||||
*
|
||||
* - https://tools.ietf.org/html/rfc4253#section-6.3
|
||||
* - https://tools.ietf.org/html/rfc4345
|
||||
*/
|
||||
public class StreamCiphers {
|
||||
|
||||
public static Factory Arcfour() {
|
||||
return new Factory(128, "arcfour", "ARCFOUR", "ECB");
|
||||
}
|
||||
public static Factory Arcfour128() {
|
||||
return new Factory(128, "arcfour128", "RC4", "ECB");
|
||||
}
|
||||
public static Factory Arcfour256() {
|
||||
return new Factory(256, "arcfour256", "RC4", "ECB");
|
||||
}
|
||||
|
||||
/** Named factory for BlockCipher */
|
||||
public static class Factory
|
||||
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
|
||||
|
||||
private int keysize;
|
||||
private String cipher;
|
||||
private String mode;
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* @param keysize The keysize used in bits.
|
||||
* @param name
|
||||
* @param cipher
|
||||
* @param mode
|
||||
*/
|
||||
public Factory(int keysize, String name, String cipher, String mode) {
|
||||
this.name = name;
|
||||
this.keysize = keysize;
|
||||
this.cipher = cipher;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cipher create() {
|
||||
return new StreamCipher(keysize / 8, cipher, cipher + "/" + mode + "/NoPadding");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,918 +0,0 @@
|
||||
/* Ported from C to Java by Dmitry Skiba [sahn0], 23/02/08.
|
||||
* Original: http://cds.xs4all.nl:8081/ecdh/
|
||||
*/
|
||||
/* Generic 64-bit integer implementation of Curve25519 ECDH
|
||||
* Written by Matthijs van Duin, 200608242056
|
||||
* Public domain.
|
||||
*
|
||||
* Based on work by Daniel J Bernstein, http://cr.yp.to/ecdh.html
|
||||
*/
|
||||
package djb;
|
||||
|
||||
public class Curve25519 {
|
||||
|
||||
/* key size */
|
||||
public static final int KEY_SIZE = 32;
|
||||
|
||||
/* 0 */
|
||||
public static final byte[] ZERO = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/* the prime 2^255-19 */
|
||||
public static final byte[] PRIME = {
|
||||
(byte)237, (byte)255, (byte)255, (byte)255,
|
||||
(byte)255, (byte)255, (byte)255, (byte)255,
|
||||
(byte)255, (byte)255, (byte)255, (byte)255,
|
||||
(byte)255, (byte)255, (byte)255, (byte)255,
|
||||
(byte)255, (byte)255, (byte)255, (byte)255,
|
||||
(byte)255, (byte)255, (byte)255, (byte)255,
|
||||
(byte)255, (byte)255, (byte)255, (byte)255,
|
||||
(byte)255, (byte)255, (byte)255, (byte)127
|
||||
};
|
||||
|
||||
/* group order (a prime near 2^252+2^124) */
|
||||
public static final byte[] ORDER = {
|
||||
(byte)237, (byte)211, (byte)245, (byte)92,
|
||||
(byte)26, (byte)99, (byte)18, (byte)88,
|
||||
(byte)214, (byte)156, (byte)247, (byte)162,
|
||||
(byte)222, (byte)249, (byte)222, (byte)20,
|
||||
(byte)0, (byte)0, (byte)0, (byte)0,
|
||||
(byte)0, (byte)0, (byte)0, (byte)0,
|
||||
(byte)0, (byte)0, (byte)0, (byte)0,
|
||||
(byte)0, (byte)0, (byte)0, (byte)16
|
||||
};
|
||||
|
||||
/********* KEY AGREEMENT *********/
|
||||
|
||||
/* Private key clamping
|
||||
* k [out] your private key for key agreement
|
||||
* k [in] 32 random bytes
|
||||
*/
|
||||
public static final void clamp(byte[] k) {
|
||||
k[31] &= 0x7F;
|
||||
k[31] |= 0x40;
|
||||
k[ 0] &= 0xF8;
|
||||
}
|
||||
|
||||
/* Key-pair generation
|
||||
* P [out] your public key
|
||||
* s [out] your private key for signing
|
||||
* k [out] your private key for key agreement
|
||||
* k [in] 32 random bytes
|
||||
* s may be NULL if you don't care
|
||||
*
|
||||
* WARNING: if s is not NULL, this function has data-dependent timing */
|
||||
public static final void keygen(byte[] P, byte[] s, byte[] k) {
|
||||
clamp(k);
|
||||
core(P, s, k, null);
|
||||
}
|
||||
|
||||
/* Key agreement
|
||||
* Z [out] shared secret (needs hashing before use)
|
||||
* k [in] your private key for key agreement
|
||||
* P [in] peer's public key
|
||||
*/
|
||||
public static final void curve(byte[] Z, byte[] k, byte[] P) {
|
||||
core(Z, null, k, P);
|
||||
}
|
||||
|
||||
/********* DIGITAL SIGNATURES *********/
|
||||
|
||||
/* deterministic EC-KCDSA
|
||||
*
|
||||
* s is the private key for signing
|
||||
* P is the corresponding public key
|
||||
* Z is the context data (signer public key or certificate, etc)
|
||||
*
|
||||
* signing:
|
||||
*
|
||||
* m = hash(Z, message)
|
||||
* x = hash(m, s)
|
||||
* keygen25519(Y, NULL, x);
|
||||
* r = hash(Y);
|
||||
* h = m XOR r
|
||||
* sign25519(v, h, x, s);
|
||||
*
|
||||
* output (v,r) as the signature
|
||||
*
|
||||
* verification:
|
||||
*
|
||||
* m = hash(Z, message);
|
||||
* h = m XOR r
|
||||
* verify25519(Y, v, h, P)
|
||||
*
|
||||
* confirm r == hash(Y)
|
||||
*
|
||||
* It would seem to me that it would be simpler to have the signer directly do
|
||||
* h = hash(m, Y) and send that to the recipient instead of r, who can verify
|
||||
* the signature by checking h == hash(m, Y). If there are any problems with
|
||||
* such a scheme, please let me know.
|
||||
*
|
||||
* Also, EC-KCDSA (like most DS algorithms) picks x random, which is a waste of
|
||||
* perfectly good entropy, but does allow Y to be calculated in advance of (or
|
||||
* parallel to) hashing the message.
|
||||
*/
|
||||
|
||||
/* Signature generation primitive, calculates (x-h)s mod q
|
||||
* v [out] signature value
|
||||
* h [in] signature hash (of message, signature pub key, and context data)
|
||||
* x [in] signature private key
|
||||
* s [in] private key for signing
|
||||
* returns true on success, false on failure (use different x or h)
|
||||
*/
|
||||
public static final boolean sign(byte[] v, byte[] h, byte[] x, byte[] s) {
|
||||
// v = (x - h) s mod q
|
||||
int w, i;
|
||||
byte[] h1 = new byte[32], x1 = new byte[32];
|
||||
byte[] tmp1 = new byte[64];
|
||||
byte[] tmp2 = new byte[64];
|
||||
|
||||
// Don't clobber the arguments, be nice!
|
||||
cpy32(h1, h);
|
||||
cpy32(x1, x);
|
||||
|
||||
// Reduce modulo group order
|
||||
byte[] tmp3=new byte[32];
|
||||
divmod(tmp3, h1, 32, ORDER, 32);
|
||||
divmod(tmp3, x1, 32, ORDER, 32);
|
||||
|
||||
// v = x1 - h1
|
||||
// If v is negative, add the group order to it to become positive.
|
||||
// If v was already positive we don't have to worry about overflow
|
||||
// when adding the order because v < ORDER and 2*ORDER < 2^256
|
||||
mula_small(v, x1, 0, h1, 32, -1);
|
||||
mula_small(v, v , 0, ORDER, 32, 1);
|
||||
|
||||
// tmp1 = (x-h)*s mod q
|
||||
mula32(tmp1, v, s, 32, 1);
|
||||
divmod(tmp2, tmp1, 64, ORDER, 32);
|
||||
|
||||
for (w = 0, i = 0; i < 32; i++)
|
||||
w |= v[i] = tmp1[i];
|
||||
return w != 0;
|
||||
}
|
||||
|
||||
/* Signature verification primitive, calculates Y = vP + hG
|
||||
* Y [out] signature public key
|
||||
* v [in] signature value
|
||||
* h [in] signature hash
|
||||
* P [in] public key
|
||||
*/
|
||||
public static final void verify(byte[] Y, byte[] v, byte[] h, byte[] P) {
|
||||
/* Y = v abs(P) + h G */
|
||||
byte[] d=new byte[32];
|
||||
long10[]
|
||||
p=new long10[]{new long10(),new long10()},
|
||||
s=new long10[]{new long10(),new long10()},
|
||||
yx=new long10[]{new long10(),new long10(),new long10()},
|
||||
yz=new long10[]{new long10(),new long10(),new long10()},
|
||||
t1=new long10[]{new long10(),new long10(),new long10()},
|
||||
t2=new long10[]{new long10(),new long10(),new long10()};
|
||||
|
||||
int vi = 0, hi = 0, di = 0, nvh=0, i, j, k;
|
||||
|
||||
/* set p[0] to G and p[1] to P */
|
||||
|
||||
set(p[0], 9);
|
||||
unpack(p[1], P);
|
||||
|
||||
/* set s[0] to P+G and s[1] to P-G */
|
||||
|
||||
/* s[0] = (Py^2 + Gy^2 - 2 Py Gy)/(Px - Gx)^2 - Px - Gx - 486662 */
|
||||
/* s[1] = (Py^2 + Gy^2 + 2 Py Gy)/(Px - Gx)^2 - Px - Gx - 486662 */
|
||||
|
||||
x_to_y2(t1[0], t2[0], p[1]); /* t2[0] = Py^2 */
|
||||
sqrt(t1[0], t2[0]); /* t1[0] = Py or -Py */
|
||||
j = is_negative(t1[0]); /* ... check which */
|
||||
t2[0]._0 += 39420360; /* t2[0] = Py^2 + Gy^2 */
|
||||
mul(t2[1], BASE_2Y, t1[0]);/* t2[1] = 2 Py Gy or -2 Py Gy */
|
||||
sub(t1[j], t2[0], t2[1]); /* t1[0] = Py^2 + Gy^2 - 2 Py Gy */
|
||||
add(t1[1-j], t2[0], t2[1]);/* t1[1] = Py^2 + Gy^2 + 2 Py Gy */
|
||||
cpy(t2[0], p[1]); /* t2[0] = Px */
|
||||
t2[0]._0 -= 9; /* t2[0] = Px - Gx */
|
||||
sqr(t2[1], t2[0]); /* t2[1] = (Px - Gx)^2 */
|
||||
recip(t2[0], t2[1], 0); /* t2[0] = 1/(Px - Gx)^2 */
|
||||
mul(s[0], t1[0], t2[0]); /* s[0] = t1[0]/(Px - Gx)^2 */
|
||||
sub(s[0], s[0], p[1]); /* s[0] = t1[0]/(Px - Gx)^2 - Px */
|
||||
s[0]._0 -= 9 + 486662; /* s[0] = X(P+G) */
|
||||
mul(s[1], t1[1], t2[0]); /* s[1] = t1[1]/(Px - Gx)^2 */
|
||||
sub(s[1], s[1], p[1]); /* s[1] = t1[1]/(Px - Gx)^2 - Px */
|
||||
s[1]._0 -= 9 + 486662; /* s[1] = X(P-G) */
|
||||
mul_small(s[0], s[0], 1); /* reduce s[0] */
|
||||
mul_small(s[1], s[1], 1); /* reduce s[1] */
|
||||
|
||||
|
||||
/* prepare the chain */
|
||||
for (i = 0; i < 32; i++) {
|
||||
vi = (vi >> 8) ^ (v[i] & 0xFF) ^ ((v[i] & 0xFF) << 1);
|
||||
hi = (hi >> 8) ^ (h[i] & 0xFF) ^ ((h[i] & 0xFF) << 1);
|
||||
nvh = ~(vi ^ hi);
|
||||
di = (nvh & (di & 0x80) >> 7) ^ vi;
|
||||
di ^= nvh & (di & 0x01) << 1;
|
||||
di ^= nvh & (di & 0x02) << 1;
|
||||
di ^= nvh & (di & 0x04) << 1;
|
||||
di ^= nvh & (di & 0x08) << 1;
|
||||
di ^= nvh & (di & 0x10) << 1;
|
||||
di ^= nvh & (di & 0x20) << 1;
|
||||
di ^= nvh & (di & 0x40) << 1;
|
||||
d[i] = (byte)di;
|
||||
}
|
||||
|
||||
di = ((nvh & (di & 0x80) << 1) ^ vi) >> 8;
|
||||
|
||||
/* initialize state */
|
||||
set(yx[0], 1);
|
||||
cpy(yx[1], p[di]);
|
||||
cpy(yx[2], s[0]);
|
||||
set(yz[0], 0);
|
||||
set(yz[1], 1);
|
||||
set(yz[2], 1);
|
||||
|
||||
/* y[0] is (even)P + (even)G
|
||||
* y[1] is (even)P + (odd)G if current d-bit is 0
|
||||
* y[1] is (odd)P + (even)G if current d-bit is 1
|
||||
* y[2] is (odd)P + (odd)G
|
||||
*/
|
||||
|
||||
vi = 0;
|
||||
hi = 0;
|
||||
|
||||
/* and go for it! */
|
||||
for (i = 32; i--!=0; ) {
|
||||
vi = (vi << 8) | (v[i] & 0xFF);
|
||||
hi = (hi << 8) | (h[i] & 0xFF);
|
||||
di = (di << 8) | (d[i] & 0xFF);
|
||||
|
||||
for (j = 8; j--!=0; ) {
|
||||
mont_prep(t1[0], t2[0], yx[0], yz[0]);
|
||||
mont_prep(t1[1], t2[1], yx[1], yz[1]);
|
||||
mont_prep(t1[2], t2[2], yx[2], yz[2]);
|
||||
|
||||
k = ((vi ^ vi >> 1) >> j & 1)
|
||||
+ ((hi ^ hi >> 1) >> j & 1);
|
||||
mont_dbl(yx[2], yz[2], t1[k], t2[k], yx[0], yz[0]);
|
||||
|
||||
k = (di >> j & 2) ^ ((di >> j & 1) << 1);
|
||||
mont_add(t1[1], t2[1], t1[k], t2[k], yx[1], yz[1],
|
||||
p[di >> j & 1]);
|
||||
|
||||
mont_add(t1[2], t2[2], t1[0], t2[0], yx[2], yz[2],
|
||||
s[((vi ^ hi) >> j & 2) >> 1]);
|
||||
}
|
||||
}
|
||||
|
||||
k = (vi & 1) + (hi & 1);
|
||||
recip(t1[0], yz[k], 0);
|
||||
mul(t1[1], yx[k], t1[0]);
|
||||
|
||||
pack(t1[1], Y);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* sahn0:
|
||||
* Using this class instead of long[10] to avoid bounds checks. */
|
||||
private static final class long10 {
|
||||
public long10() {}
|
||||
public long10(
|
||||
long _0, long _1, long _2, long _3, long _4,
|
||||
long _5, long _6, long _7, long _8, long _9)
|
||||
{
|
||||
this._0=_0; this._1=_1; this._2=_2;
|
||||
this._3=_3; this._4=_4; this._5=_5;
|
||||
this._6=_6; this._7=_7; this._8=_8;
|
||||
this._9=_9;
|
||||
}
|
||||
public long _0,_1,_2,_3,_4,_5,_6,_7,_8,_9;
|
||||
}
|
||||
|
||||
/********************* radix 2^8 math *********************/
|
||||
|
||||
private static final void cpy32(byte[] d, byte[] s) {
|
||||
int i;
|
||||
for (i = 0; i < 32; i++)
|
||||
d[i] = s[i];
|
||||
}
|
||||
|
||||
/* p[m..n+m-1] = q[m..n+m-1] + z * x */
|
||||
/* n is the size of x */
|
||||
/* n+m is the size of p and q */
|
||||
private static final int mula_small(byte[] p,byte[] q,int m,byte[] x,int n,int z) {
|
||||
int v=0;
|
||||
for (int i=0;i<n;++i) {
|
||||
v+=(q[i+m] & 0xFF)+z*(x[i] & 0xFF);
|
||||
p[i+m]=(byte)v;
|
||||
v>>=8;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/* p += x * y * z where z is a small integer
|
||||
* x is size 32, y is size t, p is size 32+t
|
||||
* y is allowed to overlap with p+32 if you don't care about the upper half */
|
||||
private static final int mula32(byte[] p, byte[] x, byte[] y, int t, int z) {
|
||||
final int n = 31;
|
||||
int w = 0;
|
||||
int i = 0;
|
||||
for (; i < t; i++) {
|
||||
int zy = z * (y[i] & 0xFF);
|
||||
w += mula_small(p, p, i, x, n, zy) +
|
||||
(p[i+n] & 0xFF) + zy * (x[n] & 0xFF);
|
||||
p[i+n] = (byte)w;
|
||||
w >>= 8;
|
||||
}
|
||||
p[i+n] = (byte)(w + (p[i+n] & 0xFF));
|
||||
return w >> 8;
|
||||
}
|
||||
|
||||
/* divide r (size n) by d (size t), returning quotient q and remainder r
|
||||
* quotient is size n-t+1, remainder is size t
|
||||
* requires t > 0 && d[t-1] != 0
|
||||
* requires that r[-1] and d[-1] are valid memory locations
|
||||
* q may overlap with r+t */
|
||||
private static final void divmod(byte[] q, byte[] r, int n, byte[] d, int t) {
|
||||
int rn = 0;
|
||||
int dt = ((d[t-1] & 0xFF) << 8);
|
||||
if (t>1) {
|
||||
dt |= (d[t-2] & 0xFF);
|
||||
}
|
||||
while (n-- >= t) {
|
||||
int z = (rn << 16) | ((r[n] & 0xFF) << 8);
|
||||
if (n>0) {
|
||||
z |= (r[n-1] & 0xFF);
|
||||
}
|
||||
z/=dt;
|
||||
rn += mula_small(r,r, n-t+1, d, t, -z);
|
||||
q[n-t+1] = (byte)((z + rn) & 0xFF); /* rn is 0 or -1 (underflow) */
|
||||
mula_small(r,r, n-t+1, d, t, -rn);
|
||||
rn = (r[n] & 0xFF);
|
||||
r[n] = 0;
|
||||
}
|
||||
r[t-1] = (byte)rn;
|
||||
}
|
||||
|
||||
private static final int numsize(byte[] x,int n) {
|
||||
while (n--!=0 && x[n]==0)
|
||||
;
|
||||
return n+1;
|
||||
}
|
||||
|
||||
/* Returns x if a contains the gcd, y if b.
|
||||
* Also, the returned buffer contains the inverse of a mod b,
|
||||
* as 32-byte signed.
|
||||
* x and y must have 64 bytes space for temporary use.
|
||||
* requires that a[-1] and b[-1] are valid memory locations */
|
||||
private static final byte[] egcd32(byte[] x,byte[] y,byte[] a,byte[] b) {
|
||||
int an, bn = 32, qn, i;
|
||||
for (i = 0; i < 32; i++)
|
||||
x[i] = y[i] = 0;
|
||||
x[0] = 1;
|
||||
an = numsize(a, 32);
|
||||
if (an==0)
|
||||
return y; /* division by zero */
|
||||
byte[] temp=new byte[32];
|
||||
while (true) {
|
||||
qn = bn - an + 1;
|
||||
divmod(temp, b, bn, a, an);
|
||||
bn = numsize(b, bn);
|
||||
if (bn==0)
|
||||
return x;
|
||||
mula32(y, x, temp, qn, -1);
|
||||
|
||||
qn = an - bn + 1;
|
||||
divmod(temp, a, an, b, bn);
|
||||
an = numsize(a, an);
|
||||
if (an==0)
|
||||
return y;
|
||||
mula32(x, y, temp, qn, -1);
|
||||
}
|
||||
}
|
||||
|
||||
/********************* radix 2^25.5 GF(2^255-19) math *********************/
|
||||
|
||||
private static final int P25=33554431; /* (1 << 25) - 1 */
|
||||
private static final int P26=67108863; /* (1 << 26) - 1 */
|
||||
|
||||
/* Convert to internal format from little-endian byte format */
|
||||
private static final void unpack(long10 x,byte[] m) {
|
||||
x._0 = ((m[0] & 0xFF)) | ((m[1] & 0xFF))<<8 |
|
||||
(m[2] & 0xFF)<<16 | ((m[3] & 0xFF)& 3)<<24;
|
||||
x._1 = ((m[3] & 0xFF)&~ 3)>>2 | (m[4] & 0xFF)<<6 |
|
||||
(m[5] & 0xFF)<<14 | ((m[6] & 0xFF)& 7)<<22;
|
||||
x._2 = ((m[6] & 0xFF)&~ 7)>>3 | (m[7] & 0xFF)<<5 |
|
||||
(m[8] & 0xFF)<<13 | ((m[9] & 0xFF)&31)<<21;
|
||||
x._3 = ((m[9] & 0xFF)&~31)>>5 | (m[10] & 0xFF)<<3 |
|
||||
(m[11] & 0xFF)<<11 | ((m[12] & 0xFF)&63)<<19;
|
||||
x._4 = ((m[12] & 0xFF)&~63)>>6 | (m[13] & 0xFF)<<2 |
|
||||
(m[14] & 0xFF)<<10 | (m[15] & 0xFF) <<18;
|
||||
x._5 = (m[16] & 0xFF) | (m[17] & 0xFF)<<8 |
|
||||
(m[18] & 0xFF)<<16 | ((m[19] & 0xFF)& 1)<<24;
|
||||
x._6 = ((m[19] & 0xFF)&~ 1)>>1 | (m[20] & 0xFF)<<7 |
|
||||
(m[21] & 0xFF)<<15 | ((m[22] & 0xFF)& 7)<<23;
|
||||
x._7 = ((m[22] & 0xFF)&~ 7)>>3 | (m[23] & 0xFF)<<5 |
|
||||
(m[24] & 0xFF)<<13 | ((m[25] & 0xFF)&15)<<21;
|
||||
x._8 = ((m[25] & 0xFF)&~15)>>4 | (m[26] & 0xFF)<<4 |
|
||||
(m[27] & 0xFF)<<12 | ((m[28] & 0xFF)&63)<<20;
|
||||
x._9 = ((m[28] & 0xFF)&~63)>>6 | (m[29] & 0xFF)<<2 |
|
||||
(m[30] & 0xFF)<<10 | (m[31] & 0xFF) <<18;
|
||||
}
|
||||
|
||||
/* Check if reduced-form input >= 2^255-19 */
|
||||
private static final boolean is_overflow(long10 x) {
|
||||
return (
|
||||
((x._0 > P26-19)) &&
|
||||
((x._1 & x._3 & x._5 & x._7 & x._9) == P25) &&
|
||||
((x._2 & x._4 & x._6 & x._8) == P26)
|
||||
) || (x._9 > P25);
|
||||
}
|
||||
|
||||
/* Convert from internal format to little-endian byte format. The
|
||||
* number must be in a reduced form which is output by the following ops:
|
||||
* unpack, mul, sqr
|
||||
* set -- if input in range 0 .. P25
|
||||
* If you're unsure if the number is reduced, first multiply it by 1. */
|
||||
private static final void pack(long10 x,byte[] m) {
|
||||
int ld = 0, ud = 0;
|
||||
long t;
|
||||
ld = (is_overflow(x)?1:0) - ((x._9 < 0)?1:0);
|
||||
ud = ld * -(P25+1);
|
||||
ld *= 19;
|
||||
t = ld + x._0 + (x._1 << 26);
|
||||
m[ 0] = (byte)t;
|
||||
m[ 1] = (byte)(t >> 8);
|
||||
m[ 2] = (byte)(t >> 16);
|
||||
m[ 3] = (byte)(t >> 24);
|
||||
t = (t >> 32) + (x._2 << 19);
|
||||
m[ 4] = (byte)t;
|
||||
m[ 5] = (byte)(t >> 8);
|
||||
m[ 6] = (byte)(t >> 16);
|
||||
m[ 7] = (byte)(t >> 24);
|
||||
t = (t >> 32) + (x._3 << 13);
|
||||
m[ 8] = (byte)t;
|
||||
m[ 9] = (byte)(t >> 8);
|
||||
m[10] = (byte)(t >> 16);
|
||||
m[11] = (byte)(t >> 24);
|
||||
t = (t >> 32) + (x._4 << 6);
|
||||
m[12] = (byte)t;
|
||||
m[13] = (byte)(t >> 8);
|
||||
m[14] = (byte)(t >> 16);
|
||||
m[15] = (byte)(t >> 24);
|
||||
t = (t >> 32) + x._5 + (x._6 << 25);
|
||||
m[16] = (byte)t;
|
||||
m[17] = (byte)(t >> 8);
|
||||
m[18] = (byte)(t >> 16);
|
||||
m[19] = (byte)(t >> 24);
|
||||
t = (t >> 32) + (x._7 << 19);
|
||||
m[20] = (byte)t;
|
||||
m[21] = (byte)(t >> 8);
|
||||
m[22] = (byte)(t >> 16);
|
||||
m[23] = (byte)(t >> 24);
|
||||
t = (t >> 32) + (x._8 << 12);
|
||||
m[24] = (byte)t;
|
||||
m[25] = (byte)(t >> 8);
|
||||
m[26] = (byte)(t >> 16);
|
||||
m[27] = (byte)(t >> 24);
|
||||
t = (t >> 32) + ((x._9 + ud) << 6);
|
||||
m[28] = (byte)t;
|
||||
m[29] = (byte)(t >> 8);
|
||||
m[30] = (byte)(t >> 16);
|
||||
m[31] = (byte)(t >> 24);
|
||||
}
|
||||
|
||||
/* Copy a number */
|
||||
private static final void cpy(long10 out, long10 in) {
|
||||
out._0=in._0; out._1=in._1;
|
||||
out._2=in._2; out._3=in._3;
|
||||
out._4=in._4; out._5=in._5;
|
||||
out._6=in._6; out._7=in._7;
|
||||
out._8=in._8; out._9=in._9;
|
||||
}
|
||||
|
||||
/* Set a number to value, which must be in range -185861411 .. 185861411 */
|
||||
private static final void set(long10 out, int in) {
|
||||
out._0=in; out._1=0;
|
||||
out._2=0; out._3=0;
|
||||
out._4=0; out._5=0;
|
||||
out._6=0; out._7=0;
|
||||
out._8=0; out._9=0;
|
||||
}
|
||||
|
||||
/* Add/subtract two numbers. The inputs must be in reduced form, and the
|
||||
* output isn't, so to do another addition or subtraction on the output,
|
||||
* first multiply it by one to reduce it. */
|
||||
private static final void add(long10 xy, long10 x, long10 y) {
|
||||
xy._0 = x._0 + y._0; xy._1 = x._1 + y._1;
|
||||
xy._2 = x._2 + y._2; xy._3 = x._3 + y._3;
|
||||
xy._4 = x._4 + y._4; xy._5 = x._5 + y._5;
|
||||
xy._6 = x._6 + y._6; xy._7 = x._7 + y._7;
|
||||
xy._8 = x._8 + y._8; xy._9 = x._9 + y._9;
|
||||
}
|
||||
private static final void sub(long10 xy, long10 x, long10 y) {
|
||||
xy._0 = x._0 - y._0; xy._1 = x._1 - y._1;
|
||||
xy._2 = x._2 - y._2; xy._3 = x._3 - y._3;
|
||||
xy._4 = x._4 - y._4; xy._5 = x._5 - y._5;
|
||||
xy._6 = x._6 - y._6; xy._7 = x._7 - y._7;
|
||||
xy._8 = x._8 - y._8; xy._9 = x._9 - y._9;
|
||||
}
|
||||
|
||||
/* Multiply a number by a small integer in range -185861411 .. 185861411.
|
||||
* The output is in reduced form, the input x need not be. x and xy may point
|
||||
* to the same buffer. */
|
||||
private static final long10 mul_small(long10 xy, long10 x, long y) {
|
||||
long t;
|
||||
t = (x._8*y);
|
||||
xy._8 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + (x._9*y);
|
||||
xy._9 = (t & ((1 << 25) - 1));
|
||||
t = 19 * (t >> 25) + (x._0*y);
|
||||
xy._0 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + (x._1*y);
|
||||
xy._1 = (t & ((1 << 25) - 1));
|
||||
t = (t >> 25) + (x._2*y);
|
||||
xy._2 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + (x._3*y);
|
||||
xy._3 = (t & ((1 << 25) - 1));
|
||||
t = (t >> 25) + (x._4*y);
|
||||
xy._4 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + (x._5*y);
|
||||
xy._5 = (t & ((1 << 25) - 1));
|
||||
t = (t >> 25) + (x._6*y);
|
||||
xy._6 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + (x._7*y);
|
||||
xy._7 = (t & ((1 << 25) - 1));
|
||||
t = (t >> 25) + xy._8;
|
||||
xy._8 = (t & ((1 << 26) - 1));
|
||||
xy._9 += (t >> 26);
|
||||
return xy;
|
||||
}
|
||||
|
||||
/* Multiply two numbers. The output is in reduced form, the inputs need not
|
||||
* be. */
|
||||
private static final long10 mul(long10 xy, long10 x, long10 y) {
|
||||
/* sahn0:
|
||||
* Using local variables to avoid class access.
|
||||
* This seem to improve performance a bit...
|
||||
*/
|
||||
long
|
||||
x_0=x._0,x_1=x._1,x_2=x._2,x_3=x._3,x_4=x._4,
|
||||
x_5=x._5,x_6=x._6,x_7=x._7,x_8=x._8,x_9=x._9;
|
||||
long
|
||||
y_0=y._0,y_1=y._1,y_2=y._2,y_3=y._3,y_4=y._4,
|
||||
y_5=y._5,y_6=y._6,y_7=y._7,y_8=y._8,y_9=y._9;
|
||||
long t;
|
||||
t = (x_0*y_8) + (x_2*y_6) + (x_4*y_4) + (x_6*y_2) +
|
||||
(x_8*y_0) + 2 * ((x_1*y_7) + (x_3*y_5) +
|
||||
(x_5*y_3) + (x_7*y_1)) + 38 *
|
||||
(x_9*y_9);
|
||||
xy._8 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + (x_0*y_9) + (x_1*y_8) + (x_2*y_7) +
|
||||
(x_3*y_6) + (x_4*y_5) + (x_5*y_4) +
|
||||
(x_6*y_3) + (x_7*y_2) + (x_8*y_1) +
|
||||
(x_9*y_0);
|
||||
xy._9 = (t & ((1 << 25) - 1));
|
||||
t = (x_0*y_0) + 19 * ((t >> 25) + (x_2*y_8) + (x_4*y_6)
|
||||
+ (x_6*y_4) + (x_8*y_2)) + 38 *
|
||||
((x_1*y_9) + (x_3*y_7) + (x_5*y_5) +
|
||||
(x_7*y_3) + (x_9*y_1));
|
||||
xy._0 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + (x_0*y_1) + (x_1*y_0) + 19 * ((x_2*y_9)
|
||||
+ (x_3*y_8) + (x_4*y_7) + (x_5*y_6) +
|
||||
(x_6*y_5) + (x_7*y_4) + (x_8*y_3) +
|
||||
(x_9*y_2));
|
||||
xy._1 = (t & ((1 << 25) - 1));
|
||||
t = (t >> 25) + (x_0*y_2) + (x_2*y_0) + 19 * ((x_4*y_8)
|
||||
+ (x_6*y_6) + (x_8*y_4)) + 2 * (x_1*y_1)
|
||||
+ 38 * ((x_3*y_9) + (x_5*y_7) +
|
||||
(x_7*y_5) + (x_9*y_3));
|
||||
xy._2 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + (x_0*y_3) + (x_1*y_2) + (x_2*y_1) +
|
||||
(x_3*y_0) + 19 * ((x_4*y_9) + (x_5*y_8) +
|
||||
(x_6*y_7) + (x_7*y_6) +
|
||||
(x_8*y_5) + (x_9*y_4));
|
||||
xy._3 = (t & ((1 << 25) - 1));
|
||||
t = (t >> 25) + (x_0*y_4) + (x_2*y_2) + (x_4*y_0) + 19 *
|
||||
((x_6*y_8) + (x_8*y_6)) + 2 * ((x_1*y_3) +
|
||||
(x_3*y_1)) + 38 *
|
||||
((x_5*y_9) + (x_7*y_7) + (x_9*y_5));
|
||||
xy._4 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + (x_0*y_5) + (x_1*y_4) + (x_2*y_3) +
|
||||
(x_3*y_2) + (x_4*y_1) + (x_5*y_0) + 19 *
|
||||
((x_6*y_9) + (x_7*y_8) + (x_8*y_7) +
|
||||
(x_9*y_6));
|
||||
xy._5 = (t & ((1 << 25) - 1));
|
||||
t = (t >> 25) + (x_0*y_6) + (x_2*y_4) + (x_4*y_2) +
|
||||
(x_6*y_0) + 19 * (x_8*y_8) + 2 * ((x_1*y_5) +
|
||||
(x_3*y_3) + (x_5*y_1)) + 38 *
|
||||
((x_7*y_9) + (x_9*y_7));
|
||||
xy._6 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + (x_0*y_7) + (x_1*y_6) + (x_2*y_5) +
|
||||
(x_3*y_4) + (x_4*y_3) + (x_5*y_2) +
|
||||
(x_6*y_1) + (x_7*y_0) + 19 * ((x_8*y_9) +
|
||||
(x_9*y_8));
|
||||
xy._7 = (t & ((1 << 25) - 1));
|
||||
t = (t >> 25) + xy._8;
|
||||
xy._8 = (t & ((1 << 26) - 1));
|
||||
xy._9 += (t >> 26);
|
||||
return xy;
|
||||
}
|
||||
|
||||
/* Square a number. Optimization of mul25519(x2, x, x) */
|
||||
private static final long10 sqr(long10 x2, long10 x) {
|
||||
long
|
||||
x_0=x._0,x_1=x._1,x_2=x._2,x_3=x._3,x_4=x._4,
|
||||
x_5=x._5,x_6=x._6,x_7=x._7,x_8=x._8,x_9=x._9;
|
||||
long t;
|
||||
t = (x_4*x_4) + 2 * ((x_0*x_8) + (x_2*x_6)) + 38 *
|
||||
(x_9*x_9) + 4 * ((x_1*x_7) + (x_3*x_5));
|
||||
x2._8 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + 2 * ((x_0*x_9) + (x_1*x_8) + (x_2*x_7) +
|
||||
(x_3*x_6) + (x_4*x_5));
|
||||
x2._9 = (t & ((1 << 25) - 1));
|
||||
t = 19 * (t >> 25) + (x_0*x_0) + 38 * ((x_2*x_8) +
|
||||
(x_4*x_6) + (x_5*x_5)) + 76 * ((x_1*x_9)
|
||||
+ (x_3*x_7));
|
||||
x2._0 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + 2 * (x_0*x_1) + 38 * ((x_2*x_9) +
|
||||
(x_3*x_8) + (x_4*x_7) + (x_5*x_6));
|
||||
x2._1 = (t & ((1 << 25) - 1));
|
||||
t = (t >> 25) + 19 * (x_6*x_6) + 2 * ((x_0*x_2) +
|
||||
(x_1*x_1)) + 38 * (x_4*x_8) + 76 *
|
||||
((x_3*x_9) + (x_5*x_7));
|
||||
x2._2 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + 2 * ((x_0*x_3) + (x_1*x_2)) + 38 *
|
||||
((x_4*x_9) + (x_5*x_8) + (x_6*x_7));
|
||||
x2._3 = (t & ((1 << 25) - 1));
|
||||
t = (t >> 25) + (x_2*x_2) + 2 * (x_0*x_4) + 38 *
|
||||
((x_6*x_8) + (x_7*x_7)) + 4 * (x_1*x_3) + 76 *
|
||||
(x_5*x_9);
|
||||
x2._4 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + 2 * ((x_0*x_5) + (x_1*x_4) + (x_2*x_3))
|
||||
+ 38 * ((x_6*x_9) + (x_7*x_8));
|
||||
x2._5 = (t & ((1 << 25) - 1));
|
||||
t = (t >> 25) + 19 * (x_8*x_8) + 2 * ((x_0*x_6) +
|
||||
(x_2*x_4) + (x_3*x_3)) + 4 * (x_1*x_5) +
|
||||
76 * (x_7*x_9);
|
||||
x2._6 = (t & ((1 << 26) - 1));
|
||||
t = (t >> 26) + 2 * ((x_0*x_7) + (x_1*x_6) + (x_2*x_5) +
|
||||
(x_3*x_4)) + 38 * (x_8*x_9);
|
||||
x2._7 = (t & ((1 << 25) - 1));
|
||||
t = (t >> 25) + x2._8;
|
||||
x2._8 = (t & ((1 << 26) - 1));
|
||||
x2._9 += (t >> 26);
|
||||
return x2;
|
||||
}
|
||||
|
||||
/* Calculates a reciprocal. The output is in reduced form, the inputs need not
|
||||
* be. Simply calculates y = x^(p-2) so it's not too fast. */
|
||||
/* When sqrtassist is true, it instead calculates y = x^((p-5)/8) */
|
||||
private static final void recip(long10 y, long10 x, int sqrtassist) {
|
||||
long10
|
||||
t0=new long10(),
|
||||
t1=new long10(),
|
||||
t2=new long10(),
|
||||
t3=new long10(),
|
||||
t4=new long10();
|
||||
int i;
|
||||
/* the chain for x^(2^255-21) is straight from djb's implementation */
|
||||
sqr(t1, x); /* 2 == 2 * 1 */
|
||||
sqr(t2, t1); /* 4 == 2 * 2 */
|
||||
sqr(t0, t2); /* 8 == 2 * 4 */
|
||||
mul(t2, t0, x); /* 9 == 8 + 1 */
|
||||
mul(t0, t2, t1); /* 11 == 9 + 2 */
|
||||
sqr(t1, t0); /* 22 == 2 * 11 */
|
||||
mul(t3, t1, t2); /* 31 == 22 + 9
|
||||
== 2^5 - 2^0 */
|
||||
sqr(t1, t3); /* 2^6 - 2^1 */
|
||||
sqr(t2, t1); /* 2^7 - 2^2 */
|
||||
sqr(t1, t2); /* 2^8 - 2^3 */
|
||||
sqr(t2, t1); /* 2^9 - 2^4 */
|
||||
sqr(t1, t2); /* 2^10 - 2^5 */
|
||||
mul(t2, t1, t3); /* 2^10 - 2^0 */
|
||||
sqr(t1, t2); /* 2^11 - 2^1 */
|
||||
sqr(t3, t1); /* 2^12 - 2^2 */
|
||||
for (i = 1; i < 5; i++) {
|
||||
sqr(t1, t3);
|
||||
sqr(t3, t1);
|
||||
} /* t3 */ /* 2^20 - 2^10 */
|
||||
mul(t1, t3, t2); /* 2^20 - 2^0 */
|
||||
sqr(t3, t1); /* 2^21 - 2^1 */
|
||||
sqr(t4, t3); /* 2^22 - 2^2 */
|
||||
for (i = 1; i < 10; i++) {
|
||||
sqr(t3, t4);
|
||||
sqr(t4, t3);
|
||||
} /* t4 */ /* 2^40 - 2^20 */
|
||||
mul(t3, t4, t1); /* 2^40 - 2^0 */
|
||||
for (i = 0; i < 5; i++) {
|
||||
sqr(t1, t3);
|
||||
sqr(t3, t1);
|
||||
} /* t3 */ /* 2^50 - 2^10 */
|
||||
mul(t1, t3, t2); /* 2^50 - 2^0 */
|
||||
sqr(t2, t1); /* 2^51 - 2^1 */
|
||||
sqr(t3, t2); /* 2^52 - 2^2 */
|
||||
for (i = 1; i < 25; i++) {
|
||||
sqr(t2, t3);
|
||||
sqr(t3, t2);
|
||||
} /* t3 */ /* 2^100 - 2^50 */
|
||||
mul(t2, t3, t1); /* 2^100 - 2^0 */
|
||||
sqr(t3, t2); /* 2^101 - 2^1 */
|
||||
sqr(t4, t3); /* 2^102 - 2^2 */
|
||||
for (i = 1; i < 50; i++) {
|
||||
sqr(t3, t4);
|
||||
sqr(t4, t3);
|
||||
} /* t4 */ /* 2^200 - 2^100 */
|
||||
mul(t3, t4, t2); /* 2^200 - 2^0 */
|
||||
for (i = 0; i < 25; i++) {
|
||||
sqr(t4, t3);
|
||||
sqr(t3, t4);
|
||||
} /* t3 */ /* 2^250 - 2^50 */
|
||||
mul(t2, t3, t1); /* 2^250 - 2^0 */
|
||||
sqr(t1, t2); /* 2^251 - 2^1 */
|
||||
sqr(t2, t1); /* 2^252 - 2^2 */
|
||||
if (sqrtassist!=0) {
|
||||
mul(y, x, t2); /* 2^252 - 3 */
|
||||
} else {
|
||||
sqr(t1, t2); /* 2^253 - 2^3 */
|
||||
sqr(t2, t1); /* 2^254 - 2^4 */
|
||||
sqr(t1, t2); /* 2^255 - 2^5 */
|
||||
mul(y, t1, t0); /* 2^255 - 21 */
|
||||
}
|
||||
}
|
||||
|
||||
/* checks if x is "negative", requires reduced input */
|
||||
private static final int is_negative(long10 x) {
|
||||
return (int)(((is_overflow(x) || (x._9 < 0))?1:0) ^ (x._0 & 1));
|
||||
}
|
||||
|
||||
/* a square root */
|
||||
private static final void sqrt(long10 x, long10 u) {
|
||||
long10 v=new long10(), t1=new long10(), t2=new long10();
|
||||
add(t1, u, u); /* t1 = 2u */
|
||||
recip(v, t1, 1); /* v = (2u)^((p-5)/8) */
|
||||
sqr(x, v); /* x = v^2 */
|
||||
mul(t2, t1, x); /* t2 = 2uv^2 */
|
||||
t2._0--; /* t2 = 2uv^2-1 */
|
||||
mul(t1, v, t2); /* t1 = v(2uv^2-1) */
|
||||
mul(x, u, t1); /* x = uv(2uv^2-1) */
|
||||
}
|
||||
|
||||
/********************* Elliptic curve *********************/
|
||||
|
||||
/* y^2 = x^3 + 486662 x^2 + x over GF(2^255-19) */
|
||||
|
||||
/* t1 = ax + az
|
||||
* t2 = ax - az */
|
||||
private static final void mont_prep(long10 t1, long10 t2, long10 ax, long10 az) {
|
||||
add(t1, ax, az);
|
||||
sub(t2, ax, az);
|
||||
}
|
||||
|
||||
/* A = P + Q where
|
||||
* X(A) = ax/az
|
||||
* X(P) = (t1+t2)/(t1-t2)
|
||||
* X(Q) = (t3+t4)/(t3-t4)
|
||||
* X(P-Q) = dx
|
||||
* clobbers t1 and t2, preserves t3 and t4 */
|
||||
private static final void mont_add(long10 t1, long10 t2, long10 t3, long10 t4,long10 ax, long10 az, long10 dx) {
|
||||
mul(ax, t2, t3);
|
||||
mul(az, t1, t4);
|
||||
add(t1, ax, az);
|
||||
sub(t2, ax, az);
|
||||
sqr(ax, t1);
|
||||
sqr(t1, t2);
|
||||
mul(az, t1, dx);
|
||||
}
|
||||
|
||||
/* B = 2 * Q where
|
||||
* X(B) = bx/bz
|
||||
* X(Q) = (t3+t4)/(t3-t4)
|
||||
* clobbers t1 and t2, preserves t3 and t4 */
|
||||
private static final void mont_dbl(long10 t1, long10 t2, long10 t3, long10 t4,long10 bx, long10 bz) {
|
||||
sqr(t1, t3);
|
||||
sqr(t2, t4);
|
||||
mul(bx, t1, t2);
|
||||
sub(t2, t1, t2);
|
||||
mul_small(bz, t2, 121665);
|
||||
add(t1, t1, bz);
|
||||
mul(bz, t1, t2);
|
||||
}
|
||||
|
||||
/* Y^2 = X^3 + 486662 X^2 + X
|
||||
* t is a temporary */
|
||||
private static final void x_to_y2(long10 t, long10 y2, long10 x) {
|
||||
sqr(t, x);
|
||||
mul_small(y2, x, 486662);
|
||||
add(t, t, y2);
|
||||
t._0++;
|
||||
mul(y2, t, x);
|
||||
}
|
||||
|
||||
/* P = kG and s = sign(P)/k */
|
||||
private static final void core(byte[] Px, byte[] s, byte[] k, byte[] Gx) {
|
||||
long10
|
||||
dx=new long10(),
|
||||
t1=new long10(),
|
||||
t2=new long10(),
|
||||
t3=new long10(),
|
||||
t4=new long10();
|
||||
long10[]
|
||||
x=new long10[]{new long10(),new long10()},
|
||||
z=new long10[]{new long10(),new long10()};
|
||||
int i, j;
|
||||
|
||||
/* unpack the base */
|
||||
if (Gx!=null)
|
||||
unpack(dx, Gx);
|
||||
else
|
||||
set(dx, 9);
|
||||
|
||||
/* 0G = point-at-infinity */
|
||||
set(x[0], 1);
|
||||
set(z[0], 0);
|
||||
|
||||
/* 1G = G */
|
||||
cpy(x[1], dx);
|
||||
set(z[1], 1);
|
||||
|
||||
for (i = 32; i--!=0; ) {
|
||||
if (i==0) {
|
||||
i=0;
|
||||
}
|
||||
for (j = 8; j--!=0; ) {
|
||||
/* swap arguments depending on bit */
|
||||
int bit1 = (k[i] & 0xFF) >> j & 1;
|
||||
int bit0 = ~(k[i] & 0xFF) >> j & 1;
|
||||
long10 ax = x[bit0];
|
||||
long10 az = z[bit0];
|
||||
long10 bx = x[bit1];
|
||||
long10 bz = z[bit1];
|
||||
|
||||
/* a' = a + b */
|
||||
/* b' = 2 b */
|
||||
mont_prep(t1, t2, ax, az);
|
||||
mont_prep(t3, t4, bx, bz);
|
||||
mont_add(t1, t2, t3, t4, ax, az, dx);
|
||||
mont_dbl(t1, t2, t3, t4, bx, bz);
|
||||
}
|
||||
}
|
||||
|
||||
recip(t1, z[0], 0);
|
||||
mul(dx, x[0], t1);
|
||||
pack(dx, Px);
|
||||
|
||||
/* calculate s such that s abs(P) = G .. assumes G is std base point */
|
||||
if (s!=null) {
|
||||
x_to_y2(t2, t1, dx); /* t1 = Py^2 */
|
||||
recip(t3, z[1], 0); /* where Q=P+G ... */
|
||||
mul(t2, x[1], t3); /* t2 = Qx */
|
||||
add(t2, t2, dx); /* t2 = Qx + Px */
|
||||
t2._0 += 9 + 486662; /* t2 = Qx + Px + Gx + 486662 */
|
||||
dx._0 -= 9; /* dx = Px - Gx */
|
||||
sqr(t3, dx); /* t3 = (Px - Gx)^2 */
|
||||
mul(dx, t2, t3); /* dx = t2 (Px - Gx)^2 */
|
||||
sub(dx, dx, t1); /* dx = t2 (Px - Gx)^2 - Py^2 */
|
||||
dx._0 -= 39420360; /* dx = t2 (Px - Gx)^2 - Py^2 - Gy^2 */
|
||||
mul(t1, dx, BASE_R2Y); /* t1 = -Py */
|
||||
if (is_negative(t1)!=0) /* sign is 1, so just copy */
|
||||
cpy32(s, k);
|
||||
else /* sign is -1, so negate */
|
||||
mula_small(s, ORDER_TIMES_8, 0, k, 32, -1);
|
||||
|
||||
/* reduce s mod q
|
||||
* (is this needed? do it just in case, it's fast anyway) */
|
||||
//divmod((dstptr) t1, s, 32, order25519, 32);
|
||||
|
||||
/* take reciprocal of s mod q */
|
||||
byte[] temp1=new byte[32];
|
||||
byte[] temp2=new byte[64];
|
||||
byte[] temp3=new byte[64];
|
||||
cpy32(temp1, ORDER);
|
||||
cpy32(s, egcd32(temp2, temp3, s, temp1));
|
||||
if ((s[31] & 0x80)!=0)
|
||||
mula_small(s, s, 0, ORDER, 32, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* smallest multiple of the order that's >= 2^255 */
|
||||
private static final byte[] ORDER_TIMES_8 = {
|
||||
(byte)104, (byte)159, (byte)174, (byte)231,
|
||||
(byte)210, (byte)24, (byte)147, (byte)192,
|
||||
(byte)178, (byte)230, (byte)188, (byte)23,
|
||||
(byte)245, (byte)206, (byte)247, (byte)166,
|
||||
(byte)0, (byte)0, (byte)0, (byte)0,
|
||||
(byte)0, (byte)0, (byte)0, (byte)0,
|
||||
(byte)0, (byte)0, (byte)0, (byte)0,
|
||||
(byte)0, (byte)0, (byte)0, (byte)128
|
||||
};
|
||||
|
||||
/* constants 2Gy and 1/(2Gy) */
|
||||
private static final long10 BASE_2Y = new long10(
|
||||
39999547, 18689728, 59995525, 1648697, 57546132,
|
||||
24010086, 19059592, 5425144, 63499247, 16420658
|
||||
);
|
||||
private static final long10 BASE_R2Y = new long10(
|
||||
5744, 8160848, 4790893, 13779497, 35730846,
|
||||
12541209, 49101323, 30047407, 40071253, 6226132
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,8 +18,6 @@ package net.schmizz.concurrent;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
|
||||
/**
|
||||
* An event can be set, cleared, or awaited, similar to Python's {@code threading.event}. The key difference is that a
|
||||
* waiter may be delivered an exception of parameterized type {@code T}.
|
||||
@@ -44,8 +42,8 @@ public class Event<T extends Throwable> {
|
||||
* @param name name of this event
|
||||
* @param chainer {@link ExceptionChainer} that will be used for chaining exceptions
|
||||
*/
|
||||
public Event(String name, ExceptionChainer<T> chainer, LoggerFactory loggerFactory) {
|
||||
promise = new Promise<Object, T>(name, chainer, loggerFactory);
|
||||
public Event(String name, ExceptionChainer<T> chainer) {
|
||||
promise = new Promise<Object, T>(name, chainer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,8 +53,8 @@ public class Event<T extends Throwable> {
|
||||
* @param chainer {@link ExceptionChainer} that will be used for chaining exceptions
|
||||
* @param lock lock to use
|
||||
*/
|
||||
public Event(String name, ExceptionChainer<T> chainer, ReentrantLock lock, LoggerFactory loggerFactory) {
|
||||
promise = new Promise<Object, T>(name, chainer, lock, loggerFactory);
|
||||
public Event(String name, ExceptionChainer<T> chainer, ReentrantLock lock) {
|
||||
promise = new Promise<Object, T>(name, chainer, lock);
|
||||
}
|
||||
|
||||
/** Sets this event to be {@code true}. Short for {@code set(true)}. */
|
||||
@@ -145,4 +143,4 @@ public class Event<T extends Throwable> {
|
||||
return promise.toString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,4 +37,4 @@ public interface ExceptionChainer<Z extends Throwable> {
|
||||
|
||||
Z chain(Throwable t);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,14 +16,13 @@
|
||||
package net.schmizz.concurrent;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Represents promised data of the parameterized type {@code V} and allows waiting on it. An exception may also be
|
||||
* delivered to a waiter, and will be of the parameterized type {@code T}.
|
||||
@@ -33,7 +32,8 @@ import net.schmizz.sshj.common.LoggerFactory;
|
||||
*/
|
||||
public class Promise<V, T extends Throwable> {
|
||||
|
||||
private final Logger log;
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final String name;
|
||||
private final ExceptionChainer<T> chainer;
|
||||
private final ReentrantLock lock;
|
||||
@@ -49,8 +49,8 @@ public class Promise<V, T extends Throwable> {
|
||||
* @param name name of this promise
|
||||
* @param chainer {@link ExceptionChainer} that will be used for chaining exceptions
|
||||
*/
|
||||
public Promise(String name, ExceptionChainer<T> chainer, LoggerFactory loggerFactory) {
|
||||
this(name, chainer, null, loggerFactory);
|
||||
public Promise(String name, ExceptionChainer<T> chainer) {
|
||||
this(name, chainer, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,11 +60,10 @@ public class Promise<V, T extends Throwable> {
|
||||
* @param chainer {@link ExceptionChainer} that will be used for chaining exceptions
|
||||
* @param lock lock to use
|
||||
*/
|
||||
public Promise(String name, ExceptionChainer<T> chainer, ReentrantLock lock, LoggerFactory loggerFactory) {
|
||||
public Promise(String name, ExceptionChainer<T> chainer, ReentrantLock lock) {
|
||||
this.name = name;
|
||||
this.chainer = chainer;
|
||||
this.lock = lock == null ? new ReentrantLock() : lock;
|
||||
this.log = loggerFactory.getLogger(getClass());
|
||||
this.cond = this.lock.newCondition();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,14 +22,14 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class KeepAlive extends Thread {
|
||||
protected final Logger log;
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected final ConnectionImpl conn;
|
||||
|
||||
protected int keepAliveInterval = 0;
|
||||
|
||||
protected KeepAlive(ConnectionImpl conn, String name) {
|
||||
this.conn = conn;
|
||||
log = conn.getTransport().getConfig().getLoggerFactory().getLogger(getClass());
|
||||
setName(name);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,13 +22,14 @@ import net.schmizz.sshj.common.SSHPacket;
|
||||
import net.schmizz.sshj.transport.Transport;
|
||||
import net.schmizz.sshj.transport.TransportException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/** An abstract class for {@link Service} that implements common or default functionality. */
|
||||
public abstract class AbstractService
|
||||
implements Service {
|
||||
|
||||
/** Logger */
|
||||
protected final Logger log;
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
/** Assigned name of this service */
|
||||
protected final String name;
|
||||
@@ -38,7 +39,6 @@ public abstract class AbstractService
|
||||
public AbstractService(String name, Transport trans) {
|
||||
this.name = name;
|
||||
this.trans = trans;
|
||||
log = trans.getConfig().getLoggerFactory().getLogger(getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,24 +15,12 @@
|
||||
*/
|
||||
package net.schmizz.sshj;
|
||||
|
||||
import net.schmizz.sshj.common.SecurityUtils;
|
||||
import net.schmizz.sshj.signature.SignatureDSA;
|
||||
import net.schmizz.sshj.signature.SignatureRSA;
|
||||
import net.schmizz.sshj.transport.random.JCERandom;
|
||||
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
|
||||
|
||||
public class AndroidConfig
|
||||
extends DefaultConfig {
|
||||
|
||||
static {
|
||||
SecurityUtils.registerSecurityProvider("org.spongycastle.jce.provider.BouncyCastleProvider");
|
||||
}
|
||||
|
||||
// don't add ECDSA
|
||||
protected void initSignatureFactories() {
|
||||
setSignatureFactories(new SignatureRSA.Factory(), new SignatureDSA.Factory());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initRandomFactory(boolean ignored) {
|
||||
setRandomFactory(new SingletonRandomFactory(new JCERandom.Factory()));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@ package net.schmizz.sshj;
|
||||
|
||||
import net.schmizz.keepalive.KeepAliveProvider;
|
||||
import net.schmizz.sshj.common.Factory;
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
import net.schmizz.sshj.signature.Signature;
|
||||
import net.schmizz.sshj.transport.cipher.Cipher;
|
||||
import net.schmizz.sshj.transport.compression.Compression;
|
||||
@@ -156,34 +155,4 @@ public interface Config {
|
||||
* @param keepAliveProvider keep-alive provider
|
||||
*/
|
||||
void setKeepAliveProvider(KeepAliveProvider keepAliveProvider);
|
||||
|
||||
/**
|
||||
* Gets whether the client should first wait for a received server ident, before sending the client ident.
|
||||
* <p/>
|
||||
* <stong>NB:</stong> This is non-standard behaviour, and can potentially deadlock if the server also waits on the client ident.
|
||||
*
|
||||
* The default value is set to false.
|
||||
*
|
||||
* @return Whether to first wait for the server ident.
|
||||
*/
|
||||
boolean isWaitForServerIdentBeforeSendingClientIdent();
|
||||
|
||||
/**
|
||||
* Sets whether the SSH client should wait for a received server ident, before sending the client ident.
|
||||
* <p/>
|
||||
* <stong>NB:</stong> This is non-standard behaviour, and can potentially deadlock if the server also waits on the client ident.
|
||||
|
||||
* @param waitForServerIdentBeforeSendingClientIdent Whether to wait for the server ident.
|
||||
*/
|
||||
void setWaitForServerIdentBeforeSendingClientIdent(boolean waitForServerIdentBeforeSendingClientIdent);
|
||||
|
||||
/**
|
||||
* Sets the LoggerFactory to use.
|
||||
*/
|
||||
void setLoggerFactory(LoggerFactory loggerFactory);
|
||||
|
||||
/**
|
||||
* @return The LoggerFactory the SSHClient will use.
|
||||
*/
|
||||
LoggerFactory getLoggerFactory();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
package net.schmizz.sshj;
|
||||
|
||||
import net.schmizz.keepalive.KeepAliveProvider;
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
import net.schmizz.sshj.common.Factory;
|
||||
import net.schmizz.sshj.signature.Signature;
|
||||
import net.schmizz.sshj.transport.cipher.Cipher;
|
||||
@@ -45,9 +44,6 @@ public class ConfigImpl
|
||||
private List<Factory.Named<Signature>> signatureFactories;
|
||||
private List<Factory.Named<FileKeyProvider>> fileKeyProviderFactories;
|
||||
|
||||
private boolean waitForServerIdentBeforeSendingClientIdent = false;
|
||||
private LoggerFactory loggerFactory;
|
||||
|
||||
@Override
|
||||
public List<Factory.Named<Cipher>> getCipherFactories() {
|
||||
return cipherFactories;
|
||||
@@ -161,24 +157,4 @@ public class ConfigImpl
|
||||
public void setKeepAliveProvider(KeepAliveProvider keepAliveProvider) {
|
||||
this.keepAliveProvider = keepAliveProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWaitForServerIdentBeforeSendingClientIdent() {
|
||||
return waitForServerIdentBeforeSendingClientIdent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWaitForServerIdentBeforeSendingClientIdent(boolean waitForServerIdentBeforeSendingClientIdent) {
|
||||
this.waitForServerIdentBeforeSendingClientIdent = waitForServerIdentBeforeSendingClientIdent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoggerFactory getLoggerFactory() {
|
||||
return loggerFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoggerFactory(LoggerFactory loggerFactory) {
|
||||
this.loggerFactory = loggerFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,27 +15,39 @@
|
||||
*/
|
||||
package net.schmizz.sshj;
|
||||
|
||||
import com.hierynomus.sshj.signature.SignatureEdDSA;
|
||||
import com.hierynomus.sshj.transport.cipher.BlockCiphers;
|
||||
import com.hierynomus.sshj.transport.cipher.StreamCiphers;
|
||||
import net.schmizz.keepalive.KeepAliveProvider;
|
||||
import net.schmizz.sshj.common.Factory;
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
import net.schmizz.sshj.common.SecurityUtils;
|
||||
import net.schmizz.sshj.signature.SignatureDSA;
|
||||
import net.schmizz.sshj.signature.SignatureECDSA;
|
||||
import net.schmizz.sshj.signature.SignatureRSA;
|
||||
import net.schmizz.sshj.transport.cipher.*;
|
||||
import net.schmizz.sshj.transport.cipher.AES128CBC;
|
||||
import net.schmizz.sshj.transport.cipher.AES128CTR;
|
||||
import net.schmizz.sshj.transport.cipher.AES192CBC;
|
||||
import net.schmizz.sshj.transport.cipher.AES192CTR;
|
||||
import net.schmizz.sshj.transport.cipher.AES256CBC;
|
||||
import net.schmizz.sshj.transport.cipher.AES256CTR;
|
||||
import net.schmizz.sshj.transport.cipher.BlowfishCBC;
|
||||
import net.schmizz.sshj.transport.cipher.Cipher;
|
||||
import net.schmizz.sshj.transport.cipher.TripleDESCBC;
|
||||
import net.schmizz.sshj.transport.compression.NoneCompression;
|
||||
import net.schmizz.sshj.transport.kex.*;
|
||||
import net.schmizz.sshj.transport.mac.*;
|
||||
import net.schmizz.sshj.transport.kex.DHG1;
|
||||
import net.schmizz.sshj.transport.kex.DHG14;
|
||||
import net.schmizz.sshj.transport.mac.HMACMD5;
|
||||
import net.schmizz.sshj.transport.mac.HMACMD596;
|
||||
import net.schmizz.sshj.transport.mac.HMACSHA1;
|
||||
import net.schmizz.sshj.transport.mac.HMACSHA196;
|
||||
import net.schmizz.sshj.transport.mac.HMACSHA2256;
|
||||
import net.schmizz.sshj.transport.mac.HMACSHA2512;
|
||||
import net.schmizz.sshj.transport.random.BouncyCastleRandom;
|
||||
import net.schmizz.sshj.transport.random.JCERandom;
|
||||
import net.schmizz.sshj.transport.random.SingletonRandomFactory;
|
||||
import net.schmizz.sshj.userauth.keyprovider.OpenSSHKeyFile;
|
||||
import net.schmizz.sshj.userauth.keyprovider.PKCS8KeyFile;
|
||||
import net.schmizz.sshj.userauth.keyprovider.PuTTYKeyFile;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
@@ -67,12 +79,11 @@ import java.util.List;
|
||||
public class DefaultConfig
|
||||
extends ConfigImpl {
|
||||
|
||||
private static final String VERSION = "SSHJ_0_17_2";
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private Logger log;
|
||||
private static final String VERSION = "SSHJ_0_9_2";
|
||||
|
||||
public DefaultConfig() {
|
||||
setLoggerFactory(LoggerFactory.DEFAULT);
|
||||
setVersion(VERSION);
|
||||
final boolean bouncyCastleRegistered = SecurityUtils.isBouncyCastleRegistered();
|
||||
initKeyExchangeFactories(bouncyCastleRegistered);
|
||||
@@ -85,25 +96,11 @@ public class DefaultConfig
|
||||
setKeepAliveProvider(KeepAliveProvider.HEARTBEAT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoggerFactory(LoggerFactory loggerFactory) {
|
||||
super.setLoggerFactory(loggerFactory);
|
||||
log = loggerFactory.getLogger(getClass());
|
||||
}
|
||||
|
||||
protected void initKeyExchangeFactories(boolean bouncyCastleRegistered) {
|
||||
if (bouncyCastleRegistered) {
|
||||
setKeyExchangeFactories(new Curve25519SHA256.Factory(),
|
||||
new DHGexSHA256.Factory(),
|
||||
new ECDHNistP.Factory521(),
|
||||
new ECDHNistP.Factory384(),
|
||||
new ECDHNistP.Factory256(),
|
||||
new DHGexSHA1.Factory(),
|
||||
new DHG14.Factory(),
|
||||
new DHG1.Factory());
|
||||
} else {
|
||||
setKeyExchangeFactories(new DHG1.Factory(), new DHGexSHA1.Factory());
|
||||
}
|
||||
if (bouncyCastleRegistered)
|
||||
setKeyExchangeFactories(new DHG14.Factory(), new DHG1.Factory());
|
||||
else
|
||||
setKeyExchangeFactories(new DHG1.Factory());
|
||||
}
|
||||
|
||||
protected void initRandomFactory(boolean bouncyCastleRegistered) {
|
||||
@@ -127,30 +124,7 @@ public class DefaultConfig
|
||||
new AES192CBC.Factory(),
|
||||
new AES256CBC.Factory(),
|
||||
new TripleDESCBC.Factory(),
|
||||
new BlowfishCBC.Factory(),
|
||||
BlockCiphers.BlowfishCTR(),
|
||||
BlockCiphers.Cast128CBC(),
|
||||
BlockCiphers.Cast128CTR(),
|
||||
BlockCiphers.IDEACBC(),
|
||||
BlockCiphers.IDEACTR(),
|
||||
BlockCiphers.Serpent128CBC(),
|
||||
BlockCiphers.Serpent128CTR(),
|
||||
BlockCiphers.Serpent192CBC(),
|
||||
BlockCiphers.Serpent192CTR(),
|
||||
BlockCiphers.Serpent256CBC(),
|
||||
BlockCiphers.Serpent256CTR(),
|
||||
BlockCiphers.TripleDESCTR(),
|
||||
BlockCiphers.Twofish128CBC(),
|
||||
BlockCiphers.Twofish128CTR(),
|
||||
BlockCiphers.Twofish192CBC(),
|
||||
BlockCiphers.Twofish192CTR(),
|
||||
BlockCiphers.Twofish256CBC(),
|
||||
BlockCiphers.Twofish256CTR(),
|
||||
BlockCiphers.TwofishCBC(),
|
||||
StreamCiphers.Arcfour(),
|
||||
StreamCiphers.Arcfour128(),
|
||||
StreamCiphers.Arcfour256())
|
||||
);
|
||||
new BlowfishCBC.Factory()));
|
||||
|
||||
boolean warn = false;
|
||||
// Ref. https://issues.apache.org/jira/browse/SSHD-24
|
||||
@@ -164,7 +138,6 @@ public class DefaultConfig
|
||||
c.init(Cipher.Mode.Encrypt, key, iv);
|
||||
} catch (Exception e) {
|
||||
warn = true;
|
||||
log.warn(e.getCause().getMessage());
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
@@ -172,30 +145,20 @@ public class DefaultConfig
|
||||
log.warn("Disabling high-strength ciphers: cipher strengths apparently limited by JCE policy");
|
||||
|
||||
setCipherFactories(avail);
|
||||
log.debug("Available cipher factories: {}", avail);
|
||||
}
|
||||
|
||||
protected void initSignatureFactories() {
|
||||
setSignatureFactories(
|
||||
new SignatureECDSA.Factory(),
|
||||
new SignatureRSA.Factory(),
|
||||
new SignatureDSA.Factory(),
|
||||
new SignatureEdDSA.Factory()
|
||||
);
|
||||
setSignatureFactories(new SignatureECDSA.Factory(), new SignatureRSA.Factory(), new SignatureDSA.Factory());
|
||||
}
|
||||
|
||||
protected void initMACFactories() {
|
||||
setMACFactories(
|
||||
new HMACSHA1.Factory(),
|
||||
new HMACSHA196.Factory(),
|
||||
new HMACMD5.Factory(),
|
||||
new HMACMD596.Factory(),
|
||||
new HMACSHA2256.Factory(),
|
||||
new HMACSHA2512.Factory()
|
||||
);
|
||||
setMACFactories(new HMACSHA1.Factory(), new HMACSHA196.Factory(), new HMACMD5.Factory(),
|
||||
new HMACMD596.Factory(), new HMACSHA2256.Factory(), new HMACSHA2512.Factory());
|
||||
}
|
||||
|
||||
protected void initCompressionFactories() {
|
||||
setCompressionFactories(new NoneCompression.Factory());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
package net.schmizz.sshj;
|
||||
|
||||
import net.schmizz.sshj.common.Factory;
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
import net.schmizz.sshj.common.SSHException;
|
||||
import net.schmizz.sshj.common.SecurityUtils;
|
||||
import net.schmizz.sshj.connection.Connection;
|
||||
@@ -40,30 +39,38 @@ import net.schmizz.sshj.transport.TransportImpl;
|
||||
import net.schmizz.sshj.transport.compression.DelayedZlibCompression;
|
||||
import net.schmizz.sshj.transport.compression.NoneCompression;
|
||||
import net.schmizz.sshj.transport.compression.ZlibCompression;
|
||||
import net.schmizz.sshj.transport.verification.AlgorithmsVerifier;
|
||||
import net.schmizz.sshj.transport.verification.HostKeyVerifier;
|
||||
import net.schmizz.sshj.transport.verification.OpenSSHKnownHosts;
|
||||
import net.schmizz.sshj.userauth.UserAuth;
|
||||
import net.schmizz.sshj.userauth.UserAuthException;
|
||||
import net.schmizz.sshj.userauth.UserAuthImpl;
|
||||
import net.schmizz.sshj.userauth.keyprovider.*;
|
||||
import net.schmizz.sshj.userauth.method.*;
|
||||
import net.schmizz.sshj.userauth.keyprovider.FileKeyProvider;
|
||||
import net.schmizz.sshj.userauth.keyprovider.KeyFormat;
|
||||
import net.schmizz.sshj.userauth.keyprovider.KeyPairWrapper;
|
||||
import net.schmizz.sshj.userauth.keyprovider.KeyProvider;
|
||||
import net.schmizz.sshj.userauth.keyprovider.KeyProviderUtil;
|
||||
import net.schmizz.sshj.userauth.method.AuthKeyboardInteractive;
|
||||
import net.schmizz.sshj.userauth.method.AuthMethod;
|
||||
import net.schmizz.sshj.userauth.method.AuthPassword;
|
||||
import net.schmizz.sshj.userauth.method.AuthPublickey;
|
||||
import net.schmizz.sshj.userauth.method.PasswordResponseProvider;
|
||||
import net.schmizz.sshj.userauth.password.PasswordFinder;
|
||||
import net.schmizz.sshj.userauth.password.PasswordUpdateProvider;
|
||||
import net.schmizz.sshj.userauth.password.PasswordUtils;
|
||||
import net.schmizz.sshj.userauth.password.Resource;
|
||||
import net.schmizz.sshj.xfer.scp.SCPFileTransfer;
|
||||
import org.ietf.jgss.Oid;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.security.auth.login.LoginContext;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PublicKey;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Secure SHell client API.
|
||||
@@ -114,8 +121,7 @@ public class SSHClient
|
||||
public static final int DEFAULT_PORT = 22;
|
||||
|
||||
/** Logger */
|
||||
protected final LoggerFactory loggerFactory;
|
||||
protected final Logger log;
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
/** Transport layer */
|
||||
protected final Transport trans;
|
||||
@@ -126,8 +132,6 @@ public class SSHClient
|
||||
/** {@code ssh-connection} service */
|
||||
protected final Connection conn;
|
||||
|
||||
private final List<LocalPortForwarder> forwarders = new ArrayList<LocalPortForwarder>();
|
||||
|
||||
/** Default constructor. Initializes this object using {@link DefaultConfig}. */
|
||||
public SSHClient() {
|
||||
this(new DefaultConfig());
|
||||
@@ -140,8 +144,6 @@ public class SSHClient
|
||||
*/
|
||||
public SSHClient(Config config) {
|
||||
super(DEFAULT_PORT);
|
||||
loggerFactory = config.getLoggerFactory();
|
||||
log = loggerFactory.getLogger(getClass());
|
||||
this.trans = new TransportImpl(config, this);
|
||||
this.auth = new UserAuthImpl(trans);
|
||||
this.conn = new ConnectionImpl(trans, config.getKeepAliveProvider());
|
||||
@@ -151,19 +153,10 @@ public class SSHClient
|
||||
* Add a {@link HostKeyVerifier} which will be invoked for verifying host key during connection establishment and
|
||||
* future key exchanges.
|
||||
*
|
||||
* @param verifier {@link HostKeyVerifier} instance
|
||||
* @param hostKeyVerifier {@link HostKeyVerifier} instance
|
||||
*/
|
||||
public void addHostKeyVerifier(HostKeyVerifier verifier) {
|
||||
trans.addHostKeyVerifier(verifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link AlgorithmsVerifier} which will be invoked for verifying negotiated algorithms.
|
||||
*
|
||||
* @param verifier {@link AlgorithmsVerifier} instance
|
||||
*/
|
||||
public void addAlgorithmsVerifier(AlgorithmsVerifier verifier) {
|
||||
trans.addAlgorithmsVerifier(verifier);
|
||||
public void addHostKeyVerifier(HostKeyVerifier hostKeyVerifier) {
|
||||
trans.addHostKeyVerifier(hostKeyVerifier);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,7 +207,6 @@ public class SSHClient
|
||||
checkConnected();
|
||||
final Deque<UserAuthException> savedEx = new LinkedList<UserAuthException>();
|
||||
for (AuthMethod method: methods) {
|
||||
method.setLoggerFactory(loggerFactory);
|
||||
try {
|
||||
if (auth.authenticate(username, (Service) conn, method, trans.getTimeoutMs()))
|
||||
return;
|
||||
@@ -286,22 +278,6 @@ public class SSHClient
|
||||
auth(username, new AuthPassword(pfinder), new AuthKeyboardInteractive(new PasswordResponseProvider(pfinder)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate {@code username} using the {@code "password"} authentication method and as a fallback basic
|
||||
* challenge-response authentication.
|
||||
*
|
||||
* @param username user to authenticate
|
||||
* @param pfinder the {@link PasswordFinder} to use for authentication
|
||||
* @param newPasswordProvider the {@link PasswordUpdateProvider} to use when a new password is being requested from the user.
|
||||
*
|
||||
* @throws UserAuthException in case of authentication failure
|
||||
* @throws TransportException if there was a transport-layer error
|
||||
*/
|
||||
public void authPassword(String username, PasswordFinder pfinder, PasswordUpdateProvider newPasswordProvider)
|
||||
throws UserAuthException, TransportException {
|
||||
auth(username, new AuthPassword(pfinder, newPasswordProvider), new AuthKeyboardInteractive(new PasswordResponseProvider(pfinder)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate {@code username} using the {@code "publickey"} authentication method, with keys from some common
|
||||
* locations on the file system. This method relies on {@code ~/.ssh/id_rsa} and {@code ~/.ssh/id_dsa}.
|
||||
@@ -389,30 +365,6 @@ public class SSHClient
|
||||
authPublickey(username, keyProviders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate {@code username} using the {@code "gssapi-with-mic"} authentication method, given a login context
|
||||
* for the peer GSS machine and a list of supported OIDs.
|
||||
* <p/>
|
||||
* Supported OIDs should be ordered by preference as the SSH server will choose the first OID that it also
|
||||
* supports. At least one OID is required
|
||||
*
|
||||
* @param username user to authenticate
|
||||
* @param context {@code LoginContext} for the peer GSS machine
|
||||
* @param supportedOid first supported OID
|
||||
* @param supportedOids other supported OIDs
|
||||
*
|
||||
* @throws UserAuthException in case of authentication failure
|
||||
* @throws TransportException if there was a transport-layer error
|
||||
*/
|
||||
public void authGssApiWithMic(String username, LoginContext context, Oid supportedOid, Oid... supportedOids)
|
||||
throws UserAuthException, TransportException {
|
||||
// insert supportedOid to the front of the list since ordering matters
|
||||
List<Oid> oids = new ArrayList<Oid>(Arrays.asList(supportedOids));
|
||||
oids.add(0, supportedOid);
|
||||
|
||||
auth(username, new AuthGssApiWithMic(context, oids));
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from the connected SSH server. {@code SSHClient} objects are not reusable therefore it is incorrect
|
||||
* to attempt connection after this method has been called.
|
||||
@@ -423,14 +375,6 @@ public class SSHClient
|
||||
@Override
|
||||
public void disconnect()
|
||||
throws IOException {
|
||||
for (LocalPortForwarder forwarder : forwarders) {
|
||||
try {
|
||||
forwarder.close();
|
||||
} catch (IOException e) {
|
||||
log.warn("Error closing forwarder", e);
|
||||
}
|
||||
}
|
||||
forwarders.clear();
|
||||
trans.disconnect();
|
||||
super.disconnect();
|
||||
}
|
||||
@@ -630,7 +574,7 @@ public class SSHClient
|
||||
*/
|
||||
public void loadKnownHosts(File location)
|
||||
throws IOException {
|
||||
addHostKeyVerifier(new OpenSSHKnownHosts(location, loggerFactory));
|
||||
addHostKeyVerifier(new OpenSSHKnownHosts(location));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -648,9 +592,7 @@ public class SSHClient
|
||||
*/
|
||||
public LocalPortForwarder newLocalPortForwarder(LocalPortForwarder.Parameters parameters,
|
||||
ServerSocket serverSocket) {
|
||||
LocalPortForwarder forwarder = new LocalPortForwarder(conn, parameters, serverSocket, loggerFactory);
|
||||
forwarders.add(forwarder);
|
||||
return forwarder;
|
||||
return new LocalPortForwarder(conn, parameters, serverSocket);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -677,7 +619,7 @@ public class SSHClient
|
||||
public SCPFileTransfer newSCPFileTransfer() {
|
||||
checkConnected();
|
||||
checkAuthenticated();
|
||||
return new SCPFileTransfer(this, loggerFactory);
|
||||
return new SCPFileTransfer(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -778,4 +720,4 @@ public class SSHClient
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package net.schmizz.sshj;
|
||||
|
||||
import com.hierynomus.sshj.backport.JavaVersion;
|
||||
import com.hierynomus.sshj.backport.Jdk7HttpProxySocket;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -48,109 +45,34 @@ public abstract class SocketClient {
|
||||
this.defaultPort = defaultPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a host via a proxy.
|
||||
* @param hostname The host name to connect to.
|
||||
* @param proxy The proxy to connect via.
|
||||
* @deprecated This method will be removed after v0.12.0. If you want to connect via a proxy, you can do this by injecting a {@link javax.net.SocketFactory}
|
||||
* into the SocketClient. The SocketFactory should create sockets using the {@link java.net.Socket#Socket(java.net.Proxy)} constructor.
|
||||
*/
|
||||
@Deprecated
|
||||
public void connect(String hostname, Proxy proxy) throws IOException {
|
||||
connect(hostname, defaultPort, proxy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a host via a proxy.
|
||||
* @param hostname The host name to connect to.
|
||||
* @param port The port to connect to.
|
||||
* @param proxy The proxy to connect via.
|
||||
* @deprecated This method will be removed after v0.12.0. If you want to connect via a proxy, you can do this by injecting a {@link javax.net.SocketFactory}
|
||||
* into the SocketClient. The SocketFactory should create sockets using the {@link java.net.Socket#Socket(java.net.Proxy)} constructor.
|
||||
*/
|
||||
@Deprecated
|
||||
public void connect(String hostname, int port, Proxy proxy) throws IOException {
|
||||
this.hostname = hostname;
|
||||
if (JavaVersion.isJava7OrEarlier() && proxy.type() == Proxy.Type.HTTP) {
|
||||
// Java7 and earlier have no support for HTTP Connect proxies, return our custom socket.
|
||||
socket = new Jdk7HttpProxySocket(proxy);
|
||||
} else {
|
||||
socket = new Socket(proxy);
|
||||
}
|
||||
socket.connect(new InetSocketAddress(hostname, port), connectTimeout);
|
||||
onConnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a host via a proxy.
|
||||
* @param host The host address to connect to.
|
||||
* @param proxy The proxy to connect via.
|
||||
* @deprecated This method will be removed after v0.12.0. If you want to connect via a proxy, you can do this by injecting a {@link javax.net.SocketFactory}
|
||||
* into the SocketClient. The SocketFactory should create sockets using the {@link java.net.Socket#Socket(java.net.Proxy)} constructor.
|
||||
*/
|
||||
@Deprecated
|
||||
public void connect(InetAddress host, Proxy proxy) throws IOException {
|
||||
connect(host, defaultPort, proxy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to a host via a proxy.
|
||||
* @param host The host address to connect to.
|
||||
* @param port The port to connect to.
|
||||
* @param proxy The proxy to connect via.
|
||||
* @deprecated This method will be removed after v0.12.0. If you want to connect via a proxy, you can do this by injecting a {@link javax.net.SocketFactory}
|
||||
* into the SocketClient. The SocketFactory should create sockets using the {@link java.net.Socket#Socket(java.net.Proxy)} constructor.
|
||||
*/
|
||||
@Deprecated
|
||||
public void connect(InetAddress host, int port, Proxy proxy) throws IOException {
|
||||
if (JavaVersion.isJava7OrEarlier() && proxy.type() == Proxy.Type.HTTP) {
|
||||
// Java7 and earlier have no support for HTTP Connect proxies, return our custom socket.
|
||||
socket = new Jdk7HttpProxySocket(proxy);
|
||||
} else {
|
||||
socket = new Socket(proxy);
|
||||
}
|
||||
socket.connect(new InetSocketAddress(host, port), connectTimeout);
|
||||
onConnect();
|
||||
}
|
||||
|
||||
public void connect(String hostname) throws IOException {
|
||||
connect(hostname, defaultPort);
|
||||
}
|
||||
|
||||
public void connect(String hostname, int port) throws IOException {
|
||||
if (hostname == null) {
|
||||
connect(InetAddress.getByName(null), port);
|
||||
} else {
|
||||
this.hostname = hostname;
|
||||
socket = socketFactory.createSocket();
|
||||
socket.connect(new InetSocketAddress(hostname, port), connectTimeout);
|
||||
onConnect();
|
||||
}
|
||||
}
|
||||
|
||||
public void connect(String hostname, int port, InetAddress localAddr, int localPort) throws IOException {
|
||||
if (hostname == null) {
|
||||
connect(InetAddress.getByName(null), port, localAddr, localPort);
|
||||
} else {
|
||||
this.hostname = hostname;
|
||||
socket = socketFactory.createSocket();
|
||||
socket.bind(new InetSocketAddress(localAddr, localPort));
|
||||
socket.connect(new InetSocketAddress(hostname, port), connectTimeout);
|
||||
onConnect();
|
||||
}
|
||||
}
|
||||
|
||||
public void connect(InetAddress host) throws IOException {
|
||||
connect(host, defaultPort);
|
||||
}
|
||||
|
||||
public void connect(InetAddress host, int port) throws IOException {
|
||||
public void connect(InetAddress host, int port)
|
||||
throws IOException {
|
||||
socket = socketFactory.createSocket();
|
||||
socket.connect(new InetSocketAddress(host, port), connectTimeout);
|
||||
onConnect();
|
||||
}
|
||||
|
||||
public void connect(InetAddress host, int port, InetAddress localAddr, int localPort)
|
||||
public void connect(InetAddress host, int port, Proxy proxy)
|
||||
throws IOException {
|
||||
socket = new Socket(proxy);
|
||||
socket.connect(new InetSocketAddress(host, port), connectTimeout);
|
||||
onConnect();
|
||||
}
|
||||
|
||||
public void connect(String hostname, int port)
|
||||
throws IOException {
|
||||
this.hostname = hostname;
|
||||
connect(InetAddress.getByName(hostname), port);
|
||||
}
|
||||
|
||||
public void connect(String hostname, int port, Proxy proxy)
|
||||
throws IOException {
|
||||
this.hostname = hostname;
|
||||
connect(InetAddress.getByName(hostname), port, proxy);
|
||||
}
|
||||
|
||||
public void connect(InetAddress host, int port,
|
||||
InetAddress localAddr, int localPort)
|
||||
throws IOException {
|
||||
socket = socketFactory.createSocket();
|
||||
socket.bind(new InetSocketAddress(localAddr, localPort));
|
||||
@@ -158,7 +80,35 @@ public abstract class SocketClient {
|
||||
onConnect();
|
||||
}
|
||||
|
||||
public void disconnect() throws IOException {
|
||||
public void connect(String hostname, int port,
|
||||
InetAddress localAddr, int localPort)
|
||||
throws IOException {
|
||||
this.hostname = hostname;
|
||||
connect(InetAddress.getByName(hostname), port, localAddr, localPort);
|
||||
}
|
||||
|
||||
public void connect(InetAddress host)
|
||||
throws IOException {
|
||||
connect(host, defaultPort);
|
||||
}
|
||||
|
||||
public void connect(String hostname)
|
||||
throws IOException {
|
||||
connect(hostname, defaultPort);
|
||||
}
|
||||
|
||||
public void connect(InetAddress host, Proxy proxy)
|
||||
throws IOException {
|
||||
connect(host, defaultPort, proxy);
|
||||
}
|
||||
|
||||
public void connect(String hostname, Proxy proxy)
|
||||
throws IOException {
|
||||
connect(hostname, defaultPort, proxy);
|
||||
}
|
||||
|
||||
public void disconnect()
|
||||
throws IOException {
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
socket = null;
|
||||
@@ -181,6 +131,7 @@ public abstract class SocketClient {
|
||||
return socket.getLocalPort();
|
||||
}
|
||||
|
||||
|
||||
public InetAddress getLocalAddress() {
|
||||
return socket.getLocalAddress();
|
||||
}
|
||||
@@ -198,11 +149,10 @@ public abstract class SocketClient {
|
||||
}
|
||||
|
||||
public void setSocketFactory(SocketFactory factory) {
|
||||
if (factory == null) {
|
||||
if (factory == null)
|
||||
socketFactory = SocketFactory.getDefault();
|
||||
} else {
|
||||
else
|
||||
socketFactory = factory;
|
||||
}
|
||||
}
|
||||
|
||||
public SocketFactory getSocketFactory() {
|
||||
@@ -237,7 +187,8 @@ public abstract class SocketClient {
|
||||
return output;
|
||||
}
|
||||
|
||||
void onConnect() throws IOException {
|
||||
void onConnect()
|
||||
throws IOException {
|
||||
socket.setSoTimeout(timeout);
|
||||
input = socket.getInputStream();
|
||||
output = socket.getOutputStream();
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package net.schmizz.sshj.common;
|
||||
|
||||
|
||||
@@ -1727,4 +1742,4 @@ public class Base64 {
|
||||
private Base64() {
|
||||
}
|
||||
|
||||
} // end class Base64
|
||||
} // end class Base64
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -426,7 +426,8 @@ public class Buffer<T extends Buffer<T>> {
|
||||
public PublicKey readPublicKey()
|
||||
throws BufferException {
|
||||
try {
|
||||
return KeyType.fromString(readString()).readPubKeyFromBuffer(this);
|
||||
final String type = readString();
|
||||
return KeyType.fromString(type).readPubKeyFromBuffer(type, this);
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new SSHRuntimeException(e);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,6 +16,7 @@
|
||||
package net.schmizz.sshj.common;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
@@ -25,33 +26,25 @@ import java.nio.charset.Charset;
|
||||
|
||||
public class IOUtils {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(IOUtils.class);
|
||||
|
||||
public static final Charset UTF8 = Charset.forName("UTF-8");
|
||||
|
||||
public static void closeQuietly(Closeable... closeables) {
|
||||
closeQuietly(LoggerFactory.DEFAULT, closeables);
|
||||
}
|
||||
|
||||
public static ByteArrayOutputStream readFully(InputStream stream)
|
||||
throws IOException {
|
||||
return readFully(stream, LoggerFactory.DEFAULT);
|
||||
}
|
||||
|
||||
public static void closeQuietly(LoggerFactory loggerFactory, Closeable... closeables) {
|
||||
for (Closeable c : closeables) {
|
||||
for (Closeable c : closeables)
|
||||
try {
|
||||
if (c != null)
|
||||
c.close();
|
||||
} catch (IOException logged) {
|
||||
loggerFactory.getLogger(IOUtils.class).warn("Error closing {} - {}", c, logged);
|
||||
LOG.warn("Error closing {} - {}", c, logged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static ByteArrayOutputStream readFully(InputStream stream, LoggerFactory loggerFactory)
|
||||
public static ByteArrayOutputStream readFully(InputStream stream)
|
||||
throws IOException {
|
||||
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
new StreamCopier(stream, baos, loggerFactory).copy();
|
||||
new StreamCopier(stream, baos).copy();
|
||||
return baos;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,12 +15,6 @@
|
||||
*/
|
||||
package net.schmizz.sshj.common;
|
||||
|
||||
import com.hierynomus.sshj.secg.SecgUtils;
|
||||
import com.hierynomus.sshj.signature.Ed25519PublicKey;
|
||||
import net.i2p.crypto.eddsa.EdDSAPublicKey;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
|
||||
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
|
||||
import org.bouncycastle.asn1.nist.NISTNamedCurves;
|
||||
import org.bouncycastle.asn1.x9.X9ECParameters;
|
||||
import org.bouncycastle.jce.spec.ECParameterSpec;
|
||||
@@ -30,10 +24,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PublicKey;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.*;
|
||||
import java.security.spec.DSAPublicKeySpec;
|
||||
import java.security.spec.RSAPublicKeySpec;
|
||||
@@ -46,7 +37,7 @@ public enum KeyType {
|
||||
/** SSH identifier for RSA keys */
|
||||
RSA("ssh-rsa") {
|
||||
@Override
|
||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
||||
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
|
||||
throws GeneralSecurityException {
|
||||
final BigInteger e, n;
|
||||
try {
|
||||
@@ -77,7 +68,7 @@ public enum KeyType {
|
||||
/** SSH identifier for DSA keys */
|
||||
DSA("ssh-dss") {
|
||||
@Override
|
||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
||||
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
|
||||
throws GeneralSecurityException {
|
||||
BigInteger p, q, g, y;
|
||||
try {
|
||||
@@ -114,11 +105,8 @@ public enum KeyType {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Override
|
||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
||||
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
|
||||
throws GeneralSecurityException {
|
||||
if (!SecurityUtils.isBouncyCastleRegistered()) {
|
||||
throw new GeneralSecurityException("BouncyCastle is required to read a key of type " + sType);
|
||||
}
|
||||
try {
|
||||
// final String algo = buf.readString(); it has been already read
|
||||
final String curveName = buf.readString();
|
||||
@@ -130,7 +118,7 @@ public enum KeyType {
|
||||
buf.readRawBytes(y);
|
||||
if(log.isDebugEnabled()) {
|
||||
log.debug(String.format("Key algo: %s, Key curve: %s, Key Len: %s, 0x04: %s\nx: %s\ny: %s",
|
||||
sType,
|
||||
type,
|
||||
curveName,
|
||||
keyLen,
|
||||
x04,
|
||||
@@ -147,7 +135,7 @@ public enum KeyType {
|
||||
BigInteger bigY = new BigInteger(1, y);
|
||||
|
||||
X9ECParameters ecParams = NISTNamedCurves.getByName("p-256");
|
||||
ECPoint pPublicPoint = ecParams.getCurve().createPoint(bigX, bigY);
|
||||
ECPoint pPublicPoint = ecParams.getCurve().createPoint(bigX, bigY, false);
|
||||
ECParameterSpec spec = new ECParameterSpec(ecParams.getCurve(),
|
||||
ecParams.getG(), ecParams.getN());
|
||||
ECPublicKeySpec publicSpec = new ECPublicKeySpec(pPublicPoint, spec);
|
||||
@@ -163,62 +151,44 @@ public enum KeyType {
|
||||
@Override
|
||||
public void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf) {
|
||||
final ECPublicKey ecdsa = (ECPublicKey) pk;
|
||||
byte[] encoded = SecgUtils.getEncoded(ecdsa.getW(), ecdsa.getParams().getCurve());
|
||||
final java.security.spec.ECPoint point = ecdsa.getW();
|
||||
final byte[] x = trimStartingZeros(point.getAffineX().toByteArray());
|
||||
final byte[] y = trimStartingZeros(point.getAffineY().toByteArray());
|
||||
|
||||
buf.putString(sType)
|
||||
.putString(NISTP_CURVE)
|
||||
.putBytes(encoded);
|
||||
.putUInt32(1 + x.length + y.length)
|
||||
.putRawBytes(new byte[] { (byte) 0x04 })
|
||||
.putRawBytes(x)
|
||||
.putRawBytes(y)
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isMyType(Key key) {
|
||||
return ("ECDSA".equals(key.getAlgorithm()));
|
||||
}
|
||||
},
|
||||
|
||||
ED25519("ssh-ed25519") {
|
||||
private final Logger log = LoggerFactory.getLogger(KeyType.class);
|
||||
@Override
|
||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf) throws GeneralSecurityException {
|
||||
try {
|
||||
final int keyLen = buf.readUInt32AsInt();
|
||||
final byte[] p = new byte[keyLen];
|
||||
buf.readRawBytes(p);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(String.format("Key algo: %s, Key curve: 25519, Key Len: %s\np: %s",
|
||||
sType,
|
||||
keyLen,
|
||||
Arrays.toString(p))
|
||||
);
|
||||
private byte[] trimStartingZeros(byte[] in) {
|
||||
|
||||
int i = 0;
|
||||
for (; i < in.length; i++) {
|
||||
if (in[i] != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable.getByName("ed25519-sha-512");
|
||||
EdDSAPublicKeySpec publicSpec = new EdDSAPublicKeySpec(p, ed25519);
|
||||
return new Ed25519PublicKey(publicSpec);
|
||||
|
||||
} catch (Buffer.BufferException be) {
|
||||
throw new SSHRuntimeException(be);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf) {
|
||||
EdDSAPublicKey key = (EdDSAPublicKey) pk;
|
||||
buf.putString(sType).putBytes(key.getAbyte());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isMyType(Key key) {
|
||||
return "EdDSA".equals(key.getAlgorithm());
|
||||
final byte[] out = new byte[in.length - i];
|
||||
System.arraycopy(in, i, out, 0, out.length);
|
||||
return out;
|
||||
}
|
||||
},
|
||||
|
||||
/** Unrecognized */
|
||||
UNKNOWN("unknown") {
|
||||
@Override
|
||||
public PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
||||
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
|
||||
throws GeneralSecurityException {
|
||||
throw new UnsupportedOperationException("Don't know how to decode key:" + sType);
|
||||
throw new UnsupportedOperationException("Don't know how to decode key:" + type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -241,7 +211,7 @@ public enum KeyType {
|
||||
this.sType = type;
|
||||
}
|
||||
|
||||
public abstract PublicKey readPubKeyFromBuffer(Buffer<?> buf)
|
||||
public abstract PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf)
|
||||
throws GeneralSecurityException;
|
||||
|
||||
public abstract void putPubKeyIntoBuffer(PublicKey pk, Buffer<?> buf);
|
||||
@@ -266,4 +236,5 @@ public enum KeyType {
|
||||
public String toString() {
|
||||
return sType;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package net.schmizz.sshj.common;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public interface LoggerFactory {
|
||||
Logger getLogger(String name);
|
||||
Logger getLogger(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Default SLF4J-based implementation of the SSHJ LoggerFactory.
|
||||
*/
|
||||
LoggerFactory DEFAULT = new LoggerFactory() {
|
||||
@Override
|
||||
public Logger getLogger(String name) {
|
||||
return org.slf4j.LoggerFactory.getLogger(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger(Class<?> clazz) {
|
||||
return org.slf4j.LoggerFactory.getLogger(clazz);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,7 +30,7 @@ public enum Message {
|
||||
|
||||
KEXDH_INIT(30),
|
||||
|
||||
/** { KEXDH_REPLY, KEXDH_GEX_GROUP, SSH_MSG_KEX_ECDH_REPLY } */
|
||||
/** { KEXDH_REPLY, KEXDH_GEX_GROUP } */
|
||||
KEXDH_31(31),
|
||||
|
||||
KEX_DH_GEX_INIT(32),
|
||||
@@ -46,9 +46,6 @@ public enum Message {
|
||||
USERAUTH_60(60),
|
||||
USERAUTH_INFO_RESPONSE(61),
|
||||
|
||||
USERAUTH_GSSAPI_EXCHANGE_COMPLETE(63),
|
||||
USERAUTH_GSSAPI_MIC(66),
|
||||
|
||||
GLOBAL_REQUEST(80),
|
||||
REQUEST_SUCCESS(81),
|
||||
REQUEST_FAILURE(82),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,25 +15,47 @@
|
||||
*/
|
||||
package net.schmizz.sshj.common;
|
||||
|
||||
import java.security.*;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyAgreement;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
|
||||
import static java.lang.String.format;
|
||||
// TODO refactor
|
||||
|
||||
/**
|
||||
* Static utility method relating to security facilities.
|
||||
*/
|
||||
/** Static utility method relating to security facilities. */
|
||||
public class SecurityUtils {
|
||||
|
||||
private static class BouncyCastleRegistration {
|
||||
|
||||
public void run()
|
||||
throws Exception {
|
||||
if (java.security.Security.getProvider(BOUNCY_CASTLE) == null) {
|
||||
LOG.debug("Trying to register BouncyCastle as a JCE provider");
|
||||
java.security.Security.addProvider(new BouncyCastleProvider());
|
||||
MessageDigest.getInstance("MD5", BOUNCY_CASTLE);
|
||||
KeyAgreement.getInstance("DH", BOUNCY_CASTLE);
|
||||
LOG.info("BouncyCastle registration succeeded");
|
||||
} else
|
||||
LOG.info("BouncyCastle already registered as a JCE provider");
|
||||
securityProvider = BOUNCY_CASTLE;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SecurityUtils.class);
|
||||
|
||||
/**
|
||||
* Identifier for the BouncyCastle JCE provider
|
||||
*/
|
||||
/** Identifier for the BouncyCastle JCE provider */
|
||||
public static final String BOUNCY_CASTLE = "BC";
|
||||
|
||||
/*
|
||||
@@ -45,42 +67,6 @@ public class SecurityUtils {
|
||||
private static Boolean registerBouncyCastle;
|
||||
private static boolean registrationDone;
|
||||
|
||||
public static boolean registerSecurityProvider(String providerClassName) {
|
||||
Provider provider = null;
|
||||
try {
|
||||
Class<?> name = Class.forName(providerClassName);
|
||||
provider = (Provider) name.newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
LOG.info("Security Provider class '{}' not found", providerClassName);
|
||||
} catch (InstantiationException e) {
|
||||
LOG.info("Security Provider class '{}' could not be created", providerClassName);
|
||||
} catch (IllegalAccessException e) {
|
||||
LOG.info("Security Provider class '{}' could not be accessed", providerClassName);
|
||||
}
|
||||
|
||||
if (provider == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (Security.getProvider(provider.getName()) == null) {
|
||||
Security.addProvider(provider);
|
||||
}
|
||||
|
||||
if (securityProvider == null) {
|
||||
MessageDigest.getInstance("MD5", provider.getName());
|
||||
KeyAgreement.getInstance("DH", provider.getName());
|
||||
setSecurityProvider(provider.getName());
|
||||
return true;
|
||||
}
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
LOG.info(format("Security Provider '%s' does not support necessary algorithm", providerClassName), e);
|
||||
} catch (NoSuchProviderException e) {
|
||||
LOG.info("Registration of Security Provider '{}' unexpectedly failed", providerClassName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static synchronized Cipher getCipher(String transformation)
|
||||
throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException {
|
||||
register();
|
||||
@@ -94,7 +80,9 @@ public class SecurityUtils {
|
||||
* Computes the fingerprint for a public key, in the standard SSH format, e.g. "4b:69:6c:72:6f:79:20:77:61:73:20:68:65:72:65:21"
|
||||
*
|
||||
* @param key the public key
|
||||
*
|
||||
* @return the fingerprint
|
||||
*
|
||||
* @see <a href="http://tools.ietf.org/html/draft-friedl-secsh-fingerprint-00">specification</a>
|
||||
*/
|
||||
public static String getFingerprint(PublicKey key) {
|
||||
@@ -117,7 +105,9 @@ public class SecurityUtils {
|
||||
* Creates a new instance of {@link KeyAgreement} with the given algorithm.
|
||||
*
|
||||
* @param algorithm key agreement algorithm
|
||||
*
|
||||
* @return new instance
|
||||
*
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws NoSuchProviderException
|
||||
*/
|
||||
@@ -134,7 +124,9 @@ public class SecurityUtils {
|
||||
* Creates a new instance of {@link KeyFactory} with the given algorithm.
|
||||
*
|
||||
* @param algorithm key factory algorithm e.g. RSA, DSA
|
||||
*
|
||||
* @return new instance
|
||||
*
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws NoSuchProviderException
|
||||
*/
|
||||
@@ -151,7 +143,9 @@ public class SecurityUtils {
|
||||
* Creates a new instance of {@link KeyPairGenerator} with the given algorithm.
|
||||
*
|
||||
* @param algorithm key pair generator algorithm
|
||||
*
|
||||
* @return new instance
|
||||
*
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws NoSuchProviderException
|
||||
*/
|
||||
@@ -168,7 +162,9 @@ public class SecurityUtils {
|
||||
* Create a new instance of {@link Mac} with the given algorithm.
|
||||
*
|
||||
* @param algorithm MAC algorithm
|
||||
*
|
||||
* @return new instance
|
||||
*
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws NoSuchProviderException
|
||||
*/
|
||||
@@ -185,7 +181,9 @@ public class SecurityUtils {
|
||||
* Create a new instance of {@link MessageDigest} with the given algorithm.
|
||||
*
|
||||
* @param algorithm MessageDigest algorithm name
|
||||
*
|
||||
* @return new instance
|
||||
*
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws NoSuchProviderException
|
||||
*/
|
||||
@@ -245,16 +243,20 @@ public class SecurityUtils {
|
||||
|
||||
private static void register() {
|
||||
if (!registrationDone) {
|
||||
if (securityProvider == null && (registerBouncyCastle == null || registerBouncyCastle)) {
|
||||
registerSecurityProvider("org.bouncycastle.jce.provider.BouncyCastleProvider");
|
||||
if (securityProvider == null && registerBouncyCastle == null) {
|
||||
LOG.info("BouncyCastle not registered, using the default JCE provider");
|
||||
} else if (securityProvider == null) {
|
||||
LOG.error("Failed to register BouncyCastle as the defaut JCE provider");
|
||||
throw new SSHRuntimeException("Failed to register BouncyCastle as the defaut JCE provider");
|
||||
if (securityProvider == null && (registerBouncyCastle == null || registerBouncyCastle))
|
||||
// Use an inner class to avoid a strong dependency on BouncyCastle
|
||||
try {
|
||||
new BouncyCastleRegistration().run();
|
||||
} catch (Throwable t) {
|
||||
if (registerBouncyCastle == null)
|
||||
LOG.info("BouncyCastle not registered, using the default JCE provider");
|
||||
else {
|
||||
LOG.error("Failed to register BouncyCastle as the defaut JCE provider");
|
||||
throw new SSHRuntimeException("Failed to register BouncyCastle as the defaut JCE provider", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
registrationDone = true;
|
||||
}
|
||||
registrationDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,10 +15,10 @@
|
||||
*/
|
||||
package net.schmizz.sshj.common;
|
||||
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
import net.schmizz.concurrent.Event;
|
||||
import net.schmizz.concurrent.ExceptionChainer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -39,8 +39,8 @@ public class StreamCopier {
|
||||
}
|
||||
};
|
||||
|
||||
private final LoggerFactory loggerFactory;
|
||||
private final Logger log;
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final InputStream in;
|
||||
private final OutputStream out;
|
||||
|
||||
@@ -50,11 +50,9 @@ public class StreamCopier {
|
||||
private boolean keepFlushing = true;
|
||||
private long length = -1;
|
||||
|
||||
public StreamCopier(InputStream in, OutputStream out, LoggerFactory loggerFactory) {
|
||||
public StreamCopier(InputStream in, OutputStream out) {
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
this.loggerFactory = loggerFactory;
|
||||
this.log = loggerFactory.getLogger(getClass());
|
||||
}
|
||||
|
||||
public StreamCopier bufSize(int bufSize) {
|
||||
@@ -93,7 +91,7 @@ public class StreamCopier {
|
||||
public IOException chain(Throwable t) {
|
||||
return (t instanceof IOException) ? (IOException) t : new IOException(t);
|
||||
}
|
||||
}, loggerFactory);
|
||||
});
|
||||
|
||||
new Thread() {
|
||||
{
|
||||
@@ -109,7 +107,7 @@ public class StreamCopier {
|
||||
log.debug("Done copying from {}", in);
|
||||
doneEvent.set();
|
||||
} catch (IOException ioe) {
|
||||
log.error(String.format("In pipe from %1$s to %2$s", in.toString(), out.toString()), ioe);
|
||||
log.error("In pipe from {} to {}: {}", in, out, ioe);
|
||||
doneEvent.deliverError(ioe);
|
||||
}
|
||||
}
|
||||
@@ -138,7 +136,7 @@ public class StreamCopier {
|
||||
|
||||
final double timeSeconds = (System.currentTimeMillis() - startTime) / 1000.0;
|
||||
final double sizeKiB = count / 1024.0;
|
||||
log.debug(String.format("%1$,.1f KiB transferred in %2$,.1f seconds (%3$,.2f KiB/s)", sizeKiB, timeSeconds, (sizeKiB / timeSeconds)));
|
||||
log.debug("{} KiB transferred in {} seconds ({} KiB/s)", sizeKiB, timeSeconds, (sizeKiB / timeSeconds));
|
||||
|
||||
if (length != -1 && read == -1)
|
||||
throw new IOException("Encountered EOF, could not transfer " + length + " bytes");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -156,4 +156,4 @@ public interface Connection {
|
||||
* @return The configured {@link net.schmizz.keepalive.KeepAlive} mechanism.
|
||||
*/
|
||||
KeepAlive getKeepAlive();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,12 @@ import net.schmizz.concurrent.Promise;
|
||||
import net.schmizz.keepalive.KeepAlive;
|
||||
import net.schmizz.keepalive.KeepAliveProvider;
|
||||
import net.schmizz.sshj.AbstractService;
|
||||
import net.schmizz.sshj.common.*;
|
||||
import net.schmizz.sshj.common.Buffer;
|
||||
import net.schmizz.sshj.common.DisconnectReason;
|
||||
import net.schmizz.sshj.common.ErrorNotifiable;
|
||||
import net.schmizz.sshj.common.Message;
|
||||
import net.schmizz.sshj.common.SSHException;
|
||||
import net.schmizz.sshj.common.SSHPacket;
|
||||
import net.schmizz.sshj.connection.channel.Channel;
|
||||
import net.schmizz.sshj.connection.channel.OpenFailException.Reason;
|
||||
import net.schmizz.sshj.connection.channel.forwarded.ForwardedChannelOpener;
|
||||
@@ -59,8 +64,9 @@ public class ConnectionImpl
|
||||
/**
|
||||
* Create with an associated {@link Transport}.
|
||||
*
|
||||
* @param config the ssh config
|
||||
* @param trans transport layer
|
||||
* @param keepAlive the keep alive provider
|
||||
* @param keepAlive
|
||||
*/
|
||||
public ConnectionImpl(Transport trans, KeepAliveProvider keepAlive) {
|
||||
super("ssh-connection", trans);
|
||||
@@ -199,7 +205,7 @@ public class ConnectionImpl
|
||||
|
||||
Promise<SSHPacket, ConnectionException> promise = null;
|
||||
if (wantReply) {
|
||||
promise = new Promise<SSHPacket, ConnectionException>("global req for " + name, ConnectionException.chainer, trans.getConfig().getLoggerFactory());
|
||||
promise = new Promise<SSHPacket, ConnectionException>("global req for " + name, ConnectionException.chainer);
|
||||
globalReqPromises.add(promise);
|
||||
}
|
||||
return promise;
|
||||
@@ -210,15 +216,13 @@ public class ConnectionImpl
|
||||
throws ConnectionException {
|
||||
synchronized (globalReqPromises) {
|
||||
Promise<SSHPacket, ConnectionException> gr = globalReqPromises.poll();
|
||||
if (gr == null) {
|
||||
if (gr == null)
|
||||
throw new ConnectionException(DisconnectReason.PROTOCOL_ERROR,
|
||||
"Got a global request response when none was requested");
|
||||
} else if (response == null) {
|
||||
"Got a global request response when none was requested");
|
||||
else if (response == null)
|
||||
gr.deliverError(new ConnectionException("Global request [" + gr + "] failed"));
|
||||
} else {
|
||||
// To prevent a race condition, copy the packet before delivering, as it will be handled in a different thread.
|
||||
gr.deliver(new SSHPacket(response));
|
||||
}
|
||||
else
|
||||
gr.deliver(response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,4 +278,4 @@ public class ConnectionImpl
|
||||
return keepAlive;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,12 +17,19 @@ package net.schmizz.sshj.connection.channel;
|
||||
|
||||
import net.schmizz.concurrent.ErrorDeliveryUtil;
|
||||
import net.schmizz.concurrent.Event;
|
||||
import net.schmizz.sshj.common.*;
|
||||
import net.schmizz.sshj.common.Buffer;
|
||||
import net.schmizz.sshj.common.ByteArrayUtils;
|
||||
import net.schmizz.sshj.common.DisconnectReason;
|
||||
import net.schmizz.sshj.common.IOUtils;
|
||||
import net.schmizz.sshj.common.Message;
|
||||
import net.schmizz.sshj.common.SSHException;
|
||||
import net.schmizz.sshj.common.SSHPacket;
|
||||
import net.schmizz.sshj.connection.Connection;
|
||||
import net.schmizz.sshj.connection.ConnectionException;
|
||||
import net.schmizz.sshj.transport.Transport;
|
||||
import net.schmizz.sshj.transport.TransportException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@@ -37,8 +44,7 @@ public abstract class AbstractChannel
|
||||
private static final int REMOTE_MAX_PACKET_SIZE_CEILING = 1024 * 1024;
|
||||
|
||||
/** Logger */
|
||||
protected final LoggerFactory loggerFactory;
|
||||
protected final Logger log;
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
/** Transport layer */
|
||||
protected final Transport trans;
|
||||
@@ -52,8 +58,6 @@ public abstract class AbstractChannel
|
||||
/** Remote recipient ID */
|
||||
private int recipient;
|
||||
|
||||
private boolean eof = false;
|
||||
|
||||
private final Queue<Event<ConnectionException>> chanReqResponseEvents = new LinkedList<Event<ConnectionException>>();
|
||||
|
||||
/* The lock used by to create the open & close events */
|
||||
@@ -79,23 +83,21 @@ public abstract class AbstractChannel
|
||||
|
||||
protected AbstractChannel(Connection conn, String type) {
|
||||
this.conn = conn;
|
||||
this.loggerFactory = conn.getTransport().getConfig().getLoggerFactory();
|
||||
this.type = type;
|
||||
this.log = loggerFactory.getLogger(getClass());
|
||||
this.trans = conn.getTransport();
|
||||
|
||||
id = conn.nextID();
|
||||
|
||||
lwin = new Window.Local(conn.getWindowSize(), conn.getMaxPacketSize(), loggerFactory);
|
||||
lwin = new Window.Local(conn.getWindowSize(), conn.getMaxPacketSize());
|
||||
in = new ChannelInputStream(this, trans, lwin);
|
||||
|
||||
openEvent = new Event<ConnectionException>("chan#" + id + " / " + "open", ConnectionException.chainer, openCloseLock, loggerFactory);
|
||||
closeEvent = new Event<ConnectionException>("chan#" + id + " / " + "close", ConnectionException.chainer, openCloseLock, loggerFactory);
|
||||
openEvent = new Event<ConnectionException>("chan#" + id + " / " + "open", ConnectionException.chainer, openCloseLock);
|
||||
closeEvent = new Event<ConnectionException>("chan#" + id + " / " + "close", ConnectionException.chainer, openCloseLock);
|
||||
}
|
||||
|
||||
protected void init(int recipient, long remoteWinSize, long remoteMaxPacketSize) {
|
||||
this.recipient = recipient;
|
||||
rwin = new Window.Remote(remoteWinSize, (int) Math.min(remoteMaxPacketSize, REMOTE_MAX_PACKET_SIZE_CEILING), loggerFactory);
|
||||
rwin = new Window.Remote(remoteWinSize, (int) Math.min(remoteMaxPacketSize, REMOTE_MAX_PACKET_SIZE_CEILING));
|
||||
out = new ChannelOutputStream(this, trans, rwin);
|
||||
log.debug("Initialized - {}", this);
|
||||
}
|
||||
@@ -193,16 +195,6 @@ public abstract class AbstractChannel
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEOF() {
|
||||
return eof;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoggerFactory getLoggerFactory() {
|
||||
return loggerFactory;
|
||||
}
|
||||
|
||||
private void gotClose()
|
||||
throws TransportException {
|
||||
log.debug("Got close");
|
||||
@@ -370,7 +362,7 @@ public abstract class AbstractChannel
|
||||
Event<ConnectionException> responseEvent = null;
|
||||
if (wantReply) {
|
||||
responseEvent = new Event<ConnectionException>("chan#" + id + " / " + "chanreq for " + reqType,
|
||||
ConnectionException.chainer, loggerFactory);
|
||||
ConnectionException.chainer);
|
||||
chanReqResponseEvents.add(responseEvent);
|
||||
}
|
||||
return responseEvent;
|
||||
@@ -401,7 +393,6 @@ public abstract class AbstractChannel
|
||||
/** Called when EOF has been received. Subclasses can override but must call super. */
|
||||
protected void eofInputStreams() {
|
||||
in.eof();
|
||||
eof = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -411,4 +402,4 @@ public abstract class AbstractChannel
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,6 @@
|
||||
package net.schmizz.sshj.connection.channel;
|
||||
|
||||
import net.schmizz.sshj.common.ErrorNotifiable;
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
import net.schmizz.sshj.common.SSHPacketHandler;
|
||||
import net.schmizz.sshj.connection.ConnectionException;
|
||||
import net.schmizz.sshj.transport.TransportException;
|
||||
@@ -26,15 +25,13 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A channel is the basic medium for application-layer data on top of an SSH transport.
|
||||
*/
|
||||
public interface Channel extends Closeable, SSHPacketHandler, ErrorNotifiable {
|
||||
/** A channel is the basic medium for application-layer data on top of an SSH transport. */
|
||||
public interface Channel
|
||||
extends Closeable, SSHPacketHandler, ErrorNotifiable {
|
||||
|
||||
/**
|
||||
* Direct channels are those that are initiated by us.
|
||||
*/
|
||||
interface Direct extends Channel {
|
||||
/** Direct channels are those that are initiated by us. */
|
||||
interface Direct
|
||||
extends Channel {
|
||||
|
||||
/**
|
||||
* Request opening this channel from remote end.
|
||||
@@ -43,30 +40,27 @@ public interface Channel extends Closeable, SSHPacketHandler, ErrorNotifiable {
|
||||
* @throws ConnectionException other connection-layer error
|
||||
* @throws TransportException error writing packets etc.
|
||||
*/
|
||||
void open() throws ConnectionException, TransportException;
|
||||
void open()
|
||||
throws ConnectionException, TransportException;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwarded channels are those that are initiated by the server.
|
||||
*/
|
||||
interface Forwarded extends Channel {
|
||||
/** Forwarded channels are those that are initiated by the server. */
|
||||
interface Forwarded
|
||||
extends Channel {
|
||||
|
||||
/**
|
||||
* Confirm {@code CHANNEL_OPEN} request.
|
||||
*
|
||||
* @throws TransportException error sending confirmation packet
|
||||
*/
|
||||
void confirm() throws TransportException;
|
||||
void confirm()
|
||||
throws TransportException;
|
||||
|
||||
/**
|
||||
* @return the IP of where the forwarded connection originates.
|
||||
*/
|
||||
/** @return the IP of where the forwarded connection originates. */
|
||||
String getOriginatorIP();
|
||||
|
||||
/**
|
||||
* @return port from which the forwarded connection originates.
|
||||
*/
|
||||
/** @return port from which the forwarded connection originates. */
|
||||
int getOriginatorPort();
|
||||
|
||||
/**
|
||||
@@ -74,73 +68,55 @@ public interface Channel extends Closeable, SSHPacketHandler, ErrorNotifiable {
|
||||
*
|
||||
* @param reason indicate {@link OpenFailException.Reason reason} for rejection of the request
|
||||
* @param message indicate a message for why the request is rejected
|
||||
*
|
||||
* @throws TransportException error sending rejection packet
|
||||
*/
|
||||
void reject(OpenFailException.Reason reason, String message) throws TransportException;
|
||||
void reject(OpenFailException.Reason reason, String message)
|
||||
throws TransportException;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close this channel.
|
||||
*/
|
||||
/** Close this channel. */
|
||||
@Override
|
||||
void close() throws TransportException, ConnectionException;
|
||||
void close()
|
||||
throws TransportException, ConnectionException;
|
||||
|
||||
/**
|
||||
* @return whether auto-expansion of local window is set.
|
||||
*
|
||||
* @see #setAutoExpand(boolean)
|
||||
*/
|
||||
boolean getAutoExpand();
|
||||
|
||||
/**
|
||||
* @return the channel ID
|
||||
*/
|
||||
/** @return the channel ID */
|
||||
int getID();
|
||||
|
||||
/**
|
||||
* @return the {@code InputStream} for this channel.
|
||||
*/
|
||||
/** @return the {@code InputStream} for this channel. */
|
||||
InputStream getInputStream();
|
||||
|
||||
/**
|
||||
* @return the maximum packet size that we have specified.
|
||||
*/
|
||||
/** @return the maximum packet size that we have specified. */
|
||||
int getLocalMaxPacketSize();
|
||||
|
||||
/**
|
||||
* @return the current local window size.
|
||||
*/
|
||||
/** @return the current local window size. */
|
||||
long getLocalWinSize();
|
||||
|
||||
/**
|
||||
* @return an {@code OutputStream} for this channel.
|
||||
*/
|
||||
/** @return an {@code OutputStream} for this channel. */
|
||||
OutputStream getOutputStream();
|
||||
|
||||
/**
|
||||
* @return the channel ID at the remote end.
|
||||
*/
|
||||
/** @return the channel ID at the remote end. */
|
||||
int getRecipient();
|
||||
|
||||
/**
|
||||
* @return the maximum packet size as specified by the remote end.
|
||||
*/
|
||||
/** @return the maximum packet size as specified by the remote end. */
|
||||
int getRemoteMaxPacketSize();
|
||||
|
||||
/**
|
||||
* @return the current remote window size.
|
||||
*/
|
||||
/** @return the current remote window size. */
|
||||
long getRemoteWinSize();
|
||||
|
||||
/**
|
||||
* @return the channel type identifier.
|
||||
*/
|
||||
/** @return the channel type identifier. */
|
||||
String getType();
|
||||
|
||||
/**
|
||||
* @return whether the channel is open.
|
||||
*/
|
||||
/** @return whether the channel is open. */
|
||||
boolean isOpen();
|
||||
|
||||
/**
|
||||
@@ -152,17 +128,10 @@ public interface Channel extends Closeable, SSHPacketHandler, ErrorNotifiable {
|
||||
*/
|
||||
void setAutoExpand(boolean autoExpand);
|
||||
|
||||
void join() throws ConnectionException;
|
||||
void join()
|
||||
throws ConnectionException;
|
||||
|
||||
void join(long timeout, TimeUnit unit) throws ConnectionException;
|
||||
void join(long timeout, TimeUnit unit)
|
||||
throws ConnectionException;
|
||||
|
||||
/**
|
||||
* Returns whether EOF has been received.
|
||||
*/
|
||||
boolean isEOF();
|
||||
|
||||
/**
|
||||
* Get the LoggerFactory associated with the SSH client.
|
||||
*/
|
||||
LoggerFactory getLoggerFactory();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,11 @@
|
||||
*/
|
||||
package net.schmizz.sshj.connection.channel;
|
||||
|
||||
import net.schmizz.sshj.common.*;
|
||||
import net.schmizz.sshj.common.Buffer;
|
||||
import net.schmizz.sshj.common.ErrorNotifiable;
|
||||
import net.schmizz.sshj.common.Message;
|
||||
import net.schmizz.sshj.common.SSHException;
|
||||
import net.schmizz.sshj.common.SSHPacket;
|
||||
import net.schmizz.sshj.connection.ConnectionException;
|
||||
import net.schmizz.sshj.transport.Transport;
|
||||
import net.schmizz.sshj.transport.TransportException;
|
||||
@@ -34,7 +38,7 @@ public final class ChannelInputStream
|
||||
extends InputStream
|
||||
implements ErrorNotifiable {
|
||||
|
||||
private final Logger log;
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final Channel chan;
|
||||
private final Transport trans;
|
||||
@@ -47,7 +51,6 @@ public final class ChannelInputStream
|
||||
|
||||
public ChannelInputStream(Channel chan, Transport trans, Window.Local win) {
|
||||
this.chan = chan;
|
||||
log = chan.getLoggerFactory().getLogger(getClass());
|
||||
this.trans = trans;
|
||||
this.win = win;
|
||||
buf = new Buffer.PlainBuffer(chan.getLocalMaxPacketSize());
|
||||
@@ -127,12 +130,7 @@ public final class ChannelInputStream
|
||||
buf.putRawBytes(data, offset, len);
|
||||
buf.notifyAll();
|
||||
}
|
||||
// Potential fix for #203 (window consumed below 0).
|
||||
// This seems to be a race condition if we receive more data, while we're already sending a SSH_MSG_CHANNEL_WINDOW_ADJUST
|
||||
// And the window has not expanded yet.
|
||||
synchronized (win) {
|
||||
win.consume(len);
|
||||
}
|
||||
win.consume(len);
|
||||
if (chan.getAutoExpand())
|
||||
checkWindow();
|
||||
}
|
||||
@@ -155,4 +153,4 @@ public final class ChannelInputStream
|
||||
return "< ChannelInputStream for Channel #" + chan.getID() + " >";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,11 @@
|
||||
*/
|
||||
package net.schmizz.sshj.connection.channel;
|
||||
|
||||
import net.schmizz.sshj.common.*;
|
||||
import net.schmizz.sshj.common.Buffer;
|
||||
import net.schmizz.sshj.common.ErrorNotifiable;
|
||||
import net.schmizz.sshj.common.Message;
|
||||
import net.schmizz.sshj.common.SSHException;
|
||||
import net.schmizz.sshj.common.SSHPacket;
|
||||
import net.schmizz.sshj.connection.ConnectionException;
|
||||
import net.schmizz.sshj.transport.Transport;
|
||||
import net.schmizz.sshj.transport.TransportException;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,12 +18,11 @@ package net.schmizz.sshj.connection.channel;
|
||||
import net.schmizz.concurrent.Event;
|
||||
import net.schmizz.sshj.common.IOUtils;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.hierynomus.sshj.backport.Sockets.asCloseable;
|
||||
|
||||
public class SocketStreamCopyMonitor
|
||||
extends Thread {
|
||||
|
||||
@@ -33,6 +32,16 @@ public class SocketStreamCopyMonitor
|
||||
setDaemon(true);
|
||||
}
|
||||
|
||||
private static Closeable wrapSocket(final Socket socket) {
|
||||
return new Closeable() {
|
||||
@Override
|
||||
public void close()
|
||||
throws IOException {
|
||||
socket.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void monitor(final int frequency, final TimeUnit unit,
|
||||
final Event<IOException> x, final Event<IOException> y,
|
||||
final Channel channel, final Socket socket) {
|
||||
@@ -45,7 +54,7 @@ public class SocketStreamCopyMonitor
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
} finally {
|
||||
IOUtils.closeQuietly(channel, asCloseable(socket));
|
||||
IOUtils.closeQuietly(channel, wrapSocket(socket));
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,14 +15,14 @@
|
||||
*/
|
||||
package net.schmizz.sshj.connection.channel;
|
||||
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
import net.schmizz.sshj.common.SSHRuntimeException;
|
||||
import net.schmizz.sshj.connection.ConnectionException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class Window {
|
||||
|
||||
protected final Logger log;
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected final Object lock = new Object();
|
||||
|
||||
@@ -30,10 +30,9 @@ public abstract class Window {
|
||||
|
||||
protected long size;
|
||||
|
||||
public Window(long initialWinSize, int maxPacketSize, LoggerFactory loggerFactory) {
|
||||
public Window(long initialWinSize, int maxPacketSize) {
|
||||
size = initialWinSize;
|
||||
this.maxPacketSize = maxPacketSize;
|
||||
log = loggerFactory.getLogger(getClass());
|
||||
}
|
||||
|
||||
public void expand(long inc) {
|
||||
@@ -73,8 +72,8 @@ public abstract class Window {
|
||||
public static final class Remote
|
||||
extends Window {
|
||||
|
||||
public Remote(long initialWinSize, int maxPacketSize, LoggerFactory loggerFactory) {
|
||||
super(initialWinSize, maxPacketSize, loggerFactory);
|
||||
public Remote(long initialWinSize, int maxPacketSize) {
|
||||
super(initialWinSize, maxPacketSize);
|
||||
}
|
||||
|
||||
public long awaitExpansion(long was)
|
||||
@@ -109,8 +108,8 @@ public abstract class Window {
|
||||
private final long initialSize;
|
||||
private final long threshold;
|
||||
|
||||
public Local(long initialWinSize, int maxPacketSize, LoggerFactory loggerFactory) {
|
||||
super(initialWinSize, maxPacketSize, loggerFactory);
|
||||
public Local(long initialWinSize, int maxPacketSize) {
|
||||
super(initialWinSize, maxPacketSize);
|
||||
this.initialSize = initialWinSize;
|
||||
threshold = Math.min(maxPacketSize * 20, initialSize / 4);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -94,4 +94,4 @@ public abstract class AbstractDirectChannel
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,22 +16,20 @@
|
||||
package net.schmizz.sshj.connection.channel.direct;
|
||||
|
||||
import net.schmizz.concurrent.Event;
|
||||
import net.schmizz.sshj.common.IOUtils;
|
||||
import net.schmizz.sshj.common.LoggerFactory;
|
||||
import net.schmizz.sshj.common.SSHPacket;
|
||||
import net.schmizz.sshj.common.StreamCopier;
|
||||
import net.schmizz.sshj.connection.Connection;
|
||||
import net.schmizz.sshj.connection.ConnectionException;
|
||||
import net.schmizz.sshj.connection.channel.SocketStreamCopyMonitor;
|
||||
import net.schmizz.sshj.transport.TransportException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.hierynomus.sshj.backport.Sockets.asCloseable;
|
||||
|
||||
public class LocalPortForwarder {
|
||||
|
||||
public static class Parameters {
|
||||
@@ -82,10 +80,10 @@ public class LocalPortForwarder {
|
||||
throws IOException {
|
||||
socket.setSendBufferSize(getLocalMaxPacketSize());
|
||||
socket.setReceiveBufferSize(getRemoteMaxPacketSize());
|
||||
final Event<IOException> soc2chan = new StreamCopier(socket.getInputStream(), getOutputStream(), loggerFactory)
|
||||
final Event<IOException> soc2chan = new StreamCopier(socket.getInputStream(), getOutputStream())
|
||||
.bufSize(getRemoteMaxPacketSize())
|
||||
.spawnDaemon("soc2chan");
|
||||
final Event<IOException> chan2soc = new StreamCopier(getInputStream(), socket.getOutputStream(), loggerFactory)
|
||||
final Event<IOException> chan2soc = new StreamCopier(getInputStream(), socket.getOutputStream())
|
||||
.bufSize(getLocalMaxPacketSize())
|
||||
.spawnDaemon("chan2soc");
|
||||
SocketStreamCopyMonitor.monitor(5, TimeUnit.SECONDS, soc2chan, chan2soc, this, socket);
|
||||
@@ -102,29 +100,23 @@ public class LocalPortForwarder {
|
||||
|
||||
}
|
||||
|
||||
private final LoggerFactory loggerFactory;
|
||||
private final Logger log;
|
||||
private final Logger log = LoggerFactory.getLogger(LocalPortForwarder.class);
|
||||
|
||||
private final Connection conn;
|
||||
private final Parameters parameters;
|
||||
private final ServerSocket serverSocket;
|
||||
|
||||
public LocalPortForwarder(Connection conn, Parameters parameters, ServerSocket serverSocket, LoggerFactory loggerFactory) {
|
||||
public LocalPortForwarder(Connection conn, Parameters parameters, ServerSocket serverSocket) {
|
||||
this.conn = conn;
|
||||
this.parameters = parameters;
|
||||
this.serverSocket = serverSocket;
|
||||
this.loggerFactory = loggerFactory;
|
||||
this.log = loggerFactory.getLogger(getClass());
|
||||
}
|
||||
|
||||
private void startChannel(Socket socket) throws IOException {
|
||||
DirectTCPIPChannel chan = new DirectTCPIPChannel(conn, socket, parameters);
|
||||
try {
|
||||
chan.open();
|
||||
chan.start();
|
||||
} catch (IOException e) {
|
||||
IOUtils.closeQuietly(chan, asCloseable(socket));
|
||||
throw e;
|
||||
}
|
||||
protected DirectTCPIPChannel openChannel(Socket socket)
|
||||
throws TransportException, ConnectionException {
|
||||
final DirectTCPIPChannel chan = new DirectTCPIPChannel(conn, socket, parameters);
|
||||
chan.open();
|
||||
return chan;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,33 +128,11 @@ public class LocalPortForwarder {
|
||||
throws IOException {
|
||||
log.info("Listening on {}", serverSocket.getLocalSocketAddress());
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
try {
|
||||
final Socket socket = serverSocket.accept();
|
||||
log.debug("Got connection from {}", socket.getRemoteSocketAddress());
|
||||
startChannel(socket);
|
||||
} catch (SocketException e) {
|
||||
if (!serverSocket.isClosed()) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (serverSocket.isClosed()) {
|
||||
log.debug("LocalPortForwarder closed");
|
||||
} else {
|
||||
log.debug("LocalPortForwarder interrupted!");
|
||||
final Socket socket = serverSocket.accept();
|
||||
log.debug("Got connection from {}", socket.getRemoteSocketAddress());
|
||||
openChannel(socket).start();
|
||||
}
|
||||
log.debug("Interrupted!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the ServerSocket that's listening for connections to forward.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if (!serverSocket.isClosed()) {
|
||||
log.info("Closing listener on {}", serverSocket.getLocalSocketAddress());
|
||||
serverSocket.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -48,24 +48,18 @@ public interface Session
|
||||
/**
|
||||
* If the command exit violently {@link #getExitSignal() with a signal}, an error message would have been
|
||||
* received and can be retrieved via this method. Otherwise, this method will return {@code null}.
|
||||
* <p/>
|
||||
* <strong>NOTE: </strong> Always call {@link #close()} first before inspecting the exit error message.
|
||||
*/
|
||||
String getExitErrorMessage();
|
||||
|
||||
/**
|
||||
* Returns the {@link Signal signal} if the command exit violently, or {@code null} if this information was not
|
||||
* received.
|
||||
* <p/>
|
||||
* <strong>NOTE: </strong> Always call {@link #close()} first before inspecting the exit signal.
|
||||
*/
|
||||
Signal getExitSignal();
|
||||
|
||||
/**
|
||||
* Returns the exit status of the command if it was received, or {@code null} if this information was not
|
||||
* received.
|
||||
* <p/>
|
||||
* <strong>NOTE: </strong> Always call {@link #close()} first before inspecting the exit status.
|
||||
*/
|
||||
Integer getExitStatus();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,12 @@
|
||||
*/
|
||||
package net.schmizz.sshj.connection.channel.direct;
|
||||
|
||||
import net.schmizz.sshj.common.*;
|
||||
import net.schmizz.sshj.common.Buffer;
|
||||
import net.schmizz.sshj.common.DisconnectReason;
|
||||
import net.schmizz.sshj.common.IOUtils;
|
||||
import net.schmizz.sshj.common.SSHException;
|
||||
import net.schmizz.sshj.common.SSHPacket;
|
||||
import net.schmizz.sshj.common.SSHRuntimeException;
|
||||
import net.schmizz.sshj.connection.Connection;
|
||||
import net.schmizz.sshj.connection.ConnectionException;
|
||||
import net.schmizz.sshj.connection.channel.ChannelInputStream;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -73,4 +73,4 @@ public abstract class AbstractForwardedChannel
|
||||
return origPort;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,14 +29,14 @@ import java.io.IOException;
|
||||
public abstract class AbstractForwardedChannelOpener
|
||||
implements ForwardedChannelOpener {
|
||||
|
||||
protected final Logger log;
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected final String chanType;
|
||||
protected final Connection conn;
|
||||
|
||||
protected AbstractForwardedChannelOpener(String chanType, Connection conn) {
|
||||
this.chanType = chanType;
|
||||
this.conn = conn;
|
||||
log = conn.getTransport().getConfig().getLoggerFactory().getLogger(getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,4 +72,4 @@ public abstract class AbstractForwardedChannelOpener
|
||||
}.start();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -117,34 +117,6 @@ public class RemotePortForwarder
|
||||
return address + ":" + port;
|
||||
}
|
||||
|
||||
private boolean handles(ForwardedTCPIPChannel channel) {
|
||||
Forward channelForward = channel.getParentForward();
|
||||
if (channelForward.getPort() != port) {
|
||||
return false;
|
||||
}
|
||||
if ("".equals(address)) {
|
||||
// This forward handles all protocols
|
||||
return true;
|
||||
}
|
||||
if (channelForward.address.equals(address)) {
|
||||
// Addresses match up
|
||||
return true;
|
||||
}
|
||||
if ("localhost".equals(address) && (channelForward.address.equals("127.0.0.1") || channelForward.address.equals("::1"))) {
|
||||
// Localhost special case.
|
||||
return true;
|
||||
}
|
||||
if ("::".equals(address) && channelForward.address.indexOf("::") > 0) {
|
||||
// Listen on all IPv6
|
||||
return true;
|
||||
}
|
||||
if ("0.0.0.0".equals(address) && channelForward.address.indexOf('.') > 0) {
|
||||
// Listen on all IPv4
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A {@code forwarded-tcpip} channel. */
|
||||
@@ -252,15 +224,11 @@ public class RemotePortForwarder
|
||||
} catch (Buffer.BufferException be) {
|
||||
throw new ConnectionException(be);
|
||||
}
|
||||
|
||||
for (Forward forward : listeners.keySet()) {
|
||||
if (forward.handles(chan)) {
|
||||
callListener(listeners.get(forward), chan);
|
||||
return;
|
||||
}
|
||||
}
|
||||
chan.reject(OpenFailException.Reason.ADMINISTRATIVELY_PROHIBITED, "Forwarding was not requested on `"
|
||||
+ chan.getParentForward() + "`");
|
||||
if (listeners.containsKey(chan.getParentForward()))
|
||||
callListener(listeners.get(chan.getParentForward()), chan);
|
||||
else
|
||||
chan.reject(OpenFailException.Reason.ADMINISTRATIVELY_PROHIBITED, "Forwarding was not requested on `"
|
||||
+ chan.getParentForward() + "`");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,8 @@ import net.schmizz.concurrent.Event;
|
||||
import net.schmizz.sshj.common.StreamCopier;
|
||||
import net.schmizz.sshj.connection.channel.Channel;
|
||||
import net.schmizz.sshj.connection.channel.SocketStreamCopyMonitor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
@@ -29,6 +31,8 @@ import java.util.concurrent.TimeUnit;
|
||||
public class SocketForwardingConnectListener
|
||||
implements ConnectListener {
|
||||
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected final SocketAddress addr;
|
||||
|
||||
/** Create with a {@link SocketAddress} this listener will forward to. */
|
||||
@@ -40,7 +44,7 @@ public class SocketForwardingConnectListener
|
||||
@Override
|
||||
public void gotConnect(Channel.Forwarded chan)
|
||||
throws IOException {
|
||||
chan.getLoggerFactory().getLogger(getClass()).debug("New connection from {}:{}", chan.getOriginatorIP(), chan.getOriginatorPort());
|
||||
log.debug("New connection from {}:{}", chan.getOriginatorIP(), chan.getOriginatorPort());
|
||||
|
||||
final Socket sock = new Socket();
|
||||
sock.setSendBufferSize(chan.getLocalMaxPacketSize());
|
||||
@@ -51,11 +55,11 @@ public class SocketForwardingConnectListener
|
||||
// ok so far -- could connect, let's confirm the channel
|
||||
chan.confirm();
|
||||
|
||||
final Event<IOException> soc2chan = new StreamCopier(sock.getInputStream(), chan.getOutputStream(), chan.getLoggerFactory())
|
||||
final Event<IOException> soc2chan = new StreamCopier(sock.getInputStream(), chan.getOutputStream())
|
||||
.bufSize(chan.getRemoteMaxPacketSize())
|
||||
.spawnDaemon("soc2chan");
|
||||
|
||||
final Event<IOException> chan2soc = new StreamCopier(chan.getInputStream(), sock.getOutputStream(), chan.getLoggerFactory())
|
||||
final Event<IOException> chan2soc = new StreamCopier(chan.getInputStream(), sock.getOutputStream())
|
||||
.bufSize(chan.getLocalMaxPacketSize())
|
||||
.spawnDaemon("chan2soc");
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -222,7 +222,7 @@ public final class FileAttributes {
|
||||
sb.append("size=").append(size).append(";");
|
||||
|
||||
if (has(Flag.UIDGID))
|
||||
sb.append("uid=").append(uid).append(",gid=").append(gid).append(";");
|
||||
sb.append("uid=").append(size).append(",gid=").append(gid).append(";");
|
||||
|
||||
if (has(Flag.MODE))
|
||||
sb.append("mode=").append(mode.toString()).append(";");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,7 +36,7 @@ public class FileMode {
|
||||
/** directory */
|
||||
DIRECTORY(0040000),
|
||||
/** symbolic link */
|
||||
SYMLINK(0120000),
|
||||
SYMKLINK(0120000),
|
||||
/** unknown */
|
||||
UNKNOWN(0);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@ package net.schmizz.sshj.sftp;
|
||||
|
||||
import net.schmizz.concurrent.Promise;
|
||||
import net.schmizz.sshj.common.SSHException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -29,7 +30,7 @@ public class PacketReader
|
||||
extends Thread {
|
||||
|
||||
/** Logger */
|
||||
private final Logger log;
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final InputStream in;
|
||||
private final Map<Long, Promise<Response, SFTPException>> promises = new ConcurrentHashMap<Long, Promise<Response, SFTPException>>();
|
||||
@@ -39,7 +40,6 @@ public class PacketReader
|
||||
|
||||
public PacketReader(SFTPEngine engine) {
|
||||
this.engine = engine;
|
||||
log = engine.getLoggerFactory().getLogger(getClass());
|
||||
this.in = engine.getSubsystem().getInputStream();
|
||||
setName("sftp reader");
|
||||
}
|
||||
@@ -107,7 +107,7 @@ public class PacketReader
|
||||
|
||||
public Promise<Response, SFTPException> expectResponseTo(long requestId) {
|
||||
final Promise<Response, SFTPException> promise
|
||||
= new Promise<Response, SFTPException>("sftp / " + requestId, SFTPException.chainer, engine.getLoggerFactory());
|
||||
= new Promise<Response, SFTPException>("sftp / " + requestId, SFTPException.chainer);
|
||||
promises.put(requestId, promise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -63,4 +63,4 @@ public class PathComponents {
|
||||
return "[parent=" + parent + "; name=" + name + "; path=" + path + "]";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,12 @@
|
||||
*/
|
||||
package net.schmizz.sshj.sftp;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
|
||||
public class RandomAccessRemoteFile
|
||||
implements DataInput, DataOutput {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,7 +25,7 @@ import java.util.concurrent.TimeUnit;
|
||||
public class RemoteDirectory
|
||||
extends RemoteResource {
|
||||
|
||||
public RemoteDirectory(SFTPEngine requester, String path, byte[] handle) {
|
||||
public RemoteDirectory(Requester requester, String path, byte[] handle) {
|
||||
super(requester, path, handle);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,6 @@ import net.schmizz.concurrent.Promise;
|
||||
import net.schmizz.sshj.common.Buffer;
|
||||
import net.schmizz.sshj.sftp.Response.StatusCode;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@@ -30,35 +29,41 @@ import java.util.concurrent.TimeUnit;
|
||||
public class RemoteFile
|
||||
extends RemoteResource {
|
||||
|
||||
public RemoteFile(SFTPEngine requester, String path, byte[] handle) {
|
||||
public RemoteFile(Requester requester, String path, byte[] handle) {
|
||||
super(requester, path, handle);
|
||||
}
|
||||
|
||||
public FileAttributes fetchAttributes() throws IOException {
|
||||
public FileAttributes fetchAttributes()
|
||||
throws IOException {
|
||||
return requester.request(newRequest(PacketType.FSTAT))
|
||||
.retrieve(requester.getTimeoutMs(), TimeUnit.MILLISECONDS)
|
||||
.ensurePacketTypeIs(PacketType.ATTRS)
|
||||
.readFileAttributes();
|
||||
}
|
||||
|
||||
public long length() throws IOException {
|
||||
public long length()
|
||||
throws IOException {
|
||||
return fetchAttributes().getSize();
|
||||
}
|
||||
|
||||
public void setLength(long len) throws IOException {
|
||||
public void setLength(long len)
|
||||
throws IOException {
|
||||
setAttributes(new FileAttributes.Builder().withSize(len).build());
|
||||
}
|
||||
|
||||
public int read(long fileOffset, byte[] to, int offset, int len) throws IOException {
|
||||
public int read(long fileOffset, byte[] to, int offset, int len)
|
||||
throws IOException {
|
||||
final Response res = asyncRead(fileOffset, len).retrieve(requester.getTimeoutMs(), TimeUnit.MILLISECONDS);
|
||||
return checkReadResponse(res, to, offset);
|
||||
}
|
||||
|
||||
protected Promise<Response, SFTPException> asyncRead(long fileOffset, int len) throws IOException {
|
||||
protected Promise<Response, SFTPException> asyncRead(long fileOffset, int len)
|
||||
throws IOException {
|
||||
return requester.request(newRequest(PacketType.READ).putUInt64(fileOffset).putUInt32(len));
|
||||
}
|
||||
|
||||
protected int checkReadResponse(Response res, byte[] to, int offset) throws Buffer.BufferException, SFTPException {
|
||||
protected int checkReadResponse(Response res, byte[] to, int offset)
|
||||
throws Buffer.BufferException, SFTPException {
|
||||
switch (res.getType()) {
|
||||
case DATA:
|
||||
int recvLen = res.readUInt32AsInt();
|
||||
@@ -74,25 +79,27 @@ public class RemoteFile
|
||||
}
|
||||
}
|
||||
|
||||
public void write(long fileOffset, byte[] data, int off, int len) throws IOException {
|
||||
public void write(long fileOffset, byte[] data, int off, int len)
|
||||
throws IOException {
|
||||
checkWriteResponse(asyncWrite(fileOffset, data, off, len));
|
||||
}
|
||||
|
||||
protected Promise<Response, SFTPException> asyncWrite(long fileOffset, byte[] data, int off, int len)
|
||||
throws IOException {
|
||||
return requester.request(newRequest(PacketType.WRITE)
|
||||
.putUInt64(fileOffset)
|
||||
// TODO The SFTP spec claims this field is unneeded...? See #187
|
||||
.putUInt32(len)
|
||||
.putRawBytes(data, off, len)
|
||||
.putUInt64(fileOffset)
|
||||
.putUInt32(len - off)
|
||||
.putRawBytes(data, off, len)
|
||||
);
|
||||
}
|
||||
|
||||
private void checkWriteResponse(Promise<Response, SFTPException> responsePromise) throws SFTPException {
|
||||
private void checkWriteResponse(Promise<Response, SFTPException> responsePromise)
|
||||
throws SFTPException {
|
||||
responsePromise.retrieve(requester.getTimeoutMs(), TimeUnit.MILLISECONDS).ensureStatusPacketIsOK();
|
||||
}
|
||||
|
||||
public void setAttributes(FileAttributes attrs) throws IOException {
|
||||
public void setAttributes(FileAttributes attrs)
|
||||
throws IOException {
|
||||
requester.request(newRequest(PacketType.FSETSTAT).putFileAttributes(attrs))
|
||||
.retrieve(requester.getTimeoutMs(), TimeUnit.MILLISECONDS).ensureStatusPacketIsOK();
|
||||
}
|
||||
@@ -132,13 +139,15 @@ public class RemoteFile
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int w) throws IOException {
|
||||
public void write(int w)
|
||||
throws IOException {
|
||||
b[0] = (byte) w;
|
||||
write(b, 0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] buf, int off, int len) throws IOException {
|
||||
public void write(byte[] buf, int off, int len)
|
||||
throws IOException {
|
||||
if (unconfirmedWrites.size() > maxUnconfirmedWrites) {
|
||||
checkWriteResponse(unconfirmedWrites.remove());
|
||||
}
|
||||
@@ -147,20 +156,23 @@ public class RemoteFile
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
public void flush()
|
||||
throws IOException {
|
||||
while (!unconfirmedWrites.isEmpty()) {
|
||||
checkWriteResponse(unconfirmedWrites.remove());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
public void close()
|
||||
throws IOException {
|
||||
flush();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class RemoteFileInputStream extends InputStream {
|
||||
public class RemoteFileInputStream
|
||||
extends InputStream {
|
||||
|
||||
private final byte[] b = new byte[1];
|
||||
|
||||
@@ -188,32 +200,31 @@ public class RemoteFile
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() throws IOException {
|
||||
public void reset()
|
||||
throws IOException {
|
||||
fileOffset = markPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
final long fileLength = length();
|
||||
final Long previousFileOffset = fileOffset;
|
||||
fileOffset = Math.min(fileOffset + n, fileLength);
|
||||
return fileOffset - previousFileOffset;
|
||||
public long skip(long n)
|
||||
throws IOException {
|
||||
return (this.fileOffset = Math.min(fileOffset + n, length()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
public int read()
|
||||
throws IOException {
|
||||
return read(b, 0, 1) == -1 ? -1 : b[0] & 0xff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] into, int off, int len) throws IOException {
|
||||
public int read(byte[] into, int off, int len)
|
||||
throws IOException {
|
||||
int read = RemoteFile.this.read(fileOffset, into, off, len);
|
||||
if (read != -1) {
|
||||
fileOffset += read;
|
||||
if (markPos != 0 && read > readLimit) {
|
||||
// Invalidate mark position
|
||||
if (markPos != 0 && read > readLimit) // Invalidate mark position
|
||||
markPos = 0;
|
||||
}
|
||||
}
|
||||
return read;
|
||||
}
|
||||
@@ -226,56 +237,27 @@ public class RemoteFile
|
||||
private final byte[] b = new byte[1];
|
||||
|
||||
private final int maxUnconfirmedReads;
|
||||
private final Queue<Promise<Response, SFTPException>> unconfirmedReads = new LinkedList<Promise<Response, SFTPException>>();
|
||||
private final Queue<Long> unconfirmedReadOffsets = new LinkedList<Long>();
|
||||
private final Queue<Promise<Response, SFTPException>> unconfirmedReads;
|
||||
|
||||
private long requestOffset;
|
||||
private long responseOffset;
|
||||
private long fileOffset;
|
||||
private boolean eof;
|
||||
|
||||
public ReadAheadRemoteFileInputStream(int maxUnconfirmedReads) {
|
||||
assert 0 <= maxUnconfirmedReads;
|
||||
|
||||
this.maxUnconfirmedReads = maxUnconfirmedReads;
|
||||
this.unconfirmedReads = new LinkedList<Promise<Response, SFTPException>>();
|
||||
this.fileOffset = 0;
|
||||
}
|
||||
|
||||
public ReadAheadRemoteFileInputStream(int maxUnconfirmedReads, long fileOffset) {
|
||||
assert 0 <= maxUnconfirmedReads;
|
||||
assert 0 <= fileOffset;
|
||||
|
||||
this.maxUnconfirmedReads = maxUnconfirmedReads;
|
||||
this.requestOffset = this.responseOffset = fileOffset;
|
||||
this.unconfirmedReads = new LinkedList<Promise<Response, SFTPException>>();
|
||||
this.fileOffset = fileOffset;
|
||||
}
|
||||
|
||||
private ByteArrayInputStream pending = new ByteArrayInputStream(new byte[0]);
|
||||
|
||||
private boolean retrieveUnconfirmedRead(boolean blocking) throws IOException {
|
||||
if (unconfirmedReads.size() <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!blocking && !unconfirmedReads.peek().isDelivered()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unconfirmedReadOffsets.remove();
|
||||
final Response res = unconfirmedReads.remove().retrieve(requester.getTimeoutMs(), TimeUnit.MILLISECONDS);
|
||||
switch (res.getType()) {
|
||||
case DATA:
|
||||
int recvLen = res.readUInt32AsInt();
|
||||
responseOffset += recvLen;
|
||||
pending = new ByteArrayInputStream(res.array(), res.rpos(), recvLen);
|
||||
break;
|
||||
|
||||
case STATUS:
|
||||
res.ensureStatusIs(Response.StatusCode.EOF);
|
||||
eof = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new SFTPException("Unexpected packet: " + res.getType());
|
||||
}
|
||||
return true;
|
||||
@Override
|
||||
public long skip(long n)
|
||||
throws IOException {
|
||||
throw new IOException("skip is not supported by ReadAheadFileInputStream, use RemoteFileInputStream instead");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -285,66 +267,26 @@ public class RemoteFile
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] into, int off, int len) throws IOException {
|
||||
|
||||
while (!eof && pending.available() <= 0) {
|
||||
|
||||
// we also need to go here for len <= 0, because pending may be at
|
||||
// EOF in which case it would return -1 instead of 0
|
||||
|
||||
while (unconfirmedReads.size() <= maxUnconfirmedReads) {
|
||||
// Send read requests as long as there is no EOF and we have not reached the maximum parallelism
|
||||
int reqLen = Math.max(1024, len); // don't be shy!
|
||||
unconfirmedReads.add(RemoteFile.this.asyncRead(requestOffset, reqLen));
|
||||
unconfirmedReadOffsets.add(requestOffset);
|
||||
requestOffset += reqLen;
|
||||
}
|
||||
|
||||
long nextOffset = unconfirmedReadOffsets.peek();
|
||||
if (responseOffset != nextOffset) {
|
||||
|
||||
// the server could not give us all the data we needed, so
|
||||
// we try to fill the gap synchronously
|
||||
|
||||
assert responseOffset < nextOffset;
|
||||
assert 0 < (nextOffset - responseOffset);
|
||||
assert (nextOffset - responseOffset) <= Integer.MAX_VALUE;
|
||||
|
||||
byte[] buf = new byte[(int) (nextOffset - responseOffset)];
|
||||
int recvLen = RemoteFile.this.read(responseOffset, buf, 0, buf.length);
|
||||
|
||||
if (recvLen < 0) {
|
||||
eof = true;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (0 == recvLen) {
|
||||
// avoid infinite loops
|
||||
throw new SFTPException("Unexpected response size (0), bailing out");
|
||||
}
|
||||
|
||||
responseOffset += recvLen;
|
||||
pending = new ByteArrayInputStream(buf, 0, recvLen);
|
||||
} else if (!retrieveUnconfirmedRead(true /*blocking*/)) {
|
||||
|
||||
// this may happen if we change prefetch strategy
|
||||
// currently, we should never get here...
|
||||
|
||||
throw new IllegalStateException("Could not retrieve data for pending read request");
|
||||
}
|
||||
public int read(byte[] into, int off, int len)
|
||||
throws IOException {
|
||||
while (!eof && unconfirmedReads.size() <= maxUnconfirmedReads) {
|
||||
// Send read requests as long as there is no EOF and we have not reached the maximum parallelism
|
||||
unconfirmedReads.add(asyncRead(fileOffset, len));
|
||||
fileOffset += len;
|
||||
}
|
||||
|
||||
return pending.read(into, off, len);
|
||||
if (unconfirmedReads.isEmpty()) {
|
||||
assert eof;
|
||||
return -1;
|
||||
}
|
||||
// Retrieve first in
|
||||
final Response res = unconfirmedReads.remove().retrieve(requester.getTimeoutMs(), TimeUnit.MILLISECONDS);
|
||||
final int recvLen = checkReadResponse(res, into, off);
|
||||
if (recvLen == -1) {
|
||||
eof = true;
|
||||
}
|
||||
return recvLen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
boolean lastRead = true;
|
||||
while (!eof && (pending.available() <= 0) && lastRead) {
|
||||
lastRead = retrieveUnconfirmedRead(false /*blocking*/);
|
||||
}
|
||||
return pending.available();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C)2009 - SSHJ Contributors
|
||||
/**
|
||||
* Copyright 2009 sshj contributors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,15 +26,14 @@ public abstract class RemoteResource
|
||||
implements Closeable {
|
||||
|
||||
/** Logger */
|
||||
protected final Logger log;
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected final SFTPEngine requester;
|
||||
protected final Requester requester;
|
||||
protected final String path;
|
||||
protected final byte[] handle;
|
||||
|
||||
protected RemoteResource(SFTPEngine requester, String path, byte[] handle) {
|
||||
protected RemoteResource(Requester requester, String path, byte[] handle) {
|
||||
this.requester = requester;
|
||||
log = requester.getLoggerFactory().getLogger(getClass());
|
||||
this.path = path;
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user