Subversion Repositories Programming Utils

Compare Revisions

Ignore whitespace Rev 85 → Rev 86

/trunk/rmsshd/assembly/src/main/distribution/NOTICE.txt
0,0 → 1,5
Apache MINA SSHD
Copyright 2008-2014 The Apache Software Foundation
 
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
/trunk/rmsshd/assembly/src/main/distribution/LICENSE.txt
0,0 → 1,251
 
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
 
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 
1. Definitions.
 
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
 
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
 
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
 
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
 
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
 
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
 
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
 
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
 
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
 
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
 
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
 
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
 
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
 
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
 
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
 
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
 
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
 
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
 
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
 
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
 
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
 
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
 
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
 
END OF TERMS AND CONDITIONS
 
APPENDIX: How to apply the Apache License to your work.
 
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
 
Copyright [yyyy] [name of copyright owner]
 
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 
=======================================================================================
Third party licenses
=======================================================================================
 
Bouncy Castle
=============
Copyright (c) 2000 - 2013 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
 
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in the
Software without restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the
following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
SLF4J
=============
Copyright (c) 2004-2011 QOS.ch
All rights reserved.
 
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
 
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/trunk/rmsshd/assembly/src/main/distribution/bin/ssh.bat
0,0 → 1,105
@echo off
rem
rem
rem Licensed to the Apache Software Foundation (ASF) under one or more
rem contributor license agreements. See the NOTICE file distributed with
rem this work for additional information regarding copyright ownership.
rem The ASF licenses this file to You under the Apache License, Version 2.0
rem (the "License"); you may not use this file except in compliance with
rem the License. You may obtain a copy of the License at
rem
rem http://www.apache.org/licenses/LICENSE-2.0
rem
rem Unless required by applicable law or agreed to in writing, software
rem distributed under the License is distributed on an "AS IS" BASIS,
rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rem See the License for the specific language governing permissions and
rem limitations under the License.
rem
rem
 
if not "%ECHO%" == "" echo %ECHO%
 
setlocal
set DIRNAME=%~dp0%
set PROGNAME=%~nx0%
set ARGS=%*
 
title Sshd
 
goto BEGIN
 
:warn
echo %PROGNAME%: %*
goto :EOF
 
:BEGIN
 
rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
if not "%SSHD_HOME%" == "" (
call :warn Ignoring predefined value for SSHD_HOME
)
set SSHD_HOME=%DIRNAME%..
if not exist "%SSHD_HOME%" (
call :warn SSHD_HOME is not valid: %SSHD_HOME%
goto END
)
 
set DEFAULT_JAVA_OPTS=-server -Xmx512M -Dcom.sun.management.jmxremote
set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
 
rem Support for loading native libraries
set PATH=%PATH%;%SSHD_HOME%\lib
 
rem Setup the Java Virtual Machine
if not "%JAVA%" == "" goto :Check_JAVA_END
set JAVA=java
if "%JAVA_HOME%" == "" call :warn JAVA_HOME not set; results may vary
if not "%JAVA_HOME%" == "" set JAVA=%JAVA_HOME%\bin\java
if not exist "%JAVA_HOME%" (
call :warn JAVA_HOME is not valid: "%JAVA_HOME%"
goto END
)
:Check_JAVA_END
 
if "%JAVA_OPTS%" == "" set JAVA_OPTS=%DEFAULT_JAVA_OPTS%
 
if "%SSHD_DEBUG%" == "" goto :SSHD_DEBUG_END
rem Use the defaults if JAVA_DEBUG_OPTS was not set
if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS%
 
set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%"
call :warn Enabling Java debug options: %JAVA_DEBUG_OPTS%
:SSHD_DEBUG_END
 
rem Setup the classpath
set CLASSPATH=%LOCAL_CLASSPATH%
pushd "%SSHD_HOME%\lib"
for %%G in (*.*) do call:APPEND_TO_CLASSPATH %%G
popd
goto CLASSPATH_END
 
: APPEND_TO_CLASSPATH
set filename=%~1
set suffix=%filename:~-4%
if %suffix% equ .jar set CLASSPATH=%CLASSPATH%;%SSHD_HOME%\lib\%filename%
goto :EOF
 
:CLASSPATH_END
 
SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8
rem Execute the Java Virtual Machine
cd %SSHD_HOME%
"%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Dsshd.home="%SSHD_HOME%" org.apache.sshd.SshClient %ARGS%
 
rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
:END
 
endlocal
 
if not "%PAUSE%" == "" pause
 
:END_NO_PAUSE
 
/trunk/rmsshd/assembly/src/main/distribution/bin/sshd.bat
0,0 → 1,105
@echo off
rem
rem
rem Licensed to the Apache Software Foundation (ASF) under one or more
rem contributor license agreements. See the NOTICE file distributed with
rem this work for additional information regarding copyright ownership.
rem The ASF licenses this file to You under the Apache License, Version 2.0
rem (the "License"); you may not use this file except in compliance with
rem the License. You may obtain a copy of the License at
rem
rem http://www.apache.org/licenses/LICENSE-2.0
rem
rem Unless required by applicable law or agreed to in writing, software
rem distributed under the License is distributed on an "AS IS" BASIS,
rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rem See the License for the specific language governing permissions and
rem limitations under the License.
rem
rem
 
if not "%ECHO%" == "" echo %ECHO%
 
setlocal
set DIRNAME=%~dp0%
set PROGNAME=%~nx0%
set ARGS=%*
 
title Sshd
 
goto BEGIN
 
:warn
echo %PROGNAME%: %*
goto :EOF
 
:BEGIN
 
rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
if not "%SSHD_HOME%" == "" (
call :warn Ignoring predefined value for SSHD_HOME
)
set SSHD_HOME=%DIRNAME%..
if not exist "%SSHD_HOME%" (
call :warn SSHD_HOME is not valid: %SSHD_HOME%
goto END
)
 
set DEFAULT_JAVA_OPTS=-server -Xmx512M -Dcom.sun.management.jmxremote
set DEFAULT_JAVA_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
 
rem Support for loading native libraries
set PATH=%PATH%;%SSHD_HOME%\lib
 
rem Setup the Java Virtual Machine
if not "%JAVA%" == "" goto :Check_JAVA_END
set JAVA=java
if "%JAVA_HOME%" == "" call :warn JAVA_HOME not set; results may vary
if not "%JAVA_HOME%" == "" set JAVA=%JAVA_HOME%\bin\java
if not exist "%JAVA_HOME%" (
call :warn JAVA_HOME is not valid: "%JAVA_HOME%"
goto END
)
:Check_JAVA_END
 
if "%JAVA_OPTS%" == "" set JAVA_OPTS=%DEFAULT_JAVA_OPTS%
 
if "%SSHD_DEBUG%" == "" goto :SSHD_DEBUG_END
rem Use the defaults if JAVA_DEBUG_OPTS was not set
if "%JAVA_DEBUG_OPTS%" == "" set JAVA_DEBUG_OPTS=%DEFAULT_JAVA_DEBUG_OPTS%
 
set "JAVA_OPTS=%JAVA_DEBUG_OPTS% %JAVA_OPTS%"
call :warn Enabling Java debug options: %JAVA_DEBUG_OPTS%
:SSHD_DEBUG_END
 
rem Setup the classpath
set CLASSPATH=%LOCAL_CLASSPATH%
pushd "%SSHD_HOME%\lib"
for %%G in (*.*) do call:APPEND_TO_CLASSPATH %%G
popd
goto CLASSPATH_END
 
: APPEND_TO_CLASSPATH
set filename=%~1
set suffix=%filename:~-4%
if %suffix% equ .jar set CLASSPATH=%CLASSPATH%;%SSHD_HOME%\lib\%filename%
goto :EOF
 
:CLASSPATH_END
 
SET ARGS=%1 %2 %3 %4 %5 %6 %7 %8
rem Execute the Java Virtual Machine
cd %SSHD_HOME%
"%JAVA%" %JAVA_OPTS% %OPTS% -classpath "%CLASSPATH%" -Dsshd.home="%SSHD_HOME%" org.apache.sshd.SshServer %ARGS%
 
rem # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
:END
 
endlocal
 
if not "%PAUSE%" == "" pause
 
:END_NO_PAUSE
 
/trunk/rmsshd/assembly/src/main/distribution/bin/ssh.sh
0,0 → 1,266
#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
 
DIRNAME=`dirname $0`
PROGNAME=`basename $0`
 
#
# Check/Set up some easily accessible MIN/MAX params for JVM mem usage
#
 
if [ "x$JAVA_MIN_MEM" = "x" ]; then
JAVA_MIN_MEM=128M
export JAVA_MIN_MEM
fi
 
if [ "x$JAVA_MAX_MEM" = "x" ]; then
JAVA_MAX_MEM=512M
export JAVA_MAX_MEM
fi
 
warn() {
echo "${PROGNAME}: $*"
}
 
die() {
warn "$*"
exit 1
}
 
maybeSource() {
file="$1"
if [ -f "$file" ] ; then
. $file
fi
}
 
detectOS() {
# OS specific support (must be 'true' or 'false').
cygwin=false;
darwin=false;
aix=false;
os400=false;
case "`uname`" in
CYGWIN*)
cygwin=true
;;
Darwin*)
darwin=true
;;
AIX*)
aix=true
;;
OS400*)
os400=true
;;
esac
# For AIX, set an environment variable
if $aix; then
export LDR_CNTRL=MAXDATA=0xB0000000@DSA
export IBM_JAVA_HEAPDUMP_TEXT=true
echo $LDR_CNTRL
fi
}
 
unlimitFD() {
# Use the maximum available, or set MAX_FD != -1 to use that
if [ "x$MAX_FD" = "x" ]; then
MAX_FD="maximum"
fi
 
# Increase the maximum file descriptors if we can
if [ "$os400" = "false" ] && [ "$cygwin" = "false" ]; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ "$MAX_FD_LIMIT" != 'unlimited' ]; then
if [ $? -eq 0 ]; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then
# use the system max
MAX_FD="$MAX_FD_LIMIT"
fi
 
ulimit -n $MAX_FD > /dev/null
# echo "ulimit -n" `ulimit -n`
if [ $? -ne 0 ]; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query system maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
fi
}
 
locateHome() {
if [ "x$SSHD_HOME" != "x" ]; then
warn "Ignoring predefined value for SSHD_HOME"
fi
 
# In POSIX shells, CDPATH may cause cd to write to stdout
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
SSHD_HOME=`cd $DIRNAME/..; pwd`
if [ ! -d "$SSHD_HOME" ]; then
die "SSHD_HOME is not valid: $SSHD_HOME"
fi
}
 
setupNativePath() {
# Support for loading native libraries
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$SSHD_BASE/lib:$SSHD_HOME/lib"
 
# For Cygwin, set PATH from LD_LIBRARY_PATH
if $cygwin; then
LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"`
PATH="$PATH;$LD_LIBRARY_PATH"
export PATH
fi
export LD_LIBRARY_PATH
}
 
locateJava() {
# Setup the Java Virtual Machine
if $cygwin ; then
[ -n "$JAVA" ] && JAVA=`cygpath --unix "$JAVA"`
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
 
if [ "x$JAVA" = "x" ]; then
if [ "x$JAVA_HOME" = "x" ] && [ "$darwin" = "true" ]; then
JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home
fi
if [ "x$JAVA_HOME" != "x" ]; then
if [ ! -d "$JAVA_HOME" ]; then
die "JAVA_HOME is not valid: $JAVA_HOME"
fi
JAVA="$JAVA_HOME/bin/java"
else
warn "JAVA_HOME not set; results may vary"
JAVA="java"
fi
fi
}
 
detectJVM() {
#echo "`$JAVA -version`"
# This service should call `java -version`,
# read stdout, and look for hints
if $JAVA -version 2>&1 | grep "^IBM" ; then
JVM_VENDOR="IBM"
# on OS/400, java -version does not contain IBM explicitly
elif $os400; then
JVM_VENDOR="IBM"
else
JVM_VENDOR="SUN"
fi
# echo "JVM vendor is $JVM_VENDOR"
}
 
setupDebugOptions() {
if [ "x$JAVA_OPTS" = "x" ]; then
JAVA_OPTS="$DEFAULT_JAVA_OPTS"
fi
export JAVA_OPTS
 
# Set Debug options if enabled
if [ "x$SSHD_DEBUG" != "x" ]; then
# Use the defaults if JAVA_DEBUG_OPTS was not set
if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then
JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS"
fi
 
JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS"
warn "Enabling Java debug options: $JAVA_DEBUG_OPTS"
fi
}
 
setupDefaults() {
DEFAULT_JAVA_OPTS="-Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM "
 
#Set the JVM_VENDOR specific JVM flags
if [ "$JVM_VENDOR" = "SUN" ]; then
DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote"
elif [ "$JVM_VENDOR" = "IBM" ]; then
if $os400; then
DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS"
elif $aix; then
DEFAULT_JAVA_OPTS="-Xverify:none -Xlp $DEFAULT_JAVA_OPTS"
else
DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS"
fi
fi
 
# Add the jars in the lib dir
for file in $SSHD_HOME/lib/*.jar
do
if [ -z "$CLASSPATH" ]; then
CLASSPATH="$file"
else
CLASSPATH="$CLASSPATH:$file"
fi
done
DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
 
##
## TODO: Move to conf/profiler/yourkit.{sh|cmd}
##
# Uncomment to enable YourKit profiling
#DEFAULT_JAVA_DEBUG_OPTS="-Xrunyjpagent"
}
 
init() {
# Determine if there is special OS handling we must perform
detectOS
 
# Unlimit the number of file descriptors if possible
unlimitFD
 
# Locate the Sshd home directory
locateHome
 
# Setup the native library path
setupNativePath
 
# Locate the Java VM to execute
locateJava
 
# Determine the JVM vendor
detectJVM
 
# Setup default options
setupDefaults
 
# Install debug options
setupDebugOptions
 
}
 
run() {
if $cygwin; then
SSHD_HOME=`cygpath --path --windows "$SSHD_HOME"`
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
fi
cd $SSHD_BASE
exec $JAVA $JAVA_OPTS -Dsshd.home="$SSHD_HOME" $OPTS -classpath "$CLASSPATH" org.apache.sshd.SshClient "$@"
}
 
main() {
init
run "$@"
}
 
main "$@"
/trunk/rmsshd/assembly/src/main/distribution/bin/sshd.sh
0,0 → 1,266
#!/bin/sh
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
 
DIRNAME=`dirname $0`
PROGNAME=`basename $0`
 
#
# Check/Set up some easily accessible MIN/MAX params for JVM mem usage
#
 
if [ "x$JAVA_MIN_MEM" = "x" ]; then
JAVA_MIN_MEM=128M
export JAVA_MIN_MEM
fi
 
if [ "x$JAVA_MAX_MEM" = "x" ]; then
JAVA_MAX_MEM=512M
export JAVA_MAX_MEM
fi
 
warn() {
echo "${PROGNAME}: $*"
}
 
die() {
warn "$*"
exit 1
}
 
maybeSource() {
file="$1"
if [ -f "$file" ] ; then
. $file
fi
}
 
detectOS() {
# OS specific support (must be 'true' or 'false').
cygwin=false;
darwin=false;
aix=false;
os400=false;
case "`uname`" in
CYGWIN*)
cygwin=true
;;
Darwin*)
darwin=true
;;
AIX*)
aix=true
;;
OS400*)
os400=true
;;
esac
# For AIX, set an environment variable
if $aix; then
export LDR_CNTRL=MAXDATA=0xB0000000@DSA
export IBM_JAVA_HEAPDUMP_TEXT=true
echo $LDR_CNTRL
fi
}
 
unlimitFD() {
# Use the maximum available, or set MAX_FD != -1 to use that
if [ "x$MAX_FD" = "x" ]; then
MAX_FD="maximum"
fi
 
# Increase the maximum file descriptors if we can
if [ "$os400" = "false" ] && [ "$cygwin" = "false" ]; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ "$MAX_FD_LIMIT" != 'unlimited' ]; then
if [ $? -eq 0 ]; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ]; then
# use the system max
MAX_FD="$MAX_FD_LIMIT"
fi
 
ulimit -n $MAX_FD > /dev/null
# echo "ulimit -n" `ulimit -n`
if [ $? -ne 0 ]; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query system maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
fi
}
 
locateHome() {
if [ "x$SSHD_HOME" != "x" ]; then
warn "Ignoring predefined value for SSHD_HOME"
fi
 
# In POSIX shells, CDPATH may cause cd to write to stdout
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
SSHD_HOME=`cd $DIRNAME/..; pwd`
if [ ! -d "$SSHD_HOME" ]; then
die "SSHD_HOME is not valid: $SSHD_HOME"
fi
}
 
setupNativePath() {
# Support for loading native libraries
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:$SSHD_BASE/lib:$SSHD_HOME/lib"
 
# For Cygwin, set PATH from LD_LIBRARY_PATH
if $cygwin; then
LD_LIBRARY_PATH=`cygpath --path --windows "$LD_LIBRARY_PATH"`
PATH="$PATH;$LD_LIBRARY_PATH"
export PATH
fi
export LD_LIBRARY_PATH
}
 
locateJava() {
# Setup the Java Virtual Machine
if $cygwin ; then
[ -n "$JAVA" ] && JAVA=`cygpath --unix "$JAVA"`
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
 
if [ "x$JAVA" = "x" ]; then
if [ "x$JAVA_HOME" = "x" ] && [ "$darwin" = "true" ]; then
JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home
fi
if [ "x$JAVA_HOME" != "x" ]; then
if [ ! -d "$JAVA_HOME" ]; then
die "JAVA_HOME is not valid: $JAVA_HOME"
fi
JAVA="$JAVA_HOME/bin/java"
else
warn "JAVA_HOME not set; results may vary"
JAVA="java"
fi
fi
}
 
detectJVM() {
#echo "`$JAVA -version`"
# This service should call `java -version`,
# read stdout, and look for hints
if $JAVA -version 2>&1 | grep "^IBM" ; then
JVM_VENDOR="IBM"
# on OS/400, java -version does not contain IBM explicitly
elif $os400; then
JVM_VENDOR="IBM"
else
JVM_VENDOR="SUN"
fi
# echo "JVM vendor is $JVM_VENDOR"
}
 
setupDebugOptions() {
if [ "x$JAVA_OPTS" = "x" ]; then
JAVA_OPTS="$DEFAULT_JAVA_OPTS"
fi
export JAVA_OPTS
 
# Set Debug options if enabled
if [ "x$SSHD_DEBUG" != "x" ]; then
# Use the defaults if JAVA_DEBUG_OPTS was not set
if [ "x$JAVA_DEBUG_OPTS" = "x" ]; then
JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS"
fi
 
JAVA_OPTS="$JAVA_DEBUG_OPTS $JAVA_OPTS"
warn "Enabling Java debug options: $JAVA_DEBUG_OPTS"
fi
}
 
setupDefaults() {
DEFAULT_JAVA_OPTS="-Xms$JAVA_MIN_MEM -Xmx$JAVA_MAX_MEM "
 
#Set the JVM_VENDOR specific JVM flags
if [ "$JVM_VENDOR" = "SUN" ]; then
DEFAULT_JAVA_OPTS="-server $DEFAULT_JAVA_OPTS -Dcom.sun.management.jmxremote"
elif [ "$JVM_VENDOR" = "IBM" ]; then
if $os400; then
DEFAULT_JAVA_OPTS="$DEFAULT_JAVA_OPTS"
elif $aix; then
DEFAULT_JAVA_OPTS="-Xverify:none -Xlp $DEFAULT_JAVA_OPTS"
else
DEFAULT_JAVA_OPTS="-Xverify:none $DEFAULT_JAVA_OPTS"
fi
fi
 
# Add the jars in the lib dir
for file in $SSHD_HOME/lib/*.jar
do
if [ -z "$CLASSPATH" ]; then
CLASSPATH="$file"
else
CLASSPATH="$CLASSPATH:$file"
fi
done
DEFAULT_JAVA_DEBUG_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
 
##
## TODO: Move to conf/profiler/yourkit.{sh|cmd}
##
# Uncomment to enable YourKit profiling
#DEFAULT_JAVA_DEBUG_OPTS="-Xrunyjpagent"
}
 
init() {
# Determine if there is special OS handling we must perform
detectOS
 
# Unlimit the number of file descriptors if possible
unlimitFD
 
# Locate the Sshd home directory
locateHome
 
# Setup the native library path
setupNativePath
 
# Locate the Java VM to execute
locateJava
 
# Determine the JVM vendor
detectJVM
 
# Setup default options
setupDefaults
 
# Install debug options
setupDebugOptions
 
}
 
run() {
if $cygwin; then
SSHD_HOME=`cygpath --path --windows "$SSHD_HOME"`
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
fi
cd $SSHD_BASE
exec $JAVA $JAVA_OPTS -Dsshd.home="$SSHD_HOME" $OPTS -classpath "$CLASSPATH" org.apache.sshd.SshServer "$@"
}
 
main() {
init
run "$@"
}
 
main "$@"
/trunk/rmsshd/assembly/src/main/distribution/README.txt
0,0 → 1,46
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
 
Welcome to Apache SSHD
 
Apache SSHD is a library to support the SSH2 protocol on both
client and server side in java.
 
This distribution provides a simple demonstration of a SSH
server that you can launched using the shell scripts in the
bin folder. By default, the port used is 8000 and the authentication
will succeed if the username and password are the same.
SCP and SFTP support are both enabled in this configuration.
 
The lib folder contains the sshd-core jar which is the main jar
and its required dependencies (slf4j-api and mina-core).
Note that if you're running on JDK 7, mina-core becomes an optional
dependency as a native IO layer built on top of NIO2 is provided
and selected by default if available.
 
The sshd-pam module is an experimental module for leveraging the
Unix PAM authentication mechanism which is not really usable at the
moment.
The sshf-sftp module is an experimental module which provides an
object model for the SFTP subsystem to ease writing custom SFTP
servers.
 
Please send feedback to users@mina.apache.org.
 
The Apache SSHD team.
/trunk/rmsshd/assembly/src/main/descriptors/windows-bin.xml
0,0 → 1,36
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<assembly>
<id>bin</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>src/main/distribution</directory>
<outputDirectory>/</outputDirectory>
<lineEnding>dos</lineEnding>
</fileSet>
</fileSets>
 
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
/trunk/rmsshd/assembly/src/main/descriptors/unix-src.xml
0,0 → 1,92
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<assembly>
<id>src</id>
<formats>
<format>tar.gz</format>
</formats>
<fileSets>
<!-- Binary Files -->
<fileSet>
<directory>${basedir}/..</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/*.jpeg</include>
<include>**/*.jpg</include>
<include>**/*.gif</include>
<include>**/*.png</include>
<include>**/*.exe</include>
<include>**/*.dll</include>
<include>**/*.jar</include>
<include>**/*.so</include>
<include>**/*.ks</include>
<include>**/*.ts</include>
<include>**/*.keystore</include>
<include>**/*.bin</include>
<include>**/*.jnilib</include>
<include>**/*.cert</include>
</includes>
<excludes>
<exclude>**/eclipse-classes/**</exclude>
<exclude>**/target/**</exclude>
</excludes>
</fileSet>
 
<!-- Text Files -->
<fileSet>
<directory>${basedir}/..</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/*.jpeg</exclude>
<exclude>**/*.jpg</exclude>
<exclude>**/*.gif</exclude>
<exclude>**/*.png</exclude>
<exclude>**/*.exe</exclude>
<exclude>**/*.dll</exclude>
<exclude>**/*.jar</exclude>
<exclude>**/*.so</exclude>
<exclude>**/*.ks</exclude>
<exclude>**/*.ts</exclude>
<exclude>**/*.keystore</exclude>
<exclude>**/*.bin</exclude>
<exclude>**/*.jnilib</exclude>
<exclude>**/*.cert</exclude>
<exclude>**/target/**</exclude>
<exclude>**/build/**</exclude>
<exclude>**/eclipse-classes/**</exclude>
<exclude>**/.*</exclude>
<exclude>**/.*/**</exclude>
 
<exclude>**/surefire*</exclude>
<exclude>**/svn-commit*</exclude>
 
<exclude>**/*.iml</exclude>
<exclude>**/*.ipr</exclude>
<exclude>**/*.iws</exclude>
 
<exclude>**/cobertura.ser</exclude>
 
<exclude>sshd-core/src/docs/*.txt</exclude>
</excludes>
<lineEnding>unix</lineEnding>
</fileSet>
</fileSets>
</assembly>
/trunk/rmsshd/assembly/src/main/descriptors/unix-bin.xml
0,0 → 1,55
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<assembly>
<id>bin</id>
<formats>
<format>tar.gz</format>
</formats>
<fileSets>
<fileSet>
<directory>src/main/distribution</directory>
<outputDirectory>/</outputDirectory>
<lineEnding>unix</lineEnding>
<excludes>
<exclude>bin/sshd.sh</exclude>
<exclude>bin/ssh.sh</exclude>
</excludes>
</fileSet>
</fileSets>
 
<files>
<file>
<source>src/main/distribution/bin/sshd.sh</source>
<outputDirectory>/bin/</outputDirectory>
<fileMode>0755</fileMode>
<lineEnding>unix</lineEnding>
</file>
<file>
<source>src/main/distribution/bin/ssh.sh</source>
<outputDirectory>/bin/</outputDirectory>
<fileMode>0755</fileMode>
<lineEnding>unix</lineEnding>
</file>
</files>
 
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
</dependencySet>
</dependencySets>
</assembly>
/trunk/rmsshd/assembly/src/main/descriptors/windows-src.xml
0,0 → 1,92
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<assembly>
<id>src</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<!-- Binary Files -->
<fileSet>
<directory>${basedir}/..</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/*.jpeg</include>
<include>**/*.jpg</include>
<include>**/*.gif</include>
<include>**/*.png</include>
<include>**/*.exe</include>
<include>**/*.dll</include>
<include>**/*.jar</include>
<include>**/*.so</include>
<include>**/*.ks</include>
<include>**/*.ts</include>
<include>**/*.keystore</include>
<include>**/*.bin</include>
<include>**/*.jnilib</include>
<include>**/*.cert</include>
</includes>
<excludes>
<exclude>**/eclipse-classes/**</exclude>
<exclude>**/target/**</exclude>
</excludes>
</fileSet>
 
<!-- Text Files -->
<fileSet>
<directory>${basedir}/..</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/*.jpeg</exclude>
<exclude>**/*.jpg</exclude>
<exclude>**/*.gif</exclude>
<exclude>**/*.png</exclude>
<exclude>**/*.exe</exclude>
<exclude>**/*.dll</exclude>
<exclude>**/*.jar</exclude>
<exclude>**/*.so</exclude>
<exclude>**/*.ks</exclude>
<exclude>**/*.ts</exclude>
<exclude>**/*.keystore</exclude>
<exclude>**/*.bin</exclude>
<exclude>**/*.jnilib</exclude>
<exclude>**/*.cert</exclude>
<exclude>**/target/**</exclude>
<exclude>**/build/**</exclude>
<exclude>**/eclipse-classes/**</exclude>
<exclude>**/.*</exclude>
<exclude>**/.*/**</exclude>
 
<exclude>**/surefire*</exclude>
<exclude>**/svn-commit*</exclude>
 
<exclude>**/*.iml</exclude>
<exclude>**/*.ipr</exclude>
<exclude>**/*.iws</exclude>
 
<exclude>**/cobertura.ser</exclude>
 
<exclude>sshd-core/src/docs/*.txt</exclude>
</excludes>
<lineEnding>unix</lineEnding>
</fileSet>
</fileSets>
</assembly>
/trunk/rmsshd/assembly/pom.xml
0,0 → 1,144
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
 
<!--
 
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
 
<modelVersion>4.0.0</modelVersion>
 
<parent>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd</artifactId>
<version>0.13.1-SNAPSHOT</version>
</parent>
 
<groupId>org.apache.sshd</groupId>
<artifactId>apache-sshd</artifactId>
<version>0.13.1-SNAPSHOT</version>
<name>Apache Mina SSHD :: Assembly</name>
<packaging>pom</packaging>
 
<properties>
<projectRoot>${basedir}/..</projectRoot>
</properties>
 
<dependencies>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
</dependency>
<!--
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-sftp</artifactId>
</dependency>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-pam</artifactId>
<exclusions>
<exclusion>
<groupId>net.sf.jpam</groupId>
<artifactId>jpam</artifactId>
</exclusion>
</exclusions>
</dependency>
-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
</dependency>
<dependency>
<groupId>tomcat</groupId>
<artifactId>tomcat-apr</artifactId>
</dependency>
</dependencies>
 
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>unix-bin</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/descriptors/unix-bin.xml</descriptor>
</descriptors>
<finalName>${project.artifactId}-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<tarLongFileMode>gnu</tarLongFileMode>
</configuration>
</execution>
<execution>
<id>windows-bin</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/descriptors/windows-bin.xml</descriptor>
</descriptors>
<finalName>${project.artifactId}-${project.version}</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
<execution>
<id>unix-src</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/descriptors/unix-src.xml</descriptor>
</descriptors>
<tarLongFileMode>gnu</tarLongFileMode>
</configuration>
</execution>
<execution>
<id>windows-src</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/descriptors/windows-src.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
 
</project>
/trunk/rmsshd/NOTICE.txt
0,0 → 1,5
Apache MINA SSHD
Copyright 2008-2014 The Apache Software Foundation
 
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
/trunk/rmsshd/LICENSE.txt
0,0 → 1,203
 
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
 
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 
1. Definitions.
 
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
 
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
 
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
 
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
 
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
 
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
 
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
 
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
 
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
 
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
 
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
 
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
 
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
 
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
 
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
 
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
 
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
 
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
 
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
 
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
 
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
 
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
 
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
 
END OF TERMS AND CONDITIONS
 
APPENDIX: How to apply the Apache License to your work.
 
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
 
Copyright [yyyy] [name of copyright owner]
 
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 
/trunk/rmsshd/sshd-git/src/test/java/org/apache/sshd/git/pgm/GitPgmCommandTest.java
0,0 → 1,98
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.git.pgm;
 
import java.io.File;
import java.util.Arrays;
 
import org.apache.sshd.ClientChannel;
import org.apache.sshd.ClientSession;
import org.apache.sshd.SshClient;
import org.apache.sshd.SshServer;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.git.util.BogusPasswordAuthenticator;
import org.apache.sshd.git.util.EchoShellFactory;
import org.apache.sshd.git.util.Utils;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.sftp.SftpSubsystem;
import org.eclipse.jgit.api.Git;
import org.junit.Test;
 
/**
*/
public class GitPgmCommandTest {
 
@Test
public void testGitpgm() throws Exception {
 
//
// TODO: the GitpgmCommandFactory is kept in the test tree
// TODO: because it's quite limited for now
//
 
SshServer sshd = SshServer.setUpDefaultServer();
sshd.setPort(8001);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystem.Factory()));
sshd.setShellFactory(new EchoShellFactory());
sshd.setCommandFactory(new GitPgmCommandFactory("target/git/pgm"));
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.start();
 
File serverDir = new File("target/git/pgm");
Utils.deleteRecursive(serverDir);
 
File repo = new File(serverDir, "test");
 
SshClient client = SshClient.setUpDefaultClient();
client.start();
 
ClientSession session = client.connect("sshd", "localhost", 8001).await().getSession();
session.addPasswordIdentity("sshd");
session.auth().verify();
 
Git.init().setDirectory(repo).call();
Git git = Git.open(repo);
git.commit().setMessage("First Commit").setCommitter("sshd", "sshd@apache.org").call();
 
new File("target/git/pgm/test/readme.txt").createNewFile();
execute(session, "git --git-dir test add readme.txt");
 
execute(session, "git --git-dir test commit -m \"readme\"");
 
client.stop();
sshd.stop();
}
 
private void execute(ClientSession session, String command) throws Exception {
ChannelExec channel = session.createExecChannel(command);
channel.setOut(System.out);
channel.setErr(System.err);
channel.open().verify();
channel.waitFor(ClientChannel.CLOSED, 0);
if (channel.getExitStatus() != null) {
int s = channel.getExitStatus();
if (s != 0) {
throw new Exception("Command failed with status " + s);
}
}
}
 
}
/trunk/rmsshd/sshd-git/src/test/java/org/apache/sshd/git/util/Utils.java
0,0 → 1,72
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.git.util;
 
import java.io.File;
import java.net.ServerSocket;
import java.net.URISyntaxException;
import java.net.URL;
 
import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
 
public class Utils {
 
public static FileKeyPairProvider createTestHostKeyProvider() {
return createTestKeyPairProvider("hostkey.pem");
}
 
public static FileKeyPairProvider createTestKeyPairProvider(String resource) {
return new FileKeyPairProvider(new String[] { getFile(resource) });
}
 
public static int getFreePort() throws Exception {
ServerSocket s = new ServerSocket(0);
try {
return s.getLocalPort();
} finally {
s.close();
}
}
 
private static String getFile(String resource) {
URL url = Utils.class.getClassLoader().getResource(resource);
File f;
try {
f = new File(url.toURI());
} catch(URISyntaxException e) {
f = new File(url.getPath());
}
return f.toString();
}
 
public static void deleteRecursive(File file) {
if (file != null) {
if (file.isDirectory()) {
File[] children = file.listFiles();
if (children != null) {
for (File child : children) {
deleteRecursive(child);
}
}
}
file.delete();
}
}
 
}
/trunk/rmsshd/sshd-git/src/test/java/org/apache/sshd/git/util/BogusPasswordAuthenticator.java
0,0 → 1,34
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.git.util;
 
import org.apache.sshd.server.PasswordAuthenticator;
import org.apache.sshd.server.session.ServerSession;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class BogusPasswordAuthenticator implements PasswordAuthenticator {
 
public boolean authenticate(String username, String password, ServerSession session) {
return username != null && username.equals(password);
}
}
/trunk/rmsshd/sshd-git/src/test/java/org/apache/sshd/git/util/EchoShellFactory.java
0,0 → 1,115
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.git.util;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
 
