Compare commits

...

89 Commits

Author SHA1 Message Date
Jeroen van Erp
64085e62f4 Removed openJDK6 as release plugin is incompatible 2016-09-05 09:54:15 +02:00
Jeroen van Erp
8c7d2fa8d0 Java6 re-enabled 2016-09-02 16:54:21 +02:00
Jeroen van Erp
766d292bad Merge pull request #269 from joval/master
Compatibility features
2016-09-02 16:46:56 +02:00
David Solin
a40957fffc Merge remote-tracking branch 'upstream/master' 2016-09-02 09:24:18 -05:00
David Solin
8ffd852e67 SPACES NOT TABS (like in Silicon Valley). 2016-09-02 09:16:26 -05:00
Jeroen van Erp
b90be512e7 REformatted 2016-09-02 16:08:26 +02:00
Jeroen van Erp
c0d49cf6b3 Removed dependency on VRallev ECC25519 library 2016-09-02 16:05:18 +02:00
David Solin
1b5b2b25b7 Merge branch 'master' into post-logging-factory 2016-09-02 06:45:58 -05:00
Jeroen van Erp
1dad19ca6e Merge pull request #267 from joval/logging-factory
Logging factory
2016-09-02 10:55:43 +02:00
David Solin
90fa26925d Merge branch 'logging-factory' into post-logging-factory 2016-08-29 15:19:57 -05:00
David Solin
9425300262 Better argument order for IdentificationStringParser constructor. 2016-08-29 15:19:06 -05:00
David A. Solin
f2bfe9bfcf Make Java-6 compatible. 2016-08-26 13:26:01 -05:00
David Solin
71498ad961 Added some features required to integrate sshj with Joval's remote jSAF provider.
1) Added boolean Channel.isEOF() method, for checking whether the server has sent EOF.
2) Added SFTP response constants to the Response enumeration
3) Spelling correction for the SYMLINK FileMode enum constant
2016-08-26 13:02:16 -05:00
David Solin
7b8b1cfdf5 Merge branch 'master' into logging-factory 2016-08-24 08:37:24 -05:00
David Solin
3f29879eca Test fixes 2016-08-24 08:35:08 -05:00
David Solin
79c1ae2bb0 Re-add public constructor used by Groovy 2016-08-24 08:08:33 -05:00
David Solin
819d411cf1 Merge branch 'master' of github.com:joval/sshj into logging-factory 2016-08-24 07:57:22 -05:00
David Solin
6579f6f710 Removed unnecessary DefaultLoggerFactory inner class from DefaultConfig
Fixed license header in LoggerFactory.java (via gradle licenseForamat)
2016-08-24 07:34:01 -05:00
David Solin
cf5830eda5 Indentation fixes. 2016-08-24 06:23:45 -05:00
Jeroen van Erp
36ad389ccf Merge pull request #266 from joval/master
Decryption fix and junit test updates for PKCS5
2016-08-24 13:04:36 +02:00
David Solin
f63a88ec9f Removed unnecessary import statements. 2016-08-23 19:24:11 -05:00
David Solin
7379a89268 Inadvertently added this class to a PR where it's not in-scope. 2016-08-23 19:18:51 -05:00
David Solin
219901211e Changes for injecting a LoggingFactory. 2016-08-23 19:13:43 -05:00
David Solin
8c1329036a Updated test case for PKCS5 over-"simplification", to prevent regression. 2016-08-23 19:08:03 -05:00
David Solin
733c19350c Un-break PKCS5 (I inadvertently over-simplified setting the salt length). 2016-08-23 17:40:00 -05:00
Jeroen van Erp
e5ec84c06a Merge pull request #265 from joval/master
Minor modifications to PKCS5KeyFile
2016-08-19 23:35:03 +02:00
David Solin
ed0156c985 Forgot to move 2 fields to the top of the file. 2016-08-19 15:54:48 -05:00
David Solin
6321685881 Moved constant declarations per codacy. 2016-08-19 15:51:07 -05:00
David Solin
f6b4d47945 Another missing import. This should be it. 2016-08-19 15:09:50 -05:00
David Solin
d198ef121c Missing import in test. 2016-08-19 15:04:55 -05:00
David Solin
7786468875 Simplification? 2016-08-19 15:00:12 -05:00
David Solin
0847e8460a Merge remote-tracking branch 'upstream/master' 2016-08-19 12:24:14 -05:00
David Solin
62b8726807 Fixed bug wherein PKCS5KeyFile messed up the data if a bad passphrase was used, which prevented decryption with a subsequent correct passphrase.
Also, made it possible for subclasses of PKCS5KeyFile to access the decrypted ASN.1 data directly (useful if you want to decrypt then store a PKCS5 key for later use elsewhere).
And I think I made the code a little prettier.
2016-08-19 12:18:49 -05:00
Jeroen van Erp
a6af27ae91 Added Codacy badge 2016-08-19 13:02:55 +02:00
Jeroen van Erp
628cbf5eba Organized imports 2016-08-19 12:57:37 +02:00
Jeroen van Erp
e134e00574 Merge pull request #263 from joval/master
Modifications for working with SSH gateways
2016-08-17 08:41:33 +02:00
David Solin
1caa7ac722 For null hostnames, use the loopback InetAddress (for backward-compatibility). 2016-08-16 10:26:57 -05:00
David Solin
4183776adb Updates per Jeroen van Erp. 2016-08-16 09:17:30 -05:00
David Solin
791f112752 Merge remote-tracking branch 'upstream/master' 2016-08-15 09:27:10 -05:00
Jeroen van Erp
233f3765c9 Added PKCS5 key file support (#262) 2016-08-15 15:49:47 +02:00
Jeroen van Erp
5f292d398f Fixed toString of FileAttributes (Fixes #258) 2016-08-15 09:56:13 +02:00
David Solin
ba347f927d Close any LocalPortForwarders with the SSHClient that produced them (assuming they're still open). 2016-08-15 00:17:48 -05:00
David Solin
6f9ecf69e4 Reordered connect methods so that the similar ones are grouped together.
Also, eliminated all use of InetAddress.getByName, because we'll want to be able to connect even when the target host is only visible to DNS from the Proxy, or the SocketFactory.
2016-08-14 14:06:40 -05:00
David Solin
e78ae4dbeb 4th time's the charm? 2016-08-13 15:11:20 -05:00
David Solin
618f2fd111 String.format error was causing tests to unexpectedly fail. 2016-08-13 14:45:00 -05:00
David Solin
8503046302 Made the pkcs8-blanks file an actual pkcs8 file (so it doesn't fail the test). 2016-08-13 14:21:59 -05:00
David Solin
c6cde27e4b Oops, I shouldn't have encrypted the pkcs8 key file. 2016-08-13 11:00:00 -05:00
David Solin
113aa0aebd Updated KeyProviderUtil, KeyFormat, KeyProviderUtilTest and test resources to properly differentiate between PKCS5 and PKCS8 file formats. 2016-08-13 10:24:05 -05:00
David Solin
e7c50165c7 Removed GNUmake-related files from source control
Removed 3rd-party JARs from source control
Re-introduced original BouncyCastle-dependent PKCS5KeyFile class
Re-named non-BouncyCastle-dependent PKCS8KeyFile class to PKCS5KeyFile, since it really only supports PKCS5 formats anyway
2016-08-13 10:03:52 -05:00
David Solin
09616c4834 Tweaks 2016-08-12 20:03:08 -05:00
David Solin
df710d8dc9 Added getFingerprint method to SSH Known Host entry API.
Removed BouncyCastle dependency for public key authentication.
2016-08-12 19:58:09 -05:00
David Solin
df82774ea3 Added resources and GNUmake files.
Updated StreamCopier class to make it compatible with older SLF4J versions.
2016-08-10 21:45:30 -05:00
Jeroen van Erp
caa6cca665 Updated README for 0.17.2 and upcoming 0.17.3 release 2016-07-19 11:36:03 +02:00
Jeroen van Erp
9a5ccefb5d Removed dependency on net.i2p.crypto.eddsa.math classes (Fixes #255) 2016-07-19 11:22:13 +02:00
Jeroen van Erp
90f8c592b0 Prepped for v0.17.2 release 2016-07-07 11:03:05 +02:00
Jeroen van Erp
f491e8d101 Fixed bug that crept in 0edc4a5 2016-07-07 11:01:43 +02:00
Jeroen van Erp
77c10334f1 Updated for 0.17.1 release 2016-07-06 16:23:12 +02:00
Jeroen van Erp
0edc4a5787 Reimplemented parsing the identification (Fixes #176)
This ensures that any header lines sent before the identification
string do not break the identification parsing if they are longer
than the identification string should be.
2016-07-06 16:20:39 +02:00
Jeroen van Erp
b43cff07bf Updated README 2016-07-05 13:14:30 +02:00
Jeroen van Erp
1ab72b7eaf Ensure that same name subdirs aren't omitted when doing SFTP (#253)
* Updated version string in config

* Fixed #252 with backwards compatible behaviour

* Fixed logic and expanded test
2016-07-05 12:21:51 +02:00
Juraj Oprsal
3229584a95 made classes non-final to allow mocking (#250) 2016-05-20 14:59:31 +02:00
Jeroen van Erp
364a82154d Add correct source manifest headers for OSGI (#244) (Fixes #242)
* Improved OSGI sources manifest

* Added correct manifest entries for OSGI source bundle (Fixes #242)

* Removed empty sourceset
2016-04-15 11:01:50 +02:00
Jeroen van Erp
11fbf2964b Merge pull request #243 from valery1707/badges
Add some useful badges with automatic version detection: Maven and Javadoc
2016-04-14 20:39:39 +02:00
Valeriy.Vyrva
a248d50301 Add some useful badges with automatic version detection: Maven and Javadoc 2016-04-14 16:42:36 +06:00
Jeroen van Erp
fddc943565 updated release notes 2016-04-11 16:17:14 +02:00
Jeroen van Erp
ae834134d0 Release task depends on build and uploadArchives 2016-04-11 16:14:58 +02:00
Jeroen van Erp
bc41908694 Added gradle release and license plugins, and updated all license headers 2016-04-11 15:48:43 +02:00
Jeroen van Erp
bf1a855647 Updated README with release notes. 2016-04-11 15:08:24 +02:00
Jeroen van Erp
cd3b0a5bd6 Some cleanup 2016-04-11 15:05:54 +02:00
Jeroen van Erp
b01eccda4a Fixed bug in Forward lookup in which we did not deal with the special cases (Fixes #239) 2016-04-11 15:05:27 +02:00
Jeroen van Erp
4c9ebc306d Added OSGI manifest to -sources.jar (Fixes #242) 2016-04-11 10:56:18 +02:00
Jeroen van Erp
c3f75cda19 Fixed javadoc warning 2016-03-21 10:17:12 +01:00
Jeroen van Erp
1f0e2b1e69 Attempt to fix race condition if a packet is received from the server immediately after successful auth (Fixes #237) 2016-03-21 10:17:01 +01:00
Jeroen van Erp
8e55e50fd9 Fixed some Java7 warnings 2016-03-21 10:15:47 +01:00
Jeroen van Erp
eb8b7b51ca Added callback to request updated password for a user in case of USERAUTH_PASSWD_CHANGEREQ (Fixes #193) 2016-03-18 15:24:58 +01:00
Jeroen van Erp
a2cccd5cef Added javadoc to indicate that close() should always be called on a Command, before inspecting the result(s) (Fixes #114) 2016-03-18 13:31:25 +01:00
Jeroen van Erp
50403483da Implemented switch for waiting on server ident before sending client ident. (Fixes #118) 2016-03-18 13:24:33 +01:00
Jeroen van Erp
3c230a0fc4 Fixed potential race condition identified in #203 2016-03-18 13:11:59 +01:00
Jeroen van Erp
4f152749ce JavaDoc fixes 2016-03-18 13:11:03 +01:00
Jeroen van Erp
e0df6a5fb5 Organised some imports 2016-03-18 13:09:28 +01:00
Jeroen van Erp
f36c011844 Dropped Java6 support (Fixes #234) 2016-03-18 13:09:28 +01:00
Jeroen van Erp
94113eb6f5 Upgraded gradle to 2.12 2016-03-18 13:09:28 +01:00
Jeroen van Erp
0532f27a78 Merge pull request #238 from hierynomus/issue-236
Fix for race condition in global request response handling (fixes #236)
2016-03-18 11:29:01 +01:00
Jeroen van Erp
bd67135ffa Fixed race condition in global request response handling 2016-03-18 11:17:09 +01:00
Jeroen van Erp
ca49ca324f Added reproducing testcase 2016-03-18 10:53:15 +01:00
Jeroen van Erp
ac2ffbc367 Added settings.gradle with project name 2015-12-11 14:46:24 +01:00
Jeroen van Erp
dbb0eb0238 Ingoring integration test 2015-11-20 15:00:02 +01:00
Jeroen van Erp
347e6ad655 Set to snapshot 2015-11-20 14:47:38 +01:00
Jeroen van Erp
2622833831 Fixed typo in README 2015-11-20 14:47:17 +01:00
282 changed files with 4730 additions and 1498 deletions

5
.gitignore vendored
View File

@@ -12,6 +12,9 @@
# Output dirs
target/
build/
docs/
.gradle/
sshj.jar
# MacOS X
.DS_Store

View File

@@ -1,2 +1,5 @@
language: java
sudo: false
jdk:
- oraclejdk7
- oraclejdk8

13
LICENSE_HEADER Normal file
View File

@@ -0,0 +1,13 @@
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.

View File

@@ -1,10 +1,13 @@
= sshj - SSHv2 library for Java
Jeroen van Erp
:sshj_groupid: com.hierynomus
:sshj_version: 0.15.0
:sshj_version: 0.17.2
:source-highlighter: pygments
image::https://travis-ci.org/hierynomus/sshj.svg?branch=master[]
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"]
To get started, have a look at one of the examples. Hopefully you will find the API pleasant to work with :)
@@ -67,7 +70,7 @@ key exchange::
`ecdh-sha2-nistp256`, `ecdh-sha2-nistp384`, `ecdh-sha2-nistp521`, `curve25519-sha256@libssh.org`
signatures::
`ssh-rsa`, `ssh-dss`, `ecdsa-sha2-nistp256`, `ssh-ed25519
`ssh-rsa`, `ssh-dss`, `ecdsa-sha2-nistp256`, `ssh-ed25519`
mac::
`hmac-md5`, `hmac-md5-96`, `hmac-sha1`, `hmac-sha1-96`, `hmac-sha2-256`, `hmac-sha2-512`
@@ -96,6 +99,26 @@ Google Group: http://groups.google.com/group/sshj-users
Fork away!
== Release history
SSHJ 0.17.3 (????-??-??)::
* 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

View File

@@ -1,95 +1,131 @@
apply plugin: "java"
apply plugin: "maven"
apply plugin: "signing"
apply plugin: "osgi"
plugins {
id "java"
id "groovy"
id "maven"
id "idea"
id "signing"
id "osgi"
id "org.ajoberstar.release-opinion" version "1.4.2"
id "com.github.hierynomus.license" version "0.12.1"
}
group = "com.hierynomus"
version = "0.15.0"
repositories {
mavenCentral()
mavenLocal()
mavenCentral()
}
sourceCompatibility = 1.6
targetCompatibility = 1.6
configurations {
compile {
transitive = false
}
configurations.compile.transitive = false
idea {
module {
downloadJavadoc = true
downloadSources = true
}
}
license {
mapping {
java = 'SLASHSTAR_STYLE'
}
header rootProject.file('LICENSE_HEADER')
strictCheck true
excludes(['**/djb/Curve25519.java', '**/sshj/common/Base64.java'])
}
release {
grgit = org.ajoberstar.grgit.Grgit.open(project.projectDir)
}
test {
testLogging {
exceptionFormat = 'full'
}
include "**/*Test.*"
if (!project.hasProperty("allTests")) {
useJUnit {
excludeCategories 'com.hierynomus.sshj.test.SlowTests'
excludeCategories 'com.hierynomus.sshj.test.KnownFailingTests'
testLogging {
exceptionFormat = 'full'
}
include "**/*Test.*"
include "**/*Spec.*"
if (!project.hasProperty("allTests")) {
useJUnit {
excludeCategories 'com.hierynomus.sshj.test.SlowTests'
excludeCategories 'com.hierynomus.sshj.test.KnownFailingTests'
}
}
}
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")
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"
dependencies {
compile "org.slf4j:slf4j-api:1.7.7"
compile "org.bouncycastle:bcprov-jdk15on:$bouncycastleVersion"
compile "org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion"
compile "com.jcraft:jzlib:1.1.3"
compile "org.slf4j:slf4j-api:1.7.7"
compile "org.bouncycastle:bcprov-jdk15on:$bouncycastleVersion"
compile "org.bouncycastle:bcpkix-jdk15on:$bouncycastleVersion"
compile "com.jcraft:jzlib:1.1.3"
compile "net.vrallev.ecc:ecc-25519-java:1.0.1"
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"
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'
testCompile "junit:junit:4.11"
testCompile "org.mockito:mockito-core:1.9.5"
testCompile "org.apache.sshd:sshd-core:1.0.0"
testRuntime "ch.qos.logback:logback-classic:1.1.2"
}
jar {
manifest {
instruction "Bundle-Description", "SSHv2 library for Java"
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", "com.jcraft.jzlib*;version=\"[1.1,2)\";resolution:=optional"
instruction "Import-Package", "org.slf4j*;version=\"[1.7,5)\""
instruction "Import-Package", "org.bouncycastle*"
instruction "Import-Package", "*"
instruction "Export-Package", "net.schmizz.*"
}
manifest {
instruction "Bundle-Description", "SSHv2 library for Java"
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*"
instruction "Import-Package", "*"
instruction "Export-Package", "net.schmizz.*"
}
}
task javadocJar(type: Jar) {
classifier = 'javadoc'
from javadoc
classifier = 'javadoc'
from javadoc
}
task sourcesJar(type: Jar) {
classifier = 'sources'
from sourceSets.main.allSource
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"
)
}
}
artifacts {
archives javadocJar, sourcesJar
archives javadocJar, sourcesJar
}
signing {
required { !version.contains("SNAPSHOT") && gradle.taskGraph.hasTask("uploadArchives") }
sign configurations.archives
required { !version.toString().contains("SNAPSHOT") && gradle.taskGraph.hasTask("uploadArchives") }
sign configurations.archives
}
// This disables the pedantic doclint feature of JDK8
@@ -100,74 +136,77 @@ if (JavaVersion.current().isJava8Compatible()) {
}
uploadArchives {
if(project.hasProperty('sonatypeUsername')) {
repositories.mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
if (project.hasProperty('sonatypeUsername')) {
repositories.mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
configuration = configurations.archives
configuration = configurations.archives
repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2') {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots/') {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
pom.project {
name "sshj"
description "SSHv2 library for Java"
url "https://github.com/hierynomus/sshj"
inceptionYear "2009"
issueManagement {
system "github"
url "https://github.com/hierynomus/sshj/issues"
}
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"
repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2') {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
}
developer {
id "shikhar"
name "Shikhar Bhushan"
email "shikhar@schmizz.net"
url "http://schmizz.net"
roles {
role "Previous lead developer"
snapshotRepository(url: 'https://oss.sonatype.org/content/repositories/snapshots/') {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
}
developer {
id "iterate"
name "David Kocher"
email "dkocher@iterate.ch"
organization "iterage GmbH"
organizationUrl "https://iterate.ch"
roles {
role "Developer"
pom.project {
name "sshj"
description "SSHv2 library for Java"
url "https://github.com/hierynomus/sshj"
inceptionYear "2009"
issueManagement {
system "github"
url "https://github.com/hierynomus/sshj/issues"
}
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"
}
}
}
}
}
}
}
}
}
}
tasks.compileGroovy.onlyIf { false }
tasks.release.dependsOn 'build', 'uploadArchives'

View File

@@ -1,18 +1,3 @@
/**
* 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;

View File

@@ -1,18 +1,3 @@
/**
* 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;

View File

@@ -1,18 +1,3 @@
/**
* 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;

View File

@@ -1,18 +1,3 @@
/**
* 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;

View File

@@ -1,18 +1,3 @@
/**
* 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;

View File

@@ -1,18 +1,3 @@
/**
* 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;
@@ -37,4 +22,4 @@ public class SCPDownload {
}
}
}
}

View File

@@ -1,18 +1,3 @@
/**
* 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;
@@ -42,4 +27,4 @@ public class SCPUpload {
ssh.disconnect();
}
}
}
}

View File

@@ -1,18 +1,3 @@
/**
* 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;
@@ -42,4 +27,4 @@ public class SFTPDownload {
}
}
}
}

View File

@@ -1,18 +1,3 @@
/**
* 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;
@@ -44,4 +29,4 @@ public class SFTPUpload {
}
}
}
}

View File

@@ -1,18 +1,3 @@
/**
* 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;
@@ -67,4 +52,4 @@ public class X11 {
ssh.disconnect();
}
}
}
}

View File

@@ -1,6 +1,6 @@
#Wed Nov 04 09:47:51 CET 2015
#Fri Mar 18 11:26:35 CET 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-all.zip

1
settings.gradle Normal file
View File

@@ -0,0 +1 @@
rootProject.name = "sshj"

View File

@@ -1,7 +1,20 @@
/*
* 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.math.BigDecimal;
public class JavaVersion {
public static boolean isJava7OrEarlier() {
String property = System.getProperty("java.specification.version");

View File

@@ -1,3 +1,18 @@
/*
* 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;

View File

@@ -1,3 +1,18 @@
/*
* 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;

View File

@@ -1,3 +1,18 @@
/*
* 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;

View File

@@ -1,3 +1,18 @@
/*
* 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;

View File

@@ -1,3 +1,18 @@
/*
* 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;

View File

@@ -0,0 +1,100 @@
/*
* 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);
}
}

View File

@@ -1,6 +1,20 @@
/*
* 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 net.schmizz.sshj.transport.cipher.BlockCipher;
import net.schmizz.sshj.transport.cipher.Cipher;

View File

@@ -1,3 +1,18 @@
/*
* 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;

View File

@@ -1,3 +1,18 @@
/*
* 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;

View File

@@ -1,3 +1,18 @@
/*
* 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;

View File

@@ -0,0 +1,918 @@
/* 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
);
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -18,6 +18,8 @@ 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}.
@@ -42,8 +44,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) {
promise = new Promise<Object, T>(name, chainer);
public Event(String name, ExceptionChainer<T> chainer, LoggerFactory loggerFactory) {
promise = new Promise<Object, T>(name, chainer, loggerFactory);
}
/**
@@ -53,8 +55,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) {
promise = new Promise<Object, T>(name, chainer, lock);
public Event(String name, ExceptionChainer<T> chainer, ReentrantLock lock, LoggerFactory loggerFactory) {
promise = new Promise<Object, T>(name, chainer, lock, loggerFactory);
}
/** Sets this event to be {@code true}. Short for {@code set(true)}. */
@@ -143,4 +145,4 @@ public class Event<T extends Throwable> {
return promise.toString();
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -37,4 +37,4 @@ public interface ExceptionChainer<Z extends Throwable> {
Z chain(Throwable t);
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -16,13 +16,14 @@
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}.
@@ -32,8 +33,7 @@ import java.util.concurrent.locks.ReentrantLock;
*/
public class Promise<V, T extends Throwable> {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Logger log;
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) {
this(name, chainer, null);
public Promise(String name, ExceptionChainer<T> chainer, LoggerFactory loggerFactory) {
this(name, chainer, null, loggerFactory);
}
/**
@@ -60,10 +60,11 @@ 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) {
public Promise(String name, ExceptionChainer<T> chainer, ReentrantLock lock, LoggerFactory loggerFactory) {
this.name = name;
this.chainer = chainer;
this.lock = lock == null ? new ReentrantLock() : lock;
this.log = loggerFactory.getLogger(getClass());
this.cond = this.lock.newCondition();
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -22,14 +22,14 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class KeepAlive extends Thread {
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final Logger log;
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);
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -22,14 +22,13 @@ 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 = LoggerFactory.getLogger(getClass());
protected final Logger log;
/** Assigned name of this service */
protected final String name;
@@ -39,6 +38,7 @@ public abstract class AbstractService
public AbstractService(String name, Transport trans) {
this.name = name;
this.trans = trans;
log = trans.getConfig().getLoggerFactory().getLogger(getClass());
}
@Override

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -17,6 +17,7 @@ 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;
@@ -155,4 +156,34 @@ 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();
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -16,6 +16,7 @@
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;
@@ -44,6 +45,9 @@ 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;
@@ -157,4 +161,24 @@ 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;
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -20,38 +20,23 @@ 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.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.cipher.*;
import net.schmizz.sshj.transport.compression.NoneCompression;
import net.schmizz.sshj.transport.kex.*;
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.mac.*;
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.awt.image.ByteLookupTable;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
@@ -82,11 +67,12 @@ import java.util.List;
public class DefaultConfig
extends ConfigImpl {
private final Logger log = LoggerFactory.getLogger(getClass());
private static final String VERSION = "SSHJ_0_17_2";
private static final String VERSION = "SSHJ_0_14_0";
private Logger log;
public DefaultConfig() {
setLoggerFactory(LoggerFactory.DEFAULT);
setVersion(VERSION);
final boolean bouncyCastleRegistered = SecurityUtils.isBouncyCastleRegistered();
initKeyExchangeFactories(bouncyCastleRegistered);
@@ -99,6 +85,12 @@ 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(),
@@ -156,7 +148,8 @@ public class DefaultConfig
BlockCiphers.TwofishCBC(),
StreamCiphers.Arcfour(),
StreamCiphers.Arcfour128(),
StreamCiphers.Arcfour256()));
StreamCiphers.Arcfour256())
);
boolean warn = false;
// Ref. https://issues.apache.org/jira/browse/SSHD-24
@@ -182,17 +175,26 @@ public class DefaultConfig
}
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(),
new SignatureEdDSA.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());
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -16,6 +16,7 @@
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;
@@ -45,38 +46,24 @@ 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.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.AuthGssApiWithMic;
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.keyprovider.*;
import net.schmizz.sshj.userauth.method.*;
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.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.*;
/**
* Secure SHell client API.
@@ -127,7 +114,8 @@ public class SSHClient
public static final int DEFAULT_PORT = 22;
/** Logger */
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final LoggerFactory loggerFactory;
protected final Logger log;
/** Transport layer */
protected final Transport trans;
@@ -138,6 +126,8 @@ 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());
@@ -150,6 +140,8 @@ 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());
@@ -222,6 +214,7 @@ 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;
@@ -293,6 +286,22 @@ 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}.
@@ -414,6 +423,14 @@ 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();
}
@@ -613,7 +630,7 @@ public class SSHClient
*/
public void loadKnownHosts(File location)
throws IOException {
addHostKeyVerifier(new OpenSSHKnownHosts(location));
addHostKeyVerifier(new OpenSSHKnownHosts(location, loggerFactory));
}
/**
@@ -631,7 +648,9 @@ public class SSHClient
*/
public LocalPortForwarder newLocalPortForwarder(LocalPortForwarder.Parameters parameters,
ServerSocket serverSocket) {
return new LocalPortForwarder(conn, parameters, serverSocket);
LocalPortForwarder forwarder = new LocalPortForwarder(conn, parameters, serverSocket, loggerFactory);
forwarders.add(forwarder);
return forwarder;
}
/**
@@ -658,7 +677,7 @@ public class SSHClient
public SCPFileTransfer newSCPFileTransfer() {
checkConnected();
checkAuthenticated();
return new SCPFileTransfer(this);
return new SCPFileTransfer(this, loggerFactory);
}
/**
@@ -759,4 +778,4 @@ public class SSHClient
}
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -48,12 +48,50 @@ public abstract class SocketClient {
this.defaultPort = defaultPort;
}
public void connect(InetAddress host, int port) throws IOException {
socket = socketFactory.createSocket();
socket.connect(new InetSocketAddress(host, port), connectTimeout);
/**
* 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.
@@ -75,23 +113,41 @@ public abstract class SocketClient {
onConnect();
}
public void connect(String hostname, int port) throws IOException {
this.hostname = hostname;
connect(InetAddress.getByName(hostname), port);
public void connect(String hostname) throws IOException {
connect(hostname, defaultPort);
}
/**
* 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;
connect(InetAddress.getByName(hostname), port, proxy);
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 {
socket = socketFactory.createSocket();
socket.connect(new InetSocketAddress(host, port), connectTimeout);
onConnect();
}
public void connect(InetAddress host, int port, InetAddress localAddr, int localPort)
@@ -102,43 +158,6 @@ public abstract class SocketClient {
onConnect();
}
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);
}
/**
* 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 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);
}
public void disconnect() throws IOException {
if (socket != null) {
socket.close();

View File

@@ -1,18 +1,3 @@
/**
* 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;
@@ -1742,4 +1727,4 @@ public class Base64 {
private Base64() {
}
} // end class Base64
} // end class Base64

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -16,7 +16,6 @@
package net.schmizz.sshj.common;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
@@ -26,25 +25,33 @@ 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) {
for (Closeable c : closeables)
try {
if (c != null)
c.close();
} catch (IOException logged) {
LOG.warn("Error closing {} - {}", c, logged);
}
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) {
try {
if (c != null)
c.close();
} catch (IOException logged) {
loggerFactory.getLogger(IOUtils.class).warn("Error closing {} - {}", c, logged);
}
}
}
public static ByteArrayOutputStream readFully(InputStream stream, LoggerFactory loggerFactory)
throws IOException {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
new StreamCopier(stream, baos).copy();
new StreamCopier(stream, baos, loggerFactory).copy();
return baos;
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -17,11 +17,9 @@ package net.schmizz.sshj.common;
import com.hierynomus.sshj.secg.SecgUtils;
import com.hierynomus.sshj.signature.Ed25519PublicKey;
import net.i2p.crypto.eddsa.*;
import net.i2p.crypto.eddsa.math.GroupElement;
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.EdDSAParameterSpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
@@ -32,8 +30,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.security.*;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.interfaces.*;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.RSAPublicKeySpec;
@@ -174,15 +174,15 @@ public enum KeyType {
},
ED25519("ssh-ed25519") {
private final Logger logger = LoggerFactory.getLogger(KeyType.class);
private final Logger log = LoggerFactory.getLogger(KeyType.class);
@Override
public PublicKey readPubKeyFromBuffer(String type, Buffer<?> buf) throws GeneralSecurityException {
try {
final int keyLen = buf.readUInt32AsInt();
final byte[] p = new byte[keyLen];
buf.readRawBytes(p);
if (logger.isDebugEnabled()) {
logger.debug(String.format("Key algo: %s, Key curve: 25519, Key Len: %s\np: %s",
if (log.isDebugEnabled()) {
log.debug(String.format("Key algo: %s, Key curve: 25519, Key Len: %s\np: %s",
type,
keyLen,
Arrays.toString(p))
@@ -190,8 +190,7 @@ public enum KeyType {
}
EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable.getByName("ed25519-sha-512");
GroupElement point = ed25519.getCurve().createPoint(p, true);
EdDSAPublicKeySpec publicSpec = new EdDSAPublicKeySpec(point, ed25519);
EdDSAPublicKeySpec publicSpec = new EdDSAPublicKeySpec(p, ed25519);
return new Ed25519PublicKey(publicSpec);
} catch (Buffer.BufferException be) {

View File

@@ -0,0 +1,38 @@
/*
* 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);
}
};
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -23,14 +23,7 @@ import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
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 java.security.*;
// TODO refactor
@@ -259,4 +252,4 @@ public class SecurityUtils {
}
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -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 Logger log = LoggerFactory.getLogger(getClass());
private final LoggerFactory loggerFactory;
private final Logger log;
private final InputStream in;
private final OutputStream out;
@@ -50,9 +50,11 @@ public class StreamCopier {
private boolean keepFlushing = true;
private long length = -1;
public StreamCopier(InputStream in, OutputStream out) {
public StreamCopier(InputStream in, OutputStream out, LoggerFactory loggerFactory) {
this.in = in;
this.out = out;
this.loggerFactory = loggerFactory;
this.log = loggerFactory.getLogger(getClass());
}
public StreamCopier bufSize(int bufSize) {
@@ -91,7 +93,7 @@ public class StreamCopier {
public IOException chain(Throwable t) {
return (t instanceof IOException) ? (IOException) t : new IOException(t);
}
});
}, loggerFactory);
new Thread() {
{
@@ -107,7 +109,7 @@ public class StreamCopier {
log.debug("Done copying from {}", in);
doneEvent.set();
} catch (IOException ioe) {
log.error("In pipe from {} to {}: {}", in, out, ioe);
log.error(String.format("In pipe from %1$s to %2$s", in.toString(), out.toString()), ioe);
doneEvent.deliverError(ioe);
}
}
@@ -136,7 +138,7 @@ public class StreamCopier {
final double timeSeconds = (System.currentTimeMillis() - startTime) / 1000.0;
final double sizeKiB = count / 1024.0;
log.debug("{} KiB transferred in {} seconds ({} KiB/s)", sizeKiB, timeSeconds, (sizeKiB / timeSeconds));
log.debug(String.format("%1$,.1f KiB transferred in %2$,.1f seconds (%3$,.2f KiB/s)", sizeKiB, timeSeconds, (sizeKiB / timeSeconds)));
if (length != -1 && read == -1)
throw new IOException("Encountered EOF, could not transfer " + length + " bytes");

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -156,4 +156,4 @@ public interface Connection {
* @return The configured {@link net.schmizz.keepalive.KeepAlive} mechanism.
*/
KeepAlive getKeepAlive();
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -20,12 +20,7 @@ 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.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.common.*;
import net.schmizz.sshj.connection.channel.Channel;
import net.schmizz.sshj.connection.channel.OpenFailException.Reason;
import net.schmizz.sshj.connection.channel.forwarded.ForwardedChannelOpener;
@@ -64,7 +59,6 @@ public class ConnectionImpl
/**
* Create with an associated {@link Transport}.
*
* @param config the ssh config
* @param trans transport layer
* @param keepAlive the keep alive provider
*/
@@ -205,7 +199,7 @@ public class ConnectionImpl
Promise<SSHPacket, ConnectionException> promise = null;
if (wantReply) {
promise = new Promise<SSHPacket, ConnectionException>("global req for " + name, ConnectionException.chainer);
promise = new Promise<SSHPacket, ConnectionException>("global req for " + name, ConnectionException.chainer, trans.getConfig().getLoggerFactory());
globalReqPromises.add(promise);
}
return promise;
@@ -216,13 +210,15 @@ 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
gr.deliver(response);
} 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));
}
}
}
@@ -278,4 +274,4 @@ public class ConnectionImpl
return keepAlive;
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -17,19 +17,12 @@ package net.schmizz.sshj.connection.channel;
import net.schmizz.concurrent.ErrorDeliveryUtil;
import net.schmizz.concurrent.Event;
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.common.*;
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;
@@ -44,7 +37,8 @@ public abstract class AbstractChannel
private static final int REMOTE_MAX_PACKET_SIZE_CEILING = 1024 * 1024;
/** Logger */
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final LoggerFactory loggerFactory;
protected final Logger log;
/** Transport layer */
protected final Transport trans;
@@ -58,6 +52,8 @@ 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 */
@@ -83,21 +79,23 @@ 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());
lwin = new Window.Local(conn.getWindowSize(), conn.getMaxPacketSize(), loggerFactory);
in = new ChannelInputStream(this, trans, lwin);
openEvent = new Event<ConnectionException>("chan#" + id + " / " + "open", ConnectionException.chainer, openCloseLock);
closeEvent = new Event<ConnectionException>("chan#" + id + " / " + "close", ConnectionException.chainer, openCloseLock);
openEvent = new Event<ConnectionException>("chan#" + id + " / " + "open", ConnectionException.chainer, openCloseLock, loggerFactory);
closeEvent = new Event<ConnectionException>("chan#" + id + " / " + "close", ConnectionException.chainer, openCloseLock, loggerFactory);
}
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));
rwin = new Window.Remote(remoteWinSize, (int) Math.min(remoteMaxPacketSize, REMOTE_MAX_PACKET_SIZE_CEILING), loggerFactory);
out = new ChannelOutputStream(this, trans, rwin);
log.debug("Initialized - {}", this);
}
@@ -195,6 +193,16 @@ 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");
@@ -362,7 +370,7 @@ public abstract class AbstractChannel
Event<ConnectionException> responseEvent = null;
if (wantReply) {
responseEvent = new Event<ConnectionException>("chan#" + id + " / " + "chanreq for " + reqType,
ConnectionException.chainer);
ConnectionException.chainer, loggerFactory);
chanReqResponseEvents.add(responseEvent);
}
return responseEvent;
@@ -393,6 +401,7 @@ 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
@@ -402,4 +411,4 @@ public abstract class AbstractChannel
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -16,6 +16,7 @@
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;
@@ -25,13 +26,15 @@ 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.
@@ -40,27 +43,30 @@ public interface Channel
* @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();
/**
@@ -68,55 +74,73 @@ public interface Channel
*
* @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();
/**
@@ -128,10 +152,17 @@ public interface Channel
*/
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();
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -15,11 +15,7 @@
*/
package net.schmizz.sshj.connection.channel;
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.common.*;
import net.schmizz.sshj.connection.ConnectionException;
import net.schmizz.sshj.transport.Transport;
import net.schmizz.sshj.transport.TransportException;
@@ -38,7 +34,7 @@ public final class ChannelInputStream
extends InputStream
implements ErrorNotifiable {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Logger log;
private final Channel chan;
private final Transport trans;
@@ -51,6 +47,7 @@ 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());
@@ -130,7 +127,12 @@ public final class ChannelInputStream
buf.putRawBytes(data, offset, len);
buf.notifyAll();
}
win.consume(len);
// 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);
}
if (chan.getAutoExpand())
checkWindow();
}
@@ -153,4 +155,4 @@ public final class ChannelInputStream
return "< ChannelInputStream for Channel #" + chan.getID() + " >";
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -15,11 +15,7 @@
*/
package net.schmizz.sshj.connection.channel;
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.common.*;
import net.schmizz.sshj.connection.ConnectionException;
import net.schmizz.sshj.transport.Transport;
import net.schmizz.sshj.transport.TransportException;

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -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 = LoggerFactory.getLogger(getClass());
protected final Logger log;
protected final Object lock = new Object();
@@ -30,9 +30,10 @@ public abstract class Window {
protected long size;
public Window(long initialWinSize, int maxPacketSize) {
public Window(long initialWinSize, int maxPacketSize, LoggerFactory loggerFactory) {
size = initialWinSize;
this.maxPacketSize = maxPacketSize;
log = loggerFactory.getLogger(getClass());
}
public void expand(long inc) {
@@ -72,8 +73,8 @@ public abstract class Window {
public static final class Remote
extends Window {
public Remote(long initialWinSize, int maxPacketSize) {
super(initialWinSize, maxPacketSize);
public Remote(long initialWinSize, int maxPacketSize, LoggerFactory loggerFactory) {
super(initialWinSize, maxPacketSize, loggerFactory);
}
public long awaitExpansion(long was)
@@ -108,8 +109,8 @@ public abstract class Window {
private final long initialSize;
private final long threshold;
public Local(long initialWinSize, int maxPacketSize) {
super(initialWinSize, maxPacketSize);
public Local(long initialWinSize, int maxPacketSize, LoggerFactory loggerFactory) {
super(initialWinSize, maxPacketSize, loggerFactory);
this.initialSize = initialWinSize;
threshold = Math.min(maxPacketSize * 20, initialSize / 4);
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -94,4 +94,4 @@ public abstract class AbstractDirectChannel
}
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -17,17 +17,17 @@ 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.channel.SocketStreamCopyMonitor;
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;
@@ -82,10 +82,10 @@ public class LocalPortForwarder {
throws IOException {
socket.setSendBufferSize(getLocalMaxPacketSize());
socket.setReceiveBufferSize(getRemoteMaxPacketSize());
final Event<IOException> soc2chan = new StreamCopier(socket.getInputStream(), getOutputStream())
final Event<IOException> soc2chan = new StreamCopier(socket.getInputStream(), getOutputStream(), loggerFactory)
.bufSize(getRemoteMaxPacketSize())
.spawnDaemon("soc2chan");
final Event<IOException> chan2soc = new StreamCopier(getInputStream(), socket.getOutputStream())
final Event<IOException> chan2soc = new StreamCopier(getInputStream(), socket.getOutputStream(), loggerFactory)
.bufSize(getLocalMaxPacketSize())
.spawnDaemon("chan2soc");
SocketStreamCopyMonitor.monitor(5, TimeUnit.SECONDS, soc2chan, chan2soc, this, socket);
@@ -102,16 +102,18 @@ public class LocalPortForwarder {
}
private final Logger log = LoggerFactory.getLogger(LocalPortForwarder.class);
private final LoggerFactory loggerFactory;
private final Logger log;
private final Connection conn;
private final Parameters parameters;
private final ServerSocket serverSocket;
public LocalPortForwarder(Connection conn, Parameters parameters, ServerSocket serverSocket) {
public LocalPortForwarder(Connection conn, Parameters parameters, ServerSocket serverSocket, LoggerFactory loggerFactory) {
this.conn = conn;
this.parameters = parameters;
this.serverSocket = serverSocket;
this.loggerFactory = loggerFactory;
this.log = loggerFactory.getLogger(getClass());
}
private void startChannel(Socket socket) throws IOException {
@@ -134,11 +136,33 @@ public class LocalPortForwarder {
throws IOException {
log.info("Listening on {}", serverSocket.getLocalSocketAddress());
while (!Thread.currentThread().isInterrupted()) {
final Socket socket = serverSocket.accept();
log.debug("Got connection from {}", socket.getRemoteSocketAddress());
startChannel(socket);
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!");
}
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();
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -48,18 +48,24 @@ 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();

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -15,12 +15,7 @@
*/
package net.schmizz.sshj.connection.channel.direct;
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.common.*;
import net.schmizz.sshj.connection.Connection;
import net.schmizz.sshj.connection.ConnectionException;
import net.schmizz.sshj.connection.channel.ChannelInputStream;

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -73,4 +73,4 @@ public abstract class AbstractForwardedChannel
return origPort;
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -29,14 +29,14 @@ import java.io.IOException;
public abstract class AbstractForwardedChannelOpener
implements ForwardedChannelOpener {
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final Logger log;
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();
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -117,6 +117,34 @@ 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. */
@@ -224,11 +252,15 @@ public class RemotePortForwarder
} catch (Buffer.BufferException be) {
throw new ConnectionException(be);
}
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() + "`");
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() + "`");
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -19,8 +19,6 @@ 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;
@@ -31,8 +29,6 @@ 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. */
@@ -44,7 +40,7 @@ public class SocketForwardingConnectListener
@Override
public void gotConnect(Channel.Forwarded chan)
throws IOException {
log.debug("New connection from {}:{}", chan.getOriginatorIP(), chan.getOriginatorPort());
chan.getLoggerFactory().getLogger(getClass()).debug("New connection from {}:{}", chan.getOriginatorIP(), chan.getOriginatorPort());
final Socket sock = new Socket();
sock.setSendBufferSize(chan.getLocalMaxPacketSize());
@@ -55,11 +51,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())
final Event<IOException> soc2chan = new StreamCopier(sock.getInputStream(), chan.getOutputStream(), chan.getLoggerFactory())
.bufSize(chan.getRemoteMaxPacketSize())
.spawnDaemon("soc2chan");
final Event<IOException> chan2soc = new StreamCopier(chan.getInputStream(), sock.getOutputStream())
final Event<IOException> chan2soc = new StreamCopier(chan.getInputStream(), sock.getOutputStream(), chan.getLoggerFactory())
.bufSize(chan.getLocalMaxPacketSize())
.spawnDaemon("chan2soc");

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -222,7 +222,7 @@ public final class FileAttributes {
sb.append("size=").append(size).append(";");
if (has(Flag.UIDGID))
sb.append("uid=").append(size).append(",gid=").append(gid).append(";");
sb.append("uid=").append(uid).append(",gid=").append(gid).append(";");
if (has(Flag.MODE))
sb.append("mode=").append(mode.toString()).append(";");

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -36,7 +36,7 @@ public class FileMode {
/** directory */
DIRECTORY(0040000),
/** symbolic link */
SYMKLINK(0120000),
SYMLINK(0120000),
/** unknown */
UNKNOWN(0);

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -17,7 +17,6 @@ package net.schmizz.sshj.sftp;
import net.schmizz.concurrent.Promise;
import net.schmizz.sshj.common.SSHException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,7 +29,7 @@ public class PacketReader
extends Thread {
/** Logger */
private final Logger log = LoggerFactory.getLogger(getClass());
private final Logger log;
private final InputStream in;
private final Map<Long, Promise<Response, SFTPException>> promises = new ConcurrentHashMap<Long, Promise<Response, SFTPException>>();
@@ -40,6 +39,7 @@ 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);
= new Promise<Response, SFTPException>("sftp / " + requestId, SFTPException.chainer, engine.getLoggerFactory());
promises.put(requestId, promise);
return promise;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -63,4 +63,4 @@ public class PathComponents {
return "[parent=" + parent + "; name=" + name + "; path=" + path + "]";
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -15,12 +15,7 @@
*/
package net.schmizz.sshj.sftp;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.*;
public class RandomAccessRemoteFile
implements DataInput, DataOutput {

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -25,7 +25,7 @@ import java.util.concurrent.TimeUnit;
public class RemoteDirectory
extends RemoteResource {
public RemoteDirectory(Requester requester, String path, byte[] handle) {
public RemoteDirectory(SFTPEngine requester, String path, byte[] handle) {
super(requester, path, handle);
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2009 sshj contributors
* <p/>
/*
* 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
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
*
* 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.
@@ -30,7 +30,7 @@ import java.util.concurrent.TimeUnit;
public class RemoteFile
extends RemoteResource {
public RemoteFile(Requester requester, String path, byte[] handle) {
public RemoteFile(SFTPEngine requester, String path, byte[] handle) {
super(requester, path, handle);
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.
@@ -26,14 +26,15 @@ public abstract class RemoteResource
implements Closeable {
/** Logger */
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final Logger log;
protected final Requester requester;
protected final SFTPEngine requester;
protected final String path;
protected final byte[] handle;
protected RemoteResource(Requester requester, String path, byte[] handle) {
protected RemoteResource(SFTPEngine requester, String path, byte[] handle) {
this.requester = requester;
log = requester.getLoggerFactory().getLogger(getClass());
this.path = path;
this.handle = handle;
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2009 sshj contributors
/*
* 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.

Some files were not shown because too many files have changed in this diff Show More