You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2008/12/04 19:59:36 UTC
svn commit: r723396 [8/12] - in /mina/sshd/trunk: ./ src/ src/docs/
src/main/ src/main/filtered-resources/ src/main/filtered-resources/org/
src/main/filtered-resources/org/apache/
src/main/filtered-resources/org/apache/sshd/ src/main/java/ src/main/jav...
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/client/channel/ChannelShell.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/client/channel/ChannelShell.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/client/channel/ChannelShell.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/client/channel/ChannelShell.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.client.channel;
+
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.util.Buffer;
+
+public class ChannelShell extends ChannelSession {
+
+ @Override
+ public void open() throws Exception {
+ super.open();
+ startShell();
+ }
+
+ protected void startShell() throws Exception {
+ Buffer buffer;
+
+ log.info("Send SSH_MSG_CHANNEL_REQUEST pty-req");
+ buffer = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_REQUEST);
+ buffer.putInt(recipient);
+ buffer.putString("pty-req");
+ buffer.putBoolean(false);
+ buffer.putString(System.getProperty("TERM", "dummy"));
+ buffer.putInt(80);
+ buffer.putInt(24);
+ buffer.putInt(640);
+ buffer.putInt(480);
+ Buffer modes = new Buffer();
+ modes.putByte((byte) 50); // ISIG
+ modes.putInt(1);
+ modes.putByte((byte) 51); // ICANON
+ modes.putInt(1);
+ modes.putByte((byte) 53); // ECHO
+ modes.putInt(1);
+ modes.putByte((byte) 54); // ECHOE
+ modes.putInt(1);
+ modes.putByte((byte) 55); // ECHOK
+ modes.putInt(1);
+ modes.putByte((byte) 56); // ECHONL
+ modes.putInt(0);
+ modes.putByte((byte) 57); // NOFLSH
+ modes.putInt(0);
+ modes.putByte((byte) 0);
+ buffer.putBytes(modes.getCompactData());
+ session.writePacket(buffer);
+
+// log.info("Send SSH_MSG_CHANNEL_REQUEST env");
+// buffer = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_REQUEST);
+// buffer.putInt(recipient);
+// buffer.putString("env");
+// session.writePacket(buffer);
+
+ log.info("Send SSH_MSG_CHANNEL_REQUEST shell");
+ buffer = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_REQUEST);
+ buffer.putInt(recipient);
+ buffer.putString("shell");
+ buffer.putBoolean(false);
+ session.writePacket(buffer);
+
+ }
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/client/kex/AbstractDHGClient.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.client.kex;
+
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+
+import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.Digest;
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.KeyPairProvider;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Signature;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.digest.SHA1;
+import org.apache.sshd.common.kex.DH;
+import org.apache.sshd.common.util.Buffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractDHGClient implements KeyExchange {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private ClientSessionImpl session;
+ private byte[] V_S;
+ private byte[] V_C;
+ private byte[] I_S;
+ private byte[] I_C;
+ private Digest sha;
+ private DH dh;
+ private byte[] e;
+ private byte[] f;
+ private byte[] K;
+ private byte[] H;
+
+ public void init(AbstractSession s, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception {
+ if (!(s instanceof ClientSessionImpl)) {
+ throw new IllegalStateException("Using a client side KeyExchange on a server");
+ }
+ session = (ClientSessionImpl) s;
+ this.V_S = V_S;
+ this.V_C = V_C;
+ this.I_S = I_S;
+ this.I_C = I_C;
+ sha = new SHA1();
+ sha.init();
+ dh = new DH();
+ initDH(dh);
+ e = dh.getE();
+
+ log.info("Send SSH_MSG_KEXDH_INIT");
+ Buffer buffer = s.createBuffer(SshConstants.Message.SSH_MSG_KEXDH_INIT);
+ buffer.putMPInt(e);
+ session.writePacket(buffer);
+ }
+
+ protected abstract void initDH(DH dh);
+
+ public boolean next(Buffer buffer) throws Exception {
+ SshConstants.Message cmd = buffer.getCommand();
+ if (cmd != SshConstants.Message.SSH_MSG_KEXDH_REPLY_KEX_DH_GEX_GROUP) {
+ throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "Protocol error: expected packet " + SshConstants.Message.SSH_MSG_KEXDH_REPLY_KEX_DH_GEX_GROUP + ", got " + cmd);
+ }
+
+ log.info("Received SSH_MSG_KEXDH_REPLY");
+
+ byte[] K_S = buffer.getBytes();
+ byte[] f = buffer.getMPIntAsBytes();
+ byte[] sig = buffer.getBytes();
+ dh.setF(f);
+ K = dh.getK();
+
+ buffer = new Buffer(K_S);
+ PublicKey key = buffer.getPublicKey();
+ String keyAlg = (key instanceof RSAPublicKey) ? KeyPairProvider.SSH_RSA : KeyPairProvider.SSH_DSS;
+
+ buffer = new Buffer();
+ buffer.putString(V_C);
+ buffer.putString(V_S);
+ buffer.putString(I_C);
+ buffer.putString(I_S);
+ buffer.putString(K_S);
+ buffer.putMPInt(e);
+ buffer.putMPInt(f);
+ buffer.putMPInt(K);
+ sha.update(buffer.array(), 0, buffer.available());
+ H = sha.digest();
+
+ Signature verif = NamedFactory.Utils.create(session.getFactoryManager().getSignatureFactories(), keyAlg);
+ verif.init(key, null);
+ verif.update(H, 0, H.length);
+ if (!verif.verify(sig)) {
+ throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED,
+ "KeyExchange signature verification failed");
+ }
+ return true;
+ }
+
+ public Digest getHash() {
+ return sha;
+ }
+
+ public byte[] getH() {
+ return H;
+ }
+
+ public byte[] getK() {
+ return K;
+ }
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/client/kex/DHG1.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/client/kex/DHG1.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/client/kex/DHG1.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/client/kex/DHG1.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.client.kex;
+
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.kex.DH;
+import org.apache.sshd.common.kex.DHGroupData;
+
+public class DHG1 extends AbstractDHGClient {
+
+ public static class Factory implements NamedFactory<KeyExchange> {
+
+ public String getName() {
+ return "diffie-hellman-group1-sha1";
+ }
+
+ public KeyExchange create() {
+ return new DHG1();
+ }
+
+ }
+
+ protected void initDH(DH dh) {
+ dh.setG(DHGroupData.G);
+ dh.setP(DHGroupData.P_1);
+ }
+
+}
\ No newline at end of file
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/client/kex/DHG14.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/client/kex/DHG14.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/client/kex/DHG14.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/client/kex/DHG14.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.client.kex;
+
+import org.apache.sshd.common.KeyExchange;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.kex.DH;
+import org.apache.sshd.common.kex.DHGroupData;
+
+/**
+ * DHG14 does not work with the default JCE implementation provided by Sun
+ * because it does not support 2048 bits encryption.
+ * It requires BouncyCastle to be used.
+ *
+ */
+public class DHG14 extends AbstractDHGClient {
+
+ public static class Factory implements NamedFactory<KeyExchange> {
+
+ public String getName() {
+ return "diffie-hellman-group14-sha1";
+ }
+
+ public KeyExchange create() {
+ return new DHG14();
+ }
+
+ }
+
+ protected void initDH(DH dh) {
+ dh.setG(DHGroupData.G);
+ dh.setP(DHGroupData.P_14);
+ }
+
+}
\ No newline at end of file
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,327 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.client.session;
+
+import java.security.PublicKey;
+import java.io.IOException;
+
+import org.apache.sshd.SshClient;
+import org.apache.sshd.client.auth.UserAuthPassword;
+import org.apache.sshd.client.channel.ChannelShell;
+import org.apache.sshd.client.channel.AbstractClientChannel;
+import org.apache.sshd.client.UserAuth;
+import org.apache.sshd.ClientChannel;
+import org.apache.sshd.ClientSession;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.KeyPairProvider;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.mina.common.IoSession;
+
+public class ClientSessionImpl extends AbstractSession implements ClientSession {
+
+ public static final String SESSION = ClientSessionImpl.class.getName();
+
+ public enum State {
+ ReceiveKexInit, Kex, ReceiveNewKeys, AuthRequestSent, WaitForAuth, UserAuth, Running, Unknown
+ }
+
+ private State state = State.ReceiveKexInit;
+ private UserAuth userAuth;
+
+ public ClientSessionImpl(SshClient client, IoSession session) throws Exception {
+ super(client, session);
+ log.info("Session created...");
+ sendClientIdentification();
+ sendKexInit();
+ }
+
+ public void authPassword(String username, String password) throws IOException {
+ if (closed) {
+ throw new IllegalStateException("Session is closed");
+ }
+ if (authed) {
+ throw new IllegalStateException("User authentication has already been performed");
+ }
+ if (userAuth != null) {
+ throw new IllegalStateException("A user authentication request is already pending");
+ }
+ waitFor(CLOSED | WAIT_AUTH, 0);
+ userAuth = new UserAuthPassword(this, username, password);
+ setState(ClientSessionImpl.State.UserAuth);
+ }
+
+ public void authPublicKey(String username, PublicKey key) throws IOException {
+ if (closed) {
+ throw new IllegalStateException("Session is closed");
+ }
+ if (authed) {
+ throw new IllegalStateException("User authentication has already been performed");
+ }
+ if (userAuth != null) {
+ throw new IllegalStateException("A user authentication request is already pending");
+ }
+ waitFor(CLOSED | WAIT_AUTH, 0);
+ // TODO: implement public key authentication method
+ throw new UnsupportedOperationException("Not supported yet");
+ }
+
+ public ClientChannel createChannel(String type) throws Exception {
+ // TODO: use NamedFactory to create channel
+ AbstractClientChannel channel;
+ if ("shell".equals(type)) {
+ channel = new ChannelShell();
+ } else {
+ throw new IllegalArgumentException("Unsupported channel type " + type);
+ }
+ int id = ++nextChannelId;
+ channel.init(this, id);
+ channels.put(id, channel);
+ return channel;
+ }
+
+ protected void handleMessage(Buffer buffer) throws Exception {
+ SshConstants.Message cmd = buffer.getCommand();
+ log.debug("Received packet {}", cmd);
+ switch (cmd) {
+ case SSH_MSG_DISCONNECT: {
+ int code = buffer.getInt();
+ String msg = buffer.getString();
+ log.info("Received SSH_MSG_DISCONNECT (reason={}, msg={})", code, msg);
+ close();
+ break;
+ }
+ case SSH_MSG_UNIMPLEMENTED: {
+ int code = buffer.getInt();
+ log.info("Received SSH_MSG_UNIMPLEMENTED #{}", code);
+ break;
+ }
+ case SSH_MSG_DEBUG: {
+ boolean display = buffer.getBoolean();
+ String msg = buffer.getString();
+ log.info("Received SSH_MSG_DEBUG '{}'", msg);
+ break;
+ }
+ case SSH_MSG_IGNORE:
+ log.info("Received SSH_MSG_IGNORE");
+ break;
+ default:
+ switch (state) {
+ case ReceiveKexInit:
+ if (cmd != SshConstants.Message.SSH_MSG_KEXINIT) {
+ log.error("Ignoring command " + cmd + " while waiting for " + SshConstants.Message.SSH_MSG_KEXINIT);
+ break;
+ }
+ log.info("Received SSH_MSG_KEXINIT");
+ receiveKexInit(buffer);
+ negociate();
+ kex = NamedFactory.Utils.create(factoryManager.getKeyExchangeFactories(), negociated[SshConstants.PROPOSAL_KEX_ALGS]);
+ kex.init(this, serverVersion.getBytes(), clientVersion.getBytes(), I_S, I_C);
+ setState(State.Kex);
+ break;
+ case Kex:
+ buffer.rpos(buffer.rpos() - 1);
+ if (kex.next(buffer)) {
+ checkHost();
+ sendNewKeys();
+ setState(State.ReceiveNewKeys);
+ }
+ break;
+ case ReceiveNewKeys:
+ if (cmd != SshConstants.Message.SSH_MSG_NEWKEYS) {
+ disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Protocol error: expected packet SSH_MSG_NEWKEYS, got " + cmd);
+ return;
+ }
+ log.info("Received SSH_MSG_NEWKEYS");
+ receiveNewKeys(false);
+ sendAuthRequest();
+ setState(State.AuthRequestSent);
+ break;
+ case AuthRequestSent:
+ if (cmd != SshConstants.Message.SSH_MSG_SERVICE_ACCEPT) {
+ disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Protocol error: expected packet SSH_MSG_SERVICE_ACCEPT, got " + cmd);
+ return;
+ }
+ setState(State.WaitForAuth);
+ break;
+ case WaitForAuth:
+ // We're waiting for the client to send an authentication request
+ // TODO: handle unexpected incoming packets
+ break;
+ case UserAuth:
+ if (userAuth == null) {
+ throw new IllegalStateException("State is userAuth, but no user auth pending!!!");
+ }
+ buffer.rpos(buffer.rpos() - 1);
+ switch (userAuth.next(buffer)) {
+ case Success:
+ authed = true;
+ setState(State.Running);
+ break;
+ case Failure:
+ userAuth = null;
+ setState(State.WaitForAuth);
+ break;
+ case Continued:
+ break;
+ }
+ break;
+ case Running:
+ switch (cmd) {
+ case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
+ channelOpenConfirmation(buffer);
+ break;
+ case SSH_MSG_CHANNEL_OPEN_FAILURE:
+ channelOpenFailure(buffer);
+ break;
+ case SSH_MSG_CHANNEL_REQUEST:
+ channelRequest(buffer);
+ break;
+ case SSH_MSG_CHANNEL_DATA:
+ channelData(buffer);
+ break;
+ case SSH_MSG_CHANNEL_EXTENDED_DATA:
+ channelExtendedData(buffer);
+ break;
+ case SSH_MSG_CHANNEL_FAILURE:
+ channelFailure(buffer);
+ break;
+ case SSH_MSG_CHANNEL_WINDOW_ADJUST:
+ channelWindowAdjust(buffer);
+ break;
+ case SSH_MSG_CHANNEL_EOF:
+ channelEof(buffer);
+ break;
+ case SSH_MSG_CHANNEL_CLOSE:
+ channelClose(buffer);
+ break;
+ // TODO: handle other requests
+ }
+ break;
+ }
+ }
+ }
+
+ public int waitFor(int mask, long timeout) {
+ long t = 0;
+ synchronized (lock) {
+ for (;;) {
+ int cond = 0;
+ if (closed) {
+ cond |= CLOSED;
+ }
+ if (authed) {
+ cond |= AUTHED;
+ }
+ if (state == State.WaitForAuth) {
+ cond |= WAIT_AUTH;
+ }
+ if ((cond & mask) != 0) {
+ return cond;
+ }
+ if (timeout > 0) {
+ if (t == 0) {
+ t = System.currentTimeMillis() + timeout;
+ } else {
+ timeout = t - System.currentTimeMillis();
+ if (timeout <= 0) {
+ cond |= TIMEOUT;
+ return cond;
+ }
+ }
+ }
+ try {
+ if (timeout > 0) {
+ lock.wait(timeout);
+ } else {
+ lock.wait();
+ }
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+ }
+ }
+
+ public void setState(State newState) {
+ synchronized (lock) {
+ this.state = newState;
+ lock.notifyAll();
+ }
+ }
+
+ protected boolean readIdentification(Buffer buffer) throws IOException {
+ serverVersion = doReadIdentification(buffer);
+ if (serverVersion == null) {
+ return false;
+ }
+ log.info("Server version string: {}", serverVersion);
+ if (!serverVersion.startsWith("SSH-2.0-")) {
+ throw new SshException(SshConstants.SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED,
+ "Unsupported protocol version: " + serverVersion);
+ }
+ return true;
+ }
+
+ private void sendClientIdentification() {
+ clientVersion = "SSH-2.0-" + getFactoryManager().getVersion();
+ sendIdentification(clientVersion);
+ }
+
+ private void sendKexInit() throws Exception {
+ clientProposal = createProposal(KeyPairProvider.SSH_RSA + "," + KeyPairProvider.SSH_DSS);
+ I_C = sendKexInit(clientProposal);
+ }
+
+ private void receiveKexInit(Buffer buffer) throws Exception {
+ serverProposal = new String[SshConstants.PROPOSAL_MAX];
+ I_S = receiveKexInit(buffer, serverProposal);
+ }
+
+ private void checkHost() throws Exception {
+ // TODO: check host fingerprint
+ }
+
+ private void sendAuthRequest() throws Exception {
+ log.info("Send SSH_MSG_SERVICE_REQUEST for ssh-userauth");
+ Buffer buffer = createBuffer(SshConstants.Message.SSH_MSG_SERVICE_REQUEST);
+ buffer.putString("ssh-userauth");
+ writePacket(buffer);
+ }
+
+ private void channelOpenConfirmation(Buffer buffer) throws IOException {
+ AbstractClientChannel channel = (AbstractClientChannel) getChannel(buffer);
+ log.info("Received SSH_MSG_CHANNEL_OPEN_CONFIRMATION on channel {}", channel.getId());
+ int recipient = buffer.getInt();
+ int rwsize = buffer.getInt();
+ int rmpsize = buffer.getInt();
+ channel.internalOpenSuccess(recipient, rwsize, rmpsize);
+ }
+
+ private void channelOpenFailure(Buffer buffer) throws IOException {
+ AbstractClientChannel channel = (AbstractClientChannel) getChannel(buffer);
+ log.info("Received SSH_MSG_CHANNEL_OPEN_FAILURE on channel {}", channel.getId());
+ channels.remove(channel.getId());
+ channel.internalOpenFailure(buffer);
+ }
+
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import java.util.List;
+import java.util.Properties;
+import java.util.Map;
+import java.util.HashMap;
+import java.io.InputStream;
+
+public abstract class AbstractFactoryManager implements FactoryManager {
+
+ private Map<String,String> properties = new HashMap<String,String>();
+ private List<NamedFactory<KeyExchange>> keyExchangeFactories;
+ private List<NamedFactory<Cipher>> cipherFactories;
+ private List<NamedFactory<Compression>> compressionFactories;
+ private List<NamedFactory<Mac>> macFactories;
+ private List<NamedFactory<Signature>> signatureFactories;
+ private NamedFactory<Random> randomFactory;
+ private KeyPairProvider keyPairProvider;
+ private String version;
+
+ protected AbstractFactoryManager() {
+ loadVersion();
+ }
+
+ public List<NamedFactory<KeyExchange>> getKeyExchangeFactories() {
+ return keyExchangeFactories;
+ }
+
+ public void setKeyExchangeFactories(List<NamedFactory<KeyExchange>> keyExchangeFactories) {
+ this.keyExchangeFactories = keyExchangeFactories;
+ }
+
+ public List<NamedFactory<Cipher>> getCipherFactories() {
+ return cipherFactories;
+ }
+
+ public void setCipherFactories(List<NamedFactory<Cipher>> cipherFactories) {
+ this.cipherFactories = cipherFactories;
+ }
+
+ public List<NamedFactory<Compression>> getCompressionFactories() {
+ return compressionFactories;
+ }
+
+ public void setCompressionFactories(List<NamedFactory<Compression>> compressionFactories) {
+ this.compressionFactories = compressionFactories;
+ }
+
+ public List<NamedFactory<Mac>> getMacFactories() {
+ return macFactories;
+ }
+
+ public void setMacFactories(List<NamedFactory<Mac>> macFactories) {
+ this.macFactories = macFactories;
+ }
+
+ public List<NamedFactory<Signature>> getSignatureFactories() {
+ return signatureFactories;
+ }
+
+ public void setSignatureFactories(List<NamedFactory<Signature>> signatureFactories) {
+ this.signatureFactories = signatureFactories;
+ }
+
+ public NamedFactory<Random> getRandomFactory() {
+ return randomFactory;
+ }
+
+ public void setRandomFactory(NamedFactory<Random> randomFactory) {
+ this.randomFactory = randomFactory;
+ }
+
+ public KeyPairProvider getKeyPairProvider() {
+ return keyPairProvider;
+ }
+
+ public void setKeyPairProvider(KeyPairProvider keyPairProvider) {
+ this.keyPairProvider = keyPairProvider;
+ }
+
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ public void setProperties(Map<String, String> properties) {
+ this.properties = properties;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ protected void loadVersion() {
+ this.version = "SSHD-UNKNOWN";
+ try {
+ InputStream input = getClass().getResourceAsStream("sshd-version.properties");
+ try {
+ Properties props = new Properties();
+ props.load(input);
+ this.version = props.getProperty("version").toUpperCase();
+ } finally {
+ input.close();
+ }
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/AbstractSessionIoHandler.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/AbstractSessionIoHandler.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/AbstractSessionIoHandler.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/AbstractSessionIoHandler.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+import org.apache.sshd.common.session.AbstractSession;
+
+public abstract class AbstractSessionIoHandler extends IoHandlerAdapter {
+
+ protected abstract AbstractSession createSession(IoSession ioSession) throws Exception;
+
+ @Override
+ public void sessionCreated(IoSession ioSession) throws Exception {
+ AbstractSession session = createSession(ioSession);
+ AbstractSession.attachSession(ioSession, session);
+ }
+
+ @Override
+ public void sessionClosed(IoSession ioSession) throws Exception {
+ AbstractSession.getSession(ioSession).close();
+ }
+
+ @Override
+ public void exceptionCaught(IoSession ioSession, Throwable cause) throws Exception {
+ AbstractSession session = AbstractSession.getSession(ioSession, true);
+ if (session != null) {
+ session.exceptionCaught(cause);
+ } else {
+ throw new IllegalStateException("No session available", cause);
+ }
+ }
+
+ @Override
+ public void messageReceived(IoSession ioSession, Object message) throws Exception {
+ AbstractSession.getSession(ioSession).messageReceived((ByteBuffer) message);
+ }
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/Channel.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/Channel.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/Channel.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/Channel.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import org.apache.sshd.common.util.Buffer;
+
+public interface Channel extends Closeable {
+
+ int getId();
+
+ void handleWindowAdjust(Buffer buffer) throws IOException;
+
+ void handleRequest(Buffer buffer) throws IOException;
+
+ void handleData(Buffer buffer) throws IOException;
+
+ void handleExtendedData(Buffer buffer) throws IOException;
+
+ void handleEof() throws IOException;
+
+ void handleFailure() throws IOException;
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/Cipher.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/Cipher.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/Cipher.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/Cipher.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+public interface Cipher {
+
+ enum Mode {
+ Encrypt, Decrypt
+ }
+
+ /**
+ * Retrieves the size of the initialization vector
+ *
+ * @return
+ */
+ int getIVSize();
+
+ /**
+ * Retrieves the block size for this cipher
+ *
+ * @return
+ */
+ int getBlockSize();
+
+ /**
+ * Initialize the cipher for encryption or decryption with
+ * the given private key and initialization vector
+ *
+ * @param mode
+ * @param key
+ * @param iv
+ * @throws Exception
+ */
+ void init(Mode mode, byte[] key, byte[] iv) throws Exception;
+
+ /**
+ * Performs in-place encryption or decryption on the given data.
+ *
+ * @param input
+ * @param inputOffset
+ * @param inputLen
+ * @throws Exception
+ */
+ void update(byte[] input, int inputOffset, int inputLen) throws Exception;
+
+}
\ No newline at end of file
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/Compression.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/Compression.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/Compression.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/Compression.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import java.io.IOException;
+
+import org.apache.sshd.common.util.Buffer;
+
+public interface Compression {
+
+ enum Type {
+ Inflater,
+ Deflater
+ }
+
+ boolean isDelayed();
+
+ void init(Type type, int level);
+
+ void compress(Buffer buffer) throws IOException;
+
+ void uncompress(Buffer from, Buffer to) throws IOException;
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/Digest.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/Digest.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/Digest.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/Digest.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+public interface Digest {
+
+ void init() throws Exception;
+
+ int getBlockSize();
+
+ void update(byte[] foo, int start, int len) throws Exception;
+
+ byte[] digest() throws Exception;
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/FactoryManager.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/FactoryManager.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/FactoryManager.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/FactoryManager.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import java.util.List;
+import java.util.Map;
+
+public interface FactoryManager {
+
+ public static final String WINDOW_SIZE = "window-size";
+ public static final String MAX_PACKET_SIZE = "packet-size";
+ public static final String MAX_AUTH_REQUESTS = "max-auth-requests";
+ public static final String AUTH_TIMEOUT = "auth-timeout";
+
+ Map<String,String> getProperties();
+
+ String getVersion();
+
+ List<NamedFactory<KeyExchange>> getKeyExchangeFactories();
+
+ List<NamedFactory<Cipher>> getCipherFactories();
+
+ List<NamedFactory<Compression>> getCompressionFactories();
+
+ List<NamedFactory<Mac>> getMacFactories();
+
+ List<NamedFactory<Signature>> getSignatureFactories();
+
+ KeyPairProvider getKeyPairProvider();
+
+ NamedFactory<Random> getRandomFactory();
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/KeyExchange.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/KeyExchange.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/KeyExchange.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/KeyExchange.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.session.AbstractSession;
+
+/**
+ * Key exchange algorithm.
+ */
+public interface KeyExchange {
+
+ /**
+ * Initialize the key exchange algorithm.
+ *
+ * @param session the session using this algorithm
+ * @param V_S the server identification string
+ * @param V_C the client identification string
+ * @param I_S the server key init packet
+ * @param I_C the client key init packet
+ * @throws Exception if an error occurs
+ */
+ void init(AbstractSession session, byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception;
+
+ /**
+ * Process the next packet
+ *
+ * @param buffer the packet
+ * @return a boolean indicating if the processing is complete or if more packets are to be received
+ * @throws Exception if an error occurs
+ */
+ boolean next(Buffer buffer) throws Exception;
+
+ /**
+ * The message digest used by this key exchange algorithm.
+ *
+ * @return the message digest
+ */
+ Digest getHash();
+
+ /**
+ * Retrieves the computed H parameter
+ *
+ * @return
+ */
+ byte[] getH();
+
+ /**
+ * Retrieves the computed K parameter
+ *
+ * @return
+ */
+ byte[] getK();
+
+}
\ No newline at end of file
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/KeyPairProvider.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/KeyPairProvider.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/KeyPairProvider.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/KeyPairProvider.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import java.security.KeyPair;
+
+/**
+ * Provider for key pairs. This provider is used on the server side to provide
+ * the host key, or on the client side to provide the user key.
+ */
+public interface KeyPairProvider {
+
+ /**
+ * SSH identifier for RSA keys
+ */
+ String SSH_RSA = "ssh-rsa";
+
+ /**
+ * SSH identifier for DSA keys
+ */
+ String SSH_DSS = "ssh-dss";
+
+ /**
+ * Load a key of the specified type which can be "ssh-rsa" or "ssh-dss".
+ * If there is no key of this type, return <code>null</code>
+ *
+ * @param type the type of key to load
+ * @return a valid key pair or <code>null</code>
+ */
+ KeyPair loadKey(String type);
+
+ /**
+ * Return a comma separated list of the key types available
+ *
+ * @return the list of key availables
+ */
+ String getKeyTypes();
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/Mac.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/Mac.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/Mac.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/Mac.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+/**
+ * Message Authentication Code for use in SSH.
+ * It usually wraps a javax.crypto.Mac class.
+ */
+public interface Mac {
+
+ int getBlockSize();
+
+ void init(byte[] key) throws Exception;
+
+ void update(byte[] foo, int start, int len);
+
+ void update(int foo);
+
+ void doFinal(byte[] buf, int offset) throws Exception;
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/NamedFactory.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/NamedFactory.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/NamedFactory.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/NamedFactory.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import java.util.List;
+
+/**
+ * A named factory is a factory identified by a name.
+ * Such names are used mainly in the algorithm negociation at the beginning of the SSH connection.
+ *
+ * @param <T>
+ */
+public interface NamedFactory<T> {
+
+ /**
+ * Name of this factory
+ * @return
+ */
+ String getName();
+
+ /**
+ * Create a new instance
+ * @return
+ */
+ T create();
+
+ /**
+ * Utility class to help using NamedFactories
+ */
+ public static class Utils {
+
+ /**
+ * Create an instance of the spcecified name by looking up the needed factory
+ * in the list.
+ *
+ * @param factories list of available factories
+ * @param name the factory name to use
+ * @param <T> type of object to create
+ * @return a newly created object or <code>null</code> if the factory is not in the list
+ */
+ public static <T> T create(List<NamedFactory<T>> factories, String name) {
+ for (NamedFactory<T> f : factories) {
+ if (f.getName().equals(name)) {
+ return f.create();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get a comma separated list of the factory names from the given list.
+ *
+ * @param factories list of available factories
+ * @param <T> type of object to create
+ * @return a comma separated list of factory names
+ */
+ public static <T> String getNames(List<NamedFactory<T>> factories) {
+ StringBuffer sb = new StringBuffer();
+ for (NamedFactory f : factories) {
+ if (sb.length() > 0) {
+ sb.append(",");
+ }
+ sb.append(f.getName());
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Remove the factory identified by the name from the list.
+ *
+ * @param factories list of factories
+ * @param name the name of the factory to remove
+ * @param <T> type of object to create
+ * @return the factory removed from the list or <code>null</code> if not in the list
+ */
+ public static <T> NamedFactory<T> remove(List<NamedFactory<T>> factories, String name) {
+ for (NamedFactory<T> f : factories) {
+ if (f.getName().equals(name)) {
+ factories.remove(f);
+ return f;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Retrieve the factory identified by its name from the list.
+ *
+ * @param factories list of available factories
+ * @param name the name of the factory to retrieve
+ * @param <T> type of object create by the factories
+ * @return a factory or <code>null</code> if not found in the list
+ */
+ public static <T> NamedFactory<T> get(List<NamedFactory<T>> factories, String name) {
+ for (NamedFactory<T> f : factories) {
+ if (f.getName().equals(name)) {
+ return f;
+ }
+ }
+ return null;
+ }
+
+ }
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/Random.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/Random.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/Random.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/Random.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+/**
+ * A pseudo random number generator
+ */
+public interface Random {
+
+ /**
+ * Fill part of bytes with random values.
+ *
+ * @param bytes byte array to be filled.
+ * @param start index to start filling at.
+ * @param len length of segment to fill.
+ */
+ void fill(byte[] bytes, int start, int len);
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/Signature.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/Signature.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/Signature.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/Signature.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+/**
+ * Signature interface for SSH used to sign or verify packets
+ * Usually wraps a javax.crypto.Signature object
+ */
+public interface Signature {
+
+ void init(PublicKey pubkey, PrivateKey prvkey) throws Exception;
+
+ void update(byte[] H, int off, int len) throws Exception;
+
+ boolean verify(byte[] sig) throws Exception;
+
+ byte[] sign() throws Exception;
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/SshConstants.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/SshConstants.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/SshConstants.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/SshConstants.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+public interface SshConstants {
+
+ public enum Message {
+
+ SSH_MSG_DISCONNECT(1),
+ SSH_MSG_IGNORE(2),
+ SSH_MSG_UNIMPLEMENTED(3),
+ SSH_MSG_DEBUG(4),
+ SSH_MSG_SERVICE_REQUEST(5),
+ SSH_MSG_SERVICE_ACCEPT(6),
+ SSH_MSG_KEXINIT(20),
+ SSH_MSG_NEWKEYS(21),
+
+ SSH_MSG_KEXDH_INIT(30),
+
+ // KEXDH_REPLY and KEX_DH_GEX_GROUP have the same command ID
+ SSH_MSG_KEXDH_REPLY_KEX_DH_GEX_GROUP(31),
+
+ SSH_MSG_KEX_DH_GEX_INIT(32),
+ SSH_MSG_KEX_DH_GEX_REPLY(33),
+ SSH_MSG_KEX_DH_GEX_REQUEST(34),
+
+ SSH_MSG_USERAUTH_REQUEST(50),
+ SSH_MSG_USERAUTH_FAILURE(51),
+ SSH_MSG_USERAUTH_SUCCESS(52),
+ SSH_MSG_USERAUTH_BANNER(53),
+ SSH_MSG_USERAUTH_INFO_REQUEST(60),
+ SSH_MSG_USERAUTH_INFO_RESPONSE(61),
+ SSH_MSG_USERAUTH_PK_OK(60),
+
+ SSH_MSG_GLOBAL_REQUEST(80),
+ SSH_MSG_REQUEST_SUCCESS(81),
+ SSH_MSG_REQUEST_FAILURE(82),
+
+ SSH_MSG_CHANNEL_OPEN(90),
+ SSH_MSG_CHANNEL_OPEN_CONFIRMATION(91),
+ SSH_MSG_CHANNEL_OPEN_FAILURE(92),
+ SSH_MSG_CHANNEL_WINDOW_ADJUST(93),
+ SSH_MSG_CHANNEL_DATA(94),
+ SSH_MSG_CHANNEL_EXTENDED_DATA(95),
+ SSH_MSG_CHANNEL_EOF(96),
+ SSH_MSG_CHANNEL_CLOSE(97),
+ SSH_MSG_CHANNEL_REQUEST(98),
+ SSH_MSG_CHANNEL_SUCCESS(99),
+ SSH_MSG_CHANNEL_FAILURE(100);
+
+ private byte b;
+ private Message(int b) {
+ this.b = (byte) b;
+ }
+
+ public byte toByte() {
+ return b;
+ }
+
+ static Message[] commands;
+ static {
+ commands = new Message[256];
+ for (Message c : Message.values()) {
+ if (commands[c.toByte()] == null) {
+ commands[c.toByte()] = c;
+ }
+ }
+ }
+ public static Message fromByte(byte b) {
+ return commands[b];
+ }
+ }
+
+ static final int PROPOSAL_KEX_ALGS = 0;
+ static final int PROPOSAL_SERVER_HOST_KEY_ALGS = 1;
+ static final int PROPOSAL_ENC_ALGS_CTOS = 2;
+ static final int PROPOSAL_ENC_ALGS_STOC = 3;
+ static final int PROPOSAL_MAC_ALGS_CTOS = 4;
+ static final int PROPOSAL_MAC_ALGS_STOC = 5;
+ static final int PROPOSAL_COMP_ALGS_CTOS = 6;
+ static final int PROPOSAL_COMP_ALGS_STOC = 7;
+ static final int PROPOSAL_LANG_CTOS = 8;
+ static final int PROPOSAL_LANG_STOC = 9;
+ static final int PROPOSAL_MAX = 10;
+
+ static final int SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT = 1;
+ static final int SSH2_DISCONNECT_PROTOCOL_ERROR = 2;
+ static final int SSH2_DISCONNECT_KEY_EXCHANGE_FAILED = 3;
+ static final int SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED = 4;
+ static final int SSH2_DISCONNECT_RESERVED = 4;
+ static final int SSH2_DISCONNECT_MAC_ERROR = 5;
+ static final int SSH2_DISCONNECT_COMPRESSION_ERROR = 6;
+ static final int SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE = 7;
+ static final int SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED = 8;
+ static final int SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE = 9;
+ static final int SSH2_DISCONNECT_CONNECTION_LOST = 10;
+ static final int SSH2_DISCONNECT_BY_APPLICATION = 11;
+ static final int SSH2_DISCONNECT_TOO_MANY_CONNECTIONS = 12;
+ static final int SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER = 13;
+ static final int SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE = 14;
+ static final int SSH2_DISCONNECT_ILLEGAL_USER_NAME = 15;
+
+ static final int SSH_OPEN_ADMINISTRATIVELY_PROHIBITED= 1;
+ static final int SSH_OPEN_CONNECT_FAILED= 2;
+ static final int SSH_OPEN_UNKNOWN_CHANNEL_TYPE= 3;
+ static final int SSH_OPEN_RESOURCE_SHORTAGE= 4;
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/SshException.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/SshException.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/SshException.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/SshException.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import java.io.IOException;
+
+public class SshException extends IOException {
+
+ private final int disconnectCode;
+
+ public SshException() {
+ this(0, null, null);
+ }
+
+ public SshException(String message) {
+ this(0, message, null);
+ }
+
+ public SshException(String message, Throwable cause) {
+ this(0, message, cause);
+ }
+
+ public SshException(Throwable cause) {
+ this(0, null, cause);
+ }
+
+ public SshException(int disconnectCode) {
+ this(disconnectCode, null, null);
+ }
+
+ public SshException(int disconnectCode, String message) {
+ this(disconnectCode, message, null);
+ }
+
+ public SshException(int disconnectCode, Throwable cause) {
+ this(disconnectCode, null, cause);
+ }
+
+ public SshException(int disconnectCode, String message, Throwable cause) {
+ super(message);
+ this.disconnectCode = disconnectCode;
+ if (cause != null) {
+ initCause(cause);
+ }
+ }
+
+ public int getDisconnectCode() {
+ return disconnectCode;
+ }
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.channel;
+
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.FactoryManager;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.BufferUtils;
+
+public abstract class AbstractChannel implements Channel {
+
+ public static final int DEFAULT_WINDOW_SIZE = 0x200000;
+ public static final int DEFAULT_PACKET_SIZE = 0x8000;
+
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+ protected final Object lock = new Object();
+ protected final Window localWindow = new Window(this, null, getClass().getName().contains(".client."), true);
+ protected final Window remoteWindow = new Window(this, null, getClass().getName().contains(".client."), false);
+ protected AbstractSession session;
+ protected int id;
+ protected int recipient;
+ protected boolean eof;
+ protected boolean closed;
+ protected boolean closing;
+
+ public int getId() {
+ return id;
+ }
+
+ public int getRecipient() {
+ return recipient;
+ }
+
+ public Window getLocalWindow() {
+ return localWindow;
+ }
+
+ public AbstractSession getSession() {
+ return session;
+ }
+
+ public void close() throws IOException {
+ log.info("Received SSH_MSG_CHANNEL_CLOSE on channel {}", id);
+ synchronized (lock) {
+ internalClose();
+ closed = true;
+ lock.notifyAll();
+ }
+ }
+
+ protected void internalClose() throws IOException {
+ synchronized (lock) {
+ if (!closing && !closed) {
+ closing = true;
+ log.info("Send SSH_MSG_CHANNEL_CLOSE on channel {}", id);
+ Buffer buffer = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_CLOSE);
+ buffer.putInt(recipient);
+ session.writePacket(buffer);
+ }
+ }
+ }
+
+ public void handleData(Buffer buffer) throws IOException {
+ int len = buffer.getInt();
+ if (len < 0 || len > 32768) {
+ throw new IllegalStateException("Bad item length: " + len);
+ }
+ log.debug("Received SSH_MSG_CHANNEL_DATA on channel {}", id);
+ if (log.isTraceEnabled()) {
+ log.trace("Received channel data: {}", BufferUtils.printHex(buffer.array(), buffer.rpos(), len));
+ }
+ doWriteData(buffer.array(), buffer.rpos(), len);
+ }
+
+ public void handleExtendedData(Buffer buffer) throws IOException {
+ int ex = buffer.getInt();
+ // Only accept extended data for stderr
+ if (ex != 1) {
+ log.info("Send SSH_MSG_CHANNEL_FAILURE on channel {}", id);
+ buffer = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_FAILURE);
+ buffer.putInt(recipient);
+ session.writePacket(buffer);
+ return;
+ }
+ int len = buffer.getInt();
+ if (len < 0 || len > 32768) {
+ throw new IllegalStateException("Bad item length: " + len);
+ }
+ log.debug("Received SSH_MSG_CHANNEL_EXTENDED_DATA on channel {}", id);
+ if (log.isTraceEnabled()) {
+ log.trace("Received channel extended data: {}", BufferUtils.printHex(buffer.array(), buffer.rpos(), len));
+ }
+ doWriteExtendedData(buffer.array(), buffer.rpos(), len);
+ }
+
+ public void handleEof() throws IOException {
+ log.info("Received SSH_MSG_CHANNEL_EOF on channel {}", id);
+ synchronized (lock) {
+ eof = true;
+ lock.notifyAll();
+ }
+ }
+
+ public void handleWindowAdjust(Buffer buffer) throws IOException {
+ log.info("Received SSH_MSG_CHANNEL_WINDOW_ADJUST on channel {}", id);
+ int window = buffer.getInt();
+ remoteWindow.expand(window);
+ }
+
+ public void handleFailure() throws IOException {
+ log.info("Received SSH_MSG_CHANNEL_FAILURE on channel {}", id);
+ // TODO: do something to report failed requests?
+ }
+
+ protected abstract void doWriteData(byte[] data, int off, int len) throws IOException;
+
+ protected abstract void doWriteExtendedData(byte[] data, int off, int len) throws IOException;
+
+ protected void sendEof() throws IOException {
+ log.info("Send SSH_MSG_CHANNEL_EOF on channel {}", id);
+ Buffer buffer = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_EOF);
+ buffer.putInt(recipient);
+ session.writePacket(buffer);
+ }
+
+ protected void configureWindow() {
+ int window = session.getIntProperty(FactoryManager.WINDOW_SIZE, DEFAULT_WINDOW_SIZE);
+ int packet = session.getIntProperty(FactoryManager.MAX_PACKET_SIZE, DEFAULT_PACKET_SIZE);
+ localWindow.init(window, packet);
+ }
+
+ protected void sendWindowAdjust(int len) throws IOException {
+ log.info("Send SSH_MSG_CHANNEL_WINDOW_ADJUST on channel {}", id);
+ Buffer buffer = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_WINDOW_ADJUST);
+ buffer.putInt(recipient);
+ buffer.putInt(len);
+ session.writePacket(buffer);
+ }
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.channel;
+
+import java.io.OutputStream;
+import java.io.IOException;
+
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.util.Buffer;
+import org.slf4j.Logger;
+
+public class ChannelOutputStream extends OutputStream {
+
+ private final AbstractChannel channel;
+ private final Window remoteWindow;
+ private final Logger log;
+ private final SshConstants.Message cmd;
+ private final byte[] b = new byte[1];
+ private Buffer buffer;
+ private boolean closed;
+ private int bufferLength;
+
+ public ChannelOutputStream(AbstractChannel channel, Window remoteWindow, Logger log, SshConstants.Message cmd) {
+ this.channel = channel;
+ this.remoteWindow = remoteWindow;
+ this.log = log;
+ this.cmd = cmd;
+ newBuffer();
+ }
+
+ public synchronized void write(int w) throws IOException {
+ b[0] = (byte) w;
+ write(b, 0, 1);
+ }
+
+ public synchronized void write(byte[] buf, int s, int l) throws IOException {
+ if (closed) {
+ throw new SshException("Already closed");
+ }
+ while (l > 0) {
+ int _l = Math.min(l, remoteWindow.getPacketSize() - bufferLength);
+ if (_l <= 0) {
+ flush();
+ continue;
+ }
+ buffer.putRawBytes(buf, s, _l);
+ bufferLength += _l;
+ s += _l;
+ l -= _l;
+ }
+ }
+
+ @Override
+ public synchronized void flush() throws IOException {
+ if (closed) {
+ throw new SshException("Already closed");
+ }
+ int pos = buffer.wpos();
+ if (bufferLength <= 0) {
+ // No data to send
+ return;
+ }
+ buffer.wpos(cmd == SshConstants.Message.SSH_MSG_CHANNEL_EXTENDED_DATA ? 14 : 10);
+ buffer.putInt(bufferLength);
+ buffer.wpos(pos);
+ try {
+ remoteWindow.waitAndConsume(bufferLength);
+ log.debug("Send {} on channel {}", cmd, channel.getId());
+ channel.getSession().writePacket(buffer);
+ } catch (SshException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SshException(e);
+ } finally {
+ newBuffer();
+ }
+ }
+
+ @Override
+ public synchronized void close() throws IOException {
+ closed = true;
+ }
+
+ private void newBuffer() {
+ buffer = channel.getSession().createBuffer(cmd);
+ buffer.putInt(channel.getRecipient());
+ if (cmd == SshConstants.Message.SSH_MSG_CHANNEL_EXTENDED_DATA) {
+ buffer.putInt(1);
+ }
+ buffer.putInt(0);
+ bufferLength = 0;
+ }
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/ChannelPipedInputStream.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/ChannelPipedInputStream.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/ChannelPipedInputStream.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/ChannelPipedInputStream.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.channel;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+
+import org.apache.sshd.common.util.Buffer;
+
+public class ChannelPipedInputStream extends InputStream {
+
+ private final Window localWindow;
+ private final Buffer buffer = new Buffer();
+ private final byte[] b = new byte[1];
+ private boolean closed;
+
+ public ChannelPipedInputStream(Window localWindow) {
+ this.localWindow = localWindow;
+ }
+
+ public int read() throws IOException {
+ synchronized (b) {
+ int l = read(b, 0, 1);
+ if (l == -1) {
+ return -1;
+ }
+ return b[0];
+ }
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ int avail;
+ synchronized (buffer) {
+ for (;;) {
+ if (closed) {
+ throw new IOException("Pipe closed");
+ }
+ if (buffer.available() > 0) {
+ break;
+ }
+ try {
+ buffer.wait();
+ } catch (InterruptedException e) {
+ throw (IOException) new InterruptedIOException().initCause(e);
+ }
+ }
+ if (len > buffer.available()) {
+ len = buffer.available();
+ }
+ buffer.getRawBytes(b, off, len);
+ if (buffer.rpos() > localWindow.getPacketSize() || buffer.available() == 0) {
+ buffer.compact();
+ }
+ avail = localWindow.getMaxSize() - buffer.available();
+ }
+ localWindow.check(avail);
+ return len;
+ }
+
+ @Override
+ public void close() throws IOException {
+ synchronized (buffer) {
+ closed = true;
+ buffer.notifyAll();
+ }
+ }
+
+ public void receive(byte[] bytes, int off, int len) throws IOException {
+ synchronized (buffer) {
+ if (closed) {
+ throw new IOException("Pipe closed");
+ }
+ buffer.putRawBytes(bytes, off, len);
+ buffer.notifyAll();
+ }
+ localWindow.consume(len);
+ }
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/ChannelPipedOutputStream.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/ChannelPipedOutputStream.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/ChannelPipedOutputStream.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/ChannelPipedOutputStream.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.channel;
+
+import java.io.OutputStream;
+import java.io.IOException;
+
+public class ChannelPipedOutputStream extends OutputStream {
+
+ private final ChannelPipedInputStream sink;
+ private final byte[] b = new byte[1];
+
+ public ChannelPipedOutputStream(ChannelPipedInputStream sink) {
+ this.sink = sink;
+ }
+
+ public void write(int i) throws IOException {
+ synchronized (b) {
+ b[0] = (byte) i;
+ write(b, 0, 1);
+ }
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ sink.receive(b, off, len);
+ }
+
+ @Override
+ public void close() throws IOException {
+ sink.close();
+ }
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/Window.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/Window.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/Window.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/channel/Window.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.channel;
+
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Window {
+
+ private final static Logger log = LoggerFactory.getLogger(Window.class);
+
+ private final AbstractChannel channel;
+ private final Object lock;
+ private final String name;
+
+ private int size;
+ private int maxSize;
+ private int packetSize;
+ private boolean waiting;
+
+ public Window(AbstractChannel channel, Object lock, boolean client, boolean local) {
+ this.channel = channel;
+ this.lock = lock != null ? lock : this;
+ this.name = (client ? "client" : "server") + " " + (local ? "local " : "remote") + " window";
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public int getMaxSize() {
+ return maxSize;
+ }
+
+ public int getPacketSize() {
+ return packetSize;
+ }
+
+ public void init(int size, int packetSize) {
+ this.size = size;
+ this.maxSize = size;
+ this.packetSize = packetSize;
+ }
+ public void expand(int window) {
+ synchronized (lock) {
+ size += window;
+ if (log.isDebugEnabled()) {
+ log.debug("Increase " + name + " by " + window + " up to " + size);
+ }
+ lock.notifyAll();
+ }
+ }
+
+ public void consume(int len) {
+ synchronized (lock) {
+ //assert size > len;
+ size -= len;
+ if (log.isTraceEnabled()) {
+ log.trace("Consume " + name + " by " + len + " down to " + size);
+ }
+ }
+ }
+
+
+ public void consumeAndCheck(int len) throws IOException {
+ synchronized (lock) {
+ //assert size > len;
+ size -= len;
+ if (log.isTraceEnabled()) {
+ log.trace("Consume " + name + " by " + len + " down to " + size);
+ }
+ check(maxSize);
+ }
+ }
+
+ public void check(int maxFree) throws IOException {
+ int threshold = Math.min(packetSize * 8, maxSize / 4);
+ synchronized (lock) {
+ if ((maxFree - size) > packetSize && (maxFree - size > threshold || size < threshold)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Increase " + name + " by " + (maxFree - size) + " up to " + maxFree);
+ }
+ channel.sendWindowAdjust(maxFree - size);
+ size = maxFree;
+ }
+ }
+ }
+
+ public void waitAndConsume(int len) throws InterruptedException {
+ synchronized (lock) {
+ while (size < len) {
+ log.debug("Waiting for {} bytes on {}", len, name);
+ waiting = true;
+ lock.wait();
+ }
+ if (waiting) {
+ log.debug("Space available for {}", name);
+ waiting = false;
+ }
+ size -= len;
+ if (log.isTraceEnabled()) {
+ log.trace("Consume " + name + " by " + len + " down to " + size);
+ }
+ }
+ }
+
+}
Added: mina/sshd/trunk/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java?rev=723396&view=auto
==============================================================================
--- mina/sshd/trunk/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java (added)
+++ mina/sshd/trunk/src/main/java/org/apache/sshd/common/cipher/AES128CBC.java Thu Dec 4 10:59:31 2008
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.cipher;
+
+import org.apache.sshd.common.Cipher;
+import org.apache.sshd.common.NamedFactory;
+
+public class AES128CBC extends BaseCipher {
+
+ public static class Factory implements NamedFactory<Cipher> {
+ public String getName() {
+ return "aes128-cbc";
+ }
+ public Cipher create() {
+ return new AES128CBC();
+ }
+ }
+
+ public AES128CBC() {
+ super(16, 16, "AES", "AES/CBC/NoPadding");
+ }
+
+}