import org.apache.sshd.common.Factory;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class EchoShellFactory implements Factory<Command> {
 
public Command create() {
return new EchoShell();
}
 
public static class EchoShell implements Command, Runnable {
 
private InputStream in;
private OutputStream out;
private OutputStream err;
private ExitCallback callback;
private Environment environment;
private Thread thread;
 
public InputStream getIn() {
return in;
}
 
public OutputStream getOut() {
return out;
}
 
public OutputStream getErr() {
return err;
}
 
public Environment getEnvironment() {
return environment;
}
 
public void setInputStream(InputStream in) {
this.in = in;
}
 
public void setOutputStream(OutputStream out) {
this.out = out;
}
 
public void setErrorStream(OutputStream err) {
this.err = err;
}
 
public void setExitCallback(ExitCallback callback) {
this.callback = callback;
}
 
public void start(Environment env) throws IOException {
environment = env;
thread = new Thread(this, "EchoShell");
thread.start();
}
 
public void destroy() {
thread.interrupt();
}
 
public void run() {
BufferedReader r = new BufferedReader(new InputStreamReader(in));
try {
for (;;) {
String s = r.readLine();
if (s == null) {
return;
}
out.write((s + "\n").getBytes());
out.flush();
if ("exit".equals(s)) {
return;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
callback.onExit(0);
}
}
}
}
/trunk/rmsshd/sshd-git/src/test/java/org/apache/sshd/git/pack/GitPackCommandTest.java
0,0 → 1,82
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.git.pack;
 
import java.io.File;
import java.util.Arrays;
 
import com.jcraft.jsch.JSch;
import org.apache.sshd.SshServer;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.git.transport.GitSshdSessionFactory;
import org.apache.sshd.git.util.BogusPasswordAuthenticator;
import org.apache.sshd.git.util.EchoShellFactory;
import org.apache.sshd.git.util.Utils;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.sftp.SftpSubsystem;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.junit.Test;
 
/**
*/
public class GitPackCommandTest {
 
@Test
public void testGitPack() throws Exception {
SshServer sshd = SshServer.setUpDefaultServer();
sshd.setPort(8001);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystem.Factory()));
sshd.setShellFactory(new EchoShellFactory());
sshd.setCommandFactory(new GitPackCommandFactory("target/git/server"));
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.start();
 
File serverDir = new File("target/git/server/test.git");
Utils.deleteRecursive(serverDir);
Git.init().setBare(true).setDirectory(serverDir).call();
 
JSch.setConfig("StrictHostKeyChecking", "no");
CredentialsProvider.setDefault(new UsernamePasswordCredentialsProvider("sshd", "sshd"));
GitSshdSessionFactory.setInstance(new GitSshdSessionFactory());
 
File dir = new File("target/git/local/test.git");
Utils.deleteRecursive(dir);
Git.cloneRepository()
.setURI("ssh://sshd@localhost:8001/test.git")
.setDirectory(dir)
.call();
 
Git git = Git.open(dir);
git.commit().setMessage("First Commit").setCommitter("sshd", "sshd@apache.org").call();
git.push().call();
 
new File("target/git/local/test.git/readme.txt").createNewFile();
git.add().addFilepattern("readme.txt").call();
git.commit().setMessage("readme").setCommitter("sshd", "sshd@apache.org").call();
git.push().call();
 
git.pull().setRebase(true).call();
 
sshd.stop();
}
 
}
/trunk/rmsshd/sshd-git/src/test/resources/hostkey.pem
0,0 → 1,30
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDdfIWeSV4o68dRrKSzFd/Bk51E65UTmmSrmW0O1ohtzi6HzsDP
jXgCtlTt3FqTcfFfI92IlTr4JWqC9UK1QT1ZTeng0MkPQmv68hDANHbt5CpETZHj
W5q4OOgWhVvj5IyOC2NZHtKlJBkdsMAa15ouOOJLzBvAvbqOR/yUROsEiQIDAQAB
AoGBANG3JDW6NoP8rF/zXoeLgLCj+tfVUPSczhGFVrQkAk4mWfyRkhN0WlwHFOec
K89MpkV1ij/XPVzU4MNbQ2yod1KiDylzvweYv+EaEhASCmYNs6LS03punml42SL9
97tOmWfVJXxlQoLiY6jHPU97vTc65k8gL+gmmrpchsW0aqmZAkEA/c8zfmKvY37T
cxcLLwzwsqqH7g2KZGTf9aRmx2ebdW+QKviJJhbdluDgl1TNNFj5vCLznFDRHiqJ
wq0wkZ39cwJBAN9l5v3kdXj21UrurNPdlV0n2GZBt2vblooQC37XHF97r2zM7Ou+
Lg6MyfJClyguhWL9dxnGbf3btQ0l3KDstxMCQCRaiEqjAfIjWVATzeNIXDWLHXso
b1kf5cA+cwY+vdKdTy4IeUR+Y/DXdvPWDqpf0C11aCVMohdLCn5a5ikFUycCQDhV
K/BuAallJNfmY7JxN87r00fF3ojWMJnT/fIYMFFrkQrwifXQWTDWE76BSDibsosJ
u1TGksnm8zrDh2UVC/0CQFrHTiSl/3DHvWAbOJawGKg46cnlDcAhSyV8Frs8/dlP
7YGG3eqkw++lsghqmFO6mRUTKsBmiiB2wgLGhL5pyYY=
-----END RSA PRIVATE KEY-----
/trunk/rmsshd/sshd-git/src/test/resources/log4j.properties
0,0 → 1,38
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
#
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
 
#
# The logging properties used during tests..
#
log4j.rootLogger=INFO, stdout
#log4j.logger.org.apache.sshd=TRACE
#log4j.logger.org.apache.sshd.common.channel.Window=DEBUG
 
# CONSOLE appender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
 
# File appender
log4j.appender.out=org.apache.log4j.FileAppender
log4j.appender.out.layout=org.apache.log4j.PatternLayout
log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
log4j.appender.out.file=target/servicemix-test.log
log4j.appender.out.append=true
/trunk/rmsshd/sshd-git/src/main/java/org/apache/sshd/git/pgm/EmbeddedCommandRunner.java
0,0 → 1,238
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.git.pgm;
 
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
 
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryBuilder;
import org.eclipse.jgit.pgm.CommandCatalog;
import org.eclipse.jgit.pgm.CommandRef;
import org.eclipse.jgit.pgm.Die;
import org.eclipse.jgit.pgm.TextBuiltin;
import org.eclipse.jgit.pgm.internal.CLIText;
import org.eclipse.jgit.pgm.opt.CmdLineParser;
import org.eclipse.jgit.pgm.opt.SubcommandHandler;
import org.eclipse.jgit.util.io.ThrowingPrintWriter;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.ExampleMode;
import org.kohsuke.args4j.Option;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class EmbeddedCommandRunner {
@Option(name = "--help", usage = "usage_displayThisHelpText", aliases = { "-h" })
private boolean help;
 
@Option(name = "--show-stack-trace", usage = "usage_displayThejavaStackTraceOnExceptions")
private boolean showStackTrace;
 
@Option(name = "--git-dir", metaVar = "metaVar_gitDir", usage = "usage_setTheGitRepositoryToOperateOn")
private String gitdir;
 
@Argument(index = 0, metaVar = "metaVar_command", required = true, handler = SubcommandHandler.class)
private TextBuiltin subcommand;
 
@Argument(index = 1, metaVar = "metaVar_arg")
private List<String> arguments = new ArrayList<String>();
 
private String rootDir;
 
public EmbeddedCommandRunner(String rootDir) {
this.rootDir = rootDir;
}
 
/**
* Execute a command.
*
* @param argv
* the command and its arguments
* @param in
* the input stream, may be null in which case the system input stream will be used
* @param out
* the output stream, may be null in which case the system output stream will be used
* @param err
* the error stream, may be null in which case the system error stream will be used
* @throws Exception
* if an error occurs
*/
public void execute(final String[] argv, InputStream in, OutputStream out, OutputStream err) throws Exception {
final CmdLineParser clp = new CmdLineParser(this);
PrintWriter writer = new PrintWriter(err != null ? err : System.err);
try {
clp.parseArgument(argv);
} catch (CmdLineException e) {
if (argv.length > 0 && !help) {
writer.println(MessageFormat.format(CLIText.get().fatalError, e.getMessage()));
writer.flush();
throw new Die(true);
}
}
 
if (argv.length == 0 || help) {
final String ex = clp.printExample(ExampleMode.ALL, CLIText.get().resourceBundle());
writer.println("jgit" + ex + " command [ARG ...]"); //$NON-NLS-1$
if (help) {
writer.println();
clp.printUsage(writer, CLIText.get().resourceBundle());
writer.println();
} else if (subcommand == null) {
writer.println();
writer.println(CLIText.get().mostCommonlyUsedCommandsAre);
final CommandRef[] common = CommandCatalog.common();
int width = 0;
for (final CommandRef c : common)
width = Math.max(width, c.getName().length());
width += 2;
 
for (final CommandRef c : common) {
writer.print(' ');
writer.print(c.getName());
for (int i = c.getName().length(); i < width; i++)
writer.print(' ');
writer.print(CLIText.get().resourceBundle().getString(c.getUsage()));
writer.println();
}
writer.println();
}
writer.flush();
throw new Die(true);
}
 
gitdir = new File(rootDir, gitdir).getPath();
 
final TextBuiltin cmd = subcommand;
// cmd.ins = in;
// cmd.outs = out;
// cmd.errs = err;
// if (cmd.requiresRepository())
// cmd.init(openGitDir(gitdir), null);
// else
// cmd.init(null, gitdir);
// try {
// cmd.execute(arguments.toArray(new String[arguments.size()]));
// } finally {
// if (cmd.outw != null)
// cmd.outw.flush();
// if (cmd.errw != null)
// cmd.errw.flush();
// }
set(cmd, "ins", in);
set(cmd, "outs", out);
set(cmd, "errs", err);
if ((Boolean) call(cmd, "requiresRepository")) {
call(cmd, "init", new Class[] { Repository.class, String.class }, new Object[] { openGitDir(gitdir), gitdir });
} else {
call(cmd, "init", new Class[] { Repository.class, String.class }, new Object[] { null, gitdir });
}
try {
cmd.execute(arguments.toArray(new String[arguments.size()]));
} finally {
if (get(cmd, "outw") != null)
((ThrowingPrintWriter) get(cmd, "outw")).flush();
if (get(cmd, "errw") != null)
((ThrowingPrintWriter) get(cmd, "errw")).flush();
}
}
 
private Object get(Object obj, String name) throws IllegalAccessException, NoSuchFieldException {
Class clazz = obj.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(name);
}
 
private void set(Object obj, String name, Object val) throws IllegalAccessException, NoSuchFieldException {
Class clazz = obj.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
field.set(obj, val);
return;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchFieldException(name);
}
 
private Object call(Object obj, String name) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
return call(obj, name, new Class[0], new Object[0]);
}
 
private Object call(Object obj, String name, Class<?>[] types, Object[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class<?> clazz = obj.getClass();
while (clazz != null) {
try {
Method method = clazz.getDeclaredMethod(name, types);
method.setAccessible(true);
return method.invoke(obj, args);
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
throw new NoSuchMethodException(name);
}
 
/**
* Evaluate the {@code --git-dir} option and open the repository.
*
* @param gitdir
* the {@code --git-dir} option given on the command line. May be
* null if it was not supplied.
* @return the repository to operate on.
* @throws IOException
* the repository cannot be opened.
*/
protected Repository openGitDir(String gitdir) throws IOException {
return Git.open(new File(gitdir)).getRepository();
/*
RepositoryBuilder rb = new RepositoryBuilder() //
.setGitDir(gitdir != null ? new File(gitdir) : null) //
.readEnvironment() //
.findGitDir();
if (rb.getGitDir() == null)
throw new Die(CLIText.get().cantFindGitDirectory);
return rb.build();
*/
}
}
/trunk/rmsshd/sshd-git/src/main/java/org/apache/sshd/git/pgm/GitPgmCommand.java
0,0 → 1,183
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.git.pgm;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
 
import org.apache.sshd.common.channel.ChannelOutputStream;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class GitPgmCommand implements Command, Runnable {
 
private String rootDir;
private String command;
private InputStream in;
private OutputStream out;
private OutputStream err;
private ExitCallback callback;
 
public GitPgmCommand(String rootDir, String command) {
this.rootDir = rootDir;
this.command = command;
}
 
public void setInputStream(InputStream in) {
this.in = in;
}
 
public void setOutputStream(OutputStream out) {
this.out = out;
if (out instanceof ChannelOutputStream) {
((ChannelOutputStream) out).setNoDelay(true);
}
}
 
public void setErrorStream(OutputStream err) {
this.err = err;
if (err instanceof ChannelOutputStream) {
((ChannelOutputStream) err).setNoDelay(true);
}
}
 
public void setExitCallback(ExitCallback callback) {
this.callback = callback;
}
 
public void start(Environment env) throws IOException {
new Thread(this).start();
}
 
public void run() {
try {
List<String> strs = parseDelimitedString(command, " ", true);
String[] args = strs.toArray(new String[strs.size()]);
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("'") && args[i].endsWith("'")) {
args[i] = args[i].substring(1, args[i].length() - 1);
}
if (args[i].startsWith("\"") && args[i].endsWith("\"")) {
args[i] = args[i].substring(1, args[i].length() - 1);
}
}
 
new EmbeddedCommandRunner(rootDir).execute(args, in, out, err);
if (callback != null) {
callback.onExit(0);
}
} catch (Throwable t) {
try {
err.write((t.getMessage() + "\n").getBytes());
err.flush();
} catch (IOException e) {
e.printStackTrace();
}
if (callback != null) {
callback.onExit(-1);
}
}
}
 
public void destroy() {
//To change body of implemented methods use File | Settings | File Templates.
}
 
/**
* Parses delimited string and returns an array containing the tokens. This
* parser obeys quotes, so the delimiter character will be ignored if it is
* inside of a quote. This method assumes that the quote character is not
* included in the set of delimiter characters.
*
* @param value the delimited string to parse.
* @param delim the characters delimiting the tokens.
* @return a list of string or an empty list if there are none.
*/
private static List<String> parseDelimitedString(String value, String delim, boolean trim) {
if (value == null) {
value = "";
}
 
List<String> list = new ArrayList<String>();
 
int CHAR = 1;
int DELIMITER = 2;
int STARTQUOTE = 4;
int ENDQUOTE = 8;
 
StringBuilder sb = new StringBuilder();
 
int expecting = (CHAR | DELIMITER | STARTQUOTE);
 
boolean isEscaped = false;
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
 
boolean isDelimiter = (delim.indexOf(c) >= 0);
 
if (!isEscaped && (c == '\\')) {
isEscaped = true;
continue;
}
 
if (isEscaped) {
sb.append(c);
} else if (isDelimiter && ((expecting & DELIMITER) > 0)) {
if (trim) {
list.add(sb.toString().trim());
} else {
list.add(sb.toString());
}
sb.delete(0, sb.length());
expecting = (CHAR | DELIMITER | STARTQUOTE);
} else if ((c == '"') && ((expecting & STARTQUOTE) > 0)) {
sb.append(c);
expecting = CHAR | ENDQUOTE;
} else if ((c == '"') && ((expecting & ENDQUOTE) > 0)) {
sb.append(c);
expecting = (CHAR | STARTQUOTE | DELIMITER);
} else if ((expecting & CHAR) > 0) {
sb.append(c);
} else {
throw new IllegalArgumentException("Invalid delimited string: " + value);
}
 
isEscaped = false;
}
 
if (sb.length() > 0) {
if (trim) {
list.add(sb.toString().trim());
} else {
list.add(sb.toString());
}
}
 
return list;
}
}
/trunk/rmsshd/sshd-git/src/main/java/org/apache/sshd/git/pgm/GitPgmCommandFactory.java
0,0 → 1,54
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.git.pgm;
 
import org.apache.sshd.server.Command;
import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.command.UnknownCommand;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class GitPgmCommandFactory implements CommandFactory {
 
private final String rootDir;
private final CommandFactory delegate;
 
public GitPgmCommandFactory(String rootDir) {
this(rootDir, null);
}
 
public GitPgmCommandFactory(String rootDir, CommandFactory delegate) {
this.rootDir = rootDir;
this.delegate = delegate;
}
 
public Command createCommand(String command) {
if (command.startsWith("git ")) {
return new GitPgmCommand(rootDir, command.substring("git ".length()));
} else if (delegate != null) {
return delegate.createCommand(command);
} else {
return new UnknownCommand(command);
}
}
 
}
/trunk/rmsshd/sshd-git/src/main/java/org/apache/sshd/git/transport/GitSshdSessionFactory.java
0,0 → 1,136
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.git.transport;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
 
import org.apache.sshd.ClientChannel;
import org.apache.sshd.ClientSession;
import org.apache.sshd.SshClient;
import org.apache.sshd.client.channel.ChannelExec;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.transport.CredentialItem;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.RemoteSession;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.util.FS;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class GitSshdSessionFactory extends SshSessionFactory {
 
@Override
public RemoteSession getSession(URIish uri, CredentialsProvider credentialsProvider, FS fs, int tms) throws TransportException {
try {
return new SshdSession(uri, credentialsProvider, fs, tms);
} catch (Exception e) {
throw new TransportException("Unable to connect", e);
}
}
 
protected SshClient createClient() {
return SshClient.setUpDefaultClient();
}
 
public class SshdSession implements RemoteSession {
 
private final SshClient client;
private final ClientSession session;
 
public SshdSession(URIish uri, CredentialsProvider credentialsProvider, FS fs, int tms) throws IOException, InterruptedException {
String user = uri.getUser();
final String pass = uri.getPass();
String host = uri.getHost();
int port = uri.getPort();
char[] pass2 = null;
 
if (!credentialsProvider.isInteractive()) {
CredentialItem.Username usrItem = new CredentialItem.Username();
CredentialItem.Password pwdItem = new CredentialItem.Password();
if (credentialsProvider.get(uri, usrItem, pwdItem)) {
if (user == null) {
user = usrItem.getValue();
} else if (user.equals(usrItem.getValue())) {
pass2 = pwdItem.getValue();
}
}
 
}
 
client = createClient();
client.start();
session = client.connect(user, host, port).await().getSession();
if (pass != null) {
session.addPasswordIdentity(pass);
}
if (pass2 != null) {
session.addPasswordIdentity(new String(pass2));
}
session.auth().verify();
 
}
 
public Process exec(String commandName, int timeout) throws IOException {
final ChannelExec channel = session.createExecChannel(commandName);
channel.open().verify();
return new Process() {
@Override
public OutputStream getOutputStream() {
return channel.getInvertedIn();
}
 
@Override
public InputStream getInputStream() {
return channel.getInvertedOut();
}
 
@Override
public InputStream getErrorStream() {
return channel.getInvertedErr();
}
 
@Override
public int waitFor() throws InterruptedException {
return channel.waitFor(ClientChannel.CLOSED, 0);
}
 
@Override
public int exitValue() {
return channel.getExitStatus();
}
 
@Override
public void destroy() {
channel.close(true);
}
};
}
 
public void disconnect() {
client.close(true);
}
 
}
}
/trunk/rmsshd/sshd-git/src/main/java/org/apache/sshd/git/pack/GitPackCommand.java
0,0 → 1,193
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.git.pack;
 
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
 
import org.apache.sshd.common.channel.ChannelOutputStream;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.transport.UploadPack;
import org.eclipse.jgit.util.FS;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class GitPackCommand implements Command, Runnable {
 
private String rootDir;
private String command;
private InputStream in;
private OutputStream out;
private OutputStream err;
private ExitCallback callback;
 
public GitPackCommand(String rootDir, String command) {
this.rootDir = rootDir;
this.command = command;
}
 
public void setInputStream(InputStream in) {
this.in = in;
}
 
public void setOutputStream(OutputStream out) {
this.out = out;
if (out instanceof ChannelOutputStream) {
((ChannelOutputStream) out).setNoDelay(true);
}
}
 
public void setErrorStream(OutputStream err) {
this.err = err;
if (err instanceof ChannelOutputStream) {
((ChannelOutputStream) err).setNoDelay(true);
}
}
 
public void setExitCallback(ExitCallback callback) {
this.callback = callback;
}
 
public void start(Environment env) throws IOException {
new Thread(this).start();
}
 
public void run() {
try {
List<String> strs = parseDelimitedString(command, " ", true);
String[] args = strs.toArray(new String[strs.size()]);
for (int i = 0; i < args.length; i++) {
if (args[i].startsWith("'") && args[i].endsWith("'")) {
args[i] = args[i].substring(1, args[i].length() - 1);
}
if (args[i].startsWith("\"") && args[i].endsWith("\"")) {
args[i] = args[i].substring(1, args[i].length() - 1);
}
}
 
if (args.length != 2) {
throw new IllegalArgumentException("Invalid git command line: " + command);
}
File srcGitdir = new File(rootDir, args[1]);
RepositoryCache.FileKey key = RepositoryCache.FileKey.lenient(srcGitdir, FS.DETECTED);
Repository db = key.open(true /* must exist */);
if ("git-upload-pack".equals(args[0])) {
new UploadPack(db).upload(in, out, err);
} else if ("git-receive-pack".equals(args[0])) {
new ReceivePack(db).receive(in, out, err);
} else {
throw new IllegalArgumentException("Unknown git command: " + command);
}
} catch (Throwable t) {
t.printStackTrace();
}
if (callback != null) {
callback.onExit(0);
}
}
 
public void destroy() {
//To change body of implemented methods use File | Settings | File Templates.
}
 
/**
* Parses delimited string and returns an array containing the tokens. This
* parser obeys quotes, so the delimiter character will be ignored if it is
* inside of a quote. This method assumes that the quote character is not
* included in the set of delimiter characters.
*
* @param value the delimited string to parse.
* @param delim the characters delimiting the tokens.
* @return a list of string or an empty list if there are none.
*/
private static List<String> parseDelimitedString(String value, String delim, boolean trim) {
if (value == null) {
value = "";
}
 
List<String> list = new ArrayList<String>();
 
int CHAR = 1;
int DELIMITER = 2;
int STARTQUOTE = 4;
int ENDQUOTE = 8;
 
StringBuilder sb = new StringBuilder();
 
int expecting = (CHAR | DELIMITER | STARTQUOTE);
 
boolean isEscaped = false;
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
 
boolean isDelimiter = (delim.indexOf(c) >= 0);
 
if (!isEscaped && (c == '\\')) {
isEscaped = true;
continue;
}
 
if (isEscaped) {
sb.append(c);
} else if (isDelimiter && ((expecting & DELIMITER) > 0)) {
if (trim) {
list.add(sb.toString().trim());
} else {
list.add(sb.toString());
}
sb.delete(0, sb.length());
expecting = (CHAR | DELIMITER | STARTQUOTE);
} else if ((c == '"') && ((expecting & STARTQUOTE) > 0)) {
sb.append(c);
expecting = CHAR | ENDQUOTE;
} else if ((c == '"') && ((expecting & ENDQUOTE) > 0)) {
sb.append(c);
expecting = (CHAR | STARTQUOTE | DELIMITER);
} else if ((expecting & CHAR) > 0) {
sb.append(c);
} else {
throw new IllegalArgumentException("Invalid delimited string: " + value);
}
 
isEscaped = false;
}
 
if (sb.length() > 0) {
if (trim) {
list.add(sb.toString().trim());
} else {
list.add(sb.toString());
}
}
 
return list;
}
}
/trunk/rmsshd/sshd-git/src/main/java/org/apache/sshd/git/pack/GitPackCommandFactory.java
0,0 → 1,54
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.git.pack;
 
import org.apache.sshd.server.Command;
import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.command.UnknownCommand;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class GitPackCommandFactory implements CommandFactory {
 
private final String rootDir;
private final CommandFactory delegate;
 
public GitPackCommandFactory(String rootDir) {
this(rootDir, null);
}
 
public GitPackCommandFactory(String rootDir, CommandFactory delegate) {
this.rootDir = rootDir;
this.delegate = delegate;
}
 
public Command createCommand(String command) {
if (command.startsWith("git-")) {
return new GitPackCommand(rootDir, command);
} else if (delegate != null) {
return delegate.createCommand(command);
} else {
return new UnknownCommand(command);
}
}
 
}
/trunk/rmsshd/sshd-git/pom.xml
0,0 → 1,100
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
 
<!--
 
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
 
<modelVersion>4.0.0</modelVersion>
 
<parent>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd</artifactId>
<version>0.13.1-SNAPSHOT</version>
</parent>
 
<artifactId>sshd-git</artifactId>
<version>0.13.1-SNAPSHOT</version>
<name>Apache Mina SSHD :: Git</name>
<packaging>jar</packaging>
<inceptionYear>2008</inceptionYear>
 
<properties>
<projectRoot>${basedir}/..</projectRoot>
</properties>
 
<dependencies>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit.pgm</artifactId>
<optional>true</optional>
</dependency>
 
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk15on</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
 
<build>
<resources>
<resource>
<directory>src/main/filtered-resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
</plugin>
</plugins>
</build>
 
</project>
/trunk/rmsshd/sshd-git/README.txt
0,0 → 1,4
This module contains an SSHD CommandFactory to support git through SSH.
The git commands are provided by a modified version of jgit-pgm
available at:
https://github.com/gnodet/jgit/tree/413522
/trunk/rmsshd/src/legal/notices.xml
0,0 → 1,89
<?xml version="1.0" encoding="UTF-8"?>
 
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
 
<supplementalDataModels>
<supplement>
<project>
<groupId>bouncycastle</groupId>
<artifactId>bcprov-jdk15</artifactId>
<name>Bouncy Castle Crypto APIs for Java</name>
<organization>
<name>The Legion of the Bouncy Castle</name>
<url>http://www.bouncycastle.org</url>
</organization>
<licenses>
<license>
<name>Bouncy Castle License</name>
<url>http://www.bouncycastle.org/licence.html</url>
</license>
</licenses>
</project>
</supplement>
<supplement>
<project>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<name>SLF4J API Module</name>
<organization>
<name>QOS.ch</name>
<url>http://www.qos.ch</url>
</organization>
<licenses>
<license>
<name>MIT style</name>
<url>http://www.slf4j.org/license.html</url>
</license>
</licenses>
</project>
</supplement>
<supplement>
<project>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<name>SLF4J JDK14 Binding</name>
<organization>
<name>QOS.ch</name>
<url>http://www.qos.ch</url>
</organization>
<licenses>
<license>
<name>MIT style</name>
<url>http://www.slf4j.org/license.html</url>
</license>
</licenses>
</project>
</supplement>
<supplement>
<project>
<groupId>net.sf.jpam</groupId>
<artifactId>jpam</artifactId>
<name>Java-PAM bridge</name>
<organization>
<name>JPAM project</name>
<url>http://jpam.sourceforge.net/</url>
</organization>
<licenses>
<license>
<name>Bouncy Castle License</name>
<url>http://www.bouncycastle.org/licence.html</url>
</license>
</licenses>
</project>
</supplement>
</supplementalDataModels>
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/MacTest.java
0,0 → 1,191
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
 
import com.jcraft.jsch.JSch;
import org.apache.sshd.common.Cipher;
import org.apache.sshd.common.Mac;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Random;
import org.apache.sshd.common.cipher.AES128CBC;
import org.apache.sshd.common.cipher.AES192CBC;
import org.apache.sshd.common.cipher.AES256CBC;
import org.apache.sshd.common.cipher.BlowfishCBC;
import org.apache.sshd.common.cipher.TripleDESCBC;
import org.apache.sshd.common.mac.HMACMD5;
import org.apache.sshd.common.mac.HMACMD596;
import org.apache.sshd.common.mac.HMACSHA1;
import org.apache.sshd.common.mac.HMACSHA196;
import org.apache.sshd.common.mac.HMACSHA256;
import org.apache.sshd.common.mac.HMACSHA512;
import org.apache.sshd.common.random.BouncyCastleRandom;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
 
/**
* Test Cipher algorithms.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class MacTest extends BaseTest {
 
private SshServer sshd;
private int port;
 
@Test
public void testHMACMD5() throws Exception {
setUp(new HMACMD5.Factory());
runTest();
}
 
@Test
public void testHMACMD596() throws Exception {
setUp(new HMACMD596.Factory());
runTest();
}
 
@Test
public void testHMACSHA1() throws Exception {
setUp(new HMACSHA1.Factory());
runTest();
}
 
@Test
public void testHMACSHA196() throws Exception {
setUp(new HMACSHA196.Factory());
runTest();
}
 
@Test
public void testHMACSHA256() throws Exception {
setUp(new HMACSHA256.Factory());
runTest();
}
 
@Test
@Ignore("Lead to ArrayIndexOutOfBoundsException in JSch")
public void testHMACSHA512() throws Exception {
setUp(new HMACSHA512.Factory());
runTest();
}
 
@Test
public void loadTest() throws Exception {
Random random = new BouncyCastleRandom();
loadTest(new AES128CBC.Factory(), random);
loadTest(new BlowfishCBC.Factory(), random);
loadTest(new TripleDESCBC.Factory(), random);
}
 
protected void loadTest(NamedFactory<Cipher> factory, Random random) throws Exception {
Cipher cipher = factory.create();
byte[] key = new byte[cipher.getBlockSize()];
byte[] iv = new byte[cipher.getIVSize()];
random.fill(key, 0, key.length);
random.fill(iv, 0, iv.length);
cipher.init(Cipher.Mode.Encrypt, key, iv);
 
byte[] input = new byte[cipher.getBlockSize()];
random.fill(input, 0, input.length);
long t0 = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
cipher.update(input, 0, input.length);
}
long t1 = System.currentTimeMillis();
System.err.println(factory.getName() + ": " + (t1 - t0) + " ms");
}
 
 
protected void setUp(NamedFactory<Mac> mac) throws Exception {
port = Utils.getFreePort();
 
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setMacFactories(Arrays.<NamedFactory<Mac>>asList(mac));
sshd.setShellFactory(new EchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.start();
}
 
@After
public void tearDown() throws Exception {
if (sshd != null) {
sshd.stop(true);
}
}
 
protected void runTest() throws Exception {
JSchLogger.init();
JSch sch = new JSch();
JSch.setConfig("cipher.s2c", "aes128-cbc,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc,none");
JSch.setConfig("cipher.c2s", "aes128-cbc,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc,none");
JSch.setConfig("mac.s2c", "hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96,hmac-sha2-512");
JSch.setConfig("mac.c2s", "hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96,hmac-sha2-512");
JSch.setConfig("hmac-sha2-512", "com.jcraft.jsch.jce.HMACSHA512");
com.jcraft.jsch.Session s = sch.getSession("smx", "localhost", port);
try {
s.setUserInfo(new SimpleUserInfo("smx"));
s.connect();
com.jcraft.jsch.Channel c = s.openChannel("shell");
c.connect();
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
for (int i = 0; i < 10; i++) {
os.write("this is my command\n".getBytes());
os.flush();
byte[] data = new byte[512];
int len = is.read(data);
String str = new String(data, 0, len);
assertEquals("this is my command\n", str);
}
c.disconnect();
} finally {
s.disconnect();
}
}
 
static boolean checkCipher(String cipher){
try{
Class c=Class.forName(cipher);
com.jcraft.jsch.Cipher _c = (com.jcraft.jsch.Cipher)(c.newInstance());
_c.init(com.jcraft.jsch.Cipher.ENCRYPT_MODE,
new byte[_c.getBlockSize()],
new byte[_c.getIVSize()]);
return true;
}
catch(Exception e){
return false;
}
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/CompressionTest.java
0,0 → 1,115
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
 
import com.jcraft.jsch.JSch;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.compression.CompressionDelayedZlib;
import org.apache.sshd.common.compression.CompressionNone;
import org.apache.sshd.common.compression.CompressionZlib;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
 
/**
* Test compression algorithms.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class CompressionTest extends BaseTest {
 
private SshServer sshd;
 
@Test
public void testCompNone() throws Exception {
setUp(new CompressionNone.Factory());
runTest();
}
 
@Test
public void testCompZlib() throws Exception {
setUp(new CompressionZlib.Factory());
runTest();
}
 
@Test
public void testCompDelayedZlib() throws Exception {
setUp(new CompressionDelayedZlib.Factory());
runTest();
}
 
 
protected void setUp(NamedFactory<org.apache.sshd.common.Compression> compression) throws Exception {
sshd = SshServer.setUpDefaultServer();
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setCompressionFactories(Arrays.<NamedFactory<org.apache.sshd.common.Compression>>asList(compression));
sshd.setShellFactory(new EchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.start();
JSch.setConfig("compression.s2c", "zlib@openssh.com,zlib,none");
JSch.setConfig("compression.c2s", "zlib@openssh.com,zlib,none");
JSch.setConfig("zlib", com.jcraft.jsch.jcraft.Compression.class.getName());
JSch.setConfig("zlib@openssh.com", com.jcraft.jsch.jcraft.Compression.class.getName());
}
 
@After
public void tearDown() throws Exception {
if (sshd != null) {
sshd.stop(true);
}
JSch.setConfig("compression.s2c", "none");
JSch.setConfig("compression.c2s", "none");
}
 
protected void runTest() throws Exception {
JSchLogger.init();
JSch sch = new JSch();
com.jcraft.jsch.Session s = sch.getSession("smx", "localhost", sshd.getPort());
s.setUserInfo(new SimpleUserInfo("smx"));
s.connect();
com.jcraft.jsch.Channel c = s.openChannel("shell");
try {
c.connect();
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
for (int i = 0; i < 10; i++) {
os.write("this is my command\n".getBytes());
os.flush();
byte[] data = new byte[512];
int len = is.read(data);
String str = new String(data, 0, len);
assertEquals("this is my command\n", str);
}
} finally {
c.disconnect();
s.disconnect();
}
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/KeepAliveTest.java
0,0 → 1,209
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.ByteArrayOutputStream;
import java.util.concurrent.CountDownLatch;
 
import org.apache.sshd.client.ClientFactoryManager;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.ServerFactoryManager;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.BogusPublickeyAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class KeepAliveTest extends BaseTest {
 
private SshServer sshd;
private int port;
 
private int heartbeat = 2000;
private int timeout = 4000;
private int wait = 8000;
 
@Before
public void setUp() throws Exception {
port = Utils.getFreePort();
 
sshd = SshServer.setUpDefaultServer();
sshd.getProperties().put(ServerFactoryManager.IDLE_TIMEOUT, Integer.toString(timeout));
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setShellFactory(new TestEchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator());
sshd.start();
}
 
@After
public void tearDown() throws Exception {
if (sshd != null) {
sshd.stop(true);
}
}
 
@Test
public void testClient() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
 
int state = channel.waitFor(ClientChannel.CLOSED, wait);
assertEquals("Wrong channel state", ClientChannel.CLOSED | ClientChannel.EOF, state);
 
channel.close(false);
client.stop();
}
 
@Test
public void testClientNew() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
 
int state = channel.waitFor(ClientChannel.CLOSED, wait);
assertEquals("Wrong channel state", ClientChannel.CLOSED | ClientChannel.EOF, state);
 
channel.close(false);
client.stop();
}
 
@Test
public void testClientWithHeartBeat() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.getProperties().put(ClientFactoryManager.HEARTBEAT_INTERVAL, Integer.toString(heartbeat));
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
 
int state = channel.waitFor(ClientChannel.CLOSED, wait);
assertEquals("Wrong channel state", ClientChannel.TIMEOUT, state);
 
channel.close(false);
client.stop();
}
 
@Test
public void testClientWithHeartBeatNew() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.getProperties().put(ClientFactoryManager.HEARTBEAT_INTERVAL, Integer.toString(heartbeat));
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
 
int state = channel.waitFor(ClientChannel.CLOSED, wait);
assertEquals("Wrong channel state", ClientChannel.TIMEOUT, state);
 
channel.close(false);
client.stop();
}
 
@Test
public void testShellClosedOnClientTimeout() throws Exception {
TestEchoShellFactory.TestEchoShell.latch = new CountDownLatch(1);
 
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open().await();
 
 
TestEchoShellFactory.TestEchoShell.latch.await();
int state = channel.waitFor(ClientChannel.CLOSED, wait);
assertEquals("Wrong channel state", ClientChannel.CLOSED | ClientChannel.EOF | ClientChannel.OPENED, state);
 
channel.close(false);
client.stop();
}
 
@Test
public void testShellClosedOnClientTimeoutNew() throws Exception {
TestEchoShellFactory.TestEchoShell.latch = new CountDownLatch(1);
 
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open().await();
 
 
TestEchoShellFactory.TestEchoShell.latch.await();
int state = channel.waitFor(ClientChannel.CLOSED, wait);
assertEquals("Wrong channel state", ClientChannel.CLOSED | ClientChannel.EOF | ClientChannel.OPENED, state);
 
channel.close(false);
client.stop();
}
 
 
public static class TestEchoShellFactory extends EchoShellFactory {
@Override
public Command create() {
return new TestEchoShell();
}
public static class TestEchoShell extends EchoShell {
 
public static CountDownLatch latch;
 
@Override
public void destroy() {
if (latch != null) {
latch.countDown();
}
super.destroy();
}
}
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/ServerTest.java
0,0 → 1,234
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
 
import org.apache.sshd.client.SessionFactory;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.future.AuthFuture;
import org.apache.sshd.client.session.ClientSessionImpl;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.SessionListener;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.server.sftp.SftpSubsystem;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class ServerTest extends BaseTest {
 
private SshServer sshd;
private SshClient client;
private int port;
 
@Before
public void setUp() throws Exception {
port = Utils.getFreePort();
 
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setShellFactory(new TestEchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.setSessionFactory(new org.apache.sshd.server.session.SessionFactory());
sshd.start();
}
 
@After
public void tearDown() throws Exception {
if (sshd != null) {
sshd.stop(true);
}
if (client != null) {
client.stop();
}
}
 
/**
* Send bad password. The server should disconnect after a few attempts
* @throws Exception
*/
@Test
public void testFailAuthenticationWithWaitFor() throws Exception {
sshd.getProperties().put(SshServer.MAX_AUTH_REQUESTS, "10");
 
client = SshClient.setUpDefaultClient();
client.start();
ClientSession s = client.connect("localhost", port).await().getSession();
int nbTrials = 0;
int res = 0;
while ((res & ClientSession.CLOSED) == 0) {
nbTrials ++;
s.authPassword("smx", "buggy");
res = s.waitFor(ClientSession.CLOSED | ClientSession.WAIT_AUTH, 5000);
if (res == ClientSession.TIMEOUT) {
throw new TimeoutException();
}
}
assertTrue(nbTrials > 10);
}
 
