├── .gitignore ├── .idea ├── assetWizardSettings.xml ├── codeStyles │ └── Project.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── libs │ └── jsch-0.1.55.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── smiskol │ │ └── phantom │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── ic_add_symbol-web.png │ ├── ic_launcher-web.png │ ├── ic_phantom_logo-web.png │ ├── ic_phantom_logo_test-web.png │ ├── java │ │ └── com │ │ │ ├── ethz │ │ │ └── ssh2 │ │ │ │ ├── ChannelCondition.java │ │ │ │ ├── Connection.java │ │ │ │ ├── ConnectionInfo.java │ │ │ │ ├── ConnectionMonitor.java │ │ │ │ ├── DHGexParameters.java │ │ │ │ ├── HTTPProxyData.java │ │ │ │ ├── HTTPProxyException.java │ │ │ │ ├── InteractiveCallback.java │ │ │ │ ├── KnownHosts.java │ │ │ │ ├── LocalPortForwarder.java │ │ │ │ ├── LocalStreamForwarder.java │ │ │ │ ├── PacketListener.java │ │ │ │ ├── ProxyData.java │ │ │ │ ├── SCPClient.java │ │ │ │ ├── SCPInputStream.java │ │ │ │ ├── SCPOutputStream.java │ │ │ │ ├── SFTPException.java │ │ │ │ ├── SFTPInputStream.java │ │ │ │ ├── SFTPOutputStream.java │ │ │ │ ├── SFTPv3Client.java │ │ │ │ ├── SFTPv3DirectoryEntry.java │ │ │ │ ├── SFTPv3FileAttributes.java │ │ │ │ ├── SFTPv3FileHandle.java │ │ │ │ ├── ServerHostKeyVerifier.java │ │ │ │ ├── Session.java │ │ │ │ ├── StreamGobbler.java │ │ │ │ ├── Version.java │ │ │ │ ├── auth │ │ │ │ └── AuthenticationManager.java │ │ │ │ ├── channel │ │ │ │ ├── Channel.java │ │ │ │ ├── ChannelClosedException.java │ │ │ │ ├── ChannelInputStream.java │ │ │ │ ├── ChannelManager.java │ │ │ │ ├── ChannelOutputStream.java │ │ │ │ ├── IChannelWorkerThread.java │ │ │ │ ├── LocalAcceptThread.java │ │ │ │ ├── RemoteAcceptThread.java │ │ │ │ ├── RemoteForwardingData.java │ │ │ │ ├── RemoteX11AcceptThread.java │ │ │ │ ├── StreamForwarder.java │ │ │ │ └── X11ServerData.java │ │ │ │ ├── crypto │ │ │ │ ├── Base64.java │ │ │ │ ├── CryptoWishList.java │ │ │ │ ├── KeyMaterial.java │ │ │ │ ├── PEMDecoder.java │ │ │ │ ├── PEMDecryptException.java │ │ │ │ ├── PEMStructure.java │ │ │ │ ├── SimpleDERReader.java │ │ │ │ ├── cipher │ │ │ │ │ ├── AES.java │ │ │ │ │ ├── BlockCipher.java │ │ │ │ │ ├── BlockCipherFactory.java │ │ │ │ │ ├── BlowFish.java │ │ │ │ │ ├── CBCMode.java │ │ │ │ │ ├── CTRMode.java │ │ │ │ │ ├── CipherInputStream.java │ │ │ │ │ ├── CipherOutputStream.java │ │ │ │ │ ├── DES.java │ │ │ │ │ ├── DESede.java │ │ │ │ │ └── NullCipher.java │ │ │ │ ├── dh │ │ │ │ │ ├── DhExchange.java │ │ │ │ │ └── DhGroupExchange.java │ │ │ │ └── digest │ │ │ │ │ ├── Digest.java │ │ │ │ │ ├── HMAC.java │ │ │ │ │ ├── HashForSSH2Types.java │ │ │ │ │ ├── MAC.java │ │ │ │ │ ├── MD5.java │ │ │ │ │ └── SHA1.java │ │ │ │ ├── log │ │ │ │ └── Logger.java │ │ │ │ ├── packets │ │ │ │ ├── PacketChannelOpenConfirmation.java │ │ │ │ ├── PacketChannelOpenFailure.java │ │ │ │ ├── PacketChannelWindowAdjust.java │ │ │ │ ├── PacketDisconnect.java │ │ │ │ ├── PacketGlobalCancelForwardRequest.java │ │ │ │ ├── PacketGlobalForwardRequest.java │ │ │ │ ├── PacketIgnore.java │ │ │ │ ├── PacketKexDHInit.java │ │ │ │ ├── PacketKexDHReply.java │ │ │ │ ├── PacketKexDhGexGroup.java │ │ │ │ ├── PacketKexDhGexInit.java │ │ │ │ ├── PacketKexDhGexReply.java │ │ │ │ ├── PacketKexDhGexRequest.java │ │ │ │ ├── PacketKexDhGexRequestOld.java │ │ │ │ ├── PacketKexInit.java │ │ │ │ ├── PacketNewKeys.java │ │ │ │ ├── PacketOpenDirectTCPIPChannel.java │ │ │ │ ├── PacketOpenSessionChannel.java │ │ │ │ ├── PacketServiceAccept.java │ │ │ │ ├── PacketServiceRequest.java │ │ │ │ ├── PacketSessionExecCommand.java │ │ │ │ ├── PacketSessionPtyRequest.java │ │ │ │ ├── PacketSessionStartShell.java │ │ │ │ ├── PacketSessionSubsystemRequest.java │ │ │ │ ├── PacketSessionX11Request.java │ │ │ │ ├── PacketUserauthBanner.java │ │ │ │ ├── PacketUserauthFailure.java │ │ │ │ ├── PacketUserauthInfoRequest.java │ │ │ │ ├── PacketUserauthInfoResponse.java │ │ │ │ ├── PacketUserauthRequestInteractive.java │ │ │ │ ├── PacketUserauthRequestNone.java │ │ │ │ ├── PacketUserauthRequestPassword.java │ │ │ │ ├── PacketUserauthRequestPublicKey.java │ │ │ │ ├── Packets.java │ │ │ │ ├── TypesReader.java │ │ │ │ └── TypesWriter.java │ │ │ │ ├── sftp │ │ │ │ ├── AttrTextHints.java │ │ │ │ ├── AttribBits.java │ │ │ │ ├── AttribFlags.java │ │ │ │ ├── AttribPermissions.java │ │ │ │ ├── AttribTypes.java │ │ │ │ ├── ErrorCodes.java │ │ │ │ ├── OpenFlags.java │ │ │ │ └── Packet.java │ │ │ │ ├── signature │ │ │ │ ├── DSAPrivateKey.java │ │ │ │ ├── DSAPublicKey.java │ │ │ │ ├── DSASHA1Verify.java │ │ │ │ ├── DSASignature.java │ │ │ │ ├── RSAPrivateKey.java │ │ │ │ ├── RSAPublicKey.java │ │ │ │ ├── RSASHA1Verify.java │ │ │ │ └── RSASignature.java │ │ │ │ ├── transport │ │ │ │ ├── ClientServerHello.java │ │ │ │ ├── KexManager.java │ │ │ │ ├── KexParameters.java │ │ │ │ ├── KexState.java │ │ │ │ ├── MessageHandler.java │ │ │ │ ├── NegotiateException.java │ │ │ │ ├── NegotiatedParameters.java │ │ │ │ ├── TransportConnection.java │ │ │ │ └── TransportManager.java │ │ │ │ └── util │ │ │ │ ├── StringEncoder.java │ │ │ │ ├── TimeoutService.java │ │ │ │ └── Tokenizer.java │ │ │ └── smiskol │ │ │ └── phantom │ │ │ ├── CenterSeekBar.java │ │ │ ├── ControlsFragment.java │ │ │ ├── MainActivity.java │ │ │ ├── SSHClass.java │ │ │ ├── ViewPagerAdapter.java │ │ │ └── WelcomeFragment.java │ └── res │ │ ├── anim │ │ └── shake.xml │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── hold_animation.xml │ │ ├── hold_disable_gradient.xml │ │ ├── hold_enable_gradient.xml │ │ ├── hold_ripple.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_plus.xml │ │ ├── ic_sub.xml │ │ ├── round_button_plus.xml │ │ └── round_button_sub.xml │ │ ├── font │ │ ├── product.xml │ │ ├── product_bold.ttf │ │ └── product_regular.ttf │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── fragment_controls.xml │ │ ├── fragment_welcome.xml │ │ └── toolbar_layout.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── smiskol │ └── phantom │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── phantom-app.apk └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches/build_file_checksums.ser 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild 12 | gradle_models.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | xmlns:android 11 | 12 | ^$ 13 | 14 | 15 | 16 |
17 |
18 | 19 | 20 | 21 | xmlns:.* 22 | 23 | ^$ 24 | 25 | 26 | BY_NAME 27 | 28 |
29 |
30 | 31 | 32 | 33 | .*:id 34 | 35 | http://schemas.android.com/apk/res/android 36 | 37 | 38 | 39 |
40 |
41 | 42 | 43 | 44 | .*:name 45 | 46 | http://schemas.android.com/apk/res/android 47 | 48 | 49 | 50 |
51 |
52 | 53 | 54 | 55 | name 56 | 57 | ^$ 58 | 59 | 60 | 61 |
62 |
63 | 64 | 65 | 66 | style 67 | 68 | ^$ 69 | 70 | 71 | 72 |
73 |
74 | 75 | 76 | 77 | .* 78 | 79 | ^$ 80 | 81 | 82 | BY_NAME 83 | 84 |
85 |
86 | 87 | 88 | 89 | .* 90 | 91 | http://schemas.android.com/apk/res/android 92 | 93 | 94 | ANDROID_ATTRIBUTE_ORDER 95 | 96 |
97 |
98 | 99 | 100 | 101 | .* 102 | 103 | .* 104 | 105 | 106 | BY_NAME 107 | 108 |
109 |
110 |
111 |
112 |
113 |
-------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 31 | 32 | 33 | 34 | 35 | 36 | 38 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Phantom 2 | Control your car's steering and movement from an app with openpilot. Designed to be a gimmick feature more than anything. It's a mock Tesla Summon. 3 | 4 | Download the app [here](https://github.com/ShaneSmiskol/phantom-app/blob/master/phantom-app.apk?raw=true). 5 | 6 | This is now outdated and only works on openpilot 0.5.12 (branch release2) on [Arne's fork here](https://github.com/arne182/openpilot). 7 | Phantom also works on Arne's 066-clean branch, however it is not tested and VERY buggy. 8 | 9 | Demo video: 10 | 11 | [![](https://img.youtube.com/vi/ghNnBpcPG7g/0.jpg)](https://youtu.be/ghNnBpcPG7g?t=314) 12 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.smiskol.phantom" 7 | minSdkVersion 21 8 | targetSdkVersion 28 9 | versionCode 3 10 | versionName "1.0.1" 11 | setProperty("archivesBaseName", "phantom-app") 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(dir: 'libs', include: ['*.jar']) 24 | implementation 'com.android.support:appcompat-v7:28.0.0' 25 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 26 | implementation 'com.android.support:support-v4:28.0.0' 27 | implementation 'com.android.support:design:28.0.0' 28 | testImplementation 'junit:junit:4.12' 29 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 30 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 31 | implementation 'com.android.support:cardview-v7:28.0.0' 32 | implementation 'com.android.support:design:28.0.0' 33 | implementation files('libs/jsch-0.1.55.jar') 34 | 35 | } 36 | -------------------------------------------------------------------------------- /app/libs/jsch-0.1.55.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/libs/jsch-0.1.55.jar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/smiskol/phantom/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.smiskol.phantom; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.smiskol.opcontroller", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/ic_add_symbol-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/ic_add_symbol-web.png -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/ic_phantom_logo-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/ic_phantom_logo-web.png -------------------------------------------------------------------------------- /app/src/main/ic_phantom_logo_test-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/ic_phantom_logo_test-web.png -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/ChannelCondition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | /** 8 | * Contains constants that can be used to specify what conditions to wait for on 9 | * a SSH-2 channel (e.g., represented by a {@link Session}). 10 | * 11 | * @see Session#waitForCondition(int, long) 12 | * 13 | * @author Christian Plattner 14 | * @version 2.50, 03/15/10 15 | */ 16 | 17 | public abstract interface ChannelCondition 18 | { 19 | /** 20 | * A timeout has occurred, none of your requested conditions is fulfilled. 21 | * However, other conditions may be true - therefore, NEVER use the "==" 22 | * operator to test for this (or any other) condition. Always use 23 | * something like ((cond & ChannelCondition.CLOSED) != 0). 24 | */ 25 | public static final int TIMEOUT = 1; 26 | 27 | /** 28 | * The underlying SSH-2 channel, however not necessarily the whole connection, 29 | * has been closed. This implies EOF. Note that there may still 30 | * be unread stdout or stderr data in the local window, i.e, STDOUT_DATA 31 | * or/and STDERR_DATA may be set at the same time. 32 | */ 33 | public static final int CLOSED = 2; 34 | 35 | /** 36 | * There is stdout data available that is ready to be consumed. 37 | */ 38 | public static final int STDOUT_DATA = 4; 39 | 40 | /** 41 | * There is stderr data available that is ready to be consumed. 42 | */ 43 | public static final int STDERR_DATA = 8; 44 | 45 | /** 46 | * EOF on has been reached, no more _new_ stdout or stderr data will arrive 47 | * from the remote server. However, there may be unread stdout or stderr 48 | * data, i.e, STDOUT_DATA or/and STDERR_DATA 49 | * may be set at the same time. 50 | */ 51 | public static final int EOF = 16; 52 | 53 | /** 54 | * The exit status of the remote process is available. 55 | * Some servers never send the exist status, or occasionally "forget" to do so. 56 | */ 57 | public static final int EXIT_STATUS = 32; 58 | 59 | /** 60 | * The exit signal of the remote process is available. 61 | */ 62 | public static final int EXIT_SIGNAL = 64; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/ConnectionInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | /** 8 | * In most cases you probably do not need the information contained in here. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class ConnectionInfo 14 | { 15 | /** 16 | * The used key exchange (KEX) algorithm in the latest key exchange. 17 | */ 18 | public String keyExchangeAlgorithm; 19 | 20 | /** 21 | * The currently used crypto algorithm for packets from to the client to the 22 | * server. 23 | */ 24 | public String clientToServerCryptoAlgorithm; 25 | /** 26 | * The currently used crypto algorithm for packets from to the server to the 27 | * client. 28 | */ 29 | public String serverToClientCryptoAlgorithm; 30 | 31 | /** 32 | * The currently used MAC algorithm for packets from to the client to the 33 | * server. 34 | */ 35 | public String clientToServerMACAlgorithm; 36 | /** 37 | * The currently used MAC algorithm for packets from to the server to the 38 | * client. 39 | */ 40 | public String serverToClientMACAlgorithm; 41 | 42 | /** 43 | * The type of the server host key (currently either "ssh-dss" or 44 | * "ssh-rsa"). 45 | */ 46 | public String serverHostKeyAlgorithm; 47 | /** 48 | * The server host key that was sent during the latest key exchange. 49 | */ 50 | public byte[] serverHostKey; 51 | 52 | /** 53 | * Number of kex exchanges performed on this connection so far. 54 | */ 55 | public int keyExchangeCounter = 0; 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/ConnectionMonitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | /** 8 | * A ConnectionMonitor is used to get notified when the 9 | * underlying socket of a connection is closed. 10 | * 11 | * @author Christian Plattner 12 | * @version 2.50, 03/15/10 13 | */ 14 | 15 | public interface ConnectionMonitor 16 | { 17 | /** 18 | * This method is called after the connection's underlying 19 | * socket has been closed. E.g., due to the {@link Connection#close()} request of the 20 | * user, if the peer closed the connection, due to a fatal error during connect() 21 | * (also if the socket cannot be established) or if a fatal error occured on 22 | * an established connection. 23 | *

24 | * This is an experimental feature. 25 | *

26 | * You MUST NOT make any assumption about the thread that invokes this method. 27 | *

28 | * Please note: if the connection is not connected (e.g., there was no successful 29 | * connect() call), then the invocation of {@link Connection#close()} will NOT trigger 30 | * this method. 31 | * 32 | * @see Connection#addConnectionMonitor(ConnectionMonitor) 33 | * 34 | * @param reason Includes an indication why the socket was closed. 35 | */ 36 | public void connectionLost(Throwable reason); 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/HTTPProxyData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | /** 8 | * A HTTPProxyData object is used to specify the needed connection data 9 | * to connect through a HTTP proxy. 10 | * 11 | * @see Connection#setProxyData(ProxyData) 12 | * 13 | * @author Christian Plattner 14 | * @version 2.50, 03/15/10 15 | */ 16 | 17 | public class HTTPProxyData implements ProxyData 18 | { 19 | public final String proxyHost; 20 | public final int proxyPort; 21 | public final String proxyUser; 22 | public final String proxyPass; 23 | public final String[] requestHeaderLines; 24 | 25 | /** 26 | * Same as calling {@link #HTTPProxyData(String, int, String, String) HTTPProxyData(proxyHost, proxyPort, null, null)} 27 | * 28 | * @param proxyHost Proxy hostname. 29 | * @param proxyPort Proxy port. 30 | */ 31 | public HTTPProxyData(String proxyHost, int proxyPort) 32 | { 33 | this(proxyHost, proxyPort, null, null); 34 | } 35 | 36 | /** 37 | * Same as calling {@link #HTTPProxyData(String, int, String, String, String[]) HTTPProxyData(proxyHost, proxyPort, null, null, null)} 38 | * 39 | * @param proxyHost Proxy hostname. 40 | * @param proxyPort Proxy port. 41 | * @param proxyUser Username for basic authentication (null if no authentication is needed). 42 | * @param proxyPass Password for basic authentication (null if no authentication is needed). 43 | */ 44 | public HTTPProxyData(String proxyHost, int proxyPort, String proxyUser, String proxyPass) 45 | { 46 | this(proxyHost, proxyPort, proxyUser, proxyPass, null); 47 | } 48 | 49 | /** 50 | * Connection data for a HTTP proxy. It is possible to specify a username and password 51 | * if the proxy requires basic authentication. Also, additional request header lines can 52 | * be specified (e.g., "User-Agent: CERN-LineMode/2.15 libwww/2.17b3"). 53 | *

54 | * Please note: if you want to use basic authentication, then both proxyUser 55 | * and proxyPass must be non-null. 56 | *

57 | * Here is an example: 58 | *

59 | * 60 | * new HTTPProxyData("192.168.1.1", "3128", "proxyuser", "secret", new String[] {"User-Agent: GanymedBasedClient/1.0", "X-My-Proxy-Option: something"}); 61 | * 62 | * 63 | * @param proxyHost Proxy hostname. 64 | * @param proxyPort Proxy port. 65 | * @param proxyUser Username for basic authentication (null if no authentication is needed). 66 | * @param proxyPass Password for basic authentication (null if no authentication is needed). 67 | * @param requestHeaderLines An array with additional request header lines (without end-of-line markers) 68 | * that have to be sent to the server. May be null. 69 | */ 70 | 71 | public HTTPProxyData(String proxyHost, int proxyPort, String proxyUser, String proxyPass, 72 | String[] requestHeaderLines) 73 | { 74 | if (proxyHost == null) 75 | throw new IllegalArgumentException("proxyHost must be non-null"); 76 | 77 | if (proxyPort < 0) 78 | throw new IllegalArgumentException("proxyPort must be non-negative"); 79 | 80 | this.proxyHost = proxyHost; 81 | this.proxyPort = proxyPort; 82 | this.proxyUser = proxyUser; 83 | this.proxyPass = proxyPass; 84 | this.requestHeaderLines = requestHeaderLines; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/HTTPProxyException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * May be thrown upon connect() if a HTTP proxy is being used. 11 | * 12 | * @see Connection#connect() 13 | * @see Connection#setProxyData(ProxyData) 14 | * 15 | * @author Christian Plattner 16 | * @version 2.50, 03/15/10 17 | */ 18 | 19 | public class HTTPProxyException extends IOException 20 | { 21 | private static final long serialVersionUID = 2241537397104426186L; 22 | 23 | public final String httpResponse; 24 | public final int httpErrorCode; 25 | 26 | public HTTPProxyException(String httpResponse, int httpErrorCode) 27 | { 28 | super("HTTP Proxy Error (" + httpErrorCode + " " + httpResponse + ")"); 29 | this.httpResponse = httpResponse; 30 | this.httpErrorCode = httpErrorCode; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/InteractiveCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | /** 8 | * An InteractiveCallback is used to respond to challenges sent 9 | * by the server if authentication mode "keyboard-interactive" is selected. 10 | * 11 | * @see Connection#authenticateWithKeyboardInteractive(String, 12 | * String[], InteractiveCallback) 13 | * 14 | * @author Christian Plattner 15 | * @version 2.50, 03/15/10 16 | */ 17 | 18 | public interface InteractiveCallback 19 | { 20 | /** 21 | * This callback interface is used during a "keyboard-interactive" 22 | * authentication. Every time the server sends a set of challenges (however, 23 | * most often just one challenge at a time), this callback function will be 24 | * called to give your application a chance to talk to the user and to 25 | * determine the response(s). 26 | *

27 | * Some copy-paste information from the standard: a command line interface 28 | * (CLI) client SHOULD print the name and instruction (if non-empty), adding 29 | * newlines. Then for each prompt in turn, the client SHOULD display the 30 | * prompt and read the user input. The name and instruction fields MAY be 31 | * empty strings, the client MUST be prepared to handle this correctly. The 32 | * prompt field(s) MUST NOT be empty strings. 33 | *

34 | * Please refer to draft-ietf-secsh-auth-kbdinteract-XX.txt for the details. 35 | *

36 | * Note: clients SHOULD use control character filtering as discussed in 37 | * RFC4251 to avoid attacks by including 38 | * terminal control characters in the fields to be displayed. 39 | * 40 | * @param name 41 | * the name String sent by the server. 42 | * @param instruction 43 | * the instruction String sent by the server. 44 | * @param numPrompts 45 | * number of prompts - may be zero (in this case, you should just 46 | * return a String array of length zero). 47 | * @param prompt 48 | * an array (length numPrompts) of Strings 49 | * @param echo 50 | * an array (length numPrompts) of booleans. For 51 | * each prompt, the corresponding echo field indicates whether or 52 | * not the user input should be echoed as characters are typed. 53 | * @return an array of reponses - the array size must match the parameter 54 | * numPrompts. 55 | */ 56 | public String[] replyToChallenge(String name, String instruction, int numPrompts, String[] prompt, boolean[] echo) 57 | throws Exception; 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/LocalPortForwarder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | import java.io.IOException; 8 | import java.net.InetSocketAddress; 9 | 10 | import ch.ethz.ssh2.channel.ChannelManager; 11 | import ch.ethz.ssh2.channel.LocalAcceptThread; 12 | 13 | /** 14 | * A LocalPortForwarder forwards TCP/IP connections to a local 15 | * port via the secure tunnel to another host (which may or may not be identical 16 | * to the remote SSH-2 server). Checkout {@link Connection#createLocalPortForwarder(int, String, int)} 17 | * on how to create one. 18 | * 19 | * @author Christian Plattner 20 | * @version 2.50, 03/15/10 21 | */ 22 | public class LocalPortForwarder 23 | { 24 | ChannelManager cm; 25 | 26 | String host_to_connect; 27 | 28 | int port_to_connect; 29 | 30 | LocalAcceptThread lat; 31 | 32 | LocalPortForwarder(ChannelManager cm, int local_port, String host_to_connect, int port_to_connect) 33 | throws IOException 34 | { 35 | this.cm = cm; 36 | this.host_to_connect = host_to_connect; 37 | this.port_to_connect = port_to_connect; 38 | 39 | lat = new LocalAcceptThread(cm, local_port, host_to_connect, port_to_connect); 40 | lat.setDaemon(true); 41 | lat.start(); 42 | } 43 | 44 | LocalPortForwarder(ChannelManager cm, InetSocketAddress addr, String host_to_connect, int port_to_connect) 45 | throws IOException 46 | { 47 | this.cm = cm; 48 | this.host_to_connect = host_to_connect; 49 | this.port_to_connect = port_to_connect; 50 | 51 | lat = new LocalAcceptThread(cm, addr, host_to_connect, port_to_connect); 52 | lat.setDaemon(true); 53 | lat.start(); 54 | } 55 | 56 | /** 57 | * Stop TCP/IP forwarding of newly arriving connections. 58 | * 59 | * @throws IOException 60 | */ 61 | public void close() throws IOException 62 | { 63 | lat.stopWorking(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/LocalStreamForwarder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | import java.net.InetAddress; 11 | 12 | import ch.ethz.ssh2.channel.Channel; 13 | import ch.ethz.ssh2.channel.ChannelManager; 14 | 15 | /** 16 | * A LocalStreamForwarder forwards an Input- and Outputstream 17 | * pair via the secure tunnel to another host (which may or may not be identical 18 | * to the remote SSH-2 server). 19 | * 20 | * @author Christian Plattner 21 | * @version 2.50, 03/15/10 22 | */ 23 | public class LocalStreamForwarder 24 | { 25 | private ChannelManager cm; 26 | 27 | private Channel cn; 28 | 29 | LocalStreamForwarder(ChannelManager cm, String host_to_connect, int port_to_connect) throws IOException 30 | { 31 | this.cm = cm; 32 | cn = cm.openDirectTCPIPChannel(host_to_connect, port_to_connect, 33 | InetAddress.getLocalHost().getHostAddress(), 0); 34 | } 35 | 36 | /** 37 | * @return An InputStream object. 38 | * @throws IOException 39 | */ 40 | public InputStream getInputStream() throws IOException 41 | { 42 | return cn.getStdoutStream(); 43 | } 44 | 45 | /** 46 | * Get the OutputStream. Please be aware that the implementation MAY use an 47 | * internal buffer. To make sure that the buffered data is sent over the 48 | * tunnel, you have to call the flush method of the 49 | * OutputStream. To signal EOF, please use the 50 | * close method of the OutputStream. 51 | * 52 | * @return An OutputStream object. 53 | * @throws IOException 54 | */ 55 | public OutputStream getOutputStream() throws IOException 56 | { 57 | return cn.getStdinStream(); 58 | } 59 | 60 | /** 61 | * Close the underlying SSH forwarding channel and free up resources. 62 | * You can also use this method to force the shutdown of the underlying 63 | * forwarding channel. Pending output (OutputStream not flushed) will NOT 64 | * be sent. Pending input (InputStream) can still be read. If the shutdown 65 | * operation is already in progress (initiated from either side), then this 66 | * call is a no-op. 67 | * 68 | * @throws IOException 69 | */ 70 | public void close() throws IOException 71 | { 72 | cm.closeChannel(cn, "Closed due to user request.", true); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/PacketListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 David Kocher. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | /** 8 | * @version $Id:$ 9 | */ 10 | public interface PacketListener { 11 | void read(String packet); 12 | 13 | void write(String packet); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/ProxyData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | /** 8 | * An abstract marker interface implemented by all proxy data implementations. 9 | * 10 | * @see HTTPProxyData 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | 16 | public abstract interface ProxyData 17 | { 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/SCPInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 David Kocher. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | import java.io.BufferedInputStream; 8 | import java.io.BufferedOutputStream; 9 | import java.io.IOException; 10 | import java.io.OutputStream; 11 | 12 | /** 13 | * @version $Id:$ 14 | */ 15 | public class SCPInputStream extends BufferedInputStream 16 | { 17 | private Session session; 18 | 19 | /** 20 | * Bytes remaining to be read from the stream 21 | */ 22 | private long remaining; 23 | 24 | public SCPInputStream(SCPClient client, Session session) throws IOException 25 | { 26 | super(session.getStdout()); 27 | 28 | this.session = session; 29 | 30 | OutputStream os = new BufferedOutputStream(session.getStdin(), 512); 31 | 32 | os.write(0x0); 33 | os.flush(); 34 | 35 | final SCPClient.LenNamePair lnp; 36 | 37 | while (true) 38 | { 39 | int c = session.getStdout().read(); 40 | if (c < 0) 41 | { 42 | throw new IOException("Remote scp terminated unexpectedly."); 43 | } 44 | 45 | String line = client.receiveLine(session.getStdout()); 46 | 47 | if (c == 'T') 48 | { 49 | /* Ignore modification times */ 50 | continue; 51 | } 52 | 53 | if ((c == 1) || (c == 2)) 54 | { 55 | throw new IOException("Remote SCP error: " + line); 56 | } 57 | 58 | if (c == 'C') 59 | { 60 | lnp = client.parseCLine(line); 61 | break; 62 | 63 | } 64 | throw new IOException("Remote SCP error: " + ((char) c) + line); 65 | } 66 | 67 | os.write(0x0); 68 | os.flush(); 69 | 70 | this.remaining = lnp.length; 71 | } 72 | 73 | @Override 74 | public int read() throws IOException 75 | { 76 | if (!(remaining > 0)) 77 | { 78 | return -1; 79 | } 80 | 81 | int read = super.read(); 82 | if (read < 0) 83 | { 84 | throw new IOException("Remote scp terminated connection unexpectedly"); 85 | } 86 | 87 | remaining -= read; 88 | 89 | return read; 90 | } 91 | 92 | @Override 93 | public int read(byte b[], int off, int len) throws IOException 94 | { 95 | if (!(remaining > 0)) 96 | { 97 | return -1; 98 | } 99 | 100 | int trans = (int) remaining; 101 | if (remaining > len) 102 | { 103 | trans = len; 104 | } 105 | 106 | int read = super.read(b, off, trans); 107 | if (read < 0) 108 | { 109 | throw new IOException("Remote scp terminated connection unexpectedly"); 110 | } 111 | 112 | remaining -= read; 113 | 114 | return read; 115 | } 116 | 117 | @Override 118 | public void close() throws IOException 119 | { 120 | try 121 | { 122 | session.getStdin().write(0x0); 123 | session.getStdin().flush(); 124 | } 125 | finally 126 | { 127 | if (session != null) 128 | { 129 | session.close(); 130 | } 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/SCPOutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 David Kocher. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | import java.io.BufferedInputStream; 8 | import java.io.BufferedOutputStream; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | 12 | import ch.ethz.ssh2.util.StringEncoder; 13 | 14 | /** 15 | * @version $Id:$ 16 | */ 17 | public class SCPOutputStream extends BufferedOutputStream 18 | { 19 | 20 | private Session session; 21 | 22 | private SCPClient scp; 23 | 24 | public SCPOutputStream(SCPClient client, Session session, final String remoteFile, long length, String mode) throws IOException 25 | { 26 | super(session.getStdin(), 40000); 27 | this.session = session; 28 | this.scp = client; 29 | 30 | InputStream is = new BufferedInputStream(session.getStdout(), 512); 31 | 32 | scp.readResponse(is); 33 | 34 | String cline = "C" + mode + " " + length + " " + remoteFile + "\n"; 35 | 36 | super.write(StringEncoder.GetBytes(cline)); 37 | this.flush(); 38 | 39 | scp.readResponse(is); 40 | } 41 | 42 | @Override 43 | public void close() throws IOException 44 | { 45 | try 46 | { 47 | this.write(0); 48 | this.flush(); 49 | 50 | scp.readResponse(session.getStdout()); 51 | 52 | this.write(StringEncoder.GetBytes("E\n")); 53 | this.flush(); 54 | } 55 | finally 56 | { 57 | if (session != null) 58 | session.close(); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/SFTPException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please see the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | import java.io.IOException; 8 | 9 | import ch.ethz.ssh2.sftp.ErrorCodes; 10 | 11 | /** 12 | * Used in combination with the SFTPv3Client. This exception wraps 13 | * error messages sent by the SFTP server. 14 | * 15 | * @author Christian Plattner 16 | * @version 2.50, 03/15/10 17 | */ 18 | 19 | public class SFTPException extends IOException 20 | { 21 | private static final long serialVersionUID = 578654644222421811L; 22 | 23 | private final String sftpErrorMessage; 24 | private final int sftpErrorCode; 25 | 26 | private static String constructMessage(String s, int errorCode) 27 | { 28 | String[] detail = ErrorCodes.getDescription(errorCode); 29 | 30 | if (detail == null) 31 | return s + " (UNKNOWN SFTP ERROR CODE)"; 32 | 33 | return s + " (" + detail[0] + ": " + detail[1] + ")"; 34 | } 35 | 36 | SFTPException(String msg, int errorCode) 37 | { 38 | super(constructMessage(msg, errorCode)); 39 | sftpErrorMessage = msg; 40 | sftpErrorCode = errorCode; 41 | } 42 | 43 | /** 44 | * Get the error message sent by the server. Often, this 45 | * message does not help a lot (e.g., "failure"). 46 | * 47 | * @return the plain string as sent by the server. 48 | */ 49 | public String getServerErrorMessage() 50 | { 51 | return sftpErrorMessage; 52 | } 53 | 54 | /** 55 | * Get the error code sent by the server. 56 | * 57 | * @return an error code as defined in the SFTP specs. 58 | */ 59 | public int getServerErrorCode() 60 | { 61 | return sftpErrorCode; 62 | } 63 | 64 | /** 65 | * Get the symbolic name of the error code as given in the SFTP specs. 66 | * 67 | * @return e.g., "SSH_FX_INVALID_FILENAME". 68 | */ 69 | public String getServerErrorCodeSymbol() 70 | { 71 | String[] detail = ErrorCodes.getDescription(sftpErrorCode); 72 | 73 | if (detail == null) 74 | return "UNKNOWN SFTP ERROR CODE " + sftpErrorCode; 75 | 76 | return detail[0]; 77 | } 78 | 79 | /** 80 | * Get the description of the error code as given in the SFTP specs. 81 | * 82 | * @return e.g., "The filename is not valid." 83 | */ 84 | public String getServerErrorCodeVerbose() 85 | { 86 | String[] detail = ErrorCodes.getDescription(sftpErrorCode); 87 | 88 | if (detail == null) 89 | return "The error code " + sftpErrorCode + " is unknown."; 90 | 91 | return detail[1]; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/SFTPInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 David Kocher. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | /** 11 | * @version $Id:$ 12 | */ 13 | public class SFTPInputStream extends InputStream 14 | { 15 | 16 | private SFTPv3FileHandle handle; 17 | 18 | /** 19 | * Offset (in bytes) in the file to read 20 | */ 21 | private long readOffset = 0; 22 | 23 | public SFTPInputStream(SFTPv3FileHandle handle) { 24 | this.handle = handle; 25 | } 26 | 27 | /** 28 | * Reads up to len bytes of data from the input stream into 29 | * an array of bytes. An attempt is made to read as many as 30 | * len bytes, but a smaller number may be read, possibly 31 | * zero. The number of bytes actually read is returned as an integer. 32 | * 33 | * @see SFTPv3Client#read(SFTPv3FileHandle,long,byte[],int,int) 34 | */ 35 | @Override 36 | public int read(byte[] buffer, int offset, int len) throws IOException 37 | { 38 | int read = handle.getClient().read(handle, readOffset, buffer, offset, len); 39 | if(read > 0) { 40 | readOffset += read; 41 | } 42 | return read; 43 | } 44 | 45 | /** 46 | * Reads the next byte of data from the input stream. The value byte is 47 | * returned as an int in the range 0 to 48 | * 255. If no byte is available because the end of the stream 49 | * has been reached, the value -1 is returned. This method 50 | * blocks until input data is available, the end of the stream is detected, 51 | * or an exception is thrown. 52 | *

53 | *

A subclass must provide an implementation of this method. 54 | * 55 | * @return the next byte of data, or -1 if the end of the 56 | * stream is reached. 57 | * @throws IOException if an I/O error occurs. 58 | */ 59 | @Override 60 | public int read() throws IOException { 61 | byte[] buffer = new byte[1]; 62 | int read = handle.getClient().read(handle, readOffset, buffer, 0, 1); 63 | if(read > 0) { 64 | readOffset += read; 65 | } 66 | return read; 67 | } 68 | 69 | /** 70 | * Skips over and discards n bytes of data from this input 71 | * stream. 72 | * 73 | * @param n the number of bytes to be skipped. 74 | * @return the actual number of bytes skipped. 75 | */ 76 | @Override 77 | public long skip(long n) { 78 | readOffset += n; 79 | return n; 80 | } 81 | 82 | @Override 83 | public void close() throws IOException { 84 | handle.getClient().closeFile(handle); 85 | } 86 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/SFTPOutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 David Kocher. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | import java.io.IOException; 8 | import java.io.OutputStream; 9 | 10 | /** 11 | * @version $Id:$ 12 | */ 13 | public class SFTPOutputStream extends OutputStream 14 | { 15 | 16 | private SFTPv3FileHandle handle; 17 | 18 | /** 19 | * Offset (in bytes) in the file to write 20 | */ 21 | private long writeOffset = 0; 22 | 23 | public SFTPOutputStream(SFTPv3FileHandle handle) { 24 | this.handle = handle; 25 | } 26 | 27 | /** 28 | * Writes len bytes from the specified byte array 29 | * starting at offset off to this output stream. 30 | * The general contract for write(b, off, len) is that 31 | * some of the bytes in the array b are written to the 32 | * output stream in order; element b[off] is the first 33 | * byte written and b[off+len-1] is the last byte written 34 | * by this operation. 35 | * 36 | * @see SFTPv3Client#write(SFTPv3FileHandle,long,byte[],int,int) 37 | */ 38 | @Override 39 | public void write(byte[] buffer, int offset, int len) throws IOException 40 | { 41 | // We can just blindly write the whole buffer at once. 42 | // if len > 32768, then the write operation will 43 | // be split into multiple writes in SFTPv3Client#write. 44 | handle.getClient().write(handle, writeOffset, buffer, offset, len); 45 | 46 | writeOffset += len; 47 | } 48 | 49 | @Override 50 | public void write(int b) throws IOException { 51 | byte[] buffer = new byte[1]; 52 | buffer[0] = (byte) b; 53 | handle.getClient().write(handle, writeOffset, buffer, 0, 1); 54 | 55 | writeOffset += 1; 56 | } 57 | 58 | public long skip(long n) { 59 | writeOffset += n; 60 | return n; 61 | } 62 | 63 | @Override 64 | public void close() throws IOException { 65 | handle.getClient().closeFile(handle); 66 | } 67 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/SFTPv3DirectoryEntry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | /** 8 | * A SFTPv3DirectoryEntry as returned by {@link SFTPv3Client#ls(String)}. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | 14 | public class SFTPv3DirectoryEntry 15 | { 16 | /** 17 | * A relative name within the directory, without any path components. 18 | */ 19 | public String filename; 20 | 21 | /** 22 | * An expanded format for the file name, similar to what is returned by 23 | * "ls -l" on Un*x systems. 24 | *

25 | * The format of this field is unspecified by the SFTP v3 protocol. 26 | * It MUST be suitable for use in the output of a directory listing 27 | * command (in fact, the recommended operation for a directory listing 28 | * command is to simply display this data). However, clients SHOULD NOT 29 | * attempt to parse the longname field for file attributes; they SHOULD 30 | * use the attrs field instead. 31 | *

32 | * The recommended format for the longname field is as follows:
33 | * -rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer 34 | */ 35 | public String longEntry; 36 | 37 | /** 38 | * The attributes of this entry. 39 | */ 40 | public SFTPv3FileAttributes attributes; 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/SFTPv3FileHandle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | /** 8 | * A SFTPv3FileHandle. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | 14 | public class SFTPv3FileHandle 15 | { 16 | protected final SFTPv3Client client; 17 | protected final byte[] fileHandle; 18 | protected boolean isClosed; 19 | 20 | protected SFTPv3FileHandle(SFTPv3Client client, byte[] h) 21 | { 22 | this.client = client; 23 | this.fileHandle = h; 24 | } 25 | 26 | /** 27 | * Get the SFTPv3Client instance which created this handle. 28 | * 29 | * @return A SFTPv3Client instance. 30 | */ 31 | public SFTPv3Client getClient() 32 | { 33 | return client; 34 | } 35 | 36 | /** 37 | * Check if this handle was closed with the {@link SFTPv3Client#closeFile(SFTPv3FileHandle)} method 38 | * of the SFTPv3Client instance which created the handle. 39 | * 40 | * @return if the handle is closed. 41 | */ 42 | public boolean isClosed() 43 | { 44 | return isClosed; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/ServerHostKeyVerifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2; 6 | 7 | /** 8 | * A callback interface used to implement a client specific method of checking 9 | * server host keys. 10 | * 11 | * @author Christian Plattner 12 | * @version 2.50, 03/15/10 13 | */ 14 | 15 | public interface ServerHostKeyVerifier 16 | { 17 | /** 18 | * The actual verifier method, it will be called by the key exchange code 19 | * on EVERY key exchange - this can happen several times during the lifetime 20 | * of a connection. 21 | *

22 | * Note: SSH-2 servers are allowed to change their hostkey at ANY time. 23 | * 24 | * @param hostname the hostname used to create the {@link Connection} object 25 | * @param port the remote TCP port 26 | * @param serverHostKeyAlgorithm the public key algorithm (ssh-rsa or ssh-dss) 27 | * @param serverHostKey the server's public key blob 28 | * @return if the client wants to accept the server's host key - if not, the 29 | * connection will be closed. 30 | * @throws Exception Will be wrapped with an IOException, extended version of returning false =) 31 | */ 32 | public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) 33 | throws Exception; 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/Version.java: -------------------------------------------------------------------------------- 1 | package ch.ethz.ssh2; 2 | 3 | /** 4 | * Provides version information from the manifest. 5 | * 6 | * @version $Id:$ 7 | */ 8 | public class Version 9 | { 10 | public static String getSpecification() 11 | { 12 | Package pkg = Version.class.getPackage(); 13 | return (pkg == null) ? null : pkg.getSpecificationVersion(); 14 | } 15 | 16 | public static String getImplementation() 17 | { 18 | Package pkg = Version.class.getPackage(); 19 | return (pkg == null) ? null : pkg.getImplementationVersion(); 20 | } 21 | 22 | /** 23 | * A simple main method that prints the version and exits 24 | */ 25 | public static void main(String[] args) 26 | { 27 | System.out.println("Version: " + getSpecification()); 28 | System.out.println("Implementation: " + getImplementation()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/channel/ChannelClosedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2011 David Kocher. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | 6 | package ch.ethz.ssh2.channel; 7 | 8 | import java.io.IOException; 9 | 10 | /** 11 | * @version $Id: ChannelClosedException.java 3183 2007-07-30 19:22:34Z dkocher $ 12 | */ 13 | public class ChannelClosedException extends IOException 14 | { 15 | 16 | /** 17 | * 18 | */ 19 | private static final long serialVersionUID = 1L; 20 | 21 | public ChannelClosedException(String s) 22 | { 23 | super(s); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/channel/ChannelInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.channel; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | /** 11 | * ChannelInputStream. 12 | * 13 | * @author Christian Plattner 14 | * @version 2.50, 03/15/10 15 | */ 16 | public final class ChannelInputStream extends InputStream 17 | { 18 | Channel c; 19 | 20 | boolean isClosed = false; 21 | boolean isEOF = false; 22 | boolean extendedFlag = false; 23 | 24 | ChannelInputStream(Channel c, boolean isExtended) 25 | { 26 | this.c = c; 27 | this.extendedFlag = isExtended; 28 | } 29 | 30 | @Override 31 | public int available() throws IOException 32 | { 33 | if (isEOF) 34 | return 0; 35 | 36 | int avail = c.cm.getAvailable(c, extendedFlag); 37 | 38 | /* We must not return -1 on EOF */ 39 | 40 | return (avail > 0) ? avail : 0; 41 | } 42 | 43 | @Override 44 | public void close() throws IOException 45 | { 46 | isClosed = true; 47 | } 48 | 49 | @Override 50 | public int read(byte[] b, int off, int len) throws IOException 51 | { 52 | if (b == null) 53 | throw new NullPointerException(); 54 | 55 | if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) 56 | throw new IndexOutOfBoundsException(); 57 | 58 | if (len == 0) 59 | return 0; 60 | 61 | if (isEOF) 62 | return -1; 63 | 64 | int ret = c.cm.getChannelData(c, extendedFlag, b, off, len); 65 | 66 | if (ret == -1) 67 | { 68 | isEOF = true; 69 | } 70 | 71 | return ret; 72 | } 73 | 74 | @Override 75 | public int read(byte[] b) throws IOException 76 | { 77 | return read(b, 0, b.length); 78 | } 79 | 80 | @Override 81 | public int read() throws IOException 82 | { 83 | /* Yes, this stream is pure and unbuffered, a single byte read() is slow */ 84 | 85 | final byte b[] = new byte[1]; 86 | 87 | int ret = read(b, 0, 1); 88 | 89 | if (ret != 1) 90 | return -1; 91 | 92 | return b[0] & 0xff; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/channel/ChannelOutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.channel; 6 | 7 | import java.io.IOException; 8 | import java.io.OutputStream; 9 | 10 | /** 11 | * ChannelOutputStream. 12 | * 13 | * @author Christian Plattner 14 | * @version 2.50, 03/15/10 15 | */ 16 | public final class ChannelOutputStream extends OutputStream 17 | { 18 | Channel c; 19 | 20 | boolean isClosed = false; 21 | 22 | ChannelOutputStream(Channel c) 23 | { 24 | this.c = c; 25 | } 26 | 27 | @Override 28 | public void write(int b) throws IOException 29 | { 30 | byte[] buff = new byte[1]; 31 | 32 | buff[0] = (byte) b; 33 | 34 | write(buff, 0, 1); 35 | } 36 | 37 | @Override 38 | public void close() throws IOException 39 | { 40 | if (isClosed == false) 41 | { 42 | isClosed = true; 43 | c.cm.sendEOF(c); 44 | } 45 | } 46 | 47 | @Override 48 | public void flush() throws IOException 49 | { 50 | if (isClosed) 51 | throw new IOException("This OutputStream is closed."); 52 | 53 | /* This is a no-op, since this stream is unbuffered */ 54 | } 55 | 56 | @Override 57 | public void write(byte[] b, int off, int len) throws IOException 58 | { 59 | if (isClosed) 60 | throw new IOException("This OutputStream is closed."); 61 | 62 | if (b == null) 63 | throw new NullPointerException(); 64 | 65 | if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) 66 | throw new IndexOutOfBoundsException(); 67 | 68 | if (len == 0) 69 | return; 70 | 71 | c.cm.sendData(c, b, off, len); 72 | } 73 | 74 | @Override 75 | public void write(byte[] b) throws IOException 76 | { 77 | write(b, 0, b.length); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/channel/IChannelWorkerThread.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.channel; 6 | 7 | /** 8 | * IChannelWorkerThread. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | interface IChannelWorkerThread 14 | { 15 | public void stopWorking(); 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/channel/LocalAcceptThread.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.channel; 6 | 7 | import java.io.IOException; 8 | import java.net.InetSocketAddress; 9 | import java.net.ServerSocket; 10 | import java.net.Socket; 11 | 12 | /** 13 | * LocalAcceptThread. 14 | * 15 | * @author Christian Plattner 16 | * @version 2.50, 03/15/10 17 | */ 18 | public class LocalAcceptThread extends Thread implements IChannelWorkerThread 19 | { 20 | ChannelManager cm; 21 | String host_to_connect; 22 | int port_to_connect; 23 | 24 | final ServerSocket ss; 25 | 26 | public LocalAcceptThread(ChannelManager cm, int local_port, String host_to_connect, int port_to_connect) 27 | throws IOException 28 | { 29 | this.cm = cm; 30 | this.host_to_connect = host_to_connect; 31 | this.port_to_connect = port_to_connect; 32 | 33 | ss = new ServerSocket(local_port); 34 | } 35 | 36 | public LocalAcceptThread(ChannelManager cm, InetSocketAddress localAddress, String host_to_connect, 37 | int port_to_connect) throws IOException 38 | { 39 | this.cm = cm; 40 | this.host_to_connect = host_to_connect; 41 | this.port_to_connect = port_to_connect; 42 | 43 | ss = new ServerSocket(); 44 | ss.bind(localAddress); 45 | } 46 | 47 | @Override 48 | public void run() 49 | { 50 | try 51 | { 52 | cm.registerThread(this); 53 | } 54 | catch (IOException e) 55 | { 56 | stopWorking(); 57 | return; 58 | } 59 | 60 | while (true) 61 | { 62 | Socket s = null; 63 | 64 | try 65 | { 66 | s = ss.accept(); 67 | } 68 | catch (IOException e) 69 | { 70 | stopWorking(); 71 | return; 72 | } 73 | 74 | Channel cn = null; 75 | StreamForwarder r2l = null; 76 | StreamForwarder l2r = null; 77 | 78 | try 79 | { 80 | /* This may fail, e.g., if the remote port is closed (in optimistic terms: not open yet) */ 81 | 82 | cn = cm.openDirectTCPIPChannel(host_to_connect, port_to_connect, s.getInetAddress().getHostAddress(), s 83 | .getPort()); 84 | 85 | } 86 | catch (IOException e) 87 | { 88 | /* Simply close the local socket and wait for the next incoming connection */ 89 | 90 | try 91 | { 92 | s.close(); 93 | } 94 | catch (IOException ignore) 95 | { 96 | } 97 | 98 | continue; 99 | } 100 | 101 | try 102 | { 103 | r2l = new StreamForwarder(cn, null, null, cn.stdoutStream, s.getOutputStream(), "RemoteToLocal"); 104 | l2r = new StreamForwarder(cn, r2l, s, s.getInputStream(), cn.stdinStream, "LocalToRemote"); 105 | } 106 | catch (IOException e) 107 | { 108 | try 109 | { 110 | /* This message is only visible during debugging, since we discard the channel immediatelly */ 111 | cn.cm.closeChannel(cn, "Weird error during creation of StreamForwarder (" + e.getMessage() + ")", 112 | true); 113 | } 114 | catch (IOException ignore) 115 | { 116 | } 117 | 118 | continue; 119 | } 120 | 121 | r2l.setDaemon(true); 122 | l2r.setDaemon(true); 123 | r2l.start(); 124 | l2r.start(); 125 | } 126 | } 127 | 128 | public void stopWorking() 129 | { 130 | try 131 | { 132 | /* This will lead to an IOException in the ss.accept() call */ 133 | ss.close(); 134 | } 135 | catch (IOException ignored) 136 | { 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/channel/RemoteAcceptThread.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.channel; 6 | 7 | import java.io.IOException; 8 | import java.net.Socket; 9 | 10 | import ch.ethz.ssh2.log.Logger; 11 | 12 | /** 13 | * RemoteAcceptThread. 14 | * 15 | * @author Christian Plattner 16 | * @version $Id$ 17 | */ 18 | public class RemoteAcceptThread extends Thread 19 | { 20 | private static final Logger log = Logger.getLogger(RemoteAcceptThread.class); 21 | 22 | Channel c; 23 | 24 | String remoteConnectedAddress; 25 | int remoteConnectedPort; 26 | String remoteOriginatorAddress; 27 | int remoteOriginatorPort; 28 | String targetAddress; 29 | int targetPort; 30 | 31 | Socket s; 32 | 33 | public RemoteAcceptThread(Channel c, String remoteConnectedAddress, int remoteConnectedPort, 34 | String remoteOriginatorAddress, int remoteOriginatorPort, String targetAddress, int targetPort) 35 | { 36 | this.c = c; 37 | this.remoteConnectedAddress = remoteConnectedAddress; 38 | this.remoteConnectedPort = remoteConnectedPort; 39 | this.remoteOriginatorAddress = remoteOriginatorAddress; 40 | this.remoteOriginatorPort = remoteOriginatorPort; 41 | this.targetAddress = targetAddress; 42 | this.targetPort = targetPort; 43 | 44 | log.debug("RemoteAcceptThread: " + remoteConnectedAddress + "/" + remoteConnectedPort + ", R: " 45 | + remoteOriginatorAddress + "/" + remoteOriginatorPort); 46 | } 47 | 48 | @Override 49 | public void run() 50 | { 51 | try 52 | { 53 | c.cm.sendOpenConfirmation(c); 54 | 55 | s = new Socket(targetAddress, targetPort); 56 | 57 | StreamForwarder r2l = new StreamForwarder(c, null, null, c.getStdoutStream(), s.getOutputStream(), 58 | "RemoteToLocal"); 59 | StreamForwarder l2r = new StreamForwarder(c, null, null, s.getInputStream(), c.getStdinStream(), 60 | "LocalToRemote"); 61 | 62 | /* No need to start two threads, one can be executed in the current thread */ 63 | 64 | r2l.setDaemon(true); 65 | r2l.start(); 66 | l2r.run(); 67 | 68 | while (r2l.isAlive()) 69 | { 70 | try 71 | { 72 | r2l.join(); 73 | } 74 | catch (InterruptedException ignored) 75 | { 76 | } 77 | } 78 | 79 | /* If the channel is already closed, then this is a no-op */ 80 | 81 | c.cm.closeChannel(c, "EOF on both streams reached.", true); 82 | s.close(); 83 | } 84 | catch (IOException e) 85 | { 86 | log.warning("IOException in proxy code: " + e.getMessage()); 87 | 88 | try 89 | { 90 | c.cm.closeChannel(c, "IOException in proxy code (" + e.getMessage() + ")", true); 91 | } 92 | catch (IOException ignored) 93 | { 94 | } 95 | try 96 | { 97 | if (s != null) 98 | s.close(); 99 | } 100 | catch (IOException ignored) 101 | { 102 | } 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/channel/RemoteForwardingData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.channel; 6 | 7 | /** 8 | * RemoteForwardingData. Data about a requested remote forwarding. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class RemoteForwardingData 14 | { 15 | public String bindAddress; 16 | public int bindPort; 17 | 18 | String targetAddress; 19 | int targetPort; 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/channel/StreamForwarder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.channel; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | import java.net.Socket; 11 | 12 | /** 13 | * A StreamForwarder forwards data between two given streams. 14 | * If two StreamForwarder threads are used (one for each direction) 15 | * then one can be configured to shutdown the underlying channel/socket 16 | * if both threads have finished forwarding (EOF). 17 | * 18 | * @author Christian Plattner 19 | * @version 2.50, 03/15/10 20 | */ 21 | public class StreamForwarder extends Thread 22 | { 23 | OutputStream os; 24 | InputStream is; 25 | byte[] buffer = new byte[Channel.CHANNEL_BUFFER_SIZE]; 26 | Channel c; 27 | StreamForwarder sibling; 28 | Socket s; 29 | String mode; 30 | 31 | StreamForwarder(Channel c, StreamForwarder sibling, Socket s, InputStream is, OutputStream os, String mode) 32 | throws IOException 33 | { 34 | this.is = is; 35 | this.os = os; 36 | this.mode = mode; 37 | this.c = c; 38 | this.sibling = sibling; 39 | this.s = s; 40 | } 41 | 42 | @Override 43 | public void run() 44 | { 45 | try 46 | { 47 | while (true) 48 | { 49 | int len = is.read(buffer); 50 | if (len <= 0) 51 | break; 52 | os.write(buffer, 0, len); 53 | os.flush(); 54 | } 55 | } 56 | catch (IOException ignore) 57 | { 58 | try 59 | { 60 | c.cm.closeChannel(c, "Closed due to exception in StreamForwarder (" + mode + "): " 61 | + ignore.getMessage(), true); 62 | } 63 | catch (IOException ignored) 64 | { 65 | } 66 | } 67 | finally 68 | { 69 | try 70 | { 71 | os.close(); 72 | } 73 | catch (IOException ignored) 74 | { 75 | } 76 | try 77 | { 78 | is.close(); 79 | } 80 | catch (IOException ignored) 81 | { 82 | } 83 | 84 | if (sibling != null) 85 | { 86 | while (sibling.isAlive()) 87 | { 88 | try 89 | { 90 | sibling.join(); 91 | } 92 | catch (InterruptedException ignored) 93 | { 94 | } 95 | } 96 | 97 | try 98 | { 99 | c.cm.closeChannel(c, "StreamForwarder (" + mode + ") is cleaning up the connection", true); 100 | } 101 | catch (IOException ignored) 102 | { 103 | } 104 | 105 | try 106 | { 107 | if (s != null) 108 | s.close(); 109 | } 110 | catch (IOException ignored) 111 | { 112 | } 113 | } 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/channel/X11ServerData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.channel; 6 | 7 | /** 8 | * X11ServerData. Data regarding an x11 forwarding target. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | * 13 | */ 14 | public class X11ServerData 15 | { 16 | public String hostname; 17 | public int port; 18 | public byte[] x11_magic_cookie; /* not the remote (fake) one, the local (real) one */ 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/Base64.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto; 6 | 7 | import java.io.CharArrayWriter; 8 | import java.io.IOException; 9 | 10 | /** 11 | * Basic Base64 Support. 12 | * 13 | * @author Christian Plattner 14 | * @version 2.50, 03/15/10 15 | */ 16 | public class Base64 17 | { 18 | static final char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); 19 | 20 | public static char[] encode(byte[] content) 21 | { 22 | CharArrayWriter cw = new CharArrayWriter((4 * content.length) / 3); 23 | 24 | int idx = 0; 25 | 26 | int x = 0; 27 | 28 | for (int i = 0; i < content.length; i++) 29 | { 30 | if (idx == 0) 31 | x = (content[i] & 0xff) << 16; 32 | else if (idx == 1) 33 | x = x | ((content[i] & 0xff) << 8); 34 | else 35 | x = x | (content[i] & 0xff); 36 | 37 | idx++; 38 | 39 | if (idx == 3) 40 | { 41 | cw.write(alphabet[x >> 18]); 42 | cw.write(alphabet[(x >> 12) & 0x3f]); 43 | cw.write(alphabet[(x >> 6) & 0x3f]); 44 | cw.write(alphabet[x & 0x3f]); 45 | 46 | idx = 0; 47 | } 48 | } 49 | 50 | if (idx == 1) 51 | { 52 | cw.write(alphabet[x >> 18]); 53 | cw.write(alphabet[(x >> 12) & 0x3f]); 54 | cw.write('='); 55 | cw.write('='); 56 | } 57 | 58 | if (idx == 2) 59 | { 60 | cw.write(alphabet[x >> 18]); 61 | cw.write(alphabet[(x >> 12) & 0x3f]); 62 | cw.write(alphabet[(x >> 6) & 0x3f]); 63 | cw.write('='); 64 | } 65 | 66 | return cw.toCharArray(); 67 | } 68 | 69 | public static byte[] decode(char[] message) throws IOException 70 | { 71 | byte buff[] = new byte[4]; 72 | byte dest[] = new byte[message.length]; 73 | 74 | int bpos = 0; 75 | int destpos = 0; 76 | 77 | for (int i = 0; i < message.length; i++) 78 | { 79 | int c = message[i]; 80 | 81 | if ((c == '\n') || (c == '\r') || (c == ' ') || (c == '\t')) 82 | continue; 83 | 84 | if ((c >= 'A') && (c <= 'Z')) 85 | { 86 | buff[bpos++] = (byte) (c - 'A'); 87 | } 88 | else if ((c >= 'a') && (c <= 'z')) 89 | { 90 | buff[bpos++] = (byte) ((c - 'a') + 26); 91 | } 92 | else if ((c >= '0') && (c <= '9')) 93 | { 94 | buff[bpos++] = (byte) ((c - '0') + 52); 95 | } 96 | else if (c == '+') 97 | { 98 | buff[bpos++] = 62; 99 | } 100 | else if (c == '/') 101 | { 102 | buff[bpos++] = 63; 103 | } 104 | else if (c == '=') 105 | { 106 | buff[bpos++] = 64; 107 | } 108 | else 109 | { 110 | throw new IOException("Illegal char in base64 code."); 111 | } 112 | 113 | if (bpos == 4) 114 | { 115 | bpos = 0; 116 | 117 | if (buff[0] == 64) 118 | break; 119 | 120 | if (buff[1] == 64) 121 | throw new IOException("Unexpected '=' in base64 code."); 122 | 123 | if (buff[2] == 64) 124 | { 125 | int v = (((buff[0] & 0x3f) << 6) | ((buff[1] & 0x3f))); 126 | dest[destpos++] = (byte) (v >> 4); 127 | break; 128 | } 129 | else if (buff[3] == 64) 130 | { 131 | int v = (((buff[0] & 0x3f) << 12) | ((buff[1] & 0x3f) << 6) | ((buff[2] & 0x3f))); 132 | dest[destpos++] = (byte) (v >> 10); 133 | dest[destpos++] = (byte) (v >> 2); 134 | break; 135 | } 136 | else 137 | { 138 | int v = (((buff[0] & 0x3f) << 18) | ((buff[1] & 0x3f) << 12) | ((buff[2] & 0x3f) << 6) | ((buff[3] & 0x3f))); 139 | dest[destpos++] = (byte) (v >> 16); 140 | dest[destpos++] = (byte) (v >> 8); 141 | dest[destpos++] = (byte) (v); 142 | } 143 | } 144 | } 145 | 146 | byte[] res = new byte[destpos]; 147 | System.arraycopy(dest, 0, res, 0, destpos); 148 | 149 | return res; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/CryptoWishList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto; 6 | 7 | import ch.ethz.ssh2.crypto.cipher.BlockCipherFactory; 8 | import ch.ethz.ssh2.crypto.digest.MAC; 9 | import ch.ethz.ssh2.transport.KexManager; 10 | 11 | /** 12 | * CryptoWishList. 13 | * 14 | * @author Christian Plattner 15 | * @version 2.50, 03/15/10 16 | */ 17 | public class CryptoWishList 18 | { 19 | public String[] kexAlgorithms = KexManager.getDefaultKexAlgorithmList(); 20 | public String[] serverHostKeyAlgorithms = KexManager.getDefaultServerHostkeyAlgorithmList(); 21 | public String[] c2s_enc_algos = BlockCipherFactory.getDefaultCipherList(); 22 | public String[] s2c_enc_algos = BlockCipherFactory.getDefaultCipherList(); 23 | public String[] c2s_mac_algos = MAC.getMacList(); 24 | public String[] s2c_mac_algos = MAC.getMacList(); 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/KeyMaterial.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto; 6 | 7 | import ch.ethz.ssh2.crypto.digest.HashForSSH2Types; 8 | import java.math.BigInteger; 9 | 10 | /** 11 | * Establishes key material for iv/key/mac (both directions). 12 | * 13 | * @author Christian Plattner 14 | * @version 2.50, 03/15/10 15 | */ 16 | public class KeyMaterial 17 | { 18 | public byte[] initial_iv_client_to_server; 19 | public byte[] initial_iv_server_to_client; 20 | public byte[] enc_key_client_to_server; 21 | public byte[] enc_key_server_to_client; 22 | public byte[] integrity_key_client_to_server; 23 | public byte[] integrity_key_server_to_client; 24 | 25 | private static byte[] calculateKey(HashForSSH2Types sh, BigInteger K, byte[] H, byte type, byte[] SessionID, 26 | int keyLength) 27 | { 28 | byte[] res = new byte[keyLength]; 29 | 30 | int dglen = sh.getDigestLength(); 31 | int numRounds = (keyLength + dglen - 1) / dglen; 32 | 33 | byte[][] tmp = new byte[numRounds][]; 34 | 35 | sh.reset(); 36 | sh.updateBigInt(K); 37 | sh.updateBytes(H); 38 | sh.updateByte(type); 39 | sh.updateBytes(SessionID); 40 | 41 | tmp[0] = sh.getDigest(); 42 | 43 | int off = 0; 44 | int produced = Math.min(dglen, keyLength); 45 | 46 | System.arraycopy(tmp[0], 0, res, off, produced); 47 | 48 | keyLength -= produced; 49 | off += produced; 50 | 51 | for (int i = 1; i < numRounds; i++) 52 | { 53 | sh.updateBigInt(K); 54 | sh.updateBytes(H); 55 | 56 | for (int j = 0; j < i; j++) 57 | sh.updateBytes(tmp[j]); 58 | 59 | tmp[i] = sh.getDigest(); 60 | 61 | produced = Math.min(dglen, keyLength); 62 | System.arraycopy(tmp[i], 0, res, off, produced); 63 | keyLength -= produced; 64 | off += produced; 65 | } 66 | 67 | return res; 68 | } 69 | 70 | public static KeyMaterial create(String hashType, byte[] H, BigInteger K, byte[] SessionID, int keyLengthCS, 71 | int blockSizeCS, int macLengthCS, int keyLengthSC, int blockSizeSC, int macLengthSC) 72 | throws IllegalArgumentException 73 | { 74 | KeyMaterial km = new KeyMaterial(); 75 | 76 | HashForSSH2Types sh = new HashForSSH2Types(hashType); 77 | 78 | km.initial_iv_client_to_server = calculateKey(sh, K, H, (byte) 'A', SessionID, blockSizeCS); 79 | 80 | km.initial_iv_server_to_client = calculateKey(sh, K, H, (byte) 'B', SessionID, blockSizeSC); 81 | 82 | km.enc_key_client_to_server = calculateKey(sh, K, H, (byte) 'C', SessionID, keyLengthCS); 83 | 84 | km.enc_key_server_to_client = calculateKey(sh, K, H, (byte) 'D', SessionID, keyLengthSC); 85 | 86 | km.integrity_key_client_to_server = calculateKey(sh, K, H, (byte) 'E', SessionID, macLengthCS); 87 | 88 | km.integrity_key_server_to_client = calculateKey(sh, K, H, (byte) 'F', SessionID, macLengthSC); 89 | 90 | return km; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/PEMDecryptException.java: -------------------------------------------------------------------------------- 1 | 2 | package ch.ethz.ssh2.crypto; 3 | 4 | /* 5 | * Copyright (c) 2002-2010 David Kocher. All rights reserved. 6 | * 7 | * http://cyberduck.ch/ 8 | * 9 | * This program is free software; you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation; either version 2 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * Bug fixes, suggestions and comments should be sent to: 20 | * dkocher@cyberduck.ch 21 | */ 22 | 23 | import java.io.IOException; 24 | 25 | /** 26 | * @version $Id: PEMDecryptException.java 5865 2010-03-27 03:28:11Z dkocher $ 27 | */ 28 | public class PEMDecryptException extends IOException 29 | { 30 | /** 31 | * 32 | */ 33 | private static final long serialVersionUID = 1L; 34 | 35 | public PEMDecryptException(String message) 36 | { 37 | super(message); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/PEMStructure.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto; 6 | 7 | /** 8 | * Parsed PEM structure. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | 14 | public class PEMStructure 15 | { 16 | int pemType; 17 | String dekInfo[]; 18 | String procType[]; 19 | byte[] data; 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/SimpleDERReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto; 6 | 7 | import java.io.IOException; 8 | 9 | import java.math.BigInteger; 10 | 11 | /** 12 | * SimpleDERReader. 13 | * 14 | * @author Christian Plattner 15 | * @version 2.50, 03/15/10 16 | */ 17 | public class SimpleDERReader 18 | { 19 | byte[] buffer; 20 | int pos; 21 | int count; 22 | 23 | public SimpleDERReader(byte[] b) 24 | { 25 | resetInput(b); 26 | } 27 | 28 | public SimpleDERReader(byte[] b, int off, int len) 29 | { 30 | resetInput(b, off, len); 31 | } 32 | 33 | public void resetInput(byte[] b) 34 | { 35 | resetInput(b, 0, b.length); 36 | } 37 | 38 | public void resetInput(byte[] b, int off, int len) 39 | { 40 | buffer = b; 41 | pos = off; 42 | count = len; 43 | } 44 | 45 | private byte readByte() throws IOException 46 | { 47 | if (count <= 0) 48 | throw new IOException("DER byte array: out of data"); 49 | count--; 50 | return buffer[pos++]; 51 | } 52 | 53 | private byte[] readBytes(int len) throws IOException 54 | { 55 | if (len > count) 56 | throw new IOException("DER byte array: out of data"); 57 | 58 | byte[] b = new byte[len]; 59 | 60 | System.arraycopy(buffer, pos, b, 0, len); 61 | 62 | pos += len; 63 | count -= len; 64 | 65 | return b; 66 | } 67 | 68 | public int available() 69 | { 70 | return count; 71 | } 72 | 73 | private int readLength() throws IOException 74 | { 75 | int len = readByte() & 0xff; 76 | 77 | if ((len & 0x80) == 0) 78 | return len; 79 | 80 | int remain = len & 0x7F; 81 | 82 | if (remain == 0) 83 | return -1; 84 | 85 | len = 0; 86 | 87 | while (remain > 0) 88 | { 89 | len = len << 8; 90 | len = len | (readByte() & 0xff); 91 | remain--; 92 | } 93 | 94 | return len; 95 | } 96 | 97 | public int ignoreNextObject() throws IOException 98 | { 99 | int type = readByte() & 0xff; 100 | 101 | int len = readLength(); 102 | 103 | if ((len < 0) || len > available()) 104 | throw new IOException("Illegal len in DER object (" + len + ")"); 105 | 106 | readBytes(len); 107 | 108 | return type; 109 | } 110 | 111 | public BigInteger readInt() throws IOException 112 | { 113 | int type = readByte() & 0xff; 114 | 115 | if (type != 0x02) 116 | throw new IOException("Expected DER Integer, but found type " + type); 117 | 118 | int len = readLength(); 119 | 120 | if ((len < 0) || len > available()) 121 | throw new IOException("Illegal len in DER object (" + len + ")"); 122 | 123 | byte[] b = readBytes(len); 124 | 125 | return new BigInteger(b); 126 | } 127 | 128 | public byte[] readSequenceAsByteArray() throws IOException 129 | { 130 | int type = readByte() & 0xff; 131 | 132 | if (type != 0x30) 133 | throw new IOException("Expected DER Sequence, but found type " + type); 134 | 135 | int len = readLength(); 136 | 137 | if ((len < 0) || len > available()) 138 | throw new IOException("Illegal len in DER object (" + len + ")"); 139 | 140 | return readBytes(len); 141 | } 142 | 143 | public byte[] readOctetString() throws IOException 144 | { 145 | int type = readByte() & 0xff; 146 | 147 | if (type != 0x04) 148 | throw new IOException("Expected DER Octetstring, but found type " + type); 149 | 150 | int len = readLength(); 151 | 152 | if ((len < 0) || len > available()) 153 | throw new IOException("Illegal len in DER object (" + len + ")"); 154 | 155 | return readBytes(len); 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/cipher/BlockCipher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto.cipher; 6 | 7 | /** 8 | * BlockCipher. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public interface BlockCipher 14 | { 15 | public void init(boolean forEncryption, byte[] key); 16 | 17 | public int getBlockSize(); 18 | 19 | public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff); 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/cipher/BlockCipherFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto.cipher; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.Vector; 10 | 11 | /** 12 | * BlockCipherFactory. 13 | * 14 | * @author Christian Plattner 15 | * @version $Id$ 16 | */ 17 | public class BlockCipherFactory 18 | { 19 | private static final class CipherEntry 20 | { 21 | String type; 22 | int blocksize; 23 | int keysize; 24 | String cipherClass; 25 | 26 | public CipherEntry(String type, int blockSize, int keySize, String cipherClass) 27 | { 28 | this.type = type; 29 | this.blocksize = blockSize; 30 | this.keysize = keySize; 31 | this.cipherClass = cipherClass; 32 | } 33 | } 34 | 35 | private static final List ciphers = new Vector(); 36 | 37 | static 38 | { 39 | /* Higher Priority First */ 40 | ciphers.add(new CipherEntry("aes128-ctr", 16, 16, "ch.ethz.ssh2.crypto.cipher.AES")); 41 | ciphers.add(new CipherEntry("aes192-ctr", 16, 24, "ch.ethz.ssh2.crypto.cipher.AES")); 42 | ciphers.add(new CipherEntry("aes256-ctr", 16, 32, "ch.ethz.ssh2.crypto.cipher.AES")); 43 | ciphers.add(new CipherEntry("blowfish-ctr", 8, 16, "ch.ethz.ssh2.crypto.cipher.BlowFish")); 44 | 45 | ciphers.add(new CipherEntry("aes128-cbc", 16, 16, "ch.ethz.ssh2.crypto.cipher.AES")); 46 | ciphers.add(new CipherEntry("aes192-cbc", 16, 24, "ch.ethz.ssh2.crypto.cipher.AES")); 47 | ciphers.add(new CipherEntry("aes256-cbc", 16, 32, "ch.ethz.ssh2.crypto.cipher.AES")); 48 | ciphers.add(new CipherEntry("blowfish-cbc", 8, 16, "ch.ethz.ssh2.crypto.cipher.BlowFish")); 49 | 50 | ciphers.add(new CipherEntry("3des-ctr", 8, 24, "ch.ethz.ssh2.crypto.cipher.DESede")); 51 | ciphers.add(new CipherEntry("3des-cbc", 8, 24, "ch.ethz.ssh2.crypto.cipher.DESede")); 52 | } 53 | 54 | public static String[] getDefaultCipherList() 55 | { 56 | List list = new ArrayList(ciphers.size()); 57 | for (CipherEntry ce : ciphers) 58 | { 59 | list.add(ce.type); 60 | } 61 | return list.toArray(new String[ciphers.size()]); 62 | } 63 | 64 | public static void checkCipherList(String[] cipherCandidates) 65 | { 66 | for (String cipherCandidate : cipherCandidates) 67 | { 68 | getEntry(cipherCandidate); 69 | } 70 | } 71 | 72 | // @SuppressWarnings("rawtypes") 73 | public static BlockCipher createCipher(String type, boolean encrypt, byte[] key, byte[] iv) 74 | { 75 | try 76 | { 77 | CipherEntry ce = getEntry(type); 78 | Class cc = Class.forName(ce.cipherClass); 79 | BlockCipher bc = (BlockCipher) cc.newInstance(); 80 | 81 | if (type.endsWith("-cbc")) 82 | { 83 | bc.init(encrypt, key); 84 | return new CBCMode(bc, iv, encrypt); 85 | } 86 | else if (type.endsWith("-ctr")) 87 | { 88 | bc.init(true, key); 89 | return new CTRMode(bc, iv, encrypt); 90 | } 91 | throw new IllegalArgumentException("Cannot instantiate " + type); 92 | } 93 | catch (ClassNotFoundException e) 94 | { 95 | throw new IllegalArgumentException("Cannot instantiate " + type, e); 96 | } 97 | catch (InstantiationException e) 98 | { 99 | throw new IllegalArgumentException("Cannot instantiate " + type, e); 100 | } 101 | catch (IllegalAccessException e) 102 | { 103 | throw new IllegalArgumentException("Cannot instantiate " + type, e); 104 | } 105 | } 106 | 107 | private static CipherEntry getEntry(String type) 108 | { 109 | for (CipherEntry ce : ciphers) 110 | { 111 | if (ce.type.equals(type)) 112 | { 113 | return ce; 114 | } 115 | } 116 | throw new IllegalArgumentException("Unkown algorithm " + type); 117 | } 118 | 119 | public static int getBlockSize(String type) 120 | { 121 | CipherEntry ce = getEntry(type); 122 | return ce.blocksize; 123 | } 124 | 125 | public static int getKeySize(String type) 126 | { 127 | CipherEntry ce = getEntry(type); 128 | return ce.keysize; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/cipher/CBCMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto.cipher; 6 | 7 | /** 8 | * CBCMode. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class CBCMode implements BlockCipher 14 | { 15 | BlockCipher tc; 16 | int blockSize; 17 | boolean doEncrypt; 18 | 19 | byte[] cbc_vector; 20 | byte[] tmp_vector; 21 | 22 | public void init(boolean forEncryption, byte[] key) 23 | { 24 | } 25 | 26 | public CBCMode(BlockCipher tc, byte[] iv, boolean doEncrypt) 27 | throws IllegalArgumentException 28 | { 29 | this.tc = tc; 30 | this.blockSize = tc.getBlockSize(); 31 | this.doEncrypt = doEncrypt; 32 | 33 | if (this.blockSize != iv.length) 34 | throw new IllegalArgumentException("IV must be " + blockSize 35 | + " bytes long! (currently " + iv.length + ")"); 36 | 37 | this.cbc_vector = new byte[blockSize]; 38 | this.tmp_vector = new byte[blockSize]; 39 | System.arraycopy(iv, 0, cbc_vector, 0, blockSize); 40 | } 41 | 42 | public int getBlockSize() 43 | { 44 | return blockSize; 45 | } 46 | 47 | private void encryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff) 48 | { 49 | for (int i = 0; i < blockSize; i++) 50 | cbc_vector[i] ^= src[srcoff + i]; 51 | 52 | tc.transformBlock(cbc_vector, 0, dst, dstoff); 53 | 54 | System.arraycopy(dst, dstoff, cbc_vector, 0, blockSize); 55 | } 56 | 57 | private void decryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff) 58 | { 59 | /* Assume the worst, src and dst are overlapping... */ 60 | 61 | System.arraycopy(src, srcoff, tmp_vector, 0, blockSize); 62 | 63 | tc.transformBlock(src, srcoff, dst, dstoff); 64 | 65 | for (int i = 0; i < blockSize; i++) 66 | dst[dstoff + i] ^= cbc_vector[i]; 67 | 68 | /* ...that is why we need a tmp buffer. */ 69 | 70 | byte[] swap = cbc_vector; 71 | cbc_vector = tmp_vector; 72 | tmp_vector = swap; 73 | } 74 | 75 | public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) 76 | { 77 | if (doEncrypt) 78 | encryptBlock(src, srcoff, dst, dstoff); 79 | else 80 | decryptBlock(src, srcoff, dst, dstoff); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/cipher/CTRMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto.cipher; 6 | 7 | /** 8 | * This is CTR mode as described in draft-ietf-secsh-newmodes-XY.txt 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class CTRMode implements BlockCipher 14 | { 15 | byte[] X; 16 | byte[] Xenc; 17 | 18 | BlockCipher bc; 19 | int blockSize; 20 | boolean doEncrypt; 21 | 22 | int count = 0; 23 | 24 | public void init(boolean forEncryption, byte[] key) 25 | { 26 | } 27 | 28 | public CTRMode(BlockCipher tc, byte[] iv, boolean doEnc) throws IllegalArgumentException 29 | { 30 | bc = tc; 31 | blockSize = bc.getBlockSize(); 32 | doEncrypt = doEnc; 33 | 34 | if (blockSize != iv.length) 35 | throw new IllegalArgumentException("IV must be " + blockSize + " bytes long! (currently " + iv.length + ")"); 36 | 37 | X = new byte[blockSize]; 38 | Xenc = new byte[blockSize]; 39 | 40 | System.arraycopy(iv, 0, X, 0, blockSize); 41 | } 42 | 43 | public final int getBlockSize() 44 | { 45 | return blockSize; 46 | } 47 | 48 | public final void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) 49 | { 50 | bc.transformBlock(X, 0, Xenc, 0); 51 | 52 | for (int i = 0; i < blockSize; i++) 53 | { 54 | dst[dstoff + i] = (byte) (src[srcoff + i] ^ Xenc[i]); 55 | } 56 | 57 | for (int i = (blockSize - 1); i >= 0; i--) 58 | { 59 | X[i]++; 60 | if (X[i] != 0) 61 | break; 62 | 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/cipher/CipherInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto.cipher; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | /** 11 | * CipherInputStream. 12 | * 13 | * @author Christian Plattner 14 | * @version $Id$ 15 | */ 16 | public class CipherInputStream 17 | { 18 | BlockCipher currentCipher; 19 | InputStream bi; 20 | byte[] buffer; 21 | byte[] enc; 22 | int blockSize; 23 | int pos; 24 | 25 | /* 26 | * We cannot use java.io.BufferedInputStream, since that is not available in 27 | * J2ME. Everything could be improved alot here. 28 | */ 29 | 30 | private static final int BUFF_SIZE = 8192; 31 | byte[] input_buffer = new byte[BUFF_SIZE]; 32 | int input_buffer_pos = 0; 33 | int input_buffer_size = 0; 34 | 35 | public CipherInputStream(BlockCipher tc, InputStream bi) 36 | { 37 | this.bi = bi; 38 | changeCipher(tc); 39 | } 40 | 41 | private int fill_buffer() throws IOException 42 | { 43 | input_buffer_pos = 0; 44 | input_buffer_size = 0; 45 | input_buffer_size = bi.read(input_buffer, 0, BUFF_SIZE); 46 | return input_buffer_size; 47 | } 48 | 49 | private int internal_read(byte[] b, int off, int len) throws IOException 50 | { 51 | if (input_buffer_size < 0) 52 | { 53 | return -1; 54 | } 55 | 56 | if (input_buffer_pos >= input_buffer_size) 57 | { 58 | if (fill_buffer() <= 0) 59 | { 60 | return -1; 61 | } 62 | } 63 | 64 | int avail = input_buffer_size - input_buffer_pos; 65 | int thiscopy = (len > avail) ? avail : len; 66 | 67 | System.arraycopy(input_buffer, input_buffer_pos, b, off, thiscopy); 68 | input_buffer_pos += thiscopy; 69 | 70 | return thiscopy; 71 | } 72 | 73 | public void changeCipher(BlockCipher bc) 74 | { 75 | this.currentCipher = bc; 76 | blockSize = bc.getBlockSize(); 77 | buffer = new byte[blockSize]; 78 | enc = new byte[blockSize]; 79 | pos = blockSize; 80 | } 81 | 82 | private void getBlock() throws IOException 83 | { 84 | int n = 0; 85 | while (n < blockSize) 86 | { 87 | int len = internal_read(enc, n, blockSize - n); 88 | if (len < 0) 89 | { 90 | throw new IOException("Cannot read full block, EOF reached."); 91 | } 92 | n += len; 93 | } 94 | 95 | try 96 | { 97 | currentCipher.transformBlock(enc, 0, buffer, 0); 98 | } 99 | catch (Exception e) 100 | { 101 | throw new IOException("Error while decrypting block."); 102 | } 103 | pos = 0; 104 | } 105 | 106 | public int read(byte[] dst) throws IOException 107 | { 108 | return read(dst, 0, dst.length); 109 | } 110 | 111 | public int read(byte[] dst, int off, int len) throws IOException 112 | { 113 | int count = 0; 114 | 115 | while (len > 0) 116 | { 117 | if (pos >= blockSize) 118 | { 119 | getBlock(); 120 | } 121 | 122 | int avail = blockSize - pos; 123 | int copy = Math.min(avail, len); 124 | System.arraycopy(buffer, pos, dst, off, copy); 125 | pos += copy; 126 | off += copy; 127 | len -= copy; 128 | count += copy; 129 | } 130 | return count; 131 | } 132 | 133 | public int read() throws IOException 134 | { 135 | if (pos >= blockSize) 136 | { 137 | getBlock(); 138 | } 139 | return buffer[pos++] & 0xff; 140 | } 141 | 142 | public int readPlain(byte[] b, int off, int len) throws IOException 143 | { 144 | if (pos != blockSize) 145 | { 146 | throw new IOException("Cannot read plain since crypto buffer is not aligned."); 147 | } 148 | int n = 0; 149 | while (n < len) 150 | { 151 | int cnt = internal_read(b, off + n, len - n); 152 | if (cnt < 0) 153 | { 154 | throw new IOException("Cannot fill buffer, EOF reached."); 155 | } 156 | n += cnt; 157 | } 158 | return n; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/cipher/CipherOutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto.cipher; 6 | 7 | import java.io.IOException; 8 | import java.io.OutputStream; 9 | 10 | /** 11 | * CipherOutputStream. 12 | * 13 | * @author Christian Plattner 14 | * @version $Id$ 15 | */ 16 | public class CipherOutputStream 17 | { 18 | BlockCipher currentCipher; 19 | OutputStream bo; 20 | byte[] buffer; 21 | byte[] enc; 22 | int blockSize; 23 | int pos; 24 | 25 | /* 26 | * We cannot use java.io.BufferedOutputStream, since that is not available 27 | * in J2ME. Everything could be improved here alot. 28 | */ 29 | 30 | private static final int BUFF_SIZE = 8192; 31 | byte[] out_buffer = new byte[BUFF_SIZE]; 32 | int out_buffer_pos = 0; 33 | 34 | public CipherOutputStream(BlockCipher tc, OutputStream bo) 35 | { 36 | this.bo = bo; 37 | changeCipher(tc); 38 | } 39 | 40 | private void internal_write(byte[] src, int off, int len) throws IOException 41 | { 42 | while (len > 0) 43 | { 44 | int space = BUFF_SIZE - out_buffer_pos; 45 | int copy = (len > space) ? space : len; 46 | 47 | System.arraycopy(src, off, out_buffer, out_buffer_pos, copy); 48 | 49 | off += copy; 50 | out_buffer_pos += copy; 51 | len -= copy; 52 | 53 | if (out_buffer_pos >= BUFF_SIZE) 54 | { 55 | bo.write(out_buffer, 0, BUFF_SIZE); 56 | out_buffer_pos = 0; 57 | } 58 | } 59 | } 60 | 61 | private void internal_write(int b) throws IOException 62 | { 63 | out_buffer[out_buffer_pos++] = (byte) b; 64 | if (out_buffer_pos >= BUFF_SIZE) 65 | { 66 | bo.write(out_buffer, 0, BUFF_SIZE); 67 | out_buffer_pos = 0; 68 | } 69 | } 70 | 71 | public void flush() throws IOException 72 | { 73 | if (pos != 0) 74 | { 75 | throw new IOException("FATAL: cannot flush since crypto buffer is not aligned."); 76 | } 77 | 78 | if (out_buffer_pos > 0) 79 | { 80 | bo.write(out_buffer, 0, out_buffer_pos); 81 | out_buffer_pos = 0; 82 | } 83 | bo.flush(); 84 | } 85 | 86 | public void changeCipher(BlockCipher bc) 87 | { 88 | this.currentCipher = bc; 89 | blockSize = bc.getBlockSize(); 90 | buffer = new byte[blockSize]; 91 | enc = new byte[blockSize]; 92 | pos = 0; 93 | } 94 | 95 | private void writeBlock() throws IOException 96 | { 97 | try 98 | { 99 | currentCipher.transformBlock(buffer, 0, enc, 0); 100 | } 101 | catch (Exception e) 102 | { 103 | throw (IOException) new IOException("Error while decrypting block.").initCause(e); 104 | } 105 | 106 | internal_write(enc, 0, blockSize); 107 | pos = 0; 108 | } 109 | 110 | public void write(byte[] src, int off, int len) throws IOException 111 | { 112 | while (len > 0) 113 | { 114 | int avail = blockSize - pos; 115 | int copy = Math.min(avail, len); 116 | 117 | System.arraycopy(src, off, buffer, pos, copy); 118 | pos += copy; 119 | off += copy; 120 | len -= copy; 121 | 122 | if (pos >= blockSize) 123 | { 124 | writeBlock(); 125 | } 126 | } 127 | } 128 | 129 | public void write(int b) throws IOException 130 | { 131 | buffer[pos++] = (byte) b; 132 | if (pos >= blockSize) 133 | { 134 | writeBlock(); 135 | } 136 | } 137 | 138 | public void writePlain(int b) throws IOException 139 | { 140 | if (pos != 0) 141 | { 142 | throw new IOException("Cannot write plain since crypto buffer is not aligned."); 143 | } 144 | internal_write(b); 145 | } 146 | 147 | public void writePlain(byte[] b, int off, int len) throws IOException 148 | { 149 | if (pos != 0) 150 | { 151 | throw new IOException("Cannot write plain since crypto buffer is not aligned."); 152 | } 153 | internal_write(b, off, len); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/cipher/DESede.java: -------------------------------------------------------------------------------- 1 | package ch.ethz.ssh2.crypto.cipher; 2 | 3 | /* 4 | This file was shamelessly taken (and modified) from the Bouncy Castle Crypto package. 5 | Their licence file states the following: 6 | 7 | Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle 8 | (http://www.bouncycastle.org) 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in 18 | all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | THE SOFTWARE. 27 | */ 28 | 29 | /** 30 | * DESede. 31 | * 32 | * @author See comments in the source file 33 | * @version 2.50, 03/15/10 34 | * 35 | */ 36 | public class DESede extends DES 37 | { 38 | private int[] key1 = null; 39 | private int[] key2 = null; 40 | private int[] key3 = null; 41 | 42 | private boolean encrypt; 43 | 44 | /** 45 | * standard constructor. 46 | */ 47 | public DESede() 48 | { 49 | } 50 | 51 | /** 52 | * initialise a DES cipher. 53 | * 54 | * @param encrypting 55 | * whether or not we are for encryption. 56 | * @param key 57 | * the parameters required to set up the cipher. 58 | * @exception IllegalArgumentException 59 | * if the params argument is inappropriate. 60 | */ 61 | @Override 62 | public void init(boolean encrypting, byte[] key) 63 | { 64 | key1 = generateWorkingKey(encrypting, key, 0); 65 | key2 = generateWorkingKey(!encrypting, key, 8); 66 | key3 = generateWorkingKey(encrypting, key, 16); 67 | 68 | encrypt = encrypting; 69 | } 70 | 71 | @Override 72 | public String getAlgorithmName() 73 | { 74 | return "DESede"; 75 | } 76 | 77 | @Override 78 | public int getBlockSize() 79 | { 80 | return 8; 81 | } 82 | 83 | @Override 84 | public void transformBlock(byte[] in, int inOff, byte[] out, int outOff) 85 | { 86 | if (key1 == null) 87 | { 88 | throw new IllegalStateException("DESede engine not initialised!"); 89 | } 90 | 91 | if (encrypt) 92 | { 93 | desFunc(key1, in, inOff, out, outOff); 94 | desFunc(key2, out, outOff, out, outOff); 95 | desFunc(key3, out, outOff, out, outOff); 96 | } 97 | else 98 | { 99 | desFunc(key3, in, inOff, out, outOff); 100 | desFunc(key2, out, outOff, out, outOff); 101 | desFunc(key1, out, outOff, out, outOff); 102 | } 103 | } 104 | 105 | @Override 106 | public void reset() 107 | { 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/cipher/NullCipher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto.cipher; 6 | 7 | /** 8 | * NullCipher. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class NullCipher implements BlockCipher 14 | { 15 | private int blockSize = 8; 16 | 17 | public NullCipher() 18 | { 19 | } 20 | 21 | public NullCipher(int blockSize) 22 | { 23 | this.blockSize = blockSize; 24 | } 25 | 26 | public void init(boolean forEncryption, byte[] key) 27 | { 28 | } 29 | 30 | public int getBlockSize() 31 | { 32 | return blockSize; 33 | } 34 | 35 | public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) 36 | { 37 | System.arraycopy(src, srcoff, dst, dstoff, blockSize); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/dh/DhGroupExchange.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto.dh; 6 | 7 | import java.math.BigInteger; 8 | import java.security.SecureRandom; 9 | 10 | import ch.ethz.ssh2.DHGexParameters; 11 | import ch.ethz.ssh2.crypto.digest.HashForSSH2Types; 12 | 13 | /** 14 | * DhGroupExchange. 15 | * 16 | * @author Christian Plattner 17 | * @version 2.50, 03/15/10 18 | */ 19 | public class DhGroupExchange 20 | { 21 | /* Given by the standard */ 22 | 23 | private BigInteger p; 24 | private BigInteger g; 25 | 26 | /* Client public and private */ 27 | 28 | private BigInteger e; 29 | private BigInteger x; 30 | 31 | /* Server public */ 32 | 33 | private BigInteger f; 34 | 35 | /* Shared secret */ 36 | 37 | private BigInteger k; 38 | 39 | public DhGroupExchange(BigInteger p, BigInteger g) 40 | { 41 | this.p = p; 42 | this.g = g; 43 | } 44 | 45 | public void init(SecureRandom rnd) 46 | { 47 | k = null; 48 | 49 | x = new BigInteger(p.bitLength() - 1, rnd); 50 | e = g.modPow(x, p); 51 | } 52 | 53 | /** 54 | * @return Returns the e. 55 | */ 56 | public BigInteger getE() 57 | { 58 | if (e == null) 59 | throw new IllegalStateException("Not initialized!"); 60 | 61 | return e; 62 | } 63 | 64 | /** 65 | * @return Returns the shared secret k. 66 | */ 67 | public BigInteger getK() 68 | { 69 | if (k == null) 70 | throw new IllegalStateException("Shared secret not yet known, need f first!"); 71 | 72 | return k; 73 | } 74 | 75 | /** 76 | * Sets f and calculates the shared secret. 77 | */ 78 | public void setF(BigInteger f) 79 | { 80 | if (e == null) 81 | throw new IllegalStateException("Not initialized!"); 82 | 83 | BigInteger zero = BigInteger.valueOf(0); 84 | 85 | if (zero.compareTo(f) >= 0 || p.compareTo(f) <= 0) 86 | throw new IllegalArgumentException("Invalid f specified!"); 87 | 88 | this.f = f; 89 | this.k = f.modPow(x, p); 90 | } 91 | 92 | public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clientKexPayload, 93 | byte[] serverKexPayload, byte[] hostKey, DHGexParameters para) 94 | { 95 | HashForSSH2Types hash = new HashForSSH2Types("SHA1"); 96 | 97 | hash.updateByteString(clientversion); 98 | hash.updateByteString(serverversion); 99 | hash.updateByteString(clientKexPayload); 100 | hash.updateByteString(serverKexPayload); 101 | hash.updateByteString(hostKey); 102 | if (para.getMin_group_len() > 0) 103 | hash.updateUINT32(para.getMin_group_len()); 104 | hash.updateUINT32(para.getPref_group_len()); 105 | if (para.getMax_group_len() > 0) 106 | hash.updateUINT32(para.getMax_group_len()); 107 | hash.updateBigInt(p); 108 | hash.updateBigInt(g); 109 | hash.updateBigInt(e); 110 | hash.updateBigInt(f); 111 | hash.updateBigInt(k); 112 | 113 | return hash.getDigest(); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/digest/Digest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto.digest; 6 | 7 | /** 8 | * Digest. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public interface Digest 14 | { 15 | public int getDigestLength(); 16 | 17 | public void update(byte b); 18 | 19 | public void update(byte[] b); 20 | 21 | public void update(byte b[], int off, int len); 22 | 23 | public void reset(); 24 | 25 | public void digest(byte[] out); 26 | 27 | public void digest(byte[] out, int off); 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/digest/HMAC.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto.digest; 6 | 7 | /** 8 | * HMAC. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public final class HMAC implements Digest 14 | { 15 | Digest md; 16 | byte[] k_xor_ipad; 17 | byte[] k_xor_opad; 18 | 19 | byte[] tmp; 20 | 21 | int size; 22 | 23 | public HMAC(Digest md, byte[] key, int size) 24 | { 25 | this.md = md; 26 | this.size = size; 27 | 28 | tmp = new byte[md.getDigestLength()]; 29 | 30 | int blocksize = 64; 31 | 32 | k_xor_ipad = new byte[blocksize]; 33 | k_xor_opad = new byte[blocksize]; 34 | 35 | if (key.length > blocksize) 36 | { 37 | md.reset(); 38 | md.update(key); 39 | md.digest(tmp); 40 | key = tmp; 41 | } 42 | 43 | System.arraycopy(key, 0, k_xor_ipad, 0, key.length); 44 | System.arraycopy(key, 0, k_xor_opad, 0, key.length); 45 | 46 | for (int i = 0; i < blocksize; i++) 47 | { 48 | k_xor_ipad[i] ^= 0x36; 49 | k_xor_opad[i] ^= 0x5C; 50 | } 51 | md.update(k_xor_ipad); 52 | } 53 | 54 | public int getDigestLength() 55 | { 56 | return size; 57 | } 58 | 59 | public void update(byte b) 60 | { 61 | md.update(b); 62 | } 63 | 64 | public void update(byte[] b) 65 | { 66 | md.update(b); 67 | } 68 | 69 | public void update(byte[] b, int off, int len) 70 | { 71 | md.update(b, off, len); 72 | } 73 | 74 | public void reset() 75 | { 76 | md.reset(); 77 | md.update(k_xor_ipad); 78 | } 79 | 80 | public void digest(byte[] out) 81 | { 82 | digest(out, 0); 83 | } 84 | 85 | public void digest(byte[] out, int off) 86 | { 87 | md.digest(tmp); 88 | 89 | md.update(k_xor_opad); 90 | md.update(tmp); 91 | 92 | md.digest(tmp); 93 | 94 | System.arraycopy(tmp, 0, out, off, size); 95 | 96 | md.update(k_xor_ipad); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/digest/HashForSSH2Types.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto.digest; 6 | 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * HashForSSH2Types. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class HashForSSH2Types 16 | { 17 | Digest md; 18 | 19 | public HashForSSH2Types(Digest md) 20 | { 21 | this.md = md; 22 | } 23 | 24 | public HashForSSH2Types(String type) 25 | { 26 | if (type.equals("SHA1")) 27 | { 28 | md = new SHA1(); 29 | } 30 | else if (type.equals("MD5")) 31 | { 32 | md = new MD5(); 33 | } 34 | else 35 | throw new IllegalArgumentException("Unknown algorithm " + type); 36 | } 37 | 38 | public void updateByte(byte b) 39 | { 40 | /* HACK - to test it with J2ME */ 41 | byte[] tmp = new byte[1]; 42 | tmp[0] = b; 43 | md.update(tmp); 44 | } 45 | 46 | public void updateBytes(byte[] b) 47 | { 48 | md.update(b); 49 | } 50 | 51 | public void updateUINT32(int v) 52 | { 53 | md.update((byte) (v >> 24)); 54 | md.update((byte) (v >> 16)); 55 | md.update((byte) (v >> 8)); 56 | md.update((byte) (v)); 57 | } 58 | 59 | public void updateByteString(byte[] b) 60 | { 61 | updateUINT32(b.length); 62 | updateBytes(b); 63 | } 64 | 65 | public void updateBigInt(BigInteger b) 66 | { 67 | updateByteString(b.toByteArray()); 68 | } 69 | 70 | public void reset() 71 | { 72 | md.reset(); 73 | } 74 | 75 | public int getDigestLength() 76 | { 77 | return md.getDigestLength(); 78 | } 79 | 80 | public byte[] getDigest() 81 | { 82 | byte[] tmp = new byte[md.getDigestLength()]; 83 | getDigest(tmp); 84 | return tmp; 85 | } 86 | 87 | public void getDigest(byte[] out) 88 | { 89 | getDigest(out, 0); 90 | } 91 | 92 | public void getDigest(byte[] out, int off) 93 | { 94 | md.digest(out, off); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/crypto/digest/MAC.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.crypto.digest; 6 | 7 | /** 8 | * MAC. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public final class MAC 14 | { 15 | Digest mac; 16 | int size; 17 | 18 | public static String[] getMacList() 19 | { 20 | /* Higher Priority First */ 21 | 22 | return new String[]{"hmac-sha1-96", "hmac-sha1", "hmac-md5-96", "hmac-md5"}; 23 | } 24 | 25 | public static void checkMacList(String[] macs) 26 | { 27 | for (int i = 0; i < macs.length; i++) 28 | getKeyLen(macs[i]); 29 | } 30 | 31 | public static int getKeyLen(String type) 32 | { 33 | if (type.equals("hmac-sha1")) 34 | return 20; 35 | if (type.equals("hmac-sha1-96")) 36 | return 20; 37 | if (type.equals("hmac-md5")) 38 | return 16; 39 | if (type.equals("hmac-md5-96")) 40 | return 16; 41 | throw new IllegalArgumentException("Unkown algorithm " + type); 42 | } 43 | 44 | public MAC(String type, byte[] key) 45 | { 46 | if (type.equals("hmac-sha1")) 47 | { 48 | mac = new HMAC(new SHA1(), key, 20); 49 | } 50 | else if (type.equals("hmac-sha1-96")) 51 | { 52 | mac = new HMAC(new SHA1(), key, 12); 53 | } 54 | else if (type.equals("hmac-md5")) 55 | { 56 | mac = new HMAC(new MD5(), key, 16); 57 | } 58 | else if (type.equals("hmac-md5-96")) 59 | { 60 | mac = new HMAC(new MD5(), key, 12); 61 | } 62 | else 63 | throw new IllegalArgumentException("Unkown algorithm " + type); 64 | 65 | size = mac.getDigestLength(); 66 | } 67 | 68 | public void initMac(int seq) 69 | { 70 | mac.reset(); 71 | mac.update((byte) (seq >> 24)); 72 | mac.update((byte) (seq >> 16)); 73 | mac.update((byte) (seq >> 8)); 74 | mac.update((byte) (seq)); 75 | } 76 | 77 | public void update(byte[] packetdata, int off, int len) 78 | { 79 | mac.update(packetdata, off, len); 80 | } 81 | 82 | public void getMac(byte[] out, int off) 83 | { 84 | mac.digest(out, off); 85 | } 86 | 87 | public int size() 88 | { 89 | return size; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/log/Logger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.log; 6 | 7 | import java.util.logging.Level; 8 | 9 | /** 10 | * Logger delegating to JRE logging. 11 | * 12 | * @author Christian Plattner 13 | * @version $Id$ 14 | */ 15 | public class Logger 16 | { 17 | 18 | private java.util.logging.Logger delegate; 19 | 20 | public static Logger getLogger(Class x) 21 | { 22 | return new Logger(x); 23 | } 24 | 25 | public Logger(Class x) 26 | { 27 | this.delegate = java.util.logging.Logger.getLogger(x.getName()); 28 | } 29 | 30 | public boolean isDebugEnabled() 31 | { 32 | return delegate.isLoggable(Level.FINER); 33 | } 34 | 35 | public void debug(String message) 36 | { 37 | delegate.fine(message); 38 | } 39 | 40 | public boolean isInfoEnabled() 41 | { 42 | return delegate.isLoggable(Level.FINE); 43 | } 44 | 45 | public void info(String message) 46 | { 47 | delegate.info(message); 48 | } 49 | 50 | public boolean isWarningEnabled() 51 | { 52 | return delegate.isLoggable(Level.WARNING); 53 | } 54 | 55 | public void warning(String message) 56 | { 57 | delegate.warning(message); 58 | } 59 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketChannelOpenConfirmation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketChannelOpenConfirmation. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketChannelOpenConfirmation 16 | { 17 | byte[] payload; 18 | 19 | public int recipientChannelID; 20 | public int senderChannelID; 21 | public int initialWindowSize; 22 | public int maxPacketSize; 23 | 24 | public PacketChannelOpenConfirmation(int recipientChannelID, int senderChannelID, int initialWindowSize, 25 | int maxPacketSize) 26 | { 27 | this.recipientChannelID = recipientChannelID; 28 | this.senderChannelID = senderChannelID; 29 | this.initialWindowSize = initialWindowSize; 30 | this.maxPacketSize = maxPacketSize; 31 | } 32 | 33 | public PacketChannelOpenConfirmation(byte payload[], int off, int len) throws IOException 34 | { 35 | this.payload = new byte[len]; 36 | System.arraycopy(payload, off, this.payload, 0, len); 37 | 38 | TypesReader tr = new TypesReader(payload, off, len); 39 | 40 | int packet_type = tr.readByte(); 41 | 42 | if (packet_type != Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) 43 | throw new IOException( 44 | "This is not a SSH_MSG_CHANNEL_OPEN_CONFIRMATION! (" 45 | + packet_type + ")"); 46 | 47 | recipientChannelID = tr.readUINT32(); 48 | senderChannelID = tr.readUINT32(); 49 | initialWindowSize = tr.readUINT32(); 50 | maxPacketSize = tr.readUINT32(); 51 | 52 | if (tr.remain() != 0) 53 | throw new IOException("Padding in SSH_MSG_CHANNEL_OPEN_CONFIRMATION packet!"); 54 | } 55 | 56 | public byte[] getPayload() 57 | { 58 | if (payload == null) 59 | { 60 | TypesWriter tw = new TypesWriter(); 61 | tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION); 62 | tw.writeUINT32(recipientChannelID); 63 | tw.writeUINT32(senderChannelID); 64 | tw.writeUINT32(initialWindowSize); 65 | tw.writeUINT32(maxPacketSize); 66 | payload = tw.getBytes(); 67 | } 68 | return payload; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketChannelOpenFailure.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketChannelOpenFailure. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketChannelOpenFailure 16 | { 17 | byte[] payload; 18 | 19 | public int recipientChannelID; 20 | public int reasonCode; 21 | public String description; 22 | public String languageTag; 23 | 24 | public PacketChannelOpenFailure(int recipientChannelID, int reasonCode, String description, 25 | String languageTag) 26 | { 27 | this.recipientChannelID = recipientChannelID; 28 | this.reasonCode = reasonCode; 29 | this.description = description; 30 | this.languageTag = languageTag; 31 | } 32 | 33 | public PacketChannelOpenFailure(byte payload[], int off, int len) throws IOException 34 | { 35 | this.payload = new byte[len]; 36 | System.arraycopy(payload, off, this.payload, 0, len); 37 | 38 | TypesReader tr = new TypesReader(payload, off, len); 39 | 40 | int packet_type = tr.readByte(); 41 | 42 | if (packet_type != Packets.SSH_MSG_CHANNEL_OPEN_FAILURE) 43 | throw new IOException( 44 | "This is not a SSH_MSG_CHANNEL_OPEN_FAILURE! (" 45 | + packet_type + ")"); 46 | 47 | recipientChannelID = tr.readUINT32(); 48 | reasonCode = tr.readUINT32(); 49 | description = tr.readString(); 50 | languageTag = tr.readString(); 51 | 52 | if (tr.remain() != 0) 53 | throw new IOException("Padding in SSH_MSG_CHANNEL_OPEN_FAILURE packet!"); 54 | } 55 | 56 | public byte[] getPayload() 57 | { 58 | if (payload == null) 59 | { 60 | TypesWriter tw = new TypesWriter(); 61 | tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN_FAILURE); 62 | tw.writeUINT32(recipientChannelID); 63 | tw.writeUINT32(reasonCode); 64 | tw.writeString(description); 65 | tw.writeString(languageTag); 66 | payload = tw.getBytes(); 67 | } 68 | return payload; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketChannelWindowAdjust.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketChannelWindowAdjust. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketChannelWindowAdjust 16 | { 17 | byte[] payload; 18 | 19 | public int recipientChannelID; 20 | public int windowChange; 21 | 22 | public PacketChannelWindowAdjust(int recipientChannelID, int windowChange) 23 | { 24 | this.recipientChannelID = recipientChannelID; 25 | this.windowChange = windowChange; 26 | } 27 | 28 | public PacketChannelWindowAdjust(byte payload[], int off, int len) throws IOException 29 | { 30 | this.payload = new byte[len]; 31 | System.arraycopy(payload, off, this.payload, 0, len); 32 | 33 | TypesReader tr = new TypesReader(payload, off, len); 34 | 35 | int packet_type = tr.readByte(); 36 | 37 | if (packet_type != Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST) 38 | throw new IOException( 39 | "This is not a SSH_MSG_CHANNEL_WINDOW_ADJUST! (" 40 | + packet_type + ")"); 41 | 42 | recipientChannelID = tr.readUINT32(); 43 | windowChange = tr.readUINT32(); 44 | 45 | if (tr.remain() != 0) 46 | throw new IOException("Padding in SSH_MSG_CHANNEL_WINDOW_ADJUST packet!"); 47 | } 48 | 49 | public byte[] getPayload() 50 | { 51 | if (payload == null) 52 | { 53 | TypesWriter tw = new TypesWriter(); 54 | tw.writeByte(Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST); 55 | tw.writeUINT32(recipientChannelID); 56 | tw.writeUINT32(windowChange); 57 | payload = tw.getBytes(); 58 | } 59 | return payload; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketDisconnect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | import java.io.IOException; 7 | 8 | /** 9 | * PacketDisconnect. 10 | * 11 | * @author Christian Plattner 12 | * @version 2.50, 03/15/10 13 | */ 14 | public class PacketDisconnect 15 | { 16 | byte[] payload; 17 | 18 | int reason; 19 | String desc; 20 | String lang; 21 | 22 | public PacketDisconnect(byte payload[], int off, int len) throws IOException 23 | { 24 | this.payload = new byte[len]; 25 | System.arraycopy(payload, off, this.payload, 0, len); 26 | 27 | TypesReader tr = new TypesReader(payload, off, len); 28 | 29 | int packet_type = tr.readByte(); 30 | 31 | if (packet_type != Packets.SSH_MSG_DISCONNECT) 32 | throw new IOException("This is not a Disconnect Packet! (" 33 | + packet_type + ")"); 34 | 35 | reason = tr.readUINT32(); 36 | desc = tr.readString(); 37 | lang = tr.readString(); 38 | } 39 | 40 | public PacketDisconnect(int reason, String desc, String lang) 41 | { 42 | this.reason = reason; 43 | this.desc = desc; 44 | this.lang = lang; 45 | } 46 | 47 | public byte[] getPayload() 48 | { 49 | if (payload == null) 50 | { 51 | TypesWriter tw = new TypesWriter(); 52 | tw.writeByte(Packets.SSH_MSG_DISCONNECT); 53 | tw.writeUINT32(reason); 54 | tw.writeString(desc); 55 | tw.writeString(lang); 56 | payload = tw.getBytes(); 57 | } 58 | return payload; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketGlobalCancelForwardRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | /** 8 | * PacketGlobalCancelForwardRequest. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class PacketGlobalCancelForwardRequest 14 | { 15 | byte[] payload; 16 | 17 | public boolean wantReply; 18 | public String bindAddress; 19 | public int bindPort; 20 | 21 | public PacketGlobalCancelForwardRequest(boolean wantReply, String bindAddress, int bindPort) 22 | { 23 | this.wantReply = wantReply; 24 | this.bindAddress = bindAddress; 25 | this.bindPort = bindPort; 26 | } 27 | 28 | public byte[] getPayload() 29 | { 30 | if (payload == null) 31 | { 32 | TypesWriter tw = new TypesWriter(); 33 | tw.writeByte(Packets.SSH_MSG_GLOBAL_REQUEST); 34 | 35 | tw.writeString("cancel-tcpip-forward"); 36 | tw.writeBoolean(wantReply); 37 | tw.writeString(bindAddress); 38 | tw.writeUINT32(bindPort); 39 | 40 | payload = tw.getBytes(); 41 | } 42 | return payload; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketGlobalForwardRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | /** 8 | * PacketGlobalForwardRequest. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class PacketGlobalForwardRequest 14 | { 15 | byte[] payload; 16 | 17 | public boolean wantReply; 18 | public String bindAddress; 19 | public int bindPort; 20 | 21 | public PacketGlobalForwardRequest(boolean wantReply, String bindAddress, int bindPort) 22 | { 23 | this.wantReply = wantReply; 24 | this.bindAddress = bindAddress; 25 | this.bindPort = bindPort; 26 | } 27 | 28 | public byte[] getPayload() 29 | { 30 | if (payload == null) 31 | { 32 | TypesWriter tw = new TypesWriter(); 33 | tw.writeByte(Packets.SSH_MSG_GLOBAL_REQUEST); 34 | 35 | tw.writeString("tcpip-forward"); 36 | tw.writeBoolean(wantReply); 37 | tw.writeString(bindAddress); 38 | tw.writeUINT32(bindPort); 39 | 40 | payload = tw.getBytes(); 41 | } 42 | return payload; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketIgnore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketIgnore. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketIgnore 16 | { 17 | byte[] payload; 18 | 19 | byte[] data; 20 | 21 | public void setData(byte[] data) 22 | { 23 | this.data = data; 24 | payload = null; 25 | } 26 | 27 | public PacketIgnore() 28 | { 29 | } 30 | 31 | public PacketIgnore(byte payload[], int off, int len) throws IOException 32 | { 33 | this.payload = new byte[len]; 34 | System.arraycopy(payload, off, this.payload, 0, len); 35 | 36 | TypesReader tr = new TypesReader(payload, off, len); 37 | 38 | int packet_type = tr.readByte(); 39 | 40 | if (packet_type != Packets.SSH_MSG_IGNORE) 41 | throw new IOException("This is not a SSH_MSG_IGNORE packet! (" + packet_type + ")"); 42 | 43 | /* Could parse String body */ 44 | } 45 | 46 | public byte[] getPayload() 47 | { 48 | if (payload == null) 49 | { 50 | TypesWriter tw = new TypesWriter(); 51 | tw.writeByte(Packets.SSH_MSG_IGNORE); 52 | 53 | if (data != null) 54 | tw.writeString(data, 0, data.length); 55 | else 56 | tw.writeString(""); 57 | 58 | payload = tw.getBytes(); 59 | } 60 | return payload; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketKexDHInit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * PacketKexDHInit. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketKexDHInit 16 | { 17 | byte[] payload; 18 | 19 | BigInteger e; 20 | 21 | public PacketKexDHInit(BigInteger e) 22 | { 23 | this.e = e; 24 | } 25 | 26 | public byte[] getPayload() 27 | { 28 | if (payload == null) 29 | { 30 | TypesWriter tw = new TypesWriter(); 31 | tw.writeByte(Packets.SSH_MSG_KEXDH_INIT); 32 | tw.writeMPInt(e); 33 | payload = tw.getBytes(); 34 | } 35 | return payload; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketKexDHReply.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | import java.math.BigInteger; 10 | 11 | /** 12 | * PacketKexDHReply. 13 | * 14 | * @author Christian Plattner 15 | * @version 2.50, 03/15/10 16 | */ 17 | public class PacketKexDHReply 18 | { 19 | byte[] payload; 20 | 21 | byte[] hostKey; 22 | BigInteger f; 23 | byte[] signature; 24 | 25 | public PacketKexDHReply(byte payload[], int off, int len) throws IOException 26 | { 27 | this.payload = new byte[len]; 28 | System.arraycopy(payload, off, this.payload, 0, len); 29 | 30 | TypesReader tr = new TypesReader(payload, off, len); 31 | 32 | int packet_type = tr.readByte(); 33 | 34 | if (packet_type != Packets.SSH_MSG_KEXDH_REPLY) 35 | throw new IOException("This is not a SSH_MSG_KEXDH_REPLY! (" 36 | + packet_type + ")"); 37 | 38 | hostKey = tr.readByteString(); 39 | f = tr.readMPINT(); 40 | signature = tr.readByteString(); 41 | 42 | if (tr.remain() != 0) throw new IOException("PADDING IN SSH_MSG_KEXDH_REPLY!"); 43 | } 44 | 45 | public BigInteger getF() 46 | { 47 | return f; 48 | } 49 | 50 | public byte[] getHostKey() 51 | { 52 | return hostKey; 53 | } 54 | 55 | public byte[] getSignature() 56 | { 57 | return signature; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketKexDhGexGroup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | import java.math.BigInteger; 10 | 11 | /** 12 | * PacketKexDhGexGroup. 13 | * 14 | * @author Christian Plattner 15 | * @version 2.50, 03/15/10 16 | */ 17 | public class PacketKexDhGexGroup 18 | { 19 | byte[] payload; 20 | 21 | BigInteger p; 22 | BigInteger g; 23 | 24 | public PacketKexDhGexGroup(byte payload[], int off, int len) throws IOException 25 | { 26 | this.payload = new byte[len]; 27 | System.arraycopy(payload, off, this.payload, 0, len); 28 | 29 | TypesReader tr = new TypesReader(payload, off, len); 30 | 31 | int packet_type = tr.readByte(); 32 | 33 | if (packet_type != Packets.SSH_MSG_KEX_DH_GEX_GROUP) 34 | throw new IllegalArgumentException( 35 | "This is not a SSH_MSG_KEX_DH_GEX_GROUP! (" + packet_type 36 | + ")"); 37 | 38 | p = tr.readMPINT(); 39 | g = tr.readMPINT(); 40 | 41 | if (tr.remain() != 0) 42 | throw new IOException("PADDING IN SSH_MSG_KEX_DH_GEX_GROUP!"); 43 | } 44 | 45 | public BigInteger getG() 46 | { 47 | return g; 48 | } 49 | 50 | public BigInteger getP() 51 | { 52 | return p; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketKexDhGexInit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * PacketKexDhGexInit. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketKexDhGexInit 16 | { 17 | byte[] payload; 18 | 19 | BigInteger e; 20 | 21 | public PacketKexDhGexInit(BigInteger e) 22 | { 23 | this.e = e; 24 | } 25 | 26 | public byte[] getPayload() 27 | { 28 | if (payload == null) 29 | { 30 | TypesWriter tw = new TypesWriter(); 31 | tw.writeByte(Packets.SSH_MSG_KEX_DH_GEX_INIT); 32 | tw.writeMPInt(e); 33 | payload = tw.getBytes(); 34 | } 35 | return payload; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketKexDhGexReply.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | import java.math.BigInteger; 10 | 11 | /** 12 | * PacketKexDhGexReply. 13 | * 14 | * @author Christian Plattner 15 | * @version 2.50, 03/15/10 16 | */ 17 | public class PacketKexDhGexReply 18 | { 19 | byte[] payload; 20 | 21 | byte[] hostKey; 22 | BigInteger f; 23 | byte[] signature; 24 | 25 | public PacketKexDhGexReply(byte payload[], int off, int len) throws IOException 26 | { 27 | this.payload = new byte[len]; 28 | System.arraycopy(payload, off, this.payload, 0, len); 29 | 30 | TypesReader tr = new TypesReader(payload, off, len); 31 | 32 | int packet_type = tr.readByte(); 33 | 34 | if (packet_type != Packets.SSH_MSG_KEX_DH_GEX_REPLY) 35 | throw new IOException("This is not a SSH_MSG_KEX_DH_GEX_REPLY! (" + packet_type + ")"); 36 | 37 | hostKey = tr.readByteString(); 38 | f = tr.readMPINT(); 39 | signature = tr.readByteString(); 40 | 41 | if (tr.remain() != 0) 42 | throw new IOException("PADDING IN SSH_MSG_KEX_DH_GEX_REPLY!"); 43 | } 44 | 45 | public BigInteger getF() 46 | { 47 | return f; 48 | } 49 | 50 | public byte[] getHostKey() 51 | { 52 | return hostKey; 53 | } 54 | 55 | public byte[] getSignature() 56 | { 57 | return signature; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketKexDhGexRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import ch.ethz.ssh2.DHGexParameters; 8 | 9 | /** 10 | * PacketKexDhGexRequest. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketKexDhGexRequest 16 | { 17 | byte[] payload; 18 | 19 | int min; 20 | int n; 21 | int max; 22 | 23 | public PacketKexDhGexRequest(DHGexParameters para) 24 | { 25 | this.min = para.getMin_group_len(); 26 | this.n = para.getPref_group_len(); 27 | this.max = para.getMax_group_len(); 28 | } 29 | 30 | public byte[] getPayload() 31 | { 32 | if (payload == null) 33 | { 34 | TypesWriter tw = new TypesWriter(); 35 | tw.writeByte(Packets.SSH_MSG_KEX_DH_GEX_REQUEST); 36 | tw.writeUINT32(min); 37 | tw.writeUINT32(n); 38 | tw.writeUINT32(max); 39 | payload = tw.getBytes(); 40 | } 41 | return payload; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketKexDhGexRequestOld.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import ch.ethz.ssh2.DHGexParameters; 8 | 9 | /** 10 | * PacketKexDhGexRequestOld. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketKexDhGexRequestOld 16 | { 17 | byte[] payload; 18 | 19 | int n; 20 | 21 | public PacketKexDhGexRequestOld(DHGexParameters para) 22 | { 23 | this.n = para.getPref_group_len(); 24 | } 25 | 26 | public byte[] getPayload() 27 | { 28 | if (payload == null) 29 | { 30 | TypesWriter tw = new TypesWriter(); 31 | tw.writeByte(Packets.SSH_MSG_KEX_DH_GEX_REQUEST_OLD); 32 | tw.writeUINT32(n); 33 | payload = tw.getBytes(); 34 | } 35 | return payload; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketNewKeys.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketNewKeys. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketNewKeys 16 | { 17 | byte[] payload; 18 | 19 | public PacketNewKeys() 20 | { 21 | } 22 | 23 | public PacketNewKeys(byte payload[], int off, int len) throws IOException 24 | { 25 | this.payload = new byte[len]; 26 | System.arraycopy(payload, off, this.payload, 0, len); 27 | 28 | TypesReader tr = new TypesReader(payload, off, len); 29 | 30 | int packet_type = tr.readByte(); 31 | 32 | if (packet_type != Packets.SSH_MSG_NEWKEYS) 33 | throw new IOException("This is not a SSH_MSG_NEWKEYS! (" 34 | + packet_type + ")"); 35 | 36 | if (tr.remain() != 0) 37 | throw new IOException("Padding in SSH_MSG_NEWKEYS packet!"); 38 | } 39 | 40 | public byte[] getPayload() 41 | { 42 | if (payload == null) 43 | { 44 | TypesWriter tw = new TypesWriter(); 45 | tw.writeByte(Packets.SSH_MSG_NEWKEYS); 46 | payload = tw.getBytes(); 47 | } 48 | return payload; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketOpenDirectTCPIPChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | /** 8 | * PacketOpenDirectTCPIPChannel. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class PacketOpenDirectTCPIPChannel 14 | { 15 | byte[] payload; 16 | 17 | int channelID; 18 | int initialWindowSize; 19 | int maxPacketSize; 20 | 21 | String host_to_connect; 22 | int port_to_connect; 23 | String originator_IP_address; 24 | int originator_port; 25 | 26 | public PacketOpenDirectTCPIPChannel(int channelID, int initialWindowSize, int maxPacketSize, 27 | String host_to_connect, int port_to_connect, String originator_IP_address, 28 | int originator_port) 29 | { 30 | this.channelID = channelID; 31 | this.initialWindowSize = initialWindowSize; 32 | this.maxPacketSize = maxPacketSize; 33 | this.host_to_connect = host_to_connect; 34 | this.port_to_connect = port_to_connect; 35 | this.originator_IP_address = originator_IP_address; 36 | this.originator_port = originator_port; 37 | } 38 | 39 | public byte[] getPayload() 40 | { 41 | if (payload == null) 42 | { 43 | TypesWriter tw = new TypesWriter(); 44 | 45 | tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN); 46 | tw.writeString("direct-tcpip"); 47 | tw.writeUINT32(channelID); 48 | tw.writeUINT32(initialWindowSize); 49 | tw.writeUINT32(maxPacketSize); 50 | tw.writeString(host_to_connect); 51 | tw.writeUINT32(port_to_connect); 52 | tw.writeString(originator_IP_address); 53 | tw.writeUINT32(originator_port); 54 | 55 | payload = tw.getBytes(); 56 | } 57 | return payload; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketOpenSessionChannel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketOpenSessionChannel. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketOpenSessionChannel 16 | { 17 | byte[] payload; 18 | 19 | int channelID; 20 | int initialWindowSize; 21 | int maxPacketSize; 22 | 23 | public PacketOpenSessionChannel(int channelID, int initialWindowSize, 24 | int maxPacketSize) 25 | { 26 | this.channelID = channelID; 27 | this.initialWindowSize = initialWindowSize; 28 | this.maxPacketSize = maxPacketSize; 29 | } 30 | 31 | public PacketOpenSessionChannel(byte payload[], int off, int len) throws IOException 32 | { 33 | this.payload = new byte[len]; 34 | System.arraycopy(payload, off, this.payload, 0, len); 35 | 36 | TypesReader tr = new TypesReader(payload); 37 | 38 | int packet_type = tr.readByte(); 39 | 40 | if (packet_type != Packets.SSH_MSG_CHANNEL_OPEN) 41 | throw new IOException("This is not a SSH_MSG_CHANNEL_OPEN! (" 42 | + packet_type + ")"); 43 | 44 | channelID = tr.readUINT32(); 45 | initialWindowSize = tr.readUINT32(); 46 | maxPacketSize = tr.readUINT32(); 47 | 48 | if (tr.remain() != 0) 49 | throw new IOException("Padding in SSH_MSG_CHANNEL_OPEN packet!"); 50 | } 51 | 52 | public byte[] getPayload() 53 | { 54 | if (payload == null) 55 | { 56 | TypesWriter tw = new TypesWriter(); 57 | tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN); 58 | tw.writeString("session"); 59 | tw.writeUINT32(channelID); 60 | tw.writeUINT32(initialWindowSize); 61 | tw.writeUINT32(maxPacketSize); 62 | payload = tw.getBytes(); 63 | } 64 | return payload; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketServiceAccept.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketServiceAccept. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketServiceAccept 16 | { 17 | byte[] payload; 18 | 19 | String serviceName; 20 | 21 | public PacketServiceAccept(String serviceName) 22 | { 23 | this.serviceName = serviceName; 24 | } 25 | 26 | public PacketServiceAccept(byte payload[], int off, int len) throws IOException 27 | { 28 | this.payload = new byte[len]; 29 | System.arraycopy(payload, off, this.payload, 0, len); 30 | 31 | TypesReader tr = new TypesReader(payload, off, len); 32 | 33 | int packet_type = tr.readByte(); 34 | 35 | if (packet_type != Packets.SSH_MSG_SERVICE_ACCEPT) 36 | throw new IOException("This is not a SSH_MSG_SERVICE_ACCEPT! (" 37 | + packet_type + ")"); 38 | 39 | serviceName = ""; 40 | 41 | if (tr.remain() != 0) 42 | { 43 | serviceName = tr.readString(); 44 | } 45 | } 46 | 47 | public byte[] getPayload() 48 | { 49 | if (payload == null) 50 | { 51 | TypesWriter tw = new TypesWriter(); 52 | tw.writeByte(Packets.SSH_MSG_SERVICE_ACCEPT); 53 | tw.writeString(serviceName); 54 | payload = tw.getBytes(); 55 | } 56 | return payload; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketServiceRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketServiceRequest. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketServiceRequest 16 | { 17 | byte[] payload; 18 | 19 | String serviceName; 20 | 21 | public PacketServiceRequest(String serviceName) 22 | { 23 | this.serviceName = serviceName; 24 | } 25 | 26 | public PacketServiceRequest(byte payload[], int off, int len) throws IOException 27 | { 28 | this.payload = new byte[len]; 29 | System.arraycopy(payload, off, this.payload, 0, len); 30 | 31 | TypesReader tr = new TypesReader(payload, off, len); 32 | 33 | int packet_type = tr.readByte(); 34 | 35 | if (packet_type != Packets.SSH_MSG_SERVICE_REQUEST) 36 | throw new IOException("This is not a SSH_MSG_SERVICE_REQUEST! (" 37 | + packet_type + ")"); 38 | 39 | serviceName = tr.readString(); 40 | 41 | if (tr.remain() != 0) 42 | throw new IOException("Padding in SSH_MSG_SERVICE_REQUEST packet!"); 43 | } 44 | 45 | public byte[] getPayload() 46 | { 47 | if (payload == null) 48 | { 49 | TypesWriter tw = new TypesWriter(); 50 | tw.writeByte(Packets.SSH_MSG_SERVICE_REQUEST); 51 | tw.writeString(serviceName); 52 | payload = tw.getBytes(); 53 | } 54 | return payload; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketSessionExecCommand.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | import java.io.UnsupportedEncodingException; 9 | 10 | /** 11 | * PacketSessionExecCommand. 12 | * 13 | * @author Christian Plattner 14 | * @version $Id$ 15 | */ 16 | public class PacketSessionExecCommand 17 | { 18 | byte[] payload; 19 | 20 | public int recipientChannelID; 21 | public boolean wantReply; 22 | public String command; 23 | 24 | public PacketSessionExecCommand(int recipientChannelID, boolean wantReply, String command) 25 | { 26 | this.recipientChannelID = recipientChannelID; 27 | this.wantReply = wantReply; 28 | this.command = command; 29 | } 30 | 31 | public byte[] getPayload() throws IOException 32 | { 33 | return this.getPayload(null); 34 | } 35 | 36 | public byte[] getPayload(String charsetName) throws UnsupportedEncodingException 37 | { 38 | if (payload == null) 39 | { 40 | TypesWriter tw = new TypesWriter(); 41 | tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); 42 | tw.writeUINT32(recipientChannelID); 43 | tw.writeString("exec"); 44 | tw.writeBoolean(wantReply); 45 | tw.writeString(command, charsetName); 46 | payload = tw.getBytes(); 47 | } 48 | return payload; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketSessionPtyRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | /** 8 | * PacketSessionPtyRequest. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class PacketSessionPtyRequest 14 | { 15 | byte[] payload; 16 | 17 | public int recipientChannelID; 18 | public boolean wantReply; 19 | public String term; 20 | public int character_width; 21 | public int character_height; 22 | public int pixel_width; 23 | public int pixel_height; 24 | public byte[] terminal_modes; 25 | 26 | public PacketSessionPtyRequest(int recipientChannelID, boolean wantReply, String term, 27 | int character_width, int character_height, int pixel_width, int pixel_height, 28 | byte[] terminal_modes) 29 | { 30 | this.recipientChannelID = recipientChannelID; 31 | this.wantReply = wantReply; 32 | this.term = term; 33 | this.character_width = character_width; 34 | this.character_height = character_height; 35 | this.pixel_width = pixel_width; 36 | this.pixel_height = pixel_height; 37 | this.terminal_modes = terminal_modes; 38 | } 39 | 40 | public byte[] getPayload() 41 | { 42 | if (payload == null) 43 | { 44 | TypesWriter tw = new TypesWriter(); 45 | tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); 46 | tw.writeUINT32(recipientChannelID); 47 | tw.writeString("pty-req"); 48 | tw.writeBoolean(wantReply); 49 | tw.writeString(term); 50 | tw.writeUINT32(character_width); 51 | tw.writeUINT32(character_height); 52 | tw.writeUINT32(pixel_width); 53 | tw.writeUINT32(pixel_height); 54 | tw.writeString(terminal_modes, 0, terminal_modes.length); 55 | 56 | payload = tw.getBytes(); 57 | } 58 | return payload; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketSessionStartShell.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | /** 8 | * PacketSessionStartShell. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class PacketSessionStartShell 14 | { 15 | byte[] payload; 16 | 17 | public int recipientChannelID; 18 | public boolean wantReply; 19 | 20 | public PacketSessionStartShell(int recipientChannelID, boolean wantReply) 21 | { 22 | this.recipientChannelID = recipientChannelID; 23 | this.wantReply = wantReply; 24 | } 25 | 26 | public byte[] getPayload() 27 | { 28 | if (payload == null) 29 | { 30 | TypesWriter tw = new TypesWriter(); 31 | tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); 32 | tw.writeUINT32(recipientChannelID); 33 | tw.writeString("shell"); 34 | tw.writeBoolean(wantReply); 35 | payload = tw.getBytes(); 36 | } 37 | return payload; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketSessionSubsystemRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | /** 8 | * PacketSessionSubsystemRequest. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class PacketSessionSubsystemRequest 14 | { 15 | byte[] payload; 16 | 17 | public int recipientChannelID; 18 | public boolean wantReply; 19 | public String subsystem; 20 | 21 | public PacketSessionSubsystemRequest(int recipientChannelID, boolean wantReply, String subsystem) 22 | { 23 | this.recipientChannelID = recipientChannelID; 24 | this.wantReply = wantReply; 25 | this.subsystem = subsystem; 26 | } 27 | 28 | public byte[] getPayload() 29 | { 30 | if (payload == null) 31 | { 32 | TypesWriter tw = new TypesWriter(); 33 | tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); 34 | tw.writeUINT32(recipientChannelID); 35 | tw.writeString("subsystem"); 36 | tw.writeBoolean(wantReply); 37 | tw.writeString(subsystem); 38 | payload = tw.getBytes(); 39 | tw.getBytes(payload); 40 | } 41 | return payload; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketSessionX11Request.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | /** 8 | * PacketSessionX11Request. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class PacketSessionX11Request 14 | { 15 | byte[] payload; 16 | 17 | public int recipientChannelID; 18 | public boolean wantReply; 19 | 20 | public boolean singleConnection; 21 | String x11AuthenticationProtocol; 22 | String x11AuthenticationCookie; 23 | int x11ScreenNumber; 24 | 25 | public PacketSessionX11Request(int recipientChannelID, boolean wantReply, boolean singleConnection, 26 | String x11AuthenticationProtocol, String x11AuthenticationCookie, int x11ScreenNumber) 27 | { 28 | this.recipientChannelID = recipientChannelID; 29 | this.wantReply = wantReply; 30 | 31 | this.singleConnection = singleConnection; 32 | this.x11AuthenticationProtocol = x11AuthenticationProtocol; 33 | this.x11AuthenticationCookie = x11AuthenticationCookie; 34 | this.x11ScreenNumber = x11ScreenNumber; 35 | } 36 | 37 | public byte[] getPayload() 38 | { 39 | if (payload == null) 40 | { 41 | TypesWriter tw = new TypesWriter(); 42 | tw.writeByte(Packets.SSH_MSG_CHANNEL_REQUEST); 43 | tw.writeUINT32(recipientChannelID); 44 | tw.writeString("x11-req"); 45 | tw.writeBoolean(wantReply); 46 | 47 | tw.writeBoolean(singleConnection); 48 | tw.writeString(x11AuthenticationProtocol); 49 | tw.writeString(x11AuthenticationCookie); 50 | tw.writeUINT32(x11ScreenNumber); 51 | 52 | payload = tw.getBytes(); 53 | } 54 | return payload; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketUserauthBanner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketUserauthBanner. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketUserauthBanner 16 | { 17 | byte[] payload; 18 | 19 | String message; 20 | String language; 21 | 22 | public PacketUserauthBanner(String message, String language) 23 | { 24 | this.message = message; 25 | this.language = language; 26 | } 27 | 28 | public String getBanner() 29 | { 30 | return message; 31 | } 32 | 33 | public PacketUserauthBanner(byte payload[], int off, int len) throws IOException 34 | { 35 | this.payload = new byte[len]; 36 | System.arraycopy(payload, off, this.payload, 0, len); 37 | 38 | TypesReader tr = new TypesReader(payload, off, len); 39 | 40 | int packet_type = tr.readByte(); 41 | 42 | if (packet_type != Packets.SSH_MSG_USERAUTH_BANNER) 43 | throw new IOException("This is not a SSH_MSG_USERAUTH_BANNER! (" + packet_type + ")"); 44 | 45 | message = tr.readString("UTF-8"); 46 | language = tr.readString(); 47 | 48 | if (tr.remain() != 0) 49 | throw new IOException("Padding in SSH_MSG_USERAUTH_REQUEST packet!"); 50 | } 51 | 52 | public byte[] getPayload() 53 | { 54 | if (payload == null) 55 | { 56 | TypesWriter tw = new TypesWriter(); 57 | tw.writeByte(Packets.SSH_MSG_USERAUTH_BANNER); 58 | tw.writeString(message); 59 | tw.writeString(language); 60 | payload = tw.getBytes(); 61 | } 62 | return payload; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketUserauthFailure.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketUserauthBanner. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketUserauthFailure 16 | { 17 | byte[] payload; 18 | 19 | String[] authThatCanContinue; 20 | boolean partialSuccess; 21 | 22 | public PacketUserauthFailure(String[] authThatCanContinue, boolean partialSuccess) 23 | { 24 | this.authThatCanContinue = authThatCanContinue; 25 | this.partialSuccess = partialSuccess; 26 | } 27 | 28 | public PacketUserauthFailure(byte payload[], int off, int len) throws IOException 29 | { 30 | this.payload = new byte[len]; 31 | System.arraycopy(payload, off, this.payload, 0, len); 32 | 33 | TypesReader tr = new TypesReader(payload, off, len); 34 | 35 | int packet_type = tr.readByte(); 36 | 37 | if (packet_type != Packets.SSH_MSG_USERAUTH_FAILURE) 38 | throw new IOException("This is not a SSH_MSG_USERAUTH_FAILURE! (" + packet_type + ")"); 39 | 40 | authThatCanContinue = tr.readNameList(); 41 | partialSuccess = tr.readBoolean(); 42 | 43 | if (tr.remain() != 0) 44 | throw new IOException("Padding in SSH_MSG_USERAUTH_FAILURE packet!"); 45 | } 46 | 47 | public String[] getAuthThatCanContinue() 48 | { 49 | return authThatCanContinue; 50 | } 51 | 52 | public boolean isPartialSuccess() 53 | { 54 | return partialSuccess; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketUserauthInfoRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketUserauthInfoRequest. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketUserauthInfoRequest 16 | { 17 | byte[] payload; 18 | 19 | String name; 20 | String instruction; 21 | String languageTag; 22 | int numPrompts; 23 | 24 | String prompt[]; 25 | boolean echo[]; 26 | 27 | public PacketUserauthInfoRequest(byte payload[], int off, int len) throws IOException 28 | { 29 | this.payload = new byte[len]; 30 | System.arraycopy(payload, off, this.payload, 0, len); 31 | 32 | TypesReader tr = new TypesReader(payload, off, len); 33 | 34 | int packet_type = tr.readByte(); 35 | 36 | if (packet_type != Packets.SSH_MSG_USERAUTH_INFO_REQUEST) 37 | throw new IOException("This is not a SSH_MSG_USERAUTH_INFO_REQUEST! (" + packet_type + ")"); 38 | 39 | name = tr.readString(); 40 | instruction = tr.readString(); 41 | languageTag = tr.readString(); 42 | 43 | numPrompts = tr.readUINT32(); 44 | 45 | prompt = new String[numPrompts]; 46 | echo = new boolean[numPrompts]; 47 | 48 | for (int i = 0; i < numPrompts; i++) 49 | { 50 | prompt[i] = tr.readString(); 51 | echo[i] = tr.readBoolean(); 52 | } 53 | 54 | if (tr.remain() != 0) 55 | throw new IOException("Padding in SSH_MSG_USERAUTH_INFO_REQUEST packet!"); 56 | } 57 | 58 | public boolean[] getEcho() 59 | { 60 | return echo; 61 | } 62 | 63 | public String getInstruction() 64 | { 65 | return instruction; 66 | } 67 | 68 | public String getLanguageTag() 69 | { 70 | return languageTag; 71 | } 72 | 73 | public String getName() 74 | { 75 | return name; 76 | } 77 | 78 | public int getNumPrompts() 79 | { 80 | return numPrompts; 81 | } 82 | 83 | public String[] getPrompt() 84 | { 85 | return prompt; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketUserauthInfoResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | /** 8 | * PacketUserauthInfoResponse. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class PacketUserauthInfoResponse 14 | { 15 | byte[] payload; 16 | 17 | String[] responses; 18 | 19 | public PacketUserauthInfoResponse(String[] responses) 20 | { 21 | this.responses = responses; 22 | } 23 | 24 | public byte[] getPayload() 25 | { 26 | if (payload == null) 27 | { 28 | TypesWriter tw = new TypesWriter(); 29 | tw.writeByte(Packets.SSH_MSG_USERAUTH_INFO_RESPONSE); 30 | tw.writeUINT32(responses.length); 31 | for (int i = 0; i < responses.length; i++) 32 | tw.writeString(responses[i]); 33 | 34 | payload = tw.getBytes(); 35 | } 36 | return payload; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketUserauthRequestInteractive.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | /** 8 | * PacketUserauthRequestInteractive. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class PacketUserauthRequestInteractive 14 | { 15 | byte[] payload; 16 | 17 | String userName; 18 | String serviceName; 19 | String[] submethods; 20 | 21 | public PacketUserauthRequestInteractive(String serviceName, String user, String[] submethods) 22 | { 23 | this.serviceName = serviceName; 24 | this.userName = user; 25 | this.submethods = submethods; 26 | } 27 | 28 | public byte[] getPayload() 29 | { 30 | if (payload == null) 31 | { 32 | TypesWriter tw = new TypesWriter(); 33 | tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); 34 | tw.writeString(userName); 35 | tw.writeString(serviceName); 36 | tw.writeString("keyboard-interactive"); 37 | tw.writeString(""); // draft-ietf-secsh-newmodes-04.txt says that 38 | // the language tag should be empty. 39 | tw.writeNameList(submethods); 40 | 41 | payload = tw.getBytes(); 42 | } 43 | return payload; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketUserauthRequestNone.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketUserauthRequestPassword. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketUserauthRequestNone 16 | { 17 | byte[] payload; 18 | 19 | String userName; 20 | String serviceName; 21 | 22 | public PacketUserauthRequestNone(String serviceName, String user) 23 | { 24 | this.serviceName = serviceName; 25 | this.userName = user; 26 | } 27 | 28 | public PacketUserauthRequestNone(byte payload[], int off, int len) throws IOException 29 | { 30 | this.payload = new byte[len]; 31 | System.arraycopy(payload, off, this.payload, 0, len); 32 | 33 | TypesReader tr = new TypesReader(payload, off, len); 34 | 35 | int packet_type = tr.readByte(); 36 | 37 | if (packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) 38 | throw new IOException("This is not a SSH_MSG_USERAUTH_REQUEST! (" + packet_type + ")"); 39 | 40 | userName = tr.readString(); 41 | serviceName = tr.readString(); 42 | 43 | String method = tr.readString(); 44 | 45 | if (method.equals("none") == false) 46 | throw new IOException("This is not a SSH_MSG_USERAUTH_REQUEST with type none!"); 47 | 48 | if (tr.remain() != 0) 49 | throw new IOException("Padding in SSH_MSG_USERAUTH_REQUEST packet!"); 50 | } 51 | 52 | public byte[] getPayload() 53 | { 54 | if (payload == null) 55 | { 56 | TypesWriter tw = new TypesWriter(); 57 | tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); 58 | tw.writeString(userName); 59 | tw.writeString(serviceName); 60 | tw.writeString("none"); 61 | payload = tw.getBytes(); 62 | } 63 | return payload; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketUserauthRequestPassword.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketUserauthRequestPassword. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketUserauthRequestPassword 16 | { 17 | byte[] payload; 18 | 19 | String userName; 20 | String serviceName; 21 | String password; 22 | 23 | public PacketUserauthRequestPassword(String serviceName, String user, String pass) 24 | { 25 | this.serviceName = serviceName; 26 | this.userName = user; 27 | this.password = pass; 28 | } 29 | 30 | public PacketUserauthRequestPassword(byte payload[], int off, int len) throws IOException 31 | { 32 | this.payload = new byte[len]; 33 | System.arraycopy(payload, off, this.payload, 0, len); 34 | 35 | TypesReader tr = new TypesReader(payload, off, len); 36 | 37 | int packet_type = tr.readByte(); 38 | 39 | if (packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) 40 | throw new IOException("This is not a SSH_MSG_USERAUTH_REQUEST! (" + packet_type + ")"); 41 | 42 | userName = tr.readString(); 43 | serviceName = tr.readString(); 44 | 45 | String method = tr.readString(); 46 | 47 | if (method.equals("password") == false) 48 | throw new IOException("This is not a SSH_MSG_USERAUTH_REQUEST with type password!"); 49 | 50 | /* ... */ 51 | 52 | if (tr.remain() != 0) 53 | throw new IOException("Padding in SSH_MSG_USERAUTH_REQUEST packet!"); 54 | } 55 | 56 | public byte[] getPayload() 57 | { 58 | if (payload == null) 59 | { 60 | TypesWriter tw = new TypesWriter(); 61 | tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); 62 | tw.writeString(userName); 63 | tw.writeString(serviceName); 64 | tw.writeString("password"); 65 | tw.writeBoolean(false); 66 | tw.writeString(password); 67 | payload = tw.getBytes(); 68 | } 69 | return payload; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/PacketUserauthRequestPublicKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * PacketUserauthRequestPublicKey. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class PacketUserauthRequestPublicKey 16 | { 17 | byte[] payload; 18 | 19 | String userName; 20 | String serviceName; 21 | String password; 22 | String pkAlgoName; 23 | byte[] pk; 24 | byte[] sig; 25 | 26 | public PacketUserauthRequestPublicKey(String serviceName, String user, 27 | String pkAlgorithmName, byte[] pk, byte[] sig) 28 | { 29 | this.serviceName = serviceName; 30 | this.userName = user; 31 | this.pkAlgoName = pkAlgorithmName; 32 | this.pk = pk; 33 | this.sig = sig; 34 | } 35 | 36 | public PacketUserauthRequestPublicKey(byte payload[], int off, int len) throws IOException 37 | { 38 | this.payload = new byte[len]; 39 | System.arraycopy(payload, off, this.payload, 0, len); 40 | 41 | TypesReader tr = new TypesReader(payload, off, len); 42 | 43 | int packet_type = tr.readByte(); 44 | 45 | if (packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) 46 | throw new IOException("This is not a SSH_MSG_USERAUTH_REQUEST! (" 47 | + packet_type + ")"); 48 | 49 | throw new IOException("Not implemented!"); 50 | } 51 | 52 | public byte[] getPayload() 53 | { 54 | if (payload == null) 55 | { 56 | TypesWriter tw = new TypesWriter(); 57 | tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); 58 | tw.writeString(userName); 59 | tw.writeString(serviceName); 60 | tw.writeString("publickey"); 61 | tw.writeBoolean(true); 62 | tw.writeString(pkAlgoName); 63 | tw.writeString(pk, 0, pk.length); 64 | tw.writeString(sig, 0, sig.length); 65 | payload = tw.getBytes(); 66 | } 67 | return payload; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/packets/TypesWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.packets; 6 | 7 | import java.io.UnsupportedEncodingException; 8 | import java.math.BigInteger; 9 | 10 | import ch.ethz.ssh2.util.StringEncoder; 11 | 12 | /** 13 | * TypesWriter. 14 | * 15 | * @author Christian Plattner 16 | * @version 2.50, 03/15/10 17 | */ 18 | public class TypesWriter 19 | { 20 | byte arr[]; 21 | int pos; 22 | 23 | public TypesWriter() 24 | { 25 | arr = new byte[256]; 26 | pos = 0; 27 | } 28 | 29 | private void resize(int len) 30 | { 31 | byte new_arr[] = new byte[len]; 32 | System.arraycopy(arr, 0, new_arr, 0, arr.length); 33 | arr = new_arr; 34 | } 35 | 36 | public int length() 37 | { 38 | return pos; 39 | } 40 | 41 | public byte[] getBytes() 42 | { 43 | byte[] dst = new byte[pos]; 44 | System.arraycopy(arr, 0, dst, 0, pos); 45 | return dst; 46 | } 47 | 48 | public void getBytes(byte dst[]) 49 | { 50 | System.arraycopy(arr, 0, dst, 0, pos); 51 | } 52 | 53 | public void writeUINT32(int val, int off) 54 | { 55 | if ((off + 4) > arr.length) 56 | resize(off + 32); 57 | 58 | arr[off++] = (byte) (val >> 24); 59 | arr[off++] = (byte) (val >> 16); 60 | arr[off++] = (byte) (val >> 8); 61 | arr[off++] = (byte) val; 62 | } 63 | 64 | public void writeUINT32(int val) 65 | { 66 | writeUINT32(val, pos); 67 | pos += 4; 68 | } 69 | 70 | public void writeUINT64(long val) 71 | { 72 | if ((pos + 8) > arr.length) 73 | resize(arr.length + 32); 74 | 75 | arr[pos++] = (byte) (val >> 56); 76 | arr[pos++] = (byte) (val >> 48); 77 | arr[pos++] = (byte) (val >> 40); 78 | arr[pos++] = (byte) (val >> 32); 79 | arr[pos++] = (byte) (val >> 24); 80 | arr[pos++] = (byte) (val >> 16); 81 | arr[pos++] = (byte) (val >> 8); 82 | arr[pos++] = (byte) val; 83 | } 84 | 85 | public void writeBoolean(boolean v) 86 | { 87 | if ((pos + 1) > arr.length) 88 | resize(arr.length + 32); 89 | 90 | arr[pos++] = v ? (byte) 1 : (byte) 0; 91 | } 92 | 93 | public void writeByte(int v, int off) 94 | { 95 | if ((off + 1) > arr.length) 96 | resize(off + 32); 97 | 98 | arr[off] = (byte) v; 99 | } 100 | 101 | public void writeByte(int v) 102 | { 103 | writeByte(v, pos); 104 | pos++; 105 | } 106 | 107 | public void writeMPInt(BigInteger b) 108 | { 109 | byte raw[] = b.toByteArray(); 110 | 111 | if ((raw.length == 1) && (raw[0] == 0)) 112 | writeUINT32(0); /* String with zero bytes of data */ 113 | else 114 | writeString(raw, 0, raw.length); 115 | } 116 | 117 | public void writeBytes(byte[] buff) 118 | { 119 | writeBytes(buff, 0, buff.length); 120 | } 121 | 122 | public void writeBytes(byte[] buff, int off, int len) 123 | { 124 | if ((pos + len) > arr.length) 125 | resize(arr.length + len + 32); 126 | 127 | System.arraycopy(buff, off, arr, pos, len); 128 | pos += len; 129 | } 130 | 131 | public void writeString(byte[] buff, int off, int len) 132 | { 133 | writeUINT32(len); 134 | writeBytes(buff, off, len); 135 | } 136 | 137 | public void writeString(String v) 138 | { 139 | byte[] b = StringEncoder.GetBytes(v); 140 | 141 | writeUINT32(b.length); 142 | writeBytes(b, 0, b.length); 143 | } 144 | 145 | public void writeString(String v, String charsetName) throws UnsupportedEncodingException 146 | { 147 | byte[] b = (charsetName == null) ? StringEncoder.GetBytes(v) : v.getBytes(charsetName); 148 | 149 | writeUINT32(b.length); 150 | writeBytes(b, 0, b.length); 151 | } 152 | 153 | public void writeNameList(String v[]) 154 | { 155 | StringBuilder sb = new StringBuilder(); 156 | for (int i = 0; i < v.length; i++) 157 | { 158 | if (i > 0) 159 | sb.append(','); 160 | sb.append(v[i]); 161 | } 162 | writeString(sb.toString()); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/sftp/AttrTextHints.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.sftp; 6 | 7 | /** 8 | * 9 | * Values for the 'text-hint' field in the SFTP ATTRS data type. 10 | * 11 | * @author Christian Plattner 12 | * @version 2.50, 03/15/10 13 | * 14 | */ 15 | public class AttrTextHints 16 | { 17 | /** 18 | * The server knows the file is a text file, and should be opened 19 | * using the SSH_FXF_ACCESS_TEXT_MODE flag. 20 | */ 21 | public static final int SSH_FILEXFER_ATTR_KNOWN_TEXT = 0x00; 22 | 23 | /** 24 | * The server has applied a heuristic or other mechanism and 25 | * believes that the file should be opened with the 26 | * SSH_FXF_ACCESS_TEXT_MODE flag. 27 | */ 28 | public static final int SSH_FILEXFER_ATTR_GUESSED_TEXT = 0x01; 29 | 30 | /** 31 | * The server knows the file has binary content. 32 | */ 33 | public static final int SSH_FILEXFER_ATTR_KNOWN_BINARY = 0x02; 34 | 35 | /** 36 | * The server has applied a heuristic or other mechanism and 37 | * believes has binary content, and should not be opened with the 38 | * SSH_FXF_ACCESS_TEXT_MODE flag. 39 | */ 40 | public static final int SSH_FILEXFER_ATTR_GUESSED_BINARY = 0x03; 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/sftp/AttribFlags.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.sftp; 6 | 7 | /** 8 | * 9 | * Attribute Flags. The 'valid-attribute-flags' field in 10 | * the SFTP ATTRS data type specifies which of the fields are actually present. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | * 15 | */ 16 | public class AttribFlags 17 | { 18 | /** 19 | * Indicates that the 'allocation-size' field is present. 20 | */ 21 | public static final int SSH_FILEXFER_ATTR_SIZE = 0x00000001; 22 | 23 | /** Protocol version 6: 24 | * 0x00000002 was used in a previous version of this protocol. 25 | * It is now a reserved value and MUST NOT appear in the mask. 26 | * Some future version of this protocol may reuse this value. 27 | */ 28 | public static final int SSH_FILEXFER_ATTR_V3_UIDGID = 0x00000002; 29 | 30 | /** 31 | * Indicates that the 'permissions' field is present. 32 | */ 33 | public static final int SSH_FILEXFER_ATTR_PERMISSIONS = 0x00000004; 34 | 35 | /** 36 | * Indicates that the 'atime' and 'mtime' field are present 37 | * (protocol v3). 38 | */ 39 | public static final int SSH_FILEXFER_ATTR_V3_ACMODTIME = 0x00000008; 40 | 41 | /** 42 | * Indicates that the 'atime' field is present. 43 | */ 44 | public static final int SSH_FILEXFER_ATTR_ACCESSTIME = 0x00000008; 45 | 46 | /** 47 | * Indicates that the 'createtime' field is present. 48 | */ 49 | public static final int SSH_FILEXFER_ATTR_CREATETIME = 0x00000010; 50 | 51 | /** 52 | * Indicates that the 'mtime' field is present. 53 | */ 54 | public static final int SSH_FILEXFER_ATTR_MODIFYTIME = 0x00000020; 55 | 56 | /** 57 | * Indicates that the 'acl' field is present. 58 | */ 59 | public static final int SSH_FILEXFER_ATTR_ACL = 0x00000040; 60 | 61 | /** 62 | * Indicates that the 'owner' and 'group' fields are present. 63 | */ 64 | public static final int SSH_FILEXFER_ATTR_OWNERGROUP = 0x00000080; 65 | 66 | /** 67 | * Indicates that additionally to the 'atime', 'createtime', 68 | * 'mtime' and 'ctime' fields (if present), there is also 69 | * 'atime-nseconds', 'createtime-nseconds', 'mtime-nseconds' 70 | * and 'ctime-nseconds'. 71 | */ 72 | public static final int SSH_FILEXFER_ATTR_SUBSECOND_TIMES = 0x00000100; 73 | 74 | /** 75 | * Indicates that the 'attrib-bits' and 'attrib-bits-valid' 76 | * fields are present. 77 | */ 78 | public static final int SSH_FILEXFER_ATTR_BITS = 0x00000200; 79 | 80 | /** 81 | * Indicates that the 'allocation-size' field is present. 82 | */ 83 | public static final int SSH_FILEXFER_ATTR_ALLOCATION_SIZE = 0x00000400; 84 | 85 | /** 86 | * Indicates that the 'text-hint' field is present. 87 | */ 88 | public static final int SSH_FILEXFER_ATTR_TEXT_HINT = 0x00000800; 89 | 90 | /** 91 | * Indicates that the 'mime-type' field is present. 92 | */ 93 | public static final int SSH_FILEXFER_ATTR_MIME_TYPE = 0x00001000; 94 | 95 | /** 96 | * Indicates that the 'link-count' field is present. 97 | */ 98 | public static final int SSH_FILEXFER_ATTR_LINK_COUNT = 0x00002000; 99 | 100 | /** 101 | * Indicates that the 'untranslated-name' field is present. 102 | */ 103 | public static final int SSH_FILEXFER_ATTR_UNTRANSLATED_NAME = 0x00004000; 104 | 105 | /** 106 | * Indicates that the 'ctime' field is present. 107 | */ 108 | public static final int SSH_FILEXFER_ATTR_CTIME = 0x00008000; 109 | 110 | /** 111 | * Indicates that the 'extended-count' field (and probablby some 112 | * 'extensions') is present. 113 | */ 114 | public static final int SSH_FILEXFER_ATTR_EXTENDED = 0x80000000; 115 | } 116 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/sftp/AttribPermissions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.sftp; 6 | 7 | /** 8 | * 9 | * Permissions for the 'permissions' field in the SFTP ATTRS data type. 10 | *

11 | * "The 'permissions' field contains a bit mask specifying file permissions. 12 | * These permissions correspond to the st_mode field of the stat structure 13 | * defined by POSIX [IEEE.1003-1.1996]." 14 | * 15 | * @author Christian Plattner 16 | * @version 2.50, 03/15/10 17 | * 18 | */ 19 | public class AttribPermissions 20 | { 21 | /* Octal values! */ 22 | 23 | public static final int S_IRUSR = 0400; 24 | public static final int S_IWUSR = 0200; 25 | public static final int S_IXUSR = 0100; 26 | public static final int S_IRGRP = 0040; 27 | public static final int S_IWGRP = 0020; 28 | public static final int S_IXGRP = 0010; 29 | public static final int S_IROTH = 0004; 30 | public static final int S_IWOTH = 0002; 31 | public static final int S_IXOTH = 0001; 32 | public static final int S_ISUID = 04000; 33 | public static final int S_ISGID = 02000; 34 | public static final int S_ISVTX = 01000; 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/sftp/AttribTypes.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.sftp; 6 | 7 | /** 8 | * 9 | * Types for the 'type' field in the SFTP ATTRS data type. 10 | *

11 | * "On a POSIX system, these values would be derived from the mode field 12 | * of the stat structure. SPECIAL should be used for files that are of 13 | * a known type which cannot be expressed in the protocol. UNKNOWN 14 | * should be used if the type is not known." 15 | * 16 | * @author Christian Plattner 17 | * @version 2.50, 03/15/10 18 | * 19 | */ 20 | public class AttribTypes 21 | { 22 | public static final int SSH_FILEXFER_TYPE_REGULAR = 1; 23 | public static final int SSH_FILEXFER_TYPE_DIRECTORY = 2; 24 | public static final int SSH_FILEXFER_TYPE_SYMLINK = 3; 25 | public static final int SSH_FILEXFER_TYPE_SPECIAL = 4; 26 | public static final int SSH_FILEXFER_TYPE_UNKNOWN = 5; 27 | public static final int SSH_FILEXFER_TYPE_SOCKET = 6; 28 | public static final int SSH_FILEXFER_TYPE_CHAR_DEVICE = 7; 29 | public static final int SSH_FILEXFER_TYPE_BLOCK_DEVICE = 8; 30 | public static final int SSH_FILEXFER_TYPE_FIFO = 9; 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/sftp/Packet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.sftp; 6 | 7 | /** 8 | * 9 | * SFTP Paket Types 10 | * 11 | * @author Christian Plattner 12 | * @version 2.50, 03/15/10 13 | * 14 | */ 15 | public class Packet 16 | { 17 | public static final int SSH_FXP_INIT = 1; 18 | public static final int SSH_FXP_VERSION = 2; 19 | public static final int SSH_FXP_OPEN = 3; 20 | public static final int SSH_FXP_CLOSE = 4; 21 | public static final int SSH_FXP_READ = 5; 22 | public static final int SSH_FXP_WRITE = 6; 23 | public static final int SSH_FXP_LSTAT = 7; 24 | public static final int SSH_FXP_FSTAT = 8; 25 | public static final int SSH_FXP_SETSTAT = 9; 26 | public static final int SSH_FXP_FSETSTAT = 10; 27 | public static final int SSH_FXP_OPENDIR = 11; 28 | public static final int SSH_FXP_READDIR = 12; 29 | public static final int SSH_FXP_REMOVE = 13; 30 | public static final int SSH_FXP_MKDIR = 14; 31 | public static final int SSH_FXP_RMDIR = 15; 32 | public static final int SSH_FXP_REALPATH = 16; 33 | public static final int SSH_FXP_STAT = 17; 34 | public static final int SSH_FXP_RENAME = 18; 35 | public static final int SSH_FXP_READLINK = 19; 36 | public static final int SSH_FXP_SYMLINK = 20; 37 | 38 | public static final int SSH_FXP_STATUS = 101; 39 | public static final int SSH_FXP_HANDLE = 102; 40 | public static final int SSH_FXP_DATA = 103; 41 | public static final int SSH_FXP_NAME = 104; 42 | public static final int SSH_FXP_ATTRS = 105; 43 | 44 | public static final int SSH_FXP_EXTENDED = 200; 45 | public static final int SSH_FXP_EXTENDED_REPLY = 201; 46 | 47 | public static String forName(int type) { 48 | switch(type) { 49 | case SSH_FXP_INIT: 50 | return "SSH_FXP_INIT"; 51 | case SSH_FXP_VERSION: 52 | return "SSH_FXP_VERSION"; 53 | case SSH_FXP_OPEN: 54 | return "SSH_FXP_OPEN"; 55 | case SSH_FXP_CLOSE: 56 | return "SSH_FXP_CLOSE"; 57 | case SSH_FXP_READ: 58 | return "SSH_FXP_READ"; 59 | case SSH_FXP_WRITE: 60 | return "SSH_FXP_WRITE"; 61 | case SSH_FXP_LSTAT: 62 | return "SSH_FXP_LSTAT"; 63 | case SSH_FXP_FSTAT: 64 | return "SSH_FXP_FSTAT"; 65 | case SSH_FXP_SETSTAT: 66 | return "SSH_FXP_SETSTAT"; 67 | case SSH_FXP_FSETSTAT: 68 | return "SSH_FXP_FSETSTAT"; 69 | case SSH_FXP_OPENDIR: 70 | return "SSH_FXP_OPENDIR"; 71 | case SSH_FXP_READDIR: 72 | return "SSH_FXP_READDIR"; 73 | case SSH_FXP_REMOVE: 74 | return "SSH_FXP_REMOVE"; 75 | case SSH_FXP_MKDIR: 76 | return "SSH_FXP_MKDIR"; 77 | case SSH_FXP_RMDIR: 78 | return "SSH_FXP_RMDIR"; 79 | case SSH_FXP_REALPATH: 80 | return "SSH_FXP_REALPATH"; 81 | case SSH_FXP_STAT: 82 | return "SSH_FXP_STAT"; 83 | case SSH_FXP_RENAME: 84 | return "SSH_FXP_RENAME"; 85 | case SSH_FXP_READLINK: 86 | return "SSH_FXP_READLINK"; 87 | case SSH_FXP_SYMLINK: 88 | return "SSH_FXP_SYMLINK"; 89 | case SSH_FXP_STATUS: 90 | return "SSH_FXP_STATUS"; 91 | case SSH_FXP_HANDLE: 92 | return "SSH_FXP_HANDLE"; 93 | case SSH_FXP_DATA: 94 | return "SSH_FXP_DATA"; 95 | case SSH_FXP_NAME: 96 | return "SSH_FXP_NAME"; 97 | case SSH_FXP_ATTRS: 98 | return "SSH_FXP_ATTRS"; 99 | case SSH_FXP_EXTENDED: 100 | return "SSH_FXP_EXTENDED"; 101 | case SSH_FXP_EXTENDED_REPLY: 102 | return "SSH_FXP_EXTENDED_REPLY"; 103 | } 104 | return null; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/signature/DSAPrivateKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.signature; 6 | 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * DSAPrivateKey. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class DSAPrivateKey 16 | { 17 | private BigInteger p; 18 | private BigInteger q; 19 | private BigInteger g; 20 | private BigInteger x; 21 | private BigInteger y; 22 | 23 | public DSAPrivateKey(BigInteger p, BigInteger q, BigInteger g, 24 | BigInteger y, BigInteger x) 25 | { 26 | this.p = p; 27 | this.q = q; 28 | this.g = g; 29 | this.y = y; 30 | this.x = x; 31 | } 32 | 33 | public BigInteger getP() 34 | { 35 | return p; 36 | } 37 | 38 | public BigInteger getQ() 39 | { 40 | return q; 41 | } 42 | 43 | public BigInteger getG() 44 | { 45 | return g; 46 | } 47 | 48 | public BigInteger getY() 49 | { 50 | return y; 51 | } 52 | 53 | public BigInteger getX() 54 | { 55 | return x; 56 | } 57 | 58 | public DSAPublicKey getPublicKey() 59 | { 60 | return new DSAPublicKey(p, q, g, y); 61 | } 62 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/signature/DSAPublicKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.signature; 6 | 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * DSAPublicKey. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class DSAPublicKey 16 | { 17 | private BigInteger p; 18 | private BigInteger q; 19 | private BigInteger g; 20 | private BigInteger y; 21 | 22 | public DSAPublicKey(BigInteger p, BigInteger q, BigInteger g, BigInteger y) 23 | { 24 | this.p = p; 25 | this.q = q; 26 | this.g = g; 27 | this.y = y; 28 | } 29 | 30 | public BigInteger getP() 31 | { 32 | return p; 33 | } 34 | 35 | public BigInteger getQ() 36 | { 37 | return q; 38 | } 39 | 40 | public BigInteger getG() 41 | { 42 | return g; 43 | } 44 | 45 | public BigInteger getY() 46 | { 47 | return y; 48 | } 49 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/signature/DSASignature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.signature; 6 | 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * DSASignature. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class DSASignature 16 | { 17 | private BigInteger r; 18 | private BigInteger s; 19 | 20 | public DSASignature(BigInteger r, BigInteger s) 21 | { 22 | this.r = r; 23 | this.s = s; 24 | } 25 | 26 | public BigInteger getR() 27 | { 28 | return r; 29 | } 30 | 31 | public BigInteger getS() 32 | { 33 | return s; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/signature/RSAPrivateKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.signature; 6 | 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * RSAPrivateKey. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class RSAPrivateKey 16 | { 17 | private BigInteger d; 18 | private BigInteger e; 19 | private BigInteger n; 20 | 21 | public RSAPrivateKey(BigInteger d, BigInteger e, BigInteger n) 22 | { 23 | this.d = d; 24 | this.e = e; 25 | this.n = n; 26 | } 27 | 28 | public BigInteger getD() 29 | { 30 | return d; 31 | } 32 | 33 | public BigInteger getE() 34 | { 35 | return e; 36 | } 37 | 38 | public BigInteger getN() 39 | { 40 | return n; 41 | } 42 | 43 | public RSAPublicKey getPublicKey() 44 | { 45 | return new RSAPublicKey(e, n); 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/signature/RSAPublicKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.signature; 6 | 7 | import java.math.BigInteger; 8 | 9 | /** 10 | * RSAPublicKey. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public class RSAPublicKey 16 | { 17 | BigInteger e; 18 | BigInteger n; 19 | 20 | public RSAPublicKey(BigInteger e, BigInteger n) 21 | { 22 | this.e = e; 23 | this.n = n; 24 | } 25 | 26 | public BigInteger getE() 27 | { 28 | return e; 29 | } 30 | 31 | public BigInteger getN() 32 | { 33 | return n; 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/signature/RSASignature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.signature; 6 | 7 | import java.math.BigInteger; 8 | 9 | 10 | /** 11 | * RSASignature. 12 | * 13 | * @author Christian Plattner 14 | * @version 2.50, 03/15/10 15 | */ 16 | 17 | public class RSASignature 18 | { 19 | BigInteger s; 20 | 21 | public BigInteger getS() 22 | { 23 | return s; 24 | } 25 | 26 | public RSASignature(BigInteger s) 27 | { 28 | this.s = s; 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/transport/ClientServerHello.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.transport; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.io.OutputStream; 10 | 11 | import ch.ethz.ssh2.util.StringEncoder; 12 | 13 | /** 14 | * ClientServerHello. 15 | * 16 | * @author Christian Plattner 17 | * @version $Id$ 18 | */ 19 | public class ClientServerHello 20 | { 21 | String server_line; 22 | String client_line; 23 | 24 | String server_versioncomment; 25 | 26 | public static int readLineRN(InputStream is, byte[] buffer) throws IOException 27 | { 28 | int pos = 0; 29 | boolean need10 = false; 30 | int len = 0; 31 | while (true) 32 | { 33 | int c = is.read(); 34 | if (c == -1) 35 | throw new IOException("Premature connection close"); 36 | 37 | buffer[pos++] = (byte) c; 38 | 39 | if (c == 13) 40 | { 41 | need10 = true; 42 | continue; 43 | } 44 | 45 | if (c == 10) 46 | break; 47 | 48 | if (need10 == true) 49 | throw new IOException("Malformed line sent by the server, the line does not end correctly."); 50 | 51 | len++; 52 | if (pos >= buffer.length) 53 | throw new IOException("The server sent a too long line."); 54 | } 55 | 56 | return len; 57 | } 58 | 59 | public ClientServerHello(String identification, InputStream bi, OutputStream bo) throws IOException 60 | { 61 | client_line = "SSH-2.0-" + identification; 62 | 63 | bo.write(StringEncoder.GetBytes(client_line + "\r\n")); 64 | bo.flush(); 65 | 66 | //In some cases connection to server fails, because server line is too long 67 | byte[] serverVersion = new byte[1024]; 68 | 69 | for (int i = 0; i < 50; i++) 70 | { 71 | int len = readLineRN(bi, serverVersion); 72 | 73 | server_line = StringEncoder.GetString(serverVersion, 0, len); 74 | 75 | if (server_line.startsWith("SSH-")) 76 | break; 77 | } 78 | 79 | if (server_line.startsWith("SSH-") == false) 80 | throw new IOException( 81 | "Malformed server identification string. There was no line starting with 'SSH-' amongst the first 50 lines."); 82 | 83 | if (server_line.startsWith("SSH-1.99-")) 84 | server_versioncomment = server_line.substring(9); 85 | else if (server_line.startsWith("SSH-2.0-")) 86 | server_versioncomment = server_line.substring(8); 87 | else 88 | throw new IOException("Server uses incompatible protocol, it is not SSH-2 compatible."); 89 | } 90 | 91 | /** 92 | * @return Returns the client_versioncomment. 93 | */ 94 | public byte[] getClientString() 95 | { 96 | return StringEncoder.GetBytes(client_line); 97 | } 98 | 99 | /** 100 | * @return Returns the server_versioncomment. 101 | */ 102 | public byte[] getServerString() 103 | { 104 | return StringEncoder.GetBytes(server_line); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/transport/KexParameters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.transport; 6 | 7 | /** 8 | * KexParameters. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class KexParameters 14 | { 15 | public byte[] cookie; 16 | public String[] kex_algorithms; 17 | public String[] server_host_key_algorithms; 18 | public String[] encryption_algorithms_client_to_server; 19 | public String[] encryption_algorithms_server_to_client; 20 | public String[] mac_algorithms_client_to_server; 21 | public String[] mac_algorithms_server_to_client; 22 | public String[] compression_algorithms_client_to_server; 23 | public String[] compression_algorithms_server_to_client; 24 | public String[] languages_client_to_server; 25 | public String[] languages_server_to_client; 26 | public boolean first_kex_packet_follows; 27 | public int reserved_field1; 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/transport/KexState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.transport; 6 | 7 | import ch.ethz.ssh2.DHGexParameters; 8 | import ch.ethz.ssh2.crypto.dh.DhExchange; 9 | import ch.ethz.ssh2.crypto.dh.DhGroupExchange; 10 | import java.math.BigInteger; 11 | import ch.ethz.ssh2.packets.PacketKexInit; 12 | 13 | /** 14 | * KexState. 15 | * 16 | * @author Christian Plattner 17 | * @version 2.50, 03/15/10 18 | */ 19 | public class KexState 20 | { 21 | public PacketKexInit localKEX; 22 | public PacketKexInit remoteKEX; 23 | public NegotiatedParameters np; 24 | public int state = 0; 25 | 26 | public BigInteger K; 27 | public byte[] H; 28 | 29 | public byte[] hostkey; 30 | 31 | public DhExchange dhx; 32 | public DhGroupExchange dhgx; 33 | public DHGexParameters dhgexParameters; 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/transport/MessageHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.transport; 6 | 7 | import java.io.IOException; 8 | 9 | /** 10 | * MessageHandler. 11 | * 12 | * @author Christian Plattner 13 | * @version 2.50, 03/15/10 14 | */ 15 | public interface MessageHandler 16 | { 17 | public void handleMessage(byte[] msg, int msglen) throws IOException; 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/transport/NegotiateException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.transport; 6 | 7 | /** 8 | * NegotiateException. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class NegotiateException extends Exception 14 | { 15 | private static final long serialVersionUID = 3689910669428143157L; 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/transport/NegotiatedParameters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.transport; 6 | 7 | /** 8 | * NegotiatedParameters. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class NegotiatedParameters 14 | { 15 | public boolean guessOK; 16 | public String kex_algo; 17 | public String server_host_key_algo; 18 | public String enc_algo_client_to_server; 19 | public String enc_algo_server_to_client; 20 | public String mac_algo_client_to_server; 21 | public String mac_algo_server_to_client; 22 | public String comp_algo_client_to_server; 23 | public String comp_algo_server_to_client; 24 | public String lang_client_to_server; 25 | public String lang_server_to_client; 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/util/StringEncoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. 3 | * All rights reserved. 4 | * Please refer to the LICENSE.txt for licensing details. 5 | */ 6 | package ch.ethz.ssh2.util; 7 | 8 | import java.io.UnsupportedEncodingException; 9 | 10 | /** 11 | * @author Christian Plattner 12 | * @version $Id$ 13 | */ 14 | public class StringEncoder 15 | { 16 | public static byte[] GetBytes(String data) 17 | { 18 | try { 19 | return data.getBytes("UTF-8"); 20 | } 21 | catch(UnsupportedEncodingException e) { 22 | throw new RuntimeException(e); 23 | } 24 | } 25 | 26 | public static String GetString(byte[] data) 27 | { 28 | return GetString(data, 0, data.length); 29 | } 30 | 31 | public static String GetString(byte[] data, int off, int len) 32 | { 33 | try { 34 | return new String(data, off, len, "UTF-8"); 35 | } 36 | catch(UnsupportedEncodingException e) { 37 | throw new RuntimeException(e); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/ethz/ssh2/util/Tokenizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. 3 | * Please refer to the LICENSE.txt for licensing details. 4 | */ 5 | package ch.ethz.ssh2.util; 6 | 7 | /** 8 | * Tokenizer. Why? Because StringTokenizer is not available in J2ME. 9 | * 10 | * @author Christian Plattner 11 | * @version 2.50, 03/15/10 12 | */ 13 | public class Tokenizer 14 | { 15 | /** 16 | * Exists because StringTokenizer is not available in J2ME. 17 | * Returns an array with at least 1 entry. 18 | * 19 | * @param source must be non-null 20 | * @param delimiter 21 | * @return an array of Strings 22 | */ 23 | public static String[] parseTokens(String source, char delimiter) 24 | { 25 | int numtoken = 1; 26 | 27 | for (int i = 0; i < source.length(); i++) 28 | { 29 | if (source.charAt(i) == delimiter) 30 | numtoken++; 31 | } 32 | 33 | String list[] = new String[numtoken]; 34 | int nextfield = 0; 35 | 36 | for (int i = 0; i < numtoken; i++) 37 | { 38 | if (nextfield >= source.length()) 39 | { 40 | list[i] = ""; 41 | } 42 | else 43 | { 44 | int idx = source.indexOf(delimiter, nextfield); 45 | if (idx == -1) 46 | idx = source.length(); 47 | list[i] = source.substring(nextfield, idx); 48 | nextfield = idx + 1; 49 | } 50 | } 51 | 52 | return list; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/smiskol/phantom/CenterSeekBar.java: -------------------------------------------------------------------------------- 1 | package com.smiskol.phantom; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Rect; 8 | import android.support.v4.content.ContextCompat; 9 | import android.support.v7.widget.AppCompatSeekBar; 10 | import android.util.AttributeSet; 11 | 12 | public class CenterSeekBar extends AppCompatSeekBar { 13 | 14 | private Rect rect; 15 | private Paint paint; 16 | private int seekbar_height; 17 | 18 | public CenterSeekBar(Context context) { 19 | super(context); 20 | 21 | } 22 | 23 | public CenterSeekBar(Context context, AttributeSet attrs) { 24 | 25 | super(context, attrs); 26 | rect = new Rect(); 27 | paint = new Paint(); 28 | seekbar_height = 36; 29 | 30 | } 31 | 32 | public CenterSeekBar(Context context, AttributeSet attrs, int defStyle) { 33 | super(context, attrs, defStyle); 34 | } 35 | 36 | @Override 37 | protected synchronized void onDraw(Canvas canvas) { 38 | getThumb().mutate().setAlpha(0); 39 | rect.set(getThumbOffset() + 5, 40 | (getHeight() / 2) - (seekbar_height / 2) + 1, 41 | getWidth() - getThumbOffset() - 5, 42 | (getHeight() / 2) + (seekbar_height / 2)); 43 | 44 | paint.setColor(Color.parseColor("#FFFFFF")); 45 | canvas.drawRect(rect, paint); 46 | 47 | if (this.getProgress() > getMax() / 2) { 48 | rect.set(getWidth() / 2, 49 | (getHeight() / 2) - (seekbar_height / 2) + 1, 50 | interp(getProgress(), getMax()/2, getMax(), getWidth()/2, getWidth()-25), 51 | getHeight() / 2 + (seekbar_height / 2)); 52 | 53 | paint.setColor(ContextCompat.getColor(getContext(), R.color.colorAccent)); 54 | canvas.drawRect(rect, paint); 55 | } 56 | 57 | if (this.getProgress() < getMax() / 2) { 58 | rect.set(interp(getProgress(), getMax()/2, 0, getWidth()/2, 25), 59 | (getHeight() / 2) - (seekbar_height / 2) + 1, 60 | getWidth() / 2, 61 | getHeight() / 2 + (seekbar_height / 2)); 62 | 63 | paint.setColor(ContextCompat.getColor(getContext(), R.color.colorAccent)); 64 | canvas.drawRect(rect, paint); 65 | } 66 | 67 | super.onDraw(canvas); 68 | } 69 | public Integer interp(int value, int from1, int to1, int from2, int to2) { 70 | return (int) Math.round(((Double.valueOf(value)) - (Double.valueOf(from1))) / ((Double.valueOf(to1)) - (Double.valueOf(from1))) * ((Double.valueOf(to2)) - (Double.valueOf(from2))) + (Double.valueOf(from2))); 71 | } 72 | } -------------------------------------------------------------------------------- /app/src/main/java/com/smiskol/phantom/ViewPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.smiskol.phantom; 2 | 3 | import android.support.annotation.Nullable; 4 | import android.support.v4.app.Fragment; 5 | import android.support.v4.app.FragmentManager; 6 | import android.support.v4.app.FragmentPagerAdapter; 7 | 8 | public class ViewPagerAdapter extends FragmentPagerAdapter { 9 | private int viewCount = 1; 10 | 11 | public void setViewCount(int N) { 12 | viewCount = N; 13 | notifyDataSetChanged(); 14 | } 15 | 16 | public ViewPagerAdapter(FragmentManager fm) { 17 | super(fm); 18 | } 19 | 20 | @Override 21 | public Fragment getItem(int position) { 22 | switch (position) { 23 | case 0: 24 | return new WelcomeFragment(); 25 | case 1: 26 | return new ControlsFragment(); 27 | } 28 | return null; 29 | } 30 | 31 | @Override 32 | public int getCount() { 33 | return viewCount; 34 | } 35 | 36 | @Nullable 37 | @Override 38 | public CharSequence getPageTitle(int position) { 39 | switch (position) { 40 | case 0: 41 | return "Connect"; 42 | case 1: 43 | return "Controls"; 44 | } 45 | 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/res/anim/shake.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/hold_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/hold_disable_gradient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/hold_enable_gradient.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/hold_ripple.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_plus.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_sub.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_button_plus.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 22 | 25 | 26 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_button_sub.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 22 | 25 | 26 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/font/product.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/font/product_bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/font/product_bold.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/product_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/font/product_regular.ttf -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 27 | 28 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/toolbar_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #006585 4 | #383838 5 | #d81b40 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #2D3037 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Phantom 3 | 84db349a3c8eb016dbb95c1d1512599e6801e437 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/test/java/com/smiskol/phantom/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.smiskol.phantom; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.5.2' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | 15 | 16 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Nov 03 17:41:33 CST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /phantom-app.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sshane/phantom-app/096a366470f3104e7d683954eac69b4e2004d929/phantom-app.apk -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------