@Test
public void testFailAuthenticationWithFuture() throws Exception {
sshd.getProperties().put(SshServer.MAX_AUTH_REQUESTS, "10");
 
client = SshClient.setUpDefaultClient();
client.start();
ClientSession s = client.connect("localhost", port).await().getSession();
int nbTrials = 0;
AuthFuture authFuture;
do {
nbTrials++;
assertTrue(nbTrials < 100);
authFuture = s.authPassword("smx", "buggy");
assertTrue(authFuture.await(5000));
assertTrue(authFuture.isDone());
assertFalse(authFuture.isSuccess());
}
while (authFuture.isFailure());
assertNotNull(authFuture.getException());
assertTrue(nbTrials > 10);
}
 
@Test
public void testAuthenticationTimeout() throws Exception {
sshd.getProperties().put(SshServer.AUTH_TIMEOUT, "5000");
 
client = SshClient.setUpDefaultClient();
client.start();
ClientSession s = client.connect("test", "localhost", port).await().getSession();
int res = s.waitFor(ClientSession.CLOSED, 10000);
assertEquals("Session should be closed", ClientSession.CLOSED | ClientSession.WAIT_AUTH, res);
}
 
@Test
public void testIdleTimeout() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
TestEchoShellFactory.TestEchoShell.latch = new CountDownLatch(1);
 
sshd.getProperties().put(SshServer.IDLE_TIMEOUT, "2500");
sshd.getSessionFactory().addListener(new SessionListener() {
public void sessionCreated(Session session) {
System.out.println("Session created");
}
public void sessionEvent(Session session, Event event) {
System.out.println("Session event: " + event);
}
public void sessionClosed(Session session) {
System.out.println("Session closed");
latch.countDown();
}
});
 
client = SshClient.setUpDefaultClient();
client.start();
ClientSession s = client.connect("test", "localhost", port).await().getSession();
s.addPasswordIdentity("test");
s.auth().verify();
ChannelShell shell = s.createShellChannel();
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
shell.setOut(out);
shell.setErr(err);
shell.open().await();
int res = s.waitFor(ClientSession.CLOSED, 5000);
assertEquals("Session should be closed", ClientSession.CLOSED | ClientSession.AUTHED, res);
assertTrue(latch.await(1, TimeUnit.SECONDS));
assertTrue(TestEchoShellFactory.TestEchoShell.latch.await(1, TimeUnit.SECONDS));
}
 
@Test
public void testLanguage() throws Exception {
client = SshClient.setUpDefaultClient();
client.setSessionFactory(new SessionFactory() {
@Override
protected AbstractSession createSession(IoSession ioSession) throws Exception {
return new ClientSessionImpl(client, ioSession) {
@Override
protected String[] createProposal(String hostKeyTypes) {
String[] proposal = super.createProposal(hostKeyTypes);
proposal[SshConstants.PROPOSAL_LANG_CTOS] = "en-US";
proposal[SshConstants.PROPOSAL_LANG_STOC] = "en-US";
return proposal;
}
};
}
});
client.start();
ClientSession s = client.connect("test", "localhost", port).await().getSession();
s.close(false);
}
 
public static class TestEchoShellFactory extends EchoShellFactory {
@Override
public Command create() {
return new TestEchoShell();
}
public static class TestEchoShell extends EchoShell {
 
public static CountDownLatch latch = new CountDownLatch(1);
 
@Override
public void destroy() {
if (latch != null) {
latch.countDown();
}
super.destroy();
}
}
}
 
public static void main(String[] args) throws Exception {
SshServer sshd = SshServer.setUpDefaultServer();
sshd.getProperties().put(SshServer.IDLE_TIMEOUT, "10000");
sshd.setPort(8001);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystem.Factory()));
sshd.setShellFactory(new EchoShellFactory());
sshd.setCommandFactory(new ScpCommandFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.start();
Thread.sleep(100000);
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/PortForwardingTest.java
0,0 → 1,434
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.HashSet;
import java.util.Set;
 
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.apache.sshd.client.channel.ChannelDirectTcpip;
import org.apache.sshd.client.future.AuthFuture;
import org.apache.sshd.client.future.ConnectFuture;
import org.apache.sshd.common.SshdSocketAddress;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusForwardingFilter;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.LoggerFactory;
 
import static org.apache.sshd.util.Utils.getFreePort;
import static org.junit.Assert.assertEquals;
 
/**
* Port forwarding tests
*/
public class PortForwardingTest extends BaseTest {
 
private final org.slf4j.Logger log = LoggerFactory.getLogger(getClass());
 
private SshServer sshd;
private int sshPort;
private int echoPort;
private IoAcceptor acceptor;
private SshClient client;
 
@Before
public void setUp() throws Exception {
sshPort = getFreePort();
echoPort = getFreePort();
 
sshd = SshServer.setUpDefaultServer();
sshd.getProperties().put(SshServer.WINDOW_SIZE, "2048");
sshd.getProperties().put(SshServer.MAX_PACKET_SIZE, "256");
sshd.setPort(sshPort);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setShellFactory(new EchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.setTcpipForwardingFilter(new BogusForwardingFilter());
sshd.start();
 
NioSocketAcceptor acceptor = new NioSocketAcceptor();
acceptor.setHandler(new IoHandlerAdapter() {
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
IoBuffer recv = (IoBuffer) message;
IoBuffer sent = IoBuffer.allocate(recv.remaining());
sent.put(recv);
sent.flip();
session.write(sent);
}
});
acceptor.setReuseAddress(true);
acceptor.bind(new InetSocketAddress(echoPort));
this.acceptor = acceptor;
 
}
 
@After
public void tearDown() throws Exception {
if (sshd != null) {
sshd.stop(true);
}
if (acceptor != null) {
acceptor.dispose(true);
}
if (client != null) {
client.stop();
}
}
 
@Test
public void testRemoteForwarding() throws Exception {
Session session = createSession();
 
int forwardedPort = getFreePort();
session.setPortForwardingR(forwardedPort, "localhost", echoPort);
Thread.sleep(100);
 
Socket s = new Socket("localhost", forwardedPort);
s.getOutputStream().write("Hello".getBytes());
s.getOutputStream().flush();
byte[] buf = new byte[1024];
int n = s.getInputStream().read(buf);
String res = new String(buf, 0, n);
assertEquals("Hello", res);
s.close();
 
session.delPortForwardingR(forwardedPort);
session.disconnect();
}
 
@Test
public void testRemoteForwardingNative() throws Exception {
ClientSession session = createNativeSession();
 
int forwardedPort = getFreePort();
SshdSocketAddress remote = new SshdSocketAddress("", forwardedPort);
SshdSocketAddress local = new SshdSocketAddress("localhost", echoPort);
 
session.startRemotePortForwarding(remote, local);
 
Socket s = new Socket(remote.getHostName(), remote.getPort());
s.getOutputStream().write("Hello".getBytes());
s.getOutputStream().flush();
byte[] buf = new byte[1024];
int n = s.getInputStream().read(buf);
String res = new String(buf, 0, n);
assertEquals("Hello", res);
s.close();
 
session.stopRemotePortForwarding(remote);
session.close(false).await();
}
 
@Test
public void testRemoteForwardingNativeBigPayload() throws Exception {
ClientSession session = createNativeSession();
 
int forwardedPort = getFreePort();
SshdSocketAddress remote = new SshdSocketAddress("", forwardedPort);
SshdSocketAddress local = new SshdSocketAddress("localhost", echoPort);
 
session.startRemotePortForwarding(remote, local);
 
byte[] buf = new byte[1024];
 
Socket s = new Socket(remote.getHostName(), remote.getPort());
for (int i = 0; i < 1000; i++) {
s.getOutputStream().write("0123456789".getBytes());
s.getOutputStream().flush();
int n = s.getInputStream().read(buf);
String res = new String(buf, 0, n);
assertEquals("0123456789", res);
}
s.close();
 
session.stopRemotePortForwarding(remote);
session.close(false).await();
}
 
@Test
public void testRemoteForwardingNativeNoExplicitPort() throws Exception {
ClientSession session = createNativeSession();
 
SshdSocketAddress remote = new SshdSocketAddress("0.0.0.0", 0);
SshdSocketAddress local = new SshdSocketAddress("localhost", echoPort);
 
SshdSocketAddress bound = session.startRemotePortForwarding(remote, local);
 
Socket s = new Socket(bound.getHostName(), bound.getPort());
s.getOutputStream().write("Hello".getBytes());
s.getOutputStream().flush();
byte[] buf = new byte[1024];
int n = s.getInputStream().read(buf);
String res = new String(buf, 0, n);
assertEquals("Hello", res);
s.close();
 
session.stopRemotePortForwarding(bound);
session.close(false).await();
}
 
@Test
public void testLocalForwarding() throws Exception {
Session session = createSession();
 
int forwardedPort = getFreePort();
session.setPortForwardingL(forwardedPort, "localhost", echoPort);
 
Socket s = new Socket("localhost", forwardedPort);
s.getOutputStream().write("Hello".getBytes());
s.getOutputStream().flush();
byte[] buf = new byte[1024];
int n = s.getInputStream().read(buf);
String res = new String(buf, 0, n);
assertEquals("Hello", res);
s.close();
 
session.delPortForwardingL(forwardedPort);
session.disconnect();
}
 
@Test
public void testLocalForwardingNative() throws Exception {
ClientSession session = createNativeSession();
 
SshdSocketAddress local = new SshdSocketAddress("", getFreePort());
SshdSocketAddress remote = new SshdSocketAddress("localhost", echoPort);
 
SshdSocketAddress bound = session.startLocalPortForwarding(local, remote);
 
Socket s = new Socket(bound.getHostName(), bound.getPort());
s.getOutputStream().write("Hello".getBytes());
s.getOutputStream().flush();
byte[] buf = new byte[1024];
int n = s.getInputStream().read(buf);
String res = new String(buf, 0, n);
assertEquals("Hello", res);
s.close();
 
session.stopLocalPortForwarding(bound);
session.close(false).await();
}
 
@Test
public void testLocalForwardingNativeBigPayload() throws Exception {
ClientSession session = createNativeSession();
 
SshdSocketAddress local = new SshdSocketAddress("", getFreePort());
SshdSocketAddress remote = new SshdSocketAddress("localhost", echoPort);
 
SshdSocketAddress bound = session.startLocalPortForwarding(local, remote);
 
byte[] buf = new byte[1024];
Socket s = new Socket(bound.getHostName(), bound.getPort());
for (int i = 0; i < 1000; i++) {
s.getOutputStream().write("Hello".getBytes());
s.getOutputStream().flush();
int n = s.getInputStream().read(buf);
String res = new String(buf, 0, n);
assertEquals("Hello", res);
}
s.close();
 
session.stopLocalPortForwarding(bound);
session.close(false).await();
}
 
@Test
public void testForwardingChannel() throws Exception {
ClientSession session = createNativeSession();
 
int forwardedPort = getFreePort();
SshdSocketAddress local = new SshdSocketAddress("", forwardedPort);
SshdSocketAddress remote = new SshdSocketAddress("localhost", echoPort);
 
ChannelDirectTcpip channel = session.createDirectTcpipChannel(local, remote);
channel.open().await();
 
channel.getInvertedIn().write("Hello".getBytes());
channel.getInvertedIn().flush();
byte[] buf = new byte[1024];
int n = channel.getInvertedOut().read(buf);
String res = new String(buf, 0, n);
assertEquals("Hello", res);
channel.close(false);
 
session.close(false).await();
}
 
@Test(timeout = 20000)
public void testRemoteForwardingWithDisconnect() throws Exception {
Session session = createSession();
 
// 1. Create a Port Forward
int forwardedPort = getFreePort();
session.setPortForwardingR(forwardedPort, "localhost", echoPort);
 
// 2. Establish a connection through it
new Socket("localhost", forwardedPort);
 
// 3. Simulate the client going away
rudelyDisconnectJschSession(session);
 
// 4. Make sure the NIOprocessor is not stuck
{
Thread.sleep(1000);
// from here, we need to check all the threads running and find a
// "NioProcessor-"
// that is stuck on a PortForward.dispose
ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
while (root.getParent() != null) {
root = root.getParent();
}
boolean stuck;
do {
stuck = false;
for (Thread t : findThreads(root, "NioProcessor-")) {
stuck = true;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
 
}
} while (stuck);
}
 
session.delPortForwardingR(forwardedPort);
session.disconnect();
}
 
/**
* Close the socket inside this JSCH session. Use reflection to find it and
* just close it.
*
* @param session
* the Session to violate
* @throws Exception
*/
private void rudelyDisconnectJschSession(Session session) throws Exception {
Field fSocket = session.getClass().getDeclaredField("socket");
fSocket.setAccessible(true);
Socket socket = (Socket) fSocket.get(session);
 
Assert.assertTrue("socket is not connected", socket.isConnected());
Assert.assertFalse("socket should not be closed", socket.isClosed());
socket.close();
Assert.assertTrue("socket has not closed", socket.isClosed());
}
 
private Set<Thread> findThreads(ThreadGroup group, String name) {
HashSet<Thread> ret = new HashSet<Thread>();
int numThreads = group.activeCount();
Thread[] threads = new Thread[numThreads * 2];
numThreads = group.enumerate(threads, false);
// Enumerate each thread in `group'
for (int i = 0; i < numThreads; ++i) {
// Get thread
// log.debug("Thread name: " + threads[i].getName());
if (checkThreadForPortForward(threads[i], name)) {
ret.add(threads[i]);
}
}
// didn't find the thread to check the
int numGroups = group.activeGroupCount();
ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
numGroups = group.enumerate(groups, false);
for (int i = 0; i < numGroups; ++i) {
ret.addAll(findThreads(groups[i], name));
}
return ret;
}
 
private boolean checkThreadForPortForward(Thread thread, String name) {
if (thread == null)
return false;
// does it contain the name we're looking for?
if (thread.getName().contains(name)) {
// look at the stack
StackTraceElement[] stack = thread.getStackTrace();
if (stack.length == 0)
return false;
else {
// does it have
// 'org.apache.sshd.server.session.TcpipForwardSupport.close'?
for (int i = 0; i < stack.length; ++i) {
String clazzName = stack[i].getClassName();
String methodName = stack[i].getMethodName();
// log.debug("Class: " + clazzName);
// log.debug("Method: " + methodName);
if (clazzName
.equals("org.apache.sshd.server.session.TcpipForwardSupport")
&& (methodName.equals("close") || methodName
.equals("sessionCreated"))) {
log.warn(thread.getName() + " stuck at " + clazzName
+ "." + methodName + ": "
+ stack[i].getLineNumber());
return true;
}
}
}
}
return false;
}
 
protected Session createSession() throws JSchException {
JSchLogger.init();
JSch sch = new JSch();
Session session = sch.getSession("sshd", "localhost", sshPort);
session.setUserInfo(new SimpleUserInfo("sshd"));
session.connect();
return session;
}
 
protected ClientSession createNativeSession() throws Exception {
client = SshClient.setUpDefaultClient();
client.getProperties().put(SshServer.WINDOW_SIZE, "2048");
client.getProperties().put(SshServer.MAX_PACKET_SIZE, "256");
client.setTcpipForwardingFilter(new BogusForwardingFilter());
client.start();
 
ClientSession session = client.connect("sshd", "localhost", sshPort).await().getSession();
session.addPasswordIdentity("sshd");
session.auth().verify();
return session;
}
 
 
}
 
 
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/AbstractSessionTest.java
0,0 → 1,134
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.IOException;
 
import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.util.BaseTest;
import org.junit.Before;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
 
/**
* Test basic stuff on AbstractSession.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class AbstractSessionTest extends BaseTest {
 
private MySession session;
 
@Before
public void setUp() throws Exception {
session = new MySession();
}
 
@Test
public void testReadIdentSimple() {
Buffer buf = new Buffer("SSH-2.0-software\r\n".getBytes());
String ident = session.doReadIdentification(buf);
assertEquals("SSH-2.0-software", ident);
}
 
@Test
public void testReadIdentWithoutCR() {
Buffer buf = new Buffer("SSH-2.0-software\n".getBytes());
String ident = session.doReadIdentification(buf);
assertEquals("SSH-2.0-software", ident);
}
 
@Test
public void testReadIdentWithHeaders() {
Buffer buf = new Buffer(("a header line\r\nSSH-2.0-software\r\n").getBytes());
String ident = session.doReadIdentification(buf);
assertEquals("SSH-2.0-software", ident);
}
 
@Test
public void testReadIdentWithSplitPackets() {
Buffer buf = new Buffer("header line\r\nSSH".getBytes());
String ident = session.doReadIdentification(buf);
assertNull(ident);
buf.putRawBytes("-2.0-software\r\n".getBytes());
ident = session.doReadIdentification(buf);
assertEquals("SSH-2.0-software", ident);
}
 
@Test(expected = IllegalStateException.class)
public void testReadIdentBadLineEnding() {
Buffer buf = new Buffer(("SSH-2.0-software\ra").getBytes());
String ident = session.doReadIdentification(buf);
}
 
@Test(expected = IllegalStateException.class)
public void testReadIdentLongLine() {
Buffer buf = new Buffer(("SSH-2.0-software" +
"01234567890123456789012345678901234567890123456789" +
"01234567890123456789012345678901234567890123456789" +
"01234567890123456789012345678901234567890123456789" +
"01234567890123456789012345678901234567890123456789" +
"01234567890123456789012345678901234567890123456789" +
"01234567890123456789012345678901234567890123456789").getBytes());
String ident = session.doReadIdentification(buf);
}
 
@Test(expected = IllegalStateException.class)
public void testReadIdentLongHeader() {
StringBuilder sb = new StringBuilder(32768);
for (int i = 0; i < 500; i++) {
sb.append("01234567890123456789012345678901234567890123456789\r\n");
}
sb.append("SSH-2.0-software\r\n");
Buffer buf = new Buffer(sb.toString().getBytes());
String ident = session.doReadIdentification(buf);
}
 
public static class MySession extends AbstractSession {
public MySession() {
super(true, SshServer.setUpDefaultServer(), null);
}
protected void handleMessage(Buffer buffer) throws Exception {
}
protected boolean readIdentification(Buffer buffer) {
return false;
}
public String doReadIdentification(Buffer buffer) {
return super.doReadIdentification(buffer);
}
@Override
protected void sendKexInit() throws IOException {
}
@Override
protected void checkKeys() {
}
@Override
protected void receiveKexInit(Buffer buffer) throws IOException {
}
@Override
public void startService(String name) throws Exception {
}
@Override
public void resetIdleTimeout() {
}
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/PortForwardingLoadTest.java
0,0 → 1,392
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
 
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpVersion;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusForwardingFilter;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.LoggerFactory;
 
import static org.apache.sshd.util.Utils.getFreePort;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
 
/**
* Port forwarding tests
*/
public class PortForwardingLoadTest extends BaseTest {
 
private final org.slf4j.Logger log = LoggerFactory.getLogger(getClass());
 
private SshServer sshd;
private int sshPort;
private int echoPort;
private IoAcceptor acceptor;
 
@Before
public void setUp() throws Exception {
sshPort = getFreePort();
echoPort = getFreePort();
 
sshd = SshServer.setUpDefaultServer();
sshd.setPort(sshPort);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setShellFactory(new EchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.setTcpipForwardingFilter(new BogusForwardingFilter());
sshd.start();
 
NioSocketAcceptor acceptor = new NioSocketAcceptor();
acceptor.setHandler(new IoHandlerAdapter() {
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
IoBuffer recv = (IoBuffer) message;
IoBuffer sent = IoBuffer.allocate(recv.remaining());
sent.put(recv);
sent.flip();
session.write(sent);
}
});
acceptor.setReuseAddress(true);
acceptor.bind(new InetSocketAddress(echoPort));
this.acceptor = acceptor;
 
}
 
@After
public void tearDown() throws Exception {
if (sshd != null) {
sshd.stop(true);
}
if (acceptor != null) {
acceptor.dispose(true);
}
}
 
@Test
public void testLocalForwardingPayload() throws Exception {
final int NUM_ITERATIONS = 100;
final String PAYLOAD_TMP = "This is significantly longer Test Data. This is significantly "+
"longer Test Data. This is significantly longer Test Data. This is significantly "+
"longer Test Data. This is significantly longer Test Data. This is significantly "+
"longer Test Data. This is significantly longer Test Data. This is significantly "+
"longer Test Data. This is significantly longer Test Data. This is significantly "+
"longer Test Data. ";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(PAYLOAD_TMP);
}
final String PAYLOAD = sb.toString();
Session session = createSession();
final ServerSocket ss = new ServerSocket(0);
int forwardedPort = ss.getLocalPort();
int sinkPort = getFreePort();
session.setPortForwardingL(sinkPort, "localhost", forwardedPort);
final AtomicInteger conCount = new AtomicInteger(0);
 
new Thread() {
public void run() {
try {
for (int i = 0; i < NUM_ITERATIONS; ++i) {
Socket s = ss.accept();
conCount.incrementAndGet();
InputStream is = s.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[8192];
int l;
while (baos.size() < PAYLOAD.length() && (l = is.read(buf)) > 0) {
baos.write(buf, 0, l);
}
if (!PAYLOAD.equals(baos.toString())) {
assertEquals(PAYLOAD, baos.toString());
}
is = new ByteArrayInputStream(baos.toByteArray());
OutputStream os = s.getOutputStream();
while ((l = is.read(buf)) > 0) {
os.write(buf, 0, l);
}
s.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
Thread.sleep(50);
 
for ( int i = 0; i < NUM_ITERATIONS; i++) {
Socket s = null;
try {
LoggerFactory.getLogger(getClass()).info("Iteration {}", i);
s = new Socket("localhost", sinkPort);
s.getOutputStream().write(PAYLOAD.getBytes());
s.getOutputStream().flush();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[8192];
int l;
while (baos.size() < PAYLOAD.length() && (l = s.getInputStream().read(buf)) > 0) {
baos.write(buf, 0, l);
}
assertEquals(PAYLOAD, baos.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (s != null) {
s.close();
}
}
}
session.delPortForwardingL(sinkPort);
}
 
@Test
public void testRemoteForwardingPayload() throws Exception {
final int NUM_ITERATIONS = 100;
final String PAYLOAD = "This is significantly longer Test Data. This is significantly "+
"longer Test Data. This is significantly longer Test Data. This is significantly "+
"longer Test Data. This is significantly longer Test Data. This is significantly "+
"longer Test Data. This is significantly longer Test Data. This is significantly "+
"longer Test Data. This is significantly longer Test Data. This is significantly "+
"longer Test Data. ";
Session session = createSession();
final ServerSocket ss = new ServerSocket(0);
int forwardedPort = ss.getLocalPort();
int sinkPort = getFreePort();
session.setPortForwardingR(sinkPort, "localhost", forwardedPort);
final boolean started[] = new boolean[1];
started[0] = false;
final AtomicInteger conCount = new AtomicInteger(0);
 
new Thread() {
public void run() {
started[0] = true;
try {
for (int i = 0; i < NUM_ITERATIONS; ++i) {
Socket s = ss.accept();
conCount.incrementAndGet();
s.getOutputStream().write(PAYLOAD.getBytes());
s.getOutputStream().flush();
s.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
Thread.sleep(50);
Assert.assertTrue("Server not started", started[0]);
 
final boolean lenOK[] = new boolean[NUM_ITERATIONS];
final boolean dataOK[] = new boolean[NUM_ITERATIONS];
for ( int i = 0; i < NUM_ITERATIONS; i++) {
final int ii = i;
Socket s = null;
try {
s = new Socket("localhost", sinkPort);
byte b1[] = new byte[PAYLOAD.length() / 2];
byte b2[] = new byte[PAYLOAD.length()];
int read1 = s.getInputStream().read(b1);
Thread.sleep(50);
int read2 = s.getInputStream().read(b2);
lenOK[ii] = PAYLOAD.length() == read1 + read2;
dataOK[ii] = PAYLOAD.equals(new String(b1, 0, read1) + new String(b2, 0, read2));
if (!lenOK[ii] || !dataOK[ii] ) {
throw new Exception("Bad data");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (s != null) {
s.close();
}
}
}
int ok = 0;
for (int i = 0; i < NUM_ITERATIONS; i++) {
ok += lenOK[i] ? 1 : 0;
}
Thread.sleep(50);
for (int i = 0; i < NUM_ITERATIONS; i++) {
Assert.assertTrue(lenOK[i]);
Assert.assertTrue(dataOK[i]);
}
session.delPortForwardingR(forwardedPort);
}
 
@Test
public void testForwardingOnLoad() throws Exception {
// final String path = "/history/recent/troubles/";
// final String host = "www.bbc.co.uk";
// final String path = "";
// final String host = "www.bahn.de";
final String path = "";
final String host = "localhost";
final int nbThread = 2;
final int nbDownloads = 2;
final int nbLoops = 2;
 
final int port = getFreePort();
StringBuilder resp = new StringBuilder();
resp.append("<html><body>\n");
for (int i = 0; i < 1000; i++) {
resp.append("0123456789\n");
}
resp.append("</body></html>\n");
final StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1 200 OK").append('\n');
sb.append("Content-Type: text/HTML").append('\n');
sb.append("Content-Length: ").append(resp.length()).append('\n');
sb.append('\n');
sb.append(resp);
NioSocketAcceptor acceptor = new NioSocketAcceptor();
acceptor.setHandler(new IoHandlerAdapter() {
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
session.write(IoBuffer.wrap(sb.toString().getBytes()));
}
});
acceptor.setReuseAddress(true);
acceptor.bind(new InetSocketAddress(port));
 
 
Session session = createSession();
 
final int forwardedPort1 = getFreePort();
final int forwardedPort2 = getFreePort();
System.err.println("URL: http://localhost:" + forwardedPort2);
 
session.setPortForwardingL(forwardedPort1, host, port);
session.setPortForwardingR(forwardedPort2, "localhost", forwardedPort1);
 
 
final CountDownLatch latch = new CountDownLatch(nbThread * nbDownloads * nbLoops);
 
final Thread[] threads = new Thread[nbThread];
final List<Throwable> errors = new CopyOnWriteArrayList<Throwable>();
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread() {
public void run() {
for (int j = 0; j < nbLoops; j++) {
final MultiThreadedHttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
final HttpClient client = new HttpClient(mgr);
client.getHttpConnectionManager().getParams().setDefaultMaxConnectionsPerHost(100);
client.getHttpConnectionManager().getParams().setMaxTotalConnections(1000);
for (int i = 0; i < nbDownloads; i++) {
try {
checkHtmlPage(client, new URL("http://localhost:" + forwardedPort2 + path));
} catch (Throwable e) {
errors.add(e);
} finally {
latch.countDown();
System.err.println("Remaining: " + latch.getCount());
}
}
mgr.shutdown();
}
}
};
}
for (int i = 0; i < threads.length; i++) {
threads[i].start();
}
latch.await();
for (Throwable t : errors) {
t.printStackTrace();
}
assertEquals(0, errors.size());
}
 
protected Session createSession() throws JSchException {
JSchLogger.init();
JSch sch = new JSch();
Session session = sch.getSession("sshd", "localhost", sshPort);
session.setUserInfo(new SimpleUserInfo("sshd"));
session.connect();
return session;
}
 
protected void checkHtmlPage(HttpClient client, URL url) throws IOException {
client.setHostConfiguration(new HostConfiguration());
client.getHostConfiguration().setHost(url.getHost(), url.getPort());
GetMethod get = new GetMethod("");
get.getParams().setVersion(HttpVersion.HTTP_1_1);
client.executeMethod(get);
String str = get.getResponseBodyAsString();
if (str.indexOf("</html>") <= 0) {
System.err.println(str);
}
assertTrue((str.indexOf("</html>") > 0));
get.releaseConnection();
// url.openConnection().setDefaultUseCaches(false);
// Reader reader = new BufferedReader(new InputStreamReader(url.openStream()));
// try {
// StringWriter sw = new StringWriter();
// char[] buf = new char[8192];
// while (true) {
// int len = reader.read(buf);
// if (len < 0) {
// break;
// }
// sw.write(buf, 0, len);
// }
// assertTrue(sw.toString().indexOf("</html>") > 0);
// } finally {
// reader.close();
// }
}
 
 
}
 
 
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeSshFileTest.java
0,0 → 1,50
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.common.file.nativefs;
 
import org.apache.sshd.util.BaseTest;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
 
public class NativeSshFileTest extends BaseTest {
 
@Test
public void testResolve() {
assertEquals("Z:/git/mina-sshd/sshd-core/target/scp/remote/out.txt",
NativeSshFile.getPhysicalName("Z:\\git/", "Z:\\git\\mina-sshd\\sshd-core", "\\mina-sshd\\sshd-core\\target\\scp\\remote\\out.txt", false));
assertEquals("Z:/git/mina-sshd/sshd-core/target/scp/remote/out.txt",
NativeSshFile.getPhysicalName("Z:/", "Z:\\git\\mina-sshd\\sshd-core", "\\git\\mina-sshd\\sshd-core\\target\\scp\\remote\\out.txt", false));
assertEquals("Z:/git/mina-sshd/sshd-core/target/scp/remote/out.txt",
NativeSshFile.getPhysicalName("Z:/", "Z:\\git\\mina-sshd\\sshd-core", "/git/mina-sshd/sshd-core/target/scp/remote/out.txt", false));
 
assertEquals("/bar", NativeSshFile.getPhysicalName("/", "/foo", "/bar", false));
assertEquals("/bar", NativeSshFile.getPhysicalName("/", "/", "/bar", false));
assertEquals("/bar", NativeSshFile.getPhysicalName("/", "/", "bar", false));
assertEquals("/foo/bar", NativeSshFile.getPhysicalName("/", "/foo", "bar", false));
assertEquals("/foo/bar", NativeSshFile.getPhysicalName("/", "/foo/xyz", "../bar", false));
assertEquals("/foo/xyz/bar", NativeSshFile.getPhysicalName("/", "/foo/xyz", "./bar", false));
 
assertEquals("/foo/bar", NativeSshFile.getPhysicalName("/foo", "/", "bar", false));
assertEquals("/foo/bar", NativeSshFile.getPhysicalName("/foo", "/xyz", "../bar", false));
assertEquals("/foo/bar", NativeSshFile.getPhysicalName("/foo", "/xyz", "../../bar", false));
assertEquals("/foo/xyz/bar", NativeSshFile.getPhysicalName("/foo", "/xyz", "./bar", false));
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/common/file/nativefs/NativeFileSystemViewTest.java
0,0 → 1,115
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.common.file.nativefs;
 
import java.io.File;
import java.util.HashMap;
import java.util.Map;
 
import org.apache.sshd.common.file.FileSystemView;
import org.apache.sshd.common.file.SshFile;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
 
public class NativeFileSystemViewTest {
 
@Test
public void testResolveWithVirtualRoots() throws Exception {
 
Map<String, String> roots = new HashMap<String, String>();
roots.put("A:", "/fs/rootA");
roots.put("Z:", "/fs/rootZ");
String current = "Z:/git";
NativeFileSystemView view = new NativeFileSystemView("user", roots, current, '/', false);
 
assertEquals("Z:/git/foo/bar", view.getFile("foo/bar").getAbsolutePath());
assertEquals("Z:/foo/bar", view.getFile("../foo/bar").getAbsolutePath());
assertEquals("A:/temp", view.getFile("A:/./a/../temp").getAbsolutePath());
assertEquals("A:/temp", view.getFile("A:/../../temp").getAbsolutePath());
 
FileSystemView normView = view.getNormalizedView();
 
assertEquals("/Z/git/foo/bar", normView.getFile("foo/bar").getAbsolutePath());
assertEquals("/Z/foo/bar", normView.getFile("../foo/bar").getAbsolutePath());
assertEquals("/A/temp", normView.getFile("/A/./a/../temp").getAbsolutePath());
assertEquals("/Z/temp", normView.getFile("/A/../Z/temp").getAbsolutePath());
}
 
@Test
public void testResolveWithVirtualRootsWithBackslash() throws Exception {
 
Map<String, String> roots = new HashMap<String, String>();
roots.put("A:", "/fs/rootA");
roots.put("Z:", "/fs/rootZ");
String current = "Z:/git";
NativeFileSystemView view = new NativeFileSystemView("user", roots, current, '\\', false);
 
assertEquals("Z:\\git\\foo\\bar", view.getFile("/Z:/git/foo/bar").getAbsolutePath());
assertEquals("Z:\\git\\foo\\bar", view.getFile("foo/bar").getAbsolutePath());
assertEquals("Z:\\git\\foo", view.getFile("foo/bar").getParentFile().getAbsolutePath());
assertEquals("Z:\\git", view.getFile("foo/bar").getParentFile().getParentFile().getAbsolutePath());
assertEquals("Z:\\", view.getFile("foo/bar").getParentFile().getParentFile().getParentFile().getAbsolutePath());
assertFalse(view.getFile("foo/bar").getParentFile().getParentFile().getParentFile().isRemovable());
assertEquals("Z:\\foo\\bar", view.getFile("../foo/bar").getAbsolutePath());
assertEquals("A:\\temp", view.getFile("A:/./a/../temp").getAbsolutePath());
assertEquals("A:\\temp", view.getFile("A:/../../temp").getAbsolutePath());
 
FileSystemView normView = view.getNormalizedView();
 
assertEquals("/Z/git/foo/bar", normView.getFile("foo/bar").getAbsolutePath());
assertEquals("/Z/git/foo", normView.getFile("foo/bar").getParentFile().getAbsolutePath());
assertEquals("/Z/foo/bar", normView.getFile("../foo/bar").getAbsolutePath());
assertEquals("/A/temp", normView.getFile("/A/./a/../temp").getAbsolutePath());
assertEquals("/Z/temp", normView.getFile("/A/../Z/temp").getAbsolutePath());
}
 
@Test
public void testResolveWithPhysicalRoots() throws Exception {
 
Map<String, String> roots = new HashMap<String, String>();
roots.put("V:", "A:/bar");
roots.put("X:", "B:");
String current = "X:/git";
NativeFileSystemView view = new NativeFileSystemView("user", roots, current, '/', false);
 
assertEquals("X:/git/foo/bar", view.getFile("foo/bar").getAbsolutePath());
 
assertEquals("X:/foo/bar", view.getFile("X:/foo/bar").getAbsolutePath());
assertEquals(new File("B:/foo/bar").toString(), ((NativeSshFile) view.getFile("X:/foo/bar")).getNativeFile().toString());
 
assertEquals("X:/foo/bar", view.getFile("../foo/bar").getAbsolutePath());
assertEquals(new File("B:/foo/bar").toString(), ((NativeSshFile) view.getFile("../foo/bar")).getNativeFile().toString());
 
assertEquals("V:/temp", view.getFile("V:/./a/../temp").getAbsolutePath());
 
assertEquals("V:/temp", view.getFile("V:/../../temp").getAbsolutePath());
assertEquals(new File("A:/bar/temp").toString(), ((NativeSshFile) view.getFile("V:/../../temp")).getNativeFile().toString());
 
assertEquals("X:/", view.getFile("..").getAbsolutePath());
 
SshFile cur = view.getFile(".");
assertEquals("X:/git", cur.getAbsolutePath());
cur = view.getFile(cur, "..");
assertEquals("X:/", cur.getAbsolutePath());
 
 
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/common/file/virtualfs/VirtualFileSystemTest.java
0,0 → 1,107
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.common.file.virtualfs;
 
import java.io.File;
import java.io.IOException;
 
import org.apache.sshd.SshServer;
import org.apache.sshd.common.file.FileSystemView;
import org.apache.sshd.common.file.SshFile;
import org.apache.sshd.common.file.nativefs.NativeFileSystemFactory;
import org.apache.sshd.common.file.nativefs.NativeSshFile;
import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.util.BaseTest;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
 
public class VirtualFileSystemTest extends BaseTest {
 
@Test
public void testNativeFileSystem() throws IOException {
String homeDir = System.getProperty("user.dir");
NativeFileSystemFactory vfs = new NativeFileSystemFactory();
 
FileSystemView view = vfs.createFileSystemView(new TestSession());
 
SshFile file = view.getFile("foo");
String physicalName = ((NativeSshFile) file).getNativeFile().getAbsolutePath();
assertEquals(homeDir + File.separator + "foo", physicalName);
 
file = view.getFile(view.getFile("foo"), "../bar");
physicalName = ((NativeSshFile) file).getNativeFile().getAbsolutePath();
assertEquals(homeDir + File.separator + "bar", physicalName);
 
file = view.getFile("../bar");
physicalName = ((NativeSshFile) file).getNativeFile().getAbsolutePath();
assertEquals(new File(homeDir, "../bar").getCanonicalPath(), physicalName);
}
 
@Test
public void testVirtualFileSystem() {
String homeDir = System.getProperty("user.dir");
VirtualFileSystemFactory vfs = new VirtualFileSystemFactory(homeDir);
 
FileSystemView view = vfs.createFileSystemView(new TestSession());
 
SshFile file = view.getFile("foo");
String physicalName = ((NativeSshFile) file).getNativeFile().getAbsolutePath();
assertEquals(homeDir + File.separator + "foo", physicalName);
 
file = view.getFile(view.getFile("foo"), "../bar");
physicalName = ((NativeSshFile) file).getNativeFile().getAbsolutePath();
assertEquals(homeDir + File.separator + "bar", physicalName);
 
file = view.getFile("../bar");
physicalName = ((NativeSshFile) file).getNativeFile().getAbsolutePath();
assertEquals(homeDir + File.separator + "bar", physicalName);
}
 
static class TestSession extends AbstractSession {
TestSession() {
super(true, SshServer.setUpDefaultServer(), null);
this.username = "userName";
}
@Override
protected void handleMessage(Buffer buffer) throws Exception {
}
@Override
protected boolean readIdentification(Buffer buffer) throws IOException {
return false;
}
@Override
protected void sendKexInit() throws IOException {
}
@Override
protected void checkKeys() {
}
@Override
protected void receiveKexInit(Buffer buffer) throws IOException {
}
@Override
public void startService(String name) throws Exception {
}
@Override
public void resetIdleTimeout() {
}
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/common/channel/ChannelPipedInputStreamTest.java
0,0 → 1,62
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.common.channel;
 
import java.util.Arrays;
 
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusChannel;
import org.junit.Test;
 
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
 
public class ChannelPipedInputStreamTest extends BaseTest {
 
@Test
public void testAvailable() throws Exception {
Window window = new Window(new BogusChannel(), null, true, true);
ChannelPipedInputStream stream = new ChannelPipedInputStream(window);
 
byte[] b = "test".getBytes();
stream.receive(b, 0, b.length);
assertEquals(b.length, stream.available());
 
stream.eof();
assertEquals(b.length, stream.available());
 
final byte[] readBytes = new byte[50];
assertEquals(b.length, stream.read(readBytes));
assertStreamEquals(b, readBytes);
assertEquals(-1, stream.available());
}
 
private void assertStreamEquals(byte[] expected, byte[] read) {
if (expected.length > read.length) {
fail("Less bytes than expected: " + Arrays.toString(expected) + " but got: " + Arrays.toString(read));
} else {
assertArrayEquals(expected, Arrays.copyOf(read, expected.length));
for (int i = expected.length; i < read.length; i++) {
assertEquals('\0', read[i]);
}
}
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/common/cipher/BaseCipherTest.java
0,0 → 1,92
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
 
package org.apache.sshd.common.cipher;
 
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
 
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
 
import org.apache.sshd.common.Cipher;
import org.apache.sshd.common.Cipher.Mode;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.util.BaseTest;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.internal.AssumptionViolatedException;
 
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public abstract class BaseCipherTest extends BaseTest {
protected BaseCipherTest() {
super();
}
 
protected void ensureKeySizeSupported(int bsize, String algorithm, String transformation) throws GeneralSecurityException {
try {
javax.crypto.Cipher cipher=SecurityUtils.getCipher(transformation);
byte[] key=new byte[bsize];
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, new SecretKeySpec(key, algorithm));
} catch(GeneralSecurityException e) {
if (e instanceof InvalidKeyException) { // NOTE: assumption violations are NOT test failures...
throw new AssumptionViolatedException(algorithm + "/" + transformation + "[" + bsize + "] N/A");
}
 
throw e;
}
}
 
protected void ensureKeySizeSupported(int ivsize, int bsize, String algorithm, String transformation) throws GeneralSecurityException {
try {
javax.crypto.Cipher cipher=SecurityUtils.getCipher(transformation);
byte[] key=new byte[bsize];
byte[] iv=new byte[ivsize];
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, new SecretKeySpec(key, algorithm), new IvParameterSpec(iv));
} catch(GeneralSecurityException e) {
if (e instanceof InvalidKeyException) {
Assume.assumeTrue(algorithm + "/" + transformation + "[" + bsize + "/" + ivsize + "]", false /* force exception */);
}
 
throw e;
}
}
 
protected void testEncryptDecrypt(NamedFactory<Cipher> factory) throws Exception {
String facName=factory.getName();
Cipher enc=factory.create();
int keySize=enc.getBlockSize(), ivSize=enc.getIVSize();
byte[] key=new byte[keySize], iv=new byte[ivSize];
enc.init(Mode.Encrypt, key, iv);
 
byte[] expected=facName.getBytes();
byte[] workBuf=expected.clone(); // need to clone since the cipher works in-line
enc.update(workBuf, 0, workBuf.length);
 
Cipher dec=factory.create();
dec.init(Mode.Decrypt, key, iv);
byte[] actual=workBuf.clone();
dec.update(actual, 0, actual.length);
 
Assert.assertArrayEquals(facName, expected, actual);
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR128Test.java
0,0 → 1,36
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
 
package org.apache.sshd.common.cipher;
 
import org.junit.Test;
 
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class ARCFOUR128Test extends BaseCipherTest {
public ARCFOUR128Test() {
super();
}
 
@Test
public void testEncryptDecrypt() throws Exception {
testEncryptDecrypt(new ARCFOUR128.Factory());
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES256CBCTest.java
0,0 → 1,38
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
 
package org.apache.sshd.common.cipher;
 
import org.junit.Test;
 
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class AES256CBCTest extends BaseCipherTest {
public AES256CBCTest() {
super();
}
 
@Test
public void testEncryptDecrypt() throws Exception {
// for AES 256 bits we need the JCE unlimited strength policy
ensureKeySizeSupported(16, 32, "AES", "AES/CBC/NoPadding");
testEncryptDecrypt(new AES256CBC.Factory());
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/common/cipher/AES192CTRTest.java
0,0 → 1,38
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
 
package org.apache.sshd.common.cipher;
 
import org.junit.Test;
 
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class AES192CTRTest extends BaseCipherTest {
public AES192CTRTest() {
super();
}
 
@Test
public void testEncryptDecrypt() throws Exception {
// for AES 256 bits we need the JCE unlimited strength policy
ensureKeySizeSupported(16, 24, "AES", "AES/CTR/NoPadding");
testEncryptDecrypt(new AES192CTR.Factory());
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/common/cipher/ARCFOUR256Test.java
0,0 → 1,38
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
 
package org.apache.sshd.common.cipher;
 
import org.junit.Test;
 
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class ARCFOUR256Test extends BaseCipherTest {
public ARCFOUR256Test() {
super();
}
 
@Test
public void testEncryptDecrypt() throws Exception {
// for RC4 256 bits we need the JCE unlimited strength policy
ensureKeySizeSupported(32, "ARCFOUR", "RC4");
testEncryptDecrypt(new ARCFOUR256.Factory());
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/common/future/FutureTest.java
0,0 → 1,49
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.common.future;
 
import org.apache.sshd.util.BaseTest;
import org.junit.Test;
 
import static junit.framework.Assert.assertNotNull;
 
/**
*/
public class FutureTest extends BaseTest {
 
@Test
public void testAwaitUnint() {
 
final DefaultSshFuture future = new DefaultSshFuture(null);
new Thread() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
future.setValue(new Object());
}
}.start();
 
future.awaitUninterruptibly();
assertNotNull(future.getValue());
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/common/util/SttySupportTest.java
0,0 → 1,55
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.common.util;
 
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Map;
 
import org.apache.sshd.common.PtyMode;
import org.apache.sshd.util.BaseTest;
import org.junit.Test;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class SttySupportTest extends BaseTest {
 
@Test
public void parseOutput1() throws Exception {
Reader r = new InputStreamReader(getClass().getResourceAsStream("stty-output-1.txt"));
char[] buf = new char[8192];
int len = r.read(buf);
String stty = new String(buf, 0, len);
Map<PtyMode, Integer> modes = SttySupport.parsePtyModes(stty);
System.err.println(modes);
}
 
@Test
public void parseOutput2() throws Exception {
Reader r = new InputStreamReader(getClass().getResourceAsStream("stty-output-2.txt"));
char[] buf = new char[8192];
int len = r.read(buf);
String stty = new String(buf, 0, len);
Map<PtyMode, Integer> modes = SttySupport.parsePtyModes(stty);
System.err.println(modes);
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/common/util/BufferTest.java
0,0 → 1,39
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.common.util;
 
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
 
import org.apache.sshd.util.BaseTest;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
 
public class BufferTest extends BaseTest {
 
@Test
public void testGetLong() throws Exception {
long v = 1234567890123456789L;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
new DataOutputStream(stream).writeLong(v);
Buffer buffer = new Buffer(stream.toByteArray());
assertEquals(v, buffer.getLong());
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/CipherTest.java
0,0 → 1,174
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
 
import com.jcraft.jsch.JSch;
import org.apache.sshd.common.Cipher;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Random;
import org.apache.sshd.common.cipher.AES128CBC;
import org.apache.sshd.common.cipher.AES192CBC;
import org.apache.sshd.common.cipher.AES256CBC;
import org.apache.sshd.common.cipher.BlowfishCBC;
import org.apache.sshd.common.cipher.TripleDESCBC;
import org.apache.sshd.common.random.BouncyCastleRandom;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
 
/**
* Test Cipher algorithms.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class CipherTest extends BaseTest {
 
private SshServer sshd;
private int port;
 
@Test
public void testAES128CBC() throws Exception {
setUp(new AES128CBC.Factory());
runTest();
}
 
@Test
public void testAES192CBC() throws Exception {
if (SecurityUtils.isBouncyCastleRegistered() && checkCipher(com.jcraft.jsch.jce.AES192CBC.class.getName())) {
setUp(new AES192CBC.Factory());
runTest();
}
}
 
@Test
public void testAES256CBC() throws Exception {
if (SecurityUtils.isBouncyCastleRegistered() && checkCipher(com.jcraft.jsch.jce.AES256CBC.class.getName())) {
setUp(new AES256CBC.Factory());
runTest();
}
}
 
@Test
public void testBlowfishCBC() throws Exception {
setUp(new BlowfishCBC.Factory());
runTest();
}
 
@Test
public void testTripleDESCBC() throws Exception {
setUp(new TripleDESCBC.Factory());
runTest();
}
 
@Test
public void loadTest() throws Exception {
Random random = new BouncyCastleRandom();
loadTest(new AES128CBC.Factory(), random);
loadTest(new BlowfishCBC.Factory(), random);
loadTest(new TripleDESCBC.Factory(), random);
}
 
protected void loadTest(NamedFactory<Cipher> factory, Random random) throws Exception {
Cipher cipher = factory.create();
byte[] key = new byte[cipher.getBlockSize()];
byte[] iv = new byte[cipher.getIVSize()];
random.fill(key, 0, key.length);
random.fill(iv, 0, iv.length);
cipher.init(Cipher.Mode.Encrypt, key, iv);
 
byte[] input = new byte[cipher.getBlockSize()];
random.fill(input, 0, input.length);
long t0 = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
cipher.update(input, 0, input.length);
}
long t1 = System.currentTimeMillis();
System.err.println(factory.getName() + ": " + (t1 - t0) + " ms");
}
 
 
protected void setUp(NamedFactory<org.apache.sshd.common.Cipher> cipher) throws Exception {
port = Utils.getFreePort();
 
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setCipherFactories(Arrays.<NamedFactory<org.apache.sshd.common.Cipher>>asList(cipher));
sshd.setShellFactory(new EchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.start();
}
 
@After
public void tearDown() throws Exception {
if (sshd != null) {
sshd.stop(true);
}
}
 
protected void runTest() throws Exception {
JSchLogger.init();
JSch sch = new JSch();
JSch.setConfig("cipher.s2c", "aes128-cbc,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc,none");
JSch.setConfig("cipher.c2s", "aes128-cbc,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc,none");
com.jcraft.jsch.Session s = sch.getSession("smx", "localhost", port);
s.setUserInfo(new SimpleUserInfo("smx"));
s.connect();
com.jcraft.jsch.Channel c = s.openChannel("shell");
c.connect();
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
for (int i = 0; i < 10; i++) {
os.write("this is my command\n".getBytes());
os.flush();
byte[] data = new byte[512];
int len = is.read(data);
String str = new String(data, 0, len);
assertEquals("this is my command\n", str);
}
c.disconnect();
s.disconnect();
}
 
static boolean checkCipher(String cipher){
try{
Class c=Class.forName(cipher);
com.jcraft.jsch.Cipher _c = (com.jcraft.jsch.Cipher)(c.newInstance());
_c.init(com.jcraft.jsch.Cipher.ENCRYPT_MODE,
new byte[_c.getBlockSize()],
new byte[_c.getIVSize()]);
return true;
}
catch(Exception e){
return false;
}
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/SinglePublicKeyAuthTest.java
0,0 → 1,148
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.security.KeyPair;
import java.security.PublicKey;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
 
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.util.KeyUtils;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.auth.CachingPublicKeyAuthenticator;
import org.apache.sshd.server.command.UnknownCommand;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class SinglePublicKeyAuthTest extends BaseTest {
 
private SshServer sshd;
private int port = 0;
private KeyPair pairRsa = Utils.createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
private KeyPair pairRsaBad = new SimpleGeneratorHostKeyProvider(null, "RSA").loadKey(KeyPairProvider.SSH_RSA);
private PublickeyAuthenticator delegate;
 
@Before
public void setUp() throws Exception {
port = Utils.getFreePort();
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setCommandFactory(new CommandFactory() {
public Command createCommand(String command) {
return new UnknownCommand(command);
}
});
sshd.getProperties().put(SshServer.AUTH_METHODS, "publickey");
sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() {
public boolean authenticate(String username, PublicKey key, ServerSession session) {
return delegate.authenticate(username, key, session);
}
});
sshd.start();
}
 
@After
public void tearDown() throws Exception {
if (sshd != null) {
sshd.stop(true);
}
}
 
@Test
public void testPublicKeyAuthWithCache() throws Exception {
final ConcurrentHashMap<String, AtomicInteger> count = new ConcurrentHashMap<String, AtomicInteger>();
TestCachingPublicKeyAuthenticator auth = new TestCachingPublicKeyAuthenticator(new PublickeyAuthenticator() {
public boolean authenticate(String username, PublicKey key,
ServerSession session) {
count.putIfAbsent(KeyUtils.getFingerPrint(key), new AtomicInteger());
count.get(KeyUtils.getFingerPrint(key)).incrementAndGet();
return key.equals(pairRsa.getPublic());
}
});
delegate = auth;
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPublicKeyIdentity(pairRsaBad);
session.addPublicKeyIdentity(pairRsa);
assertTrue(session.auth().await().isSuccess());
assertEquals(2, count.size());
assertTrue(count.containsKey(KeyUtils.getFingerPrint(pairRsaBad.getPublic())));
assertTrue(count.containsKey(KeyUtils.getFingerPrint(pairRsa.getPublic())));
assertEquals(1, count.get(KeyUtils.getFingerPrint(pairRsaBad.getPublic())).get());
assertEquals(1, count.get(KeyUtils.getFingerPrint(pairRsa.getPublic())).get());
client.close(false).await();
Thread.sleep(100);
assertTrue(auth.getCache().isEmpty());
}
 
@Test
public void testPublicKeyAuthWithoutCache() throws Exception {
final ConcurrentHashMap<String, AtomicInteger> count = new ConcurrentHashMap<String, AtomicInteger>();
delegate = new PublickeyAuthenticator() {
public boolean authenticate(String username, PublicKey key,
ServerSession session) {
count.putIfAbsent(KeyUtils.getFingerPrint(key), new AtomicInteger());
count.get(KeyUtils.getFingerPrint(key)).incrementAndGet();
return key.equals(pairRsa.getPublic());
}
};
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPublicKeyIdentity(pairRsaBad);
session.addPublicKeyIdentity(pairRsa);
assertTrue(session.auth().await().isSuccess());
assertEquals(2, count.size());
assertTrue(count.containsKey(KeyUtils.getFingerPrint(pairRsaBad.getPublic())));
assertTrue(count.containsKey(KeyUtils.getFingerPrint(pairRsa.getPublic())));
assertEquals(1, count.get(KeyUtils.getFingerPrint(pairRsaBad.getPublic())).get());
assertEquals(2, count.get(KeyUtils.getFingerPrint(pairRsa.getPublic())).get());
}
 
public static class TestCachingPublicKeyAuthenticator extends CachingPublicKeyAuthenticator {
public TestCachingPublicKeyAuthenticator(PublickeyAuthenticator authenticator) {
super(authenticator);
}
public Map<ServerSession, Map<PublicKey, Boolean>> getCache() {
return cache;
}
}
 
}
 
 
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/SftpTest.java
0,0 → 1,401
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Vector;
 
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import org.apache.sshd.client.SftpClient;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.server.sftp.SftpSubsystem;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
 
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
 
public class SftpTest extends BaseTest {
 
private SshServer sshd;
private int port;
private com.jcraft.jsch.Session session;
 
@Before
public void setUp() throws Exception {
port = Utils.getFreePort();
 
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystem.Factory()));
sshd.setCommandFactory(new ScpCommandFactory());
sshd.setShellFactory(new EchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.start();
 
JSchLogger.init();
JSch sch = new JSch();
session = sch.getSession("sshd", "localhost", port);
session.setUserInfo(new SimpleUserInfo("sshd"));
session.connect();
}
 
@After
public void tearDown() throws Exception {
session.disconnect();
sshd.stop(true);
}
 
@Test
@Ignore
public void testExternal() throws Exception {
System.out.println("SFTP subsystem available on port " + port);
Thread.sleep(5 * 60000);
}
 
@Test
public void testOpen() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("x", "localhost", port).await().getSession();
session.addPasswordIdentity("x");
session.auth().verify();
 
String file = "target/sftp/client/test.txt";
 
new File(file).getParentFile().mkdirs();
new File(file).createNewFile();
new File(file).setWritable(false, false);
new File(file).setReadable(false, false);
 
SftpClient sftp = session.createSftpClient();
SftpClient.Handle h;
 
try {
sftp.open(file, EnumSet.of(SftpClient.OpenMode.Read));
fail("Should have failed");
} catch (IOException e) {
// ok
}
 
try {
sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write));
fail("Should have failed");
} catch (IOException e) {
// ok
}
 
try {
sftp.open(file, EnumSet.of(SftpClient.OpenMode.Truncate));
fail("Should have failed");
} catch (IOException e) {
// ok
}
 
Assert.assertEquals(0, (sftp.stat(file).perms & (SftpClient.S_IWUSR | SftpClient.S_IRUSR)));
 
new File(file).setWritable(true, false);
 
h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Truncate, SftpClient.OpenMode.Write));
sftp.close(h);
 
h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write));
byte[] d = "0123456789\n".getBytes();
sftp.write(h, 0, d, 0, d.length);
sftp.write(h, d.length, d, 0, d.length);
sftp.close(h);
h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write));
sftp.write(h, d.length * 2, d, 0, d.length);
sftp.close(h);
h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Write));
sftp.write(h, 3, "-".getBytes(), 0, 1);
sftp.close(h);
 
try {
sftp.open(file, EnumSet.of(SftpClient.OpenMode.Read));
fail("Should have failed");
} catch (IOException e) {
// ok
}
 
new File(file).setReadable(true, false);
 
h = sftp.open(file, EnumSet.of(SftpClient.OpenMode.Read));
byte[] buf = new byte[3];
int l = sftp.read(h, 2l, buf, 0, 3);
assertEquals("2-4", new String(buf, 0, l));
sftp.close(h);
}
 
@Test
public void testClient() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("x", "localhost", port).await().getSession();
session.addPasswordIdentity("x");
session.auth().verify();
 
Utils.deleteRecursive(new File("target/sftp"));
new File("target/sftp").mkdirs();
new File("target/sftp/client/test.txt").delete();
new File("target/sftp/client").delete();
 
SftpClient sftp = session.createSftpClient();
 
sftp.mkdir("target/sftp/client");
 
SftpClient.Handle h = sftp.open("target/sftp/client/test.txt", EnumSet.of(SftpClient.OpenMode.Write, SftpClient.OpenMode.Create));
byte[] d = "0123456789\n".getBytes();
sftp.write(h, 0, d, 0, d.length);
sftp.write(h, d.length, d, 0, d.length);
 
SftpClient.Attributes attrs = sftp.stat(h);
Assert.assertNotNull(attrs);
 
sftp.close(h);
 
h = sftp.openDir("target/sftp/client");
SftpClient.DirEntry[] dir = sftp.readDir(h);
assertNotNull(dir);
assertEquals(1, dir.length);
assertNull(sftp.readDir(h));
sftp.close(h);
 
sftp.remove("target/sftp/client/test.txt");
 
OutputStream os = sftp.write("target/sftp/client/test.txt");
os.write(new byte[1024 * 128]);
os.close();
 
InputStream is = sftp.read("target/sftp/client/test.txt");
is.read(new byte[1024 * 128]);
int i = is.read();
is.close();
is.close();
 
SftpClient.Attributes attributes = sftp.stat("target/sftp/client/test.txt");
assertTrue(attributes.isRegularFile());
 
attributes = sftp.stat("target/sftp/client");
assertTrue(attributes.isDirectory());
 
int nb = 0;
for (SftpClient.DirEntry entry : sftp.readDir("target/sftp/client")) {
nb++;
}
assertEquals(1, nb);
 
sftp.remove("target/sftp/client/test.txt");
 
sftp.rmdir("target/sftp/client/");
 
sftp.close();
 
client.stop();
}
 
@Test
public void testSftp() throws Exception {
String d = "0123456789\n";
 
File root = new File("target/sftp");
File target = new File("target/sftp/out.txt");
Utils.deleteRecursive(root);
root.mkdirs();
assertTrue(root.exists());
 
for (int j = 10; j <= 10; j++) {
String data = "";
for (int i = 0; i < j; i++) {
data = data + d;
}
 
target.delete();
assertFalse(target.exists());
sendFile("target/sftp/out.txt", data);
assertFileLength(target, data.length(), 5000);
 
target.delete();
assertFalse(target.exists());
}
root.delete();
}
 
@Test
public void testReadWriteWithOffset() throws Exception {
File root = new File("target/sftp");
String unixPath = "target/sftp/out.txt";
File target = new File(unixPath);
Utils.deleteRecursive(root);
root.mkdirs();
assertTrue(root.exists());
 
ChannelSftp c = (ChannelSftp) session.openChannel("sftp");
c.connect();
c.put(new ByteArrayInputStream("0123456789".getBytes()), unixPath);
 
assertTrue(target.exists());
assertEquals("0123456789", readFile(unixPath));
 
OutputStream os = c.put(unixPath, null, ChannelSftp.APPEND, -5);
os.write("a".getBytes());
os.close();
c.disconnect();
 
assertTrue(target.exists());
assertEquals("01234a6789", readFile(unixPath));
 
target.delete();
assertFalse(target.exists());
root.delete();
}
 
@Test
public void testReadDir() throws Exception {
ChannelSftp c = (ChannelSftp) session.openChannel("sftp");
c.connect();
 
URI url = getClass().getClassLoader().getResource(SshClient.class.getName().replace('.', '/') + ".class").toURI();
URI base = new File(System.getProperty("user.dir")).getAbsoluteFile().toURI();
String path = new File(base.relativize(url).getPath()).getParent() + "/";
path = path.replace('\\', '/');
Vector res = c.ls(path);
for (Object f : res) {
System.out.println(f.toString());
}
}
 
@Test
public void testRealPath() throws Exception {
ChannelSftp c = (ChannelSftp) session.openChannel("sftp");
c.connect();
 
URI url = getClass().getClassLoader().getResource(SshClient.class.getName().replace('.', '/') + ".class").toURI();
URI base = new File(System.getProperty("user.dir")).getAbsoluteFile().toURI();
String path = new File(base.relativize(url).getPath()).getParent() + "/";
path = path.replace('\\', '/');
String real = c.realpath(path + "/foobar");
System.out.println(real);
}
 
@Test
public void testCreateSymbolicLink() throws Exception {
// Do not execute on windows as the file system does not support symlinks
if (System.getProperty("os.name").toLowerCase().contains("win")) {
return;
}
 
File root = new File("target/sftp");
String unixPath = "target/sftp/out.txt";
String linkUnixPath = "target/sftp/link.txt";
File target = new File(unixPath);
File link = new File(linkUnixPath);
Utils.deleteRecursive(root);
root.mkdirs();
assertTrue(root.exists());
 
ChannelSftp c = (ChannelSftp) session.openChannel("sftp");
c.connect();
c.put(new ByteArrayInputStream("0123456789".getBytes()), unixPath);
 
assertTrue(target.exists());
assertEquals("0123456789", readFile(unixPath));
 
c.symlink(unixPath, linkUnixPath);
 
assertTrue(link.exists());
assertEquals("0123456789", readFile(linkUnixPath));
 
String str1 = c.readlink(linkUnixPath);
String str2 = c.realpath(unixPath);
assertEquals(str1, str2);
}
 
protected void assertFileLength(File file, long length, long timeout) throws Exception {
boolean ok = false;
while (timeout > 0) {
if (file.exists() && file.length() == length) {
if (!ok) {
ok = true;
} else {
return;
}
} else {
ok = false;
}
Thread.sleep(100);
timeout -= 100;
}
assertTrue(file.exists());
assertEquals(length, file.length());
}
 
protected String readFile(String path) throws Exception {
ChannelSftp c = (ChannelSftp) session.openChannel("sftp");
c.connect();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
InputStream is = c.get(path);
try {
byte[] buffer = new byte[256];
int count;
while (-1 != (count = is.read(buffer))) {
bos.write(buffer, 0, count);
}
} finally {
is.close();
}
 
c.disconnect();
return new String(bos.toByteArray());
}
 
protected void sendFile(String path, String data) throws Exception {
ChannelSftp c = (ChannelSftp) session.openChannel("sftp");
c.connect();
c.put(new ByteArrayInputStream(data.getBytes()), path);
c.disconnect();
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/ClientTest.java
0,0 → 1,779
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.SocketAddress;
import java.security.KeyPair;
import java.security.PublicKey;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
 
import org.apache.sshd.client.ClientFactoryManager;
import org.apache.sshd.client.ServerKeyVerifier;
import org.apache.sshd.client.UserAuth;
import org.apache.sshd.client.UserInteraction;
import org.apache.sshd.client.auth.UserAuthKeyboardInteractive;
import org.apache.sshd.client.auth.UserAuthPassword;
import org.apache.sshd.client.auth.UserAuthPublicKey;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.future.AuthFuture;
import org.apache.sshd.client.future.OpenFuture;
import org.apache.sshd.common.Channel;
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.RuntimeSshException;
import org.apache.sshd.common.Service;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.SshException;
import org.apache.sshd.common.forward.TcpipServerChannel;
import org.apache.sshd.common.future.CloseFuture;
import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.IoReadFuture;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.io.IoWriteFuture;
import org.apache.sshd.common.io.mina.MinaSession;
import org.apache.sshd.common.io.nio2.Nio2Session;
import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.common.util.BufferUtils;
import org.apache.sshd.common.util.NoCloseOutputStream;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.channel.ChannelSession;
import org.apache.sshd.server.command.UnknownCommand;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerConnectionService;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.session.ServerUserAuthService;
import org.apache.sshd.util.AsyncEchoShellFactory;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.BogusPublickeyAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.TeeOutputStream;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class ClientTest extends BaseTest {
 
private SshServer sshd;
private SshClient client;
private int port;
private CountDownLatch authLatch;
private CountDownLatch channelLatch;
 
@Before
public void setUp() throws Exception {
port = Utils.getFreePort();
authLatch = new CountDownLatch(0);
channelLatch = new CountDownLatch(0);
 
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setShellFactory(new TestEchoShellFactory());
sshd.setCommandFactory(new CommandFactory() {
public Command createCommand(String command) {
return new UnknownCommand(command);
}
});
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator());
sshd.setServiceFactories(Arrays.asList(
new ServerUserAuthService.Factory() {
@Override
public Service create(Session session) throws IOException {
return new ServerUserAuthService(session) {
@Override
public void process(byte cmd, Buffer buffer) throws Exception {
authLatch.await();
super.process(cmd, buffer);
}
};
}
},
new ServerConnectionService.Factory()
));
sshd.setChannelFactories(Arrays.<NamedFactory<Channel>>asList(
new ChannelSession.Factory() {
@Override
public Channel create() {
return new ChannelSession() {
@Override
public OpenFuture open(int recipient, int rwsize, int rmpsize, Buffer buffer) {
try {
channelLatch.await();
} catch (InterruptedException e) {
throw new RuntimeSshException(e);
}
return super.open(recipient, rwsize, rmpsize, buffer);
}
 
@Override
public String toString() {
return "ChannelSession" + "[id=" + id + ", recipient=" + recipient + "]";
}
};
}
},
new TcpipServerChannel.DirectTcpipFactory()));
sshd.start();
 
client = SshClient.setUpDefaultClient();
}
 
@After
public void tearDown() throws Exception {
if (sshd != null) {
sshd.stop(true);
}
if (client != null) {
client.stop();
}
}
 
@Test
public void testAsyncClient() throws Exception {
sshd.getProperties().put(SshServer.WINDOW_SIZE, "1024");
sshd.setShellFactory(new AsyncEchoShellFactory());
 
client.getProperties().put(SshClient.WINDOW_SIZE, "1024");
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
final ChannelShell channel = session.createShellChannel();
channel.setStreaming(ClientChannel.Streaming.Async);
channel.open().verify();
 
 
final byte[] message = "0123456789\n".getBytes();
final int nbMessages = 1000;
 
final ByteArrayOutputStream baosOut = new ByteArrayOutputStream();
final ByteArrayOutputStream baosErr = new ByteArrayOutputStream();
final AtomicInteger writes = new AtomicInteger(nbMessages);
 
channel.getAsyncIn().write(new Buffer(message))
.addListener(new SshFutureListener<IoWriteFuture>() {
public void operationComplete(IoWriteFuture future) {
try {
if (future.isWritten()) {
if (writes.decrementAndGet() > 0) {
channel.getAsyncIn().write(new Buffer(message)).addListener(this);
} else {
channel.getAsyncIn().close(false);
}
} else {
throw new SshException("Error writing", future.getException());
}
} catch (IOException e) {
if (!channel.isClosing()) {
e.printStackTrace();
channel.close(true);
}
}
}
});
channel.getAsyncOut().read(new Buffer())
.addListener(new SshFutureListener<IoReadFuture>() {
public void operationComplete(IoReadFuture future) {
try {
future.verify();
Buffer buffer = future.getBuffer();
baosOut.write(buffer.array(), buffer.rpos(), buffer.available());
buffer.rpos(buffer.rpos() + buffer.available());
buffer.compact();
channel.getAsyncOut().read(buffer).addListener(this);
} catch (IOException e) {
if (!channel.isClosing()) {
e.printStackTrace();
channel.close(true);
}
}
}
});
channel.getAsyncErr().read(new Buffer())
.addListener(new SshFutureListener<IoReadFuture>() {
public void operationComplete(IoReadFuture future) {
try {
future.verify();
Buffer buffer = future.getBuffer();
baosErr.write(buffer.array(), buffer.rpos(), buffer.available());
buffer.rpos(buffer.rpos() + buffer.available());
buffer.compact();
channel.getAsyncErr().read(buffer).addListener(this);
} catch (IOException e) {
if (!channel.isClosing()) {
e.printStackTrace();
channel.close(true);
}
}
}
});
 
channel.waitFor(ClientChannel.CLOSED, 0);
 
assertEquals(nbMessages * message.length, baosOut.size());
 
client.close(true);
}
 
@Test
public void testCommandDeadlock() throws Exception {
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ChannelExec channel = session.createExecChannel("test");
channel.setOut(new NoCloseOutputStream(System.out));
channel.setErr(new NoCloseOutputStream(System.err));
channel.open().await();
Thread.sleep(100);
try {
for (int i = 0; i < 100; i++) {
channel.getInvertedIn().write("a".getBytes());
channel.getInvertedIn().flush();
}
} catch (SshException e) {
// That's ok, the channel is being closed by the other side
}
assertEquals(ChannelExec.CLOSED, channel.waitFor(ChannelExec.CLOSED, 0) & ChannelExec.CLOSED);
session.close(false).await();
client.stop();
}
 
@Test
public void testClient() throws Exception {
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
 
ByteArrayOutputStream sent = new ByteArrayOutputStream();
PipedOutputStream pipedIn = new PipedOutputStream();
channel.setIn(new PipedInputStream(pipedIn));
OutputStream teeOut = new TeeOutputStream(sent, pipedIn);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open();
 
teeOut.write("this is my command\n".getBytes());
teeOut.flush();
 
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append("0123456789");
}
sb.append("\n");
teeOut.write(sb.toString().getBytes());
 
teeOut.write("exit\n".getBytes());
teeOut.flush();
 
channel.waitFor(ClientChannel.CLOSED, 0);
 
channel.close(false);
client.stop();
 
assertArrayEquals(sent.toByteArray(), out.toByteArray());
}
 
@Test
public void testClientInverted() throws Exception {
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
 
ByteArrayOutputStream sent = new ByteArrayOutputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open().await();
 
OutputStream pipedIn = new TeeOutputStream(sent, channel.getInvertedIn());
 
pipedIn.write("this is my command\n".getBytes());
pipedIn.flush();
 
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append("0123456789");
}
sb.append("\n");
pipedIn.write(sb.toString().getBytes());
 
pipedIn.write("exit\n".getBytes());
pipedIn.flush();
 
channel.waitFor(ClientChannel.CLOSED, 0);
 
channel.close(false);
client.stop();
 
assertArrayEquals(sent.toByteArray(), out.toByteArray());
}
 
@Test
public void testClientWithCustomChannel() throws Exception {
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
 
ChannelShell channel = new ChannelShell();
session.getService(ConnectionService.class).registerChannel(channel);
 
ByteArrayOutputStream sent = new ByteArrayOutputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open().verify();
 
channel.close(false).await();
client.stop();
}
 
@Test
public void testClientClosingStream() throws Exception {
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
 
 
ByteArrayOutputStream sent = new ByteArrayOutputStream();
PipedOutputStream pipedIn = new PipedOutputStream();
OutputStream teeOut = new TeeOutputStream(sent, pipedIn);
channel.setIn(new PipedInputStream(pipedIn));
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open();
 
teeOut.write("this is my command\n".getBytes());
teeOut.flush();
 
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append("0123456789");
}
sb.append("\n");
teeOut.write(sb.toString().getBytes());
 
teeOut.close();
 
channel.waitFor(ClientChannel.CLOSED, 0);
 
channel.close(false);
client.stop();
 
assertArrayEquals(sent.toByteArray(), out.toByteArray());
}
 
@Test
public void testClientWithLengthyDialog() throws Exception {
// Reduce window size and packet size
// client.getProperties().put(SshClient.WINDOW_SIZE, Integer.toString(0x20000));
// client.getProperties().put(SshClient.MAX_PACKET_SIZE, Integer.toString(0x1000));
// sshd.getProperties().put(SshServer.WINDOW_SIZE, Integer.toString(0x20000));
// sshd.getProperties().put(SshServer.MAX_PACKET_SIZE, Integer.toString(0x1000));
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
ByteArrayOutputStream sent = new ByteArrayOutputStream();
PipedOutputStream pipedIn = new PipedOutputStream();
OutputStream teeOut = new TeeOutputStream(sent, pipedIn);
channel.setIn(new PipedInputStream(pipedIn));
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open().await();
 
long t0 = System.currentTimeMillis();
 
int bytes = 0;
for (int i = 0; i < 10000; i++) {
byte[] data = "01234567890123456789012345678901234567890123456789\n".getBytes();
teeOut.write(data);
teeOut.flush();
bytes += data.length;
if ((bytes & 0xFFF00000) != ((bytes - data.length) & 0xFFF00000)) {
System.out.println("Bytes written: " + bytes);
}
}
teeOut.write("exit\n".getBytes());
teeOut.flush();
 
long t1 = System.currentTimeMillis();
 
System.out.println("Sent " + (bytes / 1024) + " Kb in " + (t1 - t0) + " ms");
 
System.out.println("Waiting for channel to be closed");
 
channel.waitFor(ClientChannel.CLOSED, 0);
 
channel.close(false);
client.stop();
 
assertTrue(BufferUtils.equals(sent.toByteArray(), out.toByteArray()));
//assertArrayEquals(sent.toByteArray(), out.toByteArray());
}
 
@Test(expected = SshException.class)
public void testOpenChannelOnClosedSession() throws Exception {
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
session.close(false);
 
PipedOutputStream pipedIn = new PipedOutputStream();
channel.setIn(new PipedInputStream(pipedIn));
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open();
}
 
@Test
public void testCloseBeforeAuthSucceed() throws Exception {
authLatch = new CountDownLatch(1);
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
AuthFuture authFuture = session.auth();
CloseFuture closeFuture = session.close(false);
authLatch.countDown();
authFuture.await();
closeFuture.await();
assertNotNull(authFuture.getException());
assertTrue(closeFuture.isClosed());
}
 
@Test
public void testCloseCleanBeforeChannelOpened() throws Exception {
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
channel.setIn(new ByteArrayInputStream(new byte[0]));
channel.setOut(new ByteArrayOutputStream());
channel.setErr(new ByteArrayOutputStream());
OpenFuture openFuture = channel.open();
CloseFuture closeFuture = session.close(false);
openFuture.await();
closeFuture.await();
assertTrue(openFuture.isOpened());
assertTrue(closeFuture.isClosed());
}
 
@Test
public void testCloseImmediateBeforeChannelOpened() throws Exception {
channelLatch = new CountDownLatch(1);
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
channel.setIn(new ByteArrayInputStream(new byte[0]));
channel.setOut(new ByteArrayOutputStream());
channel.setErr(new ByteArrayOutputStream());
OpenFuture openFuture = channel.open();
CloseFuture closeFuture = session.close(true);
channelLatch.countDown();
openFuture.await();
closeFuture.await();
assertNotNull(openFuture.getException());
assertTrue(closeFuture.isClosed());
}
 
@Test
public void testPublicKeyAuth() throws Exception {
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
 
KeyPair pair = Utils.createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
session.addPublicKeyIdentity(pair);
session.auth().verify();
}
 
@Test
public void testPublicKeyAuthNew() throws Exception {
client.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList(new UserAuthPublicKey.Factory()));
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPublicKeyIdentity(Utils.createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA));
session.auth().verify();
}
 
@Test
public void testPublicKeyAuthNewWithFailureOnFirstIdentity() throws Exception {
final KeyPair pair = Utils.createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() {
public boolean authenticate(String username, PublicKey key, ServerSession session) {
return key.equals(pair.getPublic());
}
});
client.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList(new UserAuthPublicKey.Factory()));
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPublicKeyIdentity(new SimpleGeneratorHostKeyProvider(null, "RSA").loadKey(KeyPairProvider.SSH_RSA));
session.addPublicKeyIdentity(pair);
session.auth().verify();
}
 
@Test
public void testPasswordAuthNew() throws Exception {
client.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList(new UserAuthPassword.Factory()));
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
}
 
@Test
public void testPasswordAuthNewWithFailureOnFirstIdentity() throws Exception {
client.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList(new UserAuthPassword.Factory()));
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("bad");
session.addPasswordIdentity("smx");
session.auth().verify();
}
 
@Test
public void testKeyboardInteractiveAuthNew() throws Exception {
client.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList(new UserAuthKeyboardInteractive.Factory()));
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
}
 
@Test
public void testKeyboardInteractiveAuthNewWithFailureOnFirstIdentity() throws Exception {
client.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList(new UserAuthKeyboardInteractive.Factory()));
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("bad");
session.addPasswordIdentity("smx");
session.auth().verify();
}
 
@Test
public void testKeyboardInteractiveWithFailures() throws Exception {
final AtomicInteger count = new AtomicInteger();
SshClient client = SshClient.setUpDefaultClient();
client.getProperties().put(ClientFactoryManager.PASSWORD_PROMPTS, "3");
client.setUserAuthFactories(Arrays.<NamedFactory<UserAuth>>asList(new UserAuthKeyboardInteractive.Factory()));
client.setUserInteraction(new UserInteraction() {
public void welcome(String banner) {
}
public String[] interactive(String destination, String name, String instruction, String[] prompt, boolean[] echo) {
count.incrementAndGet();
return new String[] { "bad" };
}
});
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
AuthFuture future = session.auth();
future.await();
assertTrue(future.isFailure());
assertEquals(3, count.get());
}
 
 
@Test
public void testKeyboardInteractiveInSessionUserInteractive() throws Exception {
final AtomicInteger count = new AtomicInteger();
client.getProperties().put(ClientFactoryManager.PASSWORD_PROMPTS, "3");
client.setUserAuthFactories(Arrays
.<NamedFactory<UserAuth>> asList(new UserAuthKeyboardInteractive.Factory()));
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.setUserInteraction(new UserInteraction() {
public void welcome(String banner) {
}
 
public String[] interactive(String destination, String name, String instruction,
String[] prompt, boolean[] echo) {
count.incrementAndGet();
return new String[] { "smx" };
}
});
AuthFuture future = session.auth();
future.await();
assertTrue(future.isSuccess());
assertFalse(future.isFailure());
assertEquals(1, count.get());
}
 
@Test
public void testKeyboardInteractiveInSessionUserInteractiveFailure() throws Exception {
final AtomicInteger count = new AtomicInteger();
client.getProperties().put(ClientFactoryManager.PASSWORD_PROMPTS, "3");
client.setUserAuthFactories(Arrays
.<NamedFactory<UserAuth>> asList(new UserAuthKeyboardInteractive.Factory()));
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.setUserInteraction(new UserInteraction() {
public void welcome(String banner) {
}
 
public String[] interactive(String destination, String name, String instruction,
String[] prompt, boolean[] echo) {
count.incrementAndGet();
return new String[] { "bad" };
}
});
AuthFuture future = session.auth();
future.await();
assertTrue(future.isFailure());
assertEquals(3, count.get());
}
 
@Test
public void testClientDisconnect() throws Exception {
TestEchoShellFactory.TestEchoShell.latch = new CountDownLatch(1);
try
{
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
PipedOutputStream pipedIn = new PipedOutputStream();
channel.setIn(new PipedInputStream(pipedIn));
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open().await();
 
// ((AbstractSession) session).disconnect(SshConstants.SSH2_DISCONNECT_BY_APPLICATION, "Cancel");
AbstractSession cs = (AbstractSession) session;
Buffer buffer = cs.createBuffer(SshConstants.SSH_MSG_DISCONNECT);
buffer.putInt(SshConstants.SSH2_DISCONNECT_BY_APPLICATION);
buffer.putString("Cancel");
buffer.putString("");
IoWriteFuture f = cs.writePacket(buffer);
f.await();
suspend(cs.getIoSession());
 
TestEchoShellFactory.TestEchoShell.latch.await();
} finally {
TestEchoShellFactory.TestEchoShell.latch = null;
}
}
 
@Test
public void testWaitAuth() throws Exception {
final AtomicBoolean ok = new AtomicBoolean();
client.setServerKeyVerifier(
new ServerKeyVerifier() {
public boolean verifyServerKey(
ClientSession sshClientSession,
SocketAddress remoteAddress,
PublicKey serverKey
) {
System.out.println(serverKey);
ok.set(true);
return true;
}
}
);
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.waitFor(ClientSession.WAIT_AUTH, 10000);
assertTrue(ok.get());
client.stop();
}
 
private void suspend(IoSession ioSession) {
if (ioSession instanceof MinaSession) {
((MinaSession) ioSession).suspend();
} else {
((Nio2Session) ioSession).suspend();
}
}
 
public static class TestEchoShellFactory extends EchoShellFactory {
@Override
public Command create() {
return new TestEchoShell();
}
public static class TestEchoShell extends EchoShell {
 
public static CountDownLatch latch = new CountDownLatch(1);
 
@Override
public void destroy() {
if (latch != null) {
latch.countDown();
}
super.destroy();
}
}
}
 
public static void main(String[] args) throws Exception {
SshClient.main(args);
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/EcdsaTest.java
0,0 → 1,167
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.ECFieldFp;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.EllipticCurve;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
 
import org.apache.sshd.client.SessionFactory;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.future.AuthFuture;
import org.apache.sshd.client.session.ClientSessionImpl;
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.RuntimeSshException;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.SessionListener;
import org.apache.sshd.common.Signature;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.SshException;
import org.apache.sshd.common.cipher.ECCurves;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.keyprovider.AbstractKeyPairProvider;
import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.common.signature.SignatureDSA;
import org.apache.sshd.common.signature.SignatureECDSA;
import org.apache.sshd.common.signature.SignatureRSA;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.sftp.SftpSubsystem;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.bouncycastle.jce.ECPointUtil;
import org.bouncycastle.util.encoders.Hex;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class EcdsaTest extends BaseTest {
 
private SshServer sshd;
private SshClient client;
private int port;
 
@Before
public void setUp() throws Exception {
port = Utils.getFreePort();
 
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
// sshd.setShellFactory(new TestEchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.setSessionFactory(new org.apache.sshd.server.session.SessionFactory());
}
 
@After
public void tearDown() throws Exception {
if (sshd != null) {
sshd.stop(true);
}
if (client != null) {
client.stop();
}
}
 
@Test
public void testECDSA_SHA2_NISTP256() throws Exception {
if (SecurityUtils.isBouncyCastleRegistered()) {
sshd.setKeyPairProvider(new AbstractKeyPairProvider() {
@Override
public Iterable<KeyPair> loadKeys() {
try {
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("secp256r1");
KeyPairGenerator generator = SecurityUtils.getKeyPairGenerator("ECDSA");
generator.initialize(ecGenSpec, new SecureRandom());
KeyPair kp = generator.generateKeyPair();
return Collections.singleton(kp);
} catch (Exception e) {
throw new RuntimeSshException(e);
}
}
});
sshd.start();
 
client = SshClient.setUpDefaultClient();
client.setSignatureFactories(Arrays.<NamedFactory<Signature>>asList(
new SignatureECDSA.NISTP256Factory(),
new SignatureECDSA.NISTP384Factory(),
new SignatureECDSA.NISTP521Factory()));
client.start();
ClientSession s = client.connect("smx", "localhost", port).await().getSession();
s.addPasswordIdentity("smx");
s.auth().verify();
}
}
 
@Test
public void testEcdsaPublicKeyAuth() throws Exception {
if (SecurityUtils.isBouncyCastleRegistered()) {
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() {
public boolean authenticate(String username, PublicKey key, ServerSession session) {
return true;
}
});
sshd.start();
 
client = SshClient.setUpDefaultClient();
client.start();
ClientSession s = client.connect("smx", "localhost", port).await().getSession();
 
ECGenParameterSpec ecGenSpec = new ECGenParameterSpec("secp256r1");
KeyPairGenerator generator = SecurityUtils.getKeyPairGenerator("ECDSA");
generator.initialize(ecGenSpec, new SecureRandom());
KeyPair kp = generator.generateKeyPair();
s.addPublicKeyIdentity(kp);
s.auth().verify();
}
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/LoadTest.java
0,0 → 1,147
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
 
import org.apache.sshd.client.kex.DHG1;
import org.apache.sshd.common.Cipher;
import org.apache.sshd.common.KeyExchange;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.cipher.BlowfishCBC;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import static org.junit.Assert.assertArrayEquals;
 
public class LoadTest extends BaseTest {
 
private SshServer sshd;
private int port;
 
@Before
public void setUp() throws Exception {
port = Utils.getFreePort();
 
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setShellFactory(new EchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.start();
}
 
@After
public void tearDown() throws Exception {
sshd.stop(true);
}
 
@Test
public void testLoad() throws Exception {
test("this is my command", 4, 4);
}
 
@Test
public void testHighLoad() throws Exception {
final StringBuilder response = new StringBuilder(1000000);
for (int i = 0; i < 100000; i++) {
response.append("0123456789");
}
test(response.toString(), 1, 100);
}
 
@Test
public void testBigResponse() throws Exception {
final StringBuilder response = new StringBuilder(1000000);
for (int i = 0; i < 100000; i++) {
response.append("0123456789");
}
test(response.toString(), 1, 1);
}
 
protected void test(final String msg, final int nbThreads, final int nbSessionsPerThread) throws Exception {
final List<Throwable> errors = new ArrayList<Throwable>();
final CountDownLatch latch = new CountDownLatch(nbThreads);
for (int i = 0; i < nbThreads; i++) {
Runnable r = new Runnable() {
public void run() {
try {
for (int i = 0; i < nbSessionsPerThread; i++) {
runClient(msg);
}
} catch (Throwable t) {
errors.add(t);
} finally {
latch.countDown();
}
}
};
new Thread(r).start();
}
latch.await();
if (errors.size() > 0) {
throw new Exception("Errors", errors.get(0));
}
}
 
protected void runClient(String msg) throws Exception {
SshClient client = SshClient.setUpDefaultClient();
try {
client.getProperties().put(SshClient.MAX_PACKET_SIZE, Integer.toString(1024 * 16));
client.getProperties().put(SshClient.WINDOW_SIZE, Integer.toString(1024 * 8));
client.setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>>asList(
new DHG1.Factory()));
client.setCipherFactories(Arrays.<NamedFactory<Cipher>>asList(
new BlowfishCBC.Factory()));
client.start();
ClientSession session = client.connect("sshd", "localhost", port).await().getSession();
session.addPasswordIdentity("sshd");
session.auth().verify();
 
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open().await();
OutputStream pipedIn = channel.getInvertedIn();
 
msg += "\nexit\n";
pipedIn.write(msg.getBytes());
pipedIn.flush();
 
channel.waitFor(ClientChannel.CLOSED, 0);
 
channel.close(false);
assertArrayEquals(msg.getBytes(), out.toByteArray());
} finally {
client.stop();
}
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/AuthenticationTest.java
0,0 → 1,144
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.security.KeyPair;
 
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.server.ServerFactoryManager;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.session.SessionFactory;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.BogusPublickeyAuthenticator;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
 
public class AuthenticationTest extends BaseTest {
 
private static final String WELCOME = "Welcome to SSHD";
 
private SshServer sshd;
private int port;
 
@Before
public void setUp() throws Exception {
port = Utils.getFreePort();
 
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator());
sshd.getProperties().put(SshServer.WELCOME_BANNER, WELCOME);
sshd.getProperties().put(SshServer.AUTH_METHODS, "publickey,password publickey,keyboard-interactive");
sshd.setSessionFactory(new SessionFactory() {
@Override
protected AbstractSession doCreateSession(IoSession ioSession) throws Exception {
return new TestSession(server, ioSession);
}
});
sshd.start();
}
 
@After
public void tearDown() throws Exception {
if (sshd != null) {
sshd.stop(true);
}
}
 
@Test
public void testChangeUser() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession s = client.connect("localhost", port).await().getSession();
s.waitFor(ClientSession.CLOSED | ClientSession.WAIT_AUTH, 0);
 
assertFalse(s.authPassword("user1", "the-password").await().isSuccess());
assertFalse(s.authPassword("user2", "the-password").await().isSuccess());
 
assertEquals(ClientSession.CLOSED, s.waitFor(ClientSession.CLOSED, 1000));
client.stop();
}
 
@Test
public void testAuthPasswordOnly() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession s = client.connect("localhost", port).await().getSession();
s.waitFor(ClientSession.CLOSED | ClientSession.WAIT_AUTH, 0);
 
assertFalse(s.authPassword("smx", "smx").await().isSuccess());
 
s.close(true);
client.stop();
}
 
@Test
public void testAuthKeyPassword() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession s = client.connect("localhost", port).await().getSession();
s.waitFor(ClientSession.CLOSED | ClientSession.WAIT_AUTH, 0);
 
KeyPair pair = Utils.createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
assertFalse(s.authPublicKey("smx", pair).await().isSuccess());
 
assertTrue(s.authPassword("smx", "smx").await().isSuccess());
 
s.close(true);
client.stop();
}
 
@Test
public void testAuthKeyInteractive() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession s = client.connect("localhost", port).await().getSession();
s.waitFor(ClientSession.CLOSED | ClientSession.WAIT_AUTH, 0);
 
KeyPair pair = Utils.createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
assertFalse(s.authPublicKey("smx", pair).await().isSuccess());
 
assertTrue(s.authInteractive("smx", "smx").await().isSuccess());
 
s.close(true);
client.stop();
}
 
public static class TestSession extends ServerSession {
public TestSession(ServerFactoryManager server, IoSession ioSession) throws Exception {
super(server, ioSession);
}
public void handleMessage(Buffer buffer) throws Exception {
super.handleMessage(buffer);
}
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/RandomTest.java
0,0 → 1,55
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import org.apache.sshd.common.Random;
import org.apache.sshd.common.random.BouncyCastleRandom;
import org.apache.sshd.common.random.JceRandom;
import org.apache.sshd.util.BaseTest;
import org.junit.Test;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class RandomTest extends BaseTest {
 
@Test
public void testJce() {
long t = test(new JceRandom());
System.out.println("JCE: " + t + " micro");
}
 
@Test
public void testBc() {
long t = test(new BouncyCastleRandom());
System.out.println("BC: " + t + " micro");
}
 
protected long test(Random random) {
byte[] bytes = new byte[32];
long l0 = System.nanoTime();
for (int i = 0; i < 1000; i++) {
random.fill(bytes, 8, 16);
}
long l1 = System.nanoTime();
return (l1 - l0) / 1000;
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/WelcomeBannerTest.java
0,0 → 1,80
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.util.concurrent.atomic.AtomicReference;
 
import org.apache.sshd.client.UserInteraction;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.BogusPublickeyAuthenticator;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import static junit.framework.Assert.assertEquals;
 
public class WelcomeBannerTest extends BaseTest {
 
private static final String WELCOME = "Welcome to SSHD";
 
private SshServer sshd;
private int port;
 
@Before
public void setUp() throws Exception {
port = Utils.getFreePort();
 
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.setPublickeyAuthenticator(new BogusPublickeyAuthenticator());
sshd.getProperties().put(SshServer.WELCOME_BANNER, WELCOME);
sshd.start();
}
 
@After
public void tearDown() throws Exception {
if (sshd != null) {
sshd.stop(true);
}
}
 
@Test
public void testBanner() throws Exception {
final AtomicReference<String> welcome = new AtomicReference<String>();
SshClient client = SshClient.setUpDefaultClient();
client.setUserInteraction(new UserInteraction() {
public void welcome(String banner) {
welcome.set(banner);
}
public String[] interactive(String destination, String name, String instruction, String[] prompt, boolean[] echo) {
return null;
}
});
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
assertEquals(WELCOME, welcome.get());
session.close(true);
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/KeyReExchangeTest.java
0,0 → 1,210
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.concurrent.atomic.AtomicInteger;
 
import com.jcraft.jsch.JSch;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.SessionListener;
import org.apache.sshd.server.ServerFactoryManager;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.TeeOutputStream;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Test;
 
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
 
/**
* Test key exchange algorithms.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class KeyReExchangeTest extends BaseTest {
 
private SshServer sshd;
private int port;
 
@After
public void tearDown() throws Exception {
sshd.stop(true);
}
 
protected void setUp(long bytesLimit, long timeLimit) throws Exception {
port = Utils.getFreePort();
 
sshd = SshServer.setUpDefaultServer();
if (bytesLimit > 0) {
sshd.getProperties().put(ServerFactoryManager.REKEY_BYTES_LIMIT, Long.toString(bytesLimit));
}
if (timeLimit > 0) {
sshd.getProperties().put(ServerFactoryManager.REKEY_TIME_LIMIT, Long.toString(timeLimit));
}
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setShellFactory(new EchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.start();
}
 
@Test
public void testReExchangeFromClient() throws Exception {
setUp(0, 0);
 
JSchLogger.init();
JSch.setConfig("kex", "diffie-hellman-group-exchange-sha1");
JSch sch = new JSch();
com.jcraft.jsch.Session s = sch.getSession("smx", "localhost", port);
s.setUserInfo(new SimpleUserInfo("smx"));
s.connect();
com.jcraft.jsch.Channel c = s.openChannel("shell");
c.connect();
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
for (int i = 0; i < 10; i++) {
os.write("this is my command\n".getBytes());
os.flush();
byte[] data = new byte[512];
int len = is.read(data);
String str = new String(data, 0, len);
assertEquals("this is my command\n", str);
s.rekey();
}
c.disconnect();
s.disconnect();
}
 
@Test
public void testReExchangeFromNativeClient() throws Exception {
setUp(0, 0);
 
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ChannelShell channel = session.createShellChannel();
 
ByteArrayOutputStream sent = new ByteArrayOutputStream();
PipedOutputStream pipedIn = new PipedOutputStream();
channel.setIn(new PipedInputStream(pipedIn));
OutputStream teeOut = new TeeOutputStream(sent, pipedIn);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open();
 
teeOut.write("this is my command\n".getBytes());
teeOut.flush();
 
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
sb.append("0123456789");
}
sb.append("\n");
 
for (int i = 0; i < 10; i++) {
teeOut.write(sb.toString().getBytes());
teeOut.flush();
session.reExchangeKeys();
}
teeOut.write("exit\n".getBytes());
teeOut.flush();
 
channel.waitFor(ClientChannel.CLOSED, 0);
 
channel.close(false);
client.stop();
 
assertArrayEquals(sent.toByteArray(), out.toByteArray());
}
 
@Test
public void testReExchangeFromServer() throws Exception {
setUp(8192, 0);
 
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ChannelShell channel = session.createShellChannel();
 
ByteArrayOutputStream sent = new ByteArrayOutputStream();
PipedOutputStream pipedIn = new PipedOutputStream();
channel.setIn(new PipedInputStream(pipedIn));
OutputStream teeOut = new TeeOutputStream(sent, pipedIn);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
channel.open();
 
teeOut.write("this is my command\n".getBytes());
teeOut.flush();
 
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
sb.append("0123456789");
}
sb.append("\n");
 
final AtomicInteger exchanges = new AtomicInteger();
session.addListener(new SessionListener() {
public void sessionCreated(Session session) {
}
public void sessionEvent(Session session, Event event) {
if (event == Event.KeyEstablished) {
exchanges.incrementAndGet();
}
}
public void sessionClosed(Session session) {
}
});
for (int i = 0; i < 100; i++) {
teeOut.write(sb.toString().getBytes());
teeOut.flush();
}
teeOut.write("exit\n".getBytes());
teeOut.flush();
 
channel.waitFor(ClientChannel.CLOSED, 0);
 
channel.close(false);
client.stop();
 
assertTrue("Expected rekeying", exchanges.get() > 0);
assertEquals(sent.toByteArray().length, out.toByteArray().length);
assertArrayEquals(sent.toByteArray(), out.toByteArray());
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/SshServerTest.java
0,0 → 1,95
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
 
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.Test;
 
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
 
/**
* @author Kohsuke Kawaguchi
* @author Michael Heemskerk
*/
public class SshServerTest extends BaseTest {
 
@Test
public void stopMethodShouldBeIdempotent() throws Exception {
SshServer sshd = new SshServer();
sshd.stop();
sshd.stop();
sshd.stop();
}
 
@Test
public void testExecutorShutdownFalse() throws Exception {
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
 
SshServer sshd = createTestServer();
sshd.setScheduledExecutorService(executorService);
 
sshd.start();
sshd.stop();
 
assertFalse(executorService.isShutdown());
executorService.shutdownNow();
}
 
@Test
public void testExecutorShutdownTrue() throws Exception {
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
 
SshServer sshd = createTestServer();
sshd.setScheduledExecutorService(executorService, true);
 
sshd.start();
sshd.stop();
 
assertTrue(executorService.isShutdown());
}
 
@Test
public void testDynamicPort() throws Exception {
SshServer sshd = createTestServer();
sshd.setHost("localhost");
sshd.start();
 
assertNotEquals(0, sshd.getPort());
 
sshd.stop();
}
 
 
private SshServer createTestServer() {
SshServer sshd = SshServer.setUpDefaultServer();
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setShellFactory(new EchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
 
return sshd;
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/ScpTest.java
0,0 → 1,635
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
 
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import org.apache.sshd.client.ScpClient;
import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
 
/**
* Test for SCP support.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class ScpTest extends BaseTest {
 
private SshServer sshd;
private int port;
private com.jcraft.jsch.Session session;
 
@Before
public void setUp() throws Exception {
port = Utils.getFreePort();
// port = 8102;
 
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setCommandFactory(new ScpCommandFactory());
sshd.setShellFactory(new EchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.start();
}
 
protected com.jcraft.jsch.Session getJschSession() throws JSchException {
JSchLogger.init();
JSch sch = new JSch();
session = sch.getSession("sshd", "localhost", port);
session.setUserInfo(new SimpleUserInfo("sshd"));
session.connect();
return session;
}
 
@After
public void tearDown() throws Exception {
if (session != null) {
session.disconnect();
}
sshd.stop(true);
}
 
@Test
@Ignore
public void testExternal() throws Exception {
System.out.println("Scp available on port " + port);
Thread.sleep(5 * 60000);
}
 
@Test
public void testUploadAbsoluteDriveLetter() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("test", "localhost", port).await().getSession();
session.addPasswordIdentity("test");
session.auth().verify();
 
ScpClient scp = session.createScpClient();
 
String data = "0123456789\n";
 
File root = new File("target/scp");
Utils.deleteRecursive(root);
root.mkdirs();
new File(root, "local").mkdirs();
assertTrue(root.exists());
 
 
writeFile(new File("target/scp/local/out.txt"), data);
new File(root, "remote").mkdirs();
scp.upload(new File("target/scp/local/out.txt").getAbsolutePath(), "/" + new File("target/scp/remote/out.txt").getAbsolutePath().replace(File.separatorChar, '/'));
assertFileLength(new File("target/scp/remote/out.txt"), data.length(), 5000);
scp.upload(new File("target/scp/local/out.txt").getAbsolutePath(), new File("target/scp/remote/out2.txt").getAbsolutePath());
assertFileLength(new File("target/scp/remote/out2.txt"), data.length(), 5000);
}
 
@Test
public void testScpNativeOnSingleFile() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("test", "localhost", port).await().getSession();
session.addPasswordIdentity("test");
session.auth().verify();
 
ScpClient scp = session.createScpClient();
 
String data = "0123456789\n";
 
File root = new File("target/scp");
Utils.deleteRecursive(root);
root.mkdirs();
new File(root, "local").mkdirs();
assertTrue(root.exists());
 
 
writeFile(new File("target/scp/local/out.txt"), data);
try {
scp.upload("target/scp/local/out.txt", "target/scp/remote/out.txt");
fail("Expected IOException");
} catch (IOException e) {
// ok
}
new File(root, "remote").mkdirs();
scp.upload("target/scp/local/out.txt", "target/scp/remote/out.txt");
assertFileLength(new File("target/scp/remote/out.txt"), data.length(), 5000);
 
scp.download("target/scp/remote/out.txt", "target/scp/local/out2.txt");
assertFileLength(new File("target/scp/local/out2.txt"), data.length(), 5000);
 
session.close(false).await();
client.stop();
}
 
@Test
public void testScpNativeOnMultipleFiles() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("test", "localhost", port).await().getSession();
session.addPasswordIdentity("test");
session.auth().verify();
 
ScpClient scp = session.createScpClient();
 
String data = "0123456789\n";
 
File root = new File("target/scp");
Utils.deleteRecursive(root);
root.mkdirs();
new File(root, "local").mkdirs();
new File(root, "remote").mkdirs();
assertTrue(root.exists());
 
 
writeFile(new File("target/scp/local/out1.txt"), data);
writeFile(new File("target/scp/local/out2.txt"), data);
try {
scp.upload(new String[] { "target/scp/local/out1.txt", "target/scp/local/out2.txt" }, "target/scp/remote/out.txt");
fail("Expected IOException");
} catch (IOException e) {
// Ok
}
writeFile(new File("target/scp/remote/out.txt"), data);
try {
scp.upload(new String[] { "target/scp/local/out1.txt", "target/scp/local/out2.txt" }, "target/scp/remote/out.txt");
fail("Expected IOException");
} catch (IOException e) {
// Ok
}
new File(root, "remote/dir").mkdirs();
scp.upload(new String[] { "target/scp/local/out1.txt", "target/scp/local/out2.txt" }, "target/scp/remote/dir");
assertFileLength(new File("target/scp/remote/dir/out1.txt"), data.length(), 5000);
assertFileLength(new File("target/scp/remote/dir/out2.txt"), data.length(), 5000);
 
try {
scp.download(new String[] { "target/scp/remote/dir/out1.txt", "target/scp/remote/dir/out2.txt" }, "target/scp/local/out1.txt");
fail("Expected IOException");
} catch (IOException e) {
// Ok
}
try {
scp.download(new String[] { "target/scp/remote/dir/out1.txt", "target/scp/remote/dir/out2.txt" }, "target/scp/local/dir");
fail("Expected IOException");
} catch (IOException e) {
// Ok
}
new File(root, "local/dir").mkdirs();
scp.download(new String[] { "target/scp/remote/dir/out1.txt", "target/scp/remote/dir/out2.txt" }, "target/scp/local/dir");
assertFileLength(new File("target/scp/local/dir/out1.txt"), data.length(), 5000);
assertFileLength(new File("target/scp/local/dir/out2.txt"), data.length(), 5000);
 
session.close(false).await();
client.stop();
}
 
@Test
public void testScpNativeOnRecursiveDirs() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("test", "localhost", port).await().getSession();
session.addPasswordIdentity("test");
session.auth().verify();
 
ScpClient scp = session.createScpClient();
 
String data = "0123456789\n";
 
File root = new File("target/scp");
Utils.deleteRecursive(root);
root.mkdirs();
new File(root, "local").mkdirs();
new File(root, "remote").mkdirs();
assertTrue(root.exists());
 
new File("target/scp/local/dir").mkdirs();
writeFile(new File("target/scp/local/dir/out1.txt"), data);
writeFile(new File("target/scp/local/dir/out2.txt"), data);
scp.upload("target/scp/local/dir", "target/scp/remote/", ScpClient.Option.Recursive);
assertFileLength(new File("target/scp/remote/dir/out1.txt"), data.length(), 5000);
assertFileLength(new File("target/scp/remote/dir/out2.txt"), data.length(), 5000);
 
Utils.deleteRecursive(new File("target/scp/local/dir"));
scp.download("target/scp/remote/dir", "target/scp/local", ScpClient.Option.Recursive);
assertFileLength(new File("target/scp/local/dir/out1.txt"), data.length(), 5000);
assertFileLength(new File("target/scp/local/dir/out2.txt"), data.length(), 5000);
 
session.close(false).await();
client.stop();
}
 
@Test
public void testScpNativeOnDirWithPattern() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("test", "localhost", port).await().getSession();
session.addPasswordIdentity("test");
session.auth().verify();
 
ScpClient scp = session.createScpClient();
 
String data = "0123456789\n";
 
File root = new File("target/scp");
Utils.deleteRecursive(root);
root.mkdirs();
new File(root, "local").mkdirs();
new File(root, "remote").mkdirs();
assertTrue(root.exists());
 
writeFile(new File("target/scp/local/out1.txt"), data);
writeFile(new File("target/scp/local/out2.txt"), data);
scp.upload("target/scp/local/*", "target/scp/remote/");
assertFileLength(new File("target/scp/remote/out1.txt"), data.length(), 5000);
assertFileLength(new File("target/scp/remote/out2.txt"), data.length(), 5000);
 
new File("target/scp/local/out1.txt").delete();
new File("target/scp/local/out2.txt").delete();
scp.download("target/scp/remote/*", "target/scp/local");
assertFileLength(new File("target/scp/local/out1.txt"), data.length(), 5000);
assertFileLength(new File("target/scp/local/out2.txt"), data.length(), 5000);
 
session.close(false).await();
client.stop();
}
 
@Test
public void testScpNativeOnMixedDirAndFiles() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("test", "localhost", port).await().getSession();
session.addPasswordIdentity("test");
session.auth().verify();
 
ScpClient scp = session.createScpClient();
 
String data = "0123456789\n";
 
File root = new File("target/scp");
Utils.deleteRecursive(root);
root.mkdirs();
new File(root, "local").mkdirs();
new File(root, "remote").mkdirs();
assertTrue(root.exists());
 
new File("target/scp/local/dir").mkdirs();
writeFile(new File("target/scp/local/out1.txt"), data);
writeFile(new File("target/scp/local/dir/out2.txt"), data);
scp.upload("target/scp/local/*", "target/scp/remote/", ScpClient.Option.Recursive);
assertFileLength(new File("target/scp/remote/out1.txt"), data.length(), 5000);
assertFileLength(new File("target/scp/remote/dir/out2.txt"), data.length(), 5000);
 
Utils.deleteRecursive(new File("target/scp/local/out1.txt"));
Utils.deleteRecursive(new File("target/scp/local/dir"));
scp.download("target/scp/remote/*", "target/scp/local");
assertFileLength(new File("target/scp/local/out1.txt"), data.length(), 5000);
assertFalse(new File("target/scp/local/dir/out2.txt").exists());
 
Utils.deleteRecursive(new File("target/scp/local/out1.txt"));
scp.download("target/scp/remote/*", "target/scp/local", ScpClient.Option.Recursive);
assertFileLength(new File("target/scp/local/out1.txt"), data.length(), 5000);
assertFileLength(new File("target/scp/local/dir/out2.txt"), data.length(), 5000);
 
session.close(false).await();
client.stop();
}
 
@Test
public void testScpNativePreserveAttributes() throws Exception {
// Ignore this test if running a Windows system
if (System.getProperty("os.name").toLowerCase().contains("win")) {
return;
}
 
SshClient client = SshClient.setUpDefaultClient();
client.start();
ClientSession session = client.connect("test", "localhost", port).await().getSession();
session.addPasswordIdentity("test");
session.auth().verify();
 
ScpClient scp = session.createScpClient();
 
String data = "0123456789\n";
 
File root = new File("target/scp");
Utils.deleteRecursive(root);
root.mkdirs();
new File(root, "local").mkdirs();
new File(root, "remote").mkdirs();
assertTrue(root.exists());
 
new File("target/scp/local/dir").mkdirs();
long lastMod = new File("target/scp/local/dir").lastModified() - TimeUnit.DAYS.toMillis(1);
 
writeFile(new File("target/scp/local/out1.txt"), data);
writeFile(new File("target/scp/local/dir/out2.txt"), data);
new File("target/scp/local/out1.txt").setLastModified(lastMod);
new File("target/scp/local/out1.txt").setExecutable(true, true);
new File("target/scp/local/out1.txt").setWritable(false, false);
new File("target/scp/local/dir/out2.txt").setLastModified(lastMod);
scp.upload("target/scp/local/*", "target/scp/remote/", ScpClient.Option.Recursive, ScpClient.Option.PreserveAttributes);
assertFileLength(new File("target/scp/remote/out1.txt"), data.length(), 5000);
assertEquals(lastMod, new File("target/scp/remote/out1.txt").lastModified());
assertFileLength(new File("target/scp/remote/dir/out2.txt"), data.length(), 5000);
assertEquals(lastMod, new File("target/scp/remote/dir/out2.txt").lastModified());
 
Utils.deleteRecursive(new File("target/scp/local"));
new File("target/scp/local").mkdirs();
scp.download("target/scp/remote/*", "target/scp/local", ScpClient.Option.Recursive, ScpClient.Option.PreserveAttributes);
assertFileLength(new File("target/scp/local/out1.txt"), data.length(), 5000);
assertEquals(lastMod, new File("target/scp/local/out1.txt").lastModified());
assertFileLength(new File("target/scp/local/dir/out2.txt"), data.length(), 5000);
assertEquals(lastMod, new File("target/scp/local/dir/out2.txt").lastModified());
 
session.close(false).await();
client.stop();
}
 
private void writeFile(File file, String data) throws IOException {
FileOutputStream fos = new FileOutputStream(file);
try {
fos.write(data.getBytes());
} finally {
fos.close();
}
}
 
@Test
public void testScp() throws Exception {
session = getJschSession();
 
String data = "0123456789\n";
 
String unixDir = "target/scp";
String fileName = "out.txt";
String unixPath = unixDir + File.separator + fileName;
File root = new File(unixDir);
File target = new File(unixPath);
Utils.deleteRecursive(root);
root.mkdirs();
assertTrue(root.exists());
 
target.delete();
assertFalse(target.exists());
sendFile(unixPath, "out.txt", data);
assertFileLength(target, data.length(), 5000);
 
target.delete();
assertFalse(target.exists());
sendFile(unixDir, "out.txt", data);
assertFileLength(target, data.length(), 5000);
 
sendFileError("target", "scp", "0123456789\n");
 
readFileError(unixDir);
 
assertEquals(data, readFile(unixPath));
 
assertEquals(data, readDir(unixDir));
 
target.delete();
root.delete();
 
sendDir("target", "scp", "out.txt", data);
assertFileLength(target, data.length(), 5000);
}
 
@Test
public void testWithGanymede() throws Exception {
// begin client config
final Connection conn = new Connection("localhost", port);
conn.connect(null, 5000, 0);
conn.authenticateWithPassword("sshd", "sshd");
final SCPClient scp_client = new SCPClient(conn);
final Properties props = new Properties();
props.setProperty("test", "test-passed");
File f = new File("target/scp/gan");
Utils.deleteRecursive(f);
f.mkdirs();
assertTrue(f.exists());
 
String name = "test.properties";
scp_client.put(toBytes(props, ""), name, "target/scp/gan");
assertTrue(new File(f, name).exists());
assertTrue(new File(f, name).delete());
 
name = "test2.properties";
scp_client.put(toBytes(props, ""), name, "target/scp/gan");
assertTrue(new File(f, name).exists());
assertTrue(new File(f, name).delete());
 
assertTrue(f.delete());
conn.close();
}
 
private byte[] toBytes(final Properties properties, final String comments) {
try {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
properties.store(baos, comments);
baos.close();
return baos.toByteArray();
} catch (final IOException cause) {
throw new RuntimeException("Failed to output properties to byte[]", cause);
}
}
 
protected void assertFileLength(File file, long length, long timeout) throws Exception{
boolean ok = false;
while (timeout > 0) {
if (file.exists() && file.length() == length) {
if (!ok) {
ok = true;
} else {
return;
}
} else {
ok = false;
}
Thread.sleep(100);
timeout -= 100;
}
assertTrue(file.exists());
assertEquals(length, file.length());
}
 
protected String readFile(String path) throws Exception {
ChannelExec c = (ChannelExec) session.openChannel("exec");
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
c.setCommand("scp -f " + path);
c.connect();
os.write(0);
os.flush();
String header = readLine(is);
assertEquals("C0644 11 out.txt", header);
int length = Integer.parseInt(header.substring(6, header.indexOf(' ', 6)));
os.write(0);
os.flush();
 
byte[] buffer = new byte[length];
length = is.read(buffer, 0, buffer.length);
assertEquals(length, buffer.length);
assertEquals(0, is.read());
os.write(0);
os.flush();
 
c.disconnect();
return new String(buffer);
}
 
protected String readDir(String path) throws Exception {
ChannelExec c = (ChannelExec) session.openChannel("exec");
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
c.setCommand("scp -r -f " + path);
c.connect();
os.write(0);
os.flush();
String header = readLine(is);
assertTrue(header.startsWith("D0755 0 "));
os.write(0);
os.flush();
header = readLine(is);
assertEquals("C0644 11 out.txt", header);
int length = Integer.parseInt(header.substring(6, header.indexOf(' ', 6)));
os.write(0);
os.flush();
byte[] buffer = new byte[length];
length = is.read(buffer, 0, buffer.length);
assertEquals(length, buffer.length);
assertEquals(0, is.read());
os.write(0);
os.flush();
header = readLine(is);
assertEquals("E", header);
os.write(0);
os.flush();
 
c.disconnect();
return new String(buffer);
}
 
protected String readFileError(String path) throws Exception {
ChannelExec c = (ChannelExec) session.openChannel("exec");
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
c.setCommand("scp -f " + path);
c.connect();
os.write(0);
os.flush();
assertEquals(2, is.read());
c.disconnect();
return null;
}
 
protected void sendFile(String path, String name, String data) throws Exception {
ChannelExec c = (ChannelExec) session.openChannel("exec");
c.setCommand("scp -t " + path);
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
c.connect();
assertEquals(0, is.read());
os.write(("C7777 "+ data.length() + " " + name + "\n").getBytes());
os.flush();
assertEquals(0, is.read());
os.write(data.getBytes());
os.flush();
assertEquals(0, is.read());
os.write(0);
os.flush();
Thread.sleep(100);
c.disconnect();
}
 
protected void sendFileError(String path, String name, String data) throws Exception {
ChannelExec c = (ChannelExec) session.openChannel("exec");
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
c.setCommand("scp -t " + path);
c.connect();
assertEquals(0, is.read());
os.write(("C7777 "+ data.length() + " " + name + "\n").getBytes());
os.flush();
assertEquals(2, is.read());
c.disconnect();
}
 
protected void sendDir(String path, String dirName, String fileName, String data) throws Exception {
ChannelExec c = (ChannelExec) session.openChannel("exec");
OutputStream os = c.getOutputStream();
InputStream is = c.getInputStream();
c.setCommand("scp -t -r " + path);
c.connect();
assertEquals(0, is.read());
os.write(("D0755 0 " + dirName + "\n").getBytes());
os.flush();
assertEquals(0, is.read());
os.write(("C7777 " + data.length() + " " + fileName + "\n").getBytes());
os.flush();
assertEquals(0, is.read());
os.write(data.getBytes());
os.flush();
assertEquals(0, is.read());
os.write(0);
os.flush();
os.write("E\n".getBytes());
os.flush();
assertEquals(0, is.read());
}
 
private String readLine(InputStream in) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (;;) {
int c = in.read();
if (c == '\n') {
return baos.toString();
} else if (c == -1) {
throw new IOException("End of stream");
} else {
baos.write(c);
}
}
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/SimpleGeneratorHostKeyProviderTest.java
0,0 → 1,170
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.server.keyprovider;
 
import java.io.File;
import java.security.spec.ECGenParameterSpec;
 
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.util.BaseTest;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class SimpleGeneratorHostKeyProviderTest extends BaseTest {
 
@Test
public void testDSA() {
File path = new File("target/keys");
path.mkdirs();
path = new File(path, "simple.key");
path.delete();
 
// Generate
SimpleGeneratorHostKeyProvider provider = new SimpleGeneratorHostKeyProvider();
provider.setAlgorithm("DSA");
provider.setKeySize(512);
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.SSH_DSS, provider.getKeyTypes());
assertNotNull(provider.loadKey(KeyPairProvider.SSH_DSS));
 
// Read existing
provider = new SimpleGeneratorHostKeyProvider();
provider.setAlgorithm("DSA");
provider.setKeySize(512);
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.SSH_DSS, provider.getKeyTypes());
assertNotNull(provider.loadKey(KeyPairProvider.SSH_DSS));
}
 
@Test
public void testRSA() {
File path = new File("target/keys");
path.mkdirs();
path = new File(path, "simple.key");
path.delete();
 
// Generate
SimpleGeneratorHostKeyProvider provider = new SimpleGeneratorHostKeyProvider();
provider.setAlgorithm("RSA");
provider.setKeySize(512);
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.SSH_RSA, provider.getKeyTypes());
assertNotNull(provider.loadKey(KeyPairProvider.SSH_RSA));
 
// Read existing
provider = new SimpleGeneratorHostKeyProvider();
provider.setAlgorithm("RSA");
provider.setKeySize(512);
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.SSH_RSA, provider.getKeyTypes());
assertNotNull(provider.loadKey(KeyPairProvider.SSH_RSA));
}
 
@Test
public void testEC_NISTP256() {
if (!SecurityUtils.isBouncyCastleRegistered()) {
return;
}
 
File path = new File("target/keys");
path.mkdirs();
path = new File(path, "simple.key");
path.delete();
 
// Generate
SimpleGeneratorHostKeyProvider provider = new SimpleGeneratorHostKeyProvider();
provider.setAlgorithm("EC");
provider.setKeySpec(new ECGenParameterSpec("prime256v1"));
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.ECDSA_SHA2_NISTP256, provider.getKeyTypes());
assertNotNull(provider.loadKey(KeyPairProvider.ECDSA_SHA2_NISTP256));
 
// Read existing
provider = new SimpleGeneratorHostKeyProvider();
provider.setAlgorithm("EC");
provider.setKeySpec(new ECGenParameterSpec("prime256v1"));
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.ECDSA_SHA2_NISTP256, provider.getKeyTypes());
assertNotNull(provider.loadKey(KeyPairProvider.ECDSA_SHA2_NISTP256));
}
@Test
public void testEC_NISTP384() {
if (!SecurityUtils.isBouncyCastleRegistered()) {
return;
}
 
File path = new File("target/keys");
path.mkdirs();
path = new File(path, "simple.key");
path.delete();
 
// Generate
SimpleGeneratorHostKeyProvider provider = new SimpleGeneratorHostKeyProvider();
provider.setAlgorithm("EC");
provider.setKeySpec(new ECGenParameterSpec("P-384"));
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.ECDSA_SHA2_NISTP384, provider.getKeyTypes());
assertNotNull(provider.loadKey(KeyPairProvider.ECDSA_SHA2_NISTP384));
 
// Read existing
provider = new SimpleGeneratorHostKeyProvider();
provider.setAlgorithm("EC");
provider.setKeySpec(new ECGenParameterSpec("P-384"));
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.ECDSA_SHA2_NISTP384, provider.getKeyTypes());
assertNotNull(provider.loadKey(KeyPairProvider.ECDSA_SHA2_NISTP384));
}
 
@Test
public void testEC_NISTP521() {
if (!SecurityUtils.isBouncyCastleRegistered()) {
return;
}
 
File path = new File("target/keys");
path.mkdirs();
path = new File(path, "simple.key");
path.delete();
 
// Generate
SimpleGeneratorHostKeyProvider provider = new SimpleGeneratorHostKeyProvider();
provider.setAlgorithm("EC");
provider.setKeySpec(new ECGenParameterSpec("P-521"));
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.ECDSA_SHA2_NISTP521, provider.getKeyTypes());
assertNotNull(provider.loadKey(KeyPairProvider.ECDSA_SHA2_NISTP521));
 
// Read existing
provider = new SimpleGeneratorHostKeyProvider();
provider.setAlgorithm("EC");
provider.setKeySpec(new ECGenParameterSpec("P-521"));
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.ECDSA_SHA2_NISTP521, provider.getKeyTypes());
assertNotNull(provider.loadKey(KeyPairProvider.ECDSA_SHA2_NISTP521));
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/PEMGeneratorHostKeyProviderTest.java
0,0 → 1,199
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.server.keyprovider;
 
import java.io.File;
import java.security.KeyPair;
import java.security.spec.ECGenParameterSpec;
 
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.util.BaseTest;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class PEMGeneratorHostKeyProviderTest extends BaseTest {
 
@Test
public void testDSA() {
if (!SecurityUtils.isBouncyCastleRegistered()) {
return;
}
 
File path = new File("target/keys");
path.mkdirs();
path = new File(path, "simple_dsa.key");
path.delete();
 
// Generate
PEMGeneratorHostKeyProvider provider = new PEMGeneratorHostKeyProvider();
provider.setAlgorithm("DSA");
provider.setKeySize(512);
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.SSH_DSS, provider.getKeyTypes());
KeyPair pk1 = provider.loadKey(KeyPairProvider.SSH_DSS);
assertNotNull(pk1);
 
// Read existing
provider = new PEMGeneratorHostKeyProvider();
provider.setAlgorithm("DSA");
provider.setKeySize(512);
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.SSH_DSS, provider.getKeyTypes());
KeyPair pk2 = provider.loadKey(KeyPairProvider.SSH_DSS);
assertNotNull(pk2);
 
assertEquals(pk2.getPublic(), pk1.getPublic());
}
 
@Test
public void testRSA() {
if (!SecurityUtils.isBouncyCastleRegistered()) {
return;
}
 
File path = new File("target/keys");
path.mkdirs();
path = new File(path, "simple_rsa.key");
path.delete();
 
// Generate
PEMGeneratorHostKeyProvider provider = new PEMGeneratorHostKeyProvider();
provider.setAlgorithm("RSA");
provider.setKeySize(512);
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.SSH_RSA, provider.getKeyTypes());
KeyPair pk1 = provider.loadKey(KeyPairProvider.SSH_RSA);
assertNotNull(pk1);
 
// Read existing
provider = new PEMGeneratorHostKeyProvider();
provider.setAlgorithm("RSA");
provider.setKeySize(512);
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.SSH_RSA, provider.getKeyTypes());
KeyPair pk2 = provider.loadKey(KeyPairProvider.SSH_RSA);
assertNotNull(pk2);
 
assertEquals(pk2.getPublic(), pk1.getPublic());
}
 
@Test
public void testEC_NISTP256() {
if (!SecurityUtils.isBouncyCastleRegistered()) {
return;
}
 
File path = new File("target/keys");
path.mkdirs();
path = new File(path, "simple_ec_nistp256.key");
path.delete();
 
// Generate
PEMGeneratorHostKeyProvider provider = new PEMGeneratorHostKeyProvider();
provider.setAlgorithm("EC");
provider.setKeySpec(new ECGenParameterSpec("prime256v1"));
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.ECDSA_SHA2_NISTP256, provider.getKeyTypes());
KeyPair pk1 = provider.loadKey(KeyPairProvider.ECDSA_SHA2_NISTP256);
assertNotNull(pk1);
 
// Read existing
provider = new PEMGeneratorHostKeyProvider();
provider.setAlgorithm("EC");
provider.setKeySpec(new ECGenParameterSpec("prime256v1"));
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.ECDSA_SHA2_NISTP256, provider.getKeyTypes());
KeyPair pk2 = provider.loadKey(KeyPairProvider.ECDSA_SHA2_NISTP256);
assertNotNull(pk2);
 
assertEquals(pk2.getPublic(), pk1.getPublic());
}
 
@Test
public void testEC_NISTP384() {
if (!SecurityUtils.isBouncyCastleRegistered()) {
return;
}
 
File path = new File("target/keys");
path.mkdirs();
path = new File(path, "simple_ec_nistp384.key");
path.delete();
 
// Generate
PEMGeneratorHostKeyProvider provider = new PEMGeneratorHostKeyProvider();
provider.setAlgorithm("EC");
provider.setKeySpec(new ECGenParameterSpec("P-384"));
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.ECDSA_SHA2_NISTP384, provider.getKeyTypes());
KeyPair pk1 = provider.loadKey(KeyPairProvider.ECDSA_SHA2_NISTP384);
assertNotNull(pk1);
 
// Read existing
provider = new PEMGeneratorHostKeyProvider();
provider.setAlgorithm("EC");
provider.setKeySpec(new ECGenParameterSpec("P-384"));
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.ECDSA_SHA2_NISTP384, provider.getKeyTypes());
KeyPair pk2 = provider.loadKey(KeyPairProvider.ECDSA_SHA2_NISTP384);
assertNotNull(pk2);
 
assertEquals(pk2.getPublic(), pk1.getPublic());
}
 
@Test
public void testEC_NISTP521() {
if (!SecurityUtils.isBouncyCastleRegistered()) {
return;
}
 
File path = new File("target/keys");
path.mkdirs();
path = new File(path, "simple_ec_nistp521.key");
path.delete();
 
// Generate
PEMGeneratorHostKeyProvider provider = new PEMGeneratorHostKeyProvider();
provider.setAlgorithm("EC");
provider.setKeySpec(new ECGenParameterSpec("P-521"));
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.ECDSA_SHA2_NISTP521, provider.getKeyTypes());
KeyPair pk1 = provider.loadKey(KeyPairProvider.ECDSA_SHA2_NISTP521);
assertNotNull(pk1);
 
// Read existing
provider = new PEMGeneratorHostKeyProvider();
provider.setAlgorithm("EC");
provider.setKeySpec(new ECGenParameterSpec("P-521"));
provider.setPath(path.getPath());
assertEquals(KeyPairProvider.ECDSA_SHA2_NISTP521, provider.getKeyTypes());
KeyPair pk2 = provider.loadKey(KeyPairProvider.ECDSA_SHA2_NISTP521);
assertNotNull(pk2);
 
assertEquals(pk2.getPublic(), pk1.getPublic());
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/server/keyprovider/AbstractGeneratorHostKeyProviderTest.java
0,0 → 1,74
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.server.keyprovider;
 
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
 
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyPair;
import java.util.concurrent.atomic.AtomicInteger;
 
import static org.junit.Assert.assertEquals;
 
public class AbstractGeneratorHostKeyProviderTest {
 
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
 
@Test
public void testOverwriteKey() throws Exception {
File keyPairFile = temporaryFolder.newFile();
 
TestProvider provider = new TestProvider(keyPairFile);
provider.loadKeys();
assertEquals(1, provider.getWriteCount());
 
provider = new TestProvider(keyPairFile);
provider.setOverwriteAllowed(false);
provider.loadKeys();
assertEquals(0, provider.getWriteCount());
}
 
private class TestProvider extends AbstractGeneratorHostKeyProvider {
private final AtomicInteger writes = new AtomicInteger(0);
 
private TestProvider(File file) {
super(file.getAbsolutePath(), "DSA", 512);
}
 
@Override
protected KeyPair doReadKeyPair(InputStream is) throws Exception {
return null;
}
 
@Override
protected void doWriteKeyPair(KeyPair kp, OutputStream os) throws Exception {
writes.incrementAndGet();
}
 
public int getWriteCount() {
return writes.get();
}
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/server/shell/InvertedShellWrapperTest.java
0,0 → 1,64
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.server.shell;
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
 
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusEnvironment;
import org.apache.sshd.util.BogusExitCallback;
import org.apache.sshd.util.BogusInvertedShell;
import org.junit.Test;
 
import static junit.framework.Assert.assertEquals;
 
public class InvertedShellWrapperTest extends BaseTest {
 
@Test
public void testStreamsAreFlushedBeforeClosing() throws Exception {
BogusInvertedShell shell = newShell("out", "err");
shell.setAlive(false);
ByteArrayInputStream in = new ByteArrayInputStream("in".getBytes());
ByteArrayOutputStream out = new ByteArrayOutputStream(50);
ByteArrayOutputStream err = new ByteArrayOutputStream();
 
InvertedShellWrapper wrapper = new InvertedShellWrapper(shell);
wrapper.setInputStream(in);
wrapper.setOutputStream(out);
wrapper.setErrorStream(err);
wrapper.setExitCallback(new BogusExitCallback());
wrapper.start(new BogusEnvironment());
 
wrapper.pumpStreams();
 
// check the streams were flushed before exiting
assertEquals("in", shell.getInputStream().toString());
assertEquals("out", out.toString());
assertEquals("err", err.toString());
}
 
private BogusInvertedShell newShell(String contentOut, String contentErr) {
ByteArrayOutputStream in = new ByteArrayOutputStream(20);
ByteArrayInputStream out = new ByteArrayInputStream(contentOut.getBytes());
ByteArrayInputStream err = new ByteArrayInputStream(contentErr.getBytes());
return new BogusInvertedShell(in, out, err);
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/server/jaas/JaasPasswordAuthenticatorTest.java
0,0 → 1,126
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.server.jaas;
 
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
 
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
 
import org.apache.sshd.util.BaseTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class JaasPasswordAuthenticatorTest extends BaseTest {
 
@Before
public void setUp() {
Configuration config = new Configuration() {
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
return new AppConfigurationEntry[] {
new AppConfigurationEntry(DummyLoginModule.class.getName(),
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
new HashMap<String,Object>())
};
}
public void refresh() {
}
};
Configuration.setConfiguration(config);
}
 
@After
public void tearDown() {
Configuration.setConfiguration(null);
}
 
@Test
public void testAuthenticator() {
JaasPasswordAuthenticator auth = new JaasPasswordAuthenticator();
assertNull(auth.getDomain());
auth.setDomain("domain");
assertEquals("domain", auth.getDomain());
assertTrue(auth.authenticate("sshd", "sshd"));
assertFalse(auth.authenticate("sshd", "dummy"));
}
 
 
protected static class DummyLoginModule implements LoginModule {
 
private Subject subject;
private CallbackHandler callbackHandler;
 
public DummyLoginModule() {
}
 
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
this.subject = subject;
this.callbackHandler = callbackHandler;
}
 
public boolean login() throws LoginException {
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("Username: ");
callbacks[1] = new PasswordCallback("Password: ", false);
try {
callbackHandler.handle(callbacks);
} catch (IOException ioe) {
throw new LoginException(ioe.getMessage());
} catch (UnsupportedCallbackException uce) {
throw new LoginException(uce.getMessage() + " not available to obtain information from user");
}
String user = ((NameCallback) callbacks[0]).getName();
char[] tmpPassword = ((PasswordCallback) callbacks[1]).getPassword();
return user.equals(new String(tmpPassword));
}
 
public boolean commit() throws LoginException {
return true;
}
 
public boolean abort() throws LoginException {
return true;
}
 
public boolean logout() throws LoginException {
return true;
}
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/KexTest.java
0,0 → 1,155
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.Collections;
 
import org.apache.sshd.client.kex.DHG1;
import org.apache.sshd.client.kex.DHG14;
import org.apache.sshd.client.kex.DHGEX;
import org.apache.sshd.client.kex.DHGEX256;
import org.apache.sshd.client.kex.ECDHP256;
import org.apache.sshd.client.kex.ECDHP384;
import org.apache.sshd.client.kex.ECDHP521;
import org.apache.sshd.common.KeyExchange;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.TeeOutputStream;
import org.apache.sshd.util.Utils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
 
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertTrue;
 
/**
* Test key exchange algorithms.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class KexTest extends BaseTest {
 
private SshServer sshd;
private int port;
 
@Before
public void setUp() throws Exception {
port = Utils.getFreePort();
 
sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
sshd.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd.setShellFactory(new EchoShellFactory());
sshd.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd.start();
}
 
@After
public void tearDown() throws Exception {
sshd.stop(true);
}
 
@Test
public void testDHGEX256() throws Exception {
testClient(new DHGEX256.Factory());
}
 
@Test
public void testDHGEX() throws Exception {
testClient(new DHGEX.Factory());
}
 
@Test
public void testDHG14() throws Exception {
if (SecurityUtils.isBouncyCastleRegistered()) {
testClient(new DHG14.Factory());
}
}
 
@Test
public void testDHG1() throws Exception {
testClient(new DHG1.Factory());
}
 
@Test
public void testECDHP521() throws Exception {
testClient(new ECDHP521.Factory());
}
 
@Test
public void testECDHP384() throws Exception {
testClient(new ECDHP384.Factory());
}
 
@Test
public void testECDHP256() throws Exception {
testClient(new ECDHP256.Factory());
}
 
private void testClient(NamedFactory<KeyExchange> kex) throws Exception {
SshClient client = SshClient.setUpDefaultClient();
ByteArrayOutputStream sent = new ByteArrayOutputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
client.setKeyExchangeFactories(Collections.singletonList(kex));
client.start();
ClientSession session = client.connect("smx", "localhost", port).await().getSession();
session.addPasswordIdentity("smx");
session.auth().verify();
ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL);
 
PipedOutputStream pipedIn = new PipedOutputStream();
channel.setIn(new PipedInputStream(pipedIn));
OutputStream teeOut = new TeeOutputStream(sent, pipedIn);
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel.setOut(out);
channel.setErr(err);
assertTrue(channel.open().await().isOpened());
 
teeOut.write("this is my command\n".getBytes());
teeOut.flush();
 
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
sb.append("0123456789");
}
sb.append("\n");
teeOut.write(sb.toString().getBytes());
 
teeOut.write("exit\n".getBytes());
teeOut.flush();
 
channel.waitFor(ClientChannel.CLOSED, 0);
 
channel.close(false);
} finally {
client.stop();
}
 
assertArrayEquals(sent.toByteArray(), out.toByteArray());
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/SpringConfigTest.java
0,0 → 1,74
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.OutputStream;
 
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.JSchLogger;
import org.apache.sshd.util.SimpleUserInfo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
/**
* Test for spring based configuration.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class SpringConfigTest extends BaseTest {
 
private ClassPathXmlApplicationContext context;
 
@Before
public void setUp() throws Exception {
context = new ClassPathXmlApplicationContext("classpath:spring.xml");
}
 
@After
public void tearDown() throws Exception {
if (context != null) {
context.destroy();
}
}
 
@Test
public void testSpringConfig() throws Exception {
int port = ((SshServer) context.getBean("sshServer")).getPort();
 
JSchLogger.init();
JSch sch = new JSch();
com.jcraft.jsch.Session s = sch.getSession("smx", "localhost", port);
s.setUserInfo(new SimpleUserInfo("smx"));
s.connect();
Channel c = s.openChannel("shell");
c.connect();
OutputStream os = c.getOutputStream();
os.write("this is my command".getBytes());
os.flush();
Thread.sleep(100);
c.disconnect();
s.disconnect();
}
 
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/Utils.java
0,0 → 1,75
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import java.io.File;
import java.net.ServerSocket;
import java.net.URISyntaxException;
import java.net.URL;
 
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
 
public class Utils {
 
public static KeyPairProvider createTestHostKeyProvider() {
return new SimpleGeneratorHostKeyProvider("target/hostkey.rsa", "RSA");
// return createTestKeyPairProvider("hostkey.pem");
}
 
public static FileKeyPairProvider createTestKeyPairProvider(String resource) {
return new FileKeyPairProvider(new String[] { getFile(resource) });
}
 
public static int getFreePort() throws Exception {
ServerSocket s = new ServerSocket(0);
try {
return s.getLocalPort();
} finally {
s.close();
}
}
 
private static String getFile(String resource) {
URL url = Utils.class.getClassLoader().getResource(resource);
File f;
try {
f = new File(url.toURI());
} catch(URISyntaxException e) {
f = new File(url.getPath());
}
return f.toString();
}
 
public static void deleteRecursive(File file) {
if (file != null) {
if (file.isDirectory()) {
File[] children = file.listFiles();
if (children != null) {
for (File child : children) {
deleteRecursive(child);
}
}
}
file.delete();
}
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/BogusPublickeyAuthenticator.java
0,0 → 1,36
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import java.security.PublicKey;
 
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.session.ServerSession;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class BogusPublickeyAuthenticator implements PublickeyAuthenticator {
 
public boolean authenticate(String username, PublicKey key, ServerSession session) {
return true;
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/BogusEnvironment.java
0,0 → 1,52
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import java.util.Collections;
import java.util.EnumSet;
import java.util.Map;
 
import org.apache.sshd.common.PtyMode;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.Signal;
import org.apache.sshd.server.SignalListener;
 
public class BogusEnvironment implements Environment {
 
public Map<String, String> getEnv() {
return Collections.emptyMap();
}
 
public Map<PtyMode, Integer> getPtyModes() {
return Collections.emptyMap();
}
 
public void addSignalListener(SignalListener listener, Signal... signal) {
}
 
public void addSignalListener(SignalListener listener, EnumSet<Signal> signals) {
}
 
public void addSignalListener(SignalListener listener) {
}
 
public void removeSignalListener(SignalListener listener) {
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/SimpleUserInfo.java
0,0 → 1,63
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import com.jcraft.jsch.UIKeyboardInteractive;
import com.jcraft.jsch.UserInfo;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class SimpleUserInfo implements UserInfo, UIKeyboardInteractive {
 
private final String password;
 
public SimpleUserInfo(String password) {
this.password = password;
}
 
public String getPassphrase() {
return null;
}
 
public String getPassword() {
return password;
}
 
public boolean promptPassword(String message) {
return true;
}
 
public boolean promptPassphrase(String message) {
return false;
}
 
public boolean promptYesNo(String message) {
return true;
}
 
public void showMessage(String message) {
}
 
public String[] promptKeyboardInteractive(String destination, String name, String instruction, String[] prompt, boolean[] echo) {
return new String[] { password };
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/BogusExitCallback.java
0,0 → 1,39
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import org.apache.sshd.server.ExitCallback;
 
public class BogusExitCallback implements ExitCallback {
 
private boolean exited;
 
public void onExit(int exitValue) {
this.exited = true;
}
 
public void onExit(int exitValue, String exitMessage) {
this.exited = true;
}
 
public boolean isExited() {
return exited;
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/JSchLogger.java
0,0 → 1,56
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Logger;
import org.slf4j.LoggerFactory;
 
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class JSchLogger implements Logger {
 
public static void init() {
JSch.setLogger(new JSchLogger());
}
 
private org.slf4j.Logger log = LoggerFactory.getLogger("org.jcraft.jsch.JSch");
 
public boolean isEnabled(int level) {
switch (level) {
case DEBUG: return log.isDebugEnabled();
case INFO: return log.isInfoEnabled();
case WARN: return log.isWarnEnabled();
case ERROR: return log.isErrorEnabled();
case FATAL: return log.isErrorEnabled();
}
return false;
}
 
public void log(int level, String message) {
switch (level) {
case DEBUG: log.debug(message); break;
case INFO: log.info(message); break;
case WARN: log.warn(message); break;
case ERROR: log.error(message); break;
case FATAL: log.error(message); break;
}
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/BogusForwardingFilter.java
0,0 → 1,46
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import org.apache.sshd.common.ForwardingFilter;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.SshdSocketAddress;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class BogusForwardingFilter implements ForwardingFilter {
public boolean canForwardAgent(Session session) {
return true;
}
 
public boolean canForwardX11(Session session) {
return true;
}
 
public boolean canConnect(SshdSocketAddress address, Session session) {
return true;
}
 
public boolean canListen(SshdSocketAddress address, Session session) {
return true;
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/BogusInvertedShell.java
0,0 → 1,89
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Map;
 
import org.apache.sshd.common.util.IoUtils;
import org.apache.sshd.server.shell.InvertedShell;
 
public class BogusInvertedShell implements InvertedShell {
 
private final OutputStream in;
private final InputStream out;
private final InputStream err;
 
// for test assertions
private boolean started = false;
private boolean alive = true;
private Map<String, String> env = null;
 
public BogusInvertedShell(OutputStream in, InputStream out, InputStream err) {
this.in = in;
this.out = out;
this.err = err;
}
 
public void start(Map<String, String> env) throws IOException {
this.started = true;
this.env = Collections.unmodifiableMap(env);
}
 
public OutputStream getInputStream() {
return in;
}
 
public InputStream getOutputStream() {
return out;
}
 
public InputStream getErrorStream() {
return err;
}
 
public boolean isAlive() {
return alive;
}
 
public int exitValue() {
return 0;
}
 
public void destroy() {
IoUtils.closeQuietly(in);
IoUtils.closeQuietly(out);
IoUtils.closeQuietly(err);
}
 
public boolean isStarted() {
return started;
}
 
public Map<String, String> getEnv() {
return env;
}
 
public void setAlive(boolean alive) {
this.alive = alive;
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/BogusChannel.java
0,0 → 1,52
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import java.io.IOException;
 
import org.apache.sshd.client.future.DefaultOpenFuture;
import org.apache.sshd.client.future.OpenFuture;
import org.apache.sshd.common.channel.AbstractChannel;
import org.apache.sshd.common.util.Buffer;
 
public class BogusChannel extends AbstractChannel {
 
@Override
protected void doWriteData(byte[] data, int off, int len) throws IOException {
}
 
@Override
protected void doWriteExtendedData(byte[] data, int off, int len) throws IOException {
}
 
@Override
protected void sendWindowAdjust(int len) throws IOException {
}
 
public OpenFuture open(int recipient, int rwsize, int rmpsize, Buffer buffer) {
return new DefaultOpenFuture(this.lock);
}
 
public void handleOpenSuccess(int recipient, int rwsize, int rmpsize, Buffer buffer) throws IOException {
}
 
public void handleOpenFailure(Buffer buffer) throws IOException {
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/BaseTest.java
0,0 → 1,48
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import org.junit.Rule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public abstract class BaseTest extends TestWatcher {
 
@Rule
public TestWatcher rule = this;
 
private long startTime;
 
@Override
protected void starting(Description description) {
System.out.println("\nStarting " + description.getClassName() + ":" + description.getMethodName() + "...\n");
startTime = System.currentTimeMillis();
}
 
@Override
protected void finished(Description description) {
long duration = System.currentTimeMillis() - startTime;
System.out.println("\nFinished " + description.getClassName() + ":" + description.getMethodName() + " in " + duration + " ms\n");
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/TeeOutputStream.java
0,0 → 1,64
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import java.io.IOException;
import java.io.OutputStream;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class TeeOutputStream extends OutputStream {
 
private OutputStream[] tees;
 
public TeeOutputStream(OutputStream... tees) {
this.tees = tees;
}
 
@Override
public void write(int b) throws IOException {
for (OutputStream s : tees) {
s.write(b);
}
}
 
@Override
public void write(byte[] b, int off, int len) throws IOException {
for (OutputStream s : tees) {
s.write(b, off, len);
}
}
 
@Override
public void flush() throws IOException {
for (OutputStream s : tees) {
s.flush();
}
}
 
@Override
public void close() throws IOException {
for (OutputStream s : tees) {
s.close();
}
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/AsyncEchoShellFactory.java
0,0 → 1,140
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
 
import org.apache.sshd.common.Factory;
import org.apache.sshd.common.channel.BufferedIoOutputStream;
import org.apache.sshd.common.future.CloseFuture;
import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.IoInputStream;
import org.apache.sshd.common.io.IoOutputStream;
import org.apache.sshd.common.io.IoWriteFuture;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.server.AsyncCommand;
import org.apache.sshd.server.ChannelSessionAware;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
import org.apache.sshd.server.channel.ChannelDataReceiver;
import org.apache.sshd.server.channel.ChannelSession;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class AsyncEchoShellFactory implements Factory<Command> {
 
public Command create() {
return new EchoShell();
}
 
public static class EchoShell implements AsyncCommand, ChannelDataReceiver, ChannelSessionAware {
 
private IoOutputStream out;
private IoOutputStream err;
private ExitCallback callback;
private Environment environment;
private ChannelSession session;
private StringBuilder buffer = new StringBuilder();
 
public IoOutputStream getOut() {
return out;
}
 
public IoOutputStream getErr() {
return err;
}
 
public Environment getEnvironment() {
return environment;
}
 
public void setInputStream(InputStream in) {
}
 
public void setOutputStream(OutputStream out) {
}
 
public void setErrorStream(OutputStream err) {
}
 
public void setIoInputStream(IoInputStream in) {
}
 
public void setIoOutputStream(IoOutputStream out) {
this.out = new BufferedIoOutputStream(out);
}
 
public void setIoErrorStream(IoOutputStream err) {
this.err = new BufferedIoOutputStream(err);
}
 
public void setExitCallback(ExitCallback callback) {
this.callback = callback;
}
 
public void setChannelSession(ChannelSession session) {
this.session = session;
}
 
public void start(Environment env) throws IOException {
environment = env;
session.setDataReceiver(this);
}
 
public void close() throws IOException {
out.close(false).addListener(new SshFutureListener<CloseFuture>() {
public void operationComplete(CloseFuture future) {
callback.onExit(0);
}
});
}
 
public void destroy() {
}
 
public int data(final ChannelSession channel, byte[] buf, int start, int len) throws IOException {
buffer.append(new String(buf, start, len));
for (int i = 0; i < buffer.length(); i++) {
if (buffer.charAt(i) == '\n') {
final String s = buffer.substring(0, i + 1);
final byte[] bytes = s.getBytes();
out.write(new Buffer(bytes)).addListener(new SshFutureListener<IoWriteFuture>() {
public void operationComplete(IoWriteFuture future) {
try {
channel.getLocalWindow().consumeAndCheck(bytes.length);
} catch (IOException e) {
channel.getSession().exceptionCaught(e);
}
}
});
buffer = new StringBuilder(buffer.substring(i + 1));
i = 0;
}
}
return 0;
}
}
 
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/BogusPasswordAuthenticator.java
0,0 → 1,34
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import org.apache.sshd.server.PasswordAuthenticator;
import org.apache.sshd.server.session.ServerSession;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class BogusPasswordAuthenticator implements PasswordAuthenticator {
 
public boolean authenticate(String username, String password, ServerSession session) {
return username != null && username.equals(password);
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/util/EchoShellFactory.java
0,0 → 1,118
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.util;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.OutputStream;
 
import org.apache.sshd.common.Factory;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
 
/**
* TODO Add javadoc
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class EchoShellFactory implements Factory<Command> {
 
public Command create() {
return new EchoShell();
}
 
public static class EchoShell implements Command, Runnable {
 
private InputStream in;
private OutputStream out;
private OutputStream err;
private ExitCallback callback;
private Environment environment;
private Thread thread;
 
public InputStream getIn() {
return in;
}
 
public OutputStream getOut() {
return out;
}
 
public OutputStream getErr() {
return err;
}
 
public Environment getEnvironment() {
return environment;
}
 
public void setInputStream(InputStream in) {
this.in = in;
}
 
public void setOutputStream(OutputStream out) {
this.out = out;
}
 
public void setErrorStream(OutputStream err) {
this.err = err;
}
 
public void setExitCallback(ExitCallback callback) {
this.callback = callback;
}
 
public void start(Environment env) throws IOException {
environment = env;
thread = new Thread(this, "EchoShell");
thread.start();
}
 
public void destroy() {
thread.interrupt();
}
 
public void run() {
BufferedReader r = new BufferedReader(new InputStreamReader(in));
try {
for (;;) {
String s = r.readLine();
if (s == null) {
return;
}
out.write((s + "\n").getBytes());
out.flush();
if ("exit".equals(s)) {
return;
}
}
} catch (InterruptedIOException e) {
// Ignore
} catch (Exception e) {
e.printStackTrace();
} finally {
callback.onExit(0);
}
}
}
}
/trunk/rmsshd/sshd-core/src/test/java/org/apache/sshd/AgentTest.java
0,0 → 1,202
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.KeyPair;
import java.security.PublicKey;
import java.util.List;
 
import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.agent.local.LocalAgentFactory;
import org.apache.sshd.agent.local.ProxyAgentFactory;
import org.apache.sshd.agent.unix.AgentClient;
import org.apache.sshd.agent.unix.AgentServer;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.util.BaseTest;
import org.apache.sshd.util.BogusPasswordAuthenticator;
import org.apache.sshd.util.BogusPublickeyAuthenticator;
import org.apache.sshd.util.EchoShellFactory;
import org.apache.sshd.util.Utils;
import org.junit.Test;
 
import static org.apache.sshd.util.Utils.createTestKeyPairProvider;
import static org.apache.sshd.util.Utils.getFreePort;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeThat;
 
public class AgentTest extends BaseTest {
 
@Test
public void testAgent() throws Exception {
// TODO: revisit this test to work without BC
if (!SecurityUtils.isBouncyCastleRegistered()) {
return;
}
 
AgentServer agent = new AgentServer();
String authSocket;
try {
authSocket = agent.start();
} catch (UnsatisfiedLinkError e) {
// the native library is not available, so these tests should be skipped
authSocket = null;
}
assumeThat(authSocket, notNullValue());
 
SshAgent client = new AgentClient(authSocket);
List<SshAgent.Pair<PublicKey, String>> keys = client.getIdentities();
assertNotNull(keys);
assertEquals(0, keys.size());
 
KeyPair k = Utils.createTestHostKeyProvider().loadKey(KeyPairProvider.SSH_RSA);
client.addIdentity(k, "");
keys = client.getIdentities();
assertNotNull(keys);
assertEquals(1, keys.size());
 
client.removeIdentity(k.getPublic());
keys = client.getIdentities();
assertNotNull(keys);
assertEquals(0, keys.size());
 
client.removeAllIdentities();
 
client.close();
 
agent.close();
}
 
@Test
public void testAgentForwarding() throws Exception {
// TODO: revisit this test to work without BC
if (!SecurityUtils.isBouncyCastleRegistered()) {
return;
}
 
int port1 = getFreePort();
int port2 = getFreePort();
 
TestEchoShellFactory shellFactory = new TestEchoShellFactory();
ProxyAgentFactory agentFactory = new ProxyAgentFactory();
LocalAgentFactory localAgentFactory = new LocalAgentFactory();
 
KeyPair pair = createTestKeyPairProvider("dsaprivkey.pem").loadKey(KeyPairProvider.SSH_DSS);
localAgentFactory.getAgent().addIdentity(pair, "smx");
 
SshServer sshd1 = SshServer.setUpDefaultServer();
sshd1.setPort(port1);
sshd1.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd1.setShellFactory(shellFactory);
sshd1.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd1.setPublickeyAuthenticator(new BogusPublickeyAuthenticator());
sshd1.setAgentFactory(agentFactory);
sshd1.start();
 
SshServer sshd2 = SshServer.setUpDefaultServer();
sshd2.setPort(port2);
sshd2.setKeyPairProvider(Utils.createTestHostKeyProvider());
sshd2.setShellFactory(new TestEchoShellFactory());
sshd2.setPasswordAuthenticator(new BogusPasswordAuthenticator());
sshd2.setPublickeyAuthenticator(new BogusPublickeyAuthenticator());
sshd2.setAgentFactory(new ProxyAgentFactory());
sshd2.start();
 
SshClient client1 = SshClient.setUpDefaultClient();
client1.setAgentFactory(localAgentFactory);
client1.start();
ClientSession session1 = client1.connect("smx", "localhost", port1).await().getSession();
session1.auth().verify();
ChannelShell channel1 = session1.createShellChannel();
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
channel1.setOut(out);
channel1.setErr(err);
channel1.setAgentForwarding(true);
channel1.open().await();
OutputStream pipedIn = channel1.getInvertedIn();
 
synchronized (shellFactory.shell) {
System.out.println("Possibly waiting for remote shell to start");
if (!shellFactory.shell.started) {
shellFactory.shell.wait();
}
}
 
SshClient client2 = SshClient.setUpDefaultClient();
client2.setAgentFactory(agentFactory);
client2.getProperties().putAll(shellFactory.shell.getEnvironment().getEnv());
client2.start();
ClientSession session2 = client2.connect("smx", "localhost", port2).await().getSession();
session2.auth().verify();
ChannelShell channel2 = session2.createShellChannel();
channel2.setIn(shellFactory.shell.getIn());
channel2.setOut(shellFactory.shell.getOut());
channel2.setErr(shellFactory.shell.getErr());
channel2.setAgentForwarding(true);
channel2.open().await();
 
pipedIn.write("foo\n".getBytes());
pipedIn.flush();
 
Thread.sleep(1000);
 
System.out.println(out.toString());
System.err.println(err.toString());
 
sshd1.stop(true);
sshd2.stop(true);
client1.stop();
client2.stop();
 
}
 
public static class TestEchoShellFactory extends EchoShellFactory {
 
TestEchoShell shell = new TestEchoShell();
 
@Override
public Command create() {
return shell;
}
 
public class TestEchoShell extends EchoShell {
 
boolean started;
 
@Override
public synchronized void start(Environment env) throws IOException {
super.start(env);
started = true;
notifyAll();
}
 
}
}
 
}
/trunk/rmsshd/sshd-core/src/test/resources/dsaprivkey.pem
0,0 → 1,27
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQDEA7leYDKyJOFJU3h0uPpWN52iTpJk8+IM53Vc/91k7pBIjjka
+MP24BMh+sI2SRhxg2AtvwnzRRBVJWzEA4+tuCI6WukgeDQtSNp3YuWzOMefZ6Wb
SAk1Y4goZb7nyqV9HZSFNSqUFQRZM10L768VURBlerNqR//GqdVd8bp7lwIVAM39
h6x2DeXbqUM8iOi01bh5jpLFAoGAEi1oFGFMEZXH/hCX+Y2VE5WvR+fBaoS9WuZl
3E0wsWPzQhbL13yD+6Htxd3XoQvrHnzyrIgi2AiAmr3mLokQbZ3d92IxEBcNB/0p
nVi020TXSeD/lWkpk5FRvgBiJ82/LeC2Lj6cssznX73aLUhR0tsSoJoXxas0sQKa
/UJgq5wCgYAtgeY99J0JxplWGSyGY/1DUpgzhdgpLdDA/o/qIjBEeHXN0QX4Ajoa
vHggJ2SwNtAxbQedBxqmB3mquFRtpfEP5zGzsVx5HHnljSH8u0SqEoLnYKFpluwh
tZ/Q3F2NHslXw8Hw+pIaPe4PAINQPAu3U+BknNUkGpLg8zU6h5+B+wIVAKRqeps1
Xl7MxZcSZp7FnmmmMecB
-----END DSA PRIVATE KEY-----
/trunk/rmsshd/sshd-core/src/test/resources/spring.xml
0,0 → 1,98
<?xml version="1.0" encoding="UTF-8"?>
<!--
 
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
 
<bean name="sshServer" class="org.apache.sshd.SshServer" factory-method="setUpDefaultServer" init-method="start" destroy-method="stop">
<!--property name="port" value="8000" /-->
<property name="shellFactory">
<bean class="org.apache.sshd.server.shell.ProcessShellFactory">
<property name="command">
<list>
<value>/bin/sh</value>
<value>-i</value>
</list>
</property>
</bean>
</property>
<property name="keyPairProvider">
<bean class="org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider" />
</property>
<property name="passwordAuthenticator">
<bean class="org.apache.sshd.util.BogusPasswordAuthenticator" />
</property>
<property name="publickeyAuthenticator">
<bean class="org.apache.sshd.util.BogusPublickeyAuthenticator" />
</property>
<!-- Standard properties -->
<!--
<property name="channelFactories">
<list>
<bean class="org.apache.sshd.server.channel.ChannelSession$Factory" />
</list>
</property>
<property name="cipherFactories">
<list>
<bean class="org.apache.sshd.common.cipher.AES128CBC$Factory" />
<bean class="org.apache.sshd.common.cipher.TripleDESCBC$Factory" />
<bean class="org.apache.sshd.common.cipher.BlowfishCBC$Factory" />
<bean class="org.apache.sshd.common.cipher.AES192CBC$Factory" />
<bean class="org.apache.sshd.common.cipher.AES256CBC$Factory" />
</list>
</property>
<property name="compressionFactories">
<list>
<bean class="org.apache.sshd.common.compression.CompressionNone$Factory" />
</list>
</property>
<property name="keyExchangeFactories">
<list>
<bean class="org.apache.sshd.server.kex.DHG1$Factory" />
</list>
</property>
<property name="macFactories">
<list>
<bean class="org.apache.sshd.common.mac.HMACMD5$Factory" />
<bean class="org.apache.sshd.common.mac.HMACSHA1$Factory" />
<bean class="org.apache.sshd.common.mac.HMACMD596$Factory" />
<bean class="org.apache.sshd.common.mac.HMACSHA196$Factory" />
</list>
</property>
<property name="randomFactory">
<bean class="org.apache.sshd.common.random.JceRandom$Factory" />
</property>
<property name="userAuthFactories">
<list>
<bean class="org.apache.sshd.server.auth.UserAuthPublicKey$Factory" />
<bean class="org.apache.sshd.server.auth.UserAuthPassword$Factory" />
</list>
</property>
<property name="signatureFactories">
<list>
<bean class="org.apache.sshd.common.signature.SignatureDSA$Factory" />
<bean class="org.apache.sshd.common.signature.SignatureRSA$Factory" />
</list>
</property>
-->
</bean>
 
</beans>
/trunk/rmsshd/sshd-core/src/test/resources/hostkey.pem
0,0 → 1,30
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
 
http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDdfIWeSV4o68dRrKSzFd/Bk51E65UTmmSrmW0O1ohtzi6HzsDP
jXgCtlTt3FqTcfFfI92IlTr4JWqC9UK1QT1ZTeng0MkPQmv68hDANHbt5CpETZHj
W5q4OOgWhVvj5IyOC2NZHtKlJBkdsMAa15ouOOJLzBvAvbqOR/yUROsEiQIDAQAB
AoGBANG3JDW6NoP8rF/zXoeLgLCj+tfVUPSczhGFVrQkAk4mWfyRkhN0WlwHFOec
K89MpkV1ij/XPVzU4MNbQ2yod1KiDylzvweYv+EaEhASCmYNs6LS03punml42SL9
97tOmWfVJXxlQoLiY6jHPU97vTc65k8gL+gmmrpchsW0aqmZAkEA/c8zfmKvY37T
cxcLLwzwsqqH7g2KZGTf9aRmx2ebdW+QKviJJhbdluDgl1TNNFj5vCLznFDRHiqJ
wq0wkZ39cwJBAN9l5v3kdXj21UrurNPdlV0n2GZBt2vblooQC37XHF97r2zM7Ou+
Lg6MyfJClyguhWL9dxnGbf3btQ0l3KDstxMCQCRaiEqjAfIjWVATzeNIXDWLHXso
b1kf5cA+cwY+vdKdTy4IeUR+Y/DXdvPWDqpf0C11aCVMohdLCn5a5ikFUycCQDhV
K/BuAallJNfmY7JxN87r00fF3ojWMJnT/fIYMFFrkQrwifXQWTDWE76BSDibsosJ
u1TGksnm8zrDh2UVC/0CQFrHTiSl/3DHvWAbOJawGKg46cnlDcAhSyV8Frs8/dlP
7YGG3eqkw++lsghqmFO6mRUTKsBmiiB2wgLGhL5pyYY=
-----END RSA PRIVATE KEY-----
/trunk/rmsshd/sshd-core/src/test/resources/org/apache/sshd/common/util/stty-output-1.txt
0,0 → 1,10
speed 38400 baud; rows 25; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon ixoff
-iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon -iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
/trunk/rmsshd/sshd-core/src/test/resources/org/apache/sshd/common/util/stty-output-2.txt
0,0 → 1,13
speed 9600 baud; 50 rows; 160 columns;
lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
-echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
-extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8
-ignbrk brkint -inpck -ignpar -parmrk
oflags: opost onlcr -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
-dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T;
stop = ^S; susp = ^Z; time = 0; werase = ^W;
/trunk/rmsshd/sshd-core/src/test/resources/log4j.properties
0,0 → 1,38
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
#
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
 
#
# The logging properties used during tests..
#
log4j.rootLogger=INFO, stdout
#log4j.logger.org.apache.sshd=TRACE
#log4j.logger.org.apache.sshd.common.channel.Window=DEBUG
 
# CONSOLE appender
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d | %-5.5p | %-16.16t | %-32.32c{1} | %-64.64C %4L | %m%n
 
# File appender
log4j.appender.out=org.apache.log4j.FileAppender
log4j.appender.out.layout=org.apache.log4j.PatternLayout
log4j.appender.out.layout.ConversionPattern=%d | %-5.5p | %-16.16t | %-32.32c{1} | %-64.64C %4L | %m%n
log4j.appender.out.file=target/sshd-tests.log
log4j.appender.out.append=true
/trunk/rmsshd/sshd-core/src/main/java/org/apache/sshd/ClientSession.java
0,0 → 1,216
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.IOException;
import java.security.KeyPair;
import java.util.Map;
 
import org.apache.sshd.client.ClientFactoryManager;
import org.apache.sshd.client.ScpClient;
import org.apache.sshd.client.SftpClient;
import org.apache.sshd.client.UserInteraction;
import org.apache.sshd.client.channel.ChannelDirectTcpip;
import org.apache.sshd.client.channel.ChannelExec;
import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.channel.ChannelSubsystem;
import org.apache.sshd.client.future.AuthFuture;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.SshdSocketAddress;
import org.apache.sshd.common.future.CloseFuture;
 
/**
* An authenticated session to a given SSH server
*
* A client session is established using the {@link SshClient}.
* Once the session has been created, the user has to authenticate
* using either {@link #authPassword(String, String)} or
* {@link #authPublicKey(String, java.security.KeyPair)}.
*
* From this session, channels can be created using the
* {@link #createChannel(String)} method. Multiple channels can
* be created on a given session concurrently.
*
* When using the client in an interactive mode, the
* {@link #waitFor(int, long)} method can be used to listen to specific
* events such as the session being established, authenticated or closed.
*
* When a given session is no longer used, it must be closed using the
* {@link #close(boolean)} method.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public interface ClientSession extends Session {
 
int TIMEOUT = 0x0001;
int CLOSED = 0x0002;
int WAIT_AUTH = 0x0004;
int AUTHED = 0x0008;
 
void addPasswordIdentity(String password);
void addPublicKeyIdentity(KeyPair key);
 
UserInteraction getUserInteraction();
void setUserInteraction(UserInteraction userInteraction);
 
/**
* Starts the authentication process.
* User identities will be tried until the server successfully authenticate the user.
* User identities must be provided before calling this method using
* {@link #addPasswordIdentity(String)} or {@link #addPublicKeyIdentity(java.security.KeyPair)}.
*
* @return the authentication future
* @throws IOException
* @see {@link #addPasswordIdentity(String)}
* @see {@link #addPublicKeyIdentity(java.security.KeyPair)}
*/
AuthFuture auth() throws IOException;
 
/**
* Authenticate the session with the given username using an ssh agent.
*
* @deprecated Use {@link #auth()} instead
* @see {@link #auth()}
*/
@Deprecated
AuthFuture authAgent(String username) throws IOException;
 
/**
* Authenticate the session with the given username and password.
*
* @deprecated Use {@link #auth()} instead
* @see {@link #auth()}
*/
@Deprecated
AuthFuture authPassword(String username, String password) throws IOException;
 
/**
* Authenticate the session with the given username and password.
*
* @deprecated Use {@link #auth()} instead
* @see {@link #auth()}
*/
@Deprecated
AuthFuture authInteractive(String username, String password) throws IOException;
 
/**
* Authenticate the session with the given username and public key.
*
* @deprecated Use {@link #auth()} instead
* @see {@link #auth()}
*/
@Deprecated
AuthFuture authPublicKey(String username, KeyPair key) throws IOException;
 
/**
* Create a channel of the given type.
* Same as calling <code>createChannel(type, null)</code>.
*/
ClientChannel createChannel(String type) throws IOException;
 
/**
* Create a channel of the given type and subtype.
*/
ClientChannel createChannel(String type, String subType) throws IOException;
 
/**
* Create a channel to start a shell.
*/
ChannelShell createShellChannel() throws IOException;
 
/**
* Create a channel to execute a command.
*/
ChannelExec createExecChannel(String command) throws IOException;
 
/**
* Create a subsystem channel.
*/
ChannelSubsystem createSubsystemChannel(String subsystem) throws IOException;
 
/**
* Create a direct tcp-ip channel which can be used to stream data to a remote port from the server.
*/
ChannelDirectTcpip createDirectTcpipChannel(SshdSocketAddress local, SshdSocketAddress remote) throws IOException;
 
/**
* Create an SCP client from this session.
*/
ScpClient createScpClient();
 
/**
* Create an SFTP client from this session.
*/
SftpClient createSftpClient() throws IOException;
 
/**
* Start forwarding the given local address on the client to the given address on the server.
*/
SshdSocketAddress startLocalPortForwarding(SshdSocketAddress local, SshdSocketAddress remote) throws IOException;
 
/**
* Stop forwarding the given local address.
*/
void stopLocalPortForwarding(SshdSocketAddress local) throws IOException;
 
/**
* Start forwarding tcpip from the given address on the server to the
* given address on the client.
*
* The remote host name is the address to bind to on the server:
* <ul>
* <li>"" means that connections are to be accepted on all protocol families
* supported by the SSH implementation</li>
* <li>"0.0.0.0" means to listen on all IPv4 addresses</li>
* <li>"::" means to listen on all IPv6 addresses</li>
* <li>"localhost" means to listen on all protocol families supported by the SSH
* implementation on loopback addresses only, [RFC3330] and RFC3513]</li>
* <li>"127.0.0.1" and "::1" indicate listening on the loopback interfaces for
* IPv4 and IPv6 respectively</li>
* </ul>
*
*/
SshdSocketAddress startRemotePortForwarding(SshdSocketAddress remote, SshdSocketAddress local) throws IOException;
 
/**
* Stop forwarding of the given remote address.
*/
void stopRemotePortForwarding(SshdSocketAddress remote) throws IOException;
 
/**
* Wait for a specific state.
*/
int waitFor(int mask, long timeout);
 
/**
* Close this session.
*/
CloseFuture close(boolean immediately);
 
/**
* Access to the metadata.
*/
Map<Object, Object> getMetadataMap();
 
/**
* Return ClientFactoryManager for this session.
*/
ClientFactoryManager getFactoryManager();
 
}
/trunk/rmsshd/sshd-core/src/main/java/org/apache/sshd/SshBuilder.java
0,0 → 1,415
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.security.InvalidKeyException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
 
import org.apache.sshd.client.ServerKeyVerifier;
import org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier;
import org.apache.sshd.common.AbstractFactoryManager;
import org.apache.sshd.common.Channel;
import org.apache.sshd.common.Cipher;
import org.apache.sshd.common.Compression;
import org.apache.sshd.common.Factory;
import org.apache.sshd.common.KeyExchange;
import org.apache.sshd.common.Mac;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Random;
import org.apache.sshd.common.RequestHandler;
import org.apache.sshd.common.Signature;
import org.apache.sshd.common.TcpipForwarderFactory;
import org.apache.sshd.common.cipher.AES128CBC;
import org.apache.sshd.common.cipher.AES128CTR;
import org.apache.sshd.common.cipher.AES192CBC;
import org.apache.sshd.common.cipher.AES192CTR;
import org.apache.sshd.common.cipher.AES256CBC;
import org.apache.sshd.common.cipher.AES256CTR;
import org.apache.sshd.common.cipher.ARCFOUR128;
import org.apache.sshd.common.cipher.ARCFOUR256;
import org.apache.sshd.common.cipher.BlowfishCBC;
import org.apache.sshd.common.cipher.TripleDESCBC;
import org.apache.sshd.common.compression.CompressionNone;
import org.apache.sshd.common.file.FileSystemFactory;
import org.apache.sshd.common.file.nativefs.NativeFileSystemFactory;
import org.apache.sshd.common.forward.DefaultTcpipForwarderFactory;
import org.apache.sshd.common.forward.TcpipServerChannel;
import org.apache.sshd.common.mac.HMACMD5;
import org.apache.sshd.common.mac.HMACMD596;
import org.apache.sshd.common.mac.HMACSHA1;
import org.apache.sshd.common.mac.HMACSHA196;
import org.apache.sshd.common.mac.HMACSHA256;
import org.apache.sshd.common.mac.HMACSHA512;
import org.apache.sshd.common.random.BouncyCastleRandom;
import org.apache.sshd.common.random.JceRandom;
import org.apache.sshd.common.random.SingletonRandomFactory;
import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.signature.SignatureDSA;
import org.apache.sshd.common.signature.SignatureECDSA;
import org.apache.sshd.common.signature.SignatureRSA;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.server.channel.ChannelSession;
import org.apache.sshd.server.global.CancelTcpipForwardHandler;
import org.apache.sshd.server.global.KeepAliveHandler;
import org.apache.sshd.server.global.NoMoreSessionsHandler;
import org.apache.sshd.server.global.TcpipForwardHandler;
 
/**
* A builder object for creating SshServer instances.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class SshBuilder {
 
public static ClientBuilder client() {
return new ClientBuilder();
}
 
public static ServerBuilder server() {
return new ServerBuilder();
}
 
protected static class BaseBuilder<T extends AbstractFactoryManager, S extends BaseBuilder<T, S>> {
 
protected Factory<T> factory = null;
 
protected List<NamedFactory<KeyExchange>> keyExchangeFactories = null;
protected List<NamedFactory<Cipher>> cipherFactories = null;
protected List<NamedFactory<Compression>> compressionFactories = null;
protected List<NamedFactory<Mac>> macFactories = null;
protected List<NamedFactory<Signature>> signatureFactories = null;
protected Factory<Random> randomFactory = null;
protected List<NamedFactory<Channel>> channelFactories = null;
protected FileSystemFactory fileSystemFactory = null;
protected TcpipForwarderFactory tcpipForwarderFactory = null;
protected List<RequestHandler<ConnectionService>> globalRequestHandlers = null;
 
protected S fillWithDefaultValues() {
if (SecurityUtils.isBouncyCastleRegistered()) {
if (signatureFactories == null) {
signatureFactories = Arrays.asList(
new SignatureECDSA.NISTP256Factory(),
new SignatureECDSA.NISTP384Factory(),
new SignatureECDSA.NISTP521Factory(),
new SignatureDSA.Factory(),
new SignatureRSA.Factory());
}
if (randomFactory == null) {
randomFactory = new SingletonRandomFactory(new BouncyCastleRandom.Factory());
}
// EC keys are not supported until OpenJDK 7
} else if (SecurityUtils.hasEcc()) {
if (signatureFactories == null) {
signatureFactories = Arrays.asList(
new SignatureECDSA.NISTP256Factory(),
new SignatureECDSA.NISTP384Factory(),
new SignatureECDSA.NISTP521Factory(),
new SignatureDSA.Factory(),
new SignatureRSA.Factory());
}
if (randomFactory == null) {
randomFactory = new SingletonRandomFactory(new JceRandom.Factory());
}
} else {
if (signatureFactories == null) {
signatureFactories = Arrays.asList(
new SignatureDSA.Factory(),
new SignatureRSA.Factory());
}
if (randomFactory == null) {
randomFactory = new SingletonRandomFactory(new JceRandom.Factory());
}
}
 
if (cipherFactories == null) {
cipherFactories = setUpDefaultCiphers();
}
 
// Compression is not enabled by default
//if (compressionFactories == null) {
// compressionFactories = Arrays.<NamedFactory<Compression>>asList(
// new CompressionNone.Factory(),
// new CompressionZlib.Factory(),
// new CompressionDelayedZlib.Factory());
//}
if (compressionFactories == null) {
compressionFactories = Arrays.<NamedFactory<Compression>>asList(
new CompressionNone.Factory());
}
if (macFactories == null) {
macFactories = Arrays.asList(
new HMACSHA256.Factory(),
new HMACSHA512.Factory(),
new HMACSHA1.Factory(),
new HMACMD5.Factory(),
new HMACSHA196.Factory(),
new HMACMD596.Factory());
}
if (fileSystemFactory == null) {
fileSystemFactory = new NativeFileSystemFactory();
}
if (tcpipForwarderFactory == null) {
tcpipForwarderFactory = new DefaultTcpipForwarderFactory();
}
 
return me();
}
 
public S keyExchangeFactories(List<NamedFactory<KeyExchange>> keyExchangeFactories) {
this.keyExchangeFactories = keyExchangeFactories;
return me();
}
 
public S signatureFactories(final List<NamedFactory<Signature>> signatureFactories) {
this.signatureFactories = signatureFactories;
return me();
}
 
public S randomFactory(final Factory<Random> randomFactory) {
this.randomFactory = randomFactory;
return me();
}
 
public S cipherFactories(final List<NamedFactory<Cipher>> cipherFactories) {
this.cipherFactories = cipherFactories;
return me();
}
 
public S compressionFactories(final List<NamedFactory<Compression>> compressionFactories) {
this.compressionFactories = compressionFactories;
return me();
}
 
public S macFactories(final List<NamedFactory<Mac>> macFactories) {
this.macFactories = macFactories;
return me();
}
 
public S channelFactories(final List<NamedFactory<Channel>> channelFactories) {
this.channelFactories = channelFactories;
return me();
}
 
public S fileSystemFactory(final FileSystemFactory fileSystemFactory) {
this.fileSystemFactory = fileSystemFactory;
return me();
}
 
public S tcpipForwarderFactory(final TcpipForwarderFactory tcpipForwarderFactory) {
this.tcpipForwarderFactory = tcpipForwarderFactory;
return me();
}
 
public S globalRequestHandlers(final List<RequestHandler<ConnectionService>> globalRequestHandlers) {
this.globalRequestHandlers = globalRequestHandlers;
return me();
}
 
public S factory(final Factory<T> factory) {
this.factory = factory;
return me();
}
 
public T build(final boolean isFillWithDefaultValues) {
if (isFillWithDefaultValues) {
fillWithDefaultValues();
}
 
T ssh = factory.create();
 
ssh.setKeyExchangeFactories(keyExchangeFactories);
ssh.setSignatureFactories(signatureFactories);
ssh.setRandomFactory(randomFactory);
ssh.setCipherFactories(cipherFactories);
ssh.setCompressionFactories(compressionFactories);
ssh.setMacFactories(macFactories);
ssh.setChannelFactories(channelFactories);
ssh.setFileSystemFactory(fileSystemFactory);
ssh.setTcpipForwarderFactory(tcpipForwarderFactory);
ssh.setGlobalRequestHandlers(globalRequestHandlers);
 
return ssh;
}
 
public T build() {
return build(true);
}
 
@SuppressWarnings("unchecked")
protected S me() {
return (S) this;
}
 
protected static List<NamedFactory<Cipher>> setUpDefaultCiphers() {
List<NamedFactory<Cipher>> avail = new LinkedList<NamedFactory<Cipher>>();
avail.add(new AES128CTR.Factory());
avail.add(new AES192CTR.Factory());
avail.add(new AES256CTR.Factory());
avail.add(new ARCFOUR128.Factory());
avail.add(new ARCFOUR256.Factory());
avail.add(new AES128CBC.Factory());
avail.add(new TripleDESCBC.Factory());
avail.add(new BlowfishCBC.Factory());
avail.add(new AES192CBC.Factory());
avail.add(new AES256CBC.Factory());
 
for (Iterator<NamedFactory<Cipher>> i = avail.iterator(); i.hasNext(); ) {
final NamedFactory<Cipher> f = i.next();
try {
final Cipher c = f.create();
final byte[] key = new byte[c.getBlockSize()];
final byte[] iv = new byte[c.getIVSize()];
c.init(Cipher.Mode.Encrypt, key, iv);
} catch (InvalidKeyException e) {
i.remove();
} catch (Exception e) {
i.remove();
}
}
return avail;
}
}
 
/**
* SshClient builder
*/
public static class ClientBuilder extends BaseBuilder<SshClient, ClientBuilder> {
 
protected ServerKeyVerifier serverKeyVerifier;
 
public ClientBuilder serverKeyVerifier(ServerKeyVerifier serverKeyVerifier) {
this.serverKeyVerifier = serverKeyVerifier;
return me();
}
 
@Override
protected ClientBuilder fillWithDefaultValues() {
super.fillWithDefaultValues();
if (SecurityUtils.isBouncyCastleRegistered()) {
if (keyExchangeFactories == null) {
keyExchangeFactories = Arrays.asList(
new org.apache.sshd.client.kex.DHGEX256.Factory(),
new org.apache.sshd.client.kex.DHGEX.Factory(),
new org.apache.sshd.client.kex.ECDHP256.Factory(),
new org.apache.sshd.client.kex.ECDHP384.Factory(),
new org.apache.sshd.client.kex.ECDHP521.Factory(),
new org.apache.sshd.client.kex.DHG14.Factory(),
new org.apache.sshd.client.kex.DHG1.Factory());
}
// EC keys are not supported until OpenJDK 7
} else if (SecurityUtils.hasEcc()) {
if (keyExchangeFactories == null) {
keyExchangeFactories = Arrays.asList(
new org.apache.sshd.client.kex.DHGEX256.Factory(),
new org.apache.sshd.client.kex.DHGEX.Factory(),
new org.apache.sshd.client.kex.ECDHP256.Factory(),
new org.apache.sshd.client.kex.ECDHP384.Factory(),
new org.apache.sshd.client.kex.ECDHP521.Factory(),
new org.apache.sshd.client.kex.DHG1.Factory());
}
} else {
if (keyExchangeFactories == null) {
keyExchangeFactories = Arrays.asList(
new org.apache.sshd.client.kex.DHGEX256.Factory(),
new org.apache.sshd.client.kex.DHGEX.Factory(),
new org.apache.sshd.client.kex.DHG1.Factory());
}
}
if (channelFactories == null) {
channelFactories = Arrays.<NamedFactory<Channel>>asList(
new TcpipServerChannel.ForwardedTcpipFactory());
}
if (serverKeyVerifier == null) {
serverKeyVerifier = AcceptAllServerKeyVerifier.INSTANCE;
}
if (factory == null) {
factory = SshClient.DEFAULT_SSH_CLIENT_FACTORY;
}
return me();
}
 
@Override
public SshClient build(boolean isFillWithDefaultValues) {
SshClient client = super.build(isFillWithDefaultValues);
client.setServerKeyVerifier(serverKeyVerifier);
return client;
}
}
 
/**
* SshServer builder
*/
public static class ServerBuilder extends BaseBuilder<SshServer, ServerBuilder> {
 
@Override
protected ServerBuilder fillWithDefaultValues() {
super.fillWithDefaultValues();
if (SecurityUtils.isBouncyCastleRegistered()) {
if (keyExchangeFactories == null) {
keyExchangeFactories = Arrays.asList(
new org.apache.sshd.server.kex.DHGEX256.Factory(),
new org.apache.sshd.server.kex.DHGEX.Factory(),
new org.apache.sshd.server.kex.ECDHP256.Factory(),
new org.apache.sshd.server.kex.ECDHP384.Factory(),
new org.apache.sshd.server.kex.ECDHP521.Factory(),
new org.apache.sshd.server.kex.DHG14.Factory(),
new org.apache.sshd.server.kex.DHG1.Factory());
}
// EC keys are not supported until OpenJDK 7
} else if (SecurityUtils.hasEcc()) {
if (keyExchangeFactories == null) {
keyExchangeFactories = Arrays.asList(
new org.apache.sshd.server.kex.DHGEX256.Factory(),
new org.apache.sshd.server.kex.DHGEX.Factory(),
new org.apache.sshd.server.kex.ECDHP256.Factory(),
new org.apache.sshd.server.kex.ECDHP384.Factory(),
new org.apache.sshd.server.kex.ECDHP521.Factory(),
new org.apache.sshd.server.kex.DHG1.Factory());
}
} else {
if (keyExchangeFactories == null) {
keyExchangeFactories = Arrays.asList(
new org.apache.sshd.server.kex.DHGEX256.Factory(),
new org.apache.sshd.server.kex.DHGEX.Factory(),
new org.apache.sshd.server.kex.DHG1.Factory());
}
}
if (channelFactories == null) {
channelFactories = Arrays.asList(
new ChannelSession.Factory(),
new TcpipServerChannel.DirectTcpipFactory());
}
if (globalRequestHandlers == null) {
globalRequestHandlers = Arrays.asList(
new KeepAliveHandler(),
new NoMoreSessionsHandler(),
new TcpipForwardHandler(),
new CancelTcpipForwardHandler());
}
if (factory == null) {
factory = SshServer.DEFAULT_SSH_SERVER_FACTORY;
}
return me();
}
}
 
}
/trunk/rmsshd/sshd-core/src/main/java/org/apache/sshd/SshServer.java
0,0 → 1,506
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd;
 
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
 
import org.apache.sshd.common.AbstractFactoryManager;
import org.apache.sshd.common.Closeable;
import org.apache.sshd.common.Factory;
import org.apache.sshd.common.ForwardingFilter;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.SshdSocketAddress;
import org.apache.sshd.common.io.DefaultIoServiceFactoryFactory;
import org.apache.sshd.common.io.IoAcceptor;
import org.apache.sshd.common.io.IoServiceFactory;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.io.mina.MinaServiceFactory;
import org.apache.sshd.common.io.nio2.Nio2ServiceFactory;
import org.apache.sshd.common.session.AbstractSession;
import org.apache.sshd.common.util.CloseableUtils;
import org.apache.sshd.common.util.OsUtils;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.common.util.ThreadUtils;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.CommandFactory;
import org.apache.sshd.server.PasswordAuthenticator;
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.ServerFactoryManager;
import org.apache.sshd.server.UserAuth;
import org.apache.sshd.server.auth.UserAuthKeyboardInteractive;
import org.apache.sshd.server.auth.UserAuthPassword;
import org.apache.sshd.server.auth.UserAuthPublicKey;
import org.apache.sshd.server.auth.gss.GSSAuthenticator;
import org.apache.sshd.server.auth.gss.UserAuthGSS;
import org.apache.sshd.server.command.ScpCommandFactory;
import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerConnectionService;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.session.ServerUserAuthService;
import org.apache.sshd.server.session.SessionFactory;
import org.apache.sshd.server.sftp.SftpSubsystem;
import org.apache.sshd.server.session.ServerSessionTimeoutListener;
import org.apache.sshd.server.shell.ProcessShellFactory;
 
/**
* The SshServer class is the main entry point for the server side of the SSH protocol.
*
* The SshServer has to be configured before being started. Such configuration can be
* done either using a dependency injection mechanism (such as the Spring framework)
* or programmatically. Basic setup is usually done using the {@link #setUpDefaultServer()}
* method, which will known ciphers, macs, channels, etc...
* Besides this basic setup, a few things have to be manually configured such as the
* port number, {@link Factory}, the {@link org.apache.sshd.common.KeyPairProvider}
* and the {@link PasswordAuthenticator}.
*
* Some properties can also be configured using the {@link #setProperties(java.util.Map)}
* method.
*
* Once the SshServer instance has been configured, it can be started using the
* {@link #start()} method and stopped using the {@link #stop()} method.
*
* @see ServerFactoryManager
* @see org.apache.sshd.common.FactoryManager
*
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class SshServer extends AbstractFactoryManager implements ServerFactoryManager, Closeable {
 
public static final Factory<SshServer> DEFAULT_SSH_SERVER_FACTORY = new Factory<SshServer>() {
public SshServer create() {
return new SshServer();
}
};
 
protected IoAcceptor acceptor;
protected String host;
protected int port;
protected List<NamedFactory<UserAuth>> userAuthFactories;
protected Factory<Command> shellFactory;
protected SessionFactory sessionFactory;
protected CommandFactory commandFactory;
protected List<NamedFactory<Command>> subsystemFactories;
protected PasswordAuthenticator passwordAuthenticator;
protected PublickeyAuthenticator publickeyAuthenticator;
protected GSSAuthenticator gssAuthenticator;
protected ServerSessionTimeoutListener sessionTimeoutListener;
protected ScheduledFuture<?> timeoutListenerFuture;
 
public SshServer() {
}
 
public String getHost() {
return host;
}
 
public void setHost(String host) {
this.host = host;
}
 
public int getPort() {
return port;
}
 
/**
* Configure the port number to use for this SSH server.
*
* @param port the port number for this SSH server
*/
public void setPort(int port) {
this.port = port;
}
 
public List<NamedFactory<UserAuth>> getUserAuthFactories() {
return userAuthFactories;
}
 
public void setUserAuthFactories(List<NamedFactory<UserAuth>> userAuthFactories) {
this.userAuthFactories = userAuthFactories;
}
 
public Factory<Command> getShellFactory() {
return shellFactory;
}
 
public void setShellFactory(Factory<Command> shellFactory) {
this.shellFactory = shellFactory;
}
 
public SessionFactory getSessionFactory() {
return sessionFactory;
}
 
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
 
public CommandFactory getCommandFactory() {
return commandFactory;
}
 
public void setCommandFactory(CommandFactory commandFactory) {
this.commandFactory = commandFactory;
}
 
public List<NamedFactory<Command>> getSubsystemFactories() {
return subsystemFactories;
}
 
public void setSubsystemFactories(List<NamedFactory<Command>> subsystemFactories) {
this.subsystemFactories = subsystemFactories;
}
 
public PasswordAuthenticator getPasswordAuthenticator() {
return passwordAuthenticator;
}
 
public void setPasswordAuthenticator(PasswordAuthenticator passwordAuthenticator) {
this.passwordAuthenticator = passwordAuthenticator;
}
 
public PublickeyAuthenticator getPublickeyAuthenticator() {
return publickeyAuthenticator;
}
 
public void setPublickeyAuthenticator(PublickeyAuthenticator publickeyAuthenticator) {
this.publickeyAuthenticator = publickeyAuthenticator;
}
 
public GSSAuthenticator getGSSAuthenticator() {
return gssAuthenticator;
}
 
public void setGSSAuthenticator(GSSAuthenticator gssAuthenticator) {
this.gssAuthenticator = gssAuthenticator;
}
 
public void setTcpipForwardingFilter(ForwardingFilter forwardingFilter) {
this.tcpipForwardingFilter = forwardingFilter;
}
 
protected void checkConfig() {
if (getPort() < 0) {
throw new IllegalArgumentException("Bad port number: " + port);
}
if (getKeyExchangeFactories() == null) {
throw new IllegalArgumentException("KeyExchangeFactories not set");
}
if (getUserAuthFactories() == null) {
List<NamedFactory<UserAuth>> factories = new ArrayList<NamedFactory<UserAuth>>();
if (getPasswordAuthenticator() != null) {
factories.add(new UserAuthPassword.Factory());
factories.add(new UserAuthKeyboardInteractive.Factory());
}
if (getPublickeyAuthenticator() != null) {
factories.add(new UserAuthPublicKey.Factory());
}
if (getGSSAuthenticator() != null) {
factories.add(new UserAuthGSS.Factory());
}
if (factories.size() > 0) {
setUserAuthFactories(factories);
} else {
throw new IllegalArgumentException("UserAuthFactories not set");
}
}
if (getScheduledExecutorService() == null) {
setScheduledExecutorService(
ThreadUtils.newSingleThreadScheduledExecutor(this.toString() + "-timer"),
true);
}
if (getCipherFactories() == null) {
throw new IllegalArgumentException("CipherFactories not set");
}
if (getCompressionFactories() == null) {
throw new IllegalArgumentException("CompressionFactories not set");
}
if (getMacFactories() == null) {
throw new IllegalArgumentException("MacFactories not set");
}
if (getChannelFactories() == null) {
throw new IllegalArgumentException("ChannelFactories not set");
}
if (getRandomFactory() == null) {
throw new IllegalArgumentException("RandomFactory not set");
}
if (getKeyPairProvider() == null) {
throw new IllegalArgumentException("HostKeyProvider not set");
}
if (getFileSystemFactory() == null) {
throw new IllegalArgumentException("FileSystemFactory not set");
}
if (getIoServiceFactoryFactory() == null) {
setIoServiceFactoryFactory(new DefaultIoServiceFactoryFactory());
}
if (getServiceFactories() == null) {
setServiceFactories(Arrays.asList(
new ServerUserAuthService.Factory(),
new ServerConnectionService.Factory()
));
}
}
 
/**
* Start the SSH server and accept incoming exceptions on the configured port.
*
* @throws IOException
*/
public void start() throws IOException {
checkConfig();
if (sessionFactory == null) {
sessionFactory = createSessionFactory();
}
sessionFactory.setServer(this);
acceptor = createAcceptor();
 
// set up the the session timeout listener and schedule it
sessionTimeoutListener = createSessionTimeoutListener();
sessionFactory.addListener(sessionTimeoutListener);
 
timeoutListenerFuture = getScheduledExecutorService()
.scheduleAtFixedRate(sessionTimeoutListener, 1, 1, TimeUnit.SECONDS);
 
if (host != null) {
String[] hosts = host.split(",");
for (String host : hosts) {
InetAddress[] inetAddresses = InetAddress.getAllByName(host);
for (InetAddress inetAddress : inetAddresses) {
acceptor.bind(new InetSocketAddress(inetAddress, port));
if (port == 0) {
port = ((InetSocketAddress) acceptor.getBoundAddresses().iterator().next()).getPort();
}
}
}
} else {
acceptor.bind(new InetSocketAddress(port));
if (port == 0) {
port = ((InetSocketAddress) acceptor.getBoundAddresses().iterator().next()).getPort();
}
}
}
 
/**
* Stop the SSH server. This method will block until all resources are actually disposed.
*/
public void stop() throws InterruptedException {
stop(false);
}
 
public void stop(boolean immediately) throws InterruptedException {
close(immediately).await();
}
 
public void open() throws IOException {
start();
}
 
@Override
protected Closeable getInnerCloseable() {
return builder()
.run(new Runnable() {
public void run() {
stopSessionTimeoutListener();
}
})
.sequential(acceptor, ioServiceFactory)
.run(new Runnable() {
public void run() {
acceptor = null;
ioServiceFactory = null;
if (shutdownExecutor && executor != null) {
executor.shutdownNow();
executor = null;
}
}
})
.build();
}
 
/**
* Obtain the list of active sessions.
*/
public List<AbstractSession> getActiveSessions() {
List<AbstractSession> sessions = new ArrayList<AbstractSession>();
for (IoSession ioSession : acceptor.getManagedSessions().values()) {
AbstractSession session = AbstractSession.getSession(ioSession, true);
if (session != null) {
sessions.add(session);
}
}
return sessions;
}
 
protected IoAcceptor createAcceptor() {
return getIoServiceFactory().createAcceptor(getSessionFactory());
}
 
protected SessionFactory createSessionFactory() {
return new SessionFactory();
}
 
protected ServerSessionTimeoutListener createSessionTimeoutListener() {
return new ServerSessionTimeoutListener();
}
 
protected void stopSessionTimeoutListener() {
// cancel the timeout monitoring task
if (timeoutListenerFuture != null) {
timeoutListenerFuture.cancel(true);
timeoutListenerFuture = null;
}
 
// remove the sessionTimeoutListener completely; should the SSH server be restarted, a new one
// will be created.
if (sessionFactory != null && sessionTimeoutListener != null) {
sessionFactory.removeListener(sessionTimeoutListener);
}
sessionTimeoutListener = null;
}
 
@Override
public String toString() {
return "SshServer[" + Integer.toHexString(hashCode()) + "]";
}
 
public static SshServer setUpDefaultServer() {
return SshBuilder.server().build();
}
 
/*=================================
Main class implementation
*=================================*/
 
public static void main(String[] args) throws Exception {
int port = 8000;
String provider;
boolean error = false;
 
for (int i = 0; i < args.length; i++) {
if ("-p".equals(args[i])) {
if (i + 1 >= args.length) {
System.err.println("option requires an argument: " + args[i]);
break;
}
port = Integer.parseInt(args[++i]);
} else if ("-io".equals(args[i])) {
if (i + 1 >= args.length) {
System.err.println("option requires an argument: " + args[i]);
break;
}
provider = args[++i];
if ("mina".equals(provider)) {
System.setProperty(IoServiceFactory.class.getName(), MinaServiceFactory.class.getName());
} else if ("nio2".endsWith(provider)) {
System.setProperty(IoServiceFactory.class.getName(), Nio2ServiceFactory.class.getName());
} else {
System.err.println("provider should be mina or nio2: " + args[i]);
break;
}
} else if (args[i].startsWith("-")) {
System.err.println("illegal option: " + args[i]);
error = true;
break;
} else {
System.err.println("extra argument: " + args[i]);
error = true;
break;
}
}
if (error) {
System.err.println("usage: sshd [-p port] [-io mina|nio2]");
System.exit(-1);
}
 
System.err.println("Starting SSHD on port " + port);
SshServer sshd = SshServer.setUpDefaultServer();
sshd.setPort(port);
sshd.getProperties().put(SshServer.WELCOME_BANNER, "Welcome to SSHD\n");
if (SecurityUtils.isBouncyCastleRegistered()) {
sshd.setKeyPairProvider(new PEMGeneratorHostKeyProvider("key.pem"));
} else {
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("key.ser"));
}
if (OsUtils.isUNIX()) {
sshd.setShellFactory(new ProcessShellFactory(new String[] { "/bin/sh", "-i", "-l" },
EnumSet.of(ProcessShellFactory.TtyOptions.ONlCr)));
} else {
sshd.setShellFactory(new ProcessShellFactory(new String[] { "cmd.exe "},
EnumSet.of(ProcessShellFactory.TtyOptions.Echo, ProcessShellFactory.TtyOptions.ICrNl, ProcessShellFactory.TtyOptions.ONlCr)));
}
sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
public boolean authenticate(String username, String password, ServerSession session) {
return username != null && username.equals(password);
}
});
sshd.setPublickeyAuthenticator(new PublickeyAuthenticator() {
public boolean authenticate(String username, PublicKey key, ServerSession session) {
//File f = new File("/Users/" + username + "/.ssh/authorized_keys");
return true;
}
});
sshd.setTcpipForwardingFilter(new ForwardingFilter() {
public boolean canForwardAgent(Session session) {
return true;
}
 
public boolean canForwardX11(Session session) {
return true;
}
 
public boolean canListen(SshdSocketAddress address, Session session) {
return true;
}
 
public boolean canConnect(SshdSocketAddress address, Session session) {
return true;
}
});
sshd.setCommandFactory(new ScpCommandFactory(new CommandFactory() {
public Command createCommand(String command) {
EnumSet<ProcessShellFactory.TtyOptions> ttyOptions;
if (OsUtils.isUNIX()) {
ttyOptions = EnumSet.of(ProcessShellFactory.TtyOptions.ONlCr);
} else {
ttyOptions = EnumSet.of(ProcessShellFactory.TtyOptions.Echo, ProcessShellFactory.TtyOptions.ICrNl, ProcessShellFactory.TtyOptions.ONlCr);
}
return new ProcessShellFactory(command.split(" "), ttyOptions).create();
}
}));
sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(
new SftpSubsystem.Factory()
));
sshd.start();
 
Thread.sleep(Long.MAX_VALUE);
}
 
}
/trunk/rmsshd/sshd-core/src/main/java/org/apache/sshd/server/UserAuth.java
0,0 → 1,70
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.server;
 
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.server.session.ServerSession;
 
/**
* Server side authentication mechanism.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public interface UserAuth {
 
/**
* Try to authenticate the user.
* This methods should return a non null object which is the user identity if
* the authentication succeeded. If the authentication failed, this method should
* throw an exception. If the authentication is still ongoing, a null value should
* be returned.
*
* @param session the current ssh session
* @param username the user trying to log in
* @param buffer the request buffer containing parameters specific to this request
* @return <code>true</code> if the authentication succeeded, <code>false</code> if the authentication
* failed and <code>null</code></code>is not finished yet
* @throws Exception if the authentication fails
*/
Boolean auth(ServerSession session, String username, String service, Buffer buffer) throws Exception;
 
/**
* Handle another step in the authentication process.
*
* @param buffer the request buffer containing parameters specific to this request
* @return <code>true</code> if the authentication succeeded, <code>false</code> if the authentication
* failed and <code>null</code></code>is not finished yet
* @throws Exception if the authentication fails
*/
Boolean next(Buffer buffer) throws Exception;
 
/**
* Get a user name which has been derived from the handshaking process, or the initial name if
* nothing has been found.
*
* @return The user name
* @throws Exception if the request fails
*/
String getUserName() throws Exception;
 
/**
* Free any system resources used by the module.
*/
void destroy();
}
/trunk/rmsshd/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSessionTimeoutListener.java
0,0 → 1,63
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.server.session;
 
import org.apache.sshd.common.Session;
import org.apache.sshd.common.SessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
 
/**
* Task that iterates over all currently open {@link ServerSession}s and checks each of them for timeouts. If
* the {@link ServerSession} has timed out (either auth or idle timeout), the session will be disconnected.
*
* @see org.apache.sshd.server.session.ServerSession#checkForTimeouts()
*/
public class ServerSessionTimeoutListener implements SessionListener, Runnable {
 
private final Logger log = LoggerFactory.getLogger(ServerSessionTimeoutListener.class);
private final Set<ServerSession> sessions = new CopyOnWriteArraySet<ServerSession>();
 
public void sessionCreated(Session session) {
if (session instanceof ServerSession) {
sessions.add((ServerSession) session);
}
}
 
public void sessionEvent(Session session, Event event) {
}
 
public void sessionClosed(Session s) {
sessions.remove(s);
}
 
public void run() {
for (ServerSession session : sessions) {
try {
session.checkForTimeouts();
} catch (Exception e) {
log.warn("An error occurred while checking session timeouts", e);
}
}
}
}
/trunk/rmsshd/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
0,0 → 1,67
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.server.session;
 
import java.io.IOException;
 
import org.apache.sshd.common.Service;
import org.apache.sshd.common.ServiceFactory;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.SshException;
import org.apache.sshd.common.session.AbstractConnectionService;
 
/**
* Server side <code>ssh-connection</code> service.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class ServerConnectionService extends AbstractConnectionService {
 
public static class Factory implements ServiceFactory {
 
public String getName() {
return "ssh-connection";
}
 
public Service create(Session session) throws IOException {
return new ServerConnectionService(session);
}
}
 
 
protected ServerConnectionService(Session s) throws SshException {
super(s);
if (!(s instanceof ServerSession)) {
throw new IllegalStateException("Server side service used on client side");
}
ServerSession session = (ServerSession) s;
if (!session.isAuthenticated()) {
throw new SshException("Session is not authenticated");
}
}
 
public String initAgentForward() throws IOException {
return agentForward.initialize();
}
 
public String createX11Display(boolean singleConnection, String authenticationProtocol, String authenticationCookie, int screen) throws IOException {
return x11Forward.createDisplay(singleConnection, authenticationProtocol, authenticationCookie, screen);
}
 
}
/trunk/rmsshd/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
0,0 → 1,258
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.server.session;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
 
import org.apache.sshd.SshServer;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Service;
import org.apache.sshd.common.ServiceFactory;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.SshException;
import org.apache.sshd.common.future.CloseFuture;
import org.apache.sshd.common.future.DefaultCloseFuture;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.common.util.CloseableUtils;
import org.apache.sshd.server.ServerFactoryManager;
import org.apache.sshd.server.UserAuth;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
/**
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
public class ServerUserAuthService extends CloseableUtils.AbstractCloseable implements Service {
 
public static class Factory implements ServiceFactory {
 
public String getName() {
return "ssh-userauth";
}
 
public Service create(Session session) throws IOException {
return new ServerUserAuthService(session);
}
}
 
private final ServerSession session;
private List<NamedFactory<UserAuth>> userAuthFactories;
private List<List<String>> authMethods;
private String authUserName;
private String authMethod;
private String authService;
private UserAuth currentAuth;
 
private int maxAuthRequests = 20;
private int nbAuthRequests;
 
public ServerUserAuthService(Session s) throws SshException {
if (!(s instanceof ServerSession)) {
throw new IllegalStateException("Server side service used on client side");
}
this.session = (ServerSession) s;
if (session.isAuthenticated()) {
throw new SshException("Session already authenticated");
}
maxAuthRequests = session.getIntProperty(ServerFactoryManager.MAX_AUTH_REQUESTS, maxAuthRequests);
 
userAuthFactories = new ArrayList<NamedFactory<UserAuth>>(getFactoryManager().getUserAuthFactories());
// Get authentication methods
authMethods = new ArrayList<List<String>>();
String mths = getFactoryManager().getProperties().get(SshServer.AUTH_METHODS);
if (mths == null) {
for (NamedFactory<UserAuth> uaf : getFactoryManager().getUserAuthFactories()) {
authMethods.add(new ArrayList<String>(Collections.singletonList(uaf.getName())));
}
} else {
for (String mthl : mths.split("\\s")) {
authMethods.add(new ArrayList<String>(Arrays.asList(mthl.split(","))));
}
}
// Verify all required methods are supported
for (List<String> l : authMethods) {
for (String m : l