# HG changeset patch # User Carl Byington # Date 1406755018 25200 # Node ID 071eccdff8ea417f2a3ca09f97cbad82e9981768 # Parent d2b303406d63aec07a72a15d2444e1a2d7febd61 fix java formatting diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/AbstractSFTPClient.java --- a/src/ch/ethz/ssh2/AbstractSFTPClient.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/AbstractSFTPClient.java Wed Jul 30 14:16:58 2014 -0700 @@ -53,61 +53,54 @@ * Mapping request ID to request. */ private Map pendingReadQueue - = new HashMap(); + = new HashMap(); /** * Mapping request ID to request. */ private Map pendingStatusQueue - = new HashMap(); + = new HashMap(); private PacketListener listener; protected AbstractSFTPClient(final Connection conn, final int version, final PacketListener listener) throws IOException { this.listener = listener; - log.debug("Opening session and starting SFTP subsystem."); sess = conn.openSession(); sess.startSubSystem("sftp"); - is = sess.getStdout(); os = new BufferedOutputStream(sess.getStdin(), 2048); - init(version); - } private void init(final int client_version) throws IOException { // Send SSH_FXP_INIT with client version - TypesWriter tw = new TypesWriter(); tw.writeUINT32(client_version); sendMessage(Packet.SSH_FXP_INIT, 0, tw.getBytes()); - - /* Receive SSH_FXP_VERSION */ - + /* Receive SSH_FXP_VERSION */ log.debug("Waiting for SSH_FXP_VERSION..."); TypesReader tr = new TypesReader(receiveMessage(34000)); /* Should be enough for any reasonable server */ - int t = tr.readByte(); listener.read(Packet.forName(t)); - if(t != Packet.SSH_FXP_VERSION) { + if (t != Packet.SSH_FXP_VERSION) { log.warning(String.format("The server did not send a SSH_FXP_VERSION but %d", t)); throw new PacketTypeException(t); } final int protocol_version = tr.readUINT32(); + log.debug("SSH_FXP_VERSION: protocol_version = " + protocol_version); - log.debug("SSH_FXP_VERSION: protocol_version = " + protocol_version); - if(protocol_version != client_version) { + if (protocol_version != client_version) { throw new IOException(String.format("Server protocol version %d does not match %d", - protocol_version, client_version)); + protocol_version, client_version)); } + // Both parties should from then on adhere to particular version of the protocol // Read and save extensions (if any) for later use - while(tr.remain() != 0) { + while (tr.remain() != 0) { String name = tr.readString(); listener.read(name); byte[] value = tr.readByteString(); @@ -145,16 +138,18 @@ * @see #getCharset() */ public void setCharset(String charset) throws IOException { - if(charset == null) { + if (charset == null) { this.charset = null; return; } + try { Charset.forName(charset); } - catch(UnsupportedCharsetException e) { + catch (UnsupportedCharsetException e) { throw new IOException("This charset is not supported", e); } + this.charset = charset; } @@ -172,82 +167,65 @@ public void mkdir(String dirName, int posixPermissions) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(dirName, this.getCharset()); tw.writeUINT32(AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS); tw.writeUINT32(posixPermissions); - sendMessage(Packet.SSH_FXP_MKDIR, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); } public void rm(String fileName) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(fileName, this.getCharset()); - sendMessage(Packet.SSH_FXP_REMOVE, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); } public void rmdir(String dirName) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(dirName, this.getCharset()); - sendMessage(Packet.SSH_FXP_RMDIR, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); } public void mv(String oldPath, String newPath) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(oldPath, this.getCharset()); tw.writeString(newPath, this.getCharset()); - sendMessage(Packet.SSH_FXP_RENAME, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); } public String readLink(String path) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(path, charset); - sendMessage(Packet.SSH_FXP_READLINK, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); - int rep_id = tr.readUINT32(); - if(rep_id != req_id) { + if (rep_id != req_id) { throw new RequestMismatchException(); } - if(t == Packet.SSH_FXP_NAME) { + if (t == Packet.SSH_FXP_NAME) { int count = tr.readUINT32(); - if(count != 1) { + if (count != 1) { throw new PacketTypeException(t); } return tr.readString(charset); } - if(t != Packet.SSH_FXP_STATUS) { + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } @@ -259,85 +237,69 @@ public void setstat(String path, SFTPFileAttributes attr) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(path, charset); tw.writeBytes(attr.toBytes()); - sendMessage(Packet.SSH_FXP_SETSTAT, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); } public void fsetstat(SFTPFileHandle handle, SFTPFileAttributes attr) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(handle.getHandle(), 0, handle.getHandle().length); tw.writeBytes(attr.toBytes()); - sendMessage(Packet.SSH_FXP_FSETSTAT, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); } public void createSymlink(String src, String target) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(src, charset); tw.writeString(target, charset); - sendMessage(Packet.SSH_FXP_SYMLINK, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); } public void createHardlink(String src, String target) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString("hardlink@openssh.com", charset); tw.writeString(target, charset); tw.writeString(src, charset); - sendMessage(Packet.SSH_FXP_EXTENDED, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); } public String canonicalPath(String path) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(path, charset); - sendMessage(Packet.SSH_FXP_REALPATH, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); - int rep_id = tr.readUINT32(); - if(rep_id != req_id) { + if (rep_id != req_id) { throw new RequestMismatchException(); } - if(t == Packet.SSH_FXP_NAME) { + if (t == Packet.SSH_FXP_NAME) { int count = tr.readUINT32(); - if(count != 1) { + if (count != 1) { throw new PacketFormatException("The server sent an invalid SSH_FXP_NAME packet."); } + final String name = tr.readString(charset); listener.read(name); return name; } - if(t != Packet.SSH_FXP_STATUS) { + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } @@ -348,14 +310,14 @@ } private void sendMessage(int type, int requestId, byte[] msg, int off, int len) throws IOException { - if(log.isDebugEnabled()) { + if (log.isDebugEnabled()) { log.debug(String.format("Send message of type %d with request id %d", type, requestId)); } + listener.write(Packet.forName(type)); - int msglen = len + 1; - if(type != Packet.SSH_FXP_INIT) { + if (type != Packet.SSH_FXP_INIT) { msglen += 4; } @@ -365,7 +327,7 @@ os.write(msglen); os.write(type); - if(type != Packet.SSH_FXP_INIT) { + if (type != Packet.SSH_FXP_INIT) { os.write(requestId >> 24); os.write(requestId >> 16); os.write(requestId >> 8); @@ -381,11 +343,13 @@ } private void readBytes(byte[] buff, int pos, int len) throws IOException { - while(len > 0) { + while (len > 0) { int count = is.read(buff, pos, len); - if(count < 0) { + + if (count < 0) { throw new SocketException("Unexpected end of stream."); } + len -= count; pos += count; } @@ -404,138 +368,139 @@ */ protected byte[] receiveMessage(int maxlen) throws IOException { byte[] msglen = new byte[4]; - readBytes(msglen, 0, 4); - int len = (((msglen[0] & 0xff) << 24) | ((msglen[1] & 0xff) << 16) | ((msglen[2] & 0xff) << 8) | (msglen[3] & 0xff)); - if((len > maxlen) || (len <= 0)) { + if ((len > maxlen) || (len <= 0)) { throw new PacketFormatException(String.format("Illegal SFTP packet length %d", len)); } byte[] msg = new byte[len]; - readBytes(msg, 0, len); - return msg; } protected int generateNextRequestID() { - synchronized(this) { + synchronized (this) { return next_request_id++; } } protected void closeHandle(byte[] handle) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(handle, 0, handle.length); - sendMessage(Packet.SSH_FXP_CLOSE, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); } private void readStatus() throws IOException { byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); int t = tr.readByte(); listener.read(Packet.forName(t)); - // Search the pending queue OutstandingStatusRequest status = pendingStatusQueue.remove(tr.readUINT32()); - if(null == status) { + + if (null == status) { throw new RequestMismatchException(); } // Evaluate the answer - if(t == Packet.SSH_FXP_STATUS) { + if (t == Packet.SSH_FXP_STATUS) { // In any case, stop sending more packets int code = tr.readUINT32(); - if(log.isDebugEnabled()) { + + if (log.isDebugEnabled()) { String[] desc = ErrorCodes.getDescription(code); log.debug("Got SSH_FXP_STATUS (" + status.req_id + ") (" + ((desc != null) ? desc[0] : "UNKNOWN") + ")"); } - if(code == ErrorCodes.SSH_FX_OK) { + + if (code == ErrorCodes.SSH_FX_OK) { return; } + String msg = tr.readString(); listener.read(msg); throw new SFTPException(msg, code); } + throw new PacketTypeException(t); } private void readPendingReadStatus() throws IOException { byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); int t = tr.readByte(); listener.read(Packet.forName(t)); - // Search the pending queue OutstandingReadRequest status = pendingReadQueue.remove(tr.readUINT32()); - if(null == status) { + + if (null == status) { throw new RequestMismatchException(); } // Evaluate the answer - if(t == Packet.SSH_FXP_STATUS) { + if (t == Packet.SSH_FXP_STATUS) { // In any case, stop sending more packets int code = tr.readUINT32(); - if(log.isDebugEnabled()) { + + if (log.isDebugEnabled()) { String[] desc = ErrorCodes.getDescription(code); log.debug("Got SSH_FXP_STATUS (" + status.req_id + ") (" + ((desc != null) ? desc[0] : "UNKNOWN") + ")"); } - if(code == ErrorCodes.SSH_FX_OK) { + + if (code == ErrorCodes.SSH_FX_OK) { return; } - if(code == ErrorCodes.SSH_FX_EOF) { + + if (code == ErrorCodes.SSH_FX_EOF) { return; } + String msg = tr.readString(); listener.read(msg); throw new SFTPException(msg, code); } + throw new PacketTypeException(t); } protected void expectStatusOKMessage(int id) throws IOException { byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); - int rep_id = tr.readUINT32(); - if(rep_id != id) { + if (rep_id != id) { throw new RequestMismatchException(); } - if(t != Packet.SSH_FXP_STATUS) { + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } int errorCode = tr.readUINT32(); - if(errorCode == ErrorCodes.SSH_FX_OK) { + if (errorCode == ErrorCodes.SSH_FX_OK) { return; } + String errorMessage = tr.readString(); listener.read(errorMessage); throw new SFTPException(errorMessage, errorCode); } public void closeFile(SFTPFileHandle handle) throws IOException { - while(!pendingReadQueue.isEmpty()) { + while (!pendingReadQueue.isEmpty()) { this.readPendingReadStatus(); } - while(!pendingStatusQueue.isEmpty()) { + + while (!pendingStatusQueue.isEmpty()) { this.readStatus(); } + closeHandle(handle.getHandle()); } @@ -543,24 +508,25 @@ boolean errorOccured = false; int remaining = len * parallelism; //int clientOffset = dstoff; + long serverOffset = fileOffset; - long serverOffset = fileOffset; - for(OutstandingReadRequest r : pendingReadQueue.values()) { + for (OutstandingReadRequest r : pendingReadQueue.values()) { // Server offset should take pending requests into account. serverOffset += r.len; } - while(true) { + while (true) { // Stop if there was an error and no outstanding request - if((pendingReadQueue.size() == 0) && errorOccured) { + if ((pendingReadQueue.size() == 0) && errorOccured) { break; } // Send as many requests as we are allowed to - while(pendingReadQueue.size() < parallelism) { - if(errorOccured) { + while (pendingReadQueue.size() < parallelism) { + if (errorOccured) { break; } + // Send the next read request OutstandingReadRequest req = new OutstandingReadRequest(); req.req_id = generateNextRequestID(); @@ -568,85 +534,85 @@ req.len = (remaining > len) ? len : remaining; req.buffer = dst; req.dstOffset = dstoff; - serverOffset += req.len; //clientOffset += req.len; remaining -= req.len; - sendReadRequest(req.req_id, handle, req.serverOffset, req.len); - pendingReadQueue.put(req.req_id, req); } - if(pendingReadQueue.size() == 0) { + + if (pendingReadQueue.size() == 0) { break; } // Receive a single answer byte[] resp = receiveMessage(34000); TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); - // Search the pending queue OutstandingReadRequest req = pendingReadQueue.remove(tr.readUINT32()); - if(null == req) { + + if (null == req) { throw new RequestMismatchException(); } + // Evaluate the answer - if(t == Packet.SSH_FXP_STATUS) { + if (t == Packet.SSH_FXP_STATUS) { /* In any case, stop sending more packets */ - int code = tr.readUINT32(); String msg = tr.readString(); listener.read(msg); - if(log.isDebugEnabled()) { + if (log.isDebugEnabled()) { String[] desc = ErrorCodes.getDescription(code); log.debug("Got SSH_FXP_STATUS (" + req.req_id + ") (" + ((desc != null) ? desc[0] : "UNKNOWN") + ")"); } + // Flag to read all pending requests but don't send any more. errorOccured = true; - if(pendingReadQueue.isEmpty()) { - if(ErrorCodes.SSH_FX_EOF == code) { + + if (pendingReadQueue.isEmpty()) { + if (ErrorCodes.SSH_FX_EOF == code) { return -1; } + throw new SFTPException(msg, code); } } - else if(t == Packet.SSH_FXP_DATA) { + else if (t == Packet.SSH_FXP_DATA) { // OK, collect data int readLen = tr.readUINT32(); - if((readLen < 0) || (readLen > req.len)) { + if ((readLen < 0) || (readLen > req.len)) { throw new PacketFormatException("The server sent an invalid length field in a SSH_FXP_DATA packet."); } - if(log.isDebugEnabled()) { + if (log.isDebugEnabled()) { log.debug("Got SSH_FXP_DATA (" + req.req_id + ") " + req.serverOffset + "/" + readLen - + " (requested: " + req.len + ")"); + + " (requested: " + req.len + ")"); } // Read bytes into buffer tr.readBytes(req.buffer, req.dstOffset, readLen); - if(readLen < req.len) { + if (readLen < req.len) { /* Send this request packet again to request the remaing data in this slot. */ req.req_id = generateNextRequestID(); req.serverOffset += readLen; req.len -= readLen; - log.debug("Requesting again: " + req.serverOffset + "/" + req.len); sendReadRequest(req.req_id, handle, req.serverOffset, req.len); - pendingReadQueue.put(req.req_id, req); } + return readLen; } else { throw new PacketTypeException(t); } } + // Should never reach here. throw new SFTPException("No EOF reached", -1); } @@ -656,35 +622,32 @@ tw.writeString(handle.getHandle(), 0, handle.getHandle().length); tw.writeUINT64(offset); tw.writeUINT32(len); - sendMessage(Packet.SSH_FXP_READ, id, tw.getBytes()); } public void write(SFTPFileHandle handle, long fileOffset, byte[] src, int srcoff, int len) throws IOException { - while(len > 0) { + while (len > 0) { int writeRequestLen = len; - if(writeRequestLen > 32768) { + if (writeRequestLen > 32768) { writeRequestLen = 32768; } // Send the next write request OutstandingStatusRequest req = new OutstandingStatusRequest(); req.req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(handle.getHandle(), 0, handle.getHandle().length); tw.writeUINT64(fileOffset); tw.writeString(src, srcoff, writeRequestLen); - sendMessage(Packet.SSH_FXP_WRITE, req.req_id, tw.getBytes()); - pendingStatusQueue.put(req.req_id, req); // Only read next status if parallelism reached - while(pendingStatusQueue.size() >= parallelism) { + while (pendingStatusQueue.size() >= parallelism) { this.readStatus(); } + fileOffset += writeRequestLen; srcoff += writeRequestLen; len -= writeRequestLen; diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/AuthenticationResult.java --- a/src/ch/ethz/ssh2/AuthenticationResult.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/AuthenticationResult.java Wed Jul 30 14:16:58 2014 -0700 @@ -3,19 +3,19 @@ public enum AuthenticationResult { - /** - * - */ - SUCCESS, - /** - * The authentication request to which this is a response was successful, however, more - * authentication requests are needed (multi-method authentication sequence). - * - * @see ServerAuthenticationCallback#getRemainingAuthMethods(ServerConnection) - */ - PARTIAL_SUCCESS, - /** - * The server rejected the authentication request. - */ - FAILURE + /** + * + */ + SUCCESS, + /** + * The authentication request to which this is a response was successful, however, more + * authentication requests are needed (multi-method authentication sequence). + * + * @see ServerAuthenticationCallback#getRemainingAuthMethods(ServerConnection) + */ + PARTIAL_SUCCESS, + /** + * The server rejected the authentication request. + */ + FAILURE } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/ChannelCondition.java --- a/src/ch/ethz/ssh2/ChannelCondition.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/ChannelCondition.java Wed Jul 30 14:16:58 2014 -0700 @@ -14,51 +14,50 @@ * @version 2.50, 03/15/10 */ -public abstract interface ChannelCondition -{ - /** - * A timeout has occurred, none of your requested conditions is fulfilled. - * However, other conditions may be true - therefore, NEVER use the "==" - * operator to test for this (or any other) condition. Always use - * something like ((cond & ChannelCondition.CLOSED) != 0). - */ - public static final int TIMEOUT = 1; +public abstract interface ChannelCondition { + /** + * A timeout has occurred, none of your requested conditions is fulfilled. + * However, other conditions may be true - therefore, NEVER use the "==" + * operator to test for this (or any other) condition. Always use + * something like ((cond & ChannelCondition.CLOSED) != 0). + */ + public static final int TIMEOUT = 1; - /** - * The underlying SSH-2 channel, however not necessarily the whole connection, - * has been closed. This implies EOF. Note that there may still - * be unread stdout or stderr data in the local window, i.e, STDOUT_DATA - * or/and STDERR_DATA may be set at the same time. - */ - public static final int CLOSED = 2; + /** + * The underlying SSH-2 channel, however not necessarily the whole connection, + * has been closed. This implies EOF. Note that there may still + * be unread stdout or stderr data in the local window, i.e, STDOUT_DATA + * or/and STDERR_DATA may be set at the same time. + */ + public static final int CLOSED = 2; - /** - * There is stdout data available that is ready to be consumed. - */ - public static final int STDOUT_DATA = 4; + /** + * There is stdout data available that is ready to be consumed. + */ + public static final int STDOUT_DATA = 4; - /** - * There is stderr data available that is ready to be consumed. - */ - public static final int STDERR_DATA = 8; + /** + * There is stderr data available that is ready to be consumed. + */ + public static final int STDERR_DATA = 8; - /** - * EOF on has been reached, no more _new_ stdout or stderr data will arrive - * from the remote server. However, there may be unread stdout or stderr - * data, i.e, STDOUT_DATA or/and STDERR_DATA - * may be set at the same time. - */ - public static final int EOF = 16; + /** + * EOF on has been reached, no more _new_ stdout or stderr data will arrive + * from the remote server. However, there may be unread stdout or stderr + * data, i.e, STDOUT_DATA or/and STDERR_DATA + * may be set at the same time. + */ + public static final int EOF = 16; - /** - * The exit status of the remote process is available. - * Some servers never send the exist status, or occasionally "forget" to do so. - */ - public static final int EXIT_STATUS = 32; + /** + * The exit status of the remote process is available. + * Some servers never send the exist status, or occasionally "forget" to do so. + */ + public static final int EXIT_STATUS = 32; - /** - * The exit signal of the remote process is available. - */ - public static final int EXIT_SIGNAL = 64; + /** + * The exit signal of the remote process is available. + */ + public static final int EXIT_SIGNAL = 64; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/Connection.java --- a/src/ch/ethz/ssh2/Connection.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/Connection.java Wed Jul 30 14:16:58 2014 -0700 @@ -58,11 +58,11 @@ * US-ASCII characters, with the exception of whitespace characters and the minus sign (-). */ private String softwareversion - = String.format("Ganymed_%s", Version.getSpecification()); + = String.format("Ganymed_%s", Version.getSpecification()); - /* Will be used to generate all random data needed for the current connection. + /* Will be used to generate all random data needed for the current connection. * Note: SecureRandom.nextBytes() is thread safe. - */ + */ private SecureRandom generator; @@ -71,6 +71,7 @@ * * @return The list of supported cipher algorithms by this implementation. */ + public static synchronized String[] getAvailableCiphers() { return BlockCipherFactory.getDefaultCipherList(); } @@ -80,6 +81,7 @@ * * @return The list of supported MAC algorthims by this implementation. */ + public static synchronized String[] getAvailableMACs() { return MAC.getMacList(); } @@ -89,6 +91,7 @@ * * @return The list of supported server host key algorthims by this implementation. */ + public static synchronized String[] getAvailableServerHostKeyAlgorithms() { return KexManager.getDefaultServerHostkeyAlgorithmList(); } @@ -99,10 +102,10 @@ private ChannelManager cm; private CryptoWishList cryptoWishList - = new CryptoWishList(); + = new CryptoWishList(); private DHGexParameters dhgexpara - = new DHGexParameters(); + = new DHGexParameters(); private final String hostname; @@ -115,7 +118,7 @@ private HTTPProxyData proxy; private List connectionMonitors - = new ArrayList(); + = new ArrayList(); /** * Prepares a fresh Connection object which can then be used @@ -196,33 +199,33 @@ * disappear in future builds. */ @Deprecated - public synchronized boolean authenticateWithDSA(String user, String pem, String password) throws IOException { - if(tm == null) { + + public synchronized boolean authenticateWithDSA(String user, String pem, String password) throws IOException { + if (tm == null) { throw new IllegalStateException("Connection is not established!"); } - if(authenticated) { + if (authenticated) { throw new IllegalStateException("Connection is already authenticated!"); } - if(am == null) { + if (am == null) { am = new AuthenticationManager(tm); } - if(cm == null) { + if (cm == null) { cm = new ChannelManager(tm); } - if(user == null) { + if (user == null) { throw new IllegalArgumentException("user argument is null"); } - if(pem == null) { + if (pem == null) { throw new IllegalArgumentException("pem argument is null"); } authenticated = am.authenticatePublicKey(user, pem.toCharArray(), password, getOrCreateSecureRND()); - return authenticated; } @@ -236,8 +239,9 @@ * @return whether the connection is now authenticated. * @throws IOException */ + public synchronized boolean authenticateWithKeyboardInteractive(String user, InteractiveCallback cb) - throws IOException { + throws IOException { return authenticateWithKeyboardInteractive(user, null, cb); } @@ -271,60 +275,59 @@ * @return whether the connection is now authenticated. * @throws IOException */ + public synchronized boolean authenticateWithKeyboardInteractive(String user, String[] submethods, - InteractiveCallback cb) throws IOException { - if(cb == null) { + InteractiveCallback cb) throws IOException { + if (cb == null) { throw new IllegalArgumentException("Callback may not ne NULL!"); } - if(tm == null) { + if (tm == null) { throw new IllegalStateException("Connection is not established!"); } - if(authenticated) { + if (authenticated) { throw new IllegalStateException("Connection is already authenticated!"); } - if(am == null) { + if (am == null) { am = new AuthenticationManager(tm); } - if(cm == null) { + if (cm == null) { cm = new ChannelManager(tm); } - if(user == null) { + if (user == null) { throw new IllegalArgumentException("user argument is null"); } authenticated = am.authenticateInteractive(user, submethods, cb); - return authenticated; } public synchronized boolean authenticateWithAgent(String user, AgentProxy proxy) throws IOException { - if(tm == null) { + if (tm == null) { throw new IllegalStateException("Connection is not established!"); } - if(authenticated) { + if (authenticated) { throw new IllegalStateException("Connection is already authenticated!"); } - if(am == null) { + if (am == null) { am = new AuthenticationManager(tm); } - if(cm == null) { + if (cm == null) { cm = new ChannelManager(tm); } - if(user == null) { + if (user == null) { throw new IllegalArgumentException("user argument is null"); } authenticated = am.authenticatePublicKey(user, proxy); - return authenticated; } @@ -352,33 +355,33 @@ * @return if the connection is now authenticated. * @throws IOException */ + public synchronized boolean authenticateWithPassword(String user, String password) throws IOException { - if(tm == null) { + if (tm == null) { throw new IllegalStateException("Connection is not established!"); } - if(authenticated) { + if (authenticated) { throw new IllegalStateException("Connection is already authenticated!"); } - if(am == null) { + if (am == null) { am = new AuthenticationManager(tm); } - if(cm == null) { + if (cm == null) { cm = new ChannelManager(tm); } - if(user == null) { + if (user == null) { throw new IllegalArgumentException("user argument is null"); } - if(password == null) { + if (password == null) { throw new IllegalArgumentException("password argument is null"); } authenticated = am.authenticatePassword(user, password); - return authenticated; } @@ -408,32 +411,31 @@ * @return if the connection is now authenticated. * @throws IOException */ + public synchronized boolean authenticateWithNone(String user) throws IOException { - if(tm == null) { + if (tm == null) { throw new IllegalStateException("Connection is not established!"); } - if(authenticated) { + if (authenticated) { throw new IllegalStateException("Connection is already authenticated!"); } - if(am == null) { + if (am == null) { am = new AuthenticationManager(tm); } - if(cm == null) { + if (cm == null) { cm = new ChannelManager(tm); } - if(user == null) { + if (user == null) { throw new IllegalArgumentException("user argument is null"); } - /* Trigger the sending of the PacketUserauthRequestNone packet */ + /* Trigger the sending of the PacketUserauthRequestNone packet */ /* (if not already done) */ - authenticated = am.authenticateNone(user); - return authenticated; } @@ -475,34 +477,34 @@ * @return whether the connection is now authenticated. * @throws IOException */ + public synchronized boolean authenticateWithPublicKey(String user, char[] pemPrivateKey, String password) - throws IOException { - if(tm == null) { + throws IOException { + if (tm == null) { throw new IllegalStateException("Connection is not established!"); } - if(authenticated) { + if (authenticated) { throw new IllegalStateException("Connection is already authenticated!"); } - if(am == null) { + if (am == null) { am = new AuthenticationManager(tm); } - if(cm == null) { + if (cm == null) { cm = new ChannelManager(tm); } - if(user == null) { + if (user == null) { throw new IllegalArgumentException("user argument is null"); } - if(pemPrivateKey == null) { + if (pemPrivateKey == null) { throw new IllegalArgumentException("pemPrivateKey argument is null"); } authenticated = am.authenticatePublicKey(user, pemPrivateKey, password, getOrCreateSecureRND()); - return authenticated; } @@ -578,28 +580,28 @@ * @return whether the connection is now authenticated. * @throws IOException */ + public synchronized boolean authenticateWithPublicKey(String user, File pemFile, String password) - throws IOException { - if(pemFile == null) { + throws IOException { + if (pemFile == null) { throw new IllegalArgumentException("pemFile argument is null"); } char[] buff = new char[256]; - CharArrayWriter cw = new CharArrayWriter(); - FileReader fr = new FileReader(pemFile); - while(true) { + while (true) { int len = fr.read(buff); - if(len < 0) { + + if (len < 0) { break; } + cw.write(buff, 0, len); } fr.close(); - return authenticateWithPublicKey(user, cw.toCharArray(), password); } @@ -616,10 +618,12 @@ * @param cmon An object implementing the {@link ConnectionMonitor} interface. * @see ConnectionMonitor */ + public synchronized void addConnectionMonitor(ConnectionMonitor cmon) { - if(!connectionMonitors.contains(cmon)) { + if (!connectionMonitors.contains(cmon)) { connectionMonitors.add(cmon); - if(tm != null) { + + if (tm != null) { tm.setConnectionMonitors(connectionMonitors); } } @@ -631,11 +635,14 @@ * @param cmon * @return whether the monitor could be removed */ + public synchronized boolean removeConnectionMonitor(ConnectionMonitor cmon) { boolean existed = connectionMonitors.remove(cmon); - if(tm != null) { + + if (tm != null) { tm.setConnectionMonitors(connectionMonitors); } + return existed; } @@ -661,27 +668,32 @@ * you don't need a connection anymore - otherwise the receiver thread may * run forever. */ + public synchronized void close() { - if(cm != null) { + if (cm != null) { cm.closeAllChannels(); } - if(tm != null) { + + if (tm != null) { tm.close(); tm = null; } + am = null; cm = null; authenticated = false; } public synchronized void close(IOException t) { - if(cm != null) { + if (cm != null) { cm.closeAllChannels(); } - if(tm != null) { + + if (tm != null) { tm.close(t); tm = null; } + am = null; cm = null; authenticated = false; @@ -693,6 +705,7 @@ * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. * @throws IOException */ + public synchronized ConnectionInfo connect() throws IOException { return connect(null, 0, 0); } @@ -703,6 +716,7 @@ * @return see comments for the {@link #connect(ServerHostKeyVerifier, int, int) connect(ServerHostKeyVerifier, int, int)} method. * @throws IOException */ + public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier) throws IOException { return connect(verifier, 0, 0); } @@ -768,33 +782,35 @@ * contains the details returned by the proxy. If the proxy is buggy and does * not return a proper HTTP response, then a normal IOException is thrown instead. */ + public synchronized ConnectionInfo connect(ServerHostKeyVerifier verifier, int connectTimeout, int kexTimeout) - throws IOException { + throws IOException { final class TimeoutState { boolean isCancelled = false; boolean timeoutSocketClosed = false; } - if(tm != null) { + if (tm != null) { throw new IllegalStateException(String.format("Connection to %s is already in connected state", hostname)); } - if(connectTimeout < 0) { + if (connectTimeout < 0) { throw new IllegalArgumentException("connectTimeout must be non-negative!"); } - if(kexTimeout < 0) { + if (kexTimeout < 0) { throw new IllegalArgumentException("kexTimeout must be non-negative!"); } final TimeoutState state = new TimeoutState(); - if(null == proxy) { + if (null == proxy) { tm = new ClientTransportManager(new Socket()); } else { tm = new HTTPProxyClientTransportManager(new Socket(), proxy); } + tm.setSoTimeout(connectTimeout); tm.setTcpNoDelay(tcpNoDelay); tm.setConnectionMonitors(connectionMonitors); @@ -802,68 +818,67 @@ try { TimeoutToken token = null; - if(kexTimeout > 0) { + if (kexTimeout > 0) { final Runnable timeoutHandler = new Runnable() { - public void run() { - synchronized(state) { - if(state.isCancelled) { + public void run() { + synchronized (state) { + if (state.isCancelled) { return; } + state.timeoutSocketClosed = true; tm.close(new SocketTimeoutException("The connect timeout expired")); } } }; - long timeoutHorizont = System.currentTimeMillis() + kexTimeout; - token = TimeoutService.addTimeoutHandler(timeoutHorizont, timeoutHandler); } tm.connect(hostname, port, softwareversion, cryptoWishList, verifier, dhgexpara, connectTimeout, - getOrCreateSecureRND()); - - /* Wait until first KEX has finished */ - + getOrCreateSecureRND()); + /* Wait until first KEX has finished */ ConnectionInfo ci = tm.getConnectionInfo(1); - /* Now try to cancel the timeout, if needed */ + /* Now try to cancel the timeout, if needed */ - if(token != null) { + if (token != null) { TimeoutService.cancelTimeoutHandler(token); - /* Were we too late? */ + /* Were we too late? */ - synchronized(state) { - if(state.timeoutSocketClosed) { + synchronized (state) { + if (state.timeoutSocketClosed) { throw new IOException("This exception will be replaced by the one below =)"); } + /* Just in case the "cancelTimeoutHandler" invocation came just a little bit * too late but the handler did not enter the semaphore yet - we can - * still stop it. - */ + * still stop it. + */ state.isCancelled = true; } } return ci; } - catch(SocketTimeoutException e) { + catch (SocketTimeoutException e) { throw e; } - catch(HTTPProxyException e) { + catch (HTTPProxyException e) { throw e; } - catch(IOException e) { + catch (IOException e) { // This will also invoke any registered connection monitors close(e); - synchronized(state) { + synchronized (state) { /* Show a clean exception, not something like "the socket is closed!?!" */ - if(state.timeoutSocketClosed) { + if (state.timeoutSocketClosed) { throw new SocketTimeoutException(String.format("The kexTimeout (%d ms) expired.", kexTimeout)); } } + throw e; } } @@ -883,10 +898,10 @@ * @return A {@link LocalPortForwarder} object. * @throws IOException */ + public synchronized LocalPortForwarder createLocalPortForwarder(int local_port, String host_to_connect, - int port_to_connect) throws IOException { + int port_to_connect) throws IOException { this.checkConnection(); - return new LocalPortForwarder(cm, local_port, host_to_connect, port_to_connect); } @@ -905,10 +920,10 @@ * @return A {@link LocalPortForwarder} object. * @throws IOException */ + public synchronized LocalPortForwarder createLocalPortForwarder(InetSocketAddress addr, String host_to_connect, - int port_to_connect) throws IOException { + int port_to_connect) throws IOException { this.checkConnection(); - return new LocalPortForwarder(cm, addr, host_to_connect, port_to_connect); } @@ -923,10 +938,10 @@ * @return A {@link LocalStreamForwarder} object. * @throws IOException */ + public synchronized LocalStreamForwarder createLocalStreamForwarder(String host_to_connect, int port_to_connect) - throws IOException { + throws IOException { this.checkConnection(); - return new LocalStreamForwarder(cm, host_to_connect, port_to_connect); } @@ -994,9 +1009,9 @@ * @return A {@link SCPClient} object. * @throws IOException */ + public synchronized SCPClient createSCPClient() throws IOException { this.checkConnection(); - return new SCPClient(this); } @@ -1012,9 +1027,9 @@ * * @throws IOException In case of any failure behind the scenes. */ + public synchronized void forceKeyExchange() throws IOException { this.checkConnection(); - tm.forceKeyExchange(cryptoWishList, dhgexpara, null, null, null); } @@ -1023,6 +1038,7 @@ * * @return the hostname */ + public synchronized String getHostname() { return hostname; } @@ -1032,6 +1048,7 @@ * * @return the TCP port */ + public synchronized int getPort() { return port; } @@ -1044,9 +1061,9 @@ * @return A {@link ConnectionInfo} object. * @throws IOException In case of any failure behind the scenes. */ + public synchronized ConnectionInfo getConnectionInfo() throws IOException { this.checkConnection(); - return tm.getConnectionInfo(1); } @@ -1072,24 +1089,25 @@ * @return a (possibly emtpy) array holding authentication method names. * @throws IOException */ + public synchronized String[] getRemainingAuthMethods(String user) throws IOException { - if(user == null) { + if (user == null) { throw new IllegalArgumentException("user argument may not be NULL!"); } - if(tm == null) { + if (tm == null) { throw new IllegalStateException("Connection is not established!"); } - if(authenticated) { + if (authenticated) { throw new IllegalStateException("Connection is already authenticated!"); } - if(am == null) { + if (am == null) { am = new AuthenticationManager(tm); } - if(cm == null) { + if (cm == null) { cm = new ChannelManager(tm); } @@ -1104,6 +1122,7 @@ * @return true if no further authentication steps are * needed. */ + public synchronized boolean isAuthenticationComplete() { return authenticated; } @@ -1120,10 +1139,12 @@ * @return if the there was a failed authentication step and the last one * was marked as a "partial success". */ + public synchronized boolean isAuthenticationPartialSuccess() { - if(am == null) { + if (am == null) { return false; } + return am.getPartialSuccess(); } @@ -1138,20 +1159,24 @@ * @return if the specified authentication method is currently available. * @throws IOException */ + public synchronized boolean isAuthMethodAvailable(String user, String method) throws IOException { String methods[] = getRemainingAuthMethods(user); - for(final String m : methods) { - if(m.compareTo(method) == 0) { + + for (final String m : methods) { + if (m.compareTo(method) == 0) { return true; } } + return false; } private SecureRandom getOrCreateSecureRND() { - if(generator == null) { + if (generator == null) { generator = new SecureRandom(); } + return generator; } @@ -1163,9 +1188,9 @@ * @return A {@link Session} object. * @throws IOException */ + public synchronized Session openSession() throws IOException { this.checkConnection(); - return new Session(cm, getOrCreateSecureRND()); } @@ -1177,12 +1202,11 @@ * * @throws IOException */ + public synchronized void sendIgnorePacket() throws IOException { SecureRandom rnd = getOrCreateSecureRND(); - byte[] data = new byte[rnd.nextInt(16)]; rnd.nextBytes(data); - sendIgnorePacket(data); } @@ -1193,17 +1217,17 @@ * * @throws IOException */ + public synchronized void sendIgnorePacket(byte[] data) throws IOException { this.checkConnection(); - PacketIgnore pi = new PacketIgnore(data); - tm.sendMessage(pi.getPayload()); } /** * Controls whether compression is used on the link or not. */ + public synchronized void setCompression(String[] algorithms) { CompressionFactory.checkCompressorList(algorithms); cryptoWishList.c2s_comp_algos = algorithms; @@ -1215,17 +1239,19 @@ } public synchronized void disableCompression() { - cryptoWishList.c2s_comp_algos = new String[]{"none"}; - cryptoWishList.s2c_comp_algos = new String[]{"none"}; + cryptoWishList.c2s_comp_algos = new String[] {"none"}; + cryptoWishList.s2c_comp_algos = new String[] {"none"}; } /** * Unless you know what you are doing, you will never need this. */ + public synchronized void setClient2ServerCiphers(final String[] ciphers) { - if((ciphers == null) || (ciphers.length == 0)) { + if ((ciphers == null) || (ciphers.length == 0)) { throw new IllegalArgumentException(); } + BlockCipherFactory.checkCipherList(ciphers); cryptoWishList.c2s_enc_algos = ciphers; } @@ -1233,6 +1259,7 @@ /** * Unless you know what you are doing, you will never need this. */ + public synchronized void setClient2ServerMACs(final String[] macs) { MAC.checkMacList(macs); cryptoWishList.c2s_mac_algos = macs; @@ -1245,8 +1272,9 @@ * * @param dgp {@link DHGexParameters}, non null. */ + public synchronized void setDHGexParameters(DHGexParameters dgp) { - if(dgp == null) { + if (dgp == null) { throw new IllegalArgumentException(); } @@ -1256,6 +1284,7 @@ /** * Unless you know what you are doing, you will never need this. */ + public synchronized void setServer2ClientCiphers(final String[] ciphers) { BlockCipherFactory.checkCipherList(ciphers); cryptoWishList.s2c_enc_algos = ciphers; @@ -1264,6 +1293,7 @@ /** * Unless you know what you are doing, you will never need this. */ + public synchronized void setServer2ClientMACs(final String[] macs) { MAC.checkMacList(macs); cryptoWishList.s2c_mac_algos = macs; @@ -1281,6 +1311,7 @@ * the entry at index 0 is the most preferred one. You must specify * at least one entry. */ + public synchronized void setServerHostKeyAlgorithms(final String[] algos) { KexManager.checkServerHostkeyAlgorithmsList(algos); cryptoWishList.serverHostKeyAlgorithms = algos; @@ -1296,9 +1327,11 @@ * @param enable the argument passed to the Socket.setTCPNoDelay() method. * @throws IOException */ + public synchronized void setTCPNoDelay(boolean enable) throws IOException { tcpNoDelay = enable; - if(tm != null) { + + if (tm != null) { tm.setTcpNoDelay(enable); } } @@ -1363,11 +1396,12 @@ * @param targetPort the target port * @throws IOException */ + public synchronized void requestRemotePortForwarding(String bindAddress, int bindPort, String targetAddress, - int targetPort) throws IOException { + int targetPort) throws IOException { this.checkConnection(); - if((bindAddress == null) || (targetAddress == null) || (bindPort <= 0) || (targetPort <= 0)) { + if ((bindAddress == null) || (targetAddress == null) || (bindPort <= 0) || (targetPort <= 0)) { throw new IllegalArgumentException(); } @@ -1384,9 +1418,9 @@ * @throws IOException if the remote side refuses the cancel request or another low * level error occurs (e.g., the underlying connection is closed) */ + public synchronized void cancelRemotePortForwarding(int bindPort) throws IOException { this.checkConnection(); - cm.requestCancelGlobalForward(bindPort); } @@ -1399,18 +1433,21 @@ * * @param rnd a SecureRandom instance */ + public synchronized void setSecureRandom(SecureRandom rnd) { - if(rnd == null) { + if (rnd == null) { throw new IllegalArgumentException(); } + this.generator = rnd; } private void checkConnection() throws IllegalStateException { - if(tm == null) { + if (tm == null) { throw new IllegalStateException("You need to establish a connection first."); } - if(!authenticated) { + + if (!authenticated) { throw new IllegalStateException("The connection is not authenticated."); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/ConnectionInfo.java --- a/src/ch/ethz/ssh2/ConnectionInfo.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/ConnectionInfo.java Wed Jul 30 14:16:58 2014 -0700 @@ -6,52 +6,51 @@ /** * In most cases you probably do not need the information contained in here. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class ConnectionInfo -{ - /** - * The used key exchange (KEX) algorithm in the latest key exchange. - */ - public String keyExchangeAlgorithm; +public class ConnectionInfo { + /** + * The used key exchange (KEX) algorithm in the latest key exchange. + */ + public String keyExchangeAlgorithm; - /** - * The currently used crypto algorithm for packets from to the client to the - * server. - */ - public String clientToServerCryptoAlgorithm; - /** - * The currently used crypto algorithm for packets from to the server to the - * client. - */ - public String serverToClientCryptoAlgorithm; + /** + * The currently used crypto algorithm for packets from to the client to the + * server. + */ + public String clientToServerCryptoAlgorithm; + /** + * The currently used crypto algorithm for packets from to the server to the + * client. + */ + public String serverToClientCryptoAlgorithm; - /** - * The currently used MAC algorithm for packets from to the client to the - * server. - */ - public String clientToServerMACAlgorithm; - /** - * The currently used MAC algorithm for packets from to the server to the - * client. - */ - public String serverToClientMACAlgorithm; + /** + * The currently used MAC algorithm for packets from to the client to the + * server. + */ + public String clientToServerMACAlgorithm; + /** + * The currently used MAC algorithm for packets from to the server to the + * client. + */ + public String serverToClientMACAlgorithm; - /** - * The type of the server host key (currently either "ssh-dss" or - * "ssh-rsa"). - */ - public String serverHostKeyAlgorithm; - - /** - * The server host key that was sent during the latest key exchange. - */ - public byte[] serverHostKey; + /** + * The type of the server host key (currently either "ssh-dss" or + * "ssh-rsa"). + */ + public String serverHostKeyAlgorithm; - /** - * Number of kex exchanges performed on this connection so far. - */ - public int keyExchangeCounter = 0; + /** + * The server host key that was sent during the latest key exchange. + */ + public byte[] serverHostKey; + + /** + * Number of kex exchanges performed on this connection so far. + */ + public int keyExchangeCounter = 0; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/ConnectionMonitor.java --- a/src/ch/ethz/ssh2/ConnectionMonitor.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/ConnectionMonitor.java Wed Jul 30 14:16:58 2014 -0700 @@ -6,32 +6,31 @@ /** * A ConnectionMonitor is used to get notified when the - * underlying socket of a connection is closed. - * + * underlying socket of a connection is closed. + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public interface ConnectionMonitor -{ - /** - * This method is called after the connection's underlying - * socket has been closed. E.g., due to the {@link Connection#close()} request of the - * user, if the peer closed the connection, due to a fatal error during connect() - * (also if the socket cannot be established) or if a fatal error occured on - * an established connection. - *

- * This is an experimental feature. - *

- * You MUST NOT make any assumption about the thread that invokes this method. - *

- * Please note: if the connection is not connected (e.g., there was no successful - * connect() call), then the invocation of {@link Connection#close()} will NOT trigger - * this method. - * - * @see Connection#addConnectionMonitor(ConnectionMonitor) - * - * @param reason Includes an indication why the socket was closed. - */ - public void connectionLost(Throwable reason); +public interface ConnectionMonitor { + /** + * This method is called after the connection's underlying + * socket has been closed. E.g., due to the {@link Connection#close()} request of the + * user, if the peer closed the connection, due to a fatal error during connect() + * (also if the socket cannot be established) or if a fatal error occured on + * an established connection. + *

+ * This is an experimental feature. + *

+ * You MUST NOT make any assumption about the thread that invokes this method. + *

+ * Please note: if the connection is not connected (e.g., there was no successful + * connect() call), then the invocation of {@link Connection#close()} will NOT trigger + * this method. + * + * @see Connection#addConnectionMonitor(ConnectionMonitor) + * + * @param reason Includes an indication why the socket was closed. + */ + public void connectionLost(Throwable reason); } \ No newline at end of file diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/DHGexParameters.java --- a/src/ch/ethz/ssh2/DHGexParameters.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/DHGexParameters.java Wed Jul 30 14:16:58 2014 -0700 @@ -11,114 +11,107 @@ * Depending on which constructor is used, either the use of a * SSH_MSG_KEX_DH_GEX_REQUEST or SSH_MSG_KEX_DH_GEX_REQUEST_OLD * can be forced. - * + * * @see Connection#setDHGexParameters(DHGexParameters) * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class DHGexParameters -{ - private final int min_group_len; - private final int pref_group_len; - private final int max_group_len; +public class DHGexParameters { + private final int min_group_len; + private final int pref_group_len; + private final int max_group_len; + + private static final int MIN_ALLOWED = 1024; + private static final int MAX_ALLOWED = 8192; - private static final int MIN_ALLOWED = 1024; - private static final int MAX_ALLOWED = 8192; + /** + * Same as calling {@link #DHGexParameters(int, int, int) DHGexParameters(1024, 1024, 4096)}. + * This is also the default used by the Connection class. + * + */ + public DHGexParameters() { + this(1024, 1024, 4096); + } - /** - * Same as calling {@link #DHGexParameters(int, int, int) DHGexParameters(1024, 1024, 4096)}. - * This is also the default used by the Connection class. - * - */ - public DHGexParameters() - { - this(1024, 1024, 4096); - } + /** + * This constructor can be used to force the sending of a + * SSH_MSG_KEX_DH_GEX_REQUEST_OLD request. + * Internally, the minimum and maximum group lengths will + * be set to zero. + * + * @param pref_group_len has to be >= 1024 and <= 8192 + */ + public DHGexParameters(int pref_group_len) { + if ((pref_group_len < MIN_ALLOWED) || (pref_group_len > MAX_ALLOWED)) + throw new IllegalArgumentException("pref_group_len out of range!"); - /** - * This constructor can be used to force the sending of a - * SSH_MSG_KEX_DH_GEX_REQUEST_OLD request. - * Internally, the minimum and maximum group lengths will - * be set to zero. - * - * @param pref_group_len has to be >= 1024 and <= 8192 - */ - public DHGexParameters(int pref_group_len) - { - if ((pref_group_len < MIN_ALLOWED) || (pref_group_len > MAX_ALLOWED)) - throw new IllegalArgumentException("pref_group_len out of range!"); - - this.pref_group_len = pref_group_len; - this.min_group_len = 0; - this.max_group_len = 0; - } + this.pref_group_len = pref_group_len; + this.min_group_len = 0; + this.max_group_len = 0; + } - /** - * This constructor can be used to force the sending of a - * SSH_MSG_KEX_DH_GEX_REQUEST request. - *

- * Note: older OpenSSH servers don't understand this request, in which - * case you should use the {@link #DHGexParameters(int)} constructor. - *

- * All values have to be >= 1024 and <= 8192. Furthermore, - * min_group_len <= pref_group_len <= max_group_len. - * - * @param min_group_len - * @param pref_group_len - * @param max_group_len - */ - public DHGexParameters(int min_group_len, int pref_group_len, int max_group_len) - { - if ((min_group_len < MIN_ALLOWED) || (min_group_len > MAX_ALLOWED)) - throw new IllegalArgumentException("min_group_len out of range!"); + /** + * This constructor can be used to force the sending of a + * SSH_MSG_KEX_DH_GEX_REQUEST request. + *

+ * Note: older OpenSSH servers don't understand this request, in which + * case you should use the {@link #DHGexParameters(int)} constructor. + *

+ * All values have to be >= 1024 and <= 8192. Furthermore, + * min_group_len <= pref_group_len <= max_group_len. + * + * @param min_group_len + * @param pref_group_len + * @param max_group_len + */ + public DHGexParameters(int min_group_len, int pref_group_len, int max_group_len) { + if ((min_group_len < MIN_ALLOWED) || (min_group_len > MAX_ALLOWED)) + throw new IllegalArgumentException("min_group_len out of range!"); - if ((pref_group_len < MIN_ALLOWED) || (pref_group_len > MAX_ALLOWED)) - throw new IllegalArgumentException("pref_group_len out of range!"); + if ((pref_group_len < MIN_ALLOWED) || (pref_group_len > MAX_ALLOWED)) + throw new IllegalArgumentException("pref_group_len out of range!"); - if ((max_group_len < MIN_ALLOWED) || (max_group_len > MAX_ALLOWED)) - throw new IllegalArgumentException("max_group_len out of range!"); + if ((max_group_len < MIN_ALLOWED) || (max_group_len > MAX_ALLOWED)) + throw new IllegalArgumentException("max_group_len out of range!"); - if ((pref_group_len < min_group_len) || (pref_group_len > max_group_len)) - throw new IllegalArgumentException("pref_group_len is incompatible with min and max!"); + if ((pref_group_len < min_group_len) || (pref_group_len > max_group_len)) + throw new IllegalArgumentException("pref_group_len is incompatible with min and max!"); - if (max_group_len < min_group_len) - throw new IllegalArgumentException("max_group_len must not be smaller than min_group_len!"); + if (max_group_len < min_group_len) + throw new IllegalArgumentException("max_group_len must not be smaller than min_group_len!"); - this.min_group_len = min_group_len; - this.pref_group_len = pref_group_len; - this.max_group_len = max_group_len; - } + this.min_group_len = min_group_len; + this.pref_group_len = pref_group_len; + this.max_group_len = max_group_len; + } - /** - * Get the maximum group length. - * - * @return the maximum group length, may be zero if - * SSH_MSG_KEX_DH_GEX_REQUEST_OLD should be requested - */ - public int getMax_group_len() - { - return max_group_len; - } + /** + * Get the maximum group length. + * + * @return the maximum group length, may be zero if + * SSH_MSG_KEX_DH_GEX_REQUEST_OLD should be requested + */ + public int getMax_group_len() { + return max_group_len; + } - /** - * Get the minimum group length. - * - * @return minimum group length, may be zero if - * SSH_MSG_KEX_DH_GEX_REQUEST_OLD should be requested - */ - public int getMin_group_len() - { - return min_group_len; - } + /** + * Get the minimum group length. + * + * @return minimum group length, may be zero if + * SSH_MSG_KEX_DH_GEX_REQUEST_OLD should be requested + */ + public int getMin_group_len() { + return min_group_len; + } - /** - * Get the preferred group length. - * - * @return the preferred group length - */ - public int getPref_group_len() - { - return pref_group_len; - } + /** + * Get the preferred group length. + * + * @return the preferred group length + */ + public int getPref_group_len() { + return pref_group_len; + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/HTTPProxyData.java --- a/src/ch/ethz/ssh2/HTTPProxyData.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/HTTPProxyData.java Wed Jul 30 14:16:58 2014 -0700 @@ -6,81 +6,77 @@ /** * A HTTPProxyData object is used to specify the needed connection data - * to connect through a HTTP proxy. - * + * to connect through a HTTP proxy. + * * @see Connection#setProxyData(ProxyData) - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class HTTPProxyData implements ProxyData -{ - public final String proxyHost; - public final int proxyPort; - public final String proxyUser; - public final String proxyPass; - public final String[] requestHeaderLines; +public class HTTPProxyData implements ProxyData { + public final String proxyHost; + public final int proxyPort; + public final String proxyUser; + public final String proxyPass; + public final String[] requestHeaderLines; - /** - * Same as calling {@link #HTTPProxyData(String, int, String, String) HTTPProxyData(proxyHost, proxyPort, null, null)} - * - * @param proxyHost Proxy hostname. - * @param proxyPort Proxy port. - */ - public HTTPProxyData(String proxyHost, int proxyPort) - { - this(proxyHost, proxyPort, null, null); - } + /** + * Same as calling {@link #HTTPProxyData(String, int, String, String) HTTPProxyData(proxyHost, proxyPort, null, null)} + * + * @param proxyHost Proxy hostname. + * @param proxyPort Proxy port. + */ + public HTTPProxyData(String proxyHost, int proxyPort) { + this(proxyHost, proxyPort, null, null); + } - /** - * Same as calling {@link #HTTPProxyData(String, int, String, String, String[]) HTTPProxyData(proxyHost, proxyPort, null, null, null)} - * - * @param proxyHost Proxy hostname. - * @param proxyPort Proxy port. - * @param proxyUser Username for basic authentication (null if no authentication is needed). - * @param proxyPass Password for basic authentication (null if no authentication is needed). - */ - public HTTPProxyData(String proxyHost, int proxyPort, String proxyUser, String proxyPass) - { - this(proxyHost, proxyPort, proxyUser, proxyPass, null); - } + /** + * Same as calling {@link #HTTPProxyData(String, int, String, String, String[]) HTTPProxyData(proxyHost, proxyPort, null, null, null)} + * + * @param proxyHost Proxy hostname. + * @param proxyPort Proxy port. + * @param proxyUser Username for basic authentication (null if no authentication is needed). + * @param proxyPass Password for basic authentication (null if no authentication is needed). + */ + public HTTPProxyData(String proxyHost, int proxyPort, String proxyUser, String proxyPass) { + this(proxyHost, proxyPort, proxyUser, proxyPass, null); + } - /** - * Connection data for a HTTP proxy. It is possible to specify a username and password - * if the proxy requires basic authentication. Also, additional request header lines can - * be specified (e.g., "User-Agent: CERN-LineMode/2.15 libwww/2.17b3"). - *

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

- * Here is an example: - *

- * - * new HTTPProxyData("192.168.1.1", "3128", "proxyuser", "secret", new String[] {"User-Agent: GanymedBasedClient/1.0", "X-My-Proxy-Option: something"}); - * - * - * @param proxyHost Proxy hostname. - * @param proxyPort Proxy port. - * @param proxyUser Username for basic authentication (null if no authentication is needed). - * @param proxyPass Password for basic authentication (null if no authentication is needed). - * @param requestHeaderLines An array with additional request header lines (without end-of-line markers) - * that have to be sent to the server. May be null. - */ + /** + * Connection data for a HTTP proxy. It is possible to specify a username and password + * if the proxy requires basic authentication. Also, additional request header lines can + * be specified (e.g., "User-Agent: CERN-LineMode/2.15 libwww/2.17b3"). + *

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

+ * Here is an example: + *

+ * + * new HTTPProxyData("192.168.1.1", "3128", "proxyuser", "secret", new String[] {"User-Agent: GanymedBasedClient/1.0", "X-My-Proxy-Option: something"}); + * + * + * @param proxyHost Proxy hostname. + * @param proxyPort Proxy port. + * @param proxyUser Username for basic authentication (null if no authentication is needed). + * @param proxyPass Password for basic authentication (null if no authentication is needed). + * @param requestHeaderLines An array with additional request header lines (without end-of-line markers) + * that have to be sent to the server. May be null. + */ - public HTTPProxyData(String proxyHost, int proxyPort, String proxyUser, String proxyPass, - String[] requestHeaderLines) - { - if (proxyHost == null) - throw new IllegalArgumentException("proxyHost must be non-null"); + public HTTPProxyData(String proxyHost, int proxyPort, String proxyUser, String proxyPass, + String[] requestHeaderLines) { + if (proxyHost == null) + throw new IllegalArgumentException("proxyHost must be non-null"); + + if (proxyPort < 0) + throw new IllegalArgumentException("proxyPort must be non-negative"); - if (proxyPort < 0) - throw new IllegalArgumentException("proxyPort must be non-negative"); - - this.proxyHost = proxyHost; - this.proxyPort = proxyPort; - this.proxyUser = proxyUser; - this.proxyPass = proxyPass; - this.requestHeaderLines = requestHeaderLines; - } + this.proxyHost = proxyHost; + this.proxyPort = proxyPort; + this.proxyUser = proxyUser; + this.proxyPass = proxyPass; + this.requestHeaderLines = requestHeaderLines; + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/HTTPProxyException.java --- a/src/ch/ethz/ssh2/HTTPProxyException.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/HTTPProxyException.java Wed Jul 30 14:16:58 2014 -0700 @@ -8,25 +8,23 @@ /** * May be thrown upon connect() if a HTTP proxy is being used. - * + * * @see Connection#connect() * @see Connection#setProxyData(ProxyData) - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class HTTPProxyException extends IOException -{ - private static final long serialVersionUID = 2241537397104426186L; +public class HTTPProxyException extends IOException { + private static final long serialVersionUID = 2241537397104426186L; - public final String httpResponse; - public final int httpErrorCode; + public final String httpResponse; + public final int httpErrorCode; - public HTTPProxyException(String httpResponse, int httpErrorCode) - { - super("HTTP Proxy Error (" + httpErrorCode + " " + httpResponse + ")"); - this.httpResponse = httpResponse; - this.httpErrorCode = httpErrorCode; - } + public HTTPProxyException(String httpResponse, int httpErrorCode) { + super("HTTP Proxy Error (" + httpErrorCode + " " + httpResponse + ")"); + this.httpResponse = httpResponse; + this.httpErrorCode = httpErrorCode; + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/InteractiveCallback.java --- a/src/ch/ethz/ssh2/InteractiveCallback.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/InteractiveCallback.java Wed Jul 30 14:16:58 2014 -0700 @@ -7,52 +7,51 @@ /** * An InteractiveCallback is used to respond to challenges sent * by the server if authentication mode "keyboard-interactive" is selected. - * + * * @see Connection#authenticateWithKeyboardInteractive(String, * String[], InteractiveCallback) - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public interface InteractiveCallback -{ - /** - * This callback interface is used during a "keyboard-interactive" - * authentication. Every time the server sends a set of challenges (however, - * most often just one challenge at a time), this callback function will be - * called to give your application a chance to talk to the user and to - * determine the response(s). - *

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

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

- * Note: clients SHOULD use control character filtering as discussed in - * RFC4251 to avoid attacks by including - * terminal control characters in the fields to be displayed. - * - * @param name - * the name String sent by the server. - * @param instruction - * the instruction String sent by the server. - * @param numPrompts - * number of prompts - may be zero (in this case, you should just - * return a String array of length zero). - * @param prompt - * an array (length numPrompts) of Strings - * @param echo - * an array (length numPrompts) of booleans. For - * each prompt, the corresponding echo field indicates whether or - * not the user input should be echoed as characters are typed. - * @return an array of reponses - the array size must match the parameter - * numPrompts. - */ - public String[] replyToChallenge(String name, String instruction, int numPrompts, String[] prompt, boolean[] echo) - throws Exception; +public interface InteractiveCallback { + /** + * This callback interface is used during a "keyboard-interactive" + * authentication. Every time the server sends a set of challenges (however, + * most often just one challenge at a time), this callback function will be + * called to give your application a chance to talk to the user and to + * determine the response(s). + *

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

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

+ * Note: clients SHOULD use control character filtering as discussed in + * RFC4251 to avoid attacks by including + * terminal control characters in the fields to be displayed. + * + * @param name + * the name String sent by the server. + * @param instruction + * the instruction String sent by the server. + * @param numPrompts + * number of prompts - may be zero (in this case, you should just + * return a String array of length zero). + * @param prompt + * an array (length numPrompts) of Strings + * @param echo + * an array (length numPrompts) of booleans. For + * each prompt, the corresponding echo field indicates whether or + * not the user input should be echoed as characters are typed. + * @return an array of reponses - the array size must match the parameter + * numPrompts. + */ + public String[] replyToChallenge(String name, String instruction, int numPrompts, String[] prompt, boolean[] echo) + throws Exception; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/KnownHosts.java --- a/src/ch/ethz/ssh2/KnownHosts.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/KnownHosts.java Wed Jul 30 14:16:58 2014 -0700 @@ -96,28 +96,28 @@ * @throws IOException */ public void addHostkey(String hostnames[], String serverHostKeyAlgorithm, byte[] serverHostKey) throws IOException { - if(hostnames == null) { + if (hostnames == null) { throw new IllegalArgumentException("hostnames may not be null"); } - if("ssh-rsa".equals(serverHostKeyAlgorithm)) { + if ("ssh-rsa".equals(serverHostKeyAlgorithm)) { RSAPublicKey rpk = RSASHA1Verify.decodeSSHRSAPublicKey(serverHostKey); - synchronized(publicKeys) { + synchronized (publicKeys) { publicKeys.add(new KnownHostsEntry(hostnames, rpk)); } } - else if("ssh-dss".equals(serverHostKeyAlgorithm)) { + else if ("ssh-dss".equals(serverHostKeyAlgorithm)) { DSAPublicKey dpk = DSASHA1Verify.decodeSSHDSAPublicKey(serverHostKey); - synchronized(publicKeys) { + synchronized (publicKeys) { publicKeys.add(new KnownHostsEntry(hostnames, dpk)); } } else if (serverHostKeyAlgorithm.startsWith("ecdsa-sha2-")) { ECPublicKey epk = ECDSASHA2Verify.decodeSSHECDSAPublicKey(serverHostKey); - synchronized(publicKeys) { + synchronized (publicKeys) { publicKeys.add(new KnownHostsEntry(hostnames, epk)); } } @@ -155,61 +155,54 @@ */ public static String createHashedHostname(String hostname) throws IOException { SHA1 sha1 = new SHA1(); - byte[] salt = new byte[sha1.getDigestLength()]; + new SecureRandom().nextBytes(salt); + byte[] hash; - new SecureRandom().nextBytes(salt); - - byte[] hash; try { hash = hmacSha1Hash(salt, hostname); } - catch(IOException e) { + catch (IOException e) { throw new IOException(e); } String base64_salt = new String(Base64.encode(salt)); String base64_hash = new String(Base64.encode(hash)); - return String.format("|1|%s|%s", base64_salt, base64_hash); } private static byte[] hmacSha1Hash(byte[] salt, String hostname) throws IOException { SHA1 sha1 = new SHA1(); - if(salt.length != sha1.getDigestLength()) { + if (salt.length != sha1.getDigestLength()) { throw new IllegalArgumentException("Salt has wrong length (" + salt.length + ")"); } + try { HMAC hmac = new HMAC(sha1, salt, salt.length); - hmac.update(StringEncoder.GetBytes(hostname)); - byte[] dig = new byte[hmac.getDigestLength()]; - hmac.digest(dig); - return dig; } - catch(DigestException e) { + catch (DigestException e) { throw new IOException(e); } } private boolean checkHashed(String entry, String hostname) { - if(entry.startsWith("|1|") == false) { + if (entry.startsWith("|1|") == false) { return false; } int delim_idx = entry.indexOf('|', 3); - if(delim_idx == -1) { + if (delim_idx == -1) { return false; } String salt_base64 = entry.substring(3, delim_idx); String hash_base64 = entry.substring(delim_idx + 1); - byte[] salt; byte[] hash; @@ -217,26 +210,27 @@ salt = Base64.decode(salt_base64.toCharArray()); hash = Base64.decode(hash_base64.toCharArray()); } - catch(IOException e) { + catch (IOException e) { return false; } SHA1 sha1 = new SHA1(); - if(salt.length != sha1.getDigestLength()) { + if (salt.length != sha1.getDigestLength()) { return false; } byte[] dig = new byte[0]; + try { dig = hmacSha1Hash(salt, hostname); } - catch(IOException e) { + catch (IOException e) { return false; } - for(int i = 0; i < dig.length; i++) { - if(dig[i] != hash[i]) { + for (int i = 0; i < dig.length; i++) { + if (dig[i] != hash[i]) { return false; } } @@ -247,30 +241,31 @@ private int checkKey(String remoteHostname, PublicKey remoteKey) { int result = HOSTKEY_IS_NEW; - synchronized(publicKeys) { - for(KnownHostsEntry ke : publicKeys) { - if(hostnameMatches(ke.patterns, remoteHostname) == false) { + synchronized (publicKeys) { + for (KnownHostsEntry ke : publicKeys) { + if (hostnameMatches(ke.patterns, remoteHostname) == false) { continue; } boolean res = matchKeys(ke.key, remoteKey); - if(res == true) { + if (res == true) { return HOSTKEY_IS_OK; } result = HOSTKEY_HAS_CHANGED; } } + return result; } private List getAllKeys(String hostname) { List keys = new ArrayList(); - synchronized(publicKeys) { - for(KnownHostsEntry ke : publicKeys) { - if(hostnameMatches(ke.patterns, hostname) == false) { + synchronized (publicKeys) { + for (KnownHostsEntry ke : publicKeys) { + if (hostnameMatches(ke.patterns, hostname) == false) { continue; } @@ -296,7 +291,7 @@ public String[] getPreferredServerHostkeyAlgorithmOrder(String hostname) { String[] algos = recommendHostkeyAlgorithms(hostname); - if(algos != null) { + if (algos != null) { return algos; } @@ -305,14 +300,14 @@ try { ipAdresses = InetAddress.getAllByName(hostname); } - catch(UnknownHostException e) { + catch (UnknownHostException e) { return null; } - for(int i = 0; i < ipAdresses.length; i++) { + for (int i = 0; i < ipAdresses.length; i++) { algos = recommendHostkeyAlgorithms(ipAdresses[i].getHostAddress()); - if(algos != null) { + if (algos != null) { return algos; } } @@ -323,21 +318,20 @@ private boolean hostnameMatches(String[] hostpatterns, String hostname) { boolean isMatch = false; boolean negate; - hostname = hostname.toLowerCase(); - for(int k = 0; k < hostpatterns.length; k++) { - if(hostpatterns[k] == null) { + for (int k = 0; k < hostpatterns.length; k++) { + if (hostpatterns[k] == null) { continue; } String pattern; - /* In contrast to OpenSSH we also allow negated hash entries (as well as hashed + /* In contrast to OpenSSH we also allow negated hash entries (as well as hashed * entries in lines with multiple entries). - */ + */ - if((hostpatterns[k].length() > 0) && (hostpatterns[k].charAt(0) == '!')) { + if ((hostpatterns[k].length() > 0) && (hostpatterns[k].charAt(0) == '!')) { pattern = hostpatterns[k].substring(1); negate = true; } @@ -346,37 +340,40 @@ negate = false; } - /* Optimize, no need to check this entry */ + /* Optimize, no need to check this entry */ - if((isMatch) && (negate == false)) { + if ((isMatch) && (negate == false)) { continue; } - /* Now compare */ + /* Now compare */ - if(pattern.charAt(0) == '|') { - if(checkHashed(pattern, hostname)) { - if(negate) { + if (pattern.charAt(0) == '|') { + if (checkHashed(pattern, hostname)) { + if (negate) { return false; } + isMatch = true; } } else { pattern = pattern.toLowerCase(); - if((pattern.indexOf('?') != -1) || (pattern.indexOf('*') != -1)) { - if(pseudoRegex(pattern.toCharArray(), 0, hostname.toCharArray(), 0)) { - if(negate) { + if ((pattern.indexOf('?') != -1) || (pattern.indexOf('*') != -1)) { + if (pseudoRegex(pattern.toCharArray(), 0, hostname.toCharArray(), 0)) { + if (negate) { return false; } + isMatch = true; } } - else if(pattern.compareTo(hostname) == 0) { - if(negate) { + else if (pattern.compareTo(hostname) == 0) { + if (negate) { return false; } + isMatch = true; } } @@ -388,33 +385,32 @@ private void initialize(char[] knownHostsData) throws IOException { BufferedReader br = new BufferedReader(new CharArrayReader(knownHostsData)); - while(true) { + while (true) { String line = br.readLine(); - if(line == null) { + if (line == null) { break; } line = line.trim(); - if(line.startsWith("#")) { + if (line.startsWith("#")) { continue; } String[] arr = line.split(" "); - if(arr.length >= 3) { + if (arr.length >= 3) { if ((arr[1].compareTo("ssh-rsa") == 0) || - (arr[1].compareTo("ssh-dss") == 0) || - (arr[1].startsWith("ecdsa-sha2-"))) { + (arr[1].compareTo("ssh-dss") == 0) || + (arr[1].startsWith("ecdsa-sha2-"))) { String[] hostnames = arr[0].split(","); - byte[] msg = Base64.decode(arr[2].toCharArray()); try { addHostkey(hostnames, arr[1], msg); } - catch(IOException e) { + catch (IOException e) { continue; } } @@ -424,23 +420,21 @@ private void initialize(File knownHosts) throws IOException { char[] buff = new char[512]; - CharArrayWriter cw = new CharArrayWriter(); - knownHosts.createNewFile(); - FileReader fr = new FileReader(knownHosts); - while(true) { + while (true) { int len = fr.read(buff); - if(len < 0) { + + if (len < 0) { break; } + cw.write(buff, 0, len); } fr.close(); - initialize(cw.toCharArray()); } @@ -449,50 +443,52 @@ } private boolean pseudoRegex(char[] pattern, int i, char[] match, int j) { - /* This matching logic is equivalent to the one present in OpenSSH 4.1 */ - - while(true) { - /* Are we at the end of the pattern? */ - - if(pattern.length == i) { + /* This matching logic is equivalent to the one present in OpenSSH 4.1 */ + while (true) { + /* Are we at the end of the pattern? */ + if (pattern.length == i) { return (match.length == j); } - if(pattern[i] == '*') { + if (pattern[i] == '*') { i++; - if(pattern.length == i) { + if (pattern.length == i) { return true; } - if((pattern[i] != '*') && (pattern[i] != '?')) { - while(true) { - if((pattern[i] == match[j]) && pseudoRegex(pattern, i + 1, match, j + 1)) { + if ((pattern[i] != '*') && (pattern[i] != '?')) { + while (true) { + if ((pattern[i] == match[j]) && pseudoRegex(pattern, i + 1, match, j + 1)) { return true; } + j++; - if(match.length == j) { + + if (match.length == j) { return false; } } } - while(true) { - if(pseudoRegex(pattern, i, match, j)) { + while (true) { + if (pseudoRegex(pattern, i, match, j)) { return true; } + j++; - if(match.length == j) { + + if (match.length == j) { return false; } } } - if(match.length == j) { + if (match.length == j) { return false; } - if((pattern[i] != '?') && (pattern[i] != match[j])) { + if ((pattern[i] != '?') && (pattern[i] != match[j])) { return false; } @@ -503,16 +499,15 @@ private String[] recommendHostkeyAlgorithms(String hostname) { String preferredAlgo = null; - List keys = getAllKeys(hostname); - for(Object key : keys) { + for (Object key : keys) { String thisAlgo; - if(key instanceof RSAPublicKey) { + if (key instanceof RSAPublicKey) { thisAlgo = "ssh-rsa"; } - else if(key instanceof DSAPublicKey) { + else if (key instanceof DSAPublicKey) { thisAlgo = "ssh-dss"; } else if (key instanceof ECPublicKey) { @@ -524,10 +519,9 @@ continue; } - if(preferredAlgo != null) { - /* If we find different key types, then return null */ - - if(preferredAlgo.compareTo(thisAlgo) != 0) { + if (preferredAlgo != null) { + /* If we find different key types, then return null */ + if (preferredAlgo.compareTo(thisAlgo) != 0) { return null; } } @@ -536,29 +530,29 @@ } } - /* If we did not find anything that we know of, return null */ + /* If we did not find anything that we know of, return null */ - if(preferredAlgo == null) { + if (preferredAlgo == null) { return null; } - /* Now put the preferred algo to the start of the array. - * You may ask yourself why we do it that way - basically, we could just - * return only the preferred algorithm: since we have a saved key of that - * type (sent earlier from the remote host), then that should work out. - * However, imagine that the server is (for whatever reasons) not offering - * that type of hostkey anymore (e.g., "ssh-rsa" was disabled and - * now "ssh-dss" is being used). If we then do not let the server send us - * a fresh key of the new type, then we shoot ourself into the foot: - * the connection cannot be established and hence the user cannot decide - * if he/she wants to accept the new key. - */ + /* Now put the preferred algo to the start of the array. + * You may ask yourself why we do it that way - basically, we could just + * return only the preferred algorithm: since we have a saved key of that + * type (sent earlier from the remote host), then that should work out. + * However, imagine that the server is (for whatever reasons) not offering + * that type of hostkey anymore (e.g., "ssh-rsa" was disabled and + * now "ssh-dss" is being used). If we then do not let the server send us + * a fresh key of the new type, then we shoot ourself into the foot: + * the connection cannot be established and hence the user cannot decide + * if he/she wants to accept the new key. + */ - if(preferredAlgo.equals("ssh-rsa")) { - return new String[]{"ssh-rsa", "ssh-dss", "ecdsa-sha2-nistp256"}; + if (preferredAlgo.equals("ssh-rsa")) { + return new String[] {"ssh-rsa", "ssh-dss", "ecdsa-sha2-nistp256"}; } - return new String[]{"ssh-dss", "ssh-rsa", "ecdsa-sha2-nistp256"}; + return new String[] {"ssh-dss", "ssh-rsa", "ecdsa-sha2-nistp256"}; } /** @@ -580,10 +574,10 @@ public int verifyHostkey(String hostname, String serverHostKeyAlgorithm, byte[] serverHostKey) throws IOException { PublicKey remoteKey; - if("ssh-rsa".equals(serverHostKeyAlgorithm)) { + if ("ssh-rsa".equals(serverHostKeyAlgorithm)) { remoteKey = RSASHA1Verify.decodeSSHRSAPublicKey(serverHostKey); } - else if("ssh-dss".equals(serverHostKeyAlgorithm)) { + else if ("ssh-dss".equals(serverHostKeyAlgorithm)) { remoteKey = DSASHA1Verify.decodeSSHDSAPublicKey(serverHostKey); } else if (serverHostKeyAlgorithm.startsWith("ecdsa-sha2-")) { @@ -595,7 +589,7 @@ int result = checkKey(hostname, remoteKey); - if(result == HOSTKEY_IS_OK) { + if (result == HOSTKEY_IS_OK) { return result; } @@ -604,18 +598,18 @@ try { ipAdresses = InetAddress.getAllByName(hostname); } - catch(UnknownHostException e) { + catch (UnknownHostException e) { return result; } - for(int i = 0; i < ipAdresses.length; i++) { + for (int i = 0; i < ipAdresses.length; i++) { int newresult = checkKey(ipAdresses[i].getHostAddress(), remoteKey); - if(newresult == HOSTKEY_IS_OK) { + if (newresult == HOSTKEY_IS_OK) { return newresult; } - if(newresult == HOSTKEY_HAS_CHANGED) { + if (newresult == HOSTKEY_HAS_CHANGED) { result = HOSTKEY_HAS_CHANGED; } } @@ -636,20 +630,21 @@ */ public static void addHostkeyToFile(File knownHosts, String[] hostnames, String serverHostKeyAlgorithm, byte[] serverHostKey) throws IOException { - if((hostnames == null) || (hostnames.length == 0)) { + if ((hostnames == null) || (hostnames.length == 0)) { throw new IllegalArgumentException("Need at least one hostname specification"); } - if((serverHostKeyAlgorithm == null) || (serverHostKey == null)) { + if ((serverHostKeyAlgorithm == null) || (serverHostKey == null)) { throw new IllegalArgumentException(); } CharArrayWriter writer = new CharArrayWriter(); - for(int i = 0; i < hostnames.length; i++) { - if(i != 0) { + for (int i = 0; i < hostnames.length; i++) { + if (i != 0) { writer.write(','); } + writer.write(hostnames[i]); } @@ -658,17 +653,15 @@ writer.write(' '); writer.write(Base64.encode(serverHostKey)); writer.write("\n"); - char[] entry = writer.toCharArray(); - RandomAccessFile raf = new RandomAccessFile(knownHosts, "rw"); - long len = raf.length(); - if(len > 0) { + if (len > 0) { raf.seek(len - 1); int last = raf.read(); - if(last != '\n') { + + if (last != '\n') { raf.write('\n'); } } @@ -688,19 +681,19 @@ static private byte[] rawFingerPrint(String type, String keyType, byte[] hostkey) throws IOException { Digest dig; - if("md5".equals(type)) { + if ("md5".equals(type)) { dig = new MD5(); } - else if("sha1".equals(type)) { + else if ("sha1".equals(type)) { dig = new SHA1(); } else { throw new IllegalArgumentException("Unknown hash type " + type); } - if("ssh-rsa".equals(keyType)) { + if ("ssh-rsa".equals(keyType)) { } - else if("ssh-dss".equals(keyType)) { + else if ("ssh-dss".equals(keyType)) { } else if (keyType.startsWith("ecdsa-sha2-")) { } @@ -708,18 +701,20 @@ throw new IllegalArgumentException("Unknown key type " + keyType); } - if(hostkey == null) { + if (hostkey == null) { throw new IllegalArgumentException("hostkey is null"); } dig.update(hostkey); byte[] res = new byte[dig.getDigestLength()]; + try { dig.digest(res); } - catch(DigestException e) { + catch (DigestException e) { throw new IOException(e); } + return res; } @@ -731,13 +726,13 @@ */ static private String rawToHexFingerprint(byte[] fingerprint) { final char[] alpha = "0123456789abcdef".toCharArray(); - StringBuilder sb = new StringBuilder(); - for(int i = 0; i < fingerprint.length; i++) { - if(i != 0) { + for (int i = 0; i < fingerprint.length; i++) { + if (i != 0) { sb.append(':'); } + int b = fingerprint[i] & 0xff; sb.append(alpha[b >> 4]); sb.append(alpha[b & 15]); @@ -755,22 +750,18 @@ static private String rawToBubblebabbleFingerprint(byte[] raw) { final char[] v = "aeiouy".toCharArray(); final char[] c = "bcdfghklmnprstvzx".toCharArray(); - StringBuilder sb = new StringBuilder(); - int seed = 1; - int rounds = (raw.length / 2) + 1; - sb.append('x'); - for(int i = 0; i < rounds; i++) { - if(((i + 1) < rounds) || ((raw.length) % 2 != 0)) { + for (int i = 0; i < rounds; i++) { + if (((i + 1) < rounds) || ((raw.length) % 2 != 0)) { sb.append(v[(((raw[2 * i] >> 6) & 3) + seed) % 6]); sb.append(c[(raw[2 * i] >> 2) & 15]); sb.append(v[((raw[2 * i] & 3) + (seed / 6)) % 6]); - if((i + 1) < rounds) { + if ((i + 1) < rounds) { sb.append(c[(((raw[(2 * i) + 1])) >> 4) & 15]); sb.append('-'); sb.append(c[(((raw[(2 * i) + 1]))) & 15]); @@ -786,7 +777,6 @@ } sb.append('x'); - return sb.toString(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/LocalPortForwarder.java --- a/src/ch/ethz/ssh2/LocalPortForwarder.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/LocalPortForwarder.java Wed Jul 30 14:16:58 2014 -0700 @@ -17,60 +17,53 @@ * port via the secure tunnel to another host (which may or may not be identical * to the remote SSH-2 server). Checkout {@link Connection#createLocalPortForwarder(int, String, int)} * on how to create one. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class LocalPortForwarder -{ - final ChannelManager cm; +public class LocalPortForwarder { + final ChannelManager cm; - final String host_to_connect; + final String host_to_connect; - final int port_to_connect; + final int port_to_connect; - final LocalAcceptThread lat; + final LocalAcceptThread lat; - LocalPortForwarder(ChannelManager cm, int local_port, String host_to_connect, int port_to_connect) - throws IOException - { - this.cm = cm; - this.host_to_connect = host_to_connect; - this.port_to_connect = port_to_connect; - - lat = new LocalAcceptThread(cm, local_port, host_to_connect, port_to_connect); - lat.setDaemon(true); - lat.start(); - } + LocalPortForwarder(ChannelManager cm, int local_port, String host_to_connect, int port_to_connect) + throws IOException { + this.cm = cm; + this.host_to_connect = host_to_connect; + this.port_to_connect = port_to_connect; + lat = new LocalAcceptThread(cm, local_port, host_to_connect, port_to_connect); + lat.setDaemon(true); + lat.start(); + } - LocalPortForwarder(ChannelManager cm, InetSocketAddress addr, String host_to_connect, int port_to_connect) - throws IOException - { - this.cm = cm; - this.host_to_connect = host_to_connect; - this.port_to_connect = port_to_connect; - - lat = new LocalAcceptThread(cm, addr, host_to_connect, port_to_connect); - lat.setDaemon(true); - lat.start(); - } + LocalPortForwarder(ChannelManager cm, InetSocketAddress addr, String host_to_connect, int port_to_connect) + throws IOException { + this.cm = cm; + this.host_to_connect = host_to_connect; + this.port_to_connect = port_to_connect; + lat = new LocalAcceptThread(cm, addr, host_to_connect, port_to_connect); + lat.setDaemon(true); + lat.start(); + } - /** - * Return the local socket address of the {@link ServerSocket} used to accept connections. - * @return - */ - public InetSocketAddress getLocalSocketAddress() - { - return (InetSocketAddress) lat.getServerSocket().getLocalSocketAddress(); - } + /** + * Return the local socket address of the {@link ServerSocket} used to accept connections. + * @return + */ + public InetSocketAddress getLocalSocketAddress() { + return (InetSocketAddress) lat.getServerSocket().getLocalSocketAddress(); + } - /** - * Stop TCP/IP forwarding of newly arriving connections. - * - * @throws IOException - */ - public void close() throws IOException - { - lat.stopWorking(); - } + /** + * Stop TCP/IP forwarding of newly arriving connections. + * + * @throws IOException + */ + public void close() throws IOException { + lat.stopWorking(); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/LocalStreamForwarder.java --- a/src/ch/ethz/ssh2/LocalStreamForwarder.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/LocalStreamForwarder.java Wed Jul 30 14:16:58 2014 -0700 @@ -20,55 +20,50 @@ * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class LocalStreamForwarder -{ - private ChannelManager cm; +public class LocalStreamForwarder { + private ChannelManager cm; - private Channel cn; + private Channel cn; - LocalStreamForwarder(ChannelManager cm, String host_to_connect, int port_to_connect) throws IOException - { - this.cm = cm; - cn = cm.openDirectTCPIPChannel(host_to_connect, port_to_connect, - InetAddress.getLocalHost().getHostAddress(), 0); - } + LocalStreamForwarder(ChannelManager cm, String host_to_connect, int port_to_connect) throws IOException { + this.cm = cm; + cn = cm.openDirectTCPIPChannel(host_to_connect, port_to_connect, + InetAddress.getLocalHost().getHostAddress(), 0); + } - /** - * @return An InputStream object. - * @throws IOException - */ - public InputStream getInputStream() throws IOException - { - return cn.getStdoutStream(); - } + /** + * @return An InputStream object. + * @throws IOException + */ + public InputStream getInputStream() throws IOException { + return cn.getStdoutStream(); + } - /** - * Get the OutputStream. Please be aware that the implementation MAY use an - * internal buffer. To make sure that the buffered data is sent over the - * tunnel, you have to call the flush method of the - * OutputStream. To signal EOF, please use the - * close method of the OutputStream. - * - * @return An OutputStream object. - * @throws IOException - */ - public OutputStream getOutputStream() throws IOException - { - return cn.getStdinStream(); - } + /** + * Get the OutputStream. Please be aware that the implementation MAY use an + * internal buffer. To make sure that the buffered data is sent over the + * tunnel, you have to call the flush method of the + * OutputStream. To signal EOF, please use the + * close method of the OutputStream. + * + * @return An OutputStream object. + * @throws IOException + */ + public OutputStream getOutputStream() throws IOException { + return cn.getStdinStream(); + } - /** - * Close the underlying SSH forwarding channel and free up resources. - * You can also use this method to force the shutdown of the underlying - * forwarding channel. Pending output (OutputStream not flushed) will NOT - * be sent. Pending input (InputStream) can still be read. If the shutdown - * operation is already in progress (initiated from either side), then this - * call is a no-op. - * - * @throws IOException - */ - public void close() throws IOException - { - cm.closeChannel(cn, "Closed due to user request.", true); - } + /** + * Close the underlying SSH forwarding channel and free up resources. + * You can also use this method to force the shutdown of the underlying + * forwarding channel. Pending output (OutputStream not flushed) will NOT + * be sent. Pending input (InputStream) can still be read. If the shutdown + * operation is already in progress (initiated from either side), then this + * call is a no-op. + * + * @throws IOException + */ + public void close() throws IOException { + cm.closeChannel(cn, "Closed due to user request.", true); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/PacketFormatException.java --- a/src/ch/ethz/ssh2/PacketFormatException.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/PacketFormatException.java Wed Jul 30 14:16:58 2014 -0700 @@ -5,11 +5,9 @@ /** * @version $Id: PacketFormatException.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ */ -public class PacketFormatException extends IOException -{ +public class PacketFormatException extends IOException { - public PacketFormatException(String message) - { - super(message); - } + public PacketFormatException(String message) { + super(message); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/ProxyData.java --- a/src/ch/ethz/ssh2/ProxyData.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/ProxyData.java Wed Jul 30 14:16:58 2014 -0700 @@ -6,13 +6,12 @@ /** * An abstract marker interface implemented by all proxy data implementations. - * + * * @see HTTPProxyData - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public abstract interface ProxyData -{ +public abstract interface ProxyData { } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/PtySettings.java --- a/src/ch/ethz/ssh2/PtySettings.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/PtySettings.java Wed Jul 30 14:16:58 2014 -0700 @@ -10,38 +10,37 @@ * the drawable area of the window. The dimension parameters are only * informational. The encoding of terminal modes (parameter * terminal_modes) is described in RFC4254. - * + * * @author Christian */ -public class PtySettings -{ - /** - * TERM environment variable value (e.g., vt100) - */ - public String term; +public class PtySettings { + /** + * TERM environment variable value (e.g., vt100) + */ + public String term; - /** - * Terminal width, characters (e.g., 80) - */ - public int term_width_characters; + /** + * Terminal width, characters (e.g., 80) + */ + public int term_width_characters; + + /** + * Terminal height, rows (e.g., 24) + */ + public int term_height_characters; - /** - * Terminal height, rows (e.g., 24) - */ - public int term_height_characters; - - /** - * Terminal width, pixels (e.g., 640) - */ - public int term_width_pixels; + /** + * Terminal width, pixels (e.g., 640) + */ + public int term_width_pixels; - /** - * Terminal height, pixels (e.g., 480) - */ - public int term_height_pixels; + /** + * Terminal height, pixels (e.g., 480) + */ + public int term_height_pixels; - /** - * Encoded terminal modes - */ - public byte[] terminal_modes; + /** + * Encoded terminal modes + */ + public byte[] terminal_modes; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/SCPClient.java --- a/src/ch/ethz/ssh2/SCPClient.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/SCPClient.java Wed Jul 30 14:16:58 2014 -0700 @@ -23,218 +23,200 @@ * @version $Id: SCPClient.java 85 2014-04-07 14:05:09Z dkocher@sudo.ch $ */ -public class SCPClient -{ - Connection conn; +public class SCPClient { + Connection conn; - String charsetName = null; + String charsetName = null; - /** - * Set the charset used to convert between Java Unicode Strings and byte encodings - * used by the server for paths and file names. - * - * @param charset the name of the charset to be used or null to use the platform's - * default encoding. - * @throws IOException - * @see #getCharset() - */ - public void setCharset(String charset) throws IOException - { - if (charset == null) - { - charsetName = charset; - return; - } + /** + * Set the charset used to convert between Java Unicode Strings and byte encodings + * used by the server for paths and file names. + * + * @param charset the name of the charset to be used or null to use the platform's + * default encoding. + * @throws IOException + * @see #getCharset() + */ + public void setCharset(String charset) throws IOException { + if (charset == null) { + charsetName = charset; + return; + } - try - { - Charset.forName(charset); - } - catch (UnsupportedCharsetException e) - { - throw new IOException("This charset is not supported", e); - } - charsetName = charset; - } + try { + Charset.forName(charset); + } + catch (UnsupportedCharsetException e) { + throw new IOException("This charset is not supported", e); + } + + charsetName = charset; + } - /** - * The currently used charset for filename encoding/decoding. - * - * @return The name of the charset (null if the platform's default charset is being used) - * @see #setCharset(String) - */ - public String getCharset() - { - return charsetName; - } + /** + * The currently used charset for filename encoding/decoding. + * + * @return The name of the charset (null if the platform's default charset is being used) + * @see #setCharset(String) + */ + public String getCharset() { + return charsetName; + } - public class LenNamePair - { - public long length; - String filename; - } + public class LenNamePair { + public long length; + String filename; + } - public SCPClient(Connection conn) - { - if (conn == null) - throw new IllegalArgumentException("Cannot accept null argument!"); - this.conn = conn; - } + public SCPClient(Connection conn) { + if (conn == null) + throw new IllegalArgumentException("Cannot accept null argument!"); - protected void readResponse(InputStream is) throws IOException - { - int c = is.read(); + this.conn = conn; + } + + protected void readResponse(InputStream is) throws IOException { + int c = is.read(); - if (c == 0) - return; + if (c == 0) + return; - if (c == -1) - throw new IOException("Remote scp terminated unexpectedly."); + if (c == -1) + throw new IOException("Remote scp terminated unexpectedly."); - if ((c != 1) && (c != 2)) - throw new IOException("Remote scp sent illegal error code."); + if ((c != 1) && (c != 2)) + throw new IOException("Remote scp sent illegal error code."); - if (c == 2) - throw new IOException("Remote scp terminated with error."); + if (c == 2) + throw new IOException("Remote scp terminated with error."); - String err = receiveLine(is); - throw new IOException("Remote scp terminated with error (" + err + ")."); - } + String err = receiveLine(is); + throw new IOException("Remote scp terminated with error (" + err + ")."); + } - protected String receiveLine(InputStream is) throws IOException - { - StringBuilder sb = new StringBuilder(30); + protected String receiveLine(InputStream is) throws IOException { + StringBuilder sb = new StringBuilder(30); - while (true) - { - /* This is a random limit - if your path names are longer, then adjust it */ + while (true) { + /* This is a random limit - if your path names are longer, then adjust it */ + if (sb.length() > 8192) + throw new IOException("Remote scp sent a too long line"); - if (sb.length() > 8192) - throw new IOException("Remote scp sent a too long line"); + int c = is.read(); - int c = is.read(); - - if (c < 0) - throw new IOException("Remote scp terminated unexpectedly."); + if (c < 0) + throw new IOException("Remote scp terminated unexpectedly."); - if (c == '\n') - break; + if (c == '\n') + break; - sb.append((char) c); + sb.append((char) c); + } - } - return sb.toString(); - } + return sb.toString(); + } - protected LenNamePair parseCLine(String line) throws IOException - { - /* Minimum line: "xxxx y z" ---> 8 chars */ + protected LenNamePair parseCLine(String line) throws IOException { + /* Minimum line: "xxxx y z" ---> 8 chars */ + if (line.length() < 8) + throw new IOException("Malformed C line sent by remote SCP binary, line too short."); - if (line.length() < 8) - throw new IOException("Malformed C line sent by remote SCP binary, line too short."); - - if ((line.charAt(4) != ' ') || (line.charAt(5) == ' ')) - throw new IOException("Malformed C line sent by remote SCP binary."); + if ((line.charAt(4) != ' ') || (line.charAt(5) == ' ')) + throw new IOException("Malformed C line sent by remote SCP binary."); - int length_name_sep = line.indexOf(' ', 5); + int length_name_sep = line.indexOf(' ', 5); - if (length_name_sep == -1) - throw new IOException("Malformed C line sent by remote SCP binary."); + if (length_name_sep == -1) + throw new IOException("Malformed C line sent by remote SCP binary."); - String length_substring = line.substring(5, length_name_sep); - String name_substring = line.substring(length_name_sep + 1); + String length_substring = line.substring(5, length_name_sep); + String name_substring = line.substring(length_name_sep + 1); - if ((length_substring.length() <= 0) || (name_substring.length() <= 0)) - throw new IOException("Malformed C line sent by remote SCP binary."); + if ((length_substring.length() <= 0) || (name_substring.length() <= 0)) + throw new IOException("Malformed C line sent by remote SCP binary."); - if ((6 + length_substring.length() + name_substring.length()) != line.length()) - throw new IOException("Malformed C line sent by remote SCP binary."); + if ((6 + length_substring.length() + name_substring.length()) != line.length()) + throw new IOException("Malformed C line sent by remote SCP binary."); + + final long len; - final long len; - try - { - len = Long.parseLong(length_substring); - } - catch (NumberFormatException e) - { - throw new IOException("Malformed C line sent by remote SCP binary, cannot parse file length."); - } + try { + len = Long.parseLong(length_substring); + } + catch (NumberFormatException e) { + throw new IOException("Malformed C line sent by remote SCP binary, cannot parse file length."); + } - if (len < 0) - throw new IOException("Malformed C line sent by remote SCP binary, illegal file length."); + if (len < 0) + throw new IOException("Malformed C line sent by remote SCP binary, illegal file length."); - LenNamePair lnp = new LenNamePair(); - lnp.length = len; - lnp.filename = name_substring; - - return lnp; - } + LenNamePair lnp = new LenNamePair(); + lnp.length = len; + lnp.filename = name_substring; + return lnp; + } - /** - * The session for opened for this SCP transfer must be closed using - * SCPOutputStream#close - * - * @param remoteFile - * @param length The size of the file to send - * @param remoteTargetDirectory - * @param mode - * @return - * @throws IOException - */ - public SCPOutputStream put(final String remoteFile, long length, String remoteTargetDirectory, String mode) - throws IOException - { - Session sess = null; + /** + * The session for opened for this SCP transfer must be closed using + * SCPOutputStream#close + * + * @param remoteFile + * @param length The size of the file to send + * @param remoteTargetDirectory + * @param mode + * @return + * @throws IOException + */ + public SCPOutputStream put(final String remoteFile, long length, String remoteTargetDirectory, String mode) + throws IOException { + Session sess = null; - if (null == remoteFile) - throw new IllegalArgumentException("Null argument."); - if (null == remoteTargetDirectory) - remoteTargetDirectory = ""; - if (null == mode) - mode = "0600"; - if (mode.length() != 4) - throw new IllegalArgumentException("Invalid mode."); + if (null == remoteFile) + throw new IllegalArgumentException("Null argument."); + + if (null == remoteTargetDirectory) + remoteTargetDirectory = ""; - for (int i = 0; i < mode.length(); i++) - if (Character.isDigit(mode.charAt(i)) == false) - throw new IllegalArgumentException("Invalid mode."); + if (null == mode) + mode = "0600"; - remoteTargetDirectory = (remoteTargetDirectory.length() > 0) ? remoteTargetDirectory : "."; + if (mode.length() != 4) + throw new IllegalArgumentException("Invalid mode."); - String cmd = "scp -t -d \"" + remoteTargetDirectory + "\""; + for (int i = 0; i < mode.length(); i++) + if (Character.isDigit(mode.charAt(i)) == false) + throw new IllegalArgumentException("Invalid mode."); - sess = conn.openSession(); - sess.execCommand(cmd, charsetName); - - return new SCPOutputStream(this, sess, remoteFile, length, mode); - } + remoteTargetDirectory = (remoteTargetDirectory.length() > 0) ? remoteTargetDirectory : "."; + String cmd = "scp -t -d \"" + remoteTargetDirectory + "\""; + sess = conn.openSession(); + sess.execCommand(cmd, charsetName); + return new SCPOutputStream(this, sess, remoteFile, length, mode); + } - /** - * The session for opened for this SCP transfer must be closed using - * SCPInputStream#close - * - * @param remoteFile - * @return - * @throws IOException - */ - public SCPInputStream get(final String remoteFile) throws IOException - { - Session sess = null; + /** + * The session for opened for this SCP transfer must be closed using + * SCPInputStream#close + * + * @param remoteFile + * @return + * @throws IOException + */ + public SCPInputStream get(final String remoteFile) throws IOException { + Session sess = null; - if (null == remoteFile) - throw new IllegalArgumentException("Null argument."); + if (null == remoteFile) + throw new IllegalArgumentException("Null argument."); - if (remoteFile.length() == 0) - throw new IllegalArgumentException("Cannot accept empty filename."); + if (remoteFile.length() == 0) + throw new IllegalArgumentException("Cannot accept empty filename."); - String cmd = "scp -f"; - cmd += (" \"" + remoteFile + "\""); - - sess = conn.openSession(); - sess.execCommand(cmd, charsetName); - - return new SCPInputStream(this, sess); - } + String cmd = "scp -f"; + cmd += (" \"" + remoteFile + "\""); + sess = conn.openSession(); + sess.execCommand(cmd, charsetName); + return new SCPInputStream(this, sess); + } private void sendBytes(Session sess, byte[] data, String fileName, String mode) throws IOException { OutputStream os = sess.getStdin(); InputStream is = new BufferedInputStream(sess.getStdout(), 512); diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/SCPInputStream.java --- a/src/ch/ethz/ssh2/SCPInputStream.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/SCPInputStream.java Wed Jul 30 14:16:58 2014 -0700 @@ -12,122 +12,101 @@ /** * @version $Id: SCPInputStream.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ */ -public class SCPInputStream extends BufferedInputStream -{ - private Session session; +public class SCPInputStream extends BufferedInputStream { + private Session session; - /** - * Bytes remaining to be read from the stream - */ - private long remaining; + /** + * Bytes remaining to be read from the stream + */ + private long remaining; - public SCPInputStream(SCPClient client, Session session) throws IOException - { - super(session.getStdout()); - - this.session = session; + public SCPInputStream(SCPClient client, Session session) throws IOException { + super(session.getStdout()); + this.session = session; + OutputStream os = new BufferedOutputStream(session.getStdin(), 512); + os.write(0x0); + os.flush(); + final SCPClient.LenNamePair lnp; - OutputStream os = new BufferedOutputStream(session.getStdin(), 512); + while (true) { + int c = session.getStdout().read(); - os.write(0x0); - os.flush(); - - final SCPClient.LenNamePair lnp; + if (c < 0) { + throw new IOException("Remote scp terminated unexpectedly."); + } - while (true) - { - int c = session.getStdout().read(); - if (c < 0) - { - throw new IOException("Remote scp terminated unexpectedly."); - } + String line = client.receiveLine(session.getStdout()); - String line = client.receiveLine(session.getStdout()); + if (c == 'T') { + /* Ignore modification times */ + continue; + } - if (c == 'T') - { - /* Ignore modification times */ - continue; - } + if ((c == 1) || (c == 2)) { + throw new IOException("Remote SCP error: " + line); + } - if ((c == 1) || (c == 2)) - { - throw new IOException("Remote SCP error: " + line); - } - - if (c == 'C') - { - lnp = client.parseCLine(line); - break; + if (c == 'C') { + lnp = client.parseCLine(line); + break; + } - } - throw new IOException("Remote SCP error: " + ((char) c) + line); - } + throw new IOException("Remote SCP error: " + ((char) c) + line); + } - os.write(0x0); - os.flush(); - - this.remaining = lnp.length; - } + os.write(0x0); + os.flush(); + this.remaining = lnp.length; + } - @Override - public int read() throws IOException - { - if (!(remaining > 0)) - { - return -1; - } + @Override + public int read() throws IOException { + if (!(remaining > 0)) { + return -1; + } + + int b = super.read(); + + if (b < 0) { + throw new IOException("Remote scp terminated connection unexpectedly"); + } - int b = super.read(); - if (b < 0) - { - throw new IOException("Remote scp terminated connection unexpectedly"); - } - - remaining -= 1; + remaining -= 1; + return b; + } - return b; - } + @Override + public int read(byte b[], int off, int len) throws IOException { + if (!(remaining > 0)) { + return -1; + } - @Override - public int read(byte b[], int off, int len) throws IOException - { - if (!(remaining > 0)) - { - return -1; - } + int trans = (int) remaining; - int trans = (int) remaining; - if (remaining > len) - { - trans = len; - } + if (remaining > len) { + trans = len; + } + + int read = super.read(b, off, trans); - int read = super.read(b, off, trans); - if (read < 0) - { - throw new IOException("Remote scp terminated connection unexpectedly"); - } + if (read < 0) { + throw new IOException("Remote scp terminated connection unexpectedly"); + } - remaining -= read; - - return read; - } + remaining -= read; + return read; + } - @Override - public void close() throws IOException - { - try - { - session.getStdin().write(0x0); - session.getStdin().flush(); - } - finally - { - if (session != null) - { - session.close(); - } - } - } + @Override + public void close() throws IOException { + try { + session.getStdin().write(0x0); + session.getStdin().flush(); + } + finally { + if (session != null) { + session.close(); + } + } + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/SCPOutputStream.java --- a/src/ch/ethz/ssh2/SCPOutputStream.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/SCPOutputStream.java Wed Jul 30 14:16:58 2014 -0700 @@ -14,48 +14,36 @@ /** * @version $Id: SCPOutputStream.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ */ -public class SCPOutputStream extends BufferedOutputStream -{ - - private Session session; - - private SCPClient scp; +public class SCPOutputStream extends BufferedOutputStream { - public SCPOutputStream(SCPClient client, Session session, final String remoteFile, long length, String mode) throws IOException - { - super(session.getStdin(), 40000); - this.session = session; - this.scp = client; + private Session session; - InputStream is = new BufferedInputStream(session.getStdout(), 512); - - scp.readResponse(is); - - String cline = "C" + mode + " " + length + " " + remoteFile + "\n"; - - super.write(StringEncoder.GetBytes(cline)); - this.flush(); + private SCPClient scp; - scp.readResponse(is); - } - - @Override - public void close() throws IOException - { - try - { - this.write(0); - this.flush(); + public SCPOutputStream(SCPClient client, Session session, final String remoteFile, long length, String mode) throws IOException { + super(session.getStdin(), 40000); + this.session = session; + this.scp = client; + InputStream is = new BufferedInputStream(session.getStdout(), 512); + scp.readResponse(is); + String cline = "C" + mode + " " + length + " " + remoteFile + "\n"; + super.write(StringEncoder.GetBytes(cline)); + this.flush(); + scp.readResponse(is); + } - scp.readResponse(session.getStdout()); - - this.write(StringEncoder.GetBytes("E\n")); - this.flush(); - } - finally - { - if (session != null) - session.close(); - } - } + @Override + public void close() throws IOException { + try { + this.write(0); + this.flush(); + scp.readResponse(session.getStdout()); + this.write(StringEncoder.GetBytes("E\n")); + this.flush(); + } + finally { + if (session != null) + session.close(); + } + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/SFTPException.java --- a/src/ch/ethz/ssh2/SFTPException.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/SFTPException.java Wed Jul 30 14:16:58 2014 -0700 @@ -11,83 +11,76 @@ /** * Used in combination with the SFTPv3Client. This exception wraps * error messages sent by the SFTP server. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class SFTPException extends IOException -{ - private static final long serialVersionUID = 578654644222421811L; +public class SFTPException extends IOException { + private static final long serialVersionUID = 578654644222421811L; - private final String sftpErrorMessage; - private final int sftpErrorCode; + private final String sftpErrorMessage; + private final int sftpErrorCode; - private static String constructMessage(String s, int errorCode) - { - String[] detail = ErrorCodes.getDescription(errorCode); + private static String constructMessage(String s, int errorCode) { + String[] detail = ErrorCodes.getDescription(errorCode); - if (detail == null) - return s + " (UNKNOWN SFTP ERROR CODE)"; + if (detail == null) + return s + " (UNKNOWN SFTP ERROR CODE)"; - return s + " (" + detail[0] + ": " + detail[1] + ")"; - } + return s + " (" + detail[0] + ": " + detail[1] + ")"; + } - SFTPException(String msg, int errorCode) - { - super(constructMessage(msg, errorCode)); - sftpErrorMessage = msg; - sftpErrorCode = errorCode; - } + SFTPException(String msg, int errorCode) { + super(constructMessage(msg, errorCode)); + sftpErrorMessage = msg; + sftpErrorCode = errorCode; + } - /** - * Get the error message sent by the server. Often, this - * message does not help a lot (e.g., "failure"). - * - * @return the plain string as sent by the server. - */ - public String getServerErrorMessage() - { - return sftpErrorMessage; - } + /** + * Get the error message sent by the server. Often, this + * message does not help a lot (e.g., "failure"). + * + * @return the plain string as sent by the server. + */ + public String getServerErrorMessage() { + return sftpErrorMessage; + } - /** - * Get the error code sent by the server. - * - * @return an error code as defined in the SFTP specs. - */ - public int getServerErrorCode() - { - return sftpErrorCode; - } + /** + * Get the error code sent by the server. + * + * @return an error code as defined in the SFTP specs. + */ + public int getServerErrorCode() { + return sftpErrorCode; + } - /** - * Get the symbolic name of the error code as given in the SFTP specs. - * - * @return e.g., "SSH_FX_INVALID_FILENAME". - */ - public String getServerErrorCodeSymbol() - { - String[] detail = ErrorCodes.getDescription(sftpErrorCode); + /** + * Get the symbolic name of the error code as given in the SFTP specs. + * + * @return e.g., "SSH_FX_INVALID_FILENAME". + */ + public String getServerErrorCodeSymbol() { + String[] detail = ErrorCodes.getDescription(sftpErrorCode); - if (detail == null) - return "UNKNOWN SFTP ERROR CODE " + sftpErrorCode; + if (detail == null) + return "UNKNOWN SFTP ERROR CODE " + sftpErrorCode; - return detail[0]; - } + return detail[0]; + } - /** - * Get the description of the error code as given in the SFTP specs. - * - * @return e.g., "The filename is not valid." - */ - public String getServerErrorCodeVerbose() - { - String[] detail = ErrorCodes.getDescription(sftpErrorCode); + /** + * Get the description of the error code as given in the SFTP specs. + * + * @return e.g., "The filename is not valid." + */ + public String getServerErrorCodeVerbose() { + String[] detail = ErrorCodes.getDescription(sftpErrorCode); - if (detail == null) - return "The error code " + sftpErrorCode + " is unknown."; + if (detail == null) + return "The error code " + sftpErrorCode + " is unknown."; - return detail[1]; - } + return detail[1]; + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/SFTPInputStream.java --- a/src/ch/ethz/ssh2/SFTPInputStream.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/SFTPInputStream.java Wed Jul 30 14:16:58 2014 -0700 @@ -34,9 +34,11 @@ @Override public int read(byte[] buffer, int offset, int len) throws IOException { int read = handle.getClient().read(handle, readOffset, buffer, offset, len); - if(read > 0) { + + if (read > 0) { readOffset += read; } + return read; } @@ -58,9 +60,11 @@ public int read() throws IOException { byte[] buffer = new byte[1]; int b = handle.getClient().read(handle, readOffset, buffer, 0, 1); - if(b > 0) { + + if (b > 0) { readOffset += 1; } + return b; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/SFTPOutputStream.java --- a/src/ch/ethz/ssh2/SFTPOutputStream.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/SFTPOutputStream.java Wed Jul 30 14:16:58 2014 -0700 @@ -40,7 +40,6 @@ // if len > 32768, then the write operation will // be split into multiple writes in SFTPv3Client#write. handle.getClient().write(handle, writeOffset, buffer, offset, len); - writeOffset += len; } @@ -49,7 +48,6 @@ byte[] buffer = new byte[1]; buffer[0] = (byte) b; handle.getClient().write(handle, writeOffset, buffer, 0, 1); - writeOffset += 1; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/SFTPv3Client.java --- a/src/ch/ethz/ssh2/SFTPv3Client.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/SFTPv3Client.java Wed Jul 30 14:16:58 2014 -0700 @@ -101,7 +101,6 @@ public void read(String packet) { log.debug("Read packet " + packet); } - public void write(String packet) { log.debug("Write packet " + packet); } @@ -121,29 +120,24 @@ public SFTPv3FileAttributes fstat(SFTPFileHandle handle) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(handle.getHandle(), 0, handle.getHandle().length); - sendMessage(Packet.SSH_FXP_FSTAT, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); - int rep_id = tr.readUINT32(); - if(rep_id != req_id) { + if (rep_id != req_id) { throw new RequestMismatchException(); } - if(t == Packet.SSH_FXP_ATTRS) { + if (t == Packet.SSH_FXP_ATTRS) { return new SFTPv3FileAttributes(tr); } - if(t != Packet.SSH_FXP_STATUS) { + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } @@ -155,29 +149,24 @@ private SFTPv3FileAttributes statBoth(String path, int statMethod) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(path, this.getCharset()); - sendMessage(statMethod, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); - int rep_id = tr.readUINT32(); - if(rep_id != req_id) { + if (rep_id != req_id) { throw new RequestMismatchException(); } - if(t == Packet.SSH_FXP_ATTRS) { + if (t == Packet.SSH_FXP_ATTRS) { return new SFTPv3FileAttributes(tr); } - if(t != Packet.SSH_FXP_STATUS) { + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } @@ -199,55 +188,56 @@ private List scanDirectory(byte[] handle) throws IOException { List files = new ArrayList(); - while(true) { + while (true) { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(handle, 0, handle.length); - sendMessage(Packet.SSH_FXP_READDIR, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); - int rep_id = tr.readUINT32(); - if(rep_id != req_id) { + if (rep_id != req_id) { throw new RequestMismatchException(); } - if(t == Packet.SSH_FXP_NAME) { + if (t == Packet.SSH_FXP_NAME) { int count = tr.readUINT32(); - if(log.isDebugEnabled()) { + + if (log.isDebugEnabled()) { log.debug(String.format("Parsing %d name entries", count)); } - while(count > 0) { + + while (count > 0) { SFTPv3DirectoryEntry file = new SFTPv3DirectoryEntry(); file.filename = tr.readString(this.getCharset()); file.longEntry = tr.readString(this.getCharset()); listener.read(file.longEntry); file.attributes = new SFTPv3FileAttributes(tr); - if(log.isDebugEnabled()) { + + if (log.isDebugEnabled()) { log.debug(String.format("Adding file %s", file)); } + files.add(file); count--; } + continue; } - if(t != Packet.SSH_FXP_STATUS) { + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } int errorCode = tr.readUINT32(); - if(errorCode == ErrorCodes.SSH_FX_EOF) { + if (errorCode == ErrorCodes.SSH_FX_EOF) { return files; } + String errorMessage = tr.readString(); listener.read(errorMessage); throw new SFTPException(errorMessage, errorCode); @@ -256,29 +246,24 @@ public final SFTPv3FileHandle openDirectory(String path) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(path, this.getCharset()); - sendMessage(Packet.SSH_FXP_OPENDIR, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); - int rep_id = tr.readUINT32(); - if(rep_id != req_id) { + if (rep_id != req_id) { throw new RequestMismatchException(); } - if(t == Packet.SSH_FXP_HANDLE) { + if (t == Packet.SSH_FXP_HANDLE) { return new SFTPv3FileHandle(this, tr.readByteString()); } - if(t != Packet.SSH_FXP_STATUS) { + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } @@ -405,32 +390,26 @@ @Override public SFTPv3FileHandle openFile(String filename, int flags, SFTPFileAttributes attr) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(filename, this.getCharset()); tw.writeUINT32(flags); - tw.writeBytes(attr.toBytes()); - sendMessage(Packet.SSH_FXP_OPEN, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); - int rep_id = tr.readUINT32(); - if(rep_id != req_id) { + if (rep_id != req_id) { throw new RequestMismatchException(); } - if(t == Packet.SSH_FXP_HANDLE) { + if (t == Packet.SSH_FXP_HANDLE) { return new SFTPv3FileHandle(this, tr.readByteString()); } - if(t != Packet.SSH_FXP_STATUS) { + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } @@ -443,15 +422,12 @@ @Override public void createSymlink(String src, String target) throws IOException { int req_id = generateNextRequestID(); - // Changed semantics of src and target. The bug is known on SFTP servers shipped with all // versions of OpenSSH (Bug #861). TypesWriter tw = new TypesWriter(); tw.writeString(target, this.getCharset()); tw.writeString(src, this.getCharset()); - sendMessage(Packet.SSH_FXP_SYMLINK, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/SFTPv3FileAttributes.java --- a/src/ch/ethz/ssh2/SFTPv3FileAttributes.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/SFTPv3FileAttributes.java Wed Jul 30 14:16:58 2014 -0700 @@ -89,9 +89,10 @@ * that this entry represents a directory. */ public boolean isDirectory() { - if(permissions == null) { + if (permissions == null) { return false; } + return ((permissions & 0040000) == 0040000); } @@ -102,9 +103,10 @@ * that this entry represents a regular file. */ public boolean isRegularFile() { - if(permissions == null) { + if (permissions == null) { return false; } + return ((permissions & 0100000) == 0100000); } @@ -115,9 +117,10 @@ * that this entry represents a symlink. */ public boolean isSymlink() { - if(permissions == null) { + if (permissions == null) { return false; } + return ((permissions & 0120000) == 0120000); } @@ -128,22 +131,20 @@ * @return NULL if permissions are not available. */ public String getOctalPermissions() { - if(permissions == null) { + if (permissions == null) { return null; } + String res = Integer.toString(permissions.intValue() & 0177777, 8); - StringBuilder sb = new StringBuilder(); - int leadingZeros = 7 - res.length(); - while(leadingZeros > 0) { + while (leadingZeros > 0) { sb.append('0'); leadingZeros--; } sb.append(res); - return sb.toString(); } @@ -179,25 +180,30 @@ */ public SFTPv3FileAttributes(final TypesReader tr) throws IOException { int flags = tr.readUINT32(); - if((flags & AttribFlags.SSH_FILEXFER_ATTR_SIZE) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SIZE) != 0) { this.size = tr.readUINT64(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_V3_UIDGID) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_V3_UIDGID) != 0) { this.uid = tr.readUINT32(); this.gid = tr.readUINT32(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { this.permissions = tr.readUINT32(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_V3_ACMODTIME) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_V3_ACMODTIME) != 0) { this.atime = tr.readUINT32(); this.mtime = tr.readUINT32(); + } - } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_EXTENDED) != 0) { + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_EXTENDED) != 0) { int count = tr.readUINT32(); + // Read it anyway to detect corrupt packets - while(count > 0) { + while (count > 0) { tr.readByteString(); tr.readByteString(); count--; @@ -215,36 +221,43 @@ public byte[] toBytes() { TypesWriter tw = new TypesWriter(); int attrFlags = 0; - if(this.size != null) { + + if (this.size != null) { attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_SIZE; } - if((this.uid != null) && (this.gid != null)) { + + if ((this.uid != null) && (this.gid != null)) { attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_V3_UIDGID; } - if(this.permissions != null) { + + if (this.permissions != null) { attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS; } - if((this.atime != null) && (this.mtime != null)) { + + if ((this.atime != null) && (this.mtime != null)) { attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_V3_ACMODTIME; } + tw.writeUINT32(attrFlags); - if(this.size != null) { + + if (this.size != null) { tw.writeUINT64(this.size); } - if((this.uid != null) && (this.gid != null)) { + if ((this.uid != null) && (this.gid != null)) { tw.writeUINT32(this.uid); tw.writeUINT32(this.gid); } - if(this.permissions != null) { + if (this.permissions != null) { tw.writeUINT32(this.permissions); } - if((this.atime != null) && (this.mtime != null)) { + if ((this.atime != null) && (this.mtime != null)) { tw.writeUINT32(this.atime); tw.writeUINT32(this.mtime); } + return tw.getBytes(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/SFTPv6Client.java --- a/src/ch/ethz/ssh2/SFTPv6Client.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/SFTPv6Client.java Wed Jul 30 14:16:58 2014 -0700 @@ -25,7 +25,6 @@ public void read(String packet) { log.debug("Read packet " + packet); } - public void write(String packet) { log.debug("Write packet " + packet); } @@ -39,29 +38,24 @@ public SFTPv6FileAttributes fstat(SFTPFileHandle handle) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(handle.getHandle(), 0, handle.getHandle().length); - sendMessage(Packet.SSH_FXP_FSTAT, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); - int rep_id = tr.readUINT32(); - if(rep_id != req_id) { + if (rep_id != req_id) { throw new RequestMismatchException(); } - if(t == Packet.SSH_FXP_ATTRS) { + if (t == Packet.SSH_FXP_ATTRS) { return new SFTPv6FileAttributes(tr); } - if(t != Packet.SSH_FXP_STATUS) { + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } @@ -73,29 +67,24 @@ private SFTPv6FileAttributes statBoth(String path, int statMethod) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(path, this.getCharset()); - sendMessage(statMethod, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); - int rep_id = tr.readUINT32(); - if(rep_id != req_id) { + if (rep_id != req_id) { throw new RequestMismatchException(); } - if(t == Packet.SSH_FXP_ATTRS) { + if (t == Packet.SSH_FXP_ATTRS) { return new SFTPv6FileAttributes(tr); } - if(t != Packet.SSH_FXP_STATUS) { + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } @@ -117,49 +106,55 @@ private List scanDirectory(byte[] handle) throws IOException { List files = new ArrayList(); - while(true) { + while (true) { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(handle, 0, handle.length); - sendMessage(Packet.SSH_FXP_READDIR, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); int rep_id = tr.readUINT32(); - if(rep_id != req_id) { + + if (rep_id != req_id) { throw new RequestMismatchException(); } - if(t == Packet.SSH_FXP_NAME) { + + if (t == Packet.SSH_FXP_NAME) { int count = tr.readUINT32(); - if(log.isDebugEnabled()) { + + if (log.isDebugEnabled()) { log.debug(String.format("Parsing %d name entries", count)); } - while(count > 0) { + + while (count > 0) { SFTPv6DirectoryEntry file = new SFTPv6DirectoryEntry(); file.filename = tr.readString(this.getCharset()); listener.read(file.filename); file.attributes = new SFTPv6FileAttributes(tr); - if(log.isDebugEnabled()) { + + if (log.isDebugEnabled()) { log.debug(String.format("Adding file %s", file)); } + files.add(file); count--; } + continue; } - if(t != Packet.SSH_FXP_STATUS) { + + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } + int errorCode = tr.readUINT32(); - if(errorCode == ErrorCodes.SSH_FX_EOF) { + + if (errorCode == ErrorCodes.SSH_FX_EOF) { return files; } + String errorMessage = tr.readString(); listener.read(errorMessage); throw new SFTPException(errorMessage, errorCode); @@ -168,29 +163,24 @@ public final SFTPFileHandle openDirectory(String path) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(path, this.getCharset()); - sendMessage(Packet.SSH_FXP_OPENDIR, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); - int rep_id = tr.readUINT32(); - if(rep_id != req_id) { + if (rep_id != req_id) { throw new RequestMismatchException(); } - if(t == Packet.SSH_FXP_HANDLE) { + if (t == Packet.SSH_FXP_HANDLE) { return new SFTPFileHandle(this, tr.readByteString()); } - if(t != Packet.SSH_FXP_STATUS) { + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } @@ -251,34 +241,28 @@ @Override public SFTPFileHandle openFile(String filename, int flags, SFTPFileAttributes attr) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); tw.writeString(filename, this.getCharset()); tw.writeUINT32(AceMask.ACE4_READ_DATA | AceMask.ACE4_READ_ATTRIBUTES | AceMask.ACE4_READ_ACL | AceMask.ACE4_READ_NAMED_ATTRS - | AceMask.ACE4_WRITE_DATA | AceMask.ACE4_APPEND_DATA | AceMask.ACE4_WRITE_ATTRIBUTES | AceMask.ACE4_WRITE_ACL | AceMask.ACE4_WRITE_NAMED_ATTRS); + | AceMask.ACE4_WRITE_DATA | AceMask.ACE4_APPEND_DATA | AceMask.ACE4_WRITE_ATTRIBUTES | AceMask.ACE4_WRITE_ACL | AceMask.ACE4_WRITE_NAMED_ATTRS); tw.writeUINT32(flags); - tw.writeBytes(attr.toBytes()); - sendMessage(Packet.SSH_FXP_OPEN, req_id, tw.getBytes()); - byte[] resp = receiveMessage(34000); - TypesReader tr = new TypesReader(resp); - int t = tr.readByte(); listener.read(Packet.forName(t)); + int rep_id = tr.readUINT32(); - int rep_id = tr.readUINT32(); - if(rep_id != req_id) { + if (rep_id != req_id) { throw new RequestMismatchException(); } - if(t == Packet.SSH_FXP_HANDLE) { + if (t == Packet.SSH_FXP_HANDLE) { return new SFTPFileHandle(this, tr.readByteString()); } - if(t != Packet.SSH_FXP_STATUS) { + if (t != Packet.SSH_FXP_STATUS) { throw new PacketTypeException(t); } @@ -291,32 +275,26 @@ @Override public void createSymlink(String src, String target) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); // new-link-path tw.writeString(src, this.getCharset()); // existing-path tw.writeString(target, this.getCharset()); tw.writeBoolean(true); - sendMessage(Packet.SSH_FXP_LINK, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); } @Override public void createHardlink(String src, String target) throws IOException { int req_id = generateNextRequestID(); - TypesWriter tw = new TypesWriter(); // new-link-path tw.writeString(src, this.getCharset()); // existing-path tw.writeString(target, this.getCharset()); tw.writeBoolean(false); - sendMessage(Packet.SSH_FXP_LINK, req_id, tw.getBytes()); - expectStatusOKMessage(req_id); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/SFTPv6FileAttributes.java --- a/src/ch/ethz/ssh2/SFTPv6FileAttributes.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/SFTPv6FileAttributes.java Wed Jul 30 14:16:58 2014 -0700 @@ -173,78 +173,98 @@ int flags = tr.readUINT32(); // The type field is always present this.type = tr.readByte(); - if((flags & AttribFlags.SSH_FILEXFER_ATTR_SIZE) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SIZE) != 0) { this.size = tr.readUINT64(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_ALLOCATION_SIZE) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_ALLOCATION_SIZE) != 0) { // Ignore tr.readUINT64(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_OWNERGROUP) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_OWNERGROUP) != 0) { this.owner = tr.readString(); this.group = tr.readString(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { this.permissions = tr.readUINT32(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_ACCESSTIME) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_ACCESSTIME) != 0) { this.atime = tr.readUINT64(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { // Ignore tr.readUINT32(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_CREATETIME) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_CREATETIME) != 0) { this.createtime = tr.readUINT64(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { // Ignore tr.readUINT32(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_MODIFYTIME) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_MODIFYTIME) != 0) { this.mtime = tr.readUINT64(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { // Ignore tr.readUINT32(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_CTIME) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_CTIME) != 0) { this.ctime = tr.readUINT64(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) { // Ignore tr.readUINT32(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_ACL) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_ACL) != 0) { // Ignore tr.readString(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_BITS) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_BITS) != 0) { // Ignore attrib-bits tr.readUINT32(); // Ignore attrib-bits-valid tr.readUINT32(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_TEXT_HINT) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_TEXT_HINT) != 0) { // Ignore tr.readByte(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_MIME_TYPE) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_MIME_TYPE) != 0) { // Ignore tr.readString(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_LINK_COUNT) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_LINK_COUNT) != 0) { // Ignore tr.readUINT32(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_UNTRANSLATED_NAME) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_UNTRANSLATED_NAME) != 0) { // Ignore tr.readString(); } - if((flags & AttribFlags.SSH_FILEXFER_ATTR_EXTENDED) != 0) { + + if ((flags & AttribFlags.SSH_FILEXFER_ATTR_EXTENDED) != 0) { int count = tr.readUINT32(); + // Read it anyway to detect corrupt packets - while(count > 0) { + while (count > 0) { // extension-name tr.readByteString(); // extension-data @@ -266,54 +286,70 @@ // The 'valid-attribute-flags' specifies which of the fields are present. Those fields // for which the corresponding flag is not set are not present int attrFlags = 0; - if(this.size != null) { + + if (this.size != null) { attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_SIZE; } - if((this.owner != null) && (this.group != null)) { + + if ((this.owner != null) && (this.group != null)) { // If either the owner or group field is zero length, the field should // be considered absent, and no change should be made to that specific // field during a modification operation. attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_OWNERGROUP; } - if(this.permissions != null) { + + if (this.permissions != null) { attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_PERMISSIONS; } - if(this.atime != null) { + + if (this.atime != null) { attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_ACCESSTIME; } - if(this.createtime != null) { + + if (this.createtime != null) { attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_CREATETIME; } - if(this.mtime != null) { + + if (this.mtime != null) { attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_MODIFYTIME; } - if(this.ctime != null) { + + if (this.ctime != null) { attrFlags = attrFlags | AttribFlags.SSH_FILEXFER_ATTR_CTIME; } + tw.writeUINT32(attrFlags); + // The type field is always present. - if(this.size != null) { + if (this.size != null) { tw.writeUINT64(this.size); } - if((this.owner != null) && (this.group != null)) { + + if ((this.owner != null) && (this.group != null)) { tw.writeString(owner); tw.writeString(group); } - if(this.permissions != null) { + + if (this.permissions != null) { tw.writeUINT32(this.permissions); } - if(this.atime != null) { + + if (this.atime != null) { tw.writeUINT64(this.atime); } - if(this.createtime != null) { + + if (this.createtime != null) { tw.writeUINT64(this.createtime); } - if(this.mtime != null) { + + if (this.mtime != null) { tw.writeUINT64(this.mtime); } - if(this.ctime != null) { + + if (this.ctime != null) { tw.writeUINT64(this.ctime); } + return tw.getBytes(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/ServerAuthenticationCallback.java --- a/src/ch/ethz/ssh2/ServerAuthenticationCallback.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/ServerAuthenticationCallback.java Wed Jul 30 14:16:58 2014 -0700 @@ -7,86 +7,85 @@ /** * A callback used during the authentication phase (see RFC 4252) when - * implementing a SSH server. - * + * implementing a SSH server. + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public interface ServerAuthenticationCallback -{ - /** - * The method name for host-based authentication. - */ - public final String METHOD_HOSTBASED = "hostbased"; +public interface ServerAuthenticationCallback { + /** + * The method name for host-based authentication. + */ + public final String METHOD_HOSTBASED = "hostbased"; - /** - * The method name for public-key authentication. - */ - public final String METHOD_PUBLICKEY = "publickey"; + /** + * The method name for public-key authentication. + */ + public final String METHOD_PUBLICKEY = "publickey"; - /** - * The method name for password authentication. - */ - public final String METHOD_PASSWORD = "password"; + /** + * The method name for password authentication. + */ + public final String METHOD_PASSWORD = "password"; - /** - * Called when the client enters authentication. - * This gives you the chance to set a custom authentication banner - * for this SSH-2 session. This is the first method called in this interface. - * It will only called at most once per ServerConnection. - * - * @param sc The corresponding ServerConnection - * @return The authentication banner or NULL in case no banner should be send. - */ - public String initAuthentication(ServerConnection sc); + /** + * Called when the client enters authentication. + * This gives you the chance to set a custom authentication banner + * for this SSH-2 session. This is the first method called in this interface. + * It will only called at most once per ServerConnection. + * + * @param sc The corresponding ServerConnection + * @return The authentication banner or NULL in case no banner should be send. + */ + public String initAuthentication(ServerConnection sc); - /** - * Return the authentication methods that are currently available to the client. - * Be prepared to return this information at any time during the authentication procedure. - *

- * The returned name-list of 'method names' (see RFC4252) indicate the authentication methods - * that may productively continue the authentication dialog. - *

- * It is RECOMMENDED that servers only include those 'method name' - * values in the name-list that are actually useful. However, it is not - * illegal to include 'method name' values that cannot be used to - * authenticate the user. - *

- * Already successfully completed authentications SHOULD NOT be included - * in the name-list, unless they should be performed again for some reason. - * - * @see #METHOD_HOSTBASED - * @see #METHOD_PASSWORD - * @see #METHOD_PUBLICKEY - * - * @param sc - * @return A list of method names. - */ - public String[] getRemainingAuthMethods(ServerConnection sc); + /** + * Return the authentication methods that are currently available to the client. + * Be prepared to return this information at any time during the authentication procedure. + *

+ * The returned name-list of 'method names' (see RFC4252) indicate the authentication methods + * that may productively continue the authentication dialog. + *

+ * It is RECOMMENDED that servers only include those 'method name' + * values in the name-list that are actually useful. However, it is not + * illegal to include 'method name' values that cannot be used to + * authenticate the user. + *

+ * Already successfully completed authentications SHOULD NOT be included + * in the name-list, unless they should be performed again for some reason. + * + * @see #METHOD_HOSTBASED + * @see #METHOD_PASSWORD + * @see #METHOD_PUBLICKEY + * + * @param sc + * @return A list of method names. + */ + public String[] getRemainingAuthMethods(ServerConnection sc); - /** - * Typically, this will be called be the client to get the list of - * authentication methods that can continue. You should simply return - * {@link AuthenticationResult#FAILURE}. - * - * @param sc - * @param username Name of the user that wants to log in with the "none" method. - * @return - */ - public AuthenticationResult authenticateWithNone(ServerConnection sc, String username); + /** + * Typically, this will be called be the client to get the list of + * authentication methods that can continue. You should simply return + * {@link AuthenticationResult#FAILURE}. + * + * @param sc + * @param username Name of the user that wants to log in with the "none" method. + * @return + */ + public AuthenticationResult authenticateWithNone(ServerConnection sc, String username); - public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password); + public AuthenticationResult authenticateWithPassword(ServerConnection sc, String username, String password); - /** - * NOTE: Not implemented yet. - * - * @param sc - * @param username - * @param algorithm - * @param publickey - * @param signature - * @return - */ - public AuthenticationResult authenticateWithPublicKey(ServerConnection sc, String username, String algorithm, - byte[] publickey, byte[] signature); + /** + * NOTE: Not implemented yet. + * + * @param sc + * @param username + * @param algorithm + * @param publickey + * @param signature + * @return + */ + public AuthenticationResult authenticateWithPublicKey(ServerConnection sc, String username, String algorithm, + byte[] publickey, byte[] signature); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/ServerConnection.java --- a/src/ch/ethz/ssh2/ServerConnection.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/ServerConnection.java Wed Jul 30 14:16:58 2014 -0700 @@ -29,30 +29,28 @@ * @author Christian * */ -public class ServerConnection -{ - /** - * The softwareversion presented to the SSH-2 client. - */ - private String softwareversion = String.format("Ganymed_SSHD_%s", Version.getSpecification()); +public class ServerConnection { + /** + * The softwareversion presented to the SSH-2 client. + */ + private String softwareversion = String.format("Ganymed_SSHD_%s", Version.getSpecification()); - private final ServerConnectionState state = new ServerConnectionState(this); + private final ServerConnectionState state = new ServerConnectionState(this); - /** - * Creates a new ServerConnection that will communicate - * with the client over the given Socket. - *

- * Note: you need to call {@link #connect()} or {@link #connect(int)} to - * perform the initial handshake and establish the encrypted communication. - * - * @see #connect(int) - * - * @param s The socket - */ - public ServerConnection(Socket s) - { - this(s, null, null, null); - } + /** + * Creates a new ServerConnection that will communicate + * with the client over the given Socket. + *

+ * Note: you need to call {@link #connect()} or {@link #connect(int)} to + * perform the initial handshake and establish the encrypted communication. + * + * @see #connect(int) + * + * @param s The socket + */ + public ServerConnection(Socket s) { + this(s, null, null, null); + } public ServerConnection(Socket s, String softwareversion) { this(s, null, null, null); @@ -60,340 +58,323 @@ } /** - * Creates a new ServerConnection that will communicate - * with the client over the given Socket. - *

- * Note: you need to call {@link #connect()} or {@link #connect(int)} to - * perform the initial handshake and establish the encrypted communication. - *

- * Please read the javadoc for the {@link #connect(int)} method. - * - * @see #connect(int) - * - * @param s The socket - * @param dsa_key The DSA hostkey, may be NULL - * @param rsa_key The RSA hostkey, may be NULL - * @param ec_key The EC hostkey, may be NULL - */ - public ServerConnection(Socket s, KeyPair dsa_key, KeyPair rsa_key, KeyPair ec_key) - { - state.s = s; - state.softwareversion = softwareversion; - state.next_dsa_key = dsa_key; - state.next_rsa_key = rsa_key; - state.next_ec_key = ec_key; - fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); - } + * Creates a new ServerConnection that will communicate + * with the client over the given Socket. + *

+ * Note: you need to call {@link #connect()} or {@link #connect(int)} to + * perform the initial handshake and establish the encrypted communication. + *

+ * Please read the javadoc for the {@link #connect(int)} method. + * + * @see #connect(int) + * + * @param s The socket + * @param dsa_key The DSA hostkey, may be NULL + * @param rsa_key The RSA hostkey, may be NULL + * @param ec_key The EC hostkey, may be NULL + */ + public ServerConnection(Socket s, KeyPair dsa_key, KeyPair rsa_key, KeyPair ec_key) { + state.s = s; + state.softwareversion = softwareversion; + state.next_dsa_key = dsa_key; + state.next_rsa_key = rsa_key; + state.next_ec_key = ec_key; + fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); + } - /** - * Establish the connection and block until the first handshake has completed. - *

- * Note: this is a wrapper that calls connect(0) (i.e., connect with no timeout). - *

- * Please read the javadoc for the {@link #connect(int)} method. - * - * @see #connect(int) - * - * @throws IOException - */ - public synchronized void connect() throws IOException - { - connect(0); - } + /** + * Establish the connection and block until the first handshake has completed. + *

+ * Note: this is a wrapper that calls connect(0) (i.e., connect with no timeout). + *

+ * Please read the javadoc for the {@link #connect(int)} method. + * + * @see #connect(int) + * + * @throws IOException + */ + + public synchronized void connect() throws IOException { + connect(0); + } - /** - * Establish the connection and block until the first handshake has completed. - *

- * Note 1: at least one DSA, RSA or EC hostkey must be set before calling this method. - *

- * Note 2: You must set the callbacks for authentication ({@link #setAuthenticationCallback(ServerAuthenticationCallback)}) - * and connection events ({@link #setServerConnectionCallback(ServerConnectionCallback)}). - * - * @see #setPEMHostKey(char[], String) - * @see #setPEMHostKey(File, String) - * @see #setRsaHostKey(RSAPrivateKey) - * @see #setDsaHostKey(DSAPrivateKey) - * - * @param timeout_milliseconds Timeout in milliseconds, 0 means no timeout. - * @throws IOException - */ - public synchronized void connect(int timeout_milliseconds) throws IOException - { - synchronized (state) - { - if (state.cb_conn == null) - throw new IllegalStateException("The callback for connection events has not been set."); + /** + * Establish the connection and block until the first handshake has completed. + *

+ * Note 1: at least one DSA, RSA or EC hostkey must be set before calling this method. + *

+ * Note 2: You must set the callbacks for authentication ({@link #setAuthenticationCallback(ServerAuthenticationCallback)}) + * and connection events ({@link #setServerConnectionCallback(ServerConnectionCallback)}). + * + * @see #setPEMHostKey(char[], String) + * @see #setPEMHostKey(File, String) + * @see #setRsaHostKey(RSAPrivateKey) + * @see #setDsaHostKey(DSAPrivateKey) + * + * @param timeout_milliseconds Timeout in milliseconds, 0 means no timeout. + * @throws IOException + */ - if (state.cb_auth == null) - throw new IllegalStateException("The callback for authentication events has not been set."); + public synchronized void connect(int timeout_milliseconds) throws IOException { + synchronized (state) { + if (state.cb_conn == null) + throw new IllegalStateException("The callback for connection events has not been set."); + + if (state.cb_auth == null) + throw new IllegalStateException("The callback for authentication events has not been set."); + + if (state.tm != null) + throw new IllegalStateException("The initial handshake has already been started."); + + if ((state.next_dsa_key == null) && (state.next_rsa_key == null) && (state.next_ec_key == null)) + throw new IllegalStateException("Neither an RSA nor a DSA nor an EC host key has been specified!"); - if (state.tm != null) - throw new IllegalStateException("The initial handshake has already been started."); - - if ((state.next_dsa_key == null) && (state.next_rsa_key == null) && (state.next_ec_key == null)) - throw new IllegalStateException("Neither an RSA nor a DSA nor an EC host key has been specified!"); + state.tm = new ServerTransportManager(state.s); + } - state.tm = new ServerTransportManager(state.s); - } - - state.tm.connect(state); - - /* Wait until first KEX has finished */ + state.tm.connect(state); + /* Wait until first KEX has finished */ + state.tm.getConnectionInfo(1); + } - state.tm.getConnectionInfo(1); - } + /** + * Retrieve the underlying socket. + * + * @return the socket that has been passed to the constructor. + */ + public Socket getSocket() { + return state.s; + } - /** - * Retrieve the underlying socket. - * - * @return the socket that has been passed to the constructor. - */ - public Socket getSocket() - { - return state.s; - } + /** + * Force an asynchronous key re-exchange (the call does not block). The + * latest values set for MAC, Cipher and DH group exchange parameters will + * be used. If a key exchange is currently in progress, then this method has + * the only effect that the so far specified parameters will be used for the + * next (client driven) key exchange. You may call this method only after + * the initial key exchange has been established. + *

+ * Note: This implementation will never start automatically a key exchange (other than the initial one) + * unless you or the connected SSH-2 client ask for it. + * + * @throws IOException + * In case of any failure behind the scenes. + */ - /** - * Force an asynchronous key re-exchange (the call does not block). The - * latest values set for MAC, Cipher and DH group exchange parameters will - * be used. If a key exchange is currently in progress, then this method has - * the only effect that the so far specified parameters will be used for the - * next (client driven) key exchange. You may call this method only after - * the initial key exchange has been established. - *

- * Note: This implementation will never start automatically a key exchange (other than the initial one) - * unless you or the connected SSH-2 client ask for it. - * - * @throws IOException - * In case of any failure behind the scenes. - */ - public synchronized void forceKeyExchange() throws IOException - { - synchronized (state) - { - if (state.tm == null) - throw new IllegalStateException( - "Cannot force another key exchange, you need to start the key exchange first."); + public synchronized void forceKeyExchange() throws IOException { + synchronized (state) { + if (state.tm == null) + throw new IllegalStateException( + "Cannot force another key exchange, you need to start the key exchange first."); + + state.tm.forceKeyExchange(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); + } + } + + /** + * Returns a {@link ConnectionInfo} object containing the details of + * the connection. May be called as soon as the first key exchange has been + * started. The method blocks in case the first key exchange has not been completed. + *

+ * Note: upon return of this method, authentication may still be pending. + * + * @return A {@link ConnectionInfo} object. + * @throws IOException + * In case of any failure behind the scenes; e.g., first key exchange was aborted. + */ - state.tm.forceKeyExchange(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); - } - } + public synchronized ConnectionInfo getConnectionInfo() throws IOException { + synchronized (state) { + if (state.tm == null) + throw new IllegalStateException( + "Cannot get details of connection, you need to start the key exchange first."); + } + + return state.tm.getConnectionInfo(1); + } - /** - * Returns a {@link ConnectionInfo} object containing the details of - * the connection. May be called as soon as the first key exchange has been - * started. The method blocks in case the first key exchange has not been completed. - *

- * Note: upon return of this method, authentication may still be pending. - * - * @return A {@link ConnectionInfo} object. - * @throws IOException - * In case of any failure behind the scenes; e.g., first key exchange was aborted. - */ - public synchronized ConnectionInfo getConnectionInfo() throws IOException - { - synchronized (state) - { - if (state.tm == null) - throw new IllegalStateException( - "Cannot get details of connection, you need to start the key exchange first."); - } + /** + * Change the current DSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with + * the client. + *

+ * Note: You can change an existing DSA hostkey after the initial kex exchange (the new value will + * be used during the next server initiated key exchange), but you cannot remove (i.e., set to null) the + * current DSA key, otherwise the next key exchange may fail in case the client supports only DSA hostkeys. + * + * @param dsa_hostkey + */ - return state.tm.getConnectionInfo(1); - } + public synchronized void setDsaHostKey(KeyPair dsa_hostkey) { + synchronized (state) { + if ((dsa_hostkey == null) && (state.next_dsa_key != null) && (state.tm != null)) + throw new IllegalStateException("Cannot remove DSA hostkey after first key exchange."); + + state.next_dsa_key = dsa_hostkey; + fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); + } + } - /** - * Change the current DSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with - * the client. - *

- * Note: You can change an existing DSA hostkey after the initial kex exchange (the new value will - * be used during the next server initiated key exchange), but you cannot remove (i.e., set to null) the - * current DSA key, otherwise the next key exchange may fail in case the client supports only DSA hostkeys. - * - * @param dsa_hostkey - */ - public synchronized void setDsaHostKey(KeyPair dsa_hostkey) - { - synchronized (state) - { - if ((dsa_hostkey == null) && (state.next_dsa_key != null) && (state.tm != null)) - throw new IllegalStateException("Cannot remove DSA hostkey after first key exchange."); + /** + * Change the current RSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with + * the client. + *

+ * Note: You can change an existing RSA hostkey after the initial kex exchange (the new value will + * be used during the next server initiated key exchange), but you cannot remove (i.e., set to null) the + * current RSA key, otherwise the next key exchange may fail in case the client supports only RSA hostkeys. + * + * @param rsa_hostkey + */ - state.next_dsa_key = dsa_hostkey; - fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); - } - } + public synchronized void setRsaHostKey(KeyPair rsa_hostkey) { + synchronized (state) { + if ((rsa_hostkey == null) && (state.next_rsa_key != null) && (state.tm != null)) + throw new IllegalStateException("Cannot remove RSA hostkey after first key exchange."); - /** - * Change the current RSA hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with - * the client. - *

- * Note: You can change an existing RSA hostkey after the initial kex exchange (the new value will - * be used during the next server initiated key exchange), but you cannot remove (i.e., set to null) the - * current RSA key, otherwise the next key exchange may fail in case the client supports only RSA hostkeys. - * - * @param rsa_hostkey - */ - public synchronized void setRsaHostKey(KeyPair rsa_hostkey) - { - synchronized (state) - { - if ((rsa_hostkey == null) && (state.next_rsa_key != null) && (state.tm != null)) - throw new IllegalStateException("Cannot remove RSA hostkey after first key exchange."); + state.next_rsa_key = rsa_hostkey; + fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); + } + } - state.next_rsa_key = rsa_hostkey; - fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); - } - } + /** + * Change the current EC hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with + * the client. + *

+ * Note: You can change an existing EC hostkey after the initial kex exchange (the new value will + * be used during the next server initiated key exchange), but you cannot remove (i.e., set to null) the + * current EC key, otherwise the next key exchange may fail in case the client supports only EC hostkeys. + * + * @param rsa_hostkey + */ + + public synchronized void setEcHostKey(KeyPair ec_hostkey) { + synchronized (state) { + if ((ec_hostkey == null) && (state.next_ec_key != null) && (state.tm != null)) + throw new IllegalStateException("Cannot remove EC hostkey after first key exchange."); - /** - * Change the current EC hostkey. Either a DSA or RSA or EC private key must be set for a successful handshake with - * the client. - *

- * Note: You can change an existing EC hostkey after the initial kex exchange (the new value will - * be used during the next server initiated key exchange), but you cannot remove (i.e., set to null) the - * current EC key, otherwise the next key exchange may fail in case the client supports only EC hostkeys. - * - * @param rsa_hostkey - */ - public synchronized void setEcHostKey(KeyPair ec_hostkey) - { - synchronized (state) - { - if ((ec_hostkey == null) && (state.next_ec_key != null) && (state.tm != null)) - throw new IllegalStateException("Cannot remove EC hostkey after first key exchange."); + state.next_ec_key = ec_hostkey; + fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); + } + } - state.next_ec_key = ec_hostkey; - fixCryptoWishList(state.next_cryptoWishList, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); - } - } - - /** - * Utility method that loads a PEM based hostkey (either RSA or DSA based) and - * calls either setRsaHostKey() or setDsaHostKey(). - * - * @param pemdata The PEM data - * @param password Password, may be null in case the PEM data is not password protected - * @throws IOException In case of any error. - */ - public void setPEMHostKey(char[] pemdata, String password) throws IOException - { - KeyPair pair = PEMDecoder.decode(pemdata, password); + /** + * Utility method that loads a PEM based hostkey (either RSA or DSA based) and + * calls either setRsaHostKey() or setDsaHostKey(). + * + * @param pemdata The PEM data + * @param password Password, may be null in case the PEM data is not password protected + * @throws IOException In case of any error. + */ + public void setPEMHostKey(char[] pemdata, String password) throws IOException { + KeyPair pair = PEMDecoder.decode(pemdata, password); PrivateKey key = pair.getPrivate(); - if (key instanceof DSAPrivateKey) setDsaHostKey(pair); + if (key instanceof DSAPrivateKey) setDsaHostKey(pair); - if (key instanceof RSAPrivateKey) setRsaHostKey(pair); + if (key instanceof RSAPrivateKey) setRsaHostKey(pair); if (key instanceof ECPrivateKey) setEcHostKey(pair); - } + } - /** - * Utility method that loads a hostkey from a PEM file (either RSA or DSA based) and - * calls either setRsaHostKey() or setDsaHostKey(). - * - * @param pemFile The PEM file - * @param password Password, may be null in case the PEM file is not password protected - * @throws IOException - */ - public void setPEMHostKey(File pemFile, String password) throws IOException - { - if (pemFile == null) - throw new IllegalArgumentException("pemfile argument is null"); + /** + * Utility method that loads a hostkey from a PEM file (either RSA or DSA based) and + * calls either setRsaHostKey() or setDsaHostKey(). + * + * @param pemFile The PEM file + * @param password Password, may be null in case the PEM file is not password protected + * @throws IOException + */ + public void setPEMHostKey(File pemFile, String password) throws IOException { + if (pemFile == null) + throw new IllegalArgumentException("pemfile argument is null"); - char[] buff = new char[256]; + char[] buff = new char[256]; + CharArrayWriter cw = new CharArrayWriter(); + FileReader fr = new FileReader(pemFile); - CharArrayWriter cw = new CharArrayWriter(); + while (true) { + int len = fr.read(buff); - FileReader fr = new FileReader(pemFile); + if (len < 0) + break; - while (true) - { - int len = fr.read(buff); - if (len < 0) - break; - cw.write(buff, 0, len); - } + cw.write(buff, 0, len); + } - fr.close(); + fr.close(); + setPEMHostKey(cw.toCharArray(), password); + } + + private void fixCryptoWishList(CryptoWishList next_cryptoWishList, KeyPair next_dsa_key, KeyPair next_rsa_key, KeyPair next_ec_key) { + List algos = new ArrayList(); + + if (next_ec_key != null) algos.add("ecdsa-sha2-nistp521"); - setPEMHostKey(cw.toCharArray(), password); - } + if (next_ec_key != null) algos.add("ecdsa-sha2-nistp384"); + + if (next_ec_key != null) algos.add("ecdsa-sha2-nistp256"); + + if (next_dsa_key != null) algos.add("ssh-dss"); - private void fixCryptoWishList(CryptoWishList next_cryptoWishList, KeyPair next_dsa_key, KeyPair next_rsa_key, KeyPair next_ec_key) - { - List algos = new ArrayList(); - if (next_ec_key != null) algos.add("ecdsa-sha2-nistp521"); - if (next_ec_key != null) algos.add("ecdsa-sha2-nistp384"); - if (next_ec_key != null) algos.add("ecdsa-sha2-nistp256"); - if (next_dsa_key != null) algos.add("ssh-dss"); - if (next_rsa_key != null) algos.add("ssh-rsa"); - next_cryptoWishList.serverHostKeyAlgorithms = new String[algos.size()]; + if (next_rsa_key != null) algos.add("ssh-rsa"); + + next_cryptoWishList.serverHostKeyAlgorithms = new String[algos.size()]; algos.toArray(next_cryptoWishList.serverHostKeyAlgorithms); - } + } - /** - * Callback interface with methods that will be called upon events - * generated by the client (e.g., client opens a new Session which results in a ServerSession). - *

- * Note: This must be set before the first handshake. - * - * @param cb The callback implementation - */ - public synchronized void setServerConnectionCallback(ServerConnectionCallback cb) - { - synchronized (state) - { - state.cb_conn = cb; - } - } + /** + * Callback interface with methods that will be called upon events + * generated by the client (e.g., client opens a new Session which results in a ServerSession). + *

+ * Note: This must be set before the first handshake. + * + * @param cb The callback implementation + */ - /** - * Callback interface with methods that will be called upon authentication events. - *

- * Note: This must be set before the first handshake. - * - * @param cb The callback implementation - */ - public synchronized void setAuthenticationCallback(ServerAuthenticationCallback cb) - { - synchronized (state) - { - state.cb_auth = cb; - } - } + public synchronized void setServerConnectionCallback(ServerConnectionCallback cb) { + synchronized (state) { + state.cb_conn = cb; + } + } + + /** + * Callback interface with methods that will be called upon authentication events. + *

+ * Note: This must be set before the first handshake. + * + * @param cb The callback implementation + */ + + public synchronized void setAuthenticationCallback(ServerAuthenticationCallback cb) { + synchronized (state) { + state.cb_auth = cb; + } + } - /** - * Close the connection to the SSH-2 server. All assigned sessions will be - * closed, too. Can be called at any time. Don't forget to call this once - * you don't need a connection anymore - otherwise the receiver thread may - * run forever. - */ - public void close() - { - synchronized (state) - { - if (state.cm != null) - state.cm.closeAllChannels(); + /** + * Close the connection to the SSH-2 server. All assigned sessions will be + * closed, too. Can be called at any time. Don't forget to call this once + * you don't need a connection anymore - otherwise the receiver thread may + * run forever. + */ + public void close() { + synchronized (state) { + if (state.cm != null) + state.cm.closeAllChannels(); - if (state.tm != null) - { - state.tm.close(); - } - } - } + if (state.tm != null) { + state.tm.close(); + } + } + } - public void close(IOException t) - { - synchronized (state) - { - if (state.cm != null) - state.cm.closeAllChannels(); + public void close(IOException t) { + synchronized (state) { + if (state.cm != null) + state.cm.closeAllChannels(); - if (state.tm != null) - { - state.tm.close(t); - } - } - } + if (state.tm != null) { + state.tm.close(t); + } + } + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/ServerConnectionCallback.java --- a/src/ch/ethz/ssh2/ServerConnectionCallback.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/ServerConnectionCallback.java Wed Jul 30 14:16:58 2014 -0700 @@ -4,7 +4,6 @@ */ package ch.ethz.ssh2; -public interface ServerConnectionCallback -{ - public ServerSessionCallback acceptSession(ServerSession session); +public interface ServerConnectionCallback { + public ServerSessionCallback acceptSession(ServerSession session); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/ServerHostKeyVerifier.java --- a/src/ch/ethz/ssh2/ServerHostKeyVerifier.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/ServerHostKeyVerifier.java Wed Jul 30 14:16:58 2014 -0700 @@ -7,28 +7,27 @@ /** * A callback interface used to implement a client specific method of checking * server host keys. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public interface ServerHostKeyVerifier -{ - /** - * The actual verifier method, it will be called by the key exchange code - * on EVERY key exchange - this can happen several times during the lifetime - * of a connection. - *

- * Note: SSH-2 servers are allowed to change their hostkey at ANY time. - * - * @param hostname the hostname used to create the {@link Connection} object - * @param port the remote TCP port - * @param serverHostKeyAlgorithm the public key algorithm (ssh-rsa or ssh-dss) - * @param serverHostKey the server's public key blob - * @return if the client wants to accept the server's host key - if not, the - * connection will be closed. - * @throws Exception Will be wrapped with an IOException, extended version of returning false =) - */ - public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) - throws Exception; +public interface ServerHostKeyVerifier { + /** + * The actual verifier method, it will be called by the key exchange code + * on EVERY key exchange - this can happen several times during the lifetime + * of a connection. + *

+ * Note: SSH-2 servers are allowed to change their hostkey at ANY time. + * + * @param hostname the hostname used to create the {@link Connection} object + * @param port the remote TCP port + * @param serverHostKeyAlgorithm the public key algorithm (ssh-rsa or ssh-dss) + * @param serverHostKey the server's public key blob + * @return if the client wants to accept the server's host key - if not, the + * connection will be closed. + * @throws Exception Will be wrapped with an IOException, extended version of returning false =) + */ + public boolean verifyServerHostKey(String hostname, int port, String serverHostKeyAlgorithm, byte[] serverHostKey) + throws Exception; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/ServerSession.java --- a/src/ch/ethz/ssh2/ServerSession.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/ServerSession.java Wed Jul 30 14:16:58 2014 -0700 @@ -9,19 +9,18 @@ /** * A ServerSession represents the server-side of a session channel. - * + * * @see Session - * + * * @author Christian * */ -public interface ServerSession -{ - public InputStream getStdout(); +public interface ServerSession { + public InputStream getStdout(); + + public InputStream getStderr(); - public InputStream getStderr(); + public OutputStream getStdin(); - public OutputStream getStdin(); - - public void close(); + public void close(); } \ No newline at end of file diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/ServerSessionCallback.java --- a/src/ch/ethz/ssh2/ServerSessionCallback.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/ServerSessionCallback.java Wed Jul 30 14:16:58 2014 -0700 @@ -26,42 +26,41 @@ *

* If you want to signal a fatal error, then please throw an IOException. Currently, this will * tear down the whole SSH connection. - * + * * @see ServerSession - * + * * @author Christian * */ -public interface ServerSessionCallback -{ - public Runnable requestPtyReq(ServerSession ss, PtySettings pty) throws IOException; +public interface ServerSessionCallback { + public Runnable requestPtyReq(ServerSession ss, PtySettings pty) throws IOException; - public Runnable requestEnv(ServerSession ss, String name, String value) throws IOException; + public Runnable requestEnv(ServerSession ss, String name, String value) throws IOException; - public Runnable requestShell(ServerSession ss) throws IOException; + public Runnable requestShell(ServerSession ss) throws IOException; - public Runnable requestExec(ServerSession ss, String command) throws IOException; + public Runnable requestExec(ServerSession ss, String command) throws IOException; - public Runnable requestSubsystem(ServerSession ss, String subsystem) throws IOException; + public Runnable requestSubsystem(ServerSession ss, String subsystem) throws IOException; - /** - * When the window (terminal) size changes on the client side, it MAY send a message to the other side to inform it of the new dimensions. - * - * @param ss the corresponding session - * @param term_width_columns - * @param term_height_rows - * @param term_width_pixels - */ - public void requestWindowChange(ServerSession ss, int term_width_columns, int term_height_rows, - int term_width_pixels, int term_height_pixels) throws IOException; + /** + * When the window (terminal) size changes on the client side, it MAY send a message to the other side to inform it of the new dimensions. + * + * @param ss the corresponding session + * @param term_width_columns + * @param term_height_rows + * @param term_width_pixels + */ + public void requestWindowChange(ServerSession ss, int term_width_columns, int term_height_rows, + int term_width_pixels, int term_height_pixels) throws IOException; - /** - * A signal can be delivered to the remote process/service. Some systems may not implement signals, in which case they SHOULD ignore this message. - * - * @param ss the corresponding session - * @param signal (a string without the "SIG" prefix) - * @return - * @throws IOException - */ + /** + * A signal can be delivered to the remote process/service. Some systems may not implement signals, in which case they SHOULD ignore this message. + * + * @param ss the corresponding session + * @param signal (a string without the "SIG" prefix) + * @return + * @throws IOException + */ } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/Session.java --- a/src/ch/ethz/ssh2/Session.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/Session.java Wed Jul 30 14:16:58 2014 -0700 @@ -22,323 +22,296 @@ * @author Christian Plattner * @version $Id: Session.java 96 2014-04-08 15:14:37Z dkocher@sudo.ch $ */ -public class Session -{ - private ChannelManager cm; - private Channel cn; +public class Session { + private ChannelManager cm; + private Channel cn; - private boolean flag_pty_requested = false; - private boolean flag_x11_requested = false; - private boolean flag_execution_started = false; - private boolean flag_closed = false; + private boolean flag_pty_requested = false; + private boolean flag_x11_requested = false; + private boolean flag_execution_started = false; + private boolean flag_closed = false; - private String x11FakeCookie = null; + private String x11FakeCookie = null; - private final SecureRandom rnd; + private final SecureRandom rnd; - protected Session(ChannelManager cm, SecureRandom rnd) throws IOException - { - this.cm = cm; - this.cn = cm.openSessionChannel(); - this.rnd = rnd; - } + protected Session(ChannelManager cm, SecureRandom rnd) throws IOException { + this.cm = cm; + this.cn = cm.openSessionChannel(); + this.rnd = rnd; + } - /** - * Basically just a wrapper for lazy people - identical to calling - * requestPTY("dumb", 0, 0, 0, 0, null). - * - * @throws IOException - */ - public void requestDumbPTY() throws IOException - { - requestPTY("dumb", 0, 0, 0, 0, null); - } + /** + * Basically just a wrapper for lazy people - identical to calling + * requestPTY("dumb", 0, 0, 0, 0, null). + * + * @throws IOException + */ + public void requestDumbPTY() throws IOException { + requestPTY("dumb", 0, 0, 0, 0, null); + } - /** - * Basically just another wrapper for lazy people - identical to calling - * requestPTY(term, 0, 0, 0, 0, null). - * - * @throws IOException - */ - public void requestPTY(String term) throws IOException - { - requestPTY(term, 0, 0, 0, 0, null); - } + /** + * Basically just another wrapper for lazy people - identical to calling + * requestPTY(term, 0, 0, 0, 0, null). + * + * @throws IOException + */ + public void requestPTY(String term) throws IOException { + requestPTY(term, 0, 0, 0, 0, null); + } - /** - * Allocate a pseudo-terminal for this session. - *

- * This method may only be called before a program or shell is started in - * this session. - *

- * Different aspects can be specified: - *

- *

    - *
  • The TERM environment variable value (e.g., vt100)
  • - *
  • The terminal's dimensions.
  • - *
  • The encoded terminal modes.
  • - *
- * Zero dimension parameters are ignored. The character/row dimensions - * override the pixel dimensions (when nonzero). Pixel dimensions refer to - * the drawable area of the window. The dimension parameters are only - * informational. The encoding of terminal modes (parameter - * terminal_modes) is described in RFC4254. - * - * @param term The TERM environment variable value (e.g., vt100) - * @param term_width_characters terminal width, characters (e.g., 80) - * @param term_height_characters terminal height, rows (e.g., 24) - * @param term_width_pixels terminal width, pixels (e.g., 640) - * @param term_height_pixels terminal height, pixels (e.g., 480) - * @param terminal_modes encoded terminal modes (may be null) - * @throws IOException - */ - public void requestPTY(String term, int term_width_characters, int term_height_characters, int term_width_pixels, - int term_height_pixels, byte[] terminal_modes) throws IOException - { - if (term == null) - throw new IllegalArgumentException("TERM cannot be null."); + /** + * Allocate a pseudo-terminal for this session. + *

+ * This method may only be called before a program or shell is started in + * this session. + *

+ * Different aspects can be specified: + *

+ *

    + *
  • The TERM environment variable value (e.g., vt100)
  • + *
  • The terminal's dimensions.
  • + *
  • The encoded terminal modes.
  • + *
+ * Zero dimension parameters are ignored. The character/row dimensions + * override the pixel dimensions (when nonzero). Pixel dimensions refer to + * the drawable area of the window. The dimension parameters are only + * informational. The encoding of terminal modes (parameter + * terminal_modes) is described in RFC4254. + * + * @param term The TERM environment variable value (e.g., vt100) + * @param term_width_characters terminal width, characters (e.g., 80) + * @param term_height_characters terminal height, rows (e.g., 24) + * @param term_width_pixels terminal width, pixels (e.g., 640) + * @param term_height_pixels terminal height, pixels (e.g., 480) + * @param terminal_modes encoded terminal modes (may be null) + * @throws IOException + */ + public void requestPTY(String term, int term_width_characters, int term_height_characters, int term_width_pixels, + int term_height_pixels, byte[] terminal_modes) throws IOException { + if (term == null) + throw new IllegalArgumentException("TERM cannot be null."); - if ((terminal_modes != null) && (terminal_modes.length > 0)) - { - if (terminal_modes[terminal_modes.length - 1] != 0) - throw new IOException("Illegal terminal modes description, does not end in zero byte"); - } - else - terminal_modes = new byte[]{0}; + if ((terminal_modes != null) && (terminal_modes.length > 0)) { + if (terminal_modes[terminal_modes.length - 1] != 0) + throw new IOException("Illegal terminal modes description, does not end in zero byte"); + } + else + terminal_modes = new byte[] {0}; - synchronized (this) - { - /* The following is just a nicer error, we would catch it anyway later in the channel code */ - if (flag_closed) - throw new IOException("This session is closed."); + synchronized (this) { + /* The following is just a nicer error, we would catch it anyway later in the channel code */ + if (flag_closed) + throw new IOException("This session is closed."); - if (flag_pty_requested) - throw new IOException("A PTY was already requested."); + if (flag_pty_requested) + throw new IOException("A PTY was already requested."); - if (flag_execution_started) - throw new IOException( - "Cannot request PTY at this stage anymore, a remote execution has already started."); + if (flag_execution_started) + throw new IOException( + "Cannot request PTY at this stage anymore, a remote execution has already started."); - flag_pty_requested = true; - } + flag_pty_requested = true; + } - cm.requestPTY(cn, term, term_width_characters, term_height_characters, term_width_pixels, term_height_pixels, - terminal_modes); - } + cm.requestPTY(cn, term, term_width_characters, term_height_characters, term_width_pixels, term_height_pixels, + terminal_modes); + } /** * Tells the server that the size of the terminal has changed. * * See {@link #requestPTY(String, int, int, int, int, byte[])} for more details about how parameters are interpreted. - * - * @param term_width_characters - * terminal width, characters (e.g., 80) - * @param term_height_characters - * terminal height, rows (e.g., 24) - * @param term_width_pixels - * terminal width, pixels (e.g., 640) - * @param term_height_pixels - * terminal height, pixels (e.g., 480) - * @throws IOException - */ + * + * @param term_width_characters + * terminal width, characters (e.g., 80) + * @param term_height_characters + * terminal height, rows (e.g., 24) + * @param term_width_pixels + * terminal width, pixels (e.g., 640) + * @param term_height_pixels + * terminal height, pixels (e.g., 480) + * @throws IOException + */ public void resizePTY(int term_width_characters, int term_height_characters, int term_width_pixels, int term_height_pixels) throws IOException { requestWindowChange(term_width_characters, term_height_characters, term_width_pixels, term_height_pixels); } - public void requestWindowChange(int term_width_characters, int term_height_characters, int term_width_pixels, - int term_height_pixels) throws IOException - { - synchronized (this) - { - /* The following is just a nicer error, we would catch it anyway later in the channel code */ - if (flag_closed) - throw new IOException("This session is closed."); + public void requestWindowChange(int term_width_characters, int term_height_characters, int term_width_pixels, + int term_height_pixels) throws IOException { + synchronized (this) { + /* The following is just a nicer error, we would catch it anyway later in the channel code */ + if (flag_closed) + throw new IOException("This session is closed."); - if (!flag_pty_requested) - throw new IOException("A PTY was not requested."); - } + if (!flag_pty_requested) + throw new IOException("A PTY was not requested."); + } - cm.requestWindowChange(cn, term_width_characters, term_height_characters, term_width_pixels, term_height_pixels); - } + cm.requestWindowChange(cn, term_width_characters, term_height_characters, term_width_pixels, term_height_pixels); + } - /** - * Request X11 forwarding for the current session. - *

- * You have to supply the name and port of your X-server. - *

- * This method may only be called before a program or shell is started in - * this session. - * - * @param hostname the hostname of the real (target) X11 server (e.g., 127.0.0.1) - * @param port the port of the real (target) X11 server (e.g., 6010) - * @param cookie if non-null, then present this cookie to the real X11 server - * @param singleConnection if true, then the server is instructed to only forward one single - * connection, no more connections shall be forwarded after first, or after the session - * channel has been closed - * @throws IOException - */ - public void requestX11Forwarding(String hostname, int port, byte[] cookie, boolean singleConnection) - throws IOException - { - if (hostname == null) - throw new IllegalArgumentException("hostname argument may not be null"); + /** + * Request X11 forwarding for the current session. + *

+ * You have to supply the name and port of your X-server. + *

+ * This method may only be called before a program or shell is started in + * this session. + * + * @param hostname the hostname of the real (target) X11 server (e.g., 127.0.0.1) + * @param port the port of the real (target) X11 server (e.g., 6010) + * @param cookie if non-null, then present this cookie to the real X11 server + * @param singleConnection if true, then the server is instructed to only forward one single + * connection, no more connections shall be forwarded after first, or after the session + * channel has been closed + * @throws IOException + */ + public void requestX11Forwarding(String hostname, int port, byte[] cookie, boolean singleConnection) + throws IOException { + if (hostname == null) + throw new IllegalArgumentException("hostname argument may not be null"); - synchronized (this) - { - /* The following is just a nicer error, we would catch it anyway later in the channel code */ - if (flag_closed) - throw new IOException("This session is closed."); - - if (flag_x11_requested) - throw new IOException("X11 forwarding was already requested."); + synchronized (this) { + /* The following is just a nicer error, we would catch it anyway later in the channel code */ + if (flag_closed) + throw new IOException("This session is closed."); - if (flag_execution_started) - throw new IOException( - "Cannot request X11 forwarding at this stage anymore, a remote execution has already started."); + if (flag_x11_requested) + throw new IOException("X11 forwarding was already requested."); - flag_x11_requested = true; - } + if (flag_execution_started) + throw new IOException( + "Cannot request X11 forwarding at this stage anymore, a remote execution has already started."); - /* X11ServerData - used to store data about the target X11 server */ - - X11ServerData x11data = new X11ServerData(); + flag_x11_requested = true; + } - x11data.hostname = hostname; - x11data.port = port; - x11data.x11_magic_cookie = cookie; /* if non-null, then present this cookie to the real X11 server */ + /* X11ServerData - used to store data about the target X11 server */ + X11ServerData x11data = new X11ServerData(); + x11data.hostname = hostname; + x11data.port = port; + x11data.x11_magic_cookie = cookie; /* if non-null, then present this cookie to the real X11 server */ + /* Generate fake cookie - this one is used between remote clients and the ganymed proxy */ + byte[] fakeCookie = new byte[16]; + String hexEncodedFakeCookie; - /* Generate fake cookie - this one is used between remote clients and the ganymed proxy */ - - byte[] fakeCookie = new byte[16]; - String hexEncodedFakeCookie; - - /* Make sure that this fake cookie is unique for this connection */ + /* Make sure that this fake cookie is unique for this connection */ - while (true) - { - rnd.nextBytes(fakeCookie); + while (true) { + rnd.nextBytes(fakeCookie); + /* Generate also hex representation of fake cookie */ + StringBuilder tmp = new StringBuilder(32); - /* Generate also hex representation of fake cookie */ + for (int i = 0; i < fakeCookie.length; i++) { + String digit2 = Integer.toHexString(fakeCookie[i] & 0xff); + tmp.append((digit2.length() == 2) ? digit2 : "0" + digit2); + } + + hexEncodedFakeCookie = tmp.toString(); - StringBuilder tmp = new StringBuilder(32); - for (int i = 0; i < fakeCookie.length; i++) - { - String digit2 = Integer.toHexString(fakeCookie[i] & 0xff); - tmp.append((digit2.length() == 2) ? digit2 : "0" + digit2); - } - hexEncodedFakeCookie = tmp.toString(); + /* Well, yes, chances are low, but we want to be on the safe side */ - /* Well, yes, chances are low, but we want to be on the safe side */ + if (cm.checkX11Cookie(hexEncodedFakeCookie) == null) + break; + } - if (cm.checkX11Cookie(hexEncodedFakeCookie) == null) - break; - } + /* Ask for X11 forwarding */ + cm.requestX11(cn, singleConnection, "MIT-MAGIC-COOKIE-1", hexEncodedFakeCookie, 0); - /* Ask for X11 forwarding */ - - cm.requestX11(cn, singleConnection, "MIT-MAGIC-COOKIE-1", hexEncodedFakeCookie, 0); - - /* OK, that went fine, get ready to accept X11 connections... */ - /* ... but only if the user has not called close() in the meantime =) */ + /* OK, that went fine, get ready to accept X11 connections... */ + /* ... but only if the user has not called close() in the meantime =) */ - synchronized (this) - { - if (flag_closed == false) - { - this.x11FakeCookie = hexEncodedFakeCookie; - cm.registerX11Cookie(hexEncodedFakeCookie, x11data); - } - } + synchronized (this) { + if (flag_closed == false) { + this.x11FakeCookie = hexEncodedFakeCookie; + cm.registerX11Cookie(hexEncodedFakeCookie, x11data); + } + } + + /* Now it is safe to start remote X11 programs */ + } - /* Now it is safe to start remote X11 programs */ - } - - /** - * Execute a command on the remote machine. - * - * @param cmd The command to execute on the remote host. - * @throws IOException - */ - public void execCommand(String cmd) throws IOException - { - this.execCommand(cmd, null); - } + /** + * Execute a command on the remote machine. + * + * @param cmd The command to execute on the remote host. + * @throws IOException + */ + public void execCommand(String cmd) throws IOException { + this.execCommand(cmd, null); + } - /** - * Execute a command on the remote machine. - * - * @param cmd The command to execute on the remote host. - * @param charsetName The charset used to convert between Java Unicode Strings and byte encodings - * @throws IOException - */ - public void execCommand(String cmd, String charsetName) throws IOException - { - if (cmd == null) - throw new IllegalArgumentException("cmd argument may not be null"); + /** + * Execute a command on the remote machine. + * + * @param cmd The command to execute on the remote host. + * @param charsetName The charset used to convert between Java Unicode Strings and byte encodings + * @throws IOException + */ + public void execCommand(String cmd, String charsetName) throws IOException { + if (cmd == null) + throw new IllegalArgumentException("cmd argument may not be null"); - synchronized (this) - { - /* The following is just a nicer error, we would catch it anyway later in the channel code */ - if (flag_closed) - throw new IOException("This session is closed."); + synchronized (this) { + /* The following is just a nicer error, we would catch it anyway later in the channel code */ + if (flag_closed) + throw new IOException("This session is closed."); - if (flag_execution_started) - throw new IOException("A remote execution has already started."); + if (flag_execution_started) + throw new IOException("A remote execution has already started."); - flag_execution_started = true; - } + flag_execution_started = true; + } + + cm.requestExecCommand(cn, cmd, charsetName); + } - cm.requestExecCommand(cn, cmd, charsetName); - } + /** + * Start a shell on the remote machine. + * + * @throws IOException + */ + public void startShell() throws IOException { + synchronized (this) { + /* The following is just a nicer error, we would catch it anyway later in the channel code */ + if (flag_closed) + throw new IOException("This session is closed."); - /** - * Start a shell on the remote machine. - * - * @throws IOException - */ - public void startShell() throws IOException - { - synchronized (this) - { - /* The following is just a nicer error, we would catch it anyway later in the channel code */ - if (flag_closed) - throw new IOException("This session is closed."); + if (flag_execution_started) + throw new IOException("A remote execution has already started."); - if (flag_execution_started) - throw new IOException("A remote execution has already started."); + flag_execution_started = true; + } - flag_execution_started = true; - } - - cm.requestShell(cn); - } + cm.requestShell(cn); + } - /** - * Start a subsystem on the remote machine. - * Unless you know what you are doing, you will never need this. - * - * @param name the name of the subsystem. - * @throws IOException - */ - public void startSubSystem(String name) throws IOException - { - if (name == null) - throw new IllegalArgumentException("name argument may not be null"); + /** + * Start a subsystem on the remote machine. + * Unless you know what you are doing, you will never need this. + * + * @param name the name of the subsystem. + * @throws IOException + */ + public void startSubSystem(String name) throws IOException { + if (name == null) + throw new IllegalArgumentException("name argument may not be null"); - synchronized (this) - { - /* The following is just a nicer error, we would catch it anyway later in the channel code */ - if (flag_closed) - throw new IOException("This session is closed."); + synchronized (this) { + /* The following is just a nicer error, we would catch it anyway later in the channel code */ + if (flag_closed) + throw new IOException("This session is closed."); - if (flag_execution_started) - throw new IOException("A remote execution has already started."); + if (flag_execution_started) + throw new IOException("A remote execution has already started."); - flag_execution_started = true; - } + flag_execution_started = true; + } - cm.requestSubSystem(cn, name); - } + cm.requestSubSystem(cn, name); + } /** * Request authentication agent forwarding. @@ -360,155 +333,144 @@ cm.requestChannelAgentForwarding(cn, agent); } - public int getState() - { - return cn.getState(); - } + public int getState() { + return cn.getState(); + } - public InputStream getStdout() - { - return cn.getStdoutStream(); - } + public InputStream getStdout() { + return cn.getStdoutStream(); + } - public InputStream getStderr() - { - return cn.getStderrStream(); - } + public InputStream getStderr() { + return cn.getStderrStream(); + } - public OutputStream getStdin() - { - return cn.getStdinStream(); - } + public OutputStream getStdin() { + return cn.getStdinStream(); + } - /** - * This method blocks until there is more data available on either the - * stdout or stderr InputStream of this Session. Very useful - * if you do not want to use two parallel threads for reading from the two - * InputStreams. One can also specify a timeout. NOTE: do NOT call this - * method if you use concurrent threads that operate on either of the two - * InputStreams of this Session (otherwise this method may - * block, even though more data is available). - * - * @param timeout The (non-negative) timeout in ms. 0 means no - * timeout, the call may block forever. - * @return

    - *
  • 0 if no more data will arrive.
  • - *
  • 1 if more data is available.
  • - *
  • -1 if a timeout occurred.
  • - *
- * @throws IOException - * @deprecated This method has been replaced with a much more powerful wait-for-condition - * interface and therefore acts only as a wrapper. - */ - public int waitUntilDataAvailable(long timeout) throws IOException - { - if (timeout < 0) - throw new IllegalArgumentException("timeout must not be negative!"); + /** + * This method blocks until there is more data available on either the + * stdout or stderr InputStream of this Session. Very useful + * if you do not want to use two parallel threads for reading from the two + * InputStreams. One can also specify a timeout. NOTE: do NOT call this + * method if you use concurrent threads that operate on either of the two + * InputStreams of this Session (otherwise this method may + * block, even though more data is available). + * + * @param timeout The (non-negative) timeout in ms. 0 means no + * timeout, the call may block forever. + * @return
    + *
  • 0 if no more data will arrive.
  • + *
  • 1 if more data is available.
  • + *
  • -1 if a timeout occurred.
  • + *
+ * @throws IOException + * @deprecated This method has been replaced with a much more powerful wait-for-condition + * interface and therefore acts only as a wrapper. + */ + public int waitUntilDataAvailable(long timeout) throws IOException { + if (timeout < 0) + throw new IllegalArgumentException("timeout must not be negative!"); - int conditions = cm.waitForCondition(cn, timeout, ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA - | ChannelCondition.EOF); + int conditions = cm.waitForCondition(cn, timeout, ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA + | ChannelCondition.EOF); - if ((conditions & ChannelCondition.TIMEOUT) != 0) - return -1; + if ((conditions & ChannelCondition.TIMEOUT) != 0) + return -1; - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) != 0) - return 1; + if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) != 0) + return 1; - /* Here we do not need to check separately for CLOSED, since CLOSED implies EOF */ + /* Here we do not need to check separately for CLOSED, since CLOSED implies EOF */ - if ((conditions & ChannelCondition.EOF) != 0) - return 0; + if ((conditions & ChannelCondition.EOF) != 0) + return 0; - throw new IllegalStateException("Unexpected condition result (" + conditions + ")"); - } + throw new IllegalStateException("Unexpected condition result (" + conditions + ")"); + } - /** - * This method blocks until certain conditions hold true on the underlying SSH-2 channel. - *

- * This method returns as soon as one of the following happens: - *

    - *
  • at least of the specified conditions (see {@link ChannelCondition}) holds true
  • - *
  • timeout > 0 and a timeout occured (TIMEOUT will be set in result conditions) - *
  • the underlying channel was closed (CLOSED will be set in result conditions) - *
- *

- * In any case, the result value contains ALL current conditions, which may be more - * than the specified condition set (i.e., never use the "==" operator to test for conditions - * in the bitmask, see also comments in {@link ChannelCondition}). - *

- * Note: do NOT call this method if you want to wait for STDOUT_DATA or STDERR_DATA and - * there are concurrent threads (e.g., StreamGobblers) that operate on either of the two - * InputStreams of this Session (otherwise this method may - * block, even though more data is available in the StreamGobblers). - * - * @param condition_set a bitmask based on {@link ChannelCondition} values - * @param timeout non-negative timeout in ms, 0 means no timeout - * @return all bitmask specifying all current conditions that are true - */ + /** + * This method blocks until certain conditions hold true on the underlying SSH-2 channel. + *

+ * This method returns as soon as one of the following happens: + *

    + *
  • at least of the specified conditions (see {@link ChannelCondition}) holds true
  • + *
  • timeout > 0 and a timeout occured (TIMEOUT will be set in result conditions) + *
  • the underlying channel was closed (CLOSED will be set in result conditions) + *
+ *

+ * In any case, the result value contains ALL current conditions, which may be more + * than the specified condition set (i.e., never use the "==" operator to test for conditions + * in the bitmask, see also comments in {@link ChannelCondition}). + *

+ * Note: do NOT call this method if you want to wait for STDOUT_DATA or STDERR_DATA and + * there are concurrent threads (e.g., StreamGobblers) that operate on either of the two + * InputStreams of this Session (otherwise this method may + * block, even though more data is available in the StreamGobblers). + * + * @param condition_set a bitmask based on {@link ChannelCondition} values + * @param timeout non-negative timeout in ms, 0 means no timeout + * @return all bitmask specifying all current conditions that are true + */ - public int waitForCondition(int condition_set, long timeout) throws IOException { - if (timeout < 0) - throw new IllegalArgumentException("timeout must be non-negative!"); - - return cm.waitForCondition(cn, timeout, condition_set); - } + public int waitForCondition(int condition_set, long timeout) throws IOException { + if (timeout < 0) + throw new IllegalArgumentException("timeout must be non-negative!"); - /** - * Get the exit code/status from the remote command - if available. Be - * careful - not all server implementations return this value. It is - * generally a good idea to call this method only when all data from the - * remote side has been consumed (see also the method). - * - * @return An Integer holding the exit code, or - * null if no exit code is (yet) available. - */ - public Integer getExitStatus() - { - return cn.getExitStatus(); - } + return cm.waitForCondition(cn, timeout, condition_set); + } - /** - * Get the name of the signal by which the process on the remote side was - * stopped - if available and applicable. Be careful - not all server - * implementations return this value. - * - * @return An String holding the name of the signal, or - * null if the process exited normally or is still - * running (or if the server forgot to send this information). - */ - public String getExitSignal() - { - return cn.getExitSignal(); - } + /** + * Get the exit code/status from the remote command - if available. Be + * careful - not all server implementations return this value. It is + * generally a good idea to call this method only when all data from the + * remote side has been consumed (see also the method). + * + * @return An Integer holding the exit code, or + * null if no exit code is (yet) available. + */ + public Integer getExitStatus() { + return cn.getExitStatus(); + } + + /** + * Get the name of the signal by which the process on the remote side was + * stopped - if available and applicable. Be careful - not all server + * implementations return this value. + * + * @return An String holding the name of the signal, or + * null if the process exited normally or is still + * running (or if the server forgot to send this information). + */ + public String getExitSignal() { + return cn.getExitSignal(); + } - /** - * Close this session. NEVER forget to call this method to free up resources - - * even if you got an exception from one of the other methods (or when - * getting an Exception on the Input- or OutputStreams). Sometimes these other - * methods may throw an exception, saying that the underlying channel is - * closed (this can happen, e.g., if the other server sent a close message.) - * However, as long as you have not called the close() - * method, you may be wasting (local) resources. - */ - public void close() - { - synchronized (this) - { - if (flag_closed) - return; + /** + * Close this session. NEVER forget to call this method to free up resources - + * even if you got an exception from one of the other methods (or when + * getting an Exception on the Input- or OutputStreams). Sometimes these other + * methods may throw an exception, saying that the underlying channel is + * closed (this can happen, e.g., if the other server sent a close message.) + * However, as long as you have not called the close() + * method, you may be wasting (local) resources. + */ + public void close() { + synchronized (this) { + if (flag_closed) + return; - flag_closed = true; + flag_closed = true; - if (x11FakeCookie != null) - cm.unRegisterX11Cookie(x11FakeCookie, true); + if (x11FakeCookie != null) + cm.unRegisterX11Cookie(x11FakeCookie, true); - try - { - cm.closeChannel(cn, "Closed due to user request", true); - } - catch (IOException ignored) - { - } - } - } + try { + cm.closeChannel(cn, "Closed due to user request", true); + } + catch (IOException ignored) { + } + } + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/SimpleServerSessionCallback.java --- a/src/ch/ethz/ssh2/SimpleServerSessionCallback.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/SimpleServerSessionCallback.java Wed Jul 30 14:16:58 2014 -0700 @@ -14,49 +14,40 @@ * the {@link ServerSessionCallback} interface directly. This way * your code works also in case the interface gets extended in future * versions. - * + * * @author Christian * */ -public class SimpleServerSessionCallback implements ServerSessionCallback -{ - public Runnable requestShell(ServerSession ss) throws IOException - { - return null; - } +public class SimpleServerSessionCallback implements ServerSessionCallback { + public Runnable requestShell(ServerSession ss) throws IOException { + return null; + } - public Runnable requestExec(ServerSession ss, String command) throws IOException - { - return null; - } + public Runnable requestExec(ServerSession ss, String command) throws IOException { + return null; + } + + public Runnable requestSubsystem(ServerSession ss, String subsystem) throws IOException { + return null; + } - public Runnable requestSubsystem(ServerSession ss, String subsystem) throws IOException - { - return null; - } - - public Runnable requestPtyReq(ServerSession ss, PtySettings pty) throws IOException - { - return null; - } + public Runnable requestPtyReq(ServerSession ss, PtySettings pty) throws IOException { + return null; + } - /** - * By default, silently ignore passwd environment variables. - */ - public Runnable requestEnv(ServerSession ss, String name, String value) throws IOException - { - return new Runnable() - { - public void run() - { - /* Do nothing */ - } - }; - } + /** + * By default, silently ignore passwd environment variables. + */ + public Runnable requestEnv(ServerSession ss, String name, String value) throws IOException { + return new Runnable() { + public void run() { + /* Do nothing */ + } + }; + } - public void requestWindowChange(ServerSession ss, int term_width_columns, int term_height_rows, - int term_width_pixels, int term_height_pixels) throws IOException - { - } + public void requestWindowChange(ServerSession ss, int term_width_columns, int term_height_rows, + int term_width_pixels, int term_height_pixels) throws IOException { + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/StreamGobbler.java --- a/src/ch/ethz/ssh2/StreamGobbler.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/StreamGobbler.java Wed Jul 30 14:16:58 2014 -0700 @@ -36,201 +36,169 @@ * @version 2.50, 03/15/10 */ -public class StreamGobbler extends InputStream -{ - class GobblerThread extends Thread - { - @Override - public void run() - { - byte[] buff = new byte[8192]; +public class StreamGobbler extends InputStream { + class GobblerThread extends Thread { + @Override + public void run() { + byte[] buff = new byte[8192]; - while (true) - { - try - { - int avail = is.read(buff); + while (true) { + try { + int avail = is.read(buff); - synchronized (synchronizer) - { - if (avail <= 0) - { - isEOF = true; - synchronizer.notifyAll(); - break; - } + synchronized (synchronizer) { + if (avail <= 0) { + isEOF = true; + synchronizer.notifyAll(); + break; + } - int space_available = buffer.length - write_pos; + int space_available = buffer.length - write_pos; - if (space_available < avail) - { - /* compact/resize buffer */ - - int unread_size = write_pos - read_pos; - int need_space = unread_size + avail; - - byte[] new_buffer = buffer; + if (space_available < avail) { + /* compact/resize buffer */ + int unread_size = write_pos - read_pos; + int need_space = unread_size + avail; + byte[] new_buffer = buffer; - if (need_space > buffer.length) - { - int inc = need_space / 3; - inc = (inc < 256) ? 256 : inc; - inc = (inc > 8192) ? 8192 : inc; - new_buffer = new byte[need_space + inc]; - } + if (need_space > buffer.length) { + int inc = need_space / 3; + inc = (inc < 256) ? 256 : inc; + inc = (inc > 8192) ? 8192 : inc; + new_buffer = new byte[need_space + inc]; + } - if (unread_size > 0) - System.arraycopy(buffer, read_pos, new_buffer, 0, unread_size); - - buffer = new_buffer; + if (unread_size > 0) + System.arraycopy(buffer, read_pos, new_buffer, 0, unread_size); - read_pos = 0; - write_pos = unread_size; - } - - System.arraycopy(buff, 0, buffer, write_pos, avail); - write_pos += avail; + buffer = new_buffer; + read_pos = 0; + write_pos = unread_size; + } - synchronizer.notifyAll(); - } - } - catch (IOException e) - { - synchronized (synchronizer) - { - exception = e; - synchronizer.notifyAll(); - break; - } - } - } - } - } + System.arraycopy(buff, 0, buffer, write_pos, avail); + write_pos += avail; + synchronizer.notifyAll(); + } + } + catch (IOException e) { + synchronized (synchronizer) { + exception = e; + synchronizer.notifyAll(); + break; + } + } + } + } + } - private InputStream is; + private InputStream is; - private final Object synchronizer = new Object(); + private final Object synchronizer = new Object(); - private boolean isEOF = false; - private boolean isClosed = false; - private IOException exception = null; - - private byte[] buffer = new byte[2048]; - private int read_pos = 0; - private int write_pos = 0; + private boolean isEOF = false; + private boolean isClosed = false; + private IOException exception = null; - public StreamGobbler(InputStream is) - { - this.is = is; - GobblerThread t = new GobblerThread(); - t.setDaemon(true); - t.start(); - } + private byte[] buffer = new byte[2048]; + private int read_pos = 0; + private int write_pos = 0; - @Override - public int read() throws IOException - { - synchronized (synchronizer) - { + public StreamGobbler(InputStream is) { + this.is = is; + GobblerThread t = new GobblerThread(); + t.setDaemon(true); + t.start(); + } + + @Override + public int read() throws IOException { + synchronized (synchronizer) { if (isClosed) throw new IOException("This StreamGobbler is closed."); - while (read_pos == write_pos) - { + while (read_pos == write_pos) { if (exception != null) throw exception; if (isEOF) return -1; - try - { + try { synchronizer.wait(); } - catch (InterruptedException e) - { + catch (InterruptedException e) { throw new InterruptedIOException(); } } + return buffer[read_pos++] & 0xff; } } @Override - public int available() throws IOException - { - synchronized (synchronizer) - { - if (isClosed) - throw new IOException("This StreamGobbler is closed."); + public int available() throws IOException { + synchronized (synchronizer) { + if (isClosed) + throw new IOException("This StreamGobbler is closed."); - return write_pos - read_pos; - } - } + return write_pos - read_pos; + } + } - @Override - public int read(byte[] b) throws IOException - { - return read(b, 0, b.length); - } + @Override + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } - @Override - public void close() throws IOException - { - synchronized (synchronizer) - { - if (isClosed) - return; - isClosed = true; - isEOF = true; - synchronizer.notifyAll(); - is.close(); - } - } + @Override + public void close() throws IOException { + synchronized (synchronizer) { + if (isClosed) + return; - @Override - public int read(byte[] b, int off, int len) throws IOException - { - if (b == null) - throw new NullPointerException(); + isClosed = true; + isEOF = true; + synchronizer.notifyAll(); + is.close(); + } + } - if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) - throw new IndexOutOfBoundsException(); + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (b == null) + throw new NullPointerException(); + + if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) + throw new IndexOutOfBoundsException(); if (len == 0) return 0; - synchronized (synchronizer) - { + + synchronized (synchronizer) { if (isClosed) throw new IOException("This StreamGobbler is closed."); - while (read_pos == write_pos) - { + while (read_pos == write_pos) { if (exception != null) throw exception; if (isEOF) return -1; - try - { + try { synchronizer.wait(); } - catch (InterruptedException e) - { + catch (InterruptedException e) { throw new InterruptedIOException(); } } int avail = write_pos - read_pos; - avail = (avail > len) ? len : avail; - System.arraycopy(buffer, read_pos, b, off, avail); - read_pos += avail; - return avail; } - } + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/Version.java --- a/src/ch/ethz/ssh2/Version.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/Version.java Wed Jul 30 14:16:58 2014 -0700 @@ -5,26 +5,22 @@ * * @version $Id: Version.java 140 2014-04-15 13:16:25Z dkocher@sudo.ch $ */ -public class Version -{ - public static String getSpecification() - { - Package pkg = Version.class.getPackage(); +public class Version { + public static String getSpecification() { + Package pkg = Version.class.getPackage(); return (pkg == null) ? "SNAPSHOT" : pkg.getSpecificationVersion() == null ? "SNAPSHOT" : pkg.getSpecificationVersion(); } - public static String getImplementation() - { - Package pkg = Version.class.getPackage(); + public static String getImplementation() { + Package pkg = Version.class.getPackage(); return (pkg == null) ? "SNAPSHOT" : pkg.getImplementationVersion() == null ? "SNAPSHOT" : pkg.getImplementationVersion(); } - /** - * A simple main method that prints the version and exits - */ - public static void main(String[] args) - { - System.out.println("Version: " + getSpecification()); - System.out.println("Implementation: " + getImplementation()); - } + /** + * A simple main method that prints the version and exits + */ + public static void main(String[] args) { + System.out.println("Version: " + getSpecification()); + System.out.println("Implementation: " + getImplementation()); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/auth/AuthenticationManager.java --- a/src/ch/ethz/ssh2/auth/AuthenticationManager.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/auth/AuthenticationManager.java Wed Jul 30 14:16:58 2014 -0700 @@ -49,14 +49,14 @@ private ClientTransportManager tm; private final BlockingQueue packets - = new ArrayBlockingQueue(5); + = new ArrayBlockingQueue(5); private boolean connectionClosed = false; private String banner; private Set remainingMethods - = new HashSet(); + = new HashSet(); private boolean isPartialSuccess = false; @@ -68,22 +68,24 @@ } private byte[] deQueue() throws IOException { - if(connectionClosed) { + if (connectionClosed) { throw tm.getReasonClosedCause(); } + // Wait for packet try { return packets.take(); } - catch(InterruptedException e) { + catch (InterruptedException e) { throw new InterruptedIOException(e.getMessage()); } } byte[] getNextMessage() throws IOException { - while(true) { + while (true) { byte[] message = deQueue(); - switch(message[0]) { + + switch (message[0]) { case Packets.SSH_MSG_USERAUTH_BANNER: // The server may send an SSH_MSG_USERAUTH_BANNER message at any // time after this authentication protocol starts and before @@ -91,6 +93,7 @@ PacketUserauthBanner sb = new PacketUserauthBanner(message); banner = sb.getBanner(); break; + default: return message; } @@ -111,61 +114,63 @@ } private boolean initialize(String user) throws IOException { - if(initDone == false) { + if (initDone == false) { tm.registerMessageHandler(this, 0, 255); - PacketServiceRequest sr = new PacketServiceRequest("ssh-userauth"); tm.sendMessage(sr.getPayload()); - final PacketServiceAccept accept = new PacketServiceAccept(this.getNextMessage()); - PacketUserauthRequestNone auth = new PacketUserauthRequestNone("ssh-connection", user); tm.sendMessage(auth.getPayload()); - byte[] message = this.getNextMessage(); initDone = true; - switch(message[0]) { + + switch (message[0]) { case Packets.SSH_MSG_USERAUTH_SUCCESS: authenticated = true; tm.removeMessageHandler(this); return true; + case Packets.SSH_MSG_USERAUTH_FAILURE: PacketUserauthFailure puf = new PacketUserauthFailure(message); remainingMethods = puf.getAuthThatCanContinue(); isPartialSuccess = puf.isPartialSuccess(); return false; } + throw new PacketTypeException(message[0]); } + return authenticated; } public boolean authenticatePublicKey(String user, AgentProxy proxy) throws IOException { initialize(user); + boolean success; - boolean success; - for(AgentIdentity identity : proxy.getIdentities()) { + for (AgentIdentity identity : proxy.getIdentities()) { success = authenticatePublicKey(user, identity); - if(success) { + + if (success) { return true; } } + return false; } private boolean authenticatePublicKey(String user, AgentIdentity identity) throws IOException { - if(!remainingMethods.contains("publickey")) { + if (!remainingMethods.contains("publickey")) { throw new IOException("Authentication method not supported"); } byte[] pubKeyBlob = identity.getPublicKeyBlob(); - if(pubKeyBlob == null) { + + if (pubKeyBlob == null) { return false; } TypesWriter tw = new TypesWriter(); byte[] H = tm.getSessionIdentifier(); - tw.writeString(H, 0, H.length); tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); tw.writeString(user); @@ -174,29 +179,27 @@ tw.writeBoolean(true); tw.writeString(identity.getAlgName()); tw.writeString(pubKeyBlob, 0, pubKeyBlob.length); - byte[] msg = tw.getBytes(); byte[] response = identity.sign(msg); - PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey( - "ssh-connection", user, identity.getAlgName(), pubKeyBlob, response); + "ssh-connection", user, identity.getAlgName(), pubKeyBlob, response); tm.sendMessage(ua.getPayload()); - byte[] message = getNextMessage(); final int type = message[0]; - switch(type) { + + switch (type) { case Packets.SSH_MSG_USERAUTH_SUCCESS: authenticated = true; tm.removeMessageHandler(this); return true; + case Packets.SSH_MSG_USERAUTH_FAILURE: PacketUserauthFailure puf = new PacketUserauthFailure(message); - remainingMethods = puf.getAuthThatCanContinue(); isPartialSuccess = puf.isPartialSuccess(); - return false; } + throw new PacketTypeException(type); } @@ -209,22 +212,19 @@ public boolean authenticatePublicKey(String user, KeyPair pair, SecureRandom rnd) throws IOException { PrivateKey key = pair.getPrivate(); + try { initialize(user); - if(!remainingMethods.contains("publickey")) { + if (!remainingMethods.contains("publickey")) { throw new IOException("Authentication method publickey not supported by the server at this stage."); } if (key instanceof DSAPrivateKey) { DSAPrivateKey pk = (DSAPrivateKey) key; - byte[] pk_enc = DSASHA1Verify.encodeSSHDSAPublicKey((DSAPublicKey) pair.getPublic()); - TypesWriter tw = new TypesWriter(); - byte[] H = tm.getSessionIdentifier(); - tw.writeString(H, 0, H.length); tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); tw.writeString(user); @@ -233,26 +233,19 @@ tw.writeBoolean(true); tw.writeString("ssh-dss"); tw.writeString(pk_enc, 0, pk_enc.length); - byte[] msg = tw.getBytes(); - byte[] ds = DSASHA1Verify.generateSignature(msg, pk, rnd); - byte[] ds_enc = DSASHA1Verify.encodeSSHDSASignature(ds); - PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user, "ssh-dss", pk_enc, ds_enc); tm.sendMessage(ua.getPayload()); } - else if(key instanceof RSAPrivateKey) { + else if (key instanceof RSAPrivateKey) { RSAPrivateKey pk = (RSAPrivateKey) key; - byte[] pk_enc = RSASHA1Verify.encodeSSHRSAPublicKey((RSAPublicKey) pair.getPublic()); - TypesWriter tw = new TypesWriter(); { byte[] H = tm.getSessionIdentifier(); - tw.writeString(H, 0, H.length); tw.writeByte(Packets.SSH_MSG_USERAUTH_REQUEST); tw.writeString(user); @@ -262,13 +255,9 @@ tw.writeString("ssh-rsa"); tw.writeString(pk_enc, 0, pk_enc.length); } - byte[] msg = tw.getBytes(); - byte[] ds = RSASHA1Verify.generateSignature(msg, pk); - byte[] rsa_sig_enc = RSASHA1Verify.encodeSSHRSASignature(ds); - PacketUserauthRequestPublicKey ua = new PacketUserauthRequestPublicKey("ssh-connection", user, "ssh-rsa", pk_enc, rsa_sig_enc); tm.sendMessage(ua.getPayload()); @@ -300,24 +289,26 @@ else { throw new IOException("Unknown private key type returned by the PEM decoder."); } + byte[] message = getNextMessage(); final int type = message[0]; - switch(type) { + + switch (type) { case Packets.SSH_MSG_USERAUTH_SUCCESS: authenticated = true; tm.removeMessageHandler(this); return true; + case Packets.SSH_MSG_USERAUTH_FAILURE: PacketUserauthFailure puf = new PacketUserauthFailure(message); - remainingMethods = puf.getAuthThatCanContinue(); isPartialSuccess = puf.isPartialSuccess(); - return false; } + throw new PacketTypeException(type); } - catch(IOException e) { + catch (IOException e) { tm.close(e); throw e; } @@ -328,7 +319,7 @@ initialize(user); return authenticated; } - catch(IOException e) { + catch (IOException e) { tm.close(e); throw e; } @@ -338,29 +329,31 @@ try { initialize(user); - if(!remainingMethods.contains("password")) { + if (!remainingMethods.contains("password")) { throw new IOException("Authentication method not supported"); } PacketUserauthRequestPassword ua = new PacketUserauthRequestPassword("ssh-connection", user, pass); tm.sendMessage(ua.getPayload()); - byte[] message = getNextMessage(); final int type = message[0]; - switch(type) { + + switch (type) { case Packets.SSH_MSG_USERAUTH_SUCCESS: authenticated = true; tm.removeMessageHandler(this); return true; + case Packets.SSH_MSG_USERAUTH_FAILURE: PacketUserauthFailure puf = new PacketUserauthFailure(message); remainingMethods = puf.getAuthThatCanContinue(); isPartialSuccess = puf.isPartialSuccess(); return false; } + throw new PacketTypeException(type); } - catch(IOException e) { + catch (IOException e) { tm.close(e); throw e; } @@ -370,49 +363,52 @@ try { initialize(user); - if(!remainingMethods.contains("keyboard-interactive")) { + if (!remainingMethods.contains("keyboard-interactive")) { throw new IOException( - "Authentication method keyboard-interactive not supported by the server at this stage."); + "Authentication method keyboard-interactive not supported by the server at this stage."); } PacketUserauthRequestInteractive ua = new PacketUserauthRequestInteractive("ssh-connection", user, submethods); - tm.sendMessage(ua.getPayload()); - while(true) { + while (true) { byte[] message = getNextMessage(); final int type = message[0]; - switch(type) { + + switch (type) { case Packets.SSH_MSG_USERAUTH_SUCCESS: authenticated = true; tm.removeMessageHandler(this); return true; + case Packets.SSH_MSG_USERAUTH_FAILURE: PacketUserauthFailure puf = new PacketUserauthFailure(message); - remainingMethods = puf.getAuthThatCanContinue(); isPartialSuccess = puf.isPartialSuccess(); + return false; - return false; case Packets.SSH_MSG_USERAUTH_INFO_REQUEST: PacketUserauthInfoRequest info = new PacketUserauthInfoRequest(message); String[] responses; + try { responses = cb.replyToChallenge(info.getName(), info.getInstruction(), info.getNumPrompts(), - info.getPrompt(), info.getEcho()); + info.getPrompt(), info.getEcho()); } - catch(Exception e) { + catch (Exception e) { throw new IOException("Exception in callback.", e); } + PacketUserauthInfoResponse puir = new PacketUserauthInfoResponse(responses); tm.sendMessage(puir.getPayload()); continue; } + throw new PacketTypeException(type); } } - catch(IOException e) { + catch (IOException e) { tm.close(e); throw e; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/auth/ServerAuthenticationManager.java --- a/src/ch/ethz/ssh2/auth/ServerAuthenticationManager.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/auth/ServerAuthenticationManager.java Wed Jul 30 14:16:58 2014 -0700 @@ -29,25 +29,22 @@ } private void sendresult(AuthenticationResult result) throws IOException { - if(AuthenticationResult.SUCCESS == result) { + if (AuthenticationResult.SUCCESS == result) { PacketUserauthSuccess pus = new PacketUserauthSuccess(); state.tm.sendAsynchronousMessage(pus.getPayload()); - state.tm.removeMessageHandler(this); state.tm.registerMessageHandler(this, 50, 79); - state.cm = new ChannelManager(state); - state.flag_auth_completed = true; - } else { Set remaining_methods = new HashSet(); - if(state.cb_auth != null) { + if (state.cb_auth != null) { remaining_methods.addAll(Arrays.asList( - state.cb_auth.getRemainingAuthMethods(state.conn))); + state.cb_auth.getRemainingAuthMethods(state.conn))); } + PacketUserauthFailure puf = new PacketUserauthFailure(remaining_methods, AuthenticationResult.PARTIAL_SUCCESS == result); state.tm.sendAsynchronousMessage(puf.getPayload()); @@ -60,68 +57,63 @@ public void handleMessage(byte[] msg) throws IOException { /* Ignore all authentication messages after successful auth */ - - if(state.flag_auth_completed) { + if (state.flag_auth_completed) { return; } - if(!state.flag_auth_serviceRequested) { - /* Must be PacketServiceRequest */ - + if (!state.flag_auth_serviceRequested) { + /* Must be PacketServiceRequest */ PacketServiceRequest psr = new PacketServiceRequest(msg); - if(!"ssh-userauth".equals(psr.getServiceName())) { + if (!"ssh-userauth".equals(psr.getServiceName())) { throw new IOException("SSH protocol error, expected ssh-userauth service request"); } PacketServiceAccept psa = new PacketServiceAccept("ssh-userauth"); state.tm.sendAsynchronousMessage(psa.getPayload()); - String banner = state.cb_auth.initAuthentication(state.conn); - if(banner != null) { + if (banner != null) { PacketUserauthBanner pub = new PacketUserauthBanner(banner); state.tm.sendAsynchronousMessage(pub.getPayload()); } state.flag_auth_serviceRequested = true; - return; } ServerAuthenticationCallback cb = state.cb_auth; - TypesReader tr = new TypesReader(msg); int packet_type = tr.readByte(); - if(packet_type == Packets.SSH_MSG_USERAUTH_REQUEST) { + if (packet_type == Packets.SSH_MSG_USERAUTH_REQUEST) { String username = tr.readString("UTF-8"); String service = tr.readString(); String method = tr.readString(); - if(!"ssh-connection".equals(service)) { + if (!"ssh-connection".equals(service)) { sendresult(AuthenticationResult.FAILURE); return; } - if("none".equals(method)) { - if(cb != null) { + if ("none".equals(method)) { + if (cb != null) { sendresult(cb.authenticateWithNone(state.conn, username)); return; } } - if("password".equals(method)) { + if ("password".equals(method)) { boolean flag_change_pass = tr.readBoolean(); - if(flag_change_pass) { + if (flag_change_pass) { sendresult(AuthenticationResult.FAILURE); return; } String password = tr.readString("UTF-8"); - if(cb != null) { + if (cb != null) { sendresult(cb.authenticateWithPassword(state.conn, username, password)); return; } @@ -130,6 +122,7 @@ sendresult(AuthenticationResult.FAILURE); return; } + throw new PacketTypeException(packet_type); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/AuthAgentForwardThread.java --- a/src/ch/ethz/ssh2/channel/AuthAgentForwardThread.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/AuthAgentForwardThread.java Wed Jul 30 14:16:58 2014 -0700 @@ -99,7 +99,6 @@ public AuthAgentForwardThread(Channel c, AuthAgentCallback authAgent) { this.c = c; this.authAgent = authAgent; - log.debug("AuthAgentForwardThread started"); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/Channel.java --- a/src/ch/ethz/ssh2/channel/Channel.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/Channel.java Wed Jul 30 14:16:58 2014 -0700 @@ -14,208 +14,192 @@ * @author Christian Plattner * @version $Id: Channel.java 123 2014-04-12 21:11:47Z dkocher@sudo.ch $ */ -public class Channel -{ - /* - * OK. Here is an important part of the JVM Specification: - * (http://java.sun.com/docs/books/vmspec/2nd-edition/html/Threads.doc.html#22214) - * - * Any association between locks and variables is purely conventional. - * Locking any lock conceptually flushes all variables from a thread's - * working memory, and unlocking any lock forces the writing out to main - * memory of all variables that the thread has assigned. That a lock may be - * associated with a particular object or a class is purely a convention. - * (...) - * - * If a thread uses a particular shared variable only after locking a - * particular lock and before the corresponding unlocking of that same lock, - * then the thread will read the shared value of that variable from main - * memory after the lock operation, if necessary, and will copy back to main - * memory the value most recently assigned to that variable before the - * unlock operation. - * - * This, in conjunction with the mutual exclusion rules for locks, suffices - * to guarantee that values are correctly transmitted from one thread to - * another through shared variables. - * - * ====> Always keep that in mind when modifying the Channel/ChannelManger - * code. - * - */ +public class Channel { + /* + * OK. Here is an important part of the JVM Specification: + * (http://java.sun.com/docs/books/vmspec/2nd-edition/html/Threads.doc.html#22214) + * + * Any association between locks and variables is purely conventional. + * Locking any lock conceptually flushes all variables from a thread's + * working memory, and unlocking any lock forces the writing out to main + * memory of all variables that the thread has assigned. That a lock may be + * associated with a particular object or a class is purely a convention. + * (...) + * + * If a thread uses a particular shared variable only after locking a + * particular lock and before the corresponding unlocking of that same lock, + * then the thread will read the shared value of that variable from main + * memory after the lock operation, if necessary, and will copy back to main + * memory the value most recently assigned to that variable before the + * unlock operation. + * + * This, in conjunction with the mutual exclusion rules for locks, suffices + * to guarantee that values are correctly transmitted from one thread to + * another through shared variables. + * + * ====> Always keep that in mind when modifying the Channel/ChannelManger + * code. + * + */ - public static final int STATE_OPENING = 1; - public static final int STATE_OPEN = 2; - public static final int STATE_CLOSED = 4; + public static final int STATE_OPENING = 1; + public static final int STATE_OPEN = 2; + public static final int STATE_CLOSED = 4; - static final int CHANNEL_BUFFER_SIZE = 32 * 1024 * 3 * 2; + static final int CHANNEL_BUFFER_SIZE = 32 * 1024 * 3 * 2; - /* - * To achieve correctness, the following rules have to be respected when - * accessing this object: - */ + /* + * To achieve correctness, the following rules have to be respected when + * accessing this object: + */ - // These fields can always be read - final ChannelManager cm; - final ChannelOutputStream stdinStream; - final ChannelInputStream stdoutStream; - final ChannelInputStream stderrStream; - - // In case this channel belongs to a server-side session. - ServerSessionImpl ss; + // These fields can always be read + final ChannelManager cm; + final ChannelOutputStream stdinStream; + final ChannelInputStream stdoutStream; + final ChannelInputStream stderrStream; - // These two fields will only be written while the Channel is in state - // STATE_OPENING. - // The code makes sure that the two fields are written out when the state is - // changing to STATE_OPEN. - // Therefore, if you know that the Channel is in state STATE_OPEN, then you - // can read these two fields without synchronizing on the Channel. However, make - // sure that you get the latest values (e.g., flush caches by synchronizing on any - // object). However, to be on the safe side, you can lock the channel. - - int localID = -1; - int remoteID = -1; + // In case this channel belongs to a server-side session. + ServerSessionImpl ss; - /* - * Make sure that we never send a data/EOF/WindowChange msg after a CLOSE - * msg. - * - * This is a little bit complicated, but we have to do it in that way, since - * we cannot keep a lock on the Channel during the send operation (this - * would block sometimes the receiver thread, and, in extreme cases, can - * lead to a deadlock on both sides of the connection (senders are blocked - * since the receive buffers on the other side are full, and receiver - * threads wait for the senders to finish). It all depends on the - * implementation on the other side. But we cannot make any assumptions, we - * have to assume the worst case. Confused? Just believe me. - */ + // These two fields will only be written while the Channel is in state + // STATE_OPENING. + // The code makes sure that the two fields are written out when the state is + // changing to STATE_OPEN. + // Therefore, if you know that the Channel is in state STATE_OPEN, then you + // can read these two fields without synchronizing on the Channel. However, make + // sure that you get the latest values (e.g., flush caches by synchronizing on any + // object). However, to be on the safe side, you can lock the channel. + + int localID = -1; + int remoteID = -1; - /* - * If you send a message on a channel, then you have to aquire the - * "channelSendLock" and check the "closeMessageSent" flag (this variable - * may only be accessed while holding the "channelSendLock" !!! - * - * BTW: NEVER EVER SEND MESSAGES FROM THE RECEIVE THREAD - see explanation - * above. - */ - - final Object channelSendLock = new Object(); - boolean closeMessageSent = false; + /* + * Make sure that we never send a data/EOF/WindowChange msg after a CLOSE + * msg. + * + * This is a little bit complicated, but we have to do it in that way, since + * we cannot keep a lock on the Channel during the send operation (this + * would block sometimes the receiver thread, and, in extreme cases, can + * lead to a deadlock on both sides of the connection (senders are blocked + * since the receive buffers on the other side are full, and receiver + * threads wait for the senders to finish). It all depends on the + * implementation on the other side. But we cannot make any assumptions, we + * have to assume the worst case. Confused? Just believe me. + */ - /* - * Stop memory fragmentation by allocating this often used buffer. - * May only be used while holding the channelSendLock - */ - - final byte[] msgWindowAdjust = new byte[9]; + /* + * If you send a message on a channel, then you have to aquire the + * "channelSendLock" and check the "closeMessageSent" flag (this variable + * may only be accessed while holding the "channelSendLock" !!! + * + * BTW: NEVER EVER SEND MESSAGES FROM THE RECEIVE THREAD - see explanation + * above. + */ - // If you access (read or write) any of the following fields, then you have - // to synchronize on the channel. + final Object channelSendLock = new Object(); + boolean closeMessageSent = false; - int state = STATE_OPENING; + /* + * Stop memory fragmentation by allocating this often used buffer. + * May only be used while holding the channelSendLock + */ - boolean closeMessageRecv = false; + final byte[] msgWindowAdjust = new byte[9]; - /* This is a stupid implementation. At the moment we can only wait - * for one pending request per channel. - */ - int successCounter = 0; - int failedCounter = 0; + // If you access (read or write) any of the following fields, then you have + // to synchronize on the channel. - int localWindow = 0; /* locally, we use a small window, < 2^31 */ - long remoteWindow = 0; /* long for readable 2^32 - 1 window support */ + int state = STATE_OPENING; - int localMaxPacketSize = -1; - int remoteMaxPacketSize = -1; + boolean closeMessageRecv = false; - final byte[] stdoutBuffer = new byte[CHANNEL_BUFFER_SIZE]; - final byte[] stderrBuffer = new byte[CHANNEL_BUFFER_SIZE]; + /* This is a stupid implementation. At the moment we can only wait + * for one pending request per channel. + */ + int successCounter = 0; + int failedCounter = 0; - int stdoutReadpos = 0; - int stdoutWritepos = 0; - int stderrReadpos = 0; - int stderrWritepos = 0; + int localWindow = 0; /* locally, we use a small window, < 2^31 */ + long remoteWindow = 0; /* long for readable 2^32 - 1 window support */ - boolean EOF = false; + int localMaxPacketSize = -1; + int remoteMaxPacketSize = -1; - Integer exit_status; - - String exit_signal; + final byte[] stdoutBuffer = new byte[CHANNEL_BUFFER_SIZE]; + final byte[] stderrBuffer = new byte[CHANNEL_BUFFER_SIZE]; - // we keep the x11 cookie so that this channel can be closed when this - // specific x11 forwarding gets stopped - - String hexX11FakeCookie; + int stdoutReadpos = 0; + int stdoutWritepos = 0; + int stderrReadpos = 0; + int stderrWritepos = 0; - // reasonClosed is special, since we sometimes need to access it - // while holding the channelSendLock. - // We protect it with a private short term lock. + boolean EOF = false; - private final Object reasonClosedLock = new Object(); - private IOException reasonClosed = null; + Integer exit_status; + + String exit_signal; - public Channel(ChannelManager cm) - { - this.cm = cm; + // we keep the x11 cookie so that this channel can be closed when this + // specific x11 forwarding gets stopped - this.localWindow = CHANNEL_BUFFER_SIZE; - this.localMaxPacketSize = TransportManager.MAX_PACKET_SIZE; + String hexX11FakeCookie; - this.stdinStream = new ChannelOutputStream(this); - this.stdoutStream = new ChannelInputStream(this, false); - this.stderrStream = new ChannelInputStream(this, true); - } + // reasonClosed is special, since we sometimes need to access it + // while holding the channelSendLock. + // We protect it with a private short term lock. - /* Methods to allow access from classes outside of this package */ + private final Object reasonClosedLock = new Object(); + private IOException reasonClosed = null; - public ChannelInputStream getStderrStream() - { - return stderrStream; - } + public Channel(ChannelManager cm) { + this.cm = cm; + this.localWindow = CHANNEL_BUFFER_SIZE; + this.localMaxPacketSize = TransportManager.MAX_PACKET_SIZE; + this.stdinStream = new ChannelOutputStream(this); + this.stdoutStream = new ChannelInputStream(this, false); + this.stderrStream = new ChannelInputStream(this, true); + } - public ChannelOutputStream getStdinStream() - { - return stdinStream; - } + /* Methods to allow access from classes outside of this package */ - public ChannelInputStream getStdoutStream() - { - return stdoutStream; - } + public ChannelInputStream getStderrStream() { + return stderrStream; + } - public String getExitSignal() - { - synchronized (this) - { - return exit_signal; - } - } + public ChannelOutputStream getStdinStream() { + return stdinStream; + } + + public ChannelInputStream getStdoutStream() { + return stdoutStream; + } - public Integer getExitStatus() - { - synchronized (this) - { - return exit_status; - } - } + public String getExitSignal() { + synchronized (this) { + return exit_signal; + } + } + + public Integer getExitStatus() { + synchronized (this) { + return exit_status; + } + } - public IOException getReasonClosed() - { - synchronized (reasonClosedLock) - { - return reasonClosed; - } - } + public IOException getReasonClosed() { + synchronized (reasonClosedLock) { + return reasonClosed; + } + } - public void setReasonClosed(IOException e) - { - synchronized (reasonClosedLock) - { + public void setReasonClosed(IOException e) { + synchronized (reasonClosedLock) { this.reasonClosed = e; - } - } + } + } - public int getState() - { - return this.state; - } + public int getState() { + return this.state; + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/ChannelClosedException.java --- a/src/ch/ethz/ssh2/channel/ChannelClosedException.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/ChannelClosedException.java Wed Jul 30 14:16:58 2014 -0700 @@ -10,16 +10,14 @@ /** * @version $Id: ChannelClosedException.java 3183 2007-07-30 19:22:34Z dkocher $ */ -public class ChannelClosedException extends IOException -{ +public class ChannelClosedException extends IOException { - /** - * - */ - private static final long serialVersionUID = 1L; + /** + * + */ + private static final long serialVersionUID = 1L; - public ChannelClosedException(String s) - { - super(s); - } + public ChannelClosedException(String s) { + super(s); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/ChannelInputStream.java --- a/src/ch/ethz/ssh2/channel/ChannelInputStream.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/ChannelInputStream.java Wed Jul 30 14:16:58 2014 -0700 @@ -9,86 +9,74 @@ /** * ChannelInputStream. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public final class ChannelInputStream extends InputStream -{ - Channel c; +public final class ChannelInputStream extends InputStream { + Channel c; - boolean isClosed = false; - boolean isEOF = false; - boolean extendedFlag = false; + boolean isClosed = false; + boolean isEOF = false; + boolean extendedFlag = false; - ChannelInputStream(Channel c, boolean isExtended) - { - this.c = c; - this.extendedFlag = isExtended; - } + ChannelInputStream(Channel c, boolean isExtended) { + this.c = c; + this.extendedFlag = isExtended; + } - @Override - public int available() throws IOException - { - if (isEOF) - return 0; + @Override + public int available() throws IOException { + if (isEOF) + return 0; - int avail = c.cm.getAvailable(c, extendedFlag); - - /* We must not return -1 on EOF */ + int avail = c.cm.getAvailable(c, extendedFlag); + /* We must not return -1 on EOF */ + return (avail > 0) ? avail : 0; + } - return (avail > 0) ? avail : 0; - } + @Override + public void close() throws IOException { + isClosed = true; + } - @Override - public void close() throws IOException - { - isClosed = true; - } - - @Override - public int read(byte[] b, int off, int len) throws IOException - { - if (b == null) - throw new NullPointerException(); + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (b == null) + throw new NullPointerException(); - if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) - throw new IndexOutOfBoundsException(); + if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) + throw new IndexOutOfBoundsException(); - if (len == 0) - return 0; + if (len == 0) + return 0; - if (isEOF) - return -1; + if (isEOF) + return -1; - int ret = c.cm.getChannelData(c, extendedFlag, b, off, len); + int ret = c.cm.getChannelData(c, extendedFlag, b, off, len); - if (ret == -1) - { - isEOF = true; - } + if (ret == -1) { + isEOF = true; + } - return ret; - } + return ret; + } - @Override - public int read(byte[] b) throws IOException - { - return read(b, 0, b.length); - } - - @Override - public int read() throws IOException - { - /* Yes, this stream is pure and unbuffered, a single byte read() is slow */ + @Override + public int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } - final byte b[] = new byte[1]; - - int ret = read(b, 0, 1); + @Override + public int read() throws IOException { + /* Yes, this stream is pure and unbuffered, a single byte read() is slow */ + final byte b[] = new byte[1]; + int ret = read(b, 0, 1); - if (ret != 1) - return -1; + if (ret != 1) + return -1; - return b[0] & 0xff; - } + return b[0] & 0xff; + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/ChannelManager.java --- a/src/ch/ethz/ssh2/channel/ChannelManager.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/ChannelManager.java Wed Jul 30 14:16:58 2014 -0700 @@ -95,20 +95,21 @@ } private Channel getChannel(int id) { - synchronized(channels) { - for(Channel c : channels) { - if(c.localID == id) { + synchronized (channels) { + for (Channel c : channels) { + if (c.localID == id) { return c; } } } + return null; } private void removeChannel(int id) { - synchronized(channels) { - for(Channel c : channels) { - if(c.localID == id) { + synchronized (channels) { + for (Channel c : channels) { + if (c.localID == id) { channels.remove(c); break; } @@ -117,24 +118,24 @@ } private int addChannel(Channel c) { - synchronized(channels) { + synchronized (channels) { channels.add(c); return nextLocalChannel++; } } private void waitUntilChannelOpen(Channel c) throws IOException { - synchronized(c) { - while(c.state == Channel.STATE_OPENING) { + synchronized (c) { + while (c.state == Channel.STATE_OPENING) { try { c.wait(); } - catch(InterruptedException e) { + catch (InterruptedException e) { throw new InterruptedIOException(e.getMessage()); } } - if(c.state != Channel.STATE_OPEN) { + if (c.state != Channel.STATE_OPEN) { removeChannel(c.localID); throw c.getReasonClosed(); } @@ -142,84 +143,90 @@ } private void waitForGlobalSuccessOrFailure() throws IOException { - synchronized(channels) { - while((globalSuccessCounter == 0) && (globalFailedCounter == 0)) { - if(shutdown) { + synchronized (channels) { + while ((globalSuccessCounter == 0) && (globalFailedCounter == 0)) { + if (shutdown) { throw new IOException("The connection is being shutdown"); } try { channels.wait(); } - catch(InterruptedException e) { + catch (InterruptedException e) { throw new InterruptedIOException(e.getMessage()); } } - if((globalFailedCounter == 0) && (globalSuccessCounter == 1)) { + + if ((globalFailedCounter == 0) && (globalSuccessCounter == 1)) { return; } - if((globalFailedCounter == 1) && (globalSuccessCounter == 0)) { + + if ((globalFailedCounter == 1) && (globalSuccessCounter == 0)) { throw new IOException("The server denied the request (did you enable port forwarding?)"); } + throw new IOException("Illegal state. The server sent " + globalSuccessCounter - + " SSH_MSG_REQUEST_SUCCESS and " + globalFailedCounter + " SSH_MSG_REQUEST_FAILURE messages."); + + " SSH_MSG_REQUEST_SUCCESS and " + globalFailedCounter + " SSH_MSG_REQUEST_FAILURE messages."); } } private void waitForChannelSuccessOrFailure(Channel c) throws IOException { - synchronized(c) { - while((c.successCounter == 0) && (c.failedCounter == 0)) { - if(c.state != Channel.STATE_OPEN) { + synchronized (c) { + while ((c.successCounter == 0) && (c.failedCounter == 0)) { + if (c.state != Channel.STATE_OPEN) { throw c.getReasonClosed(); } + try { c.wait(); } - catch(InterruptedException ignore) { + catch (InterruptedException ignore) { throw new InterruptedIOException(); } } - if((c.failedCounter == 0) && (c.successCounter == 1)) { + + if ((c.failedCounter == 0) && (c.successCounter == 1)) { return; } - if((c.failedCounter == 1) && (c.successCounter == 0)) { + + if ((c.failedCounter == 1) && (c.successCounter == 0)) { throw new IOException("The server denied the request."); } + throw new IOException("Illegal state. The server sent " + c.successCounter - + " SSH_MSG_CHANNEL_SUCCESS and " + c.failedCounter + " SSH_MSG_CHANNEL_FAILURE messages."); + + " SSH_MSG_CHANNEL_SUCCESS and " + c.failedCounter + " SSH_MSG_CHANNEL_FAILURE messages."); } } public void registerX11Cookie(String hexFakeCookie, X11ServerData data) { - synchronized(x11_magic_cookies) { + synchronized (x11_magic_cookies) { x11_magic_cookies.put(hexFakeCookie, data); } } public void unRegisterX11Cookie(String hexFakeCookie, boolean killChannels) { - if(hexFakeCookie == null) { + if (hexFakeCookie == null) { throw new IllegalStateException("hexFakeCookie may not be null"); } - synchronized(x11_magic_cookies) { + synchronized (x11_magic_cookies) { x11_magic_cookies.remove(hexFakeCookie); } - if(killChannels == false) { + if (killChannels == false) { return; } log.debug("Closing all X11 channels for the given fake cookie"); - List channel_copy = new ArrayList(); - synchronized(channels) { + synchronized (channels) { channel_copy.addAll(channels); } - for(Channel c : channel_copy) { - synchronized(c) { - if(hexFakeCookie.equals(c.hexX11FakeCookie) == false) { + for (Channel c : channel_copy) { + synchronized (c) { + if (hexFakeCookie.equals(c.hexX11FakeCookie) == false) { continue; } } @@ -227,34 +234,34 @@ try { closeChannel(c, "Closing X11 channel since the corresponding session is closing", true); } - catch(IOException ignored) { + catch (IOException ignored) { } } } public X11ServerData checkX11Cookie(String hexFakeCookie) { - synchronized(x11_magic_cookies) { - if(hexFakeCookie != null) { + synchronized (x11_magic_cookies) { + if (hexFakeCookie != null) { return x11_magic_cookies.get(hexFakeCookie); } } + return null; } public void closeAllChannels() { log.debug("Closing all channels"); - List channel_copy = new ArrayList(); - synchronized(channels) { + synchronized (channels) { channel_copy.addAll(channels); } - for(Channel c : channel_copy) { + for (Channel c : channel_copy) { try { closeChannel(c, "Closing all channels", true); } - catch(IOException ignored) { + catch (IOException ignored) { } } } @@ -266,27 +273,26 @@ public void closeChannel(Channel c, IOException reason, boolean force) throws IOException { byte msg[] = new byte[5]; - synchronized(c) { - if(force) { + synchronized (c) { + if (force) { c.state = Channel.STATE_CLOSED; c.EOF = true; } c.setReasonClosed(reason); - msg[0] = Packets.SSH_MSG_CHANNEL_CLOSE; - msg[1] = (byte) (c.remoteID >> 24); - msg[2] = (byte) (c.remoteID >> 16); - msg[3] = (byte) (c.remoteID >> 8); - msg[4] = (byte) (c.remoteID); - + msg[1] = (byte)(c.remoteID >> 24); + msg[2] = (byte)(c.remoteID >> 16); + msg[3] = (byte)(c.remoteID >> 8); + msg[4] = (byte)(c.remoteID); c.notifyAll(); } - synchronized(c.channelSendLock) { - if(c.closeMessageSent) { + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { return; } + tm.sendMessage(msg); c.closeMessageSent = true; } @@ -297,113 +303,110 @@ public void sendEOF(Channel c) throws IOException { byte[] msg = new byte[5]; - synchronized(c) { - if(c.state != Channel.STATE_OPEN) { + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { return; } msg[0] = Packets.SSH_MSG_CHANNEL_EOF; - msg[1] = (byte) (c.remoteID >> 24); - msg[2] = (byte) (c.remoteID >> 16); - msg[3] = (byte) (c.remoteID >> 8); - msg[4] = (byte) (c.remoteID); + msg[1] = (byte)(c.remoteID >> 24); + msg[2] = (byte)(c.remoteID >> 16); + msg[3] = (byte)(c.remoteID >> 8); + msg[4] = (byte)(c.remoteID); } - synchronized(c.channelSendLock) { - if(c.closeMessageSent == true) { + synchronized (c.channelSendLock) { + if (c.closeMessageSent == true) { return; } + tm.sendMessage(msg); } - log.debug("Sent EOF (Channel " + c.localID + "/" + c.remoteID + ")"); } public void sendOpenConfirmation(Channel c) throws IOException { PacketChannelOpenConfirmation pcoc = null; - synchronized(c) { - if(c.state != Channel.STATE_OPENING) { + synchronized (c) { + if (c.state != Channel.STATE_OPENING) { return; } c.state = Channel.STATE_OPEN; - pcoc = new PacketChannelOpenConfirmation(c.remoteID, c.localID, c.localWindow, c.localMaxPacketSize); } - synchronized(c.channelSendLock) { - if(c.closeMessageSent == true) { + synchronized (c.channelSendLock) { + if (c.closeMessageSent == true) { return; } + tm.sendMessage(pcoc.getPayload()); } } public void sendData(Channel c, byte[] buffer, int pos, int len) throws IOException { - while(len > 0) { + while (len > 0) { int thislen = 0; byte[] msg; - synchronized(c) { - while(true) { - if(c.state == Channel.STATE_CLOSED) { + synchronized (c) { + while (true) { + if (c.state == Channel.STATE_CLOSED) { throw c.getReasonClosed(); } - if(c.state != Channel.STATE_OPEN) { + + if (c.state != Channel.STATE_OPEN) { throw new ChannelClosedException("SSH channel in strange state. (" + c.state + ")"); } - if(c.remoteWindow != 0) { + if (c.remoteWindow != 0) { break; } try { c.wait(); } - catch(InterruptedException e) { + catch (InterruptedException e) { throw new InterruptedIOException(e.getMessage()); } } /* len > 0, no sign extension can happen when comparing */ - thislen = (c.remoteWindow >= len) ? len : (int) c.remoteWindow; - int estimatedMaxDataLen = c.remoteMaxPacketSize - (tm.getPacketOverheadEstimate() + 9); /* The worst case scenario =) a true bottleneck */ - if(estimatedMaxDataLen <= 0) { + if (estimatedMaxDataLen <= 0) { estimatedMaxDataLen = 1; } - if(thislen > estimatedMaxDataLen) { + if (thislen > estimatedMaxDataLen) { thislen = estimatedMaxDataLen; } c.remoteWindow -= thislen; - msg = new byte[1 + 8 + thislen]; - msg[0] = Packets.SSH_MSG_CHANNEL_DATA; - msg[1] = (byte) (c.remoteID >> 24); - msg[2] = (byte) (c.remoteID >> 16); - msg[3] = (byte) (c.remoteID >> 8); - msg[4] = (byte) (c.remoteID); - msg[5] = (byte) (thislen >> 24); - msg[6] = (byte) (thislen >> 16); - msg[7] = (byte) (thislen >> 8); - msg[8] = (byte) (thislen); - + msg[1] = (byte)(c.remoteID >> 24); + msg[2] = (byte)(c.remoteID >> 16); + msg[3] = (byte)(c.remoteID >> 8); + msg[4] = (byte)(c.remoteID); + msg[5] = (byte)(thislen >> 24); + msg[6] = (byte)(thislen >> 16); + msg[7] = (byte)(thislen >> 8); + msg[8] = (byte)(thislen); System.arraycopy(buffer, pos, msg, 9, thislen); } - synchronized(c.channelSendLock) { - if(c.closeMessageSent) { + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { throw c.getReasonClosed(); } + tm.sendMessage(msg); } @@ -413,37 +416,37 @@ } public int requestGlobalForward(String bindAddress, int bindPort, String targetAddress, int targetPort) - throws IOException { + throws IOException { RemoteForwardingData rfd = new RemoteForwardingData(); - rfd.bindAddress = bindAddress; rfd.bindPort = bindPort; rfd.targetAddress = targetAddress; rfd.targetPort = targetPort; - synchronized(remoteForwardings) { - if(remoteForwardings.get(bindPort) != null) { + synchronized (remoteForwardings) { + if (remoteForwardings.get(bindPort) != null) { throw new IOException("There is already a forwarding for remote port " + bindPort); } + remoteForwardings.put(bindPort, rfd); } - synchronized(channels) { + synchronized (channels) { globalSuccessCounter = globalFailedCounter = 0; } PacketGlobalForwardRequest pgf = new PacketGlobalForwardRequest(true, bindAddress, bindPort); tm.sendMessage(pgf.getPayload()); - log.debug("Requesting a remote forwarding ('" + bindAddress + "', " + bindPort + ")"); try { waitForGlobalSuccessOrFailure(); } - catch(IOException e) { - synchronized(remoteForwardings) { + catch (IOException e) { + synchronized (remoteForwardings) { remoteForwardings.remove(bindPort); } + throw e; } @@ -453,29 +456,27 @@ public void requestCancelGlobalForward(int bindPort) throws IOException { RemoteForwardingData rfd; - synchronized(remoteForwardings) { + synchronized (remoteForwardings) { rfd = remoteForwardings.get(bindPort); - if(rfd == null) { + if (rfd == null) { throw new IOException("Sorry, there is no known remote forwarding for remote port " + bindPort); } } - synchronized(channels) { + synchronized (channels) { globalSuccessCounter = globalFailedCounter = 0; } PacketGlobalCancelForwardRequest pgcf = new PacketGlobalCancelForwardRequest(true, rfd.bindAddress, rfd.bindPort); tm.sendMessage(pgcf.getPayload()); - log.debug("Requesting cancelation of remote forward ('" + rfd.bindAddress + "', " + rfd.bindPort + ")"); - waitForGlobalSuccessOrFailure(); - /* Only now we are sure that no more forwarded connections will arrive */ + /* Only now we are sure that no more forwarded connections will arrive */ - synchronized(remoteForwardings) { + synchronized (remoteForwardings) { remoteForwardings.remove(bindPort); } } @@ -497,29 +498,31 @@ } log.debug("Requesting agent forwarding"); + PacketChannelAuthAgentReq aar = new PacketChannelAuthAgentReq(c.remoteID); - PacketChannelAuthAgentReq aar = new PacketChannelAuthAgentReq(c.remoteID); - synchronized(c.channelSendLock) { + synchronized (c.channelSendLock) { if (c.closeMessageSent) { throw c.getReasonClosed(); } + tm.sendMessage(aar.getPayload()); } try { waitForChannelSuccessOrFailure(c); } - catch(IOException e) { + catch (IOException e) { authAgent = null; throw e; } } public void registerThread(IChannelWorkerThread thr) throws IOException { - synchronized(listenerThreads) { - if(listenerThreadsAllowed == false) { + synchronized (listenerThreads) { + if (listenerThreadsAllowed == false) { throw new IOException("Too late, this connection is closed."); } + listenerThreads.add(thr); } } @@ -528,36 +531,30 @@ int originator_port) throws IOException { Channel c = new Channel(this); - synchronized(c) { + synchronized (c) { c.localID = addChannel(c); // end of synchronized block forces writing out to main memory } PacketOpenDirectTCPIPChannel dtc = new PacketOpenDirectTCPIPChannel(c.localID, c.localWindow, c.localMaxPacketSize, host_to_connect, port_to_connect, originator_IP_address, originator_port); - tm.sendMessage(dtc.getPayload()); - waitUntilChannelOpen(c); - return c; } public Channel openSessionChannel() throws IOException { Channel c = new Channel(this); - synchronized(c) { + synchronized (c) { c.localID = addChannel(c); // end of synchronized block forces the writing out to main memory } log.debug("Sending SSH_MSG_CHANNEL_OPEN (Channel " + c.localID + ")"); - PacketOpenSessionChannel smo = new PacketOpenSessionChannel(c.localID, c.localWindow, c.localMaxPacketSize); tm.sendMessage(smo.getPayload()); - waitUntilChannelOpen(c); - return c; } @@ -565,27 +562,28 @@ int term_width_pixels, int term_height_pixels, byte[] terminal_modes) throws IOException { PacketSessionPtyRequest spr; - synchronized(c) { - if(c.state != Channel.STATE_OPEN) { + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { throw c.getReasonClosed(); } + spr = new PacketSessionPtyRequest(c.remoteID, true, term, term_width_characters, term_height_characters, - term_width_pixels, term_height_pixels, terminal_modes); - + term_width_pixels, term_height_pixels, terminal_modes); c.successCounter = c.failedCounter = 0; } - synchronized(c.channelSendLock) { - if(c.closeMessageSent) { + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { throw c.getReasonClosed(); } + tm.sendMessage(spr.getPayload()); } try { waitForChannelSuccessOrFailure(c); } - catch(IOException e) { + catch (IOException e) { throw new IOException("PTY request failed", e); } } @@ -594,27 +592,28 @@ int term_width_pixels, int term_height_pixels) throws IOException { PacketWindowChange pwc; - synchronized(c) { - if(c.state != Channel.STATE_OPEN) { + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { throw c.getReasonClosed(); } + pwc = new PacketWindowChange(c.remoteID, term_width_characters, term_height_characters, - term_width_pixels, term_height_pixels); - + term_width_pixels, term_height_pixels); c.successCounter = c.failedCounter = 0; } - synchronized(c.channelSendLock) { - if(c.closeMessageSent) { + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { throw c.getReasonClosed(); } + tm.sendMessage(pwc.getPayload()); } try { waitForChannelSuccessOrFailure(c); } - catch(IOException e) { + catch (IOException e) { throw new IOException("The window-change request failed.", e); } } @@ -623,20 +622,21 @@ String x11AuthenticationCookie, int x11ScreenNumber) throws IOException { PacketSessionX11Request psr; - synchronized(c) { - if(c.state != Channel.STATE_OPEN) { + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { throw c.getReasonClosed(); } + psr = new PacketSessionX11Request(c.remoteID, true, singleConnection, x11AuthenticationProtocol, - x11AuthenticationCookie, x11ScreenNumber); - + x11AuthenticationCookie, x11ScreenNumber); c.successCounter = c.failedCounter = 0; } - synchronized(c.channelSendLock) { - if(c.closeMessageSent) { + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { throw c.getReasonClosed(); } + tm.sendMessage(psr.getPayload()); } @@ -645,7 +645,7 @@ try { waitForChannelSuccessOrFailure(c); } - catch(IOException e) { + catch (IOException e) { throw new IOException("The X11 request failed.", e); } } @@ -653,26 +653,27 @@ public void requestSubSystem(Channel c, String subSystemName) throws IOException { PacketSessionSubsystemRequest ssr; - synchronized(c) { - if(c.state != Channel.STATE_OPEN) { + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { throw c.getReasonClosed(); } + ssr = new PacketSessionSubsystemRequest(c.remoteID, true, subSystemName); - c.successCounter = c.failedCounter = 0; } - synchronized(c.channelSendLock) { - if(c.closeMessageSent) { + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { throw c.getReasonClosed(); } + tm.sendMessage(ssr.getPayload()); } try { waitForChannelSuccessOrFailure(c); } - catch(IOException e) { + catch (IOException e) { throw new IOException("The subsystem request failed.", e); } } @@ -687,19 +688,20 @@ public void requestExecCommand(Channel c, String cmd, String charsetName) throws IOException { PacketSessionExecCommand sm; - synchronized(c) { - if(c.state != Channel.STATE_OPEN) { + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { throw c.getReasonClosed(); } + sm = new PacketSessionExecCommand(c.remoteID, true, cmd, charsetName); - c.successCounter = c.failedCounter = 0; } - synchronized(c.channelSendLock) { - if(c.closeMessageSent) { + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { throw c.getReasonClosed(); } + tm.sendMessage(sm.getPayload()); } @@ -708,7 +710,7 @@ try { waitForChannelSuccessOrFailure(c); } - catch(IOException e) { + catch (IOException e) { throw new IOException("The execute request failed.", e); } } @@ -716,75 +718,73 @@ public void requestShell(Channel c) throws IOException { PacketSessionStartShell sm; - synchronized(c) { - if(c.state != Channel.STATE_OPEN) { + synchronized (c) { + if (c.state != Channel.STATE_OPEN) { throw c.getReasonClosed(); } + sm = new PacketSessionStartShell(c.remoteID, true); - c.successCounter = c.failedCounter = 0; } - synchronized(c.channelSendLock) { - if(c.closeMessageSent) { + synchronized (c.channelSendLock) { + if (c.closeMessageSent) { throw c.getReasonClosed(); } + tm.sendMessage(sm.getPayload()); } try { waitForChannelSuccessOrFailure(c); } - catch(IOException e) { + catch (IOException e) { throw new IOException("The shell request failed.", e); } } public void msgChannelExtendedData(byte[] msg) throws IOException { - if(msg.length <= 13) { + if (msg.length <= 13) { throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_EXTENDED_DATA message has wrong size (%d)", msg.length)); } int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); int dataType = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff); int len = ((msg[9] & 0xff) << 24) | ((msg[10] & 0xff) << 16) | ((msg[11] & 0xff) << 8) | (msg[12] & 0xff); - Channel c = getChannel(id); - if(c == null) { + if (c == null) { throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_EXTENDED_DATA message for non-existent channel " + id); } - if(dataType != Packets.SSH_EXTENDED_DATA_STDERR) { + if (dataType != Packets.SSH_EXTENDED_DATA_STDERR) { throw new PacketFormatException("SSH_MSG_CHANNEL_EXTENDED_DATA message has unknown type (" + dataType + ")"); } - if(len != (msg.length - 13)) { + if (len != (msg.length - 13)) { throw new PacketFormatException("SSH_MSG_CHANNEL_EXTENDED_DATA message has wrong len (calculated " + (msg.length - 13) - + ", got " + len + ")"); + + ", got " + len + ")"); } log.debug("Got SSH_MSG_CHANNEL_EXTENDED_DATA (channel " + id + ", " + len + ")"); - synchronized(c) { - if(c.state == Channel.STATE_CLOSED) { + synchronized (c) { + if (c.state == Channel.STATE_CLOSED) { return; // ignore } - if(c.state != Channel.STATE_OPEN) { + if (c.state != Channel.STATE_OPEN) { throw new PacketTypeException("Got SSH_MSG_CHANNEL_EXTENDED_DATA, but channel is not in correct state (" - + c.state + ")"); + + c.state + ")"); } - if(c.localWindow < len) { + if (c.localWindow < len) { throw new PacketFormatException("Remote sent too much data, does not fit into window."); } c.localWindow -= len; - System.arraycopy(msg, 13, c.stderrBuffer, c.stderrWritepos, len); c.stderrWritepos += len; - c.notifyAll(); } } @@ -801,64 +801,63 @@ long end_time = 0; boolean end_time_set = false; - synchronized(c) { - while(true) { + synchronized (c) { + while (true) { int current_cond = 0; - int stdoutAvail = c.stdoutWritepos - c.stdoutReadpos; int stderrAvail = c.stderrWritepos - c.stderrReadpos; - if(stdoutAvail > 0) { + if (stdoutAvail > 0) { current_cond = current_cond | ChannelCondition.STDOUT_DATA; } - if(stderrAvail > 0) { + if (stderrAvail > 0) { current_cond = current_cond | ChannelCondition.STDERR_DATA; } - if(c.EOF) { + if (c.EOF) { current_cond = current_cond | ChannelCondition.EOF; } - if(c.getExitStatus() != null) { + if (c.getExitStatus() != null) { current_cond = current_cond | ChannelCondition.EXIT_STATUS; } - if(c.getExitSignal() != null) { + if (c.getExitSignal() != null) { current_cond = current_cond | ChannelCondition.EXIT_SIGNAL; } - if(c.state == Channel.STATE_CLOSED) { + if (c.state == Channel.STATE_CLOSED) { return current_cond | ChannelCondition.CLOSED | ChannelCondition.EOF; } - if((current_cond & condition_mask) != 0) { + if ((current_cond & condition_mask) != 0) { return current_cond; } - if(timeout > 0) { - if(!end_time_set) { + if (timeout > 0) { + if (!end_time_set) { end_time = System.currentTimeMillis() + timeout; end_time_set = true; } else { timeout = end_time - System.currentTimeMillis(); - if(timeout <= 0) { + if (timeout <= 0) { return current_cond | ChannelCondition.TIMEOUT; } } } try { - if(timeout > 0) { + if (timeout > 0) { c.wait(timeout); } else { c.wait(); } } - catch(InterruptedException e) { + catch (InterruptedException e) { throw new InterruptedIOException(e.getMessage()); } } @@ -866,10 +865,10 @@ } public int getAvailable(Channel c, boolean extended) throws IOException { - synchronized(c) { + synchronized (c) { int avail; - if(extended) { + if (extended) { avail = c.stderrWritepos - c.stderrReadpos; } else { @@ -886,53 +885,50 @@ int remoteID = 0; int localID = 0; - synchronized(c) { + synchronized (c) { int stdoutAvail = 0; int stderrAvail = 0; - while(true) { + while (true) { /* * Data available? We have to return remaining data even if the * channel is already closed. */ - stdoutAvail = c.stdoutWritepos - c.stdoutReadpos; stderrAvail = c.stderrWritepos - c.stderrReadpos; - if((!extended) && (stdoutAvail != 0)) { + if ((!extended) && (stdoutAvail != 0)) { break; } - if((extended) && (stderrAvail != 0)) { + if ((extended) && (stderrAvail != 0)) { break; } /* Do not wait if more data will never arrive (EOF or CLOSED) */ - if((c.EOF) || (c.state != Channel.STATE_OPEN)) { + if ((c.EOF) || (c.state != Channel.STATE_OPEN)) { return -1; } try { c.wait(); } - catch(InterruptedException e) { + catch (InterruptedException e) { throw new InterruptedIOException(e.getMessage()); } } /* OK, there is some data. Return it. */ - if(!extended) { + if (!extended) { copylen = (stdoutAvail > len) ? len : stdoutAvail; System.arraycopy(c.stdoutBuffer, c.stdoutReadpos, target, off, copylen); c.stdoutReadpos += copylen; - if(c.stdoutReadpos != c.stdoutWritepos) - - { + if (c.stdoutReadpos != c.stdoutWritepos) { System.arraycopy(c.stdoutBuffer, c.stdoutReadpos, c.stdoutBuffer, 0, c.stdoutWritepos - - c.stdoutReadpos); + - c.stdoutReadpos); } c.stdoutWritepos -= c.stdoutReadpos; @@ -943,25 +939,22 @@ System.arraycopy(c.stderrBuffer, c.stderrReadpos, target, off, copylen); c.stderrReadpos += copylen; - if(c.stderrReadpos != c.stderrWritepos) - - { + if (c.stderrReadpos != c.stderrWritepos) { System.arraycopy(c.stderrBuffer, c.stderrReadpos, c.stderrBuffer, 0, c.stderrWritepos - - c.stderrReadpos); + - c.stderrReadpos); } c.stderrWritepos -= c.stderrReadpos; c.stderrReadpos = 0; } - if(c.state != Channel.STATE_OPEN) { + if (c.state != Channel.STATE_OPEN) { return copylen; } - if(c.localWindow < ((Channel.CHANNEL_BUFFER_SIZE + 1) / 2)) { + if (c.localWindow < ((Channel.CHANNEL_BUFFER_SIZE + 1) / 2)) { int minFreeSpace = Math.min(Channel.CHANNEL_BUFFER_SIZE - c.stdoutWritepos, - Channel.CHANNEL_BUFFER_SIZE - c.stderrWritepos); - + Channel.CHANNEL_BUFFER_SIZE - c.stderrWritepos); increment = minFreeSpace - c.localWindow; c.localWindow = minFreeSpace; } @@ -976,23 +969,22 @@ * does not matter in which order they arrive at the server. */ - if(increment > 0) { + if (increment > 0) { log.debug("Sending SSH_MSG_CHANNEL_WINDOW_ADJUST (channel " + localID + ", " + increment + ")"); - synchronized(c.channelSendLock) { + synchronized (c.channelSendLock) { byte[] msg = c.msgWindowAdjust; - msg[0] = Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST; - msg[1] = (byte) (remoteID >> 24); - msg[2] = (byte) (remoteID >> 16); - msg[3] = (byte) (remoteID >> 8); - msg[4] = (byte) (remoteID); - msg[5] = (byte) (increment >> 24); - msg[6] = (byte) (increment >> 16); - msg[7] = (byte) (increment >> 8); - msg[8] = (byte) (increment); + msg[1] = (byte)(remoteID >> 24); + msg[2] = (byte)(remoteID >> 16); + msg[3] = (byte)(remoteID >> 8); + msg[4] = (byte)(remoteID); + msg[5] = (byte)(increment >> 24); + msg[6] = (byte)(increment >> 16); + msg[7] = (byte)(increment >> 8); + msg[8] = (byte)(increment); - if(!c.closeMessageSent) { + if (!c.closeMessageSent) { tm.sendMessage(msg); } } @@ -1002,193 +994,170 @@ } public void msgChannelData(byte[] msg) throws IOException { - if(msg.length <= 9) { + if (msg.length <= 9) { throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_DATA message has wrong size (%d)", msg.length)); } int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); int len = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff); - Channel c = getChannel(id); - if(c == null) { + if (c == null) { throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_DATA message for non-existent channel " + id); } - if(len != (msg.length - 9)) { + if (len != (msg.length - 9)) { throw new PacketFormatException("SSH_MSG_CHANNEL_DATA message has wrong len (calculated " + (msg.length - 9) + ", got " - + len + ")"); + + len + ")"); } log.debug("Got SSH_MSG_CHANNEL_DATA (channel " + id + ", " + len + ")"); - synchronized(c) { - if(c.state == Channel.STATE_CLOSED) { + synchronized (c) { + if (c.state == Channel.STATE_CLOSED) { return; // ignore } - if(c.state != Channel.STATE_OPEN) { + if (c.state != Channel.STATE_OPEN) { throw new PacketTypeException("Got SSH_MSG_CHANNEL_DATA, but channel is not in correct state (" + c.state + ")"); } - if(c.localWindow < len) { + if (c.localWindow < len) { throw new IOException("Remote sent too much data, does not fit into window."); } c.localWindow -= len; - System.arraycopy(msg, 9, c.stdoutBuffer, c.stdoutWritepos, len); c.stdoutWritepos += len; - c.notifyAll(); } } public void msgChannelWindowAdjust(byte[] msg) throws IOException { - if(msg.length != 9) { + if (msg.length != 9) { throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_WINDOW_ADJUST message has wrong size (%d)", msg.length)); } int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); int windowChange = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff); - Channel c = getChannel(id); - if(c == null) { + if (c == null) { throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_WINDOW_ADJUST message for non-existent channel " + id); } - synchronized(c) { + synchronized (c) { final long huge = 0xFFFFffffL; /* 2^32 - 1 */ - c.remoteWindow += (windowChange & huge); /* avoid sign extension */ - /* TODO - is this a good heuristic? */ + /* TODO - is this a good heuristic? */ - if((c.remoteWindow > huge)) { + if ((c.remoteWindow > huge)) { c.remoteWindow = huge; } c.notifyAll(); } - log.debug("Got SSH_MSG_CHANNEL_WINDOW_ADJUST (channel " + id + ", " + windowChange + ")"); } public void msgChannelOpen(byte[] msg) throws IOException { TypesReader tr = new TypesReader(msg); - tr.readByte(); // skip packet type String channelType = tr.readString(); int remoteID = tr.readUINT32(); /* sender channel */ int remoteWindow = tr.readUINT32(); /* initial window size */ int remoteMaxPacketSize = tr.readUINT32(); /* maximum packet size */ - if("x11".equals(channelType)) { - synchronized(x11_magic_cookies) { + if ("x11".equals(channelType)) { + synchronized (x11_magic_cookies) { /* If we did not request X11 forwarding, then simply ignore this bogus request. */ - - if(x11_magic_cookies.size() == 0) { + if (x11_magic_cookies.size() == 0) { PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(remoteID, Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, "X11 forwarding not activated", ""); - tm.sendAsynchronousMessage(pcof.getPayload()); - log.warning("Unexpected X11 request, denying it!"); - return; } } String remoteOriginatorAddress = tr.readString(); int remoteOriginatorPort = tr.readUINT32(); - Channel c = new Channel(this); - synchronized(c) { + synchronized (c) { c.remoteID = remoteID; c.remoteWindow = remoteWindow & 0xFFFFffffL; /* properly convert UINT32 to long */ c.remoteMaxPacketSize = remoteMaxPacketSize; c.localID = addChannel(c); } - /* + /* * The open confirmation message will be sent from another thread - */ - + */ RemoteX11AcceptThread rxat = new RemoteX11AcceptThread(c, remoteOriginatorAddress, remoteOriginatorPort); rxat.setDaemon(true); rxat.start(); - return; } - if("forwarded-tcpip".equals(channelType)) { + if ("forwarded-tcpip".equals(channelType)) { String remoteConnectedAddress = tr.readString(); /* address that was connected */ int remoteConnectedPort = tr.readUINT32(); /* port that was connected */ String remoteOriginatorAddress = tr.readString(); /* originator IP address */ int remoteOriginatorPort = tr.readUINT32(); /* originator port */ - RemoteForwardingData rfd; - synchronized(remoteForwardings) { + synchronized (remoteForwardings) { rfd = remoteForwardings.get(remoteConnectedPort); } - if(rfd == null) { + if (rfd == null) { PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(remoteID, Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, "No thanks, unknown port in forwarded-tcpip request", ""); - - /* Always try to be polite. */ - + /* Always try to be polite. */ tm.sendAsynchronousMessage(pcof.getPayload()); - log.debug("Unexpected forwarded-tcpip request, denying it!"); - return; } Channel c = new Channel(this); - synchronized(c) { + synchronized (c) { c.remoteID = remoteID; c.remoteWindow = remoteWindow & 0xFFFFffffL; /* convert UINT32 to long */ c.remoteMaxPacketSize = remoteMaxPacketSize; c.localID = addChannel(c); } - /* - * The open confirmation message will be sent from another thread. - */ - + /* + * The open confirmation message will be sent from another thread. + */ RemoteAcceptThread rat = new RemoteAcceptThread(c, remoteConnectedAddress, remoteConnectedPort, remoteOriginatorAddress, remoteOriginatorPort, rfd.targetAddress, rfd.targetPort); - rat.setDaemon(true); rat.start(); - return; } - if((server_state != null) && ("session".equals(channelType))) { + if ((server_state != null) && ("session".equals(channelType))) { ServerConnectionCallback cb; - synchronized(server_state) { + synchronized (server_state) { cb = server_state.cb_conn; } - if(cb == null) { + if (cb == null) { tm.sendAsynchronousMessage(new PacketChannelOpenFailure(remoteID, Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, - "Sessions are currently not enabled", "en").getPayload()); - + "Sessions are currently not enabled", "en").getPayload()); return; } final Channel c = new Channel(this); - synchronized(c) { + synchronized (c) { c.remoteID = remoteID; c.remoteWindow = remoteWindow & 0xFFFFffffL; /* convert UINT32 to long */ c.remoteMaxPacketSize = remoteMaxPacketSize; @@ -1199,22 +1168,15 @@ PacketChannelOpenConfirmation pcoc = new PacketChannelOpenConfirmation(c.remoteID, c.localID, c.localWindow, c.localMaxPacketSize); - tm.sendAsynchronousMessage(pcoc.getPayload()); - c.ss.sscb = cb.acceptSession(c.ss); - return; } - /* Tell the server that we have no idea what it is talking about */ - + /* Tell the server that we have no idea what it is talking about */ PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(remoteID, Packets.SSH_OPEN_UNKNOWN_CHANNEL_TYPE, "Unknown channel type", ""); - tm.sendAsynchronousMessage(pcof.getPayload()); - - log.warning("The peer tried to open an unsupported channel type (" + channelType + ")"); } @@ -1226,55 +1188,51 @@ public void msgChannelRequest(byte[] msg) throws IOException { TypesReader tr = new TypesReader(msg); - tr.readByte(); // skip packet type int id = tr.readUINT32(); - Channel c = getChannel(id); - if(c == null) { + if (c == null) { throw new IOException("Unexpected SSH_MSG_CHANNEL_REQUEST message for non-existent channel " + id); } ServerSessionImpl server_session = null; - if(server_state != null) { - synchronized(c) { + if (server_state != null) { + synchronized (c) { server_session = c.ss; } } String type = tr.readString("US-ASCII"); boolean wantReply = tr.readBoolean(); - log.debug("Got SSH_MSG_CHANNEL_REQUEST (channel " + id + ", '" + type + "')"); - if(type.equals("exit-status")) { - if(wantReply) { + if (type.equals("exit-status")) { + if (wantReply) { throw new IOException( - "Badly formatted SSH_MSG_CHANNEL_REQUEST exit-status message, 'want reply' is true"); + "Badly formatted SSH_MSG_CHANNEL_REQUEST exit-status message, 'want reply' is true"); } int exit_status = tr.readUINT32(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); } - synchronized(c) { + synchronized (c) { c.exit_status = exit_status; c.notifyAll(); } log.debug("Got EXIT STATUS (channel " + id + ", status " + exit_status + ")"); - return; } - if((server_state == null) && (type.equals("exit-signal"))) { - if(wantReply) { + if ((server_state == null) && (type.equals("exit-signal"))) { + if (wantReply) { throw new IOException( - "Badly formatted SSH_MSG_CHANNEL_REQUEST exit-signal message, 'want reply' is true"); + "Badly formatted SSH_MSG_CHANNEL_REQUEST exit-signal message, 'want reply' is true"); } String signame = tr.readString("US-ASCII"); @@ -1282,23 +1240,21 @@ tr.readString(); tr.readString(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); } - synchronized(c) { + synchronized (c) { c.exit_signal = signame; c.notifyAll(); } log.debug("Got EXIT SIGNAL (channel " + id + ", signal " + signame + ")"); - return; } - if((server_session != null) && (type.equals("pty-req"))) { + if ((server_session != null) && (type.equals("pty-req"))) { PtySettings pty = new PtySettings(); - pty.term = tr.readString(); pty.term_width_characters = tr.readUINT32(); pty.term_height_characters = tr.readUINT32(); @@ -1306,20 +1262,19 @@ pty.term_height_pixels = tr.readUINT32(); pty.terminal_modes = tr.readByteString(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); } Runnable run_after_sending_success = null; - ServerSessionCallback sscb = server_session.getServerSessionCallback(); - if(sscb != null) { + if (sscb != null) { run_after_sending_success = sscb.requestPtyReq(server_session, pty); } - if(wantReply) { - if(run_after_sending_success != null) { + if (wantReply) { + if (run_after_sending_success != null) { tm.sendAsynchronousMessage(new PacketChannelSuccess(c.remoteID).getPayload()); } else { @@ -1327,27 +1282,27 @@ } } - if(run_after_sending_success != null) { + if (run_after_sending_success != null) { runAsync(run_after_sending_success); } return; } - if((server_session != null) && (type.equals("shell"))) { - if(tr.remain() != 0) { + if ((server_session != null) && (type.equals("shell"))) { + if (tr.remain() != 0) { throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); } Runnable run_after_sending_success = null; ServerSessionCallback sscb = server_session.getServerSessionCallback(); - if(sscb != null) { + if (sscb != null) { run_after_sending_success = sscb.requestShell(server_session); } - if(wantReply) { - if(run_after_sending_success != null) { + if (wantReply) { + if (run_after_sending_success != null) { tm.sendAsynchronousMessage(new PacketChannelSuccess(c.remoteID).getPayload()); } else { @@ -1355,29 +1310,29 @@ } } - if(run_after_sending_success != null) { + if (run_after_sending_success != null) { runAsync(run_after_sending_success); } return; } - if((server_session != null) && (type.equals("exec"))) { + if ((server_session != null) && (type.equals("exec"))) { String command = tr.readString(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); } Runnable run_after_sending_success = null; ServerSessionCallback sscb = server_session.getServerSessionCallback(); - if(sscb != null) { + if (sscb != null) { run_after_sending_success = sscb.requestExec(server_session, command); } - if(wantReply) { - if(run_after_sending_success != null) { + if (wantReply) { + if (run_after_sending_success != null) { tm.sendAsynchronousMessage(new PacketChannelSuccess(c.remoteID).getPayload()); } else { @@ -1385,18 +1340,18 @@ } } - if(run_after_sending_success != null) { + if (run_after_sending_success != null) { runAsync(run_after_sending_success); } return; } - /* We simply ignore unknown channel requests, however, if the server wants a reply, - * then we signal that we have no idea what it is about. - */ + /* We simply ignore unknown channel requests, however, if the server wants a reply, + * then we signal that we have no idea what it is about. + */ - if(wantReply) { + if (wantReply) { tm.sendAsynchronousMessage(new PacketChannelFailure(c.remoteID).getPayload()); } @@ -1404,19 +1359,18 @@ } public void msgChannelEOF(byte[] msg) throws IOException { - if(msg.length != 5) { + if (msg.length != 5) { throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_EOF message has wrong size (%d)", msg.length)); } int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); - Channel c = getChannel(id); - if(c == null) { + if (c == null) { throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_EOF message for non-existent channel " + id); } - synchronized(c) { + synchronized (c) { c.EOF = true; c.notifyAll(); } @@ -1425,26 +1379,23 @@ } public void msgChannelClose(byte[] msg) throws IOException { - if(msg.length != 5) { + if (msg.length != 5) { throw new PacketFormatException("SSH_MSG_CHANNEL_CLOSE message has wrong size (" + msg.length + ")"); } int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); - Channel c = getChannel(id); - if(c == null) { + if (c == null) { throw new IOException("Unexpected SSH_MSG_CHANNEL_CLOSE message for non-existent channel " + id); } - synchronized(c) { + synchronized (c) { c.EOF = true; c.state = Channel.STATE_CLOSED; c.setReasonClosed(new ChannelClosedException("Close requested by remote")); c.closeMessageRecv = true; - removeChannel(c.localID); - c.notifyAll(); } @@ -1452,19 +1403,18 @@ } public void msgChannelSuccess(byte[] msg) throws IOException { - if(msg.length != 5) { + if (msg.length != 5) { throw new PacketFormatException("SSH_MSG_CHANNEL_SUCCESS message has wrong size (" + msg.length + ")"); } int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); - Channel c = getChannel(id); - if(c == null) { + if (c == null) { throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_SUCCESS message for non-existent channel " + id); } - synchronized(c) { + synchronized (c) { c.successCounter++; c.notifyAll(); } @@ -1473,19 +1423,18 @@ } public void msgChannelFailure(byte[] msg) throws IOException { - if(msg.length != 5) { + if (msg.length != 5) { throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_FAILURE message has wrong size (%d)", msg.length)); } int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); - Channel c = getChannel(id); - if(c == null) { + if (c == null) { throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_FAILURE message for non-existent channel " + id); } - synchronized(c) { + synchronized (c) { c.failedCounter++; c.notifyAll(); } @@ -1495,18 +1444,17 @@ public void msgChannelOpenConfirmation(byte[] msg) throws IOException { PacketChannelOpenConfirmation sm = new PacketChannelOpenConfirmation(msg); - Channel c = getChannel(sm.getRecipientChannelID()); - if(c == null) { + if (c == null) { throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION message for non-existent channel " - + sm.getRecipientChannelID()); + + sm.getRecipientChannelID()); } - synchronized(c) { - if(c.state != Channel.STATE_OPENING) { + synchronized (c) { + if (c.state != Channel.STATE_OPENING) { throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION message for channel " - + sm.getRecipientChannelID()); + + sm.getRecipientChannelID()); } c.remoteID = sm.getSenderChannelID(); @@ -1517,43 +1465,44 @@ } log.debug("Got SSH_MSG_CHANNEL_OPEN_CONFIRMATION (channel " + sm.getRecipientChannelID() + " / remote: " - + sm.getSenderChannelID() + ")"); + + sm.getSenderChannelID() + ")"); } public void msgChannelOpenFailure(byte[] msg) throws IOException { - if(msg.length < 5) { + if (msg.length < 5) { throw new PacketFormatException(String.format("SSH_MSG_CHANNEL_OPEN_FAILURE message has wrong size (%d)", msg.length)); } TypesReader tr = new TypesReader(msg); - tr.readByte(); // skip packet type int id = tr.readUINT32(); /* sender channel */ - Channel c = getChannel(id); - if(c == null) { + if (c == null) { throw new PacketTypeException("Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE message for non-existent channel " + id); } int reasonCode = tr.readUINT32(); String description = tr.readString("UTF-8"); - String reasonCodeSymbolicName; - switch(reasonCode) { + switch (reasonCode) { case 1: reasonCodeSymbolicName = "SSH_OPEN_ADMINISTRATIVELY_PROHIBITED"; break; + case 2: reasonCodeSymbolicName = "SSH_OPEN_CONNECT_FAILED"; break; + case 3: reasonCodeSymbolicName = "SSH_OPEN_UNKNOWN_CHANNEL_TYPE"; break; + case 4: reasonCodeSymbolicName = "SSH_OPEN_RESOURCE_SHORTAGE"; break; + default: reasonCodeSymbolicName = "UNKNOWN REASON CODE (" + reasonCode + ")"; } @@ -1561,20 +1510,21 @@ StringBuilder descriptionBuffer = new StringBuilder(); descriptionBuffer.append(description); - for(int i = 0; i < descriptionBuffer.length(); i++) { + for (int i = 0; i < descriptionBuffer.length(); i++) { char cc = descriptionBuffer.charAt(i); - if((cc >= 32) && (cc <= 126)) { + if ((cc >= 32) && (cc <= 126)) { continue; } + descriptionBuffer.setCharAt(i, '\uFFFD'); } - synchronized(c) { + synchronized (c) { c.EOF = true; c.state = Channel.STATE_CLOSED; c.setReasonClosed(new ChannelClosedException(String.format("The server refused to open the channel (%s, '%s')", - reasonCodeSymbolicName, descriptionBuffer.toString()))); + reasonCodeSymbolicName, descriptionBuffer.toString()))); c.notifyAll(); } @@ -1582,28 +1532,24 @@ } public void msgGlobalRequest(byte[] msg) throws IOException { - /* Currently we do not support any kind of global request */ - + /* Currently we do not support any kind of global request */ TypesReader tr = new TypesReader(msg); - tr.readByte(); // skip packet type String requestName = tr.readString(); boolean wantReply = tr.readBoolean(); - if(wantReply) { + if (wantReply) { byte[] reply_failure = new byte[1]; reply_failure[0] = Packets.SSH_MSG_REQUEST_FAILURE; - tm.sendAsynchronousMessage(reply_failure); } - /* We do not clean up the requestName String - that is OK for debug */ - + /* We do not clean up the requestName String - that is OK for debug */ log.debug("Got SSH_MSG_GLOBAL_REQUEST (" + requestName + ")"); } public void msgGlobalSuccess() throws IOException { - synchronized(channels) { + synchronized (channels) { globalSuccessCounter++; channels.notifyAll(); } @@ -1612,7 +1558,7 @@ } public void msgGlobalFailure() throws IOException { - synchronized(channels) { + synchronized (channels) { globalFailedCounter++; channels.notifyAll(); } @@ -1623,18 +1569,19 @@ public void handleFailure(final IOException failure) { log.debug("HandleMessage: got shutdown"); - synchronized(listenerThreads) { - for(IChannelWorkerThread lat : listenerThreads) { + synchronized (listenerThreads) { + for (IChannelWorkerThread lat : listenerThreads) { lat.stopWorking(); } + listenerThreadsAllowed = false; } - synchronized(channels) { + synchronized (channels) { shutdown = true; - for(Channel c : channels) { - synchronized(c) { + for (Channel c : channels) { + synchronized (c) { c.EOF = true; c.state = Channel.STATE_CLOSED; c.setReasonClosed(failure); @@ -1642,55 +1589,70 @@ c.notifyAll(); } } + channels.clear(); channels.notifyAll(); /* Notify global response waiters */ } } public void handleMessage(byte[] msg) throws IOException { - switch(msg[0]) { + switch (msg[0]) { case Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION: msgChannelOpenConfirmation(msg); break; + case Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST: msgChannelWindowAdjust(msg); break; + case Packets.SSH_MSG_CHANNEL_DATA: msgChannelData(msg); break; + case Packets.SSH_MSG_CHANNEL_EXTENDED_DATA: msgChannelExtendedData(msg); break; + case Packets.SSH_MSG_CHANNEL_REQUEST: msgChannelRequest(msg); break; + case Packets.SSH_MSG_CHANNEL_EOF: msgChannelEOF(msg); break; + case Packets.SSH_MSG_CHANNEL_OPEN: msgChannelOpen(msg); break; + case Packets.SSH_MSG_CHANNEL_CLOSE: msgChannelClose(msg); break; + case Packets.SSH_MSG_CHANNEL_SUCCESS: msgChannelSuccess(msg); break; + case Packets.SSH_MSG_CHANNEL_FAILURE: msgChannelFailure(msg); break; + case Packets.SSH_MSG_CHANNEL_OPEN_FAILURE: msgChannelOpenFailure(msg); break; + case Packets.SSH_MSG_GLOBAL_REQUEST: msgGlobalRequest(msg); break; + case Packets.SSH_MSG_REQUEST_SUCCESS: msgGlobalSuccess(); break; + case Packets.SSH_MSG_REQUEST_FAILURE: msgGlobalFailure(); break; + default: throw new PacketTypeException(msg[0]); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/ChannelOutputStream.java --- a/src/ch/ethz/ssh2/channel/ChannelOutputStream.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/ChannelOutputStream.java Wed Jul 30 14:16:58 2014 -0700 @@ -9,71 +9,61 @@ /** * ChannelOutputStream. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public final class ChannelOutputStream extends OutputStream -{ - Channel c; +public final class ChannelOutputStream extends OutputStream { + Channel c; - boolean isClosed = false; - - ChannelOutputStream(Channel c) - { - this.c = c; - } + boolean isClosed = false; + + ChannelOutputStream(Channel c) { + this.c = c; + } - @Override - public void write(int b) throws IOException - { - byte[] buff = new byte[1]; - - buff[0] = (byte) b; - - write(buff, 0, 1); - } + @Override + public void write(int b) throws IOException { + byte[] buff = new byte[1]; + buff[0] = (byte) b; + write(buff, 0, 1); + } - @Override - public void close() throws IOException - { - if (isClosed == false) - { - isClosed = true; - c.cm.sendEOF(c); - } - } + @Override + public void close() throws IOException { + if (isClosed == false) { + isClosed = true; + c.cm.sendEOF(c); + } + } - @Override - public void flush() throws IOException - { - if (isClosed) - throw new IOException("This OutputStream is closed."); + @Override + public void flush() throws IOException { + if (isClosed) + throw new IOException("This OutputStream is closed."); - /* This is a no-op, since this stream is unbuffered */ - } + /* This is a no-op, since this stream is unbuffered */ + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + if (isClosed) + throw new IOException("This OutputStream is closed."); - @Override - public void write(byte[] b, int off, int len) throws IOException - { - if (isClosed) - throw new IOException("This OutputStream is closed."); - - if (b == null) - throw new NullPointerException(); + if (b == null) + throw new NullPointerException(); - if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) - throw new IndexOutOfBoundsException(); + if ((off < 0) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0) || (off > b.length)) + throw new IndexOutOfBoundsException(); + + if (len == 0) + return; - if (len == 0) - return; - - c.cm.sendData(c, b, off, len); - } + c.cm.sendData(c, b, off, len); + } - @Override - public void write(byte[] b) throws IOException - { - write(b, 0, b.length); - } + @Override + public void write(byte[] b) throws IOException { + write(b, 0, b.length); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/IChannelWorkerThread.java --- a/src/ch/ethz/ssh2/channel/IChannelWorkerThread.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/IChannelWorkerThread.java Wed Jul 30 14:16:58 2014 -0700 @@ -6,11 +6,10 @@ /** * IChannelWorkerThread. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -interface IChannelWorkerThread -{ - public void stopWorking(); +interface IChannelWorkerThread { + public void stopWorking(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/LocalAcceptThread.java --- a/src/ch/ethz/ssh2/channel/LocalAcceptThread.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/LocalAcceptThread.java Wed Jul 30 14:16:58 2014 -0700 @@ -11,133 +11,107 @@ /** * LocalAcceptThread. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class LocalAcceptThread extends Thread implements IChannelWorkerThread -{ - ChannelManager cm; - String host_to_connect; - int port_to_connect; +public class LocalAcceptThread extends Thread implements IChannelWorkerThread { + ChannelManager cm; + String host_to_connect; + int port_to_connect; - final ServerSocket ss; + final ServerSocket ss; - public LocalAcceptThread(ChannelManager cm, int local_port, String host_to_connect, int port_to_connect) - throws IOException - { - this.cm = cm; - this.host_to_connect = host_to_connect; - this.port_to_connect = port_to_connect; - - ss = new ServerSocket(local_port); - } + public LocalAcceptThread(ChannelManager cm, int local_port, String host_to_connect, int port_to_connect) + throws IOException { + this.cm = cm; + this.host_to_connect = host_to_connect; + this.port_to_connect = port_to_connect; + ss = new ServerSocket(local_port); + } - public LocalAcceptThread(ChannelManager cm, InetSocketAddress localAddress, String host_to_connect, - int port_to_connect) throws IOException - { - this.cm = cm; - this.host_to_connect = host_to_connect; - this.port_to_connect = port_to_connect; - - ss = new ServerSocket(); - ss.bind(localAddress); - } + public LocalAcceptThread(ChannelManager cm, InetSocketAddress localAddress, String host_to_connect, + int port_to_connect) throws IOException { + this.cm = cm; + this.host_to_connect = host_to_connect; + this.port_to_connect = port_to_connect; + ss = new ServerSocket(); + ss.bind(localAddress); + } - public ServerSocket getServerSocket() - { - return ss; - } - - @Override - public void run() - { - try - { - cm.registerThread(this); - } - catch (IOException e) - { - stopWorking(); - return; - } + public ServerSocket getServerSocket() { + return ss; + } - while (true) - { - Socket s = null; + @Override + public void run() { + try { + cm.registerThread(this); + } + catch (IOException e) { + stopWorking(); + return; + } - try - { - s = ss.accept(); - } - catch (IOException e) - { - stopWorking(); - return; - } + while (true) { + Socket s = null; + + try { + s = ss.accept(); + } + catch (IOException e) { + stopWorking(); + return; + } - Channel cn = null; - StreamForwarder r2l = null; - StreamForwarder l2r = null; - - try - { - /* This may fail, e.g., if the remote port is closed (in optimistic terms: not open yet) */ - - cn = cm.openDirectTCPIPChannel(host_to_connect, port_to_connect, s.getInetAddress().getHostAddress(), s - .getPort()); + Channel cn = null; + StreamForwarder r2l = null; + StreamForwarder l2r = null; - } - catch (IOException e) - { - /* Simply close the local socket and wait for the next incoming connection */ + try { + /* This may fail, e.g., if the remote port is closed (in optimistic terms: not open yet) */ + cn = cm.openDirectTCPIPChannel(host_to_connect, port_to_connect, s.getInetAddress().getHostAddress(), s + .getPort()); + } + catch (IOException e) { + /* Simply close the local socket and wait for the next incoming connection */ + try { + s.close(); + } + catch (IOException ignore) { + } - try - { - s.close(); - } - catch (IOException ignore) - { - } - - continue; - } + continue; + } - try - { - r2l = new StreamForwarder(cn, null, null, cn.stdoutStream, s.getOutputStream(), "RemoteToLocal"); - l2r = new StreamForwarder(cn, r2l, s, s.getInputStream(), cn.stdinStream, "LocalToRemote"); - } - catch (IOException e) - { - try - { - /* This message is only visible during debugging, since we discard the channel immediatelly */ - cn.cm.closeChannel(cn, e, true); - } - catch (IOException ignore) - { - } + try { + r2l = new StreamForwarder(cn, null, null, cn.stdoutStream, s.getOutputStream(), "RemoteToLocal"); + l2r = new StreamForwarder(cn, r2l, s, s.getInputStream(), cn.stdinStream, "LocalToRemote"); + } + catch (IOException e) { + try { + /* This message is only visible during debugging, since we discard the channel immediatelly */ + cn.cm.closeChannel(cn, e, true); + } + catch (IOException ignore) { + } - continue; - } + continue; + } - r2l.setDaemon(true); - l2r.setDaemon(true); - r2l.start(); - l2r.start(); - } - } + r2l.setDaemon(true); + l2r.setDaemon(true); + r2l.start(); + l2r.start(); + } + } - public void stopWorking() - { - try - { - /* This will lead to an IOException in the ss.accept() call */ - ss.close(); - } - catch (IOException ignored) - { - } - } + public void stopWorking() { + try { + /* This will lead to an IOException in the ss.accept() call */ + ss.close(); + } + catch (IOException ignored) { + } + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/RemoteAcceptThread.java --- a/src/ch/ethz/ssh2/channel/RemoteAcceptThread.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/RemoteAcceptThread.java Wed Jul 30 14:16:58 2014 -0700 @@ -15,91 +15,74 @@ * @author Christian Plattner * @version $Id: RemoteAcceptThread.java 119 2014-04-12 20:30:58Z dkocher@sudo.ch $ */ -public class RemoteAcceptThread extends Thread -{ - private static final Logger log = Logger.getLogger(RemoteAcceptThread.class); +public class RemoteAcceptThread extends Thread { + private static final Logger log = Logger.getLogger(RemoteAcceptThread.class); - Channel c; + Channel c; - String remoteConnectedAddress; - int remoteConnectedPort; - String remoteOriginatorAddress; - int remoteOriginatorPort; - String targetAddress; - int targetPort; - - Socket s; + String remoteConnectedAddress; + int remoteConnectedPort; + String remoteOriginatorAddress; + int remoteOriginatorPort; + String targetAddress; + int targetPort; - public RemoteAcceptThread(Channel c, String remoteConnectedAddress, int remoteConnectedPort, - String remoteOriginatorAddress, int remoteOriginatorPort, String targetAddress, int targetPort) - { - this.c = c; - this.remoteConnectedAddress = remoteConnectedAddress; - this.remoteConnectedPort = remoteConnectedPort; - this.remoteOriginatorAddress = remoteOriginatorAddress; - this.remoteOriginatorPort = remoteOriginatorPort; - this.targetAddress = targetAddress; - this.targetPort = targetPort; + Socket s; - log.debug("RemoteAcceptThread: " + remoteConnectedAddress + "/" + remoteConnectedPort + ", R: " - + remoteOriginatorAddress + "/" + remoteOriginatorPort); - } - - @Override - public void run() - { - try - { - c.cm.sendOpenConfirmation(c); - - s = new Socket(targetAddress, targetPort); - - StreamForwarder r2l = new StreamForwarder(c, null, null, c.getStdoutStream(), s.getOutputStream(), - "RemoteToLocal"); - StreamForwarder l2r = new StreamForwarder(c, null, null, s.getInputStream(), c.getStdinStream(), - "LocalToRemote"); + public RemoteAcceptThread(Channel c, String remoteConnectedAddress, int remoteConnectedPort, + String remoteOriginatorAddress, int remoteOriginatorPort, String targetAddress, int targetPort) { + this.c = c; + this.remoteConnectedAddress = remoteConnectedAddress; + this.remoteConnectedPort = remoteConnectedPort; + this.remoteOriginatorAddress = remoteOriginatorAddress; + this.remoteOriginatorPort = remoteOriginatorPort; + this.targetAddress = targetAddress; + this.targetPort = targetPort; + log.debug("RemoteAcceptThread: " + remoteConnectedAddress + "/" + remoteConnectedPort + ", R: " + + remoteOriginatorAddress + "/" + remoteOriginatorPort); + } - /* No need to start two threads, one can be executed in the current thread */ - - r2l.setDaemon(true); - r2l.start(); - l2r.run(); + @Override + public void run() { + try { + c.cm.sendOpenConfirmation(c); + s = new Socket(targetAddress, targetPort); + StreamForwarder r2l = new StreamForwarder(c, null, null, c.getStdoutStream(), s.getOutputStream(), + "RemoteToLocal"); + StreamForwarder l2r = new StreamForwarder(c, null, null, s.getInputStream(), c.getStdinStream(), + "LocalToRemote"); + /* No need to start two threads, one can be executed in the current thread */ + r2l.setDaemon(true); + r2l.start(); + l2r.run(); - while (r2l.isAlive()) - { - try - { - r2l.join(); - } - catch (InterruptedException ignored) - { - } - } - - /* If the channel is already closed, then this is a no-op */ + while (r2l.isAlive()) { + try { + r2l.join(); + } + catch (InterruptedException ignored) { + } + } - c.cm.closeChannel(c, "EOF on both streams reached.", true); - s.close(); - } - catch (IOException e) - { - log.warning("IOException in proxy code: " + e.getMessage()); + /* If the channel is already closed, then this is a no-op */ + c.cm.closeChannel(c, "EOF on both streams reached.", true); + s.close(); + } + catch (IOException e) { + log.warning("IOException in proxy code: " + e.getMessage()); - try - { - c.cm.closeChannel(c, e, true); - } - catch (IOException ignored) - { - } - try - { - if (s != null) - s.close(); - } - catch (IOException ignored) - { - } - } - } + try { + c.cm.closeChannel(c, e, true); + } + catch (IOException ignored) { + } + + try { + if (s != null) + s.close(); + } + catch (IOException ignored) { + } + } + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/RemoteForwardingData.java --- a/src/ch/ethz/ssh2/channel/RemoteForwardingData.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/RemoteForwardingData.java Wed Jul 30 14:16:58 2014 -0700 @@ -6,15 +6,14 @@ /** * RemoteForwardingData. Data about a requested remote forwarding. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class RemoteForwardingData -{ - public String bindAddress; - public int bindPort; +public class RemoteForwardingData { + public String bindAddress; + public int bindPort; - String targetAddress; - int targetPort; + String targetAddress; + int targetPort; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/RemoteX11AcceptThread.java --- a/src/ch/ethz/ssh2/channel/RemoteX11AcceptThread.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/RemoteX11AcceptThread.java Wed Jul 30 14:16:58 2014 -0700 @@ -18,229 +18,194 @@ * @author Christian Plattner * @version $Id: RemoteX11AcceptThread.java 119 2014-04-12 20:30:58Z dkocher@sudo.ch $ */ -public class RemoteX11AcceptThread extends Thread -{ - private static final Logger log = Logger.getLogger(RemoteX11AcceptThread.class); - - Channel c; - - String remoteOriginatorAddress; - int remoteOriginatorPort; +public class RemoteX11AcceptThread extends Thread { + private static final Logger log = Logger.getLogger(RemoteX11AcceptThread.class); - Socket s; + Channel c; - public RemoteX11AcceptThread(Channel c, String remoteOriginatorAddress, int remoteOriginatorPort) - { - this.c = c; - this.remoteOriginatorAddress = remoteOriginatorAddress; - this.remoteOriginatorPort = remoteOriginatorPort; - } + String remoteOriginatorAddress; + int remoteOriginatorPort; - @Override - public void run() - { - try - { - /* Send Open Confirmation */ - - c.cm.sendOpenConfirmation(c); - - /* Read startup packet from client */ + Socket s; - OutputStream remote_os = c.getStdinStream(); - InputStream remote_is = c.getStdoutStream(); - - /* The following code is based on the protocol description given in: - * Scheifler/Gettys, - * X Windows System: Core and Extension Protocols: - * X Version 11, Releases 6 and 6.1 ISBN 1-55558-148-X - * (from the ETH library - after being here for almost ten - * years one of the few books I borrowed... sad but true =) - */ + public RemoteX11AcceptThread(Channel c, String remoteOriginatorAddress, int remoteOriginatorPort) { + this.c = c; + this.remoteOriginatorAddress = remoteOriginatorAddress; + this.remoteOriginatorPort = remoteOriginatorPort; + } - /* - * Client startup: - * - * 1 0X42 MSB first/0x6c lSB first - byteorder - * 1 - unused - * 2 card16 - protocol-major-version - * 2 card16 - protocol-minor-version - * 2 n - lenght of authorization-protocol-name - * 2 d - lenght of authorization-protocol-data - * 2 - unused - * string8 - authorization-protocol-name - * p - unused, p=pad(n) - * string8 - authorization-protocol-data - * q - unused, q=pad(d) - * - * pad(X) = (4 - (X mod 4)) mod 4 - * - * Server response: - * - * 1 (0 failed, 2 authenticate, 1 success) - * ... - * - */ - - /* Later on we will simply forward the first 6 header bytes to the "real" X11 server */ - - byte[] header = new byte[6]; - - if (remote_is.read(header) != 6) - throw new IOException("Unexpected EOF on X11 startup!"); - - if ((header[0] != 0x42) && (header[0] != 0x6c)) // 0x42 MSB first, 0x6C LSB first - throw new IOException("Unknown endian format in X11 message!"); + @Override + public void run() { + try { + /* Send Open Confirmation */ + c.cm.sendOpenConfirmation(c); + /* Read startup packet from client */ + OutputStream remote_os = c.getStdinStream(); + InputStream remote_is = c.getStdoutStream(); + /* The following code is based on the protocol description given in: + * Scheifler/Gettys, + * X Windows System: Core and Extension Protocols: + * X Version 11, Releases 6 and 6.1 ISBN 1-55558-148-X + * (from the ETH library - after being here for almost ten + * years one of the few books I borrowed... sad but true =) + */ + /* + * Client startup: + * + * 1 0X42 MSB first/0x6c lSB first - byteorder + * 1 - unused + * 2 card16 - protocol-major-version + * 2 card16 - protocol-minor-version + * 2 n - lenght of authorization-protocol-name + * 2 d - lenght of authorization-protocol-data + * 2 - unused + * string8 - authorization-protocol-name + * p - unused, p=pad(n) + * string8 - authorization-protocol-data + * q - unused, q=pad(d) + * + * pad(X) = (4 - (X mod 4)) mod 4 + * + * Server response: + * + * 1 (0 failed, 2 authenticate, 1 success) + * ... + * + */ + /* Later on we will simply forward the first 6 header bytes to the "real" X11 server */ + byte[] header = new byte[6]; - /* Yes, I came up with this myself - shall I file an application for a patent? =) */ - - int idxMSB = (header[0] == 0x42) ? 0 : 1; + if (remote_is.read(header) != 6) + throw new IOException("Unexpected EOF on X11 startup!"); - /* Read authorization data header */ - - byte[] auth_buff = new byte[6]; + if ((header[0] != 0x42) && (header[0] != 0x6c)) // 0x42 MSB first, 0x6C LSB first + throw new IOException("Unknown endian format in X11 message!"); - if (remote_is.read(auth_buff) != 6) - throw new IOException("Unexpected EOF on X11 startup!"); + /* Yes, I came up with this myself - shall I file an application for a patent? =) */ + int idxMSB = (header[0] == 0x42) ? 0 : 1; + /* Read authorization data header */ + byte[] auth_buff = new byte[6]; - int authProtocolNameLength = ((auth_buff[idxMSB] & 0xff) << 8) | (auth_buff[1 - idxMSB] & 0xff); - int authProtocolDataLength = ((auth_buff[2 + idxMSB] & 0xff) << 8) | (auth_buff[3 - idxMSB] & 0xff); + if (remote_is.read(auth_buff) != 6) + throw new IOException("Unexpected EOF on X11 startup!"); - if ((authProtocolNameLength > 256) || (authProtocolDataLength > 256)) - throw new IOException("Buggy X11 authorization data"); + int authProtocolNameLength = ((auth_buff[idxMSB] & 0xff) << 8) | (auth_buff[1 - idxMSB] & 0xff); + int authProtocolDataLength = ((auth_buff[2 + idxMSB] & 0xff) << 8) | (auth_buff[3 - idxMSB] & 0xff); - int authProtocolNamePadding = ((4 - (authProtocolNameLength % 4)) % 4); - int authProtocolDataPadding = ((4 - (authProtocolDataLength % 4)) % 4); + if ((authProtocolNameLength > 256) || (authProtocolDataLength > 256)) + throw new IOException("Buggy X11 authorization data"); - byte[] authProtocolName = new byte[authProtocolNameLength]; - byte[] authProtocolData = new byte[authProtocolDataLength]; - - byte[] paddingBuffer = new byte[4]; + int authProtocolNamePadding = ((4 - (authProtocolNameLength % 4)) % 4); + int authProtocolDataPadding = ((4 - (authProtocolDataLength % 4)) % 4); + byte[] authProtocolName = new byte[authProtocolNameLength]; + byte[] authProtocolData = new byte[authProtocolDataLength]; + byte[] paddingBuffer = new byte[4]; - if (remote_is.read(authProtocolName) != authProtocolNameLength) - throw new IOException("Unexpected EOF on X11 startup! (authProtocolName)"); + if (remote_is.read(authProtocolName) != authProtocolNameLength) + throw new IOException("Unexpected EOF on X11 startup! (authProtocolName)"); - if (remote_is.read(paddingBuffer, 0, authProtocolNamePadding) != authProtocolNamePadding) - throw new IOException("Unexpected EOF on X11 startup! (authProtocolNamePadding)"); + if (remote_is.read(paddingBuffer, 0, authProtocolNamePadding) != authProtocolNamePadding) + throw new IOException("Unexpected EOF on X11 startup! (authProtocolNamePadding)"); - if (remote_is.read(authProtocolData) != authProtocolDataLength) - throw new IOException("Unexpected EOF on X11 startup! (authProtocolData)"); + if (remote_is.read(authProtocolData) != authProtocolDataLength) + throw new IOException("Unexpected EOF on X11 startup! (authProtocolData)"); - if (remote_is.read(paddingBuffer, 0, authProtocolDataPadding) != authProtocolDataPadding) - throw new IOException("Unexpected EOF on X11 startup! (authProtocolDataPadding)"); + if (remote_is.read(paddingBuffer, 0, authProtocolDataPadding) != authProtocolDataPadding) + throw new IOException("Unexpected EOF on X11 startup! (authProtocolDataPadding)"); - if ("MIT-MAGIC-COOKIE-1".equals(StringEncoder.GetString(authProtocolName)) == false) - throw new IOException("Unknown X11 authorization protocol!"); - - if (authProtocolDataLength != 16) - throw new IOException("Wrong data length for X11 authorization data!"); + if ("MIT-MAGIC-COOKIE-1".equals(StringEncoder.GetString(authProtocolName)) == false) + throw new IOException("Unknown X11 authorization protocol!"); - StringBuilder tmp = new StringBuilder(32); - for (int i = 0; i < authProtocolData.length; i++) - { - String digit2 = Integer.toHexString(authProtocolData[i] & 0xff); - tmp.append((digit2.length() == 2) ? digit2 : "0" + digit2); - } - String hexEncodedFakeCookie = tmp.toString(); + if (authProtocolDataLength != 16) + throw new IOException("Wrong data length for X11 authorization data!"); + + StringBuilder tmp = new StringBuilder(32); - /* Order is very important here - it may be that a certain x11 forwarding - * gets disabled right in the moment when we check and register our connection - * */ + for (int i = 0; i < authProtocolData.length; i++) { + String digit2 = Integer.toHexString(authProtocolData[i] & 0xff); + tmp.append((digit2.length() == 2) ? digit2 : "0" + digit2); + } - synchronized (c) - { - /* Please read the comment in Channel.java */ - c.hexX11FakeCookie = hexEncodedFakeCookie; - } + String hexEncodedFakeCookie = tmp.toString(); - /* Now check our fake cookie directory to see if we produced this cookie */ - - X11ServerData sd = c.cm.checkX11Cookie(hexEncodedFakeCookie); + /* Order is very important here - it may be that a certain x11 forwarding + * gets disabled right in the moment when we check and register our connection + * */ - if (sd == null) - throw new IOException("Invalid X11 cookie received."); + synchronized (c) { + /* Please read the comment in Channel.java */ + c.hexX11FakeCookie = hexEncodedFakeCookie; + } - /* If the session which corresponds to this cookie is closed then we will - * detect this: the session's close code will close all channels - * with the session's assigned x11 fake cookie. - */ - - s = new Socket(sd.hostname, sd.port); - - OutputStream x11_os = s.getOutputStream(); - InputStream x11_is = s.getInputStream(); + /* Now check our fake cookie directory to see if we produced this cookie */ + X11ServerData sd = c.cm.checkX11Cookie(hexEncodedFakeCookie); - /* Now we are sending the startup packet to the real X11 server */ - - x11_os.write(header); + if (sd == null) + throw new IOException("Invalid X11 cookie received."); - if (sd.x11_magic_cookie == null) - { - byte[] emptyAuthData = new byte[6]; - /* empty auth data, hopefully you are connecting to localhost =) */ - x11_os.write(emptyAuthData); - } - else - { - if (sd.x11_magic_cookie.length != 16) - throw new IOException("The real X11 cookie has an invalid length!"); + /* If the session which corresponds to this cookie is closed then we will + * detect this: the session's close code will close all channels + * with the session's assigned x11 fake cookie. + */ + s = new Socket(sd.hostname, sd.port); + OutputStream x11_os = s.getOutputStream(); + InputStream x11_is = s.getInputStream(); + /* Now we are sending the startup packet to the real X11 server */ + x11_os.write(header); - /* send X11 cookie specified by client */ - x11_os.write(auth_buff); - x11_os.write(authProtocolName); /* re-use */ - x11_os.write(paddingBuffer, 0, authProtocolNamePadding); - x11_os.write(sd.x11_magic_cookie); - x11_os.write(paddingBuffer, 0, authProtocolDataPadding); - } - - x11_os.flush(); + if (sd.x11_magic_cookie == null) { + byte[] emptyAuthData = new byte[6]; + /* empty auth data, hopefully you are connecting to localhost =) */ + x11_os.write(emptyAuthData); + } + else { + if (sd.x11_magic_cookie.length != 16) + throw new IOException("The real X11 cookie has an invalid length!"); - /* Start forwarding traffic */ - - StreamForwarder r2l = new StreamForwarder(c, null, null, remote_is, x11_os, "RemoteToX11"); - StreamForwarder l2r = new StreamForwarder(c, null, null, x11_is, remote_os, "X11ToRemote"); + /* send X11 cookie specified by client */ + x11_os.write(auth_buff); + x11_os.write(authProtocolName); /* re-use */ + x11_os.write(paddingBuffer, 0, authProtocolNamePadding); + x11_os.write(sd.x11_magic_cookie); + x11_os.write(paddingBuffer, 0, authProtocolDataPadding); + } - /* No need to start two threads, one can be executed in the current thread */ - - r2l.setDaemon(true); - r2l.start(); - l2r.run(); + x11_os.flush(); + /* Start forwarding traffic */ + StreamForwarder r2l = new StreamForwarder(c, null, null, remote_is, x11_os, "RemoteToX11"); + StreamForwarder l2r = new StreamForwarder(c, null, null, x11_is, remote_os, "X11ToRemote"); + /* No need to start two threads, one can be executed in the current thread */ + r2l.setDaemon(true); + r2l.start(); + l2r.run(); - while (r2l.isAlive()) - { - try - { - r2l.join(); - } - catch (InterruptedException ignored) - { - } - } + while (r2l.isAlive()) { + try { + r2l.join(); + } + catch (InterruptedException ignored) { + } + } - /* If the channel is already closed, then this is a no-op */ + /* If the channel is already closed, then this is a no-op */ + c.cm.closeChannel(c, "EOF on both X11 streams reached.", true); + s.close(); + } + catch (IOException e) { + log.warning("IOException in X11 proxy code: " + e.getMessage()); - c.cm.closeChannel(c, "EOF on both X11 streams reached.", true); - s.close(); - } - catch (IOException e) - { - log.warning("IOException in X11 proxy code: " + e.getMessage()); + try { + c.cm.closeChannel(c, e, true); + } + catch (IOException ignored) { + } - try - { - c.cm.closeChannel(c, e, true); - } - catch (IOException ignored) - { - } - try - { - if (s != null) - s.close(); - } - catch (IOException ignored) - { - } - } - } + try { + if (s != null) + s.close(); + } + catch (IOException ignored) { + } + } + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/ServerSessionImpl.java --- a/src/ch/ethz/ssh2/channel/ServerSessionImpl.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/ServerSessionImpl.java Wed Jul 30 14:16:58 2014 -0700 @@ -8,54 +8,43 @@ import ch.ethz.ssh2.ServerSession; import ch.ethz.ssh2.ServerSessionCallback; -public class ServerSessionImpl implements ServerSession -{ - Channel c; - public ServerSessionCallback sscb; +public class ServerSessionImpl implements ServerSession { + Channel c; + public ServerSessionCallback sscb; - public ServerSessionImpl(Channel c) - { - this.c = c; - } + public ServerSessionImpl(Channel c) { + this.c = c; + } - public int getState() - { - return c.getState(); - } + public int getState() { + return c.getState(); + } - public InputStream getStdout() - { - return c.getStdoutStream(); - } + public InputStream getStdout() { + return c.getStdoutStream(); + } - public InputStream getStderr() - { - return c.getStderrStream(); - } + public InputStream getStderr() { + return c.getStderrStream(); + } - public OutputStream getStdin() - { - return c.getStdinStream(); - } + public OutputStream getStdin() { + return c.getStdinStream(); + } - public void close() - { - try - { - c.cm.closeChannel(c, "Closed due to server request", true); - } - catch (IOException ignored) - { - } - } + public void close() { + try { + c.cm.closeChannel(c, "Closed due to server request", true); + } + catch (IOException ignored) { + } + } - public synchronized ServerSessionCallback getServerSessionCallback() - { - return sscb; - } + public synchronized ServerSessionCallback getServerSessionCallback() { + return sscb; + } - public synchronized void setServerSessionCallback(ServerSessionCallback sscb) - { - this.sscb = sscb; - } + public synchronized void setServerSessionCallback(ServerSessionCallback sscb) { + this.sscb = sscb; + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/StreamForwarder.java --- a/src/ch/ethz/ssh2/channel/StreamForwarder.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/StreamForwarder.java Wed Jul 30 14:16:58 2014 -0700 @@ -10,106 +10,88 @@ import java.net.Socket; /** - * A StreamForwarder forwards data between two given streams. + * A StreamForwarder forwards data between two given streams. * If two StreamForwarder threads are used (one for each direction) * then one can be configured to shutdown the underlying channel/socket * if both threads have finished forwarding (EOF). - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class StreamForwarder extends Thread -{ - OutputStream os; - InputStream is; - byte[] buffer = new byte[Channel.CHANNEL_BUFFER_SIZE]; - Channel c; - StreamForwarder sibling; - Socket s; - String mode; +public class StreamForwarder extends Thread { + OutputStream os; + InputStream is; + byte[] buffer = new byte[Channel.CHANNEL_BUFFER_SIZE]; + Channel c; + StreamForwarder sibling; + Socket s; + String mode; - StreamForwarder(Channel c, StreamForwarder sibling, Socket s, InputStream is, OutputStream os, String mode) - throws IOException - { - this.is = is; - this.os = os; - this.mode = mode; - this.c = c; - this.sibling = sibling; - this.s = s; - } + StreamForwarder(Channel c, StreamForwarder sibling, Socket s, InputStream is, OutputStream os, String mode) + throws IOException { + this.is = is; + this.os = os; + this.mode = mode; + this.c = c; + this.sibling = sibling; + this.s = s; + } + + @Override + public void run() { + try { + while (true) { + int len = is.read(buffer); + + if (len <= 0) + break; - @Override - public void run() - { - try - { - while (true) - { - int len = is.read(buffer); - if (len <= 0) - break; - os.write(buffer, 0, len); - os.flush(); - } - } - catch (IOException e) - { - try - { - c.cm.closeChannel(c, e, true); - } - catch (IOException ignored) - { - } - } - finally - { - try - { - os.close(); - } - catch (IOException ignored) - { - } - try - { - is.close(); - } - catch (IOException ignored) - { - } + os.write(buffer, 0, len); + os.flush(); + } + } + catch (IOException e) { + try { + c.cm.closeChannel(c, e, true); + } + catch (IOException ignored) { + } + } + finally { + try { + os.close(); + } + catch (IOException ignored) { + } + + try { + is.close(); + } + catch (IOException ignored) { + } - if (sibling != null) - { - while (sibling.isAlive()) - { - try - { - sibling.join(); - } - catch (InterruptedException ignored) - { - } - } + if (sibling != null) { + while (sibling.isAlive()) { + try { + sibling.join(); + } + catch (InterruptedException ignored) { + } + } - try - { - c.cm.closeChannel(c, "StreamForwarder (" + mode + ") is cleaning up the connection", true); - } - catch (IOException ignored) - { - } + try { + c.cm.closeChannel(c, "StreamForwarder (" + mode + ") is cleaning up the connection", true); + } + catch (IOException ignored) { + } - try - { - if (s != null) - s.close(); - } - catch (IOException ignored) - { - } - } - } - } + try { + if (s != null) + s.close(); + } + catch (IOException ignored) { + } + } + } + } } \ No newline at end of file diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/channel/X11ServerData.java --- a/src/ch/ethz/ssh2/channel/X11ServerData.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/channel/X11ServerData.java Wed Jul 30 14:16:58 2014 -0700 @@ -9,11 +9,10 @@ * * @author Christian Plattner * @version 2.50, 03/15/10 - * + * */ -public class X11ServerData -{ - public String hostname; - public int port; - public byte[] x11_magic_cookie; /* not the remote (fake) one, the local (real) one */ +public class X11ServerData { + public String hostname; + public int port; + public byte[] x11_magic_cookie; /* not the remote (fake) one, the local (real) one */ } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/compression/CompressionFactory.java --- a/src/ch/ethz/ssh2/compression/CompressionFactory.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/compression/CompressionFactory.java Wed Jul 30 14:16:58 2014 -0700 @@ -19,7 +19,7 @@ } private static final List compressors - = new ArrayList(); + = new ArrayList(); static { // Higher priority first @@ -28,15 +28,17 @@ public static String[] getDefaultCompressorList() { String list[] = new String[compressors.size()]; - for(int i = 0; i < compressors.size(); i++) { + + for (int i = 0; i < compressors.size(); i++) { CompressorEntry ce = compressors.get(i); list[i] = ce.type; } + return list; } public static void checkCompressorList(String[] list) { - for(final String candidate : list) { + for (final String candidate : list) { getEntry(candidate); } } @@ -44,23 +46,26 @@ public static Compressor createCompressor(String type) { try { CompressorEntry ce = getEntry(type); - if(null == ce.compressorClass) { + + if (null == ce.compressorClass) { return null; } + Class cc = Class.forName(ce.compressorClass); return (Compressor) cc.newInstance(); } - catch(Exception e) { + catch (Exception e) { throw new IllegalArgumentException("Cannot instantiate " + type); } } private static CompressorEntry getEntry(String type) { - for(CompressorEntry ce : compressors) { - if(ce.type.equals(type)) { + for (CompressorEntry ce : compressors) { + if (ce.type.equals(type)) { return ce; } } + throw new IllegalArgumentException("Unknown algorithm " + type); } } \ No newline at end of file diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/Base64.java --- a/src/ch/ethz/ssh2/crypto/Base64.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/Base64.java Wed Jul 30 14:16:58 2014 -0700 @@ -9,143 +9,119 @@ /** * Basic Base64 Support. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class Base64 -{ - static final char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); - - public static char[] encode(byte[] content) - { - CharArrayWriter cw = new CharArrayWriter((4 * content.length) / 3); +public class Base64 { + static final char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); - int idx = 0; - - int x = 0; + public static char[] encode(byte[] content) { + CharArrayWriter cw = new CharArrayWriter((4 * content.length) / 3); + int idx = 0; + int x = 0; - for (int i = 0; i < content.length; i++) - { - if (idx == 0) - x = (content[i] & 0xff) << 16; - else if (idx == 1) - x = x | ((content[i] & 0xff) << 8); - else - x = x | (content[i] & 0xff); - - idx++; + for (int i = 0; i < content.length; i++) { + if (idx == 0) + x = (content[i] & 0xff) << 16; + else if (idx == 1) + x = x | ((content[i] & 0xff) << 8); + else + x = x | (content[i] & 0xff); - if (idx == 3) - { - cw.write(alphabet[x >> 18]); - cw.write(alphabet[(x >> 12) & 0x3f]); - cw.write(alphabet[(x >> 6) & 0x3f]); - cw.write(alphabet[x & 0x3f]); + idx++; - idx = 0; - } - } + if (idx == 3) { + cw.write(alphabet[x >> 18]); + cw.write(alphabet[(x >> 12) & 0x3f]); + cw.write(alphabet[(x >> 6) & 0x3f]); + cw.write(alphabet[x & 0x3f]); + idx = 0; + } + } - if (idx == 1) - { - cw.write(alphabet[x >> 18]); - cw.write(alphabet[(x >> 12) & 0x3f]); - cw.write('='); - cw.write('='); - } + if (idx == 1) { + cw.write(alphabet[x >> 18]); + cw.write(alphabet[(x >> 12) & 0x3f]); + cw.write('='); + cw.write('='); + } - if (idx == 2) - { - cw.write(alphabet[x >> 18]); - cw.write(alphabet[(x >> 12) & 0x3f]); - cw.write(alphabet[(x >> 6) & 0x3f]); - cw.write('='); - } + if (idx == 2) { + cw.write(alphabet[x >> 18]); + cw.write(alphabet[(x >> 12) & 0x3f]); + cw.write(alphabet[(x >> 6) & 0x3f]); + cw.write('='); + } - return cw.toCharArray(); - } - - public static byte[] decode(char[] message) throws IOException - { - byte buff[] = new byte[4]; - byte dest[] = new byte[message.length]; + return cw.toCharArray(); + } - int bpos = 0; - int destpos = 0; + public static byte[] decode(char[] message) throws IOException { + byte buff[] = new byte[4]; + byte dest[] = new byte[message.length]; + int bpos = 0; + int destpos = 0; - for (int i = 0; i < message.length; i++) - { - int c = message[i]; + for (int i = 0; i < message.length; i++) { + int c = message[i]; - if ((c == '\n') || (c == '\r') || (c == ' ') || (c == '\t')) - continue; + if ((c == '\n') || (c == '\r') || (c == ' ') || (c == '\t')) + continue; - if ((c >= 'A') && (c <= 'Z')) - { - buff[bpos++] = (byte) (c - 'A'); - } - else if ((c >= 'a') && (c <= 'z')) - { - buff[bpos++] = (byte) ((c - 'a') + 26); - } - else if ((c >= '0') && (c <= '9')) - { - buff[bpos++] = (byte) ((c - '0') + 52); - } - else if (c == '+') - { - buff[bpos++] = 62; - } - else if (c == '/') - { - buff[bpos++] = 63; - } - else if (c == '=') - { - buff[bpos++] = 64; - } - else - { - throw new IOException("Illegal char in base64 code."); - } + if ((c >= 'A') && (c <= 'Z')) { + buff[bpos++] = (byte)(c - 'A'); + } + else if ((c >= 'a') && (c <= 'z')) { + buff[bpos++] = (byte)((c - 'a') + 26); + } + else if ((c >= '0') && (c <= '9')) { + buff[bpos++] = (byte)((c - '0') + 52); + } + else if (c == '+') { + buff[bpos++] = 62; + } + else if (c == '/') { + buff[bpos++] = 63; + } + else if (c == '=') { + buff[bpos++] = 64; + } + else { + throw new IOException("Illegal char in base64 code."); + } - if (bpos == 4) - { - bpos = 0; + if (bpos == 4) { + bpos = 0; + + if (buff[0] == 64) + break; - if (buff[0] == 64) - break; - - if (buff[1] == 64) - throw new IOException("Unexpected '=' in base64 code."); + if (buff[1] == 64) + throw new IOException("Unexpected '=' in base64 code."); - if (buff[2] == 64) - { - int v = (((buff[0] & 0x3f) << 6) | ((buff[1] & 0x3f))); - dest[destpos++] = (byte) (v >> 4); - break; - } - else if (buff[3] == 64) - { - int v = (((buff[0] & 0x3f) << 12) | ((buff[1] & 0x3f) << 6) | ((buff[2] & 0x3f))); - dest[destpos++] = (byte) (v >> 10); - dest[destpos++] = (byte) (v >> 2); - break; - } - else - { - int v = (((buff[0] & 0x3f) << 18) | ((buff[1] & 0x3f) << 12) | ((buff[2] & 0x3f) << 6) | ((buff[3] & 0x3f))); - dest[destpos++] = (byte) (v >> 16); - dest[destpos++] = (byte) (v >> 8); - dest[destpos++] = (byte) (v); - } - } - } + if (buff[2] == 64) { + int v = (((buff[0] & 0x3f) << 6) | ((buff[1] & 0x3f))); + dest[destpos++] = (byte)(v >> 4); + break; + } + else if (buff[3] == 64) { + int v = (((buff[0] & 0x3f) << 12) | ((buff[1] & 0x3f) << 6) | ((buff[2] & 0x3f))); + dest[destpos++] = (byte)(v >> 10); + dest[destpos++] = (byte)(v >> 2); + break; + } + else { + int v = (((buff[0] & 0x3f) << 18) | ((buff[1] & 0x3f) << 12) | ((buff[2] & 0x3f) << 6) | ((buff[3] & 0x3f))); + dest[destpos++] = (byte)(v >> 16); + dest[destpos++] = (byte)(v >> 8); + dest[destpos++] = (byte)(v); + } + } + } - byte[] res = new byte[destpos]; - System.arraycopy(dest, 0, res, 0, destpos); - - return res; - } + byte[] res = new byte[destpos]; + System.arraycopy(dest, 0, res, 0, destpos); + return res; + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/CryptoWishList.java --- a/src/ch/ethz/ssh2/crypto/CryptoWishList.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/CryptoWishList.java Wed Jul 30 14:16:58 2014 -0700 @@ -11,25 +11,23 @@ /** * CryptoWishList. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class CryptoWishList -{ - public String[] kexAlgorithms = KexManager.getDefaultClientKexAlgorithmList(); - public String[] serverHostKeyAlgorithms = KexManager.getDefaultServerHostkeyAlgorithmList(); - public String[] c2s_enc_algos = BlockCipherFactory.getDefaultCipherList(); - public String[] s2c_enc_algos = BlockCipherFactory.getDefaultCipherList(); - public String[] c2s_mac_algos = MAC.getMacList(); - public String[] s2c_mac_algos = MAC.getMacList(); +public class CryptoWishList { + public String[] kexAlgorithms = KexManager.getDefaultClientKexAlgorithmList(); + public String[] serverHostKeyAlgorithms = KexManager.getDefaultServerHostkeyAlgorithmList(); + public String[] c2s_enc_algos = BlockCipherFactory.getDefaultCipherList(); + public String[] s2c_enc_algos = BlockCipherFactory.getDefaultCipherList(); + public String[] c2s_mac_algos = MAC.getMacList(); + public String[] s2c_mac_algos = MAC.getMacList(); public String[] c2s_comp_algos = CompressionFactory.getDefaultCompressorList(); - public String[] s2c_comp_algos = CompressionFactory.getDefaultCompressorList(); + public String[] s2c_comp_algos = CompressionFactory.getDefaultCompressorList(); - public static CryptoWishList forServer() - { - CryptoWishList cwl = new CryptoWishList(); - cwl.kexAlgorithms = KexManager.getDefaultServerKexAlgorithmList(); - return cwl; - } + public static CryptoWishList forServer() { + CryptoWishList cwl = new CryptoWishList(); + cwl.kexAlgorithms = KexManager.getDefaultServerKexAlgorithmList(); + return cwl; + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/KeyMaterial.java --- a/src/ch/ethz/ssh2/crypto/KeyMaterial.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/KeyMaterial.java Wed Jul 30 14:16:58 2014 -0700 @@ -26,38 +26,30 @@ private static byte[] calculateKey(HashForSSH2Types sh, BigInteger K, byte[] H, byte type, byte[] SessionID, int keyLength) throws IOException { byte[] res = new byte[keyLength]; - int dglen = sh.getDigestLength(); int numRounds = (keyLength + dglen - 1) / dglen; - byte[][] tmp = new byte[numRounds][]; - sh.reset(); sh.updateBigInt(K); sh.updateBytes(H); sh.updateByte(type); sh.updateBytes(SessionID); - tmp[0] = sh.getDigest(); - int off = 0; int produced = Math.min(dglen, keyLength); - System.arraycopy(tmp[0], 0, res, off, produced); - keyLength -= produced; off += produced; - for(int i = 1; i < numRounds; i++) { + for (int i = 1; i < numRounds; i++) { sh.updateBigInt(K); sh.updateBytes(H); - for(int j = 0; j < i; j++) { + for (int j = 0; j < i; j++) { sh.updateBytes(tmp[j]); } tmp[i] = sh.getDigest(); - produced = Math.min(dglen, keyLength); System.arraycopy(tmp[i], 0, res, off, produced); keyLength -= produced; @@ -69,23 +61,15 @@ public static KeyMaterial create(String hashType, byte[] H, BigInteger K, byte[] SessionID, int keyLengthCS, int blockSizeCS, int macLengthCS, int keyLengthSC, int blockSizeSC, int macLengthSC) - throws IOException { + throws IOException { KeyMaterial km = new KeyMaterial(); - HashForSSH2Types sh = new HashForSSH2Types(hashType); - km.initial_iv_client_to_server = calculateKey(sh, K, H, (byte) 'A', SessionID, blockSizeCS); - km.initial_iv_server_to_client = calculateKey(sh, K, H, (byte) 'B', SessionID, blockSizeSC); - km.enc_key_client_to_server = calculateKey(sh, K, H, (byte) 'C', SessionID, keyLengthCS); - km.enc_key_server_to_client = calculateKey(sh, K, H, (byte) 'D', SessionID, keyLengthSC); - km.integrity_key_client_to_server = calculateKey(sh, K, H, (byte) 'E', SessionID, macLengthCS); - km.integrity_key_server_to_client = calculateKey(sh, K, H, (byte) 'F', SessionID, macLengthSC); - return km; } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/PEMDecryptException.java --- a/src/ch/ethz/ssh2/crypto/PEMDecryptException.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/PEMDecryptException.java Wed Jul 30 14:16:58 2014 -0700 @@ -9,15 +9,13 @@ /** * @version $Id: PEMDecryptException.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ */ -public class PEMDecryptException extends IOException -{ - /** - * - */ - private static final long serialVersionUID = 1L; +public class PEMDecryptException extends IOException { + /** + * + */ + private static final long serialVersionUID = 1L; - public PEMDecryptException(String message) - { - super(message); - } + public PEMDecryptException(String message) { + super(message); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/PEMStructure.java --- a/src/ch/ethz/ssh2/crypto/PEMStructure.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/PEMStructure.java Wed Jul 30 14:16:58 2014 -0700 @@ -11,10 +11,9 @@ * @version 2.50, 03/15/10 */ -public class PEMStructure -{ - public int pemType; - String dekInfo[]; - String procType[]; - byte[] data; +public class PEMStructure { + public int pemType; + String dekInfo[]; + String procType[]; + byte[] data; } \ No newline at end of file diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/cipher/AES.java --- a/src/ch/ethz/ssh2/crypto/cipher/AES.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/cipher/AES.java Wed Jul 30 14:16:58 2014 -0700 @@ -23,7 +23,7 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + THE SOFTWARE. */ /** @@ -32,666 +32,630 @@ * For further details see: http://csrc.nist.gov/encryption/aes/ * . - * + * * This implementation is based on optimizations from Dr. Brian Gladman's paper * and C code at http://fp.gladman.plus.com/cryptography_technology/rijndael/ * - * + * * There are three levels of tradeoff of speed vs memory Because java has no * preprocessor, they are written as three separate classes from which to choose - * + * * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 * 256 word tables for encryption and 4 for decryption. - * + * * The middle performance version uses only one 256 word table for each, for a * total of 2Kbytes, adding 12 rotate operations per round to compute the values * contained in the other tables from the contents of the first - * + * * The slowest version uses no static tables at all and computes the values in * each round *

* This file contains the fast version with 8Kbytes of static tables for round * precomputation - * + * * @author See comments in the source file * @version 2.50, 03/15/10 */ -public class AES implements BlockCipher -{ - // The S box - private static final byte[] S = { (byte) 99, (byte) 124, (byte) 119, (byte) 123, (byte) 242, (byte) 107, - (byte) 111, (byte) 197, (byte) 48, (byte) 1, (byte) 103, (byte) 43, (byte) 254, (byte) 215, (byte) 171, - (byte) 118, (byte) 202, (byte) 130, (byte) 201, (byte) 125, (byte) 250, (byte) 89, (byte) 71, (byte) 240, - (byte) 173, (byte) 212, (byte) 162, (byte) 175, (byte) 156, (byte) 164, (byte) 114, (byte) 192, (byte) 183, - (byte) 253, (byte) 147, (byte) 38, (byte) 54, (byte) 63, (byte) 247, (byte) 204, (byte) 52, (byte) 165, - (byte) 229, (byte) 241, (byte) 113, (byte) 216, (byte) 49, (byte) 21, (byte) 4, (byte) 199, (byte) 35, - (byte) 195, (byte) 24, (byte) 150, (byte) 5, (byte) 154, (byte) 7, (byte) 18, (byte) 128, (byte) 226, - (byte) 235, (byte) 39, (byte) 178, (byte) 117, (byte) 9, (byte) 131, (byte) 44, (byte) 26, (byte) 27, - (byte) 110, (byte) 90, (byte) 160, (byte) 82, (byte) 59, (byte) 214, (byte) 179, (byte) 41, (byte) 227, - (byte) 47, (byte) 132, (byte) 83, (byte) 209, (byte) 0, (byte) 237, (byte) 32, (byte) 252, (byte) 177, - (byte) 91, (byte) 106, (byte) 203, (byte) 190, (byte) 57, (byte) 74, (byte) 76, (byte) 88, (byte) 207, - (byte) 208, (byte) 239, (byte) 170, (byte) 251, (byte) 67, (byte) 77, (byte) 51, (byte) 133, (byte) 69, - (byte) 249, (byte) 2, (byte) 127, (byte) 80, (byte) 60, (byte) 159, (byte) 168, (byte) 81, (byte) 163, - (byte) 64, (byte) 143, (byte) 146, (byte) 157, (byte) 56, (byte) 245, (byte) 188, (byte) 182, (byte) 218, - (byte) 33, (byte) 16, (byte) 255, (byte) 243, (byte) 210, (byte) 205, (byte) 12, (byte) 19, (byte) 236, - (byte) 95, (byte) 151, (byte) 68, (byte) 23, (byte) 196, (byte) 167, (byte) 126, (byte) 61, (byte) 100, - (byte) 93, (byte) 25, (byte) 115, (byte) 96, (byte) 129, (byte) 79, (byte) 220, (byte) 34, (byte) 42, - (byte) 144, (byte) 136, (byte) 70, (byte) 238, (byte) 184, (byte) 20, (byte) 222, (byte) 94, (byte) 11, - (byte) 219, (byte) 224, (byte) 50, (byte) 58, (byte) 10, (byte) 73, (byte) 6, (byte) 36, (byte) 92, - (byte) 194, (byte) 211, (byte) 172, (byte) 98, (byte) 145, (byte) 149, (byte) 228, (byte) 121, (byte) 231, - (byte) 200, (byte) 55, (byte) 109, (byte) 141, (byte) 213, (byte) 78, (byte) 169, (byte) 108, (byte) 86, - (byte) 244, (byte) 234, (byte) 101, (byte) 122, (byte) 174, (byte) 8, (byte) 186, (byte) 120, (byte) 37, - (byte) 46, (byte) 28, (byte) 166, (byte) 180, (byte) 198, (byte) 232, (byte) 221, (byte) 116, (byte) 31, - (byte) 75, (byte) 189, (byte) 139, (byte) 138, (byte) 112, (byte) 62, (byte) 181, (byte) 102, (byte) 72, - (byte) 3, (byte) 246, (byte) 14, (byte) 97, (byte) 53, (byte) 87, (byte) 185, (byte) 134, (byte) 193, - (byte) 29, (byte) 158, (byte) 225, (byte) 248, (byte) 152, (byte) 17, (byte) 105, (byte) 217, (byte) 142, - (byte) 148, (byte) 155, (byte) 30, (byte) 135, (byte) 233, (byte) 206, (byte) 85, (byte) 40, (byte) 223, - (byte) 140, (byte) 161, (byte) 137, (byte) 13, (byte) 191, (byte) 230, (byte) 66, (byte) 104, (byte) 65, - (byte) 153, (byte) 45, (byte) 15, (byte) 176, (byte) 84, (byte) 187, (byte) 22, }; +public class AES implements BlockCipher { + // The S box + private static final byte[] S = { (byte) 99, (byte) 124, (byte) 119, (byte) 123, (byte) 242, (byte) 107, + (byte) 111, (byte) 197, (byte) 48, (byte) 1, (byte) 103, (byte) 43, (byte) 254, (byte) 215, (byte) 171, + (byte) 118, (byte) 202, (byte) 130, (byte) 201, (byte) 125, (byte) 250, (byte) 89, (byte) 71, (byte) 240, + (byte) 173, (byte) 212, (byte) 162, (byte) 175, (byte) 156, (byte) 164, (byte) 114, (byte) 192, (byte) 183, + (byte) 253, (byte) 147, (byte) 38, (byte) 54, (byte) 63, (byte) 247, (byte) 204, (byte) 52, (byte) 165, + (byte) 229, (byte) 241, (byte) 113, (byte) 216, (byte) 49, (byte) 21, (byte) 4, (byte) 199, (byte) 35, + (byte) 195, (byte) 24, (byte) 150, (byte) 5, (byte) 154, (byte) 7, (byte) 18, (byte) 128, (byte) 226, + (byte) 235, (byte) 39, (byte) 178, (byte) 117, (byte) 9, (byte) 131, (byte) 44, (byte) 26, (byte) 27, + (byte) 110, (byte) 90, (byte) 160, (byte) 82, (byte) 59, (byte) 214, (byte) 179, (byte) 41, (byte) 227, + (byte) 47, (byte) 132, (byte) 83, (byte) 209, (byte) 0, (byte) 237, (byte) 32, (byte) 252, (byte) 177, + (byte) 91, (byte) 106, (byte) 203, (byte) 190, (byte) 57, (byte) 74, (byte) 76, (byte) 88, (byte) 207, + (byte) 208, (byte) 239, (byte) 170, (byte) 251, (byte) 67, (byte) 77, (byte) 51, (byte) 133, (byte) 69, + (byte) 249, (byte) 2, (byte) 127, (byte) 80, (byte) 60, (byte) 159, (byte) 168, (byte) 81, (byte) 163, + (byte) 64, (byte) 143, (byte) 146, (byte) 157, (byte) 56, (byte) 245, (byte) 188, (byte) 182, (byte) 218, + (byte) 33, (byte) 16, (byte) 255, (byte) 243, (byte) 210, (byte) 205, (byte) 12, (byte) 19, (byte) 236, + (byte) 95, (byte) 151, (byte) 68, (byte) 23, (byte) 196, (byte) 167, (byte) 126, (byte) 61, (byte) 100, + (byte) 93, (byte) 25, (byte) 115, (byte) 96, (byte) 129, (byte) 79, (byte) 220, (byte) 34, (byte) 42, + (byte) 144, (byte) 136, (byte) 70, (byte) 238, (byte) 184, (byte) 20, (byte) 222, (byte) 94, (byte) 11, + (byte) 219, (byte) 224, (byte) 50, (byte) 58, (byte) 10, (byte) 73, (byte) 6, (byte) 36, (byte) 92, + (byte) 194, (byte) 211, (byte) 172, (byte) 98, (byte) 145, (byte) 149, (byte) 228, (byte) 121, (byte) 231, + (byte) 200, (byte) 55, (byte) 109, (byte) 141, (byte) 213, (byte) 78, (byte) 169, (byte) 108, (byte) 86, + (byte) 244, (byte) 234, (byte) 101, (byte) 122, (byte) 174, (byte) 8, (byte) 186, (byte) 120, (byte) 37, + (byte) 46, (byte) 28, (byte) 166, (byte) 180, (byte) 198, (byte) 232, (byte) 221, (byte) 116, (byte) 31, + (byte) 75, (byte) 189, (byte) 139, (byte) 138, (byte) 112, (byte) 62, (byte) 181, (byte) 102, (byte) 72, + (byte) 3, (byte) 246, (byte) 14, (byte) 97, (byte) 53, (byte) 87, (byte) 185, (byte) 134, (byte) 193, + (byte) 29, (byte) 158, (byte) 225, (byte) 248, (byte) 152, (byte) 17, (byte) 105, (byte) 217, (byte) 142, + (byte) 148, (byte) 155, (byte) 30, (byte) 135, (byte) 233, (byte) 206, (byte) 85, (byte) 40, (byte) 223, + (byte) 140, (byte) 161, (byte) 137, (byte) 13, (byte) 191, (byte) 230, (byte) 66, (byte) 104, (byte) 65, + (byte) 153, (byte) 45, (byte) 15, (byte) 176, (byte) 84, (byte) 187, (byte) 22, + }; - // The inverse S-box - private static final byte[] Si = { (byte) 82, (byte) 9, (byte) 106, (byte) 213, (byte) 48, (byte) 54, (byte) 165, - (byte) 56, (byte) 191, (byte) 64, (byte) 163, (byte) 158, (byte) 129, (byte) 243, (byte) 215, (byte) 251, - (byte) 124, (byte) 227, (byte) 57, (byte) 130, (byte) 155, (byte) 47, (byte) 255, (byte) 135, (byte) 52, - (byte) 142, (byte) 67, (byte) 68, (byte) 196, (byte) 222, (byte) 233, (byte) 203, (byte) 84, (byte) 123, - (byte) 148, (byte) 50, (byte) 166, (byte) 194, (byte) 35, (byte) 61, (byte) 238, (byte) 76, (byte) 149, - (byte) 11, (byte) 66, (byte) 250, (byte) 195, (byte) 78, (byte) 8, (byte) 46, (byte) 161, (byte) 102, - (byte) 40, (byte) 217, (byte) 36, (byte) 178, (byte) 118, (byte) 91, (byte) 162, (byte) 73, (byte) 109, - (byte) 139, (byte) 209, (byte) 37, (byte) 114, (byte) 248, (byte) 246, (byte) 100, (byte) 134, (byte) 104, - (byte) 152, (byte) 22, (byte) 212, (byte) 164, (byte) 92, (byte) 204, (byte) 93, (byte) 101, (byte) 182, - (byte) 146, (byte) 108, (byte) 112, (byte) 72, (byte) 80, (byte) 253, (byte) 237, (byte) 185, (byte) 218, - (byte) 94, (byte) 21, (byte) 70, (byte) 87, (byte) 167, (byte) 141, (byte) 157, (byte) 132, (byte) 144, - (byte) 216, (byte) 171, (byte) 0, (byte) 140, (byte) 188, (byte) 211, (byte) 10, (byte) 247, (byte) 228, - (byte) 88, (byte) 5, (byte) 184, (byte) 179, (byte) 69, (byte) 6, (byte) 208, (byte) 44, (byte) 30, - (byte) 143, (byte) 202, (byte) 63, (byte) 15, (byte) 2, (byte) 193, (byte) 175, (byte) 189, (byte) 3, - (byte) 1, (byte) 19, (byte) 138, (byte) 107, (byte) 58, (byte) 145, (byte) 17, (byte) 65, (byte) 79, - (byte) 103, (byte) 220, (byte) 234, (byte) 151, (byte) 242, (byte) 207, (byte) 206, (byte) 240, (byte) 180, - (byte) 230, (byte) 115, (byte) 150, (byte) 172, (byte) 116, (byte) 34, (byte) 231, (byte) 173, (byte) 53, - (byte) 133, (byte) 226, (byte) 249, (byte) 55, (byte) 232, (byte) 28, (byte) 117, (byte) 223, (byte) 110, - (byte) 71, (byte) 241, (byte) 26, (byte) 113, (byte) 29, (byte) 41, (byte) 197, (byte) 137, (byte) 111, - (byte) 183, (byte) 98, (byte) 14, (byte) 170, (byte) 24, (byte) 190, (byte) 27, (byte) 252, (byte) 86, - (byte) 62, (byte) 75, (byte) 198, (byte) 210, (byte) 121, (byte) 32, (byte) 154, (byte) 219, (byte) 192, - (byte) 254, (byte) 120, (byte) 205, (byte) 90, (byte) 244, (byte) 31, (byte) 221, (byte) 168, (byte) 51, - (byte) 136, (byte) 7, (byte) 199, (byte) 49, (byte) 177, (byte) 18, (byte) 16, (byte) 89, (byte) 39, - (byte) 128, (byte) 236, (byte) 95, (byte) 96, (byte) 81, (byte) 127, (byte) 169, (byte) 25, (byte) 181, - (byte) 74, (byte) 13, (byte) 45, (byte) 229, (byte) 122, (byte) 159, (byte) 147, (byte) 201, (byte) 156, - (byte) 239, (byte) 160, (byte) 224, (byte) 59, (byte) 77, (byte) 174, (byte) 42, (byte) 245, (byte) 176, - (byte) 200, (byte) 235, (byte) 187, (byte) 60, (byte) 131, (byte) 83, (byte) 153, (byte) 97, (byte) 23, - (byte) 43, (byte) 4, (byte) 126, (byte) 186, (byte) 119, (byte) 214, (byte) 38, (byte) 225, (byte) 105, - (byte) 20, (byte) 99, (byte) 85, (byte) 33, (byte) 12, (byte) 125, }; + // The inverse S-box + private static final byte[] Si = { (byte) 82, (byte) 9, (byte) 106, (byte) 213, (byte) 48, (byte) 54, (byte) 165, + (byte) 56, (byte) 191, (byte) 64, (byte) 163, (byte) 158, (byte) 129, (byte) 243, (byte) 215, (byte) 251, + (byte) 124, (byte) 227, (byte) 57, (byte) 130, (byte) 155, (byte) 47, (byte) 255, (byte) 135, (byte) 52, + (byte) 142, (byte) 67, (byte) 68, (byte) 196, (byte) 222, (byte) 233, (byte) 203, (byte) 84, (byte) 123, + (byte) 148, (byte) 50, (byte) 166, (byte) 194, (byte) 35, (byte) 61, (byte) 238, (byte) 76, (byte) 149, + (byte) 11, (byte) 66, (byte) 250, (byte) 195, (byte) 78, (byte) 8, (byte) 46, (byte) 161, (byte) 102, + (byte) 40, (byte) 217, (byte) 36, (byte) 178, (byte) 118, (byte) 91, (byte) 162, (byte) 73, (byte) 109, + (byte) 139, (byte) 209, (byte) 37, (byte) 114, (byte) 248, (byte) 246, (byte) 100, (byte) 134, (byte) 104, + (byte) 152, (byte) 22, (byte) 212, (byte) 164, (byte) 92, (byte) 204, (byte) 93, (byte) 101, (byte) 182, + (byte) 146, (byte) 108, (byte) 112, (byte) 72, (byte) 80, (byte) 253, (byte) 237, (byte) 185, (byte) 218, + (byte) 94, (byte) 21, (byte) 70, (byte) 87, (byte) 167, (byte) 141, (byte) 157, (byte) 132, (byte) 144, + (byte) 216, (byte) 171, (byte) 0, (byte) 140, (byte) 188, (byte) 211, (byte) 10, (byte) 247, (byte) 228, + (byte) 88, (byte) 5, (byte) 184, (byte) 179, (byte) 69, (byte) 6, (byte) 208, (byte) 44, (byte) 30, + (byte) 143, (byte) 202, (byte) 63, (byte) 15, (byte) 2, (byte) 193, (byte) 175, (byte) 189, (byte) 3, + (byte) 1, (byte) 19, (byte) 138, (byte) 107, (byte) 58, (byte) 145, (byte) 17, (byte) 65, (byte) 79, + (byte) 103, (byte) 220, (byte) 234, (byte) 151, (byte) 242, (byte) 207, (byte) 206, (byte) 240, (byte) 180, + (byte) 230, (byte) 115, (byte) 150, (byte) 172, (byte) 116, (byte) 34, (byte) 231, (byte) 173, (byte) 53, + (byte) 133, (byte) 226, (byte) 249, (byte) 55, (byte) 232, (byte) 28, (byte) 117, (byte) 223, (byte) 110, + (byte) 71, (byte) 241, (byte) 26, (byte) 113, (byte) 29, (byte) 41, (byte) 197, (byte) 137, (byte) 111, + (byte) 183, (byte) 98, (byte) 14, (byte) 170, (byte) 24, (byte) 190, (byte) 27, (byte) 252, (byte) 86, + (byte) 62, (byte) 75, (byte) 198, (byte) 210, (byte) 121, (byte) 32, (byte) 154, (byte) 219, (byte) 192, + (byte) 254, (byte) 120, (byte) 205, (byte) 90, (byte) 244, (byte) 31, (byte) 221, (byte) 168, (byte) 51, + (byte) 136, (byte) 7, (byte) 199, (byte) 49, (byte) 177, (byte) 18, (byte) 16, (byte) 89, (byte) 39, + (byte) 128, (byte) 236, (byte) 95, (byte) 96, (byte) 81, (byte) 127, (byte) 169, (byte) 25, (byte) 181, + (byte) 74, (byte) 13, (byte) 45, (byte) 229, (byte) 122, (byte) 159, (byte) 147, (byte) 201, (byte) 156, + (byte) 239, (byte) 160, (byte) 224, (byte) 59, (byte) 77, (byte) 174, (byte) 42, (byte) 245, (byte) 176, + (byte) 200, (byte) 235, (byte) 187, (byte) 60, (byte) 131, (byte) 83, (byte) 153, (byte) 97, (byte) 23, + (byte) 43, (byte) 4, (byte) 126, (byte) 186, (byte) 119, (byte) 214, (byte) 38, (byte) 225, (byte) 105, + (byte) 20, (byte) 99, (byte) 85, (byte) 33, (byte) 12, (byte) 125, + }; - // vector used in calculating key schedule (powers of x in GF(256)) - private static final int[] rcon = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, - 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 }; + // vector used in calculating key schedule (powers of x in GF(256)) + private static final int[] rcon = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, + 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 + }; - // precomputation tables of calculations for rounds - private static final int[] T0 = { 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6, - 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, - 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, - 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, 0xc2b7b775, - 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551, - 0x34e5e5d1, 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795, 0x65232346, - 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, - 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, - 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, - 0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, - 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, - 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a, - 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, - 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, - 0x63212142, 0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, - 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, - 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, - 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, - 0x76dbdbad, 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8, - 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, - 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac, - 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a, - 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, - 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, - 0x05030306, 0x01f6f6f7, 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, - 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, - 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, - 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, - 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c }; + // precomputation tables of calculations for rounds + private static final int[] T0 = { 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6, + 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, + 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, + 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, 0xc2b7b775, + 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551, + 0x34e5e5d1, 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795, 0x65232346, + 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, + 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, + 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, + 0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, + 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, + 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a, + 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, + 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1, 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, + 0x63212142, 0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, + 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, + 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, + 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, + 0x76dbdbad, 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8, + 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, + 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac, + 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a, + 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, + 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, + 0x05030306, 0x01f6f6f7, 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, + 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, + 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, + 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, + 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c + }; - private static final int[] T1 = { 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd, - 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6, - 0x7676ec9a, 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87, 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, - 0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b, 0xb7b775c2, - 0xfdfde11c, 0x93933dae, 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, 0x3434685c, 0xa5a551f4, - 0xe5e5d134, 0xf1f1f908, 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f, 0x0404080c, 0xc7c79552, 0x23234665, - 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d, - 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, - 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb, 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, - 0x2f2f5e71, 0x84841397, 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060, 0xfcfce31f, 0xb1b179c8, - 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a, - 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, 0x45458acf, - 0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe, - 0x404080c0, 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104, 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, - 0x21214263, 0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f, - 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47, 0x6464c8ac, - 0x5d5dbae7, 0x1919322b, 0x7373e695, 0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e, - 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, - 0xdbdbad76, 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4, - 0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b, 0xe7e7d532, - 0xc8c88b43, 0x37376e59, 0x6d6ddab7, 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4, 0x5656acfa, - 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018, 0xbaba6fd5, 0x7878f088, 0x25254a6f, - 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751, 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, - 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa, 0x484890d8, - 0x03030605, 0xf6f6f701, 0x0e0e1c12, 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, 0x86861791, 0xc1c19958, - 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, - 0x949433a7, 0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a, - 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, - 0x999929b0, 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a }; + private static final int[] T1 = { 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd, + 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6, + 0x7676ec9a, 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87, 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, + 0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b, 0xb7b775c2, + 0xfdfde11c, 0x93933dae, 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, 0x3434685c, 0xa5a551f4, + 0xe5e5d134, 0xf1f1f908, 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f, 0x0404080c, 0xc7c79552, 0x23234665, + 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d, + 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, + 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb, 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, + 0x2f2f5e71, 0x84841397, 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060, 0xfcfce31f, 0xb1b179c8, + 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a, + 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, 0x45458acf, + 0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe, + 0x404080c0, 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104, 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, + 0x21214263, 0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f, + 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47, 0x6464c8ac, + 0x5d5dbae7, 0x1919322b, 0x7373e695, 0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e, + 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, + 0xdbdbad76, 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4, + 0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b, 0xe7e7d532, + 0xc8c88b43, 0x37376e59, 0x6d6ddab7, 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4, 0x5656acfa, + 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018, 0xbaba6fd5, 0x7878f088, 0x25254a6f, + 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751, 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, + 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa, 0x484890d8, + 0x03030605, 0xf6f6f701, 0x0e0e1c12, 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, 0x86861791, 0xc1c19958, + 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, + 0x949433a7, 0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a, + 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, + 0x999929b0, 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a + }; - private static final int[] T2 = { 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b, - 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab, - 0x76ec9a76, 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d, 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, - 0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0, 0xb775c2b7, - 0xfde11cfd, 0x933dae93, 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, 0x34685c34, 0xa551f4a5, - 0xe5d134e5, 0xf1f908f1, 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15, 0x04080c04, 0xc79552c7, 0x23466523, - 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2, - 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, - 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0, 0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, - 0x2f5e712f, 0x84139784, 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020, 0xfce31ffc, 0xb179c8b1, - 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf, - 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, 0x458acf45, - 0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3, - 0x4080c040, 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5, 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, - 0x21426321, 0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec, - 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d, 0x64c8ac64, - 0x5dbae75d, 0x19322b19, 0x73e69573, 0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a, - 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, - 0xdbad76db, 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c, - 0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79, 0xe7d532e7, - 0xc88b43c8, 0x376e5937, 0x6ddab76d, 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c, 0x56acfa56, - 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808, 0xba6fd5ba, 0x78f08878, 0x254a6f25, - 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6, 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, - 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66, 0x4890d848, - 0x03060503, 0xf6f701f6, 0x0e1c120e, 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, 0x86179186, 0xc19958c1, - 0x1d3a271d, 0x9e27b99e, 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9, 0x8e07898e, - 0x9433a794, 0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf, - 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, - 0x9929b099, 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16 }; + private static final int[] T2 = { 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b, + 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab, + 0x76ec9a76, 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d, 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, + 0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0, 0xb775c2b7, + 0xfde11cfd, 0x933dae93, 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, 0x34685c34, 0xa551f4a5, + 0xe5d134e5, 0xf1f908f1, 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15, 0x04080c04, 0xc79552c7, 0x23466523, + 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2, + 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, + 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0, 0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, + 0x2f5e712f, 0x84139784, 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020, 0xfce31ffc, 0xb179c8b1, + 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf, + 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, 0x458acf45, + 0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3, + 0x4080c040, 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5, 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, + 0x21426321, 0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec, + 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d, 0x64c8ac64, + 0x5dbae75d, 0x19322b19, 0x73e69573, 0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a, + 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, + 0xdbad76db, 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c, + 0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79, 0xe7d532e7, + 0xc88b43c8, 0x376e5937, 0x6ddab76d, 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c, 0x56acfa56, + 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808, 0xba6fd5ba, 0x78f08878, 0x254a6f25, + 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6, 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, + 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66, 0x4890d848, + 0x03060503, 0xf6f701f6, 0x0e1c120e, 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, 0x86179186, 0xc19958c1, + 0x1d3a271d, 0x9e27b99e, 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9, 0x8e07898e, + 0x9433a794, 0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf, + 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, + 0x9929b099, 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16 + }; - private static final int[] T3 = { 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b, - 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab, - 0xec9a7676, 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d, 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, - 0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, - 0xe11cfdfd, 0x3dae9393, 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, 0x685c3434, 0x51f4a5a5, - 0xd134e5e5, 0xf908f1f1, 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515, 0x080c0404, 0x9552c7c7, 0x46652323, - 0x9d5ec3c3, 0x30281818, 0x37a19696, 0x0a0f0505, 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2, - 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, - 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0, 0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, - 0x5e712f2f, 0x13978484, 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020, 0xe31ffcfc, 0x79c8b1b1, - 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf, - 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, 0x8acf4545, - 0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3, - 0x80c04040, 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5, 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, - 0x42632121, 0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec, - 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d, 0xc8ac6464, - 0xbae75d5d, 0x322b1919, 0xe6957373, 0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a, - 0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, - 0xad76dbdb, 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c, - 0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979, 0xd532e7e7, - 0x8b43c8c8, 0x6e593737, 0xdab76d6d, 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c, 0xacfa5656, - 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808, 0x6fd5baba, 0xf0887878, 0x4a6f2525, - 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6, 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, - 0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666, 0x90d84848, - 0x06050303, 0xf701f6f6, 0x1c120e0e, 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, 0x17918686, 0x9958c1c1, - 0x3a271d1d, 0x27b99e9e, 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9, 0x07898e8e, - 0x33a79494, 0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf, - 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868, 0x82c34141, - 0x29b09999, 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616 }; - - private static final int[] Tinv0 = { 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, - 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, - 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, - 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, 0x6a89c275, - 0x78798ef4, 0x6b3e5899, 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5, - 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f, 0x876cde94, - 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3, - 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, - 0xd5be0506, 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040, - 0x069f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491, 0x055dc471, 0x6fd40604, - 0xff155060, 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, - 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000, 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd, - 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, - 0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, - 0x1d171b12, 0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, - 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, - 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, - 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, - 0xef903322, 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, - 0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, 0xbe805d9f, - 0x7c93d069, 0xa92dd56f, 0xb31225cf, 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd, 0xf418596e, - 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea, - 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, - 0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, 0xe3b5d19e, - 0x1b886a4c, 0xb81f2cc1, 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92, - 0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7, 0xede51ce1, - 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, - 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, - 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0 }; + private static final int[] T3 = { 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b, + 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab, + 0xec9a7676, 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d, 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, + 0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, + 0xe11cfdfd, 0x3dae9393, 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, 0x685c3434, 0x51f4a5a5, + 0xd134e5e5, 0xf908f1f1, 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515, 0x080c0404, 0x9552c7c7, 0x46652323, + 0x9d5ec3c3, 0x30281818, 0x37a19696, 0x0a0f0505, 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2, + 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, + 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0, 0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, + 0x5e712f2f, 0x13978484, 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020, 0xe31ffcfc, 0x79c8b1b1, + 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf, + 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, 0x8acf4545, + 0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3, + 0x80c04040, 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5, 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, + 0x42632121, 0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec, + 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d, 0xc8ac6464, + 0xbae75d5d, 0x322b1919, 0xe6957373, 0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a, + 0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, + 0xad76dbdb, 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c, + 0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979, 0xd532e7e7, + 0x8b43c8c8, 0x6e593737, 0xdab76d6d, 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c, 0xacfa5656, + 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808, 0x6fd5baba, 0xf0887878, 0x4a6f2525, + 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6, 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, + 0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666, 0x90d84848, + 0x06050303, 0xf701f6f6, 0x1c120e0e, 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, 0x17918686, 0x9958c1c1, + 0x3a271d1d, 0x27b99e9e, 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9, 0x07898e8e, + 0x33a79494, 0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf, + 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868, 0x82c34141, + 0x29b09999, 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616 + }; - private static final int[] Tinv1 = { 0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb, 0x459d1ff1, - 0x58faacab, 0x03e34b93, 0xfa302055, 0x6d76adf6, 0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680, - 0xa362b58f, 0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1, 0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6, - 0x5f8f03e7, 0x9c921595, 0x7a6dbfeb, 0x595295da, 0x83bed42d, 0x217458d3, 0x69e04929, 0xc8c98e44, 0x89c2756a, - 0x798ef478, 0x3e58996b, 0x71b927dd, 0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4, 0x4adf6318, 0x311ae582, - 0x33519760, 0x7f536245, 0x7764b1e0, 0xae6bbb84, 0xa081fe1c, 0x2b08f994, 0x68487058, 0xfd458f19, 0x6cde9487, - 0xf87b52b7, 0xd373ab23, 0x024b72e2, 0x8f1fe357, 0xab55662a, 0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x0837d3a5, - 0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c, 0x1ccf8a2b, 0xb479a792, 0xf207f3f0, 0xe2694ea1, 0xf4da65cd, - 0xbe0506d5, 0x6234d11f, 0xfea6c48a, 0x532e349d, 0x55f3a2a0, 0xe18a0532, 0xebf6a475, 0xec830b39, 0xef6040aa, - 0x9f715e06, 0x106ebd51, 0x8a213ef9, 0x06dd963d, 0x053eddae, 0xbde64d46, 0x8d5491b5, 0x5dc47105, 0xd406046f, - 0x155060ff, 0xfb981924, 0xe9bdd697, 0x434089cc, 0x9ed96777, 0x42e8b0bd, 0x8b890788, 0x5b19e738, 0xeec879db, - 0x0a7ca147, 0x0f427ce9, 0x1e84f8c9, 0x00000000, 0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e, 0xff0efdfb, - 0x38850f56, 0xd5ae3d1e, 0x392d3627, 0xd90f0a64, 0xa65c6821, 0x545b9bd1, 0x2e36243a, 0x670a0cb1, 0xe757930f, - 0x96eeb4d2, 0x919b1b9e, 0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16, 0xba93e20a, 0x2aa0c0e5, 0xe0223c43, - 0x171b121d, 0x0d090e0b, 0xc78bf2ad, 0xa8b62db9, 0xa91e14c8, 0x19f15785, 0x0775af4c, 0xdd99eebb, 0x607fa3fd, - 0x2601f79f, 0xf5725cbc, 0x3b6644c5, 0x7efb5b34, 0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863, 0xdc31d7ca, - 0x85634210, 0x22971340, 0x11c68420, 0x244a857d, 0x3dbbd2f8, 0x32f9ae11, 0xa129c76d, 0x2f9e1d4b, 0x30b2dcf3, - 0x52860dec, 0xe3c177d0, 0x16b32b6c, 0xb970a999, 0x489411fa, 0x64e94722, 0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, - 0x903322ef, 0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0x0bd49836, 0x81f5a6cf, 0xde7aa528, 0x8eb7da26, 0xbfad3fa4, - 0x9d3a2ce4, 0x9278500d, 0xcc5f6a9b, 0x467e5462, 0x138df6c2, 0xb8d890e8, 0xf7392e5e, 0xafc382f5, 0x805d9fbe, - 0x93d0697c, 0x2dd56fa9, 0x1225cfb3, 0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b, 0x7826cd09, 0x18596ef4, - 0xb79aec01, 0x9a4f83a8, 0x6e95e665, 0xe6ffaa7e, 0xcfbc2108, 0xe815efe6, 0x9be7bad9, 0x366f4ace, 0x099fead4, - 0x7cb029d6, 0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0, 0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315, - 0x9804f14a, 0xdaec41f7, 0x50cd7f0e, 0xf691172f, 0xd64d768d, 0xb0ef434d, 0x4daacc54, 0x0496e4df, 0xb5d19ee3, - 0x886a4c1b, 0x1f2cc1b8, 0x5165467f, 0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e, 0x1d67b35a, 0xd2db9252, - 0x5610e933, 0x47d66d13, 0x61d79a8c, 0x0ca1377a, 0x14f8598e, 0x3c13eb89, 0x27a9ceee, 0xc961b735, 0xe51ce1ed, - 0xb1477a3c, 0xdfd29c59, 0x73f2553f, 0xce141879, 0x37c773bf, 0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886, - 0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672, 0x25e2bc0c, 0x493c288b, 0x950dff41, 0x01a83971, - 0xb30c08de, 0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874, 0x57b8d042 }; + private static final int[] Tinv0 = { 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, + 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, + 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, + 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, 0x6a89c275, + 0x78798ef4, 0x6b3e5899, 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5, + 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f, 0x876cde94, + 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3, + 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, + 0xd5be0506, 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040, + 0x069f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491, 0x055dc471, 0x6fd40604, + 0xff155060, 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, + 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000, 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd, + 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, + 0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, + 0x1d171b12, 0x0b0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, + 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, + 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, + 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, + 0xef903322, 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, + 0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, 0xbe805d9f, + 0x7c93d069, 0xa92dd56f, 0xb31225cf, 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd, 0xf418596e, + 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea, + 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, + 0x4a9804f1, 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, 0xe3b5d19e, + 0x1b886a4c, 0xb81f2cc1, 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92, + 0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7, 0xede51ce1, + 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, + 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, + 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0 + }; - private static final int[] Tinv2 = { 0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b, 0x9d1ff145, - 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d, 0xcc889176, 0x02f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044, - 0x62b58fa3, 0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0, 0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9, - 0x8f03e75f, 0x9215959c, 0x6dbfeb7a, 0x5295da59, 0xbed42d83, 0x7458d321, 0xe0492969, 0xc98e44c8, 0xc2756a89, - 0x8ef47879, 0x58996b3e, 0xb927dd71, 0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a, 0xdf63184a, 0x1ae58231, - 0x51976033, 0x5362457f, 0x64b1e077, 0x6bbb84ae, 0x81fe1ca0, 0x08f9942b, 0x48705868, 0x458f19fd, 0xde94876c, - 0x7b52b7f8, 0x73ab23d3, 0x4b72e202, 0x1fe3578f, 0x55662aab, 0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508, - 0x2830f287, 0xbf23b2a5, 0x0302ba6a, 0x16ed5c82, 0xcf8a2b1c, 0x79a792b4, 0x07f3f0f2, 0x694ea1e2, 0xda65cdf4, - 0x0506d5be, 0x34d11f62, 0xa6c48afe, 0x2e349d53, 0xf3a2a055, 0x8a0532e1, 0xf6a475eb, 0x830b39ec, 0x6040aaef, - 0x715e069f, 0x6ebd5110, 0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd, 0x5491b58d, 0xc471055d, 0x06046fd4, - 0x5060ff15, 0x981924fb, 0xbdd697e9, 0x4089cc43, 0xd967779e, 0xe8b0bd42, 0x8907888b, 0x19e7385b, 0xc879dbee, - 0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x00000000, 0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72, 0x0efdfbff, - 0x850f5638, 0xae3d1ed5, 0x2d362739, 0x0f0a64d9, 0x5c6821a6, 0x5b9bd154, 0x36243a2e, 0x0a0cb167, 0x57930fe7, - 0xeeb4d296, 0x9b1b9e91, 0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a, 0x93e20aba, 0xa0c0e52a, 0x223c43e0, - 0x1b121d17, 0x090e0b0d, 0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9, 0xf1578519, 0x75af4c07, 0x99eebbdd, 0x7fa3fd60, - 0x01f79f26, 0x725cbcf5, 0x6644c53b, 0xfb5b347e, 0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1, 0x31d7cadc, - 0x63421085, 0x97134022, 0xc6842011, 0x4a857d24, 0xbbd2f83d, 0xf9ae1132, 0x29c76da1, 0x9e1d4b2f, 0xb2dcf330, - 0x860dec52, 0xc177d0e3, 0xb32b6c16, 0x70a999b9, 0x9411fa48, 0xe9472264, 0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, - 0x3322ef90, 0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b, 0xf5a6cf81, 0x7aa528de, 0xb7da268e, 0xad3fa4bf, - 0x3a2ce49d, 0x78500d92, 0x5f6a9bcc, 0x7e546246, 0x8df6c213, 0xd890e8b8, 0x392e5ef7, 0xc382f5af, 0x5d9fbe80, - 0xd0697c93, 0xd56fa92d, 0x25cfb312, 0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb, 0x26cd0978, 0x596ef418, - 0x9aec01b7, 0x4f83a89a, 0x95e6656e, 0xffaa7ee6, 0xbc2108cf, 0x15efe6e8, 0xe7bad99b, 0x6f4ace36, 0x9fead409, - 0xb029d67c, 0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066, 0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8, - 0x04f14a98, 0xec41f7da, 0xcd7f0e50, 0x91172ff6, 0x4d768dd6, 0xef434db0, 0xaacc544d, 0x96e4df04, 0xd19ee3b5, - 0x6a4c1b88, 0x2cc1b81f, 0x65467f51, 0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41, 0x67b35a1d, 0xdb9252d2, - 0x10e93356, 0xd66d1347, 0xd79a8c61, 0xa1377a0c, 0xf8598e14, 0x13eb893c, 0xa9ceee27, 0x61b735c9, 0x1ce1ede5, - 0x477a3cb1, 0xd29c59df, 0xf2553f73, 0x141879ce, 0xc773bf37, 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db, - 0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3, 0xe2bc0c25, 0x3c288b49, 0x0dff4195, 0xa8397101, - 0x0c08deb3, 0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c, 0xb8d04257 }; + private static final int[] Tinv1 = { 0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb, 0x459d1ff1, + 0x58faacab, 0x03e34b93, 0xfa302055, 0x6d76adf6, 0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680, + 0xa362b58f, 0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1, 0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6, + 0x5f8f03e7, 0x9c921595, 0x7a6dbfeb, 0x595295da, 0x83bed42d, 0x217458d3, 0x69e04929, 0xc8c98e44, 0x89c2756a, + 0x798ef478, 0x3e58996b, 0x71b927dd, 0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4, 0x4adf6318, 0x311ae582, + 0x33519760, 0x7f536245, 0x7764b1e0, 0xae6bbb84, 0xa081fe1c, 0x2b08f994, 0x68487058, 0xfd458f19, 0x6cde9487, + 0xf87b52b7, 0xd373ab23, 0x024b72e2, 0x8f1fe357, 0xab55662a, 0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x0837d3a5, + 0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c, 0x1ccf8a2b, 0xb479a792, 0xf207f3f0, 0xe2694ea1, 0xf4da65cd, + 0xbe0506d5, 0x6234d11f, 0xfea6c48a, 0x532e349d, 0x55f3a2a0, 0xe18a0532, 0xebf6a475, 0xec830b39, 0xef6040aa, + 0x9f715e06, 0x106ebd51, 0x8a213ef9, 0x06dd963d, 0x053eddae, 0xbde64d46, 0x8d5491b5, 0x5dc47105, 0xd406046f, + 0x155060ff, 0xfb981924, 0xe9bdd697, 0x434089cc, 0x9ed96777, 0x42e8b0bd, 0x8b890788, 0x5b19e738, 0xeec879db, + 0x0a7ca147, 0x0f427ce9, 0x1e84f8c9, 0x00000000, 0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e, 0xff0efdfb, + 0x38850f56, 0xd5ae3d1e, 0x392d3627, 0xd90f0a64, 0xa65c6821, 0x545b9bd1, 0x2e36243a, 0x670a0cb1, 0xe757930f, + 0x96eeb4d2, 0x919b1b9e, 0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16, 0xba93e20a, 0x2aa0c0e5, 0xe0223c43, + 0x171b121d, 0x0d090e0b, 0xc78bf2ad, 0xa8b62db9, 0xa91e14c8, 0x19f15785, 0x0775af4c, 0xdd99eebb, 0x607fa3fd, + 0x2601f79f, 0xf5725cbc, 0x3b6644c5, 0x7efb5b34, 0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863, 0xdc31d7ca, + 0x85634210, 0x22971340, 0x11c68420, 0x244a857d, 0x3dbbd2f8, 0x32f9ae11, 0xa129c76d, 0x2f9e1d4b, 0x30b2dcf3, + 0x52860dec, 0xe3c177d0, 0x16b32b6c, 0xb970a999, 0x489411fa, 0x64e94722, 0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, + 0x903322ef, 0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0x0bd49836, 0x81f5a6cf, 0xde7aa528, 0x8eb7da26, 0xbfad3fa4, + 0x9d3a2ce4, 0x9278500d, 0xcc5f6a9b, 0x467e5462, 0x138df6c2, 0xb8d890e8, 0xf7392e5e, 0xafc382f5, 0x805d9fbe, + 0x93d0697c, 0x2dd56fa9, 0x1225cfb3, 0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b, 0x7826cd09, 0x18596ef4, + 0xb79aec01, 0x9a4f83a8, 0x6e95e665, 0xe6ffaa7e, 0xcfbc2108, 0xe815efe6, 0x9be7bad9, 0x366f4ace, 0x099fead4, + 0x7cb029d6, 0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0, 0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315, + 0x9804f14a, 0xdaec41f7, 0x50cd7f0e, 0xf691172f, 0xd64d768d, 0xb0ef434d, 0x4daacc54, 0x0496e4df, 0xb5d19ee3, + 0x886a4c1b, 0x1f2cc1b8, 0x5165467f, 0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e, 0x1d67b35a, 0xd2db9252, + 0x5610e933, 0x47d66d13, 0x61d79a8c, 0x0ca1377a, 0x14f8598e, 0x3c13eb89, 0x27a9ceee, 0xc961b735, 0xe51ce1ed, + 0xb1477a3c, 0xdfd29c59, 0x73f2553f, 0xce141879, 0x37c773bf, 0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886, + 0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672, 0x25e2bc0c, 0x493c288b, 0x950dff41, 0x01a83971, + 0xb30c08de, 0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874, 0x57b8d042 + }; - private static final int[] Tinv3 = { 0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab, 0x1ff1459d, - 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76, 0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435, - 0xb58fa362, 0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe, 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, - 0x03e75f8f, 0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174, 0x492969e0, 0x8e44c8c9, 0x756a89c2, - 0xf478798e, 0x996b3e58, 0x27dd71b9, 0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace, 0x63184adf, 0xe582311a, - 0x97603351, 0x62457f53, 0xb1e07764, 0xbb84ae6b, 0xfe1ca081, 0xf9942b08, 0x70586848, 0x8f19fd45, 0x94876cde, - 0x52b7f87b, 0xab23d373, 0x72e2024b, 0xe3578f1f, 0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837, - 0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, 0x8a2b1ccf, 0xa792b479, 0xf3f0f207, 0x4ea1e269, 0x65cdf4da, - 0x06d5be05, 0xd11f6234, 0xc48afea6, 0x349d532e, 0xa2a055f3, 0x0532e18a, 0xa475ebf6, 0x0b39ec83, 0x40aaef60, - 0x5e069f71, 0xbd51106e, 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, 0x91b58d54, 0x71055dc4, 0x046fd406, - 0x60ff1550, 0x1924fb98, 0xd697e9bd, 0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x07888b89, 0xe7385b19, 0x79dbeec8, - 0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000, 0x09838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a, 0xfdfbff0e, - 0x0f563885, 0x3d1ed5ae, 0x3627392d, 0x0a64d90f, 0x6821a65c, 0x9bd1545b, 0x243a2e36, 0x0cb1670a, 0x930fe757, - 0xb4d296ee, 0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12, 0xe20aba93, 0xc0e52aa0, 0x3c43e022, - 0x121d171b, 0x0e0b0d09, 0xf2adc78b, 0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775, 0xeebbdd99, 0xa3fd607f, - 0xf79f2601, 0x5cbcf572, 0x44c53b66, 0x5b347efb, 0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4, 0xd7cadc31, - 0x42108563, 0x13402297, 0x842011c6, 0x857d244a, 0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2, - 0x0dec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894, 0x472264e9, 0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, - 0x22ef9033, 0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4, 0xa6cf81f5, 0xa528de7a, 0xda268eb7, 0x3fa4bfad, - 0x2ce49d3a, 0x500d9278, 0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8, 0x2e5ef739, 0x82f5afc3, 0x9fbe805d, - 0x697c93d0, 0x6fa92dd5, 0xcfb31225, 0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826, 0x6ef41859, - 0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff, 0x2108cfbc, 0xefe6e815, 0xbad99be7, 0x4ace366f, 0xead4099f, - 0x29d67cb0, 0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2, 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, - 0xf14a9804, 0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef, 0xcc544daa, 0xe4df0496, 0x9ee3b5d1, - 0x4c1b886a, 0xc1b81f2c, 0x467f5165, 0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b, 0xb35a1d67, 0x9252d2db, - 0xe9335610, 0x6d1347d6, 0x9a8c61d7, 0x377a0ca1, 0x598e14f8, 0xeb893c13, 0xceee27a9, 0xb735c961, 0xe1ede51c, - 0x7a3cb147, 0x9c59dfd2, 0x553f73f2, 0x1879ce14, 0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44, - 0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d, 0xbc0c25e2, 0x288b493c, 0xff41950d, 0x397101a8, - 0x08deb30c, 0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c, 0xd04257b8 }; - - private int shift(int r, int shift) - { - return (((r >>> shift) | (r << (32 - shift)))); - } - - /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ + private static final int[] Tinv2 = { 0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b, 0x9d1ff145, + 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d, 0xcc889176, 0x02f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044, + 0x62b58fa3, 0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0, 0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9, + 0x8f03e75f, 0x9215959c, 0x6dbfeb7a, 0x5295da59, 0xbed42d83, 0x7458d321, 0xe0492969, 0xc98e44c8, 0xc2756a89, + 0x8ef47879, 0x58996b3e, 0xb927dd71, 0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a, 0xdf63184a, 0x1ae58231, + 0x51976033, 0x5362457f, 0x64b1e077, 0x6bbb84ae, 0x81fe1ca0, 0x08f9942b, 0x48705868, 0x458f19fd, 0xde94876c, + 0x7b52b7f8, 0x73ab23d3, 0x4b72e202, 0x1fe3578f, 0x55662aab, 0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508, + 0x2830f287, 0xbf23b2a5, 0x0302ba6a, 0x16ed5c82, 0xcf8a2b1c, 0x79a792b4, 0x07f3f0f2, 0x694ea1e2, 0xda65cdf4, + 0x0506d5be, 0x34d11f62, 0xa6c48afe, 0x2e349d53, 0xf3a2a055, 0x8a0532e1, 0xf6a475eb, 0x830b39ec, 0x6040aaef, + 0x715e069f, 0x6ebd5110, 0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd, 0x5491b58d, 0xc471055d, 0x06046fd4, + 0x5060ff15, 0x981924fb, 0xbdd697e9, 0x4089cc43, 0xd967779e, 0xe8b0bd42, 0x8907888b, 0x19e7385b, 0xc879dbee, + 0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x00000000, 0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72, 0x0efdfbff, + 0x850f5638, 0xae3d1ed5, 0x2d362739, 0x0f0a64d9, 0x5c6821a6, 0x5b9bd154, 0x36243a2e, 0x0a0cb167, 0x57930fe7, + 0xeeb4d296, 0x9b1b9e91, 0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a, 0x93e20aba, 0xa0c0e52a, 0x223c43e0, + 0x1b121d17, 0x090e0b0d, 0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9, 0xf1578519, 0x75af4c07, 0x99eebbdd, 0x7fa3fd60, + 0x01f79f26, 0x725cbcf5, 0x6644c53b, 0xfb5b347e, 0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1, 0x31d7cadc, + 0x63421085, 0x97134022, 0xc6842011, 0x4a857d24, 0xbbd2f83d, 0xf9ae1132, 0x29c76da1, 0x9e1d4b2f, 0xb2dcf330, + 0x860dec52, 0xc177d0e3, 0xb32b6c16, 0x70a999b9, 0x9411fa48, 0xe9472264, 0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, + 0x3322ef90, 0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b, 0xf5a6cf81, 0x7aa528de, 0xb7da268e, 0xad3fa4bf, + 0x3a2ce49d, 0x78500d92, 0x5f6a9bcc, 0x7e546246, 0x8df6c213, 0xd890e8b8, 0x392e5ef7, 0xc382f5af, 0x5d9fbe80, + 0xd0697c93, 0xd56fa92d, 0x25cfb312, 0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb, 0x26cd0978, 0x596ef418, + 0x9aec01b7, 0x4f83a89a, 0x95e6656e, 0xffaa7ee6, 0xbc2108cf, 0x15efe6e8, 0xe7bad99b, 0x6f4ace36, 0x9fead409, + 0xb029d67c, 0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066, 0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8, + 0x04f14a98, 0xec41f7da, 0xcd7f0e50, 0x91172ff6, 0x4d768dd6, 0xef434db0, 0xaacc544d, 0x96e4df04, 0xd19ee3b5, + 0x6a4c1b88, 0x2cc1b81f, 0x65467f51, 0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41, 0x67b35a1d, 0xdb9252d2, + 0x10e93356, 0xd66d1347, 0xd79a8c61, 0xa1377a0c, 0xf8598e14, 0x13eb893c, 0xa9ceee27, 0x61b735c9, 0x1ce1ede5, + 0x477a3cb1, 0xd29c59df, 0xf2553f73, 0x141879ce, 0xc773bf37, 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db, + 0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3, 0xe2bc0c25, 0x3c288b49, 0x0dff4195, 0xa8397101, + 0x0c08deb3, 0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c, 0xb8d04257 + }; - private static final int m1 = 0x80808080; - private static final int m2 = 0x7f7f7f7f; - private static final int m3 = 0x0000001b; - - private int FFmulX(int x) - { - return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3)); - } - - /* - * The following defines provide alternative definitions of FFmulX that - * might give improved performance if a fast 32-bit multiply is not - * available. - * - * private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & - * m2) < < 1) ^ ((u >>> 3) | (u >>> 6)); } private static final int m4 = - * 0x1b1b1b1b; private int FFmulX(int x) { int u = x & m1; return ((x & m2) < < - * 1) ^ ((u - (u >>> 7)) & m4); } - * - */ - - private int inv_mcol(int x) - { - int f2 = FFmulX(x); - int f4 = FFmulX(f2); - int f8 = FFmulX(f4); - int f9 = x ^ f8; - - return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24); - } + private static final int[] Tinv3 = { 0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab, 0x1ff1459d, + 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76, 0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435, + 0xb58fa362, 0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe, 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, + 0x03e75f8f, 0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174, 0x492969e0, 0x8e44c8c9, 0x756a89c2, + 0xf478798e, 0x996b3e58, 0x27dd71b9, 0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace, 0x63184adf, 0xe582311a, + 0x97603351, 0x62457f53, 0xb1e07764, 0xbb84ae6b, 0xfe1ca081, 0xf9942b08, 0x70586848, 0x8f19fd45, 0x94876cde, + 0x52b7f87b, 0xab23d373, 0x72e2024b, 0xe3578f1f, 0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837, + 0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, 0x8a2b1ccf, 0xa792b479, 0xf3f0f207, 0x4ea1e269, 0x65cdf4da, + 0x06d5be05, 0xd11f6234, 0xc48afea6, 0x349d532e, 0xa2a055f3, 0x0532e18a, 0xa475ebf6, 0x0b39ec83, 0x40aaef60, + 0x5e069f71, 0xbd51106e, 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, 0x91b58d54, 0x71055dc4, 0x046fd406, + 0x60ff1550, 0x1924fb98, 0xd697e9bd, 0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x07888b89, 0xe7385b19, 0x79dbeec8, + 0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000, 0x09838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a, 0xfdfbff0e, + 0x0f563885, 0x3d1ed5ae, 0x3627392d, 0x0a64d90f, 0x6821a65c, 0x9bd1545b, 0x243a2e36, 0x0cb1670a, 0x930fe757, + 0xb4d296ee, 0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12, 0xe20aba93, 0xc0e52aa0, 0x3c43e022, + 0x121d171b, 0x0e0b0d09, 0xf2adc78b, 0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775, 0xeebbdd99, 0xa3fd607f, + 0xf79f2601, 0x5cbcf572, 0x44c53b66, 0x5b347efb, 0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4, 0xd7cadc31, + 0x42108563, 0x13402297, 0x842011c6, 0x857d244a, 0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2, + 0x0dec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894, 0x472264e9, 0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, + 0x22ef9033, 0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4, 0xa6cf81f5, 0xa528de7a, 0xda268eb7, 0x3fa4bfad, + 0x2ce49d3a, 0x500d9278, 0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8, 0x2e5ef739, 0x82f5afc3, 0x9fbe805d, + 0x697c93d0, 0x6fa92dd5, 0xcfb31225, 0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826, 0x6ef41859, + 0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff, 0x2108cfbc, 0xefe6e815, 0xbad99be7, 0x4ace366f, 0xead4099f, + 0x29d67cb0, 0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2, 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, + 0xf14a9804, 0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef, 0xcc544daa, 0xe4df0496, 0x9ee3b5d1, + 0x4c1b886a, 0xc1b81f2c, 0x467f5165, 0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b, 0xb35a1d67, 0x9252d2db, + 0xe9335610, 0x6d1347d6, 0x9a8c61d7, 0x377a0ca1, 0x598e14f8, 0xeb893c13, 0xceee27a9, 0xb735c961, 0xe1ede51c, + 0x7a3cb147, 0x9c59dfd2, 0x553f73f2, 0x1879ce14, 0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44, + 0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d, 0xbc0c25e2, 0x288b493c, 0xff41950d, 0x397101a8, + 0x08deb30c, 0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c, 0xd04257b8 + }; - private int subWord(int x) - { - return (S[x & 255] & 255 | ((S[(x >> 8) & 255] & 255) << 8) | ((S[(x >> 16) & 255] & 255) << 16) | S[(x >> 24) & 255] << 24); - } + private int shift(int r, int shift) { + return (((r >>> shift) | (r << (32 - shift)))); + } + + /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ - /** - * Calculate the necessary round keys The number of calculations depends on - * key size and block size AES specified a fixed block size of 128 bits and - * key sizes 128/192/256 bits This code is written assuming those are the - * only possible values - */ - private int[][] generateWorkingKey(byte[] key, boolean forEncryption) - { - int KC = key.length / 4; // key length in words - int t; + private static final int m1 = 0x80808080; + private static final int m2 = 0x7f7f7f7f; + private static final int m3 = 0x0000001b; + + private int FFmulX(int x) { + return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3)); + } - if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length)) - { - throw new IllegalArgumentException("Key length not 128/192/256 bits."); - } - - ROUNDS = KC + 6; // This is not always true for the generalized - // Rijndael that allows larger block sizes - int[][] W = new int[ROUNDS + 1][4]; // 4 words in a block + /* + * The following defines provide alternative definitions of FFmulX that + * might give improved performance if a fast 32-bit multiply is not + * available. + * + * private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & + * m2) < < 1) ^ ((u >>> 3) | (u >>> 6)); } private static final int m4 = + * 0x1b1b1b1b; private int FFmulX(int x) { int u = x & m1; return ((x & m2) < < + * 1) ^ ((u - (u >>> 7)) & m4); } + * + */ - // - // copy the key into the round key array - // + private int inv_mcol(int x) { + int f2 = FFmulX(x); + int f4 = FFmulX(f2); + int f8 = FFmulX(f4); + int f9 = x ^ f8; + return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24); + } - t = 0; - for (int i = 0; i < key.length; t++) - { - W[t >> 2][t & 3] = (key[i] & 0xff) | ((key[i + 1] & 0xff) << 8) | ((key[i + 2] & 0xff) << 16) - | (key[i + 3] << 24); - i += 4; - } + private int subWord(int x) { + return (S[x & 255] & 255 | ((S[(x >> 8) & 255] & 255) << 8) | ((S[(x >> 16) & 255] & 255) << 16) | S[(x >> 24) & 255] << 24); + } - // - // while not enough round key material calculated - // calculate new values - // - int k = (ROUNDS + 1) << 2; - for (int i = KC; (i < k); i++) - { - int temp = W[(i - 1) >> 2][(i - 1) & 3]; - if ((i % KC) == 0) - { - temp = subWord(shift(temp, 8)) ^ rcon[(i / KC) - 1]; - } - else if ((KC > 6) && ((i % KC) == 4)) - { - temp = subWord(temp); - } + /** + * Calculate the necessary round keys The number of calculations depends on + * key size and block size AES specified a fixed block size of 128 bits and + * key sizes 128/192/256 bits This code is written assuming those are the + * only possible values + */ + private int[][] generateWorkingKey(byte[] key, boolean forEncryption) { + int KC = key.length / 4; // key length in words + int t; - W[i >> 2][i & 3] = W[(i - KC) >> 2][(i - KC) & 3] ^ temp; - } + if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length)) { + throw new IllegalArgumentException("Key length not 128/192/256 bits."); + } - if (!forEncryption) - { - for (int j = 1; j < ROUNDS; j++) - { - for (int i = 0; i < 4; i++) - { - W[j][i] = inv_mcol(W[j][i]); - } - } - } + ROUNDS = KC + 6; // This is not always true for the generalized + // Rijndael that allows larger block sizes + int[][] W = new int[ROUNDS + 1][4]; // 4 words in a block + // + // copy the key into the round key array + // + t = 0; - return W; - } + for (int i = 0; i < key.length; t++) { + W[t >> 2][t & 3] = (key[i] & 0xff) | ((key[i + 1] & 0xff) << 8) | ((key[i + 2] & 0xff) << 16) + | (key[i + 3] << 24); + i += 4; + } - private int ROUNDS; - private int[][] WorkingKey = null; - private int C0, C1, C2, C3; - private boolean doEncrypt; + // + // while not enough round key material calculated + // calculate new values + // + int k = (ROUNDS + 1) << 2; - private static final int BLOCK_SIZE = 16; + for (int i = KC; (i < k); i++) { + int temp = W[(i - 1) >> 2][(i - 1) & 3]; - /** - * default constructor - 128 bit block size. - */ - public AES() - { - } + if ((i % KC) == 0) { + temp = subWord(shift(temp, 8)) ^ rcon[(i / KC) - 1]; + } + else if ((KC > 6) && ((i % KC) == 4)) { + temp = subWord(temp); + } + + W[i >> 2][i & 3] = W[(i - KC) >> 2][(i - KC) & 3] ^ temp; + } - /** - * initialise an AES cipher. - * - * @param forEncryption - * whether or not we are for encryption. - * @param key - * the key required to set up the cipher. - * @exception IllegalArgumentException - * if the params argument is inappropriate. - */ + if (!forEncryption) { + for (int j = 1; j < ROUNDS; j++) { + for (int i = 0; i < 4; i++) { + W[j][i] = inv_mcol(W[j][i]); + } + } + } - public final void init(boolean forEncryption, byte[] key) - { - WorkingKey = generateWorkingKey(key, forEncryption); - this.doEncrypt = forEncryption; - } + return W; + } - public final String getAlgorithmName() - { - return "AES"; - } + private int ROUNDS; + private int[][] WorkingKey = null; + private int C0, C1, C2, C3; + private boolean doEncrypt; - public final int getBlockSize() - { - return BLOCK_SIZE; - } + private static final int BLOCK_SIZE = 16; + + /** + * default constructor - 128 bit block size. + */ + public AES() { + } - public final int processBlock(byte[] in, int inOff, byte[] out, int outOff) - { - if (WorkingKey == null) - { - throw new IllegalStateException("AES engine not initialised"); - } + /** + * initialise an AES cipher. + * + * @param forEncryption + * whether or not we are for encryption. + * @param key + * the key required to set up the cipher. + * @exception IllegalArgumentException + * if the params argument is inappropriate. + */ - if ((inOff + (32 / 2)) > in.length) - { - throw new IllegalArgumentException("input buffer too short"); - } - - if ((outOff + (32 / 2)) > out.length) - { - throw new IllegalArgumentException("output buffer too short"); - } + public final void init(boolean forEncryption, byte[] key) { + WorkingKey = generateWorkingKey(key, forEncryption); + this.doEncrypt = forEncryption; + } - if (doEncrypt) - { - unpackBlock(in, inOff); - encryptBlock(WorkingKey); - packBlock(out, outOff); - } - else - { - unpackBlock(in, inOff); - decryptBlock(WorkingKey); - packBlock(out, outOff); - } + public final String getAlgorithmName() { + return "AES"; + } + + public final int getBlockSize() { + return BLOCK_SIZE; + } - return BLOCK_SIZE; - } + public final int processBlock(byte[] in, int inOff, byte[] out, int outOff) { + if (WorkingKey == null) { + throw new IllegalStateException("AES engine not initialised"); + } + + if ((inOff + (32 / 2)) > in.length) { + throw new IllegalArgumentException("input buffer too short"); + } - public final void reset() - { - } - - private void unpackBlock(byte[] bytes, int off) - { - int index = off; + if ((outOff + (32 / 2)) > out.length) { + throw new IllegalArgumentException("output buffer too short"); + } - C0 = (bytes[index++] & 0xff); - C0 |= (bytes[index++] & 0xff) << 8; - C0 |= (bytes[index++] & 0xff) << 16; - C0 |= bytes[index++] << 24; + if (doEncrypt) { + unpackBlock(in, inOff); + encryptBlock(WorkingKey); + packBlock(out, outOff); + } + else { + unpackBlock(in, inOff); + decryptBlock(WorkingKey); + packBlock(out, outOff); + } - C1 = (bytes[index++] & 0xff); - C1 |= (bytes[index++] & 0xff) << 8; - C1 |= (bytes[index++] & 0xff) << 16; - C1 |= bytes[index++] << 24; + return BLOCK_SIZE; + } - C2 = (bytes[index++] & 0xff); - C2 |= (bytes[index++] & 0xff) << 8; - C2 |= (bytes[index++] & 0xff) << 16; - C2 |= bytes[index++] << 24; + public final void reset() { + } - C3 = (bytes[index++] & 0xff); - C3 |= (bytes[index++] & 0xff) << 8; - C3 |= (bytes[index++] & 0xff) << 16; - C3 |= bytes[index++] << 24; - } - - private void packBlock(byte[] bytes, int off) - { - int index = off; - - bytes[index++] = (byte) C0; - bytes[index++] = (byte) (C0 >> 8); - bytes[index++] = (byte) (C0 >> 16); - bytes[index++] = (byte) (C0 >> 24); - - bytes[index++] = (byte) C1; - bytes[index++] = (byte) (C1 >> 8); - bytes[index++] = (byte) (C1 >> 16); - bytes[index++] = (byte) (C1 >> 24); + private void unpackBlock(byte[] bytes, int off) { + int index = off; + C0 = (bytes[index++] & 0xff); + C0 |= (bytes[index++] & 0xff) << 8; + C0 |= (bytes[index++] & 0xff) << 16; + C0 |= bytes[index++] << 24; + C1 = (bytes[index++] & 0xff); + C1 |= (bytes[index++] & 0xff) << 8; + C1 |= (bytes[index++] & 0xff) << 16; + C1 |= bytes[index++] << 24; + C2 = (bytes[index++] & 0xff); + C2 |= (bytes[index++] & 0xff) << 8; + C2 |= (bytes[index++] & 0xff) << 16; + C2 |= bytes[index++] << 24; + C3 = (bytes[index++] & 0xff); + C3 |= (bytes[index++] & 0xff) << 8; + C3 |= (bytes[index++] & 0xff) << 16; + C3 |= bytes[index++] << 24; + } - bytes[index++] = (byte) C2; - bytes[index++] = (byte) (C2 >> 8); - bytes[index++] = (byte) (C2 >> 16); - bytes[index++] = (byte) (C2 >> 24); - - bytes[index++] = (byte) C3; - bytes[index++] = (byte) (C3 >> 8); - bytes[index++] = (byte) (C3 >> 16); - bytes[index++] = (byte) (C3 >> 24); - } - - private void encryptBlock(int[][] KW) - { - int r, r0, r1, r2, r3; - - C0 ^= KW[0][0]; - C1 ^= KW[0][1]; - C2 ^= KW[0][2]; - C3 ^= KW[0][3]; + private void packBlock(byte[] bytes, int off) { + int index = off; + bytes[index++] = (byte) C0; + bytes[index++] = (byte)(C0 >> 8); + bytes[index++] = (byte)(C0 >> 16); + bytes[index++] = (byte)(C0 >> 24); + bytes[index++] = (byte) C1; + bytes[index++] = (byte)(C1 >> 8); + bytes[index++] = (byte)(C1 >> 16); + bytes[index++] = (byte)(C1 >> 24); + bytes[index++] = (byte) C2; + bytes[index++] = (byte)(C2 >> 8); + bytes[index++] = (byte)(C2 >> 16); + bytes[index++] = (byte)(C2 >> 24); + bytes[index++] = (byte) C3; + bytes[index++] = (byte)(C3 >> 8); + bytes[index++] = (byte)(C3 >> 16); + bytes[index++] = (byte)(C3 >> 24); + } - for (r = 1; r < ROUNDS - 1;) - { - r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[(C3 >> 24) & 255] ^ KW[r][0]; - r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[(C0 >> 24) & 255] ^ KW[r][1]; - r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[(C1 >> 24) & 255] ^ KW[r][2]; - r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[(C2 >> 24) & 255] ^ KW[r++][3]; - C0 = T0[r0 & 255] ^ T1[(r1 >> 8) & 255] ^ T2[(r2 >> 16) & 255] ^ T3[(r3 >> 24) & 255] ^ KW[r][0]; - C1 = T0[r1 & 255] ^ T1[(r2 >> 8) & 255] ^ T2[(r3 >> 16) & 255] ^ T3[(r0 >> 24) & 255] ^ KW[r][1]; - C2 = T0[r2 & 255] ^ T1[(r3 >> 8) & 255] ^ T2[(r0 >> 16) & 255] ^ T3[(r1 >> 24) & 255] ^ KW[r][2]; - C3 = T0[r3 & 255] ^ T1[(r0 >> 8) & 255] ^ T2[(r1 >> 16) & 255] ^ T3[(r2 >> 24) & 255] ^ KW[r++][3]; - } - - r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[(C3 >> 24) & 255] ^ KW[r][0]; - r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[(C0 >> 24) & 255] ^ KW[r][1]; - r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[(C1 >> 24) & 255] ^ KW[r][2]; - r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[(C2 >> 24) & 255] ^ KW[r++][3]; - - // the final round's table is a simple function of S so we don't use a - // whole other four tables for it + private void encryptBlock(int[][] KW) { + int r, r0, r1, r2, r3; + C0 ^= KW[0][0]; + C1 ^= KW[0][1]; + C2 ^= KW[0][2]; + C3 ^= KW[0][3]; - C0 = (S[r0 & 255] & 255) ^ ((S[(r1 >> 8) & 255] & 255) << 8) ^ ((S[(r2 >> 16) & 255] & 255) << 16) - ^ (S[(r3 >> 24) & 255] << 24) ^ KW[r][0]; - C1 = (S[r1 & 255] & 255) ^ ((S[(r2 >> 8) & 255] & 255) << 8) ^ ((S[(r3 >> 16) & 255] & 255) << 16) - ^ (S[(r0 >> 24) & 255] << 24) ^ KW[r][1]; - C2 = (S[r2 & 255] & 255) ^ ((S[(r3 >> 8) & 255] & 255) << 8) ^ ((S[(r0 >> 16) & 255] & 255) << 16) - ^ (S[(r1 >> 24) & 255] << 24) ^ KW[r][2]; - C3 = (S[r3 & 255] & 255) ^ ((S[(r0 >> 8) & 255] & 255) << 8) ^ ((S[(r1 >> 16) & 255] & 255) << 16) - ^ (S[(r2 >> 24) & 255] << 24) ^ KW[r][3]; + for (r = 1; r < ROUNDS - 1;) { + r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[(C3 >> 24) & 255] ^ KW[r][0]; + r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[(C0 >> 24) & 255] ^ KW[r][1]; + r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[(C1 >> 24) & 255] ^ KW[r][2]; + r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[(C2 >> 24) & 255] ^ KW[r++][3]; + C0 = T0[r0 & 255] ^ T1[(r1 >> 8) & 255] ^ T2[(r2 >> 16) & 255] ^ T3[(r3 >> 24) & 255] ^ KW[r][0]; + C1 = T0[r1 & 255] ^ T1[(r2 >> 8) & 255] ^ T2[(r3 >> 16) & 255] ^ T3[(r0 >> 24) & 255] ^ KW[r][1]; + C2 = T0[r2 & 255] ^ T1[(r3 >> 8) & 255] ^ T2[(r0 >> 16) & 255] ^ T3[(r1 >> 24) & 255] ^ KW[r][2]; + C3 = T0[r3 & 255] ^ T1[(r0 >> 8) & 255] ^ T2[(r1 >> 16) & 255] ^ T3[(r2 >> 24) & 255] ^ KW[r++][3]; + } - } - - private void decryptBlock(int[][] KW) - { - int r, r0, r1, r2, r3; - - C0 ^= KW[ROUNDS][0]; - C1 ^= KW[ROUNDS][1]; - C2 ^= KW[ROUNDS][2]; - C3 ^= KW[ROUNDS][3]; + r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[(C3 >> 24) & 255] ^ KW[r][0]; + r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[(C0 >> 24) & 255] ^ KW[r][1]; + r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[(C1 >> 24) & 255] ^ KW[r][2]; + r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[(C2 >> 24) & 255] ^ KW[r++][3]; + // the final round's table is a simple function of S so we don't use a + // whole other four tables for it + C0 = (S[r0 & 255] & 255) ^ ((S[(r1 >> 8) & 255] & 255) << 8) ^ ((S[(r2 >> 16) & 255] & 255) << 16) + ^ (S[(r3 >> 24) & 255] << 24) ^ KW[r][0]; + C1 = (S[r1 & 255] & 255) ^ ((S[(r2 >> 8) & 255] & 255) << 8) ^ ((S[(r3 >> 16) & 255] & 255) << 16) + ^ (S[(r0 >> 24) & 255] << 24) ^ KW[r][1]; + C2 = (S[r2 & 255] & 255) ^ ((S[(r3 >> 8) & 255] & 255) << 8) ^ ((S[(r0 >> 16) & 255] & 255) << 16) + ^ (S[(r1 >> 24) & 255] << 24) ^ KW[r][2]; + C3 = (S[r3 & 255] & 255) ^ ((S[(r0 >> 8) & 255] & 255) << 8) ^ ((S[(r1 >> 16) & 255] & 255) << 16) + ^ (S[(r2 >> 24) & 255] << 24) ^ KW[r][3]; + } - for (r = ROUNDS - 1; r > 1;) - { - r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[(C1 >> 24) & 255] - ^ KW[r][0]; - r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[(C2 >> 24) & 255] - ^ KW[r][1]; - r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[(C3 >> 24) & 255] - ^ KW[r][2]; - r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[(C0 >> 24) & 255] - ^ KW[r--][3]; - C0 = Tinv0[r0 & 255] ^ Tinv1[(r3 >> 8) & 255] ^ Tinv2[(r2 >> 16) & 255] ^ Tinv3[(r1 >> 24) & 255] - ^ KW[r][0]; - C1 = Tinv0[r1 & 255] ^ Tinv1[(r0 >> 8) & 255] ^ Tinv2[(r3 >> 16) & 255] ^ Tinv3[(r2 >> 24) & 255] - ^ KW[r][1]; - C2 = Tinv0[r2 & 255] ^ Tinv1[(r1 >> 8) & 255] ^ Tinv2[(r0 >> 16) & 255] ^ Tinv3[(r3 >> 24) & 255] - ^ KW[r][2]; - C3 = Tinv0[r3 & 255] ^ Tinv1[(r2 >> 8) & 255] ^ Tinv2[(r1 >> 16) & 255] ^ Tinv3[(r0 >> 24) & 255] - ^ KW[r--][3]; - } + private void decryptBlock(int[][] KW) { + int r, r0, r1, r2, r3; + C0 ^= KW[ROUNDS][0]; + C1 ^= KW[ROUNDS][1]; + C2 ^= KW[ROUNDS][2]; + C3 ^= KW[ROUNDS][3]; - r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[(C1 >> 24) & 255] ^ KW[r][0]; - r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[(C2 >> 24) & 255] ^ KW[r][1]; - r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[(C3 >> 24) & 255] ^ KW[r][2]; - r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[(C0 >> 24) & 255] ^ KW[r--][3]; - - // the final round's table is a simple function of Si so we don't use a - // whole other four tables for it + for (r = ROUNDS - 1; r > 1;) { + r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[(C1 >> 24) & 255] + ^ KW[r][0]; + r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[(C2 >> 24) & 255] + ^ KW[r][1]; + r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[(C3 >> 24) & 255] + ^ KW[r][2]; + r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[(C0 >> 24) & 255] + ^ KW[r--][3]; + C0 = Tinv0[r0 & 255] ^ Tinv1[(r3 >> 8) & 255] ^ Tinv2[(r2 >> 16) & 255] ^ Tinv3[(r1 >> 24) & 255] + ^ KW[r][0]; + C1 = Tinv0[r1 & 255] ^ Tinv1[(r0 >> 8) & 255] ^ Tinv2[(r3 >> 16) & 255] ^ Tinv3[(r2 >> 24) & 255] + ^ KW[r][1]; + C2 = Tinv0[r2 & 255] ^ Tinv1[(r1 >> 8) & 255] ^ Tinv2[(r0 >> 16) & 255] ^ Tinv3[(r3 >> 24) & 255] + ^ KW[r][2]; + C3 = Tinv0[r3 & 255] ^ Tinv1[(r2 >> 8) & 255] ^ Tinv2[(r1 >> 16) & 255] ^ Tinv3[(r0 >> 24) & 255] + ^ KW[r--][3]; + } - C0 = (Si[r0 & 255] & 255) ^ ((Si[(r3 >> 8) & 255] & 255) << 8) ^ ((Si[(r2 >> 16) & 255] & 255) << 16) - ^ (Si[(r1 >> 24) & 255] << 24) ^ KW[0][0]; - C1 = (Si[r1 & 255] & 255) ^ ((Si[(r0 >> 8) & 255] & 255) << 8) ^ ((Si[(r3 >> 16) & 255] & 255) << 16) - ^ (Si[(r2 >> 24) & 255] << 24) ^ KW[0][1]; - C2 = (Si[r2 & 255] & 255) ^ ((Si[(r1 >> 8) & 255] & 255) << 8) ^ ((Si[(r0 >> 16) & 255] & 255) << 16) - ^ (Si[(r3 >> 24) & 255] << 24) ^ KW[0][2]; - C3 = (Si[r3 & 255] & 255) ^ ((Si[(r2 >> 8) & 255] & 255) << 8) ^ ((Si[(r1 >> 16) & 255] & 255) << 16) - ^ (Si[(r0 >> 24) & 255] << 24) ^ KW[0][3]; - } + r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[(C1 >> 24) & 255] ^ KW[r][0]; + r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[(C2 >> 24) & 255] ^ KW[r][1]; + r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[(C3 >> 24) & 255] ^ KW[r][2]; + r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[(C0 >> 24) & 255] ^ KW[r--][3]; + // the final round's table is a simple function of Si so we don't use a + // whole other four tables for it + C0 = (Si[r0 & 255] & 255) ^ ((Si[(r3 >> 8) & 255] & 255) << 8) ^ ((Si[(r2 >> 16) & 255] & 255) << 16) + ^ (Si[(r1 >> 24) & 255] << 24) ^ KW[0][0]; + C1 = (Si[r1 & 255] & 255) ^ ((Si[(r0 >> 8) & 255] & 255) << 8) ^ ((Si[(r3 >> 16) & 255] & 255) << 16) + ^ (Si[(r2 >> 24) & 255] << 24) ^ KW[0][1]; + C2 = (Si[r2 & 255] & 255) ^ ((Si[(r1 >> 8) & 255] & 255) << 8) ^ ((Si[(r0 >> 16) & 255] & 255) << 16) + ^ (Si[(r3 >> 24) & 255] << 24) ^ KW[0][2]; + C3 = (Si[r3 & 255] & 255) ^ ((Si[(r2 >> 8) & 255] & 255) << 8) ^ ((Si[(r1 >> 16) & 255] & 255) << 16) + ^ (Si[(r0 >> 24) & 255] << 24) ^ KW[0][3]; + } - public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) - { - processBlock(src, srcoff, dst, dstoff); - } + public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { + processBlock(src, srcoff, dst, dstoff); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/cipher/BlockCipher.java --- a/src/ch/ethz/ssh2/crypto/cipher/BlockCipher.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/cipher/BlockCipher.java Wed Jul 30 14:16:58 2014 -0700 @@ -6,15 +6,14 @@ /** * BlockCipher. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public interface BlockCipher -{ - public void init(boolean forEncryption, byte[] key); +public interface BlockCipher { + public void init(boolean forEncryption, byte[] key); - public int getBlockSize(); + public int getBlockSize(); - public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff); + public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/cipher/BlockCipherFactory.java --- a/src/ch/ethz/ssh2/crypto/cipher/BlockCipherFactory.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/cipher/BlockCipherFactory.java Wed Jul 30 14:16:58 2014 -0700 @@ -14,117 +14,99 @@ * @author Christian Plattner * @version $Id: BlockCipherFactory.java 86 2014-04-07 14:15:18Z dkocher@sudo.ch $ */ -public class BlockCipherFactory -{ - private static final class CipherEntry - { - String type; - int blocksize; - int keysize; - String cipherClass; +public class BlockCipherFactory { + private static final class CipherEntry { + String type; + int blocksize; + int keysize; + String cipherClass; - public CipherEntry(String type, int blockSize, int keySize, String cipherClass) - { - this.type = type; - this.blocksize = blockSize; - this.keysize = keySize; - this.cipherClass = cipherClass; - } - } + public CipherEntry(String type, int blockSize, int keySize, String cipherClass) { + this.type = type; + this.blocksize = blockSize; + this.keysize = keySize; + this.cipherClass = cipherClass; + } + } - private static final List ciphers = new ArrayList(); + private static final List ciphers = new ArrayList(); - static - { - /* Higher Priority First */ - ciphers.add(new CipherEntry("aes128-ctr", 16, 16, "ch.ethz.ssh2.crypto.cipher.AES")); - ciphers.add(new CipherEntry("aes192-ctr", 16, 24, "ch.ethz.ssh2.crypto.cipher.AES")); - ciphers.add(new CipherEntry("aes256-ctr", 16, 32, "ch.ethz.ssh2.crypto.cipher.AES")); - ciphers.add(new CipherEntry("blowfish-ctr", 8, 16, "ch.ethz.ssh2.crypto.cipher.BlowFish")); - - ciphers.add(new CipherEntry("aes128-cbc", 16, 16, "ch.ethz.ssh2.crypto.cipher.AES")); - ciphers.add(new CipherEntry("aes192-cbc", 16, 24, "ch.ethz.ssh2.crypto.cipher.AES")); - ciphers.add(new CipherEntry("aes256-cbc", 16, 32, "ch.ethz.ssh2.crypto.cipher.AES")); - ciphers.add(new CipherEntry("blowfish-cbc", 8, 16, "ch.ethz.ssh2.crypto.cipher.BlowFish")); - - ciphers.add(new CipherEntry("3des-ctr", 8, 24, "ch.ethz.ssh2.crypto.cipher.DESede")); - ciphers.add(new CipherEntry("3des-cbc", 8, 24, "ch.ethz.ssh2.crypto.cipher.DESede")); - } + static { + /* Higher Priority First */ + ciphers.add(new CipherEntry("aes128-ctr", 16, 16, "ch.ethz.ssh2.crypto.cipher.AES")); + ciphers.add(new CipherEntry("aes192-ctr", 16, 24, "ch.ethz.ssh2.crypto.cipher.AES")); + ciphers.add(new CipherEntry("aes256-ctr", 16, 32, "ch.ethz.ssh2.crypto.cipher.AES")); + ciphers.add(new CipherEntry("blowfish-ctr", 8, 16, "ch.ethz.ssh2.crypto.cipher.BlowFish")); + ciphers.add(new CipherEntry("aes128-cbc", 16, 16, "ch.ethz.ssh2.crypto.cipher.AES")); + ciphers.add(new CipherEntry("aes192-cbc", 16, 24, "ch.ethz.ssh2.crypto.cipher.AES")); + ciphers.add(new CipherEntry("aes256-cbc", 16, 32, "ch.ethz.ssh2.crypto.cipher.AES")); + ciphers.add(new CipherEntry("blowfish-cbc", 8, 16, "ch.ethz.ssh2.crypto.cipher.BlowFish")); + ciphers.add(new CipherEntry("3des-ctr", 8, 24, "ch.ethz.ssh2.crypto.cipher.DESede")); + ciphers.add(new CipherEntry("3des-cbc", 8, 24, "ch.ethz.ssh2.crypto.cipher.DESede")); + } - public static String[] getDefaultCipherList() - { - List list = new ArrayList(ciphers.size()); - for (CipherEntry ce : ciphers) - { - list.add(ce.type); - } - return list.toArray(new String[ciphers.size()]); - } + public static String[] getDefaultCipherList() { + List list = new ArrayList(ciphers.size()); + + for (CipherEntry ce : ciphers) { + list.add(ce.type); + } - public static void checkCipherList(String[] cipherCandidates) - { - for (String cipherCandidate : cipherCandidates) - { - getEntry(cipherCandidate); - } - } + return list.toArray(new String[ciphers.size()]); + } + + public static void checkCipherList(String[] cipherCandidates) { + for (String cipherCandidate : cipherCandidates) { + getEntry(cipherCandidate); + } + } - // @SuppressWarnings("rawtypes") - public static BlockCipher createCipher(String type, boolean encrypt, byte[] key, byte[] iv) - { - try - { - CipherEntry ce = getEntry(type); - Class cc = Class.forName(ce.cipherClass); - BlockCipher bc = (BlockCipher) cc.newInstance(); + // @SuppressWarnings("rawtypes") + public static BlockCipher createCipher(String type, boolean encrypt, byte[] key, byte[] iv) { + try { + CipherEntry ce = getEntry(type); + Class cc = Class.forName(ce.cipherClass); + BlockCipher bc = (BlockCipher) cc.newInstance(); + + if (type.endsWith("-cbc")) { + bc.init(encrypt, key); + return new CBCMode(bc, iv, encrypt); + } + else if (type.endsWith("-ctr")) { + bc.init(true, key); + return new CTRMode(bc, iv, encrypt); + } - if (type.endsWith("-cbc")) - { - bc.init(encrypt, key); - return new CBCMode(bc, iv, encrypt); - } - else if (type.endsWith("-ctr")) - { - bc.init(true, key); - return new CTRMode(bc, iv, encrypt); - } - throw new IllegalArgumentException("Cannot instantiate " + type); - } - catch (ClassNotFoundException e) - { - throw new IllegalArgumentException("Cannot instantiate " + type, e); - } - catch (InstantiationException e) - { - throw new IllegalArgumentException("Cannot instantiate " + type, e); - } - catch (IllegalAccessException e) - { - throw new IllegalArgumentException("Cannot instantiate " + type, e); - } - } + throw new IllegalArgumentException("Cannot instantiate " + type); + } + catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Cannot instantiate " + type, e); + } + catch (InstantiationException e) { + throw new IllegalArgumentException("Cannot instantiate " + type, e); + } + catch (IllegalAccessException e) { + throw new IllegalArgumentException("Cannot instantiate " + type, e); + } + } - private static CipherEntry getEntry(String type) - { - for (CipherEntry ce : ciphers) - { - if (ce.type.equals(type)) - { - return ce; - } - } - throw new IllegalArgumentException("Unkown algorithm " + type); - } + private static CipherEntry getEntry(String type) { + for (CipherEntry ce : ciphers) { + if (ce.type.equals(type)) { + return ce; + } + } + + throw new IllegalArgumentException("Unkown algorithm " + type); + } - public static int getBlockSize(String type) - { - CipherEntry ce = getEntry(type); - return ce.blocksize; - } + public static int getBlockSize(String type) { + CipherEntry ce = getEntry(type); + return ce.blocksize; + } - public static int getKeySize(String type) - { - CipherEntry ce = getEntry(type); - return ce.keysize; - } + public static int getKeySize(String type) { + CipherEntry ce = getEntry(type); + return ce.keysize; + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/cipher/BlowFish.java --- a/src/ch/ethz/ssh2/crypto/cipher/BlowFish.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/cipher/BlowFish.java Wed Jul 30 14:16:58 2014 -0700 @@ -23,380 +23,354 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + THE SOFTWARE. */ /** * A class that provides Blowfish key encryption operations, such as encoding * data and generating keys. All the algorithms herein are from Applied * Cryptography and implement a simplified cryptography interface. - * + * * @author See comments in the source file * @version 2.50, 03/15/10 */ -public class BlowFish implements BlockCipher -{ +public class BlowFish implements BlockCipher { - private final static int[] KP = { 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0, - 0x082EFA98, 0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, - 0xB5470917, 0x9216D5D9, 0x8979FB1B }, + private final static int[] KP = { 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0, + 0x082EFA98, 0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, + 0xB5470917, 0x9216D5D9, 0x8979FB1B + }, - KS0 = { 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, 0x24A19947, - 0xB3916CF7, 0x0801F2E2, 0x858EFC16, 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658, - 0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, 0xC5D1B023, 0x286085F0, 0xCA417918, - 0xB8DB38EF, 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, - 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, 0xA15486AF, - 0x7C72E993, 0xB3EE1411, 0x636FBC2A, 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C, - 0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, 0x61D809CC, 0xFB21A991, 0x487CAC60, - 0x5DEC8032, 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, - 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, 0x6A51A0D2, - 0xD8542F68, 0x960FA728, 0xAB5133A3, 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176, - 0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, 0xE06F75D8, 0x85C12073, 0x401A449F, - 0x56C16AA6, 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, - 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, 0xC1A94FB6, - 0x409F60C4, 0x5E5C9EC2, 0x196A2463, 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, 0x6DFC511F, 0x9B30952C, - 0xCC814544, 0xAF5EBD09, 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, 0xC0CBA857, 0x45C8740F, 0xD20B5F39, - 0xB9D3FBDB, 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, - 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, 0x9E5C57BB, - 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, 0x695B27B0, 0xBBCA58C8, - 0xE1FFA35D, 0xB8F011A0, 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, 0x9A53E479, 0xB6F84565, 0xD28E49BC, - 0x4BFB9790, 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, - 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, 0x8FF6E2FB, - 0xF2122B64, 0x8888B812, 0x900DF01C, 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, 0x2F2F2218, 0xBE0E1777, - 0xEA752DFE, 0x8B021FA1, 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, - 0xD2ADA8D9, 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, - 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, 0x2464369B, - 0xF009B91E, 0x5563911D, 0x59DFA6AA, 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, 0x83260376, 0x6295CFA9, - 0x11C81968, 0x4E734A41, 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, - 0x81E67400, 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, - 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A }, + KS0 = { 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, 0x24A19947, + 0xB3916CF7, 0x0801F2E2, 0x858EFC16, 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658, + 0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013, 0xC5D1B023, 0x286085F0, 0xCA417918, + 0xB8DB38EF, 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, + 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, 0xA15486AF, + 0x7C72E993, 0xB3EE1411, 0x636FBC2A, 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C, + 0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, 0x61D809CC, 0xFB21A991, 0x487CAC60, + 0x5DEC8032, 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, + 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, 0x6A51A0D2, + 0xD8542F68, 0x960FA728, 0xAB5133A3, 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176, + 0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, 0xE06F75D8, 0x85C12073, 0x401A449F, + 0x56C16AA6, 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, + 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, 0xC1A94FB6, + 0x409F60C4, 0x5E5C9EC2, 0x196A2463, 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, 0x6DFC511F, 0x9B30952C, + 0xCC814544, 0xAF5EBD09, 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, 0xC0CBA857, 0x45C8740F, 0xD20B5F39, + 0xB9D3FBDB, 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, + 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, 0x9E5C57BB, + 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB, 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, 0x695B27B0, 0xBBCA58C8, + 0xE1FFA35D, 0xB8F011A0, 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, 0x9A53E479, 0xB6F84565, 0xD28E49BC, + 0x4BFB9790, 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8, 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, + 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, 0x8FF6E2FB, + 0xF2122B64, 0x8888B812, 0x900DF01C, 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, 0x2F2F2218, 0xBE0E1777, + 0xEA752DFE, 0x8B021FA1, 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299, 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, + 0xD2ADA8D9, 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477, 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, + 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, 0x2464369B, + 0xF009B91E, 0x5563911D, 0x59DFA6AA, 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, 0x83260376, 0x6295CFA9, + 0x11C81968, 0x4E734A41, 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915, 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, + 0x81E67400, 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A + }, - KS1 = { 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, 0xECAA8C71, - 0x699A17FF, 0x5664526C, 0xC2B19EE1, 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65, - 0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, 0x4CDD2086, 0x8470EB26, 0x6382E9C6, - 0x021ECC5E, 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, - 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, 0xAE0CF51A, - 0x3CB574B2, 0x25837A58, 0xDC0921BD, 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, 0x3AE5E581, 0x37C2DADC, - 0xC8B57634, 0x9AF3DDA7, 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, - 0x183EB331, 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, - 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, 0x7A584718, - 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, 0xEF1C1847, 0x3215D908, - 0xDD433B37, 0x24C2BA16, 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, 0x71DFF89E, 0x10314E55, 0x81AC77D6, - 0x5F11199B, 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, - 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, 0x803E89D6, - 0x5266C825, 0x2E4CC978, 0x9C10B36A, 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, 0xF2F74EA7, 0x361D2B3D, - 0x1939260F, 0x19C27960, 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, 0xE3BC4595, 0xA67BC883, 0xB17F37D1, - 0x018CFF28, 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, - 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, 0xB5735C90, - 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, 0x648B1EAF, 0x19BDF0CA, - 0xA02369B9, 0x655ABB50, 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, 0x9B540B19, 0x875FA099, 0x95F7997E, - 0x623D7DA8, 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, - 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, 0x58EBF2EF, - 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, 0x45EEE2B6, 0xA3AAABEA, - 0xDB6C4F15, 0xFACB4FD0, 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, 0xD81E799E, 0x86854DC7, 0xE44B476A, - 0x3D816250, 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, - 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, 0x3372F092, - 0x8D937E41, 0xD65FECF1, 0x6C223BDB, 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, 0xA6078084, 0x19F8509E, - 0xE8EFD855, 0x61D99735, 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, 0x9E447A2E, 0xC3453484, 0xFDD56705, - 0x0E1E9EC9, 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, - 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 }, + KS1 = { 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266, 0xECAA8C71, + 0x699A17FF, 0x5664526C, 0xC2B19EE1, 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65, + 0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, 0x4CDD2086, 0x8470EB26, 0x6382E9C6, + 0x021ECC5E, 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737, + 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF, 0xAE0CF51A, + 0x3CB574B2, 0x25837A58, 0xDC0921BD, 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, 0x3AE5E581, 0x37C2DADC, + 0xC8B57634, 0x9AF3DDA7, 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, + 0x183EB331, 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF, + 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, 0x7A584718, + 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, 0xEF1C1847, 0x3215D908, + 0xDD433B37, 0x24C2BA16, 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, 0x71DFF89E, 0x10314E55, 0x81AC77D6, + 0x5F11199B, 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, + 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, 0x803E89D6, + 0x5266C825, 0x2E4CC978, 0x9C10B36A, 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, 0xF2F74EA7, 0x361D2B3D, + 0x1939260F, 0x19C27960, 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, 0xE3BC4595, 0xA67BC883, 0xB17F37D1, + 0x018CFF28, 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, + 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, 0xB5735C90, + 0x4C70A239, 0xD59E9E0B, 0xCBAADE14, 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, 0x648B1EAF, 0x19BDF0CA, + 0xA02369B9, 0x655ABB50, 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, 0x9B540B19, 0x875FA099, 0x95F7997E, + 0x623D7DA8, 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281, 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, + 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, 0x58EBF2EF, + 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, 0x45EEE2B6, 0xA3AAABEA, + 0xDB6C4F15, 0xFACB4FD0, 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105, 0xD81E799E, 0x86854DC7, 0xE44B476A, + 0x3D816250, 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3, 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, + 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, 0x3372F092, + 0x8D937E41, 0xD65FECF1, 0x6C223BDB, 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, 0xA6078084, 0x19F8509E, + 0xE8EFD855, 0x61D99735, 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC, 0x9E447A2E, 0xC3453484, 0xFDD56705, + 0x0E1E9EC9, 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340, 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7 + }, - KS2 = { 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, 0xD4082471, - 0x3320F46A, 0x43B7D4B7, 0x500061AF, 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, 0x4D95FC1D, 0x96B591AF, - 0x70F4DDD3, 0x66A02F45, 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, 0x96EB27B3, 0x55FD3941, 0xDA2547E6, - 0xABCA0A9A, 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, - 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, 0x20FE9E35, - 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, 0x3A6EFA74, 0xDD5B4332, - 0x6841E7F7, 0xCA7820FB, 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, 0x55533A3A, 0x20838D87, 0xFE6BA9B7, - 0xD096954B, 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, - 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, 0x07F9C9EE, - 0x41041F0F, 0x404779A4, 0x5D886E17, 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, 0x257B7834, 0x602A9C60, - 0xDFF8E8A3, 0x1F636C1B, 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, 0x6B2395E0, 0x333E92E1, 0x3B240B62, - 0xEEBEB922, 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, - 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, 0xA812DC60, - 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, 0xF1290DC7, 0xCC00FFA3, - 0xB5390F92, 0x690FED0B, 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, 0xBB132F88, 0x515BAD24, 0x7B9479BF, - 0x763BD6EB, 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, - 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, 0x44421659, - 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, 0x9DBC8057, 0xF0F7C086, - 0x60787BF8, 0x6003604D, 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, 0x83426B33, 0xF01EAB71, 0xB0804187, - 0x3C005E5F, 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, - 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, 0x466E598E, - 0x20B45770, 0x8CD55591, 0xC902DE4C, 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, 0xB77F19B6, 0xE0A9DC09, - 0x662D09A1, 0xC4324633, 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, - 0x2868F169, 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, - 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, 0x11E69ED7, - 0x2338EA63, 0x53C2DD94, 0xC2C21634, 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, 0x6F05E409, 0x4B7C0188, - 0x39720A3D, 0x7C927C24, 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, 0xED545578, 0x08FCA5B5, 0xD83D7CD3, - 0x4DAD0FC4, 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, - 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 }, + KS2 = { 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068, 0xD4082471, + 0x3320F46A, 0x43B7D4B7, 0x500061AF, 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, 0x4D95FC1D, 0x96B591AF, + 0x70F4DDD3, 0x66A02F45, 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, 0x96EB27B3, 0x55FD3941, 0xDA2547E6, + 0xABCA0A9A, 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE, + 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42, 0x20FE9E35, + 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, 0x3A6EFA74, 0xDD5B4332, + 0x6841E7F7, 0xCA7820FB, 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, 0x55533A3A, 0x20838D87, 0xFE6BA9B7, + 0xD096954B, 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C, + 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC, 0x07F9C9EE, + 0x41041F0F, 0x404779A4, 0x5D886E17, 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, 0x257B7834, 0x602A9C60, + 0xDFF8E8A3, 0x1F636C1B, 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, 0x6B2395E0, 0x333E92E1, 0x3B240B62, + 0xEEBEB922, 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0, + 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, 0xA812DC60, + 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D, 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, 0xF1290DC7, 0xCC00FFA3, + 0xB5390F92, 0x690FED0B, 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, 0xBB132F88, 0x515BAD24, 0x7B9479BF, + 0x763BD6EB, 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, + 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, 0x44421659, + 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A, 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, 0x9DBC8057, 0xF0F7C086, + 0x60787BF8, 0x6003604D, 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, 0x83426B33, 0xF01EAB71, 0xB0804187, + 0x3C005E5F, 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61, 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, + 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, 0x466E598E, + 0x20B45770, 0x8CD55591, 0xC902DE4C, 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, 0xB77F19B6, 0xE0A9DC09, + 0x662D09A1, 0xC4324633, 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10, 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, + 0x2868F169, 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52, 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, + 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, 0x11E69ED7, + 0x2338EA63, 0x53C2DD94, 0xC2C21634, 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, 0x6F05E409, 0x4B7C0188, + 0x39720A3D, 0x7C927C24, 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC, 0xED545578, 0x08FCA5B5, 0xD83D7CD3, + 0x4DAD0FC4, 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0 + }, - KS3 = { 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, 0xD5118E9D, - 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, 0x5748AB2F, 0xBC946E79, - 0xC6A376D2, 0x6549C2C8, 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, - 0xBE5EE304, 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, - 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, 0xC72FEFD3, - 0xF752F7DA, 0x3F046F69, 0x77FA0A59, 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, 0xE990FD5A, 0x9E34D797, - 0x2CF0B7D9, 0x022B8B51, 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, - 0x5A88F54C, 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, - 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, 0xC3EB9E15, - 0x3C9057A2, 0x97271AEC, 0xA93A072A, 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, 0x7533D928, 0xB155FDF5, - 0x03563482, 0x8ABA3CBB, 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, 0x4DE81751, 0x3830DC8E, 0x379D5862, - 0x9320F991, 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, - 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, 0x5BBEF7DD, - 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, 0x72EACEA8, 0xFA6484BB, - 0x8D6612AE, 0xBF3C6F47, 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, 0x740E0D8D, 0xE75B1357, 0xF8721671, - 0xAF537D5D, 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, - 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, 0xA08839E1, - 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, 0x1A908749, 0xD44FBD9A, - 0xD0DADECB, 0xD50ADA38, 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, - 0x27D9459C, 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, - 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, 0x9F1F9532, - 0xE0D392DF, 0xD3A0342B, 0x8971F21E, 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, 0xDF359F8D, 0x9B992F2E, - 0xE60B6F47, 0x0FE3F11D, 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, 0x1618B166, 0xFD2C1D05, 0x848FD2C5, - 0xF6FB2299, 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, - 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, 0xC9AA53FD, - 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, 0x53113EC0, 0x1640E3D3, - 0x38ABBD60, 0x2547ADF0, 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, - 0x4CF9AA7E, 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, - 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 }; - - // ==================================== - // Useful constants - // ==================================== - - private static final int ROUNDS = 16; - private static final int BLOCK_SIZE = 8; // bytes = 64 bits - private static final int SBOX_SK = 256; - private static final int P_SZ = ROUNDS + 2; - - private final int[] S0, S1, S2, S3; // the s-boxes - private final int[] P; // the p-array + KS3 = { 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE, 0xD5118E9D, + 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, 0x5748AB2F, 0xBC946E79, + 0xC6A376D2, 0x6549C2C8, 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, + 0xBE5EE304, 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4, + 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9, 0xC72FEFD3, + 0xF752F7DA, 0x3F046F69, 0x77FA0A59, 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, 0xE990FD5A, 0x9E34D797, + 0x2CF0B7D9, 0x022B8B51, 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, + 0x5A88F54C, 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28, + 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD, 0xC3EB9E15, + 0x3C9057A2, 0x97271AEC, 0xA93A072A, 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, 0x7533D928, 0xB155FDF5, + 0x03563482, 0x8ABA3CBB, 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, 0x4DE81751, 0x3830DC8E, 0x379D5862, + 0x9320F991, 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680, + 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, 0x5BBEF7DD, + 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB, 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, 0x72EACEA8, 0xFA6484BB, + 0x8D6612AE, 0xBF3C6F47, 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, 0x740E0D8D, 0xE75B1357, 0xF8721671, + 0xAF537D5D, 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, + 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, 0xA08839E1, + 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9, 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, 0x1A908749, 0xD44FBD9A, + 0xD0DADECB, 0xD50ADA38, 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, + 0x27D9459C, 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525, 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, + 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, 0x9F1F9532, + 0xE0D392DF, 0xD3A0342B, 0x8971F21E, 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, 0xDF359F8D, 0x9B992F2E, + 0xE60B6F47, 0x0FE3F11D, 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F, 0x1618B166, 0xFD2C1D05, 0x848FD2C5, + 0xF6FB2299, 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02, 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, + 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, 0xC9AA53FD, + 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, 0x53113EC0, 0x1640E3D3, + 0x38ABBD60, 0x2547ADF0, 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060, 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, + 0x4CF9AA7E, 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6 + }; - private boolean doEncrypt = false; - - private byte[] workingKey = null; + // ==================================== + // Useful constants + // ==================================== - public BlowFish() - { - S0 = new int[SBOX_SK]; - S1 = new int[SBOX_SK]; - S2 = new int[SBOX_SK]; - S3 = new int[SBOX_SK]; - P = new int[P_SZ]; - } + private static final int ROUNDS = 16; + private static final int BLOCK_SIZE = 8; // bytes = 64 bits + private static final int SBOX_SK = 256; + private static final int P_SZ = ROUNDS + 2; + + private final int[] S0, S1, S2, S3; // the s-boxes + private final int[] P; // the p-array - /** - * initialise a Blowfish cipher. - * - * @param encrypting - * whether or not we are for encryption. - * @param key - * the key required to set up the cipher. - * @exception IllegalArgumentException - * if the params argument is inappropriate. - */ - public void init(boolean encrypting, byte[] key) - { - this.doEncrypt = encrypting; - this.workingKey = key; - setKey(this.workingKey); - } + private boolean doEncrypt = false; + + private byte[] workingKey = null; - public String getAlgorithmName() - { - return "Blowfish"; - } - - public final void transformBlock(byte[] in, int inOff, byte[] out, int outOff) - { - if (workingKey == null) - { - throw new IllegalStateException("Blowfish not initialised"); - } + public BlowFish() { + S0 = new int[SBOX_SK]; + S1 = new int[SBOX_SK]; + S2 = new int[SBOX_SK]; + S3 = new int[SBOX_SK]; + P = new int[P_SZ]; + } - if (doEncrypt) - { - encryptBlock(in, inOff, out, outOff); - } - else - { - decryptBlock(in, inOff, out, outOff); - } - } - - public void reset() - { - } - - public int getBlockSize() - { - return BLOCK_SIZE; - } + /** + * initialise a Blowfish cipher. + * + * @param encrypting + * whether or not we are for encryption. + * @param key + * the key required to set up the cipher. + * @exception IllegalArgumentException + * if the params argument is inappropriate. + */ + public void init(boolean encrypting, byte[] key) { + this.doEncrypt = encrypting; + this.workingKey = key; + setKey(this.workingKey); + } - // ================================== - // Private Implementation - // ================================== - - private int F(int x) - { - return (((S0[(x >>> 24)] + S1[(x >>> 16) & 0xff]) ^ S2[(x >>> 8) & 0xff]) + S3[x & 0xff]); - } + public String getAlgorithmName() { + return "Blowfish"; + } - /** - * apply the encryption cycle to each value pair in the table. - */ - private void processTable(int xl, int xr, int[] table) - { - int size = table.length; + public final void transformBlock(byte[] in, int inOff, byte[] out, int outOff) { + if (workingKey == null) { + throw new IllegalStateException("Blowfish not initialised"); + } - for (int s = 0; s < size; s += 2) - { - xl ^= P[0]; - - for (int i = 1; i < ROUNDS; i += 2) - { - xr ^= F(xl) ^ P[i]; - xl ^= F(xr) ^ P[i + 1]; - } + if (doEncrypt) { + encryptBlock(in, inOff, out, outOff); + } + else { + decryptBlock(in, inOff, out, outOff); + } + } - xr ^= P[ROUNDS + 1]; + public void reset() { + } - table[s] = xr; - table[s + 1] = xl; + public int getBlockSize() { + return BLOCK_SIZE; + } - xr = xl; // end of cycle swap - xl = table[s]; - } - } + // ================================== + // Private Implementation + // ================================== + + private int F(int x) { + return (((S0[(x >>> 24)] + S1[(x >>> 16) & 0xff]) ^ S2[(x >>> 8) & 0xff]) + S3[x & 0xff]); + } - private void setKey(byte[] key) - { - /* - * - comments are from _Applied Crypto_, Schneier, p338 please be - * careful comparing the two, AC numbers the arrays from 1, the enclosed - * code from 0. - * - * (1) Initialise the S-boxes and the P-array, with a fixed string This - * string contains the hexadecimal digits of pi (3.141...) - */ - System.arraycopy(KS0, 0, S0, 0, SBOX_SK); - System.arraycopy(KS1, 0, S1, 0, SBOX_SK); - System.arraycopy(KS2, 0, S2, 0, SBOX_SK); - System.arraycopy(KS3, 0, S3, 0, SBOX_SK); + /** + * apply the encryption cycle to each value pair in the table. + */ + private void processTable(int xl, int xr, int[] table) { + int size = table.length; - System.arraycopy(KP, 0, P, 0, P_SZ); + for (int s = 0; s < size; s += 2) { + xl ^= P[0]; - /* - * (2) Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with - * the second 32-bits of the key, and so on for all bits of the key (up - * to P[17]). Repeatedly cycle through the key bits until the entire - * P-array has been XOR-ed with the key bits - */ - int keyLength = key.length; - int keyIndex = 0; + for (int i = 1; i < ROUNDS; i += 2) { + xr ^= F(xl) ^ P[i]; + xl ^= F(xr) ^ P[i + 1]; + } - for (int i = 0; i < P_SZ; i++) - { - // get the 32 bits of the key, in 4 * 8 bit chunks - int data = 0x0000000; - for (int j = 0; j < 4; j++) - { - // create a 32 bit block - data = (data << 8) | (key[keyIndex++] & 0xff); + xr ^= P[ROUNDS + 1]; + table[s] = xr; + table[s + 1] = xl; + xr = xl; // end of cycle swap + xl = table[s]; + } + } - // wrap when we get to the end of the key - if (keyIndex >= keyLength) - { - keyIndex = 0; - } - } - // XOR the newly created 32 bit chunk onto the P-array - P[i] ^= data; - } + private void setKey(byte[] key) { + /* + * - comments are from _Applied Crypto_, Schneier, p338 please be + * careful comparing the two, AC numbers the arrays from 1, the enclosed + * code from 0. + * + * (1) Initialise the S-boxes and the P-array, with a fixed string This + * string contains the hexadecimal digits of pi (3.141...) + */ + System.arraycopy(KS0, 0, S0, 0, SBOX_SK); + System.arraycopy(KS1, 0, S1, 0, SBOX_SK); + System.arraycopy(KS2, 0, S2, 0, SBOX_SK); + System.arraycopy(KS3, 0, S3, 0, SBOX_SK); + System.arraycopy(KP, 0, P, 0, P_SZ); + /* + * (2) Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with + * the second 32-bits of the key, and so on for all bits of the key (up + * to P[17]). Repeatedly cycle through the key bits until the entire + * P-array has been XOR-ed with the key bits + */ + int keyLength = key.length; + int keyIndex = 0; - /* - * (3) Encrypt the all-zero string with the Blowfish algorithm, using - * the subkeys described in (1) and (2) - * - * (4) Replace P1 and P2 with the output of step (3) - * - * (5) Encrypt the output of step(3) using the Blowfish algorithm, with - * the modified subkeys. - * - * (6) Replace P3 and P4 with the output of step (5) - * - * (7) Continue the process, replacing all elements of the P-array and - * then all four S-boxes in order, with the output of the continuously - * changing Blowfish algorithm - */ + for (int i = 0; i < P_SZ; i++) { + // get the 32 bits of the key, in 4 * 8 bit chunks + int data = 0x0000000; + + for (int j = 0; j < 4; j++) { + // create a 32 bit block + data = (data << 8) | (key[keyIndex++] & 0xff); - processTable(0, 0, P); - processTable(P[P_SZ - 2], P[P_SZ - 1], S0); - processTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1); - processTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2); - processTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3); - } + // wrap when we get to the end of the key + if (keyIndex >= keyLength) { + keyIndex = 0; + } + } - /** - * Encrypt the given input starting at the given offset and place the result - * in the provided buffer starting at the given offset. The input will be an - * exact multiple of our blocksize. - */ - private void encryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex) - { - int xl = BytesTo32bits(src, srcIndex); - int xr = BytesTo32bits(src, srcIndex + 4); - - xl ^= P[0]; + // XOR the newly created 32 bit chunk onto the P-array + P[i] ^= data; + } - for (int i = 1; i < ROUNDS; i += 2) - { - xr ^= F(xl) ^ P[i]; - xl ^= F(xr) ^ P[i + 1]; - } - - xr ^= P[ROUNDS + 1]; - - Bits32ToBytes(xr, dst, dstIndex); - Bits32ToBytes(xl, dst, dstIndex + 4); - } + /* + * (3) Encrypt the all-zero string with the Blowfish algorithm, using + * the subkeys described in (1) and (2) + * + * (4) Replace P1 and P2 with the output of step (3) + * + * (5) Encrypt the output of step(3) using the Blowfish algorithm, with + * the modified subkeys. + * + * (6) Replace P3 and P4 with the output of step (5) + * + * (7) Continue the process, replacing all elements of the P-array and + * then all four S-boxes in order, with the output of the continuously + * changing Blowfish algorithm + */ + processTable(0, 0, P); + processTable(P[P_SZ - 2], P[P_SZ - 1], S0); + processTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1); + processTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2); + processTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3); + } - /** - * Decrypt the given input starting at the given offset and place the result - * in the provided buffer starting at the given offset. The input will be an - * exact multiple of our blocksize. - */ - private void decryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex) - { - int xl = BytesTo32bits(src, srcIndex); - int xr = BytesTo32bits(src, srcIndex + 4); - - xl ^= P[ROUNDS + 1]; + /** + * Encrypt the given input starting at the given offset and place the result + * in the provided buffer starting at the given offset. The input will be an + * exact multiple of our blocksize. + */ + private void encryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex) { + int xl = BytesTo32bits(src, srcIndex); + int xr = BytesTo32bits(src, srcIndex + 4); + xl ^= P[0]; - for (int i = ROUNDS; i > 0; i -= 2) - { - xr ^= F(xl) ^ P[i]; - xl ^= F(xr) ^ P[i - 1]; - } + for (int i = 1; i < ROUNDS; i += 2) { + xr ^= F(xl) ^ P[i]; + xl ^= F(xr) ^ P[i + 1]; + } + + xr ^= P[ROUNDS + 1]; + Bits32ToBytes(xr, dst, dstIndex); + Bits32ToBytes(xl, dst, dstIndex + 4); + } - xr ^= P[0]; - - Bits32ToBytes(xr, dst, dstIndex); - Bits32ToBytes(xl, dst, dstIndex + 4); - } + /** + * Decrypt the given input starting at the given offset and place the result + * in the provided buffer starting at the given offset. The input will be an + * exact multiple of our blocksize. + */ + private void decryptBlock(byte[] src, int srcIndex, byte[] dst, int dstIndex) { + int xl = BytesTo32bits(src, srcIndex); + int xr = BytesTo32bits(src, srcIndex + 4); + xl ^= P[ROUNDS + 1]; - private int BytesTo32bits(byte[] b, int i) - { - return ((b[i] & 0xff) << 24) | ((b[i + 1] & 0xff) << 16) | ((b[i + 2] & 0xff) << 8) | ((b[i + 3] & 0xff)); - } + for (int i = ROUNDS; i > 0; i -= 2) { + xr ^= F(xl) ^ P[i]; + xl ^= F(xr) ^ P[i - 1]; + } + + xr ^= P[0]; + Bits32ToBytes(xr, dst, dstIndex); + Bits32ToBytes(xl, dst, dstIndex + 4); + } - private void Bits32ToBytes(int in, byte[] b, int offset) - { - b[offset + 3] = (byte) in; - b[offset + 2] = (byte) (in >> 8); - b[offset + 1] = (byte) (in >> 16); - b[offset] = (byte) (in >> 24); - } + private int BytesTo32bits(byte[] b, int i) { + return ((b[i] & 0xff) << 24) | ((b[i + 1] & 0xff) << 16) | ((b[i + 2] & 0xff) << 8) | ((b[i + 3] & 0xff)); + } + + private void Bits32ToBytes(int in, byte[] b, int offset) { + b[offset + 3] = (byte) in; + b[offset + 2] = (byte)(in >> 8); + b[offset + 1] = (byte)(in >> 16); + b[offset] = (byte)(in >> 24); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/cipher/CBCMode.java --- a/src/ch/ethz/ssh2/crypto/cipher/CBCMode.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/cipher/CBCMode.java Wed Jul 30 14:16:58 2014 -0700 @@ -6,77 +6,66 @@ /** * CBCMode. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class CBCMode implements BlockCipher -{ - BlockCipher tc; - int blockSize; - boolean doEncrypt; +public class CBCMode implements BlockCipher { + BlockCipher tc; + int blockSize; + boolean doEncrypt; - byte[] cbc_vector; - byte[] tmp_vector; + byte[] cbc_vector; + byte[] tmp_vector; + + public void init(boolean forEncryption, byte[] key) { + } - public void init(boolean forEncryption, byte[] key) - { - } - - public CBCMode(BlockCipher tc, byte[] iv, boolean doEncrypt) - throws IllegalArgumentException - { - this.tc = tc; - this.blockSize = tc.getBlockSize(); - this.doEncrypt = doEncrypt; + public CBCMode(BlockCipher tc, byte[] iv, boolean doEncrypt) + throws IllegalArgumentException { + this.tc = tc; + this.blockSize = tc.getBlockSize(); + this.doEncrypt = doEncrypt; - if (this.blockSize != iv.length) - throw new IllegalArgumentException("IV must be " + blockSize - + " bytes long! (currently " + iv.length + ")"); + if (this.blockSize != iv.length) + throw new IllegalArgumentException("IV must be " + blockSize + + " bytes long! (currently " + iv.length + ")"); - this.cbc_vector = new byte[blockSize]; - this.tmp_vector = new byte[blockSize]; - System.arraycopy(iv, 0, cbc_vector, 0, blockSize); - } + this.cbc_vector = new byte[blockSize]; + this.tmp_vector = new byte[blockSize]; + System.arraycopy(iv, 0, cbc_vector, 0, blockSize); + } - public int getBlockSize() - { - return blockSize; - } + public int getBlockSize() { + return blockSize; + } - private void encryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff) - { - for (int i = 0; i < blockSize; i++) - cbc_vector[i] ^= src[srcoff + i]; + private void encryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { + for (int i = 0; i < blockSize; i++) + cbc_vector[i] ^= src[srcoff + i]; - tc.transformBlock(cbc_vector, 0, dst, dstoff); + tc.transformBlock(cbc_vector, 0, dst, dstoff); + System.arraycopy(dst, dstoff, cbc_vector, 0, blockSize); + } - System.arraycopy(dst, dstoff, cbc_vector, 0, blockSize); - } + private void decryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { + /* Assume the worst, src and dst are overlapping... */ + System.arraycopy(src, srcoff, tmp_vector, 0, blockSize); + tc.transformBlock(src, srcoff, dst, dstoff); - private void decryptBlock(byte[] src, int srcoff, byte[] dst, int dstoff) - { - /* Assume the worst, src and dst are overlapping... */ - - System.arraycopy(src, srcoff, tmp_vector, 0, blockSize); - - tc.transformBlock(src, srcoff, dst, dstoff); - - for (int i = 0; i < blockSize; i++) - dst[dstoff + i] ^= cbc_vector[i]; + for (int i = 0; i < blockSize; i++) + dst[dstoff + i] ^= cbc_vector[i]; - /* ...that is why we need a tmp buffer. */ - - byte[] swap = cbc_vector; - cbc_vector = tmp_vector; - tmp_vector = swap; - } + /* ...that is why we need a tmp buffer. */ + byte[] swap = cbc_vector; + cbc_vector = tmp_vector; + tmp_vector = swap; + } - public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) - { - if (doEncrypt) - encryptBlock(src, srcoff, dst, dstoff); - else - decryptBlock(src, srcoff, dst, dstoff); - } + public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { + if (doEncrypt) + encryptBlock(src, srcoff, dst, dstoff); + else + decryptBlock(src, srcoff, dst, dstoff); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/cipher/CTRMode.java --- a/src/ch/ethz/ssh2/crypto/cipher/CTRMode.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/cipher/CTRMode.java Wed Jul 30 14:16:58 2014 -0700 @@ -6,60 +6,52 @@ /** * This is CTR mode as described in draft-ietf-secsh-newmodes-XY.txt - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class CTRMode implements BlockCipher -{ - byte[] X; - byte[] Xenc; +public class CTRMode implements BlockCipher { + byte[] X; + byte[] Xenc; - BlockCipher bc; - int blockSize; - boolean doEncrypt; + BlockCipher bc; + int blockSize; + boolean doEncrypt; - int count = 0; + int count = 0; - public void init(boolean forEncryption, byte[] key) - { - } + public void init(boolean forEncryption, byte[] key) { + } - public CTRMode(BlockCipher tc, byte[] iv, boolean doEnc) throws IllegalArgumentException - { - bc = tc; - blockSize = bc.getBlockSize(); - doEncrypt = doEnc; + public CTRMode(BlockCipher tc, byte[] iv, boolean doEnc) throws IllegalArgumentException { + bc = tc; + blockSize = bc.getBlockSize(); + doEncrypt = doEnc; - if (blockSize != iv.length) - throw new IllegalArgumentException("IV must be " + blockSize + " bytes long! (currently " + iv.length + ")"); - - X = new byte[blockSize]; - Xenc = new byte[blockSize]; + if (blockSize != iv.length) + throw new IllegalArgumentException("IV must be " + blockSize + " bytes long! (currently " + iv.length + ")"); - System.arraycopy(iv, 0, X, 0, blockSize); - } + X = new byte[blockSize]; + Xenc = new byte[blockSize]; + System.arraycopy(iv, 0, X, 0, blockSize); + } - public final int getBlockSize() - { - return blockSize; - } + public final int getBlockSize() { + return blockSize; + } - public final void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) - { - bc.transformBlock(X, 0, Xenc, 0); + public final void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { + bc.transformBlock(X, 0, Xenc, 0); - for (int i = 0; i < blockSize; i++) - { - dst[dstoff + i] = (byte) (src[srcoff + i] ^ Xenc[i]); - } + for (int i = 0; i < blockSize; i++) { + dst[dstoff + i] = (byte)(src[srcoff + i] ^ Xenc[i]); + } - for (int i = (blockSize - 1); i >= 0; i--) - { - X[i]++; - if (X[i] != 0) - break; + for (int i = (blockSize - 1); i >= 0; i--) { + X[i]++; - } - } + if (X[i] != 0) + break; + } + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/cipher/CipherInputStream.java --- a/src/ch/ethz/ssh2/crypto/cipher/CipherInputStream.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/cipher/CipherInputStream.java Wed Jul 30 14:16:58 2014 -0700 @@ -13,148 +13,134 @@ * @author Christian Plattner * @version $Id: CipherInputStream.java 11 2011-05-27 14:14:06Z dkocher@sudo.ch $ */ -public class CipherInputStream -{ - BlockCipher currentCipher; - InputStream bi; - byte[] buffer; - byte[] enc; - int blockSize; - int pos; +public class CipherInputStream { + BlockCipher currentCipher; + InputStream bi; + byte[] buffer; + byte[] enc; + int blockSize; + int pos; - /* - * We cannot use java.io.BufferedInputStream, since that is not available in - * J2ME. Everything could be improved alot here. - */ + /* + * We cannot use java.io.BufferedInputStream, since that is not available in + * J2ME. Everything could be improved alot here. + */ - private static final int BUFF_SIZE = 8192; - byte[] input_buffer = new byte[BUFF_SIZE]; - int input_buffer_pos = 0; - int input_buffer_size = 0; + private static final int BUFF_SIZE = 8192; + byte[] input_buffer = new byte[BUFF_SIZE]; + int input_buffer_pos = 0; + int input_buffer_size = 0; - public CipherInputStream(BlockCipher tc, InputStream bi) - { - this.bi = bi; - changeCipher(tc); - } + public CipherInputStream(BlockCipher tc, InputStream bi) { + this.bi = bi; + changeCipher(tc); + } - private int fill_buffer() throws IOException - { - input_buffer_pos = 0; - input_buffer_size = 0; - input_buffer_size = bi.read(input_buffer, 0, BUFF_SIZE); - return input_buffer_size; - } + private int fill_buffer() throws IOException { + input_buffer_pos = 0; + input_buffer_size = 0; + input_buffer_size = bi.read(input_buffer, 0, BUFF_SIZE); + return input_buffer_size; + } - private int internal_read(byte[] b, int off, int len) throws IOException - { - if (input_buffer_size < 0) - { - return -1; - } + private int internal_read(byte[] b, int off, int len) throws IOException { + if (input_buffer_size < 0) { + return -1; + } - if (input_buffer_pos >= input_buffer_size) - { - if (fill_buffer() <= 0) - { - return -1; - } - } + if (input_buffer_pos >= input_buffer_size) { + if (fill_buffer() <= 0) { + return -1; + } + } + + int avail = input_buffer_size - input_buffer_pos; + int thiscopy = (len > avail) ? avail : len; + System.arraycopy(input_buffer, input_buffer_pos, b, off, thiscopy); + input_buffer_pos += thiscopy; + return thiscopy; + } - int avail = input_buffer_size - input_buffer_pos; - int thiscopy = (len > avail) ? avail : len; - - System.arraycopy(input_buffer, input_buffer_pos, b, off, thiscopy); - input_buffer_pos += thiscopy; - - return thiscopy; - } + public void changeCipher(BlockCipher bc) { + this.currentCipher = bc; + blockSize = bc.getBlockSize(); + buffer = new byte[blockSize]; + enc = new byte[blockSize]; + pos = blockSize; + } - public void changeCipher(BlockCipher bc) - { - this.currentCipher = bc; - blockSize = bc.getBlockSize(); - buffer = new byte[blockSize]; - enc = new byte[blockSize]; - pos = blockSize; - } + private void getBlock() throws IOException { + int n = 0; + + while (n < blockSize) { + int len = internal_read(enc, n, blockSize - n); + + if (len < 0) { + throw new IOException("Cannot read full block, EOF reached."); + } - private void getBlock() throws IOException - { - int n = 0; - while (n < blockSize) - { - int len = internal_read(enc, n, blockSize - n); - if (len < 0) - { - throw new IOException("Cannot read full block, EOF reached."); - } - n += len; - } + n += len; + } + + try { + currentCipher.transformBlock(enc, 0, buffer, 0); + } + catch (Exception e) { + throw new IOException("Error while decrypting block."); + } - try - { - currentCipher.transformBlock(enc, 0, buffer, 0); - } - catch (Exception e) - { - throw new IOException("Error while decrypting block."); - } - pos = 0; - } + pos = 0; + } + + public int read(byte[] dst) throws IOException { + return read(dst, 0, dst.length); + } - public int read(byte[] dst) throws IOException - { - return read(dst, 0, dst.length); - } + public int read(byte[] dst, int off, int len) throws IOException { + int count = 0; - public int read(byte[] dst, int off, int len) throws IOException - { - int count = 0; - - while (len > 0) - { - if (pos >= blockSize) - { - getBlock(); - } + while (len > 0) { + if (pos >= blockSize) { + getBlock(); + } - int avail = blockSize - pos; - int copy = Math.min(avail, len); - System.arraycopy(buffer, pos, dst, off, copy); - pos += copy; - off += copy; - len -= copy; - count += copy; - } - return count; - } + int avail = blockSize - pos; + int copy = Math.min(avail, len); + System.arraycopy(buffer, pos, dst, off, copy); + pos += copy; + off += copy; + len -= copy; + count += copy; + } - public int read() throws IOException - { - if (pos >= blockSize) - { - getBlock(); - } - return buffer[pos++] & 0xff; - } + return count; + } + + public int read() throws IOException { + if (pos >= blockSize) { + getBlock(); + } + + return buffer[pos++] & 0xff; + } - public int readPlain(byte[] b, int off, int len) throws IOException - { - if (pos != blockSize) - { - throw new IOException("Cannot read plain since crypto buffer is not aligned."); - } - int n = 0; - while (n < len) - { - int cnt = internal_read(b, off + n, len - n); - if (cnt < 0) - { - throw new IOException("Cannot fill buffer, EOF reached."); - } - n += cnt; - } - return n; - } + public int readPlain(byte[] b, int off, int len) throws IOException { + if (pos != blockSize) { + throw new IOException("Cannot read plain since crypto buffer is not aligned."); + } + + int n = 0; + + while (n < len) { + int cnt = internal_read(b, off + n, len - n); + + if (cnt < 0) { + throw new IOException("Cannot fill buffer, EOF reached."); + } + + n += cnt; + } + + return n; + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/cipher/CipherOutputStream.java --- a/src/ch/ethz/ssh2/crypto/cipher/CipherOutputStream.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/cipher/CipherOutputStream.java Wed Jul 30 14:16:58 2014 -0700 @@ -13,143 +13,122 @@ * @author Christian Plattner * @version $Id: CipherOutputStream.java 85 2014-04-07 14:05:09Z dkocher@sudo.ch $ */ -public class CipherOutputStream -{ - BlockCipher currentCipher; - OutputStream bo; - byte[] buffer; - byte[] enc; - int blockSize; - int pos; - - /* - * We cannot use java.io.BufferedOutputStream, since that is not available - * in J2ME. Everything could be improved here alot. - */ +public class CipherOutputStream { + BlockCipher currentCipher; + OutputStream bo; + byte[] buffer; + byte[] enc; + int blockSize; + int pos; - private static final int BUFF_SIZE = 8192; - byte[] out_buffer = new byte[BUFF_SIZE]; - int out_buffer_pos = 0; + /* + * We cannot use java.io.BufferedOutputStream, since that is not available + * in J2ME. Everything could be improved here alot. + */ - public CipherOutputStream(BlockCipher tc, OutputStream bo) - { - this.bo = bo; - changeCipher(tc); - } + private static final int BUFF_SIZE = 8192; + byte[] out_buffer = new byte[BUFF_SIZE]; + int out_buffer_pos = 0; - private void internal_write(byte[] src, int off, int len) throws IOException - { - while (len > 0) - { - int space = BUFF_SIZE - out_buffer_pos; - int copy = (len > space) ? space : len; - - System.arraycopy(src, off, out_buffer, out_buffer_pos, copy); + public CipherOutputStream(BlockCipher tc, OutputStream bo) { + this.bo = bo; + changeCipher(tc); + } - off += copy; - out_buffer_pos += copy; - len -= copy; + private void internal_write(byte[] src, int off, int len) throws IOException { + while (len > 0) { + int space = BUFF_SIZE - out_buffer_pos; + int copy = (len > space) ? space : len; + System.arraycopy(src, off, out_buffer, out_buffer_pos, copy); + off += copy; + out_buffer_pos += copy; + len -= copy; - if (out_buffer_pos >= BUFF_SIZE) - { - bo.write(out_buffer, 0, BUFF_SIZE); - out_buffer_pos = 0; - } - } - } + if (out_buffer_pos >= BUFF_SIZE) { + bo.write(out_buffer, 0, BUFF_SIZE); + out_buffer_pos = 0; + } + } + } + + private void internal_write(int b) throws IOException { + out_buffer[out_buffer_pos++] = (byte) b; - private void internal_write(int b) throws IOException - { - out_buffer[out_buffer_pos++] = (byte) b; - if (out_buffer_pos >= BUFF_SIZE) - { - bo.write(out_buffer, 0, BUFF_SIZE); - out_buffer_pos = 0; - } - } + if (out_buffer_pos >= BUFF_SIZE) { + bo.write(out_buffer, 0, BUFF_SIZE); + out_buffer_pos = 0; + } + } - public void flush() throws IOException - { - if (pos != 0) - { - throw new IOException("FATAL: cannot flush since crypto buffer is not aligned."); - } + public void flush() throws IOException { + if (pos != 0) { + throw new IOException("FATAL: cannot flush since crypto buffer is not aligned."); + } - if (out_buffer_pos > 0) - { - bo.write(out_buffer, 0, out_buffer_pos); - out_buffer_pos = 0; - } - bo.flush(); - } + if (out_buffer_pos > 0) { + bo.write(out_buffer, 0, out_buffer_pos); + out_buffer_pos = 0; + } + + bo.flush(); + } - public void changeCipher(BlockCipher bc) - { - this.currentCipher = bc; - blockSize = bc.getBlockSize(); - buffer = new byte[blockSize]; - enc = new byte[blockSize]; - pos = 0; - } + public void changeCipher(BlockCipher bc) { + this.currentCipher = bc; + blockSize = bc.getBlockSize(); + buffer = new byte[blockSize]; + enc = new byte[blockSize]; + pos = 0; + } - private void writeBlock() throws IOException - { - try - { - currentCipher.transformBlock(buffer, 0, enc, 0); - } - catch (Exception e) - { - throw new IOException("Error while decrypting block.", e); - } + private void writeBlock() throws IOException { + try { + currentCipher.transformBlock(buffer, 0, enc, 0); + } + catch (Exception e) { + throw new IOException("Error while decrypting block.", e); + } - internal_write(enc, 0, blockSize); - pos = 0; - } + internal_write(enc, 0, blockSize); + pos = 0; + } - public void write(byte[] src, int off, int len) throws IOException - { - while (len > 0) - { - int avail = blockSize - pos; - int copy = Math.min(avail, len); + public void write(byte[] src, int off, int len) throws IOException { + while (len > 0) { + int avail = blockSize - pos; + int copy = Math.min(avail, len); + System.arraycopy(src, off, buffer, pos, copy); + pos += copy; + off += copy; + len -= copy; - System.arraycopy(src, off, buffer, pos, copy); - pos += copy; - off += copy; - len -= copy; + if (pos >= blockSize) { + writeBlock(); + } + } + } - if (pos >= blockSize) - { - writeBlock(); - } - } - } + public void write(int b) throws IOException { + buffer[pos++] = (byte) b; + + if (pos >= blockSize) { + writeBlock(); + } + } - public void write(int b) throws IOException - { - buffer[pos++] = (byte) b; - if (pos >= blockSize) - { - writeBlock(); - } - } + public void writePlain(int b) throws IOException { + if (pos != 0) { + throw new IOException("Cannot write plain since crypto buffer is not aligned."); + } + + internal_write(b); + } - public void writePlain(int b) throws IOException - { - if (pos != 0) - { - throw new IOException("Cannot write plain since crypto buffer is not aligned."); - } - internal_write(b); - } + public void writePlain(byte[] b, int off, int len) throws IOException { + if (pos != 0) { + throw new IOException("Cannot write plain since crypto buffer is not aligned."); + } - public void writePlain(byte[] b, int off, int len) throws IOException - { - if (pos != 0) - { - throw new IOException("Cannot write plain since crypto buffer is not aligned."); - } - internal_write(b, off, len); - } + internal_write(b, off, len); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/cipher/DES.java --- a/src/ch/ethz/ssh2/crypto/cipher/DES.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/cipher/DES.java Wed Jul 30 14:16:58 2014 -0700 @@ -23,350 +23,330 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + THE SOFTWARE. */ /** * DES. - * + * * @author See comments in the source file * @version 2.50, 03/15/10 - * + * */ -public class DES implements BlockCipher -{ - private int[] workingKey = null; +public class DES implements BlockCipher { + private int[] workingKey = null; - /** - * standard constructor. - */ - public DES() - { - } + /** + * standard constructor. + */ + public DES() { + } - /** - * initialise a DES cipher. - * - * @param encrypting - * whether or not we are for encryption. - * @param key - * the parameters required to set up the cipher. - * @exception IllegalArgumentException - * if the params argument is inappropriate. - */ - public void init(boolean encrypting, byte[] key) - { - this.workingKey = generateWorkingKey(encrypting, key, 0); - } + /** + * initialise a DES cipher. + * + * @param encrypting + * whether or not we are for encryption. + * @param key + * the parameters required to set up the cipher. + * @exception IllegalArgumentException + * if the params argument is inappropriate. + */ + public void init(boolean encrypting, byte[] key) { + this.workingKey = generateWorkingKey(encrypting, key, 0); + } - public String getAlgorithmName() - { - return "DES"; - } + public String getAlgorithmName() { + return "DES"; + } - public int getBlockSize() - { - return 8; - } + public int getBlockSize() { + return 8; + } - public void transformBlock(byte[] in, int inOff, byte[] out, int outOff) - { - if (workingKey == null) - { - throw new IllegalStateException("DES engine not initialised!"); - } + public void transformBlock(byte[] in, int inOff, byte[] out, int outOff) { + if (workingKey == null) { + throw new IllegalStateException("DES engine not initialised!"); + } - desFunc(workingKey, in, inOff, out, outOff); - } + desFunc(workingKey, in, inOff, out, outOff); + } - public void reset() - { - } + public void reset() { + } - /** - * what follows is mainly taken from "Applied Cryptography", by Bruce - * Schneier, however it also bears great resemblance to Richard - * Outerbridge's D3DES... - */ + /** + * what follows is mainly taken from "Applied Cryptography", by Bruce + * Schneier, however it also bears great resemblance to Richard + * Outerbridge's D3DES... + */ + + static short[] Df_Key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, + 0x10, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67 + }; - static short[] Df_Key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, - 0x10, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67 }; + static short[] bytebit = { 0200, 0100, 040, 020, 010, 04, 02, 01 }; - static short[] bytebit = { 0200, 0100, 040, 020, 010, 04, 02, 01 }; + static int[] bigbyte = { 0x800000, 0x400000, 0x200000, 0x100000, 0x80000, 0x40000, 0x20000, 0x10000, 0x8000, + 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 + }; - static int[] bigbyte = { 0x800000, 0x400000, 0x200000, 0x100000, 0x80000, 0x40000, 0x20000, 0x10000, 0x8000, - 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }; + /* + * Use the key schedule specified in the Standard (ANSI X3.92-1981). + */ - /* - * Use the key schedule specified in the Standard (ANSI X3.92-1981). - */ + static byte[] pc1 = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, + 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, + 4, 27, 19, 11, 3 + }; - static byte[] pc1 = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, - 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, - 4, 27, 19, 11, 3 }; + static byte[] totrot = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 }; - static byte[] totrot = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 }; - - static byte[] pc2 = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, - 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; + static byte[] pc2 = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, + 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 + }; - static int[] SP1 = { 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, - 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, - 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, - 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, - 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, - 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, - 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, - 0x00010400, 0x00000000, 0x01010004 }; + static int[] SP1 = { 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004, + 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004, + 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404, + 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400, + 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004, + 0x00010400, 0x00000000, 0x01010004 + }; - static int[] SP2 = { 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, - 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, - 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, - 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, - 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, - 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, - 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, - 0x80100020, 0x80108020, 0x00108000 }; + static int[] SP2 = { 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020, + 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020, + 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020, + 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020, + 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000, + 0x80100020, 0x80108020, 0x00108000 + }; - static int[] SP3 = { 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, - 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, - 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, - 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, - 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, - 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, - 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, - 0x00000008, 0x08020008, 0x00020200 }; + static int[] SP3 = { 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208, + 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208, + 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000, + 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208, + 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208, + 0x00000008, 0x08020008, 0x00020200 + }; - static int[] SP4 = { 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, - 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, - 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, - 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, - 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, - 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, - 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, - 0x00800000, 0x00002000, 0x00802080 }; - - static int[] SP5 = { 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, - 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, - 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, - 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, - 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, - 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, - 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, - 0x40080000, 0x02080100, 0x40000100 }; + static int[] SP4 = { 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001, + 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081, + 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001, + 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081, + 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080, + 0x00800000, 0x00002000, 0x00802080 + }; - static int[] SP6 = { 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, - 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, - 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, - 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, - 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, - 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, - 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, - 0x20000000, 0x00400010, 0x20004010 }; + static int[] SP5 = { 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000, + 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000, + 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100, + 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000, + 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000, + 0x40080000, 0x02080100, 0x40000100 + }; - static int[] SP7 = { 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, - 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, - 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, - 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, - 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, - 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, - 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, - 0x04000800, 0x00000800, 0x00200002 }; + static int[] SP6 = { 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010, + 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010, + 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010, + 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000, + 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000, + 0x20000000, 0x00400010, 0x20004010 + }; - static int[] SP8 = { 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, - 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, - 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, - 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, - 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, - 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, - 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, - 0x00040040, 0x10000000, 0x10041000 }; + static int[] SP7 = { 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802, + 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000, + 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800, + 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800, + 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002, + 0x04000800, 0x00000800, 0x00200002 + }; - /** - * generate an integer based working key based on our secret key and what we - * processing we are planning to do. - * - * Acknowledgements for this routine go to James Gillogly & Phil Karn. - * (whoever, and wherever they are!). - */ - protected int[] generateWorkingKey(boolean encrypting, byte[] key, int off) - { - int[] newKey = new int[32]; - boolean[] pc1m = new boolean[56], pcr = new boolean[56]; - - for (int j = 0; j < 56; j++) - { - int l = pc1[j]; - - pc1m[j] = ((key[off + (l >>> 3)] & bytebit[l & 07]) != 0); - } + static int[] SP8 = { 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040, + 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040, + 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000, + 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040, + 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040, + 0x00040040, 0x10000000, 0x10041000 + }; - for (int i = 0; i < 16; i++) - { - int l, m, n; + /** + * generate an integer based working key based on our secret key and what we + * processing we are planning to do. + * + * Acknowledgements for this routine go to James Gillogly & Phil Karn. + * (whoever, and wherever they are!). + */ + protected int[] generateWorkingKey(boolean encrypting, byte[] key, int off) { + int[] newKey = new int[32]; + boolean[] pc1m = new boolean[56], pcr = new boolean[56]; - if (encrypting) - { - m = i << 1; - } - else - { - m = (15 - i) << 1; - } + for (int j = 0; j < 56; j++) { + int l = pc1[j]; + pc1m[j] = ((key[off + (l >>> 3)] & bytebit[l & 07]) != 0); + } - n = m + 1; - newKey[m] = newKey[n] = 0; + for (int i = 0; i < 16; i++) { + int l, m, n; - for (int j = 0; j < 28; j++) - { - l = j + totrot[i]; - if (l < 28) - { - pcr[j] = pc1m[l]; - } - else - { - pcr[j] = pc1m[l - 28]; - } - } + if (encrypting) { + m = i << 1; + } + else { + m = (15 - i) << 1; + } + + n = m + 1; + newKey[m] = newKey[n] = 0; + + for (int j = 0; j < 28; j++) { + l = j + totrot[i]; - for (int j = 28; j < 56; j++) - { - l = j + totrot[i]; - if (l < 56) - { - pcr[j] = pc1m[l]; - } - else - { - pcr[j] = pc1m[l - 28]; - } - } + if (l < 28) { + pcr[j] = pc1m[l]; + } + else { + pcr[j] = pc1m[l - 28]; + } + } - for (int j = 0; j < 24; j++) - { - if (pcr[pc2[j]]) - { - newKey[m] |= bigbyte[j]; - } + for (int j = 28; j < 56; j++) { + l = j + totrot[i]; - if (pcr[pc2[j + 24]]) - { - newKey[n] |= bigbyte[j]; - } - } - } + if (l < 56) { + pcr[j] = pc1m[l]; + } + else { + pcr[j] = pc1m[l - 28]; + } + } - // - // store the processed key - // - for (int i = 0; i != 32; i += 2) - { - int i1, i2; + for (int j = 0; j < 24; j++) { + if (pcr[pc2[j]]) { + newKey[m] |= bigbyte[j]; + } - i1 = newKey[i]; - i2 = newKey[i + 1]; - - newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10) | ((i2 & 0x00fc0000) >>> 10) - | ((i2 & 0x00000fc0) >>> 6); + if (pcr[pc2[j + 24]]) { + newKey[n] |= bigbyte[j]; + } + } + } - newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16) | ((i2 & 0x0003f000) >>> 4) - | (i2 & 0x0000003f); - } - - return newKey; - } + // + // store the processed key + // + for (int i = 0; i != 32; i += 2) { + int i1, i2; + i1 = newKey[i]; + i2 = newKey[i + 1]; + newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10) | ((i2 & 0x00fc0000) >>> 10) + | ((i2 & 0x00000fc0) >>> 6); + newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16) | ((i2 & 0x0003f000) >>> 4) + | (i2 & 0x0000003f); + } - /** - * the DES engine. - */ - protected void desFunc(int[] wKey, byte[] in, int inOff, byte[] out, int outOff) - { - int work, right, left; + return newKey; + } - left = (in[inOff + 0] & 0xff) << 24; - left |= (in[inOff + 1] & 0xff) << 16; - left |= (in[inOff + 2] & 0xff) << 8; - left |= (in[inOff + 3] & 0xff); - - right = (in[inOff + 4] & 0xff) << 24; - right |= (in[inOff + 5] & 0xff) << 16; - right |= (in[inOff + 6] & 0xff) << 8; - right |= (in[inOff + 7] & 0xff); - - work = ((left >>> 4) ^ right) & 0x0f0f0f0f; - right ^= work; - left ^= (work << 4); - work = ((left >>> 16) ^ right) & 0x0000ffff; - right ^= work; - left ^= (work << 16); - work = ((right >>> 2) ^ left) & 0x33333333; - left ^= work; - right ^= (work << 2); - work = ((right >>> 8) ^ left) & 0x00ff00ff; - left ^= work; - right ^= (work << 8); - right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff; - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff; - - for (int round = 0; round < 8; round++) - { - int fval; + /** + * the DES engine. + */ + protected void desFunc(int[] wKey, byte[] in, int inOff, byte[] out, int outOff) { + int work, right, left; + left = (in[inOff + 0] & 0xff) << 24; + left |= (in[inOff + 1] & 0xff) << 16; + left |= (in[inOff + 2] & 0xff) << 8; + left |= (in[inOff + 3] & 0xff); + right = (in[inOff + 4] & 0xff) << 24; + right |= (in[inOff + 5] & 0xff) << 16; + right |= (in[inOff + 6] & 0xff) << 8; + right |= (in[inOff + 7] & 0xff); + work = ((left >>> 4) ^ right) & 0x0f0f0f0f; + right ^= work; + left ^= (work << 4); + work = ((left >>> 16) ^ right) & 0x0000ffff; + right ^= work; + left ^= (work << 16); + work = ((right >>> 2) ^ left) & 0x33333333; + left ^= work; + right ^= (work << 2); + work = ((right >>> 8) ^ left) & 0x00ff00ff; + left ^= work; + right ^= (work << 8); + right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff; + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff; - work = (right << 28) | (right >>> 4); - work ^= wKey[round * 4 + 0]; - fval = SP7[work & 0x3f]; - fval |= SP5[(work >>> 8) & 0x3f]; - fval |= SP3[(work >>> 16) & 0x3f]; - fval |= SP1[(work >>> 24) & 0x3f]; - work = right ^ wKey[round * 4 + 1]; - fval |= SP8[work & 0x3f]; - fval |= SP6[(work >>> 8) & 0x3f]; - fval |= SP4[(work >>> 16) & 0x3f]; - fval |= SP2[(work >>> 24) & 0x3f]; - left ^= fval; - work = (left << 28) | (left >>> 4); - work ^= wKey[round * 4 + 2]; - fval = SP7[work & 0x3f]; - fval |= SP5[(work >>> 8) & 0x3f]; - fval |= SP3[(work >>> 16) & 0x3f]; - fval |= SP1[(work >>> 24) & 0x3f]; - work = left ^ wKey[round * 4 + 3]; - fval |= SP8[work & 0x3f]; - fval |= SP6[(work >>> 8) & 0x3f]; - fval |= SP4[(work >>> 16) & 0x3f]; - fval |= SP2[(work >>> 24) & 0x3f]; - right ^= fval; - } + for (int round = 0; round < 8; round++) { + int fval; + work = (right << 28) | (right >>> 4); + work ^= wKey[round * 4 + 0]; + fval = SP7[work & 0x3f]; + fval |= SP5[(work >>> 8) & 0x3f]; + fval |= SP3[(work >>> 16) & 0x3f]; + fval |= SP1[(work >>> 24) & 0x3f]; + work = right ^ wKey[round * 4 + 1]; + fval |= SP8[work & 0x3f]; + fval |= SP6[(work >>> 8) & 0x3f]; + fval |= SP4[(work >>> 16) & 0x3f]; + fval |= SP2[(work >>> 24) & 0x3f]; + left ^= fval; + work = (left << 28) | (left >>> 4); + work ^= wKey[round * 4 + 2]; + fval = SP7[work & 0x3f]; + fval |= SP5[(work >>> 8) & 0x3f]; + fval |= SP3[(work >>> 16) & 0x3f]; + fval |= SP1[(work >>> 24) & 0x3f]; + work = left ^ wKey[round * 4 + 3]; + fval |= SP8[work & 0x3f]; + fval |= SP6[(work >>> 8) & 0x3f]; + fval |= SP4[(work >>> 16) & 0x3f]; + fval |= SP2[(work >>> 24) & 0x3f]; + right ^= fval; + } - right = (right << 31) | (right >>> 1); - work = (left ^ right) & 0xaaaaaaaa; - left ^= work; - right ^= work; - left = (left << 31) | (left >>> 1); - work = ((left >>> 8) ^ right) & 0x00ff00ff; - right ^= work; - left ^= (work << 8); - work = ((left >>> 2) ^ right) & 0x33333333; - right ^= work; - left ^= (work << 2); - work = ((right >>> 16) ^ left) & 0x0000ffff; - left ^= work; - right ^= (work << 16); - work = ((right >>> 4) ^ left) & 0x0f0f0f0f; - left ^= work; - right ^= (work << 4); - - out[outOff + 0] = (byte) ((right >>> 24) & 0xff); - out[outOff + 1] = (byte) ((right >>> 16) & 0xff); - out[outOff + 2] = (byte) ((right >>> 8) & 0xff); - out[outOff + 3] = (byte) (right & 0xff); - out[outOff + 4] = (byte) ((left >>> 24) & 0xff); - out[outOff + 5] = (byte) ((left >>> 16) & 0xff); - out[outOff + 6] = (byte) ((left >>> 8) & 0xff); - out[outOff + 7] = (byte) (left & 0xff); - } + right = (right << 31) | (right >>> 1); + work = (left ^ right) & 0xaaaaaaaa; + left ^= work; + right ^= work; + left = (left << 31) | (left >>> 1); + work = ((left >>> 8) ^ right) & 0x00ff00ff; + right ^= work; + left ^= (work << 8); + work = ((left >>> 2) ^ right) & 0x33333333; + right ^= work; + left ^= (work << 2); + work = ((right >>> 16) ^ left) & 0x0000ffff; + left ^= work; + right ^= (work << 16); + work = ((right >>> 4) ^ left) & 0x0f0f0f0f; + left ^= work; + right ^= (work << 4); + out[outOff + 0] = (byte)((right >>> 24) & 0xff); + out[outOff + 1] = (byte)((right >>> 16) & 0xff); + out[outOff + 2] = (byte)((right >>> 8) & 0xff); + out[outOff + 3] = (byte)(right & 0xff); + out[outOff + 4] = (byte)((left >>> 24) & 0xff); + out[outOff + 5] = (byte)((left >>> 16) & 0xff); + out[outOff + 6] = (byte)((left >>> 8) & 0xff); + out[outOff + 7] = (byte)(left & 0xff); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/cipher/DESede.java --- a/src/ch/ethz/ssh2/crypto/cipher/DESede.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/cipher/DESede.java Wed Jul 30 14:16:58 2014 -0700 @@ -23,87 +23,76 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + THE SOFTWARE. */ /** * DESede. - * + * * @author See comments in the source file * @version 2.50, 03/15/10 - * + * */ -public class DESede extends DES -{ - private int[] key1 = null; - private int[] key2 = null; - private int[] key3 = null; +public class DESede extends DES { + private int[] key1 = null; + private int[] key2 = null; + private int[] key3 = null; - private boolean encrypt; + private boolean encrypt; - /** - * standard constructor. - */ - public DESede() - { - } + /** + * standard constructor. + */ + public DESede() { + } - /** - * initialise a DES cipher. - * - * @param encrypting - * whether or not we are for encryption. - * @param key - * the parameters required to set up the cipher. - * @exception IllegalArgumentException - * if the params argument is inappropriate. - */ - @Override - public void init(boolean encrypting, byte[] key) - { - key1 = generateWorkingKey(encrypting, key, 0); - key2 = generateWorkingKey(!encrypting, key, 8); - key3 = generateWorkingKey(encrypting, key, 16); - - encrypt = encrypting; - } + /** + * initialise a DES cipher. + * + * @param encrypting + * whether or not we are for encryption. + * @param key + * the parameters required to set up the cipher. + * @exception IllegalArgumentException + * if the params argument is inappropriate. + */ + @Override + public void init(boolean encrypting, byte[] key) { + key1 = generateWorkingKey(encrypting, key, 0); + key2 = generateWorkingKey(!encrypting, key, 8); + key3 = generateWorkingKey(encrypting, key, 16); + encrypt = encrypting; + } - @Override - public String getAlgorithmName() - { - return "DESede"; - } + @Override + public String getAlgorithmName() { + return "DESede"; + } - @Override - public int getBlockSize() - { - return 8; - } + @Override + public int getBlockSize() { + return 8; + } - @Override - public void transformBlock(byte[] in, int inOff, byte[] out, int outOff) - { - if (key1 == null) - { - throw new IllegalStateException("DESede engine not initialised!"); - } + @Override + public void transformBlock(byte[] in, int inOff, byte[] out, int outOff) { + if (key1 == null) { + throw new IllegalStateException("DESede engine not initialised!"); + } - if (encrypt) - { - desFunc(key1, in, inOff, out, outOff); - desFunc(key2, out, outOff, out, outOff); - desFunc(key3, out, outOff, out, outOff); - } - else - { - desFunc(key3, in, inOff, out, outOff); - desFunc(key2, out, outOff, out, outOff); - desFunc(key1, out, outOff, out, outOff); - } - } + if (encrypt) { + desFunc(key1, in, inOff, out, outOff); + desFunc(key2, out, outOff, out, outOff); + desFunc(key3, out, outOff, out, outOff); + } + else { + desFunc(key3, in, inOff, out, outOff); + desFunc(key2, out, outOff, out, outOff); + desFunc(key1, out, outOff, out, outOff); + } + } - @Override - public void reset() - { - } + @Override + public void reset() { + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/cipher/NullCipher.java --- a/src/ch/ethz/ssh2/crypto/cipher/NullCipher.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/cipher/NullCipher.java Wed Jul 30 14:16:58 2014 -0700 @@ -6,34 +6,28 @@ /** * NullCipher. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class NullCipher implements BlockCipher -{ - private int blockSize = 8; - - public NullCipher() - { - } +public class NullCipher implements BlockCipher { + private int blockSize = 8; + + public NullCipher() { + } + + public NullCipher(int blockSize) { + this.blockSize = blockSize; + } - public NullCipher(int blockSize) - { - this.blockSize = blockSize; - } - - public void init(boolean forEncryption, byte[] key) - { - } + public void init(boolean forEncryption, byte[] key) { + } - public int getBlockSize() - { - return blockSize; - } + public int getBlockSize() { + return blockSize; + } - public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) - { - System.arraycopy(src, srcoff, dst, dstoff, blockSize); - } + public void transformBlock(byte[] src, int srcoff, byte[] dst, int dstoff) { + System.arraycopy(src, srcoff, dst, dstoff, blockSize); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/dh/DhExchange.java --- a/src/ch/ethz/ssh2/crypto/dh/DhExchange.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/dh/DhExchange.java Wed Jul 30 14:16:58 2014 -0700 @@ -19,43 +19,41 @@ public class DhExchange { private static final Logger log = Logger.getLogger(DhExchange.class); - /* Given by the standard */ + /* Given by the standard */ static final BigInteger p1, p14; static final BigInteger g; BigInteger p; - /* Client public and private */ + /* Client public and private */ BigInteger e; BigInteger x; - /* Server public and private */ + /* Server public and private */ BigInteger f; BigInteger y; - /* Shared secret */ + /* Shared secret */ BigInteger k; static { final String p1_string = "17976931348623159077083915679378745319786029604875" - + "60117064444236841971802161585193689478337958649255415021805654859805036464" - + "40548199239100050792877003355816639229553136239076508735759914822574862575" - + "00742530207744771258955095793777842444242661733472762929938766870920560605" - + "0270810842907692932019128194467627007"; - + + "60117064444236841971802161585193689478337958649255415021805654859805036464" + + "40548199239100050792877003355816639229553136239076508735759914822574862575" + + "00742530207744771258955095793777842444242661733472762929938766870920560605" + + "0270810842907692932019128194467627007"; final String p14_string = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129" - + "024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0" - + "A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB" - + "6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A" - + "163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208" - + "552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36C" - + "E3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF69558171" - + "83995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF"; - + + "024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0" + + "A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB" + + "6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A" + + "163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208" + + "552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36C" + + "E3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF69558171" + + "83995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF"; p1 = new BigInteger(p1_string); p14 = new BigInteger(p14_string, 16); g = new BigInteger("2"); @@ -67,19 +65,20 @@ public void clientInit(int group, SecureRandom rnd) { k = null; - if(group == 1) { + if (group == 1) { p = p1; } - else if(group == 14) { + else if (group == 14) { p = p14; } else { throw new IllegalArgumentException("Unknown DH group " + group); } - while(true) { + while (true) { x = new BigInteger(p.bitLength() - 1, rnd); - if(x.compareTo(BigInteger.ONE) > 0) { + + if (x.compareTo(BigInteger.ONE) > 0) { break; } } @@ -90,10 +89,10 @@ public void serverInit(int group, SecureRandom rnd) { k = null; - if(group == 1) { + if (group == 1) { p = p1; } - else if(group == 14) { + else if (group == 14) { p = p14; } else { @@ -101,7 +100,6 @@ } y = new BigInteger(p.bitLength() - 1, rnd); - f = g.modPow(y, p); } @@ -110,7 +108,7 @@ * @throws IllegalStateException */ public BigInteger getE() { - if(e == null) { + if (e == null) { throw new IllegalStateException("DhDsaExchange not initialized!"); } @@ -122,7 +120,7 @@ * @throws IllegalStateException */ public BigInteger getF() { - if(f == null) { + if (f == null) { throw new IllegalStateException("DhDsaExchange not initialized!"); } @@ -134,7 +132,7 @@ * @throws IllegalStateException */ public BigInteger getK() { - if(k == null) { + if (k == null) { throw new IllegalStateException("Shared secret not yet known, need f first!"); } @@ -145,11 +143,11 @@ * @param f */ public void setF(BigInteger f) { - if(e == null) { + if (e == null) { throw new IllegalStateException("DhDsaExchange not initialized!"); } - if(BigInteger.ZERO.compareTo(f) >= 0 || p.compareTo(f) <= 0) { + if (BigInteger.ZERO.compareTo(f) >= 0 || p.compareTo(f) <= 0) { throw new IllegalArgumentException("Invalid f specified!"); } @@ -161,11 +159,11 @@ * @param e */ public void setE(BigInteger e) { - if(f == null) { + if (f == null) { throw new IllegalStateException("DhDsaExchange not initialized!"); } - if(BigInteger.ZERO.compareTo(e) >= 0 || p.compareTo(e) <= 0) { + if (BigInteger.ZERO.compareTo(e) >= 0 || p.compareTo(e) <= 0) { throw new IllegalArgumentException("Invalid e specified!"); } @@ -177,7 +175,7 @@ byte[] serverKexPayload, byte[] hostKey) throws IOException { HashForSSH2Types hash = new HashForSSH2Types("SHA1"); - if(log.isInfoEnabled()) { + if (log.isInfoEnabled()) { log.info("Client: '" + StringEncoder.GetString(clientversion) + "'"); log.info("Server: '" + StringEncoder.GetString(serverversion) + "'"); } @@ -190,7 +188,6 @@ hash.updateBigInt(e); hash.updateBigInt(f); hash.updateBigInt(k); - return hash.getDigest(); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/dh/DhGroupExchange.java --- a/src/ch/ethz/ssh2/crypto/dh/DhGroupExchange.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/dh/DhGroupExchange.java Wed Jul 30 14:16:58 2014 -0700 @@ -23,16 +23,16 @@ private BigInteger p; private BigInteger g; - /* Client public and private */ + /* Client public and private */ private BigInteger e; private BigInteger x; - /* Server public */ + /* Server public */ private BigInteger f; - /* Shared secret */ + /* Shared secret */ private BigInteger k; @@ -43,7 +43,6 @@ public void init(SecureRandom rnd) { k = null; - x = new BigInteger(p.bitLength() - 1, rnd); e = g.modPow(x, p); } @@ -52,7 +51,7 @@ * @return Returns the e. */ public BigInteger getE() { - if(e == null) { + if (e == null) { throw new IllegalStateException("Not initialized!"); } @@ -63,7 +62,7 @@ * @return Returns the shared secret k. */ public BigInteger getK() { - if(k == null) { + if (k == null) { throw new IllegalStateException("Shared secret not yet known, need f first!"); } @@ -74,13 +73,13 @@ * Sets f and calculates the shared secret. */ public void setF(BigInteger f) { - if(e == null) { + if (e == null) { throw new IllegalStateException("Not initialized!"); } BigInteger zero = BigInteger.valueOf(0); - if(zero.compareTo(f) >= 0 || p.compareTo(f) <= 0) { + if (zero.compareTo(f) >= 0 || p.compareTo(f) <= 0) { throw new IllegalArgumentException("Invalid f specified!"); } @@ -91,25 +90,27 @@ public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clientKexPayload, byte[] serverKexPayload, byte[] hostKey, DHGexParameters para) throws IOException { HashForSSH2Types hash = new HashForSSH2Types("SHA1"); - hash.updateByteString(clientversion); hash.updateByteString(serverversion); hash.updateByteString(clientKexPayload); hash.updateByteString(serverKexPayload); hash.updateByteString(hostKey); - if(para.getMin_group_len() > 0) { + + if (para.getMin_group_len() > 0) { hash.updateUINT32(para.getMin_group_len()); } + hash.updateUINT32(para.getPref_group_len()); - if(para.getMax_group_len() > 0) { + + if (para.getMax_group_len() > 0) { hash.updateUINT32(para.getMax_group_len()); } + hash.updateBigInt(p); hash.updateBigInt(g); hash.updateBigInt(e); hash.updateBigInt(f); hash.updateBigInt(k); - return hash.getDigest(); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/digest/HMAC.java --- a/src/ch/ethz/ssh2/crypto/digest/HMAC.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/digest/HMAC.java Wed Jul 30 14:16:58 2014 -0700 @@ -8,90 +8,76 @@ /** * HMAC. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public final class HMAC implements Digest -{ - Digest md; - byte[] k_xor_ipad; - byte[] k_xor_opad; +public final class HMAC implements Digest { + Digest md; + byte[] k_xor_ipad; + byte[] k_xor_opad; - byte[] tmp; + byte[] tmp; - int size; + int size; - public HMAC(Digest md, byte[] key, int size) throws DigestException { - this.md = md; - this.size = size; - - tmp = new byte[md.getDigestLength()]; - - final int BLOCKSIZE = 64; + public HMAC(Digest md, byte[] key, int size) throws DigestException { + this.md = md; + this.size = size; + tmp = new byte[md.getDigestLength()]; + final int BLOCKSIZE = 64; + k_xor_ipad = new byte[BLOCKSIZE]; + k_xor_opad = new byte[BLOCKSIZE]; - k_xor_ipad = new byte[BLOCKSIZE]; - k_xor_opad = new byte[BLOCKSIZE]; - - if (key.length > BLOCKSIZE) - { - md.reset(); - md.update(key); - md.digest(tmp); - key = tmp; - } + if (key.length > BLOCKSIZE) { + md.reset(); + md.update(key); + md.digest(tmp); + key = tmp; + } - System.arraycopy(key, 0, k_xor_ipad, 0, key.length); - System.arraycopy(key, 0, k_xor_opad, 0, key.length); + System.arraycopy(key, 0, k_xor_ipad, 0, key.length); + System.arraycopy(key, 0, k_xor_opad, 0, key.length); - for (int i = 0; i < BLOCKSIZE; i++) - { - k_xor_ipad[i] ^= 0x36; - k_xor_opad[i] ^= 0x5C; - } - md.update(k_xor_ipad); - } + for (int i = 0; i < BLOCKSIZE; i++) { + k_xor_ipad[i] ^= 0x36; + k_xor_opad[i] ^= 0x5C; + } + + md.update(k_xor_ipad); + } - public final int getDigestLength() - { - return size; - } + public final int getDigestLength() { + return size; + } - public final void update(byte b) - { - md.update(b); - } + public final void update(byte b) { + md.update(b); + } - public final void update(byte[] b) - { - md.update(b); - } + public final void update(byte[] b) { + md.update(b); + } - public final void update(byte[] b, int off, int len) - { - md.update(b, off, len); - } + public final void update(byte[] b, int off, int len) { + md.update(b, off, len); + } - public final void reset() - { - md.reset(); - md.update(k_xor_ipad); - } + public final void reset() { + md.reset(); + md.update(k_xor_ipad); + } - public final void digest(byte[] out) throws DigestException { - digest(out, 0); - } + public final void digest(byte[] out) throws DigestException { + digest(out, 0); + } - public final void digest(byte[] out, int off) throws DigestException { - md.digest(tmp); - - md.update(k_xor_opad); - md.update(tmp); - - md.digest(tmp); - - System.arraycopy(tmp, 0, out, off, size); - - md.update(k_xor_ipad); - } + public final void digest(byte[] out, int off) throws DigestException { + md.digest(tmp); + md.update(k_xor_opad); + md.update(tmp); + md.digest(tmp); + System.arraycopy(tmp, 0, out, off, size); + md.update(k_xor_ipad); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/digest/HashForSSH2Types.java --- a/src/ch/ethz/ssh2/crypto/digest/HashForSSH2Types.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/digest/HashForSSH2Types.java Wed Jul 30 14:16:58 2014 -0700 @@ -22,13 +22,13 @@ } public HashForSSH2Types(String type) { - if(type.equals("SHA1")) { + if (type.equals("SHA1")) { md = new SHA1(); } - else if(type.equals("SHA2")) { + else if (type.equals("SHA2")) { md = new SHA256(); } - else if(type.equals("MD5")) { + else if (type.equals("MD5")) { md = new MD5(); } else { @@ -45,10 +45,10 @@ } public void updateUINT32(int v) { - md.update((byte) (v >> 24)); - md.update((byte) (v >> 16)); - md.update((byte) (v >> 8)); - md.update((byte) (v)); + md.update((byte)(v >> 24)); + md.update((byte)(v >> 16)); + md.update((byte)(v >> 8)); + md.update((byte)(v)); } public void updateByteString(byte[] b) { @@ -78,7 +78,7 @@ try { getDigest(out, 0); } - catch(DigestException e) { + catch (DigestException e) { throw new IOException(e); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/digest/MAC.java --- a/src/ch/ethz/ssh2/crypto/digest/MAC.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/digest/MAC.java Wed Jul 30 14:16:58 2014 -0700 @@ -19,68 +19,75 @@ public static String[] getMacList() { // Higher priority first. Added SHA-2 algorithms as in RFC 6668 - return new String[]{"hmac-sha1-96", "hmac-sha1", "hmac-md5-96", "hmac-md5", "hmac-sha2-256", "hmac-sha2-512"}; + return new String[] {"hmac-sha1-96", "hmac-sha1", "hmac-md5-96", "hmac-md5", "hmac-sha2-256", "hmac-sha2-512"}; } public static void checkMacList(final String[] macs) { - for(String m : macs) { + for (String m : macs) { getKeyLen(m); } } public static int getKeyLen(final String type) { - if(type.equals("hmac-sha1")) { + if (type.equals("hmac-sha1")) { return 20; } - if(type.equals("hmac-sha1-96")) { + + if (type.equals("hmac-sha1-96")) { return 20; } - if(type.equals("hmac-md5")) { + + if (type.equals("hmac-md5")) { return 16; } - if(type.equals("hmac-md5-96")) { + + if (type.equals("hmac-md5-96")) { return 16; } - if(type.equals("hmac-sha2-256")) { + + if (type.equals("hmac-sha2-256")) { return 32; } - if(type.equals("hmac-sha2-512")) { + + if (type.equals("hmac-sha2-512")) { return 64; } + throw new IllegalArgumentException(String.format("Unknown algorithm %s", type)); } public MAC(final String type, final byte[] key) throws DigestException { - if(type.equals("hmac-sha1")) { + if (type.equals("hmac-sha1")) { mac = new HMAC(new SHA1(), key, 20); } - else if(type.equals("hmac-sha1-96")) { + else if (type.equals("hmac-sha1-96")) { mac = new HMAC(new SHA1(), key, 12); } - else if(type.equals("hmac-md5")) { + else if (type.equals("hmac-md5")) { mac = new HMAC(new MD5(), key, 16); } - else if(type.equals("hmac-md5-96")) { + else if (type.equals("hmac-md5-96")) { mac = new HMAC(new MD5(), key, 12); } - else if(type.equals("hmac-sha2-256")) { + else if (type.equals("hmac-sha2-256")) { mac = new HMAC(new SHA256(), key, 32); } - else if(type.equals("hmac-sha2-512")) { + else if (type.equals("hmac-sha2-512")) { mac = new HMAC(new SHA512(), key, 64); } else { throw new IllegalArgumentException(String.format("Unknown algorithm %s", type)); } + size = mac.getDigestLength(); } public final void initMac(final int seq) { mac.reset(); - mac.update((byte) (seq >> 24)); - mac.update((byte) (seq >> 16)); - mac.update((byte) (seq >> 8)); - mac.update((byte) (seq)); + mac.update((byte)(seq >> 24)); + mac.update((byte)(seq >> 16)); + mac.update((byte)(seq >> 8)); + mac.update((byte)(seq)); } public final void update(byte[] packetdata, int off, int len) { @@ -91,7 +98,7 @@ try { mac.digest(out, off); } - catch(DigestException e) { + catch (DigestException e) { throw new IOException(e); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/digest/MD5.java --- a/src/ch/ethz/ssh2/crypto/digest/MD5.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/digest/MD5.java Wed Jul 30 14:16:58 2014 -0700 @@ -19,7 +19,7 @@ try { md = MessageDigest.getInstance("MD5"); } - catch(NoSuchAlgorithmException e) { + catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/digest/SHA1.java --- a/src/ch/ethz/ssh2/crypto/digest/SHA1.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/digest/SHA1.java Wed Jul 30 14:16:58 2014 -0700 @@ -19,7 +19,7 @@ try { md = MessageDigest.getInstance("SHA-1"); } - catch(NoSuchAlgorithmException e) { + catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/digest/SHA256.java --- a/src/ch/ethz/ssh2/crypto/digest/SHA256.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/digest/SHA256.java Wed Jul 30 14:16:58 2014 -0700 @@ -19,7 +19,7 @@ try { md = MessageDigest.getInstance("SHA-256"); } - catch(NoSuchAlgorithmException e) { + catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/crypto/digest/SHA512.java --- a/src/ch/ethz/ssh2/crypto/digest/SHA512.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/crypto/digest/SHA512.java Wed Jul 30 14:16:58 2014 -0700 @@ -19,7 +19,7 @@ try { md = MessageDigest.getInstance("SHA-512"); } - catch(NoSuchAlgorithmException e) { + catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException(e); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/log/Logger.java --- a/src/ch/ethz/ssh2/log/Logger.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/log/Logger.java Wed Jul 30 14:16:58 2014 -0700 @@ -14,56 +14,47 @@ * @author Christian Plattner * @version $Id: Logger.java 49 2013-08-01 12:28:42Z cleondris@gmail.com $ */ -public class Logger -{ - private java.util.logging.Logger delegate; +public class Logger { + private java.util.logging.Logger delegate; - public static boolean enabled = false; + public static boolean enabled = false; - public static Logger getLogger(Class x) - { - return new Logger(x); - } + public static Logger getLogger(Class x) { + return new Logger(x); + } - public Logger(Class x) - { - this.delegate = java.util.logging.Logger.getLogger(x.getName()); - } + public Logger(Class x) { + this.delegate = java.util.logging.Logger.getLogger(x.getName()); + } public final boolean isEnabled() { return enabled; } - public boolean isDebugEnabled() - { - return enabled && delegate.isLoggable(Level.FINER); - } + public boolean isDebugEnabled() { + return enabled && delegate.isLoggable(Level.FINER); + } - public void debug(String message) - { - if (enabled) - delegate.fine(message); - } + public void debug(String message) { + if (enabled) + delegate.fine(message); + } - public boolean isInfoEnabled() - { - return enabled && delegate.isLoggable(Level.FINE); - } + public boolean isInfoEnabled() { + return enabled && delegate.isLoggable(Level.FINE); + } - public void info(String message) - { - if (enabled) - delegate.info(message); - } + public void info(String message) { + if (enabled) + delegate.info(message); + } - public boolean isWarningEnabled() - { - return enabled && delegate.isLoggable(Level.WARNING); - } + public boolean isWarningEnabled() { + return enabled && delegate.isLoggable(Level.WARNING); + } - public void warning(String message) - { - if (enabled) - delegate.warning(message); - } + public void warning(String message) { + if (enabled) + delegate.warning(message); + } } \ No newline at end of file diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketChannelOpenConfirmation.java --- a/src/ch/ethz/ssh2/packets/PacketChannelOpenConfirmation.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketChannelOpenConfirmation.java Wed Jul 30 14:16:58 2014 -0700 @@ -39,12 +39,10 @@ public PacketChannelOpenConfirmation(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) { + if (packet_type != Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) { throw new PacketTypeException(packet_type); } @@ -53,7 +51,7 @@ initialWindowSize = tr.readUINT32(); maxPacketSize = tr.readUINT32(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketChannelOpenFailure.java --- a/src/ch/ethz/ssh2/packets/PacketChannelOpenFailure.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketChannelOpenFailure.java Wed Jul 30 14:16:58 2014 -0700 @@ -29,15 +29,13 @@ public PacketChannelOpenFailure(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_CHANNEL_OPEN_FAILURE) { + if (packet_type != Packets.SSH_MSG_CHANNEL_OPEN_FAILURE) { throw new IOException( - "This is not a SSH_MSG_CHANNEL_OPEN_FAILURE! (" - + packet_type + ")" + "This is not a SSH_MSG_CHANNEL_OPEN_FAILURE! (" + + packet_type + ")" ); } @@ -46,7 +44,7 @@ String description = tr.readString(); String languageTag = tr.readString(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketChannelWindowAdjust.java --- a/src/ch/ethz/ssh2/packets/PacketChannelWindowAdjust.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketChannelWindowAdjust.java Wed Jul 30 14:16:58 2014 -0700 @@ -26,22 +26,20 @@ public PacketChannelWindowAdjust(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST) { + if (packet_type != Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST) { throw new IOException( - "This is not a SSH_MSG_CHANNEL_WINDOW_ADJUST! (" - + packet_type + ")" + "This is not a SSH_MSG_CHANNEL_WINDOW_ADJUST! (" + + packet_type + ")" ); } int recipientChannelID = tr.readUINT32(); int windowChange = tr.readUINT32(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketDisconnect.java --- a/src/ch/ethz/ssh2/packets/PacketDisconnect.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketDisconnect.java Wed Jul 30 14:16:58 2014 -0700 @@ -41,19 +41,18 @@ public PacketDisconnect(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_DISCONNECT) { + if (packet_type != Packets.SSH_MSG_DISCONNECT) { throw new PacketTypeException(packet_type); } + reason = PacketDisconnect.Reason.values()[tr.readUINT32()]; message = tr.readString(); String lang = tr.readString(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketGlobalCancelForwardRequest.java --- a/src/ch/ethz/ssh2/packets/PacketGlobalCancelForwardRequest.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketGlobalCancelForwardRequest.java Wed Jul 30 14:16:58 2014 -0700 @@ -15,12 +15,10 @@ public PacketGlobalCancelForwardRequest(boolean wantReply, String bindAddress, int bindPort) { TypesWriter tw = new TypesWriter(); tw.writeByte(Packets.SSH_MSG_GLOBAL_REQUEST); - tw.writeString("cancel-tcpip-forward"); tw.writeBoolean(wantReply); tw.writeString(bindAddress); tw.writeUINT32(bindPort); - payload = tw.getBytes(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketGlobalForwardRequest.java --- a/src/ch/ethz/ssh2/packets/PacketGlobalForwardRequest.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketGlobalForwardRequest.java Wed Jul 30 14:16:58 2014 -0700 @@ -15,12 +15,10 @@ public PacketGlobalForwardRequest(boolean wantReply, String bindAddress, int bindPort) { TypesWriter tw = new TypesWriter(); tw.writeByte(Packets.SSH_MSG_GLOBAL_REQUEST); - tw.writeString("tcpip-forward"); tw.writeBoolean(wantReply); tw.writeString(bindAddress); tw.writeUINT32(bindPort); - payload = tw.getBytes(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketIgnore.java --- a/src/ch/ethz/ssh2/packets/PacketIgnore.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketIgnore.java Wed Jul 30 14:16:58 2014 -0700 @@ -19,12 +19,13 @@ TypesWriter tw = new TypesWriter(); tw.writeByte(Packets.SSH_MSG_IGNORE); - if(data != null) { + if (data != null) { tw.writeString(data, 0, data.length); } else { tw.writeString(""); } + payload = tw.getBytes(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketKexDHInit.java --- a/src/ch/ethz/ssh2/packets/PacketKexDHInit.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketKexDHInit.java Wed Jul 30 14:16:58 2014 -0700 @@ -30,18 +30,16 @@ public PacketKexDHInit(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_KEXDH_INIT) { + if (packet_type != Packets.SSH_MSG_KEXDH_INIT) { throw new PacketTypeException(packet_type); } e = tr.readMPINT(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketKexDHReply.java --- a/src/ch/ethz/ssh2/packets/PacketKexDHReply.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketKexDHReply.java Wed Jul 30 14:16:58 2014 -0700 @@ -36,19 +36,18 @@ public PacketKexDHReply(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_KEXDH_REPLY) { + if (packet_type != Packets.SSH_MSG_KEXDH_REPLY) { throw new PacketTypeException(packet_type); } + hostKey = tr.readByteString(); f = tr.readMPINT(); signature = tr.readByteString(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketKexDhGexGroup.java --- a/src/ch/ethz/ssh2/packets/PacketKexDhGexGroup.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketKexDhGexGroup.java Wed Jul 30 14:16:58 2014 -0700 @@ -21,17 +21,16 @@ public PacketKexDhGexGroup(byte payload[]) throws IOException { TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_KEX_DH_GEX_GROUP) { + if (packet_type != Packets.SSH_MSG_KEX_DH_GEX_GROUP) { throw new PacketTypeException(packet_type); } p = tr.readMPINT(); g = tr.readMPINT(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketKexDhGexReply.java --- a/src/ch/ethz/ssh2/packets/PacketKexDhGexReply.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketKexDhGexReply.java Wed Jul 30 14:16:58 2014 -0700 @@ -22,10 +22,9 @@ public PacketKexDhGexReply(byte payload[]) throws IOException { TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_KEX_DH_GEX_REPLY) { + if (packet_type != Packets.SSH_MSG_KEX_DH_GEX_REPLY) { throw new PacketTypeException(packet_type); } @@ -33,7 +32,7 @@ f = tr.readMPINT(); signature = tr.readByteString(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketKexInit.java --- a/src/ch/ethz/ssh2/packets/PacketKexInit.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketKexInit.java Wed Jul 30 14:16:58 2014 -0700 @@ -24,7 +24,6 @@ public PacketKexInit(CryptoWishList cwl, SecureRandom rnd) { kp.cookie = new byte[16]; rnd.nextBytes(kp.cookie); - kp.kex_algorithms = cwl.kexAlgorithms; kp.server_host_key_algorithms = cwl.serverHostKeyAlgorithms; kp.encryption_algorithms_client_to_server = cwl.c2s_enc_algos; @@ -33,11 +32,10 @@ kp.mac_algorithms_server_to_client = cwl.s2c_mac_algos; kp.compression_algorithms_client_to_server = cwl.c2s_comp_algos; kp.compression_algorithms_server_to_client = cwl.s2c_comp_algos; - kp.languages_client_to_server = new String[]{""}; - kp.languages_server_to_client = new String[]{""}; + kp.languages_client_to_server = new String[] {""}; + kp.languages_server_to_client = new String[] {""}; kp.first_kex_packet_follows = false; kp.reserved_field1 = 0; - TypesWriter tw = new TypesWriter(); tw.writeByte(Packets.SSH_MSG_KEXINIT); tw.writeBytes(kp.cookie, 0, 16); @@ -58,14 +56,13 @@ public PacketKexInit(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_KEXINIT) { + if (packet_type != Packets.SSH_MSG_KEXINIT) { throw new PacketTypeException(packet_type); } + kp.cookie = tr.readBytes(16); kp.kex_algorithms = tr.readNameList(); kp.server_host_key_algorithms = tr.readNameList(); @@ -80,7 +77,7 @@ kp.first_kex_packet_follows = tr.readBoolean(); kp.reserved_field1 = tr.readUINT32(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketNewKeys.java --- a/src/ch/ethz/ssh2/packets/PacketNewKeys.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketNewKeys.java Wed Jul 30 14:16:58 2014 -0700 @@ -24,15 +24,14 @@ public PacketNewKeys(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_NEWKEYS) { + if (packet_type != Packets.SSH_MSG_NEWKEYS) { throw new PacketTypeException(packet_type); } - if(tr.remain() != 0) { + + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketOpenDirectTCPIPChannel.java --- a/src/ch/ethz/ssh2/packets/PacketOpenDirectTCPIPChannel.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketOpenDirectTCPIPChannel.java Wed Jul 30 14:16:58 2014 -0700 @@ -15,7 +15,6 @@ String host_to_connect, int port_to_connect, String originator_IP_address, int originator_port) { TypesWriter tw = new TypesWriter(); - tw.writeByte(Packets.SSH_MSG_CHANNEL_OPEN); tw.writeString("direct-tcpip"); tw.writeUINT32(channelID); @@ -25,7 +24,6 @@ tw.writeUINT32(port_to_connect); tw.writeString(originator_IP_address); tw.writeUINT32(originator_port); - payload = tw.getBytes(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketOpenSessionChannel.java --- a/src/ch/ethz/ssh2/packets/PacketOpenSessionChannel.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketOpenSessionChannel.java Wed Jul 30 14:16:58 2014 -0700 @@ -28,12 +28,10 @@ public PacketOpenSessionChannel(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_CHANNEL_OPEN) { + if (packet_type != Packets.SSH_MSG_CHANNEL_OPEN) { throw new PacketTypeException(packet_type); } @@ -41,7 +39,7 @@ int initialWindowSize = tr.readUINT32(); int maxPacketSize = tr.readUINT32(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketServiceAccept.java --- a/src/ch/ethz/ssh2/packets/PacketServiceAccept.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketServiceAccept.java Wed Jul 30 14:16:58 2014 -0700 @@ -16,7 +16,6 @@ private final byte[] payload; public PacketServiceAccept(String serviceName) { - TypesWriter tw = new TypesWriter(); tw.writeByte(Packets.SSH_MSG_SERVICE_ACCEPT); tw.writeString(serviceName); @@ -25,15 +24,14 @@ public PacketServiceAccept(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_SERVICE_ACCEPT) { + if (packet_type != Packets.SSH_MSG_SERVICE_ACCEPT) { throw new PacketTypeException(packet_type); } - if(tr.remain() != 0) { + + if (tr.remain() != 0) { String serviceName = tr.readString(); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketServiceRequest.java --- a/src/ch/ethz/ssh2/packets/PacketServiceRequest.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketServiceRequest.java Wed Jul 30 14:16:58 2014 -0700 @@ -32,18 +32,16 @@ public PacketServiceRequest(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_SERVICE_REQUEST) { + if (packet_type != Packets.SSH_MSG_SERVICE_REQUEST) { throw new PacketTypeException(packet_type); } serviceName = tr.readString(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketSessionPtyRequest.java --- a/src/ch/ethz/ssh2/packets/PacketSessionPtyRequest.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketSessionPtyRequest.java Wed Jul 30 14:16:58 2014 -0700 @@ -25,7 +25,6 @@ tw.writeUINT32(pixel_width); tw.writeUINT32(pixel_height); tw.writeString(terminal_modes, 0, terminal_modes.length); - payload = tw.getBytes(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketSessionX11Request.java --- a/src/ch/ethz/ssh2/packets/PacketSessionX11Request.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketSessionX11Request.java Wed Jul 30 14:16:58 2014 -0700 @@ -18,12 +18,10 @@ tw.writeUINT32(recipientChannelID); tw.writeString("x11-req"); tw.writeBoolean(wantReply); - tw.writeBoolean(singleConnection); tw.writeString(x11AuthenticationProtocol); tw.writeString(x11AuthenticationCookie); tw.writeUINT32(x11ScreenNumber); - payload = tw.getBytes(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketUserauthBanner.java --- a/src/ch/ethz/ssh2/packets/PacketUserauthBanner.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketUserauthBanner.java Wed Jul 30 14:16:58 2014 -0700 @@ -33,18 +33,17 @@ public PacketUserauthBanner(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_USERAUTH_BANNER) { + if (packet_type != Packets.SSH_MSG_USERAUTH_BANNER) { throw new PacketTypeException(packet_type); } + message = tr.readString("UTF-8"); String language = tr.readString(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketUserauthFailure.java --- a/src/ch/ethz/ssh2/packets/PacketUserauthFailure.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketUserauthFailure.java Wed Jul 30 14:16:58 2014 -0700 @@ -36,18 +36,17 @@ public PacketUserauthFailure(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_USERAUTH_FAILURE) { + if (packet_type != Packets.SSH_MSG_USERAUTH_FAILURE) { throw new PacketTypeException(packet_type); } + authThatCanContinue = new HashSet(Arrays.asList(tr.readNameList())); partialSuccess = tr.readBoolean(); - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketUserauthInfoRequest.java --- a/src/ch/ethz/ssh2/packets/PacketUserauthInfoRequest.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketUserauthInfoRequest.java Wed Jul 30 14:16:58 2014 -0700 @@ -25,27 +25,25 @@ public PacketUserauthInfoRequest(byte payload[]) throws IOException { TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_USERAUTH_INFO_REQUEST) { + if (packet_type != Packets.SSH_MSG_USERAUTH_INFO_REQUEST) { throw new PacketTypeException(packet_type); } + name = tr.readString(); instruction = tr.readString(); languageTag = tr.readString(); - numPrompts = tr.readUINT32(); - prompt = new String[numPrompts]; echo = new boolean[numPrompts]; - for(int i = 0; i < numPrompts; i++) { + for (int i = 0; i < numPrompts; i++) { prompt[i] = tr.readString(); echo[i] = tr.readBoolean(); } - if(tr.remain() != 0) { + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketUserauthInfoResponse.java --- a/src/ch/ethz/ssh2/packets/PacketUserauthInfoResponse.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketUserauthInfoResponse.java Wed Jul 30 14:16:58 2014 -0700 @@ -15,9 +15,11 @@ TypesWriter tw = new TypesWriter(); tw.writeByte(Packets.SSH_MSG_USERAUTH_INFO_RESPONSE); tw.writeUINT32(responses.length); - for(String response : responses) { + + for (String response : responses) { tw.writeString(response); } + payload = tw.getBytes(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketUserauthRequestInteractive.java --- a/src/ch/ethz/ssh2/packets/PacketUserauthRequestInteractive.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketUserauthRequestInteractive.java Wed Jul 30 14:16:58 2014 -0700 @@ -20,7 +20,7 @@ tw.writeString("keyboard-interactive"); tw.writeString(""); // draft-ietf-secsh-newmodes-04.txt says that // the language tag should be empty. - tw.writeNameList(null == submethods ? new String[]{} : submethods); + tw.writeNameList(null == submethods ? new String[] {} : submethods); payload = tw.getBytes(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketUserauthRequestNone.java --- a/src/ch/ethz/ssh2/packets/PacketUserauthRequestNone.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketUserauthRequestNone.java Wed Jul 30 14:16:58 2014 -0700 @@ -28,23 +28,22 @@ public PacketUserauthRequestNone(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) { + if (packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) { throw new PacketTypeException(packet_type); } + String userName = tr.readString(); String serviceName = tr.readString(); - String method = tr.readString(); - if(!method.equals("none")) { + if (!method.equals("none")) { throw new IOException(String.format("Unexpected method %s", method)); } - if(tr.remain() != 0) { + + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketUserauthRequestPassword.java --- a/src/ch/ethz/ssh2/packets/PacketUserauthRequestPassword.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketUserauthRequestPassword.java Wed Jul 30 14:16:58 2014 -0700 @@ -30,23 +30,22 @@ public PacketUserauthRequestPassword(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) { + if (packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) { throw new PacketTypeException(packet_type); } + String userName = tr.readString(); String serviceName = tr.readString(); - String method = tr.readString(); - if(!method.equals("password")) { + if (!method.equals("password")) { throw new IOException(String.format("Unexpected method %s", method)); } - if(tr.remain() != 0) { + + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketUserauthRequestPublicKey.java --- a/src/ch/ethz/ssh2/packets/PacketUserauthRequestPublicKey.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketUserauthRequestPublicKey.java Wed Jul 30 14:16:58 2014 -0700 @@ -33,23 +33,22 @@ public PacketUserauthRequestPublicKey(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) { + if (packet_type != Packets.SSH_MSG_USERAUTH_REQUEST) { throw new PacketTypeException(packet_type); } + String userName = tr.readString(); String serviceName = tr.readString(); - String method = tr.readString(); - if(!method.equals("publickey")) { + if (!method.equals("publickey")) { throw new IOException(String.format("Unexpected method %s", method)); } - if(tr.remain() != 0) { + + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketUserauthSuccess.java --- a/src/ch/ethz/ssh2/packets/PacketUserauthSuccess.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketUserauthSuccess.java Wed Jul 30 14:16:58 2014 -0700 @@ -25,15 +25,14 @@ public PacketUserauthSuccess(byte payload[]) throws IOException { this.payload = payload; - TypesReader tr = new TypesReader(payload); - int packet_type = tr.readByte(); - if(packet_type != Packets.SSH_MSG_USERAUTH_SUCCESS) { + if (packet_type != Packets.SSH_MSG_USERAUTH_SUCCESS) { throw new PacketTypeException(packet_type); } - if(tr.remain() != 0) { + + if (tr.remain() != 0) { throw new PacketFormatException(String.format("Padding in %s", Packets.getMessageName(packet_type))); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/PacketWindowChange.java --- a/src/ch/ethz/ssh2/packets/PacketWindowChange.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/PacketWindowChange.java Wed Jul 30 14:16:58 2014 -0700 @@ -21,7 +21,6 @@ tw.writeUINT32(character_height); tw.writeUINT32(pixel_width); tw.writeUINT32(pixel_height); - payload = tw.getBytes(); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/Packets.java --- a/src/ch/ethz/ssh2/packets/Packets.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/Packets.java Wed Jul 30 14:16:58 2014 -0700 @@ -6,131 +6,121 @@ /** * Packets. - * + * * @author Christian Plattner * @version 2.50, 03/15/10 */ -public final class Packets -{ - public static final int SSH_MSG_DISCONNECT = 1; - public static final int SSH_MSG_IGNORE = 2; - public static final int SSH_MSG_UNIMPLEMENTED = 3; - public static final int SSH_MSG_DEBUG = 4; - public static final int SSH_MSG_SERVICE_REQUEST = 5; - public static final int SSH_MSG_SERVICE_ACCEPT = 6; - - public static final int SSH_MSG_KEXINIT = 20; - public static final int SSH_MSG_NEWKEYS = 21; +public final class Packets { + public static final int SSH_MSG_DISCONNECT = 1; + public static final int SSH_MSG_IGNORE = 2; + public static final int SSH_MSG_UNIMPLEMENTED = 3; + public static final int SSH_MSG_DEBUG = 4; + public static final int SSH_MSG_SERVICE_REQUEST = 5; + public static final int SSH_MSG_SERVICE_ACCEPT = 6; - public static final int SSH_MSG_KEXDH_INIT = 30; - public static final int SSH_MSG_KEXDH_REPLY = 31; + public static final int SSH_MSG_KEXINIT = 20; + public static final int SSH_MSG_NEWKEYS = 21; + + public static final int SSH_MSG_KEXDH_INIT = 30; + public static final int SSH_MSG_KEXDH_REPLY = 31; - public static final int SSH_MSG_KEX_DH_GEX_REQUEST_OLD = 30; - public static final int SSH_MSG_KEX_DH_GEX_REQUEST = 34; - public static final int SSH_MSG_KEX_DH_GEX_GROUP = 31; - public static final int SSH_MSG_KEX_DH_GEX_INIT = 32; - public static final int SSH_MSG_KEX_DH_GEX_REPLY = 33; - - public static final int SSH_MSG_USERAUTH_REQUEST = 50; - public static final int SSH_MSG_USERAUTH_FAILURE = 51; - public static final int SSH_MSG_USERAUTH_SUCCESS = 52; - public static final int SSH_MSG_USERAUTH_BANNER = 53; - public static final int SSH_MSG_USERAUTH_INFO_REQUEST = 60; - public static final int SSH_MSG_USERAUTH_INFO_RESPONSE = 61; + public static final int SSH_MSG_KEX_DH_GEX_REQUEST_OLD = 30; + public static final int SSH_MSG_KEX_DH_GEX_REQUEST = 34; + public static final int SSH_MSG_KEX_DH_GEX_GROUP = 31; + public static final int SSH_MSG_KEX_DH_GEX_INIT = 32; + public static final int SSH_MSG_KEX_DH_GEX_REPLY = 33; - public static final int SSH_MSG_GLOBAL_REQUEST = 80; - public static final int SSH_MSG_REQUEST_SUCCESS = 81; - public static final int SSH_MSG_REQUEST_FAILURE = 82; + public static final int SSH_MSG_USERAUTH_REQUEST = 50; + public static final int SSH_MSG_USERAUTH_FAILURE = 51; + public static final int SSH_MSG_USERAUTH_SUCCESS = 52; + public static final int SSH_MSG_USERAUTH_BANNER = 53; + public static final int SSH_MSG_USERAUTH_INFO_REQUEST = 60; + public static final int SSH_MSG_USERAUTH_INFO_RESPONSE = 61; - public static final int SSH_MSG_CHANNEL_OPEN = 90; - public static final int SSH_MSG_CHANNEL_OPEN_CONFIRMATION = 91; - public static final int SSH_MSG_CHANNEL_OPEN_FAILURE = 92; - public static final int SSH_MSG_CHANNEL_WINDOW_ADJUST = 93; - public static final int SSH_MSG_CHANNEL_DATA = 94; - public static final int SSH_MSG_CHANNEL_EXTENDED_DATA = 95; - public static final int SSH_MSG_CHANNEL_EOF = 96; - public static final int SSH_MSG_CHANNEL_CLOSE = 97; - public static final int SSH_MSG_CHANNEL_REQUEST = 98; - public static final int SSH_MSG_CHANNEL_SUCCESS = 99; - public static final int SSH_MSG_CHANNEL_FAILURE = 100; + public static final int SSH_MSG_GLOBAL_REQUEST = 80; + public static final int SSH_MSG_REQUEST_SUCCESS = 81; + public static final int SSH_MSG_REQUEST_FAILURE = 82; - public static final int SSH_EXTENDED_DATA_STDERR = 1; - - public static final int SSH_OPEN_ADMINISTRATIVELY_PROHIBITED = 1; - public static final int SSH_OPEN_CONNECT_FAILED = 2; - public static final int SSH_OPEN_UNKNOWN_CHANNEL_TYPE = 3; - public static final int SSH_OPEN_RESOURCE_SHORTAGE = 4; - - private static final String[] reverseNames = new String[101]; + public static final int SSH_MSG_CHANNEL_OPEN = 90; + public static final int SSH_MSG_CHANNEL_OPEN_CONFIRMATION = 91; + public static final int SSH_MSG_CHANNEL_OPEN_FAILURE = 92; + public static final int SSH_MSG_CHANNEL_WINDOW_ADJUST = 93; + public static final int SSH_MSG_CHANNEL_DATA = 94; + public static final int SSH_MSG_CHANNEL_EXTENDED_DATA = 95; + public static final int SSH_MSG_CHANNEL_EOF = 96; + public static final int SSH_MSG_CHANNEL_CLOSE = 97; + public static final int SSH_MSG_CHANNEL_REQUEST = 98; + public static final int SSH_MSG_CHANNEL_SUCCESS = 99; + public static final int SSH_MSG_CHANNEL_FAILURE = 100; - static - { - reverseNames[1] = "SSH_MSG_DISCONNECT"; - reverseNames[2] = "SSH_MSG_IGNORE"; - reverseNames[3] = "SSH_MSG_UNIMPLEMENTED"; - reverseNames[4] = "SSH_MSG_DEBUG"; - reverseNames[5] = "SSH_MSG_SERVICE_REQUEST"; - reverseNames[6] = "SSH_MSG_SERVICE_ACCEPT"; + public static final int SSH_EXTENDED_DATA_STDERR = 1; + + public static final int SSH_OPEN_ADMINISTRATIVELY_PROHIBITED = 1; + public static final int SSH_OPEN_CONNECT_FAILED = 2; + public static final int SSH_OPEN_UNKNOWN_CHANNEL_TYPE = 3; + public static final int SSH_OPEN_RESOURCE_SHORTAGE = 4; + + private static final String[] reverseNames = new String[101]; - reverseNames[20] = "SSH_MSG_KEXINIT"; - reverseNames[21] = "SSH_MSG_NEWKEYS"; - - reverseNames[30] = "SSH_MSG_KEXDH_INIT"; - reverseNames[31] = "SSH_MSG_KEXDH_REPLY/SSH_MSG_KEX_DH_GEX_GROUP"; - reverseNames[32] = "SSH_MSG_KEX_DH_GEX_INIT"; - reverseNames[33] = "SSH_MSG_KEX_DH_GEX_REPLY"; - reverseNames[34] = "SSH_MSG_KEX_DH_GEX_REQUEST"; - - reverseNames[50] = "SSH_MSG_USERAUTH_REQUEST"; - reverseNames[51] = "SSH_MSG_USERAUTH_FAILURE"; - reverseNames[52] = "SSH_MSG_USERAUTH_SUCCESS"; - reverseNames[53] = "SSH_MSG_USERAUTH_BANNER"; - - reverseNames[60] = "SSH_MSG_USERAUTH_INFO_REQUEST"; - reverseNames[61] = "SSH_MSG_USERAUTH_INFO_RESPONSE"; - - reverseNames[80] = "SSH_MSG_GLOBAL_REQUEST"; - reverseNames[81] = "SSH_MSG_REQUEST_SUCCESS"; - reverseNames[82] = "SSH_MSG_REQUEST_FAILURE"; + static { + reverseNames[1] = "SSH_MSG_DISCONNECT"; + reverseNames[2] = "SSH_MSG_IGNORE"; + reverseNames[3] = "SSH_MSG_UNIMPLEMENTED"; + reverseNames[4] = "SSH_MSG_DEBUG"; + reverseNames[5] = "SSH_MSG_SERVICE_REQUEST"; + reverseNames[6] = "SSH_MSG_SERVICE_ACCEPT"; + reverseNames[20] = "SSH_MSG_KEXINIT"; + reverseNames[21] = "SSH_MSG_NEWKEYS"; + reverseNames[30] = "SSH_MSG_KEXDH_INIT"; + reverseNames[31] = "SSH_MSG_KEXDH_REPLY/SSH_MSG_KEX_DH_GEX_GROUP"; + reverseNames[32] = "SSH_MSG_KEX_DH_GEX_INIT"; + reverseNames[33] = "SSH_MSG_KEX_DH_GEX_REPLY"; + reverseNames[34] = "SSH_MSG_KEX_DH_GEX_REQUEST"; + reverseNames[50] = "SSH_MSG_USERAUTH_REQUEST"; + reverseNames[51] = "SSH_MSG_USERAUTH_FAILURE"; + reverseNames[52] = "SSH_MSG_USERAUTH_SUCCESS"; + reverseNames[53] = "SSH_MSG_USERAUTH_BANNER"; + reverseNames[60] = "SSH_MSG_USERAUTH_INFO_REQUEST"; + reverseNames[61] = "SSH_MSG_USERAUTH_INFO_RESPONSE"; + reverseNames[80] = "SSH_MSG_GLOBAL_REQUEST"; + reverseNames[81] = "SSH_MSG_REQUEST_SUCCESS"; + reverseNames[82] = "SSH_MSG_REQUEST_FAILURE"; + reverseNames[90] = "SSH_MSG_CHANNEL_OPEN"; + reverseNames[91] = "SSH_MSG_CHANNEL_OPEN_CONFIRMATION"; + reverseNames[92] = "SSH_MSG_CHANNEL_OPEN_FAILURE"; + reverseNames[93] = "SSH_MSG_CHANNEL_WINDOW_ADJUST"; + reverseNames[94] = "SSH_MSG_CHANNEL_DATA"; + reverseNames[95] = "SSH_MSG_CHANNEL_EXTENDED_DATA"; + reverseNames[96] = "SSH_MSG_CHANNEL_EOF"; + reverseNames[97] = "SSH_MSG_CHANNEL_CLOSE"; + reverseNames[98] = "SSH_MSG_CHANNEL_REQUEST"; + reverseNames[99] = "SSH_MSG_CHANNEL_SUCCESS"; + reverseNames[100] = "SSH_MSG_CHANNEL_FAILURE"; + } - reverseNames[90] = "SSH_MSG_CHANNEL_OPEN"; - reverseNames[91] = "SSH_MSG_CHANNEL_OPEN_CONFIRMATION"; - reverseNames[92] = "SSH_MSG_CHANNEL_OPEN_FAILURE"; - reverseNames[93] = "SSH_MSG_CHANNEL_WINDOW_ADJUST"; - reverseNames[94] = "SSH_MSG_CHANNEL_DATA"; - reverseNames[95] = "SSH_MSG_CHANNEL_EXTENDED_DATA"; - reverseNames[96] = "SSH_MSG_CHANNEL_EOF"; - reverseNames[97] = "SSH_MSG_CHANNEL_CLOSE"; - reverseNames[98] = "SSH_MSG_CHANNEL_REQUEST"; - reverseNames[99] = "SSH_MSG_CHANNEL_SUCCESS"; - reverseNames[100] = "SSH_MSG_CHANNEL_FAILURE"; - } + public static final String getMessageName(int type) { + String res = null; - public static final String getMessageName(int type) - { - String res = null; + if ((type >= 0) && (type < reverseNames.length)) { + res = reverseNames[type]; + } + + return (res == null) ? ("UNKNOWN MSG " + type) : res; + } - if ((type >= 0) && (type < reverseNames.length)) - { - res = reverseNames[type]; - } - - return (res == null) ? ("UNKNOWN MSG " + type) : res; - } - - // public static final void debug(String tag, byte[] msg) - // { - // System.err.println(tag + " Type: " + msg[0] + ", LEN: " + msg.length); - // - // for (int i = 0; i < msg.length; i++) - // { - // if (((msg[i] >= 'a') && (msg[i] <= 'z')) || ((msg[i] >= 'A') && (msg[i] <= 'Z')) - // || ((msg[i] >= '0') && (msg[i] <= '9')) || (msg[i] == ' ')) - // System.err.print((char) msg[i]); - // else - // System.err.print("."); - // } - // System.err.println(); - // System.err.flush(); - // } + // public static final void debug(String tag, byte[] msg) + // { + // System.err.println(tag + " Type: " + msg[0] + ", LEN: " + msg.length); + // + // for (int i = 0; i < msg.length; i++) + // { + // if (((msg[i] >= 'a') && (msg[i] <= 'z')) || ((msg[i] >= 'A') && (msg[i] <= 'Z')) + // || ((msg[i] >= '0') && (msg[i] <= '9')) || (msg[i] == ' ')) + // System.err.print((char) msg[i]); + // else + // System.err.print("."); + // } + // System.err.println(); + // System.err.flush(); + // } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/TypesReader.java --- a/src/ch/ethz/ssh2/packets/TypesReader.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/TypesReader.java Wed Jul 30 14:16:58 2014 -0700 @@ -30,7 +30,7 @@ this.pos = off; this.max = arr.length; - if((pos < 0) || (pos > arr.length)) { + if ((pos < 0) || (pos > arr.length)) { throw new IllegalArgumentException("Illegal offset."); } } @@ -40,17 +40,17 @@ this.pos = off; this.max = off + len; - if((pos < 0) || (pos > arr.length)) { + if ((pos < 0) || (pos > arr.length)) { throw new IllegalArgumentException("Illegal offset."); } - if((max < 0) || (max > arr.length)) { + if ((max < 0) || (max > arr.length)) { throw new IllegalArgumentException("Illegal length."); } } public int readByte() throws IOException { - if(pos >= max) { + if (pos >= max) { throw new PacketFormatException("Packet too short."); } @@ -58,20 +58,18 @@ } public byte[] readBytes(int len) throws IOException { - if((pos + len) > max) { + if ((pos + len) > max) { throw new PacketFormatException("Packet too short."); } byte[] res = new byte[len]; - System.arraycopy(arr, pos, res, 0, len); pos += len; - return res; } public void readBytes(byte[] dst, int off, int len) throws IOException { - if((pos + len) > max) { + if ((pos + len) > max) { throw new PacketFormatException("Packet too short."); } @@ -80,7 +78,7 @@ } public boolean readBoolean() throws IOException { - if(pos >= max) { + if (pos >= max) { throw new PacketFormatException("Packet too short."); } @@ -88,34 +86,31 @@ } public int readUINT32() throws IOException { - if((pos + 4) > max) { + if ((pos + 4) > max) { throw new PacketFormatException("Packet too short."); } return ((arr[pos++] & 0xff) << 24) | ((arr[pos++] & 0xff) << 16) | ((arr[pos++] & 0xff) << 8) - | (arr[pos++] & 0xff); + | (arr[pos++] & 0xff); } public long readUINT64() throws IOException { - if((pos + 8) > max) { + if ((pos + 8) > max) { throw new PacketFormatException("Packet too short."); } long high = ((arr[pos++] & 0xff) << 24) | ((arr[pos++] & 0xff) << 16) | ((arr[pos++] & 0xff) << 8) - | (arr[pos++] & 0xff); /* sign extension may take place - will be shifted away =) */ - + | (arr[pos++] & 0xff); /* sign extension may take place - will be shifted away =) */ long low = ((arr[pos++] & 0xff) << 24) | ((arr[pos++] & 0xff) << 16) | ((arr[pos++] & 0xff) << 8) - | (arr[pos++] & 0xff); /* sign extension may take place - handle below */ - + | (arr[pos++] & 0xff); /* sign extension may take place - handle below */ return (high << 32) | (low & 0xffffffffl); /* see Java language spec (15.22.1, 5.6.2) */ } public BigInteger readMPINT() throws IOException { BigInteger b; - byte raw[] = readByteString(); - if(raw.length == 0) { + if (raw.length == 0) { b = BigInteger.ZERO; } else { @@ -128,7 +123,7 @@ public byte[] readByteString() throws IOException { int len = readUINT32(); - if((len + pos) > max) { + if ((len + pos) > max) { throw new PacketFormatException("Malformed SSH byte string."); } @@ -141,26 +136,24 @@ public String readString(String charsetName) throws IOException { int len = readUINT32(); - if((len + pos) > max) { + if ((len + pos) > max) { throw new PacketFormatException("Malformed SSH string."); } String res = (charsetName == null) ? new String(arr, pos, len) : new String(arr, pos, len, charsetName); pos += len; - return res; } public String readString() throws IOException { int len = readUINT32(); - if((len + pos) > max) { + if ((len + pos) > max) { throw new PacketFormatException("Malformed SSH string."); } String res = StringEncoder.GetString(arr, pos, len); pos += len; - return res; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/packets/TypesWriter.java --- a/src/ch/ethz/ssh2/packets/TypesWriter.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/packets/TypesWriter.java Wed Jul 30 14:16:58 2014 -0700 @@ -43,13 +43,13 @@ } public void writeUINT32(int val, int off) { - if((off + 4) > arr.length) { + if ((off + 4) > arr.length) { resize(off + 32); } - arr[off++] = (byte) (val >> 24); - arr[off++] = (byte) (val >> 16); - arr[off++] = (byte) (val >> 8); + arr[off++] = (byte)(val >> 24); + arr[off++] = (byte)(val >> 16); + arr[off++] = (byte)(val >> 8); arr[off++] = (byte) val; } @@ -59,22 +59,22 @@ } public void writeUINT64(long val) { - if((pos + 8) > arr.length) { + if ((pos + 8) > arr.length) { resize(arr.length + 32); } - arr[pos++] = (byte) (val >> 56); - arr[pos++] = (byte) (val >> 48); - arr[pos++] = (byte) (val >> 40); - arr[pos++] = (byte) (val >> 32); - arr[pos++] = (byte) (val >> 24); - arr[pos++] = (byte) (val >> 16); - arr[pos++] = (byte) (val >> 8); + arr[pos++] = (byte)(val >> 56); + arr[pos++] = (byte)(val >> 48); + arr[pos++] = (byte)(val >> 40); + arr[pos++] = (byte)(val >> 32); + arr[pos++] = (byte)(val >> 24); + arr[pos++] = (byte)(val >> 16); + arr[pos++] = (byte)(val >> 8); arr[pos++] = (byte) val; } public void writeBoolean(boolean v) { - if((pos + 1) > arr.length) { + if ((pos + 1) > arr.length) { resize(arr.length + 32); } @@ -82,7 +82,7 @@ } public void writeByte(int v, int off) { - if((off + 1) > arr.length) { + if ((off + 1) > arr.length) { resize(off + 32); } @@ -97,7 +97,7 @@ public void writeMPInt(BigInteger b) { byte raw[] = b.toByteArray(); - if((raw.length == 1) && (raw[0] == 0)) { + if ((raw.length == 1) && (raw[0] == 0)) { writeUINT32(0); /* String with zero bytes of data */ } else { @@ -110,7 +110,7 @@ } public void writeBytes(byte[] buff, int off, int len) { - if((pos + len) > arr.length) { + if ((pos + len) > arr.length) { resize(arr.length + len + 32); } @@ -125,26 +125,27 @@ public void writeString(String v) { byte[] b = StringEncoder.GetBytes(v); - writeUINT32(b.length); writeBytes(b, 0, b.length); } public void writeString(String v, String charsetName) throws UnsupportedEncodingException { byte[] b = (charsetName == null) ? StringEncoder.GetBytes(v) : v.getBytes(charsetName); - writeUINT32(b.length); writeBytes(b, 0, b.length); } public void writeNameList(String v[]) { StringBuilder sb = new StringBuilder(); - for(int i = 0; i < v.length; i++) { - if(i > 0) { + + for (int i = 0; i < v.length; i++) { + if (i > 0) { sb.append(','); } + sb.append(v[i]); } + writeString(sb.toString()); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/server/ServerConnectionState.java --- a/src/ch/ethz/ssh2/server/ServerConnectionState.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/server/ServerConnectionState.java Wed Jul 30 14:16:58 2014 -0700 @@ -21,36 +21,34 @@ import ch.ethz.ssh2.transport.ClientServerHello; import ch.ethz.ssh2.transport.ServerTransportManager; -public class ServerConnectionState -{ - public ServerConnection conn; +public class ServerConnectionState { + public ServerConnection conn; - public SecureRandom generator = new SecureRandom(); + public SecureRandom generator = new SecureRandom(); - public String softwareversion; + public String softwareversion; - //public String auth_banner = null; - public ServerConnectionCallback cb_conn; - public ServerAuthenticationCallback cb_auth; + //public String auth_banner = null; + public ServerConnectionCallback cb_conn; + public ServerAuthenticationCallback cb_auth; - /* Settings for the next key exchange */ - public CryptoWishList next_cryptoWishList = CryptoWishList.forServer(); - public KeyPair next_dsa_key; - public KeyPair next_ec_key; - public KeyPair next_rsa_key; + /* Settings for the next key exchange */ + public CryptoWishList next_cryptoWishList = CryptoWishList.forServer(); + public KeyPair next_dsa_key; + public KeyPair next_ec_key; + public KeyPair next_rsa_key; - public Socket s; + public Socket s; - public ClientServerHello csh; - public ServerTransportManager tm; - public ServerAuthenticationManager am; - public ChannelManager cm; + public ClientServerHello csh; + public ServerTransportManager tm; + public ServerAuthenticationManager am; + public ChannelManager cm; - public boolean flag_auth_serviceRequested = false; - public boolean flag_auth_completed = false; + public boolean flag_auth_serviceRequested = false; + public boolean flag_auth_completed = false; - public ServerConnectionState(ServerConnection conn) - { - this.conn = conn; - } + public ServerConnectionState(ServerConnection conn) { + this.conn = conn; + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/sftp/AttrTextHints.java --- a/src/ch/ethz/ssh2/sftp/AttrTextHints.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/sftp/AttrTextHints.java Wed Jul 30 14:16:58 2014 -0700 @@ -5,37 +5,36 @@ package ch.ethz.ssh2.sftp; /** - * + * * Values for the 'text-hint' field in the SFTP ATTRS data type. * * @author Christian Plattner * @version 2.50, 03/15/10 * */ -public class AttrTextHints -{ - /** - * The server knows the file is a text file, and should be opened - * using the SSH_FXF_ACCESS_TEXT_MODE flag. - */ - public static final int SSH_FILEXFER_ATTR_KNOWN_TEXT = 0x00; +public class AttrTextHints { + /** + * The server knows the file is a text file, and should be opened + * using the SSH_FXF_ACCESS_TEXT_MODE flag. + */ + public static final int SSH_FILEXFER_ATTR_KNOWN_TEXT = 0x00; - /** - * The server has applied a heuristic or other mechanism and - * believes that the file should be opened with the - * SSH_FXF_ACCESS_TEXT_MODE flag. - */ - public static final int SSH_FILEXFER_ATTR_GUESSED_TEXT = 0x01; + /** + * The server has applied a heuristic or other mechanism and + * believes that the file should be opened with the + * SSH_FXF_ACCESS_TEXT_MODE flag. + */ + public static final int SSH_FILEXFER_ATTR_GUESSED_TEXT = 0x01; - /** - * The server knows the file has binary content. - */ - public static final int SSH_FILEXFER_ATTR_KNOWN_BINARY = 0x02; + /** + * The server knows the file has binary content. + */ + public static final int SSH_FILEXFER_ATTR_KNOWN_BINARY = 0x02; - /** - * The server has applied a heuristic or other mechanism and - * believes has binary content, and should not be opened with the - * SSH_FXF_ACCESS_TEXT_MODE flag. - */ - public static final int SSH_FILEXFER_ATTR_GUESSED_BINARY = 0x03; + /** + * The server has applied a heuristic or other mechanism and + * believes has binary content, and should not be opened with the + * SSH_FXF_ACCESS_TEXT_MODE flag. + */ + public static final int SSH_FILEXFER_ATTR_GUESSED_BINARY = 0x03; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/sftp/ErrorCodes.java --- a/src/ch/ethz/ssh2/sftp/ErrorCodes.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/sftp/ErrorCodes.java Wed Jul 30 14:16:58 2014 -0700 @@ -53,56 +53,79 @@ private static final String[][] messages = { - {"SSH_FX_OK", "Indicates successful completion of the operation."}, - {"SSH_FX_EOF", - "An attempt to read past the end-of-file was made; or, there are no more directory entries to return."}, - {"SSH_FX_NO_SUCH_FILE", "A reference was made to a file which does not exist."}, - {"SSH_FX_PERMISSION_DENIED", "The user does not have sufficient permissions to perform the operation."}, - {"SSH_FX_FAILURE", "An error occurred, but no specific error code exists to describe the failure."}, - {"SSH_FX_BAD_MESSAGE", "A badly formatted packet or other SFTP protocol incompatibility was detected."}, - {"SSH_FX_NO_CONNECTION", "There is no connection to the server."}, - {"SSH_FX_CONNECTION_LOST", "The connection to the server was lost."}, - {"SSH_FX_OP_UNSUPPORTED", - "An attempted operation could not be completed by the server because the server does not support the operation."}, - {"SSH_FX_INVALID_HANDLE", "The handle value was invalid."}, - {"SSH_FX_NO_SUCH_PATH", "The file path does not exist or is invalid."}, - {"SSH_FX_FILE_ALREADY_EXISTS", "The file already exists."}, - {"SSH_FX_WRITE_PROTECT", "The file is on read-only media, or the media is write protected."}, - {"SSH_FX_NO_MEDIA", - "The requested operation cannot be completed because there is no media available in the drive."}, - {"SSH_FX_NO_SPACE_ON_FILESYSTEM", - "The requested operation cannot be completed because there is insufficient free space on the filesystem."}, - {"SSH_FX_QUOTA_EXCEEDED", - "The operation cannot be completed because it would exceed the user's storage quota."}, - { - "SSH_FX_UNKNOWN_PRINCIPAL", - "A principal referenced by the request (either the 'owner', 'group', or 'who' field of an ACL), was unknown. The error specific data contains the problematic names."}, - {"SSH_FX_LOCK_CONFLICT", "The file could not be opened because it is locked by another process."}, - {"SSH_FX_DIR_NOT_EMPTY", "The directory is not empty."}, - {"SSH_FX_NOT_A_DIRECTORY", "The specified file is not a directory."}, - {"SSH_FX_INVALID_FILENAME", "The filename is not valid."}, - {"SSH_FX_LINK_LOOP", - "Too many symbolic links encountered or, an SSH_FXF_NOFOLLOW open encountered a symbolic link as the final component."}, - {"SSH_FX_CANNOT_DELETE", - "The file cannot be deleted. One possible reason is that the advisory READONLY attribute-bit is set."}, - {"SSH_FX_INVALID_PARAMETER", - "One of the parameters was out of range, or the parameters specified cannot be used together."}, - {"SSH_FX_FILE_IS_A_DIRECTORY", - "The specified file was a directory in a context where a directory cannot be used."}, - {"SSH_FX_BYTE_RANGE_LOCK_CONFLICT", - " A read or write operation failed because another process's mandatory byte-range lock overlaps with the request."}, - {"SSH_FX_BYTE_RANGE_LOCK_REFUSED", "A request for a byte range lock was refused."}, - {"SSH_FX_DELETE_PENDING", "An operation was attempted on a file for which a delete operation is pending."}, - {"SSH_FX_FILE_CORRUPT", "The file is corrupt; an filesystem integrity check should be run."}, - {"SSH_FX_OWNER_INVALID", "The principal specified can not be assigned as an owner of a file."}, - {"SSH_FX_GROUP_INVALID", "The principal specified can not be assigned as the primary group of a file."}, - {"SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK", - "The requested operation could not be completed because the specifed byte range lock has not been granted."}, + {"SSH_FX_OK", "Indicates successful completion of the operation."}, + { + "SSH_FX_EOF", + "An attempt to read past the end-of-file was made; or, there are no more directory entries to return." + }, + {"SSH_FX_NO_SUCH_FILE", "A reference was made to a file which does not exist."}, + {"SSH_FX_PERMISSION_DENIED", "The user does not have sufficient permissions to perform the operation."}, + {"SSH_FX_FAILURE", "An error occurred, but no specific error code exists to describe the failure."}, + {"SSH_FX_BAD_MESSAGE", "A badly formatted packet or other SFTP protocol incompatibility was detected."}, + {"SSH_FX_NO_CONNECTION", "There is no connection to the server."}, + {"SSH_FX_CONNECTION_LOST", "The connection to the server was lost."}, + { + "SSH_FX_OP_UNSUPPORTED", + "An attempted operation could not be completed by the server because the server does not support the operation." + }, + {"SSH_FX_INVALID_HANDLE", "The handle value was invalid."}, + {"SSH_FX_NO_SUCH_PATH", "The file path does not exist or is invalid."}, + {"SSH_FX_FILE_ALREADY_EXISTS", "The file already exists."}, + {"SSH_FX_WRITE_PROTECT", "The file is on read-only media, or the media is write protected."}, + { + "SSH_FX_NO_MEDIA", + "The requested operation cannot be completed because there is no media available in the drive." + }, + { + "SSH_FX_NO_SPACE_ON_FILESYSTEM", + "The requested operation cannot be completed because there is insufficient free space on the filesystem." + }, + { + "SSH_FX_QUOTA_EXCEEDED", + "The operation cannot be completed because it would exceed the user's storage quota." + }, + { + "SSH_FX_UNKNOWN_PRINCIPAL", + "A principal referenced by the request (either the 'owner', 'group', or 'who' field of an ACL), was unknown. The error specific data contains the problematic names." + }, + {"SSH_FX_LOCK_CONFLICT", "The file could not be opened because it is locked by another process."}, + {"SSH_FX_DIR_NOT_EMPTY", "The directory is not empty."}, + {"SSH_FX_NOT_A_DIRECTORY", "The specified file is not a directory."}, + {"SSH_FX_INVALID_FILENAME", "The filename is not valid."}, + { + "SSH_FX_LINK_LOOP", + "Too many symbolic links encountered or, an SSH_FXF_NOFOLLOW open encountered a symbolic link as the final component." + }, + { + "SSH_FX_CANNOT_DELETE", + "The file cannot be deleted. One possible reason is that the advisory READONLY attribute-bit is set." + }, + { + "SSH_FX_INVALID_PARAMETER", + "One of the parameters was out of range, or the parameters specified cannot be used together." + }, + { + "SSH_FX_FILE_IS_A_DIRECTORY", + "The specified file was a directory in a context where a directory cannot be used." + }, + { + "SSH_FX_BYTE_RANGE_LOCK_CONFLICT", + " A read or write operation failed because another process's mandatory byte-range lock overlaps with the request." + }, + {"SSH_FX_BYTE_RANGE_LOCK_REFUSED", "A request for a byte range lock was refused."}, + {"SSH_FX_DELETE_PENDING", "An operation was attempted on a file for which a delete operation is pending."}, + {"SSH_FX_FILE_CORRUPT", "The file is corrupt; an filesystem integrity check should be run."}, + {"SSH_FX_OWNER_INVALID", "The principal specified can not be assigned as an owner of a file."}, + {"SSH_FX_GROUP_INVALID", "The principal specified can not be assigned as the primary group of a file."}, + { + "SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK", + "The requested operation could not be completed because the specifed byte range lock has not been granted." + }, }; public static final String[] getDescription(int errorCode) { - if((errorCode < 0) || (errorCode >= messages.length)) { + if ((errorCode < 0) || (errorCode >= messages.length)) { return null; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/sftp/Packet.java --- a/src/ch/ethz/ssh2/sftp/Packet.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/sftp/Packet.java Wed Jul 30 14:16:58 2014 -0700 @@ -51,62 +51,89 @@ public static final int SSH_FXP_EXTENDED_REPLY = 201; public static String forName(int type) { - switch(type) { + switch (type) { case SSH_FXP_INIT: return "SSH_FXP_INIT"; + case SSH_FXP_VERSION: return "SSH_FXP_VERSION"; + case SSH_FXP_OPEN: return "SSH_FXP_OPEN"; + case SSH_FXP_CLOSE: return "SSH_FXP_CLOSE"; + case SSH_FXP_READ: return "SSH_FXP_READ"; + case SSH_FXP_WRITE: return "SSH_FXP_WRITE"; + case SSH_FXP_LSTAT: return "SSH_FXP_LSTAT"; + case SSH_FXP_FSTAT: return "SSH_FXP_FSTAT"; + case SSH_FXP_SETSTAT: return "SSH_FXP_SETSTAT"; + case SSH_FXP_FSETSTAT: return "SSH_FXP_FSETSTAT"; + case SSH_FXP_OPENDIR: return "SSH_FXP_OPENDIR"; + case SSH_FXP_READDIR: return "SSH_FXP_READDIR"; + case SSH_FXP_REMOVE: return "SSH_FXP_REMOVE"; + case SSH_FXP_MKDIR: return "SSH_FXP_MKDIR"; + case SSH_FXP_RMDIR: return "SSH_FXP_RMDIR"; + case SSH_FXP_REALPATH: return "SSH_FXP_REALPATH"; + case SSH_FXP_STAT: return "SSH_FXP_STAT"; + case SSH_FXP_RENAME: return "SSH_FXP_RENAME"; + case SSH_FXP_READLINK: return "SSH_FXP_READLINK"; + case SSH_FXP_SYMLINK: return "SSH_FXP_SYMLINK"; + case SSH_FXP_STATUS: return "SSH_FXP_STATUS"; + case SSH_FXP_HANDLE: return "SSH_FXP_HANDLE"; + case SSH_FXP_DATA: return "SSH_FXP_DATA"; + case SSH_FXP_NAME: return "SSH_FXP_NAME"; + case SSH_FXP_ATTRS: return "SSH_FXP_ATTRS"; + case SSH_FXP_EXTENDED: return "SSH_FXP_EXTENDED"; + case SSH_FXP_EXTENDED_REPLY: return "SSH_FXP_EXTENDED_REPLY"; } + return null; } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/transport/ClientKexManager.java --- a/src/ch/ethz/ssh2/transport/ClientKexManager.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/transport/ClientKexManager.java Wed Jul 30 14:16:58 2014 -0700 @@ -65,18 +65,14 @@ if (kxs.np.server_host_key_algo.equals("ssh-rsa")) { byte[] rs = RSASHA1Verify.decodeSSHRSASignature(sig); RSAPublicKey rpk = RSASHA1Verify.decodeSSHRSAPublicKey(hostkey); - log.debug("Verifying ssh-rsa signature"); - return RSASHA1Verify.verifySignature(kxs.H, rs, rpk); } if (kxs.np.server_host_key_algo.equals("ssh-dss")) { byte[] ds = DSASHA1Verify.decodeSSHDSASignature(sig); DSAPublicKey dpk = DSASHA1Verify.decodeSSHDSAPublicKey(hostkey); - log.debug("Verifying ssh-dss signature"); - return DSASHA1Verify.verifySignature(kxs.H, ds, dpk); } @@ -84,7 +80,7 @@ } public void handleFailure(final IOException failure) { - synchronized(accessLock) { + synchronized (accessLock) { connectionClosed = true; accessLock.notifyAll(); } @@ -93,25 +89,25 @@ public synchronized void handleMessage(byte[] msg) throws IOException { PacketKexInit kip; - if((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) { + if ((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) { throw new PacketTypeException(msg[0]); } - if(ignore_next_kex_packet) { + if (ignore_next_kex_packet) { ignore_next_kex_packet = false; return; } - if(msg[0] == Packets.SSH_MSG_KEXINIT) { - if((kxs != null) && (kxs.state != 0)) { + if (msg[0] == Packets.SSH_MSG_KEXINIT) { + if ((kxs != null) && (kxs.state != 0)) { throw new PacketTypeException(msg[0]); } - if(kxs == null) { + if (kxs == null) { /* * Ah, OK, peer wants to do KEX. Let's be nice and play - * together. - */ + * together. + */ kxs = new KexState(); kxs.dhgexParameters = nextKEXdhgexParameters; kip = new PacketKexInit(nextKEXcryptoWishList, rnd); @@ -121,33 +117,32 @@ kip = new PacketKexInit(msg); kxs.remoteKEX = kip; - kxs.np = mergeKexParameters(kxs.localKEX.getKexParameters(), kxs.remoteKEX.getKexParameters()); - if(kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) { + if (kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) { // Guess was wrong, we need to ignore the next kex packet. ignore_next_kex_packet = true; } - if(kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha1")) { - if(kxs.dhgexParameters.getMin_group_len() == 0) { + if (kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha1")) { + if (kxs.dhgexParameters.getMin_group_len() == 0) { PacketKexDhGexRequestOld dhgexreq = new PacketKexDhGexRequestOld(kxs.dhgexParameters); tm.sendKexMessage(dhgexreq.getPayload()); - } else { PacketKexDhGexRequest dhgexreq = new PacketKexDhGexRequest(kxs.dhgexParameters); tm.sendKexMessage(dhgexreq.getPayload()); } + kxs.state = 1; return; } - if(kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") + if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") || kxs.np.kex_algo.equals("diffie-hellman-group14-sha1")) { kxs.dhx = new DhExchange(); - if(kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")) { + if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")) { kxs.dhx.clientInit(1, rnd); } else { @@ -163,8 +158,8 @@ throw new IllegalStateException("Unkown KEX method!"); } - if(msg[0] == Packets.SSH_MSG_NEWKEYS) { - if(km == null) { + if (msg[0] == Packets.SSH_MSG_NEWKEYS) { + if (km == null) { throw new IOException("Peer sent SSH_MSG_NEWKEYS, but I have no key material ready!"); } @@ -174,28 +169,25 @@ try { cbc = BlockCipherFactory.createCipher(kxs.np.enc_algo_server_to_client, false, - km.enc_key_server_to_client, km.initial_iv_server_to_client); + km.enc_key_server_to_client, km.initial_iv_server_to_client); try { mac = new MAC(kxs.np.mac_algo_server_to_client, km.integrity_key_server_to_client); } - catch(DigestException e) { + catch (DigestException e) { throw new IOException(e); } comp = CompressionFactory.createCompressor(kxs.np.comp_algo_server_to_client); } - catch(IllegalArgumentException e) { + catch (IllegalArgumentException e) { throw new IOException(e.getMessage()); } tm.changeRecvCipher(cbc, mac); tm.changeRecvCompression(comp); - ConnectionInfo sci = new ConnectionInfo(); - kexCount++; - sci.keyExchangeAlgorithm = kxs.np.kex_algo; sci.keyExchangeCounter = kexCount; sci.clientToServerCryptoAlgorithm = kxs.np.enc_algo_client_to_server; @@ -205,7 +197,7 @@ sci.serverHostKeyAlgorithm = kxs.np.server_host_key_algo; sci.serverHostKey = kxs.remote_hostkey; - synchronized(accessLock) { + synchronized (accessLock) { lastConnInfo = sci; accessLock.notifyAll(); } @@ -214,12 +206,12 @@ return; } - if((kxs == null) || (kxs.state == 0)) { + if ((kxs == null) || (kxs.state == 0)) { throw new IOException("Unexpected Kex submessage!"); } - if(kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha1")) { - if(kxs.state == 1) { + if (kxs.np.kex_algo.equals("diffie-hellman-group-exchange-sha1")) { + if (kxs.state == 1) { PacketKexDhGexGroup dhgexgrp = new PacketKexDhGexGroup(msg); kxs.dhgx = new DhGroupExchange(dhgexgrp.getP(), dhgexgrp.getG()); kxs.dhgx.init(rnd); @@ -229,20 +221,19 @@ return; } - if(kxs.state == 2) { + if (kxs.state == 2) { PacketKexDhGexReply dhgexrpl = new PacketKexDhGexReply(msg); - kxs.remote_hostkey = dhgexrpl.getHostKey(); - if(verifier != null) { + if (verifier != null) { try { - if(!verifier.verifyServerHostKey(hostname, port, kxs.np.server_host_key_algo, kxs.remote_hostkey)) { + if (!verifier.verifyServerHostKey(hostname, port, kxs.np.server_host_key_algo, kxs.remote_hostkey)) { throw new IOException("The server host key was not accepted by the verifier callback"); } } - catch(Exception e) { + catch (Exception e) { throw new IOException( - "The server host key was not accepted by the verifier callback.", e); + "The server host key was not accepted by the verifier callback.", e); } } @@ -250,15 +241,17 @@ try { kxs.H = kxs.dhgx.calculateH(csh.getClientString(), csh.getServerString(), - kxs.localKEX.getPayload(), kxs.remoteKEX.getPayload(), dhgexrpl.getHostKey(), - kxs.dhgexParameters); + kxs.localKEX.getPayload(), kxs.remoteKEX.getPayload(), dhgexrpl.getHostKey(), + kxs.dhgexParameters); } - catch(IllegalArgumentException e) { + catch (IllegalArgumentException e) { throw new IOException("KEX error.", e); } - if(!verifySignature(dhgexrpl.getSignature(), kxs.remote_hostkey)) { + + if (!verifySignature(dhgexrpl.getSignature(), kxs.remote_hostkey)) { throw new IOException("Invalid remote host key signature"); } + kxs.K = kxs.dhgx.getK(); finishKex(true); kxs.state = -1; @@ -268,41 +261,44 @@ throw new IllegalStateException("Illegal State in KEX Exchange!"); } - if(kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") + if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") || kxs.np.kex_algo.equals("diffie-hellman-group14-sha1")) { - if(kxs.state == 1) { - + if (kxs.state == 1) { PacketKexDHReply dhr = new PacketKexDHReply(msg); - kxs.remote_hostkey = dhr.getHostKey(); - if(verifier != null) { + if (verifier != null) { try { - if(!verifier.verifyServerHostKey(hostname, port, kxs.np.server_host_key_algo, kxs.remote_hostkey)) { + if (!verifier.verifyServerHostKey(hostname, port, kxs.np.server_host_key_algo, kxs.remote_hostkey)) { throw new IOException("The server host key was not accepted by the verifier callback"); } } - catch(Exception e) { + catch (Exception e) { throw new IOException("The server host key was not accepted by the verifier callback", e); } } + kxs.dhx.setF(dhr.getF()); + try { kxs.H = kxs.dhx.calculateH(csh.getClientString(), csh.getServerString(), kxs.localKEX.getPayload(), - kxs.remoteKEX.getPayload(), dhr.getHostKey()); + kxs.remoteKEX.getPayload(), dhr.getHostKey()); } - catch(IllegalArgumentException e) { + catch (IllegalArgumentException e) { throw new IOException("KEX error.", e); } - if(!verifySignature(dhr.getSignature(), kxs.remote_hostkey)) { + + if (!verifySignature(dhr.getSignature(), kxs.remote_hostkey)) { throw new IOException("Invalid remote host key signature"); } + kxs.K = kxs.dhx.getK(); finishKex(true); kxs.state = -1; return; } } + throw new IllegalStateException(String.format("Unknown KEX method %s", kxs.np.kex_algo)); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/transport/ClientServerHello.java --- a/src/ch/ethz/ssh2/transport/ClientServerHello.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/transport/ClientServerHello.java Wed Jul 30 14:16:58 2014 -0700 @@ -27,35 +27,37 @@ } public static ClientServerHello clientHello(String softwareversion, InputStream bi, OutputStream bo) - throws IOException { + throws IOException { return exchange(softwareversion, bi, bo, true); } public static ClientServerHello serverHello(String softwareversion, InputStream bi, OutputStream bo) - throws IOException { + throws IOException { return exchange(softwareversion, bi, bo, false); } private static ClientServerHello exchange(String softwareversion, InputStream bi, OutputStream bo, boolean clientMode) - throws IOException { + throws IOException { String localIdentifier = String.format("SSH-2.0-%s", softwareversion); - bo.write(StringEncoder.GetBytes(String.format("%s\r\n", localIdentifier))); bo.flush(); - // Expect SSH-protoversion-softwareversion SP comments CR LF String remoteIdentifier = new LineNumberReader(new InputStreamReader(bi)).readLine(); - if(null == remoteIdentifier) { + + if (null == remoteIdentifier) { throw new IOException("Premature connection close"); } - if(!remoteIdentifier.startsWith("SSH-")) { + + if (!remoteIdentifier.startsWith("SSH-")) { throw new IOException(String.format("Malformed SSH identification %s", remoteIdentifier)); } - if(!remoteIdentifier.startsWith("SSH-1.99-") + + if (!remoteIdentifier.startsWith("SSH-1.99-") && !remoteIdentifier.startsWith("SSH-2.0-")) { throw new IOException(String.format("Incompatible remote protocol version %s", remoteIdentifier)); } - if(clientMode) { + + if (clientMode) { return new ClientServerHello(localIdentifier, remoteIdentifier); } else { diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/transport/ClientTransportManager.java --- a/src/ch/ethz/ssh2/transport/ClientTransportManager.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/transport/ClientTransportManager.java Wed Jul 30 14:16:58 2014 -0700 @@ -31,29 +31,23 @@ public void connect(String hostname, int port, String softwareversion, CryptoWishList cwl, ServerHostKeyVerifier verifier, DHGexParameters dhgex, int connectTimeout, SecureRandom rnd) - throws IOException { + throws IOException { // Establish the TCP connection to the SSH-2 server this.connect(hostname, port, connectTimeout); - // Parse the server line and say hello - important: this information is later needed for the // key exchange (to stop man-in-the-middle attacks) - that is why we wrap it into an object // for later use. - ClientServerHello csh = ClientServerHello.clientHello(softwareversion, sock.getInputStream(), - sock.getOutputStream()); - + sock.getOutputStream()); TransportConnection tc = new TransportConnection(sock.getInputStream(), sock.getOutputStream(), rnd); - KexManager km = new ClientKexManager(this, csh, cwl, hostname, port, verifier, rnd); super.init(tc, km); - km.initiateKEX(cwl, dhgex, null, null, null); - this.startReceiver(); } protected void connect(String hostname, int port, int connectTimeout) - throws IOException { + throws IOException { sock.connect(new InetSocketAddress(hostname, port), connectTimeout); } } \ No newline at end of file diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/transport/HTTPProxyClientTransportManager.java --- a/src/ch/ethz/ssh2/transport/HTTPProxyClientTransportManager.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/transport/HTTPProxyClientTransportManager.java Wed Jul 30 14:16:58 2014 -0700 @@ -34,19 +34,16 @@ @Override protected void connect(final String hostname, final int port, final int connectTimeout) throws IOException { - sock.connect(new InetSocketAddress(pd.proxyHost, pd.proxyPort), connectTimeout); - // Tell the proxy where we actually want to connect to StringBuilder sb = new StringBuilder(); - sb.append("CONNECT "); sb.append(hostname); sb.append(':'); sb.append(port); sb.append(" HTTP/1.0\r\n"); - if((pd.proxyUser != null) && (pd.proxyPass != null)) { + if ((pd.proxyUser != null) && (pd.proxyPass != null)) { String credentials = pd.proxyUser + ":" + pd.proxyPass; char[] encoded = Base64.encode(StringEncoder.GetBytes(credentials)); sb.append("Proxy-Authorization: Basic "); @@ -54,9 +51,9 @@ sb.append("\r\n"); } - if(pd.requestHeaderLines != null) { - for(int i = 0; i < pd.requestHeaderLines.length; i++) { - if(pd.requestHeaderLines[i] != null) { + if (pd.requestHeaderLines != null) { + for (int i = 0; i < pd.requestHeaderLines.length; i++) { + if (pd.requestHeaderLines[i] != null) { sb.append(pd.requestHeaderLines[i]); sb.append("\r\n"); } @@ -64,26 +61,21 @@ } sb.append("\r\n"); - OutputStream out = sock.getOutputStream(); - out.write(StringEncoder.GetBytes(sb.toString())); out.flush(); - // Parse the HTTP response - InputStream in = sock.getInputStream(); - final LineNumberReader reader = new LineNumberReader(new InputStreamReader(in)); String httpReponse = reader.readLine(); - if(!httpReponse.startsWith("HTTP/")) { + if (!httpReponse.startsWith("HTTP/")) { throw new IOException("The proxy did not send back a valid HTTP response."); } // "HTTP/1.X XYZ X" => 14 characters minimum - if((httpReponse.length() < 14) || (httpReponse.charAt(8) != ' ') || (httpReponse.charAt(12) != ' ')) { + if ((httpReponse.length() < 14) || (httpReponse.charAt(8) != ' ') || (httpReponse.charAt(12) != ' ')) { throw new IOException("The proxy did not send back a valid HTTP response."); } @@ -92,19 +84,19 @@ try { errorCode = Integer.parseInt(httpReponse.substring(9, 12)); } - catch(NumberFormatException ignore) { + catch (NumberFormatException ignore) { throw new IOException("The proxy did not send back a valid HTTP response."); } - if((errorCode < 0) || (errorCode > 999)) { + if ((errorCode < 0) || (errorCode > 999)) { throw new IOException("The proxy did not send back a valid HTTP response."); } - if(errorCode != 200) { + if (errorCode != 200) { throw new HTTPProxyException(httpReponse.substring(13), errorCode); } - while(reader.readLine() != null) { + while (reader.readLine() != null) { // Read until empty line } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/transport/KexManager.java --- a/src/ch/ethz/ssh2/transport/KexManager.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/transport/KexManager.java Wed Jul 30 14:16:58 2014 -0700 @@ -91,18 +91,20 @@ } public ConnectionInfo getOrWaitForConnectionInfo(int minKexCount) throws IOException { - synchronized(accessLock) { - while(true) { - if((lastConnInfo != null) && (lastConnInfo.keyExchangeCounter >= minKexCount)) { + synchronized (accessLock) { + while (true) { + if ((lastConnInfo != null) && (lastConnInfo.keyExchangeCounter >= minKexCount)) { return lastConnInfo; } - if(connectionClosed) { + + if (connectionClosed) { throw tm.getReasonClosedCause(); } + try { accessLock.wait(); } - catch(InterruptedException e) { + catch (InterruptedException e) { throw new InterruptedIOException(e.getMessage()); } } @@ -110,110 +112,105 @@ } private String getFirstMatch(String[] client, String[] server) throws NegotiateException { - if(client == null || server == null) { + if (client == null || server == null) { throw new IllegalArgumentException(); } - for(String c : client) { - for(String s : server) { - if(c.equals(s)) { + + for (String c : client) { + for (String s : server) { + if (c.equals(s)) { return c; } } } + throw new NegotiateException(String.format("Negotiation failed for %s", Arrays.toString(server))); } private boolean compareFirstOfNameList(String[] a, String[] b) { - if(a == null || b == null) { + if (a == null || b == null) { throw new IllegalArgumentException(); } - if((a.length == 0) && (b.length == 0)) { + + if ((a.length == 0) && (b.length == 0)) { return true; } - if((a.length == 0) || (b.length == 0)) { + + if ((a.length == 0) || (b.length == 0)) { return false; } + return (a[0].equals(b[0])); } private boolean isGuessOK(KexParameters cpar, KexParameters spar) { - if(cpar == null || spar == null) { + if (cpar == null || spar == null) { throw new IllegalArgumentException(); } - if(!compareFirstOfNameList(cpar.kex_algorithms, spar.kex_algorithms)) { - return false; - } - if(!compareFirstOfNameList(cpar.server_host_key_algorithms, spar.server_host_key_algorithms)) { + + if (!compareFirstOfNameList(cpar.kex_algorithms, spar.kex_algorithms)) { return false; } - /* + if (!compareFirstOfNameList(cpar.server_host_key_algorithms, spar.server_host_key_algorithms)) { + return false; + } + + /* * We do NOT check here if the other algorithms can be agreed on, this - * is just a check if kex_algorithms and server_host_key_algorithms were - * guessed right! - */ - + * is just a check if kex_algorithms and server_host_key_algorithms were + * guessed right! + */ return true; } protected NegotiatedParameters mergeKexParameters(KexParameters client, KexParameters server) - throws NegotiateException { + throws NegotiateException { NegotiatedParameters np = new NegotiatedParameters(); - np.kex_algo = getFirstMatch(client.kex_algorithms, server.kex_algorithms); - log.info("kex_algo=" + np.kex_algo); - np.server_host_key_algo = getFirstMatch(client.server_host_key_algorithms, - server.server_host_key_algorithms); - + server.server_host_key_algorithms); log.info("server_host_key_algo=" + np.server_host_key_algo); - np.enc_algo_client_to_server = getFirstMatch(client.encryption_algorithms_client_to_server, - server.encryption_algorithms_client_to_server); + server.encryption_algorithms_client_to_server); np.enc_algo_server_to_client = getFirstMatch(client.encryption_algorithms_server_to_client, - server.encryption_algorithms_server_to_client); - + server.encryption_algorithms_server_to_client); log.info("enc_algo_client_to_server=" + np.enc_algo_client_to_server); log.info("enc_algo_server_to_client=" + np.enc_algo_server_to_client); - np.mac_algo_client_to_server = getFirstMatch(client.mac_algorithms_client_to_server, - server.mac_algorithms_client_to_server); + server.mac_algorithms_client_to_server); np.mac_algo_server_to_client = getFirstMatch(client.mac_algorithms_server_to_client, - server.mac_algorithms_server_to_client); - + server.mac_algorithms_server_to_client); log.info("mac_algo_client_to_server=" + np.mac_algo_client_to_server); log.info("mac_algo_server_to_client=" + np.mac_algo_server_to_client); - np.comp_algo_client_to_server = getFirstMatch(client.compression_algorithms_client_to_server, - server.compression_algorithms_client_to_server); + server.compression_algorithms_client_to_server); np.comp_algo_server_to_client = getFirstMatch(client.compression_algorithms_server_to_client, - server.compression_algorithms_server_to_client); - + server.compression_algorithms_server_to_client); log.info("comp_algo_client_to_server=" + np.comp_algo_client_to_server); log.info("comp_algo_server_to_client=" + np.comp_algo_server_to_client); - np.lang_client_to_server = getFirstMatch(client.languages_client_to_server, - server.languages_client_to_server); + server.languages_client_to_server); + np.lang_server_to_client = getFirstMatch(client.languages_server_to_client, + server.languages_server_to_client); - np.lang_server_to_client = getFirstMatch(client.languages_server_to_client, - server.languages_server_to_client); - - if(isGuessOK(client, server)) { + if (isGuessOK(client, server)) { np.guessOK = true; } + return np; } public synchronized void initiateKEX(CryptoWishList cwl, DHGexParameters dhgex, KeyPair dsa, KeyPair rsa, KeyPair ec) - throws IOException { + throws IOException { nextKEXcryptoWishList = cwl; nextKEXdhgexParameters = dhgex; nextKEXdsakey = dsa; nextKEXrsakey = rsa; nextKEXeckey = ec; - if(kxs == null) { + if (kxs == null) { kxs = new KexState(); kxs.local_dsa_key = dsa; kxs.local_rsa_key = rsa; @@ -229,53 +226,49 @@ int mac_cs_key_len = MAC.getKeyLen(kxs.np.mac_algo_client_to_server); int enc_cs_key_len = BlockCipherFactory.getKeySize(kxs.np.enc_algo_client_to_server); int enc_cs_block_len = BlockCipherFactory.getBlockSize(kxs.np.enc_algo_client_to_server); - int mac_sc_key_len = MAC.getKeyLen(kxs.np.mac_algo_server_to_client); int enc_sc_key_len = BlockCipherFactory.getKeySize(kxs.np.enc_algo_server_to_client); int enc_sc_block_len = BlockCipherFactory.getBlockSize(kxs.np.enc_algo_server_to_client); - km = KeyMaterial.create("SHA1", kxs.H, kxs.K, sessionId, enc_cs_key_len, enc_cs_block_len, mac_cs_key_len, - enc_sc_key_len, enc_sc_block_len, mac_sc_key_len); + enc_sc_key_len, enc_sc_block_len, mac_sc_key_len); } - catch(IllegalArgumentException e) { + catch (IllegalArgumentException e) { return false; } + return true; } protected void finishKex(boolean clientMode) throws IOException { - if(sessionId == null) { + if (sessionId == null) { sessionId = kxs.H; } establishKeyMaterial(); - - /* Tell the other side that we start using the new material */ - + /* Tell the other side that we start using the new material */ PacketNewKeys ign = new PacketNewKeys(); tm.sendKexMessage(ign.getPayload()); - BlockCipher cbc; MAC mac; Compressor comp; try { cbc = BlockCipherFactory.createCipher(clientMode ? kxs.np.enc_algo_client_to_server - : kxs.np.enc_algo_server_to_client, true, clientMode ? km.enc_key_client_to_server - : km.enc_key_server_to_client, clientMode ? km.initial_iv_client_to_server - : km.initial_iv_server_to_client); + : kxs.np.enc_algo_server_to_client, true, clientMode ? km.enc_key_client_to_server + : km.enc_key_server_to_client, clientMode ? km.initial_iv_client_to_server + : km.initial_iv_server_to_client); try { mac = new MAC(clientMode ? kxs.np.mac_algo_client_to_server : kxs.np.mac_algo_server_to_client, clientMode - ? km.integrity_key_client_to_server : km.integrity_key_server_to_client); + ? km.integrity_key_client_to_server : km.integrity_key_server_to_client); } - catch(DigestException e) { + catch (DigestException e) { throw new IOException(e); } comp = CompressionFactory.createCompressor(kxs.np.comp_algo_client_to_server); } - catch(IllegalArgumentException f) { + catch (IllegalArgumentException f) { throw new IOException(String.format("Fatal error initializing ciphers. %s", f.getMessage())); } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/transport/KexParameters.java --- a/src/ch/ethz/ssh2/transport/KexParameters.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/transport/KexParameters.java Wed Jul 30 14:16:58 2014 -0700 @@ -10,21 +10,20 @@ * @author Christian Plattner * @version $Id: KexParameters.java 159 2014-05-01 14:12:34Z dkocher@sudo.ch $ */ -public class KexParameters -{ - public byte[] cookie; - public String[] kex_algorithms; - public String[] server_host_key_algorithms; - public String[] encryption_algorithms_client_to_server; - public String[] encryption_algorithms_server_to_client; - public String[] mac_algorithms_client_to_server; - public String[] mac_algorithms_server_to_client; - public String[] compression_algorithms_client_to_server; - public String[] compression_algorithms_server_to_client; - public String[] languages_client_to_server; - public String[] languages_server_to_client; - public boolean first_kex_packet_follows; - public int reserved_field1; +public class KexParameters { + public byte[] cookie; + public String[] kex_algorithms; + public String[] server_host_key_algorithms; + public String[] encryption_algorithms_client_to_server; + public String[] encryption_algorithms_server_to_client; + public String[] mac_algorithms_client_to_server; + public String[] mac_algorithms_server_to_client; + public String[] compression_algorithms_client_to_server; + public String[] compression_algorithms_server_to_client; + public String[] languages_client_to_server; + public String[] languages_server_to_client; + public boolean first_kex_packet_follows; + public int reserved_field1; @Override public String toString() { diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/transport/KexState.java --- a/src/ch/ethz/ssh2/transport/KexState.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/transport/KexState.java Wed Jul 30 14:16:58 2014 -0700 @@ -21,23 +21,22 @@ * @author Christian Plattner * @version 2.50, 03/15/10 */ -public class KexState -{ - public PacketKexInit localKEX; - public PacketKexInit remoteKEX; - public NegotiatedParameters np; - public int state = 0; +public class KexState { + public PacketKexInit localKEX; + public PacketKexInit remoteKEX; + public NegotiatedParameters np; + public int state = 0; - public BigInteger K; - public byte[] H; + public BigInteger K; + public byte[] H; - public byte[] remote_hostkey; + public byte[] remote_hostkey; - public DhExchange dhx; - public DhGroupExchange dhgx; - public DHGexParameters dhgexParameters; + public DhExchange dhx; + public DhGroupExchange dhgx; + public DHGexParameters dhgexParameters; - public KeyPair local_dsa_key; - public KeyPair local_rsa_key; - public KeyPair local_ec_key; + public KeyPair local_dsa_key; + public KeyPair local_rsa_key; + public KeyPair local_ec_key; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/transport/NegotiatedParameters.java --- a/src/ch/ethz/ssh2/transport/NegotiatedParameters.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/transport/NegotiatedParameters.java Wed Jul 30 14:16:58 2014 -0700 @@ -8,19 +8,18 @@ * @author Christian Plattner * @version $Id: NegotiatedParameters.java 159 2014-05-01 14:12:34Z dkocher@sudo.ch $ */ -public class NegotiatedParameters -{ - public boolean guessOK; - public String kex_algo; - public String server_host_key_algo; - public String enc_algo_client_to_server; - public String enc_algo_server_to_client; - public String mac_algo_client_to_server; - public String mac_algo_server_to_client; - public String comp_algo_client_to_server; - public String comp_algo_server_to_client; - public String lang_client_to_server; - public String lang_server_to_client; +public class NegotiatedParameters { + public boolean guessOK; + public String kex_algo; + public String server_host_key_algo; + public String enc_algo_client_to_server; + public String enc_algo_server_to_client; + public String mac_algo_client_to_server; + public String mac_algo_server_to_client; + public String comp_algo_client_to_server; + public String comp_algo_server_to_client; + public String lang_client_to_server; + public String lang_server_to_client; @Override public String toString() { diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/transport/ServerKexManager.java --- a/src/ch/ethz/ssh2/transport/ServerKexManager.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/transport/ServerKexManager.java Wed Jul 30 14:16:58 2014 -0700 @@ -44,7 +44,7 @@ } public void handleFailure(final IOException failure) { - synchronized(accessLock) { + synchronized (accessLock) { connectionClosed = true; accessLock.notifyAll(); } @@ -53,25 +53,25 @@ public void handleMessage(byte[] msg) throws IOException { PacketKexInit kip; - if((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) { + if ((kxs == null) && (msg[0] != Packets.SSH_MSG_KEXINIT)) { throw new PacketTypeException(msg[0]); } - if(ignore_next_kex_packet) { + if (ignore_next_kex_packet) { ignore_next_kex_packet = false; return; } - if(msg[0] == Packets.SSH_MSG_KEXINIT) { - if((kxs != null) && (kxs.state != 0)) { + if (msg[0] == Packets.SSH_MSG_KEXINIT) { + if ((kxs != null) && (kxs.state != 0)) { throw new PacketTypeException(msg[0]); } - if(kxs == null) { + if (kxs == null) { /* * Ah, OK, peer wants to do KEX. Let's be nice and play - * together. - */ + * together. + */ kxs = new KexState(); kxs.local_dsa_key = nextKEXdsakey; kxs.local_rsa_key = nextKEXrsakey; @@ -84,19 +84,18 @@ kip = new PacketKexInit(msg); kxs.remoteKEX = kip; - kxs.np = mergeKexParameters(kxs.remoteKEX.getKexParameters(), kxs.localKEX.getKexParameters()); - if(kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) { + if (kxs.remoteKEX.isFirst_kex_packet_follows() && (kxs.np.guessOK == false)) { // Guess was wrong, we need to ignore the next kex packet. ignore_next_kex_packet = true; } - if(kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") + if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") || kxs.np.kex_algo.equals("diffie-hellman-group14-sha1")) { kxs.dhx = new DhExchange(); - if(kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")) { + if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1")) { kxs.dhx.serverInit(1, rnd); } else { @@ -110,8 +109,8 @@ throw new IllegalStateException("Unkown KEX method!"); } - if(msg[0] == Packets.SSH_MSG_NEWKEYS) { - if(km == null) { + if (msg[0] == Packets.SSH_MSG_NEWKEYS) { + if (km == null) { throw new IOException("Peer sent SSH_MSG_NEWKEYS, but I have no key material ready!"); } @@ -120,26 +119,22 @@ try { cbc = BlockCipherFactory.createCipher(kxs.np.enc_algo_client_to_server, false, - km.enc_key_client_to_server, km.initial_iv_client_to_server); + km.enc_key_client_to_server, km.initial_iv_client_to_server); try { mac = new MAC(kxs.np.mac_algo_client_to_server, km.integrity_key_client_to_server); } - catch(DigestException e) { + catch (DigestException e) { throw new IOException(e); } - } - catch(IllegalArgumentException e) { + catch (IllegalArgumentException e) { throw new IOException(e); } tm.changeRecvCipher(cbc, mac); - ConnectionInfo sci = new ConnectionInfo(); - kexCount++; - sci.keyExchangeAlgorithm = kxs.np.kex_algo; sci.keyExchangeCounter = kexCount; sci.clientToServerCryptoAlgorithm = kxs.np.enc_algo_client_to_server; @@ -149,7 +144,7 @@ sci.serverHostKeyAlgorithm = kxs.np.server_host_key_algo; sci.serverHostKey = kxs.remote_hostkey; - synchronized(accessLock) { + synchronized (accessLock) { lastConnInfo = sci; accessLock.notifyAll(); } @@ -158,41 +153,38 @@ return; } - if((kxs == null) || (kxs.state == 0)) { + if ((kxs == null) || (kxs.state == 0)) { throw new IOException("Unexpected Kex submessage!"); } - if(kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") + if (kxs.np.kex_algo.equals("diffie-hellman-group1-sha1") || kxs.np.kex_algo.equals("diffie-hellman-group14-sha1")) { - if(kxs.state == 1) { + if (kxs.state == 1) { PacketKexDHInit dhi = new PacketKexDHInit(msg); - kxs.dhx.setE(dhi.getE()); - byte[] hostKey = null; if (kxs.np.server_host_key_algo.startsWith("ecdsa-sha2-")) { hostKey = ECDSASHA2Verify.encodeSSHECDSAPublicKey((ECPublicKey)kxs.local_ec_key.getPublic()); } - if(kxs.np.server_host_key_algo.equals("ssh-rsa")) { + if (kxs.np.server_host_key_algo.equals("ssh-rsa")) { hostKey = RSASHA1Verify.encodeSSHRSAPublicKey((RSAPublicKey)kxs.local_rsa_key.getPublic()); } - if(kxs.np.server_host_key_algo.equals("ssh-dss")) { + if (kxs.np.server_host_key_algo.equals("ssh-dss")) { hostKey = DSASHA1Verify.encodeSSHDSAPublicKey((DSAPublicKey)kxs.local_dsa_key.getPublic()); } try { kxs.H = kxs.dhx.calculateH(csh.getClientString(), csh.getServerString(), - kxs.remoteKEX.getPayload(), kxs.localKEX.getPayload(), hostKey); + kxs.remoteKEX.getPayload(), kxs.localKEX.getPayload(), hostKey); } - catch(IllegalArgumentException e) { + catch (IllegalArgumentException e) { throw new IOException("KEX error.", e); } kxs.K = kxs.dhx.getK(); - byte[] signature = null; if (kxs.np.server_host_key_algo.startsWith("ecdsa-sha2-")) { @@ -213,11 +205,10 @@ PacketKexDHReply dhr = new PacketKexDHReply(hostKey, kxs.dhx.getF(), signature); tm.sendKexMessage(dhr.getPayload()); - finishKex(false); kxs.state = -1; - if(authenticationStarted == false) { + if (authenticationStarted == false) { authenticationStarted = true; state.am = new ServerAuthenticationManager(state); } @@ -225,6 +216,7 @@ return; } } + throw new IllegalStateException(String.format("Unknown KEX method %s", kxs.np.kex_algo)); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/transport/ServerTransportManager.java --- a/src/ch/ethz/ssh2/transport/ServerTransportManager.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/transport/ServerTransportManager.java Wed Jul 30 14:16:58 2014 -0700 @@ -8,35 +8,27 @@ /** * @version $Id: ServerTransportManager.java 151 2014-04-28 10:03:39Z dkocher@sudo.ch $ */ -public class ServerTransportManager extends TransportManager -{ +public class ServerTransportManager extends TransportManager { - private final Socket sock; + private final Socket sock; - public ServerTransportManager(final Socket socket) - { - super(socket); - // TCP connection is already established - this.sock = socket; - } + public ServerTransportManager(final Socket socket) { + super(socket); + // TCP connection is already established + this.sock = socket; + } - public void connect(ServerConnectionState state) throws IOException - { - /* Parse the client lin - e and say hello - important: this information is later needed for the - * key exchange (to stop man-in-the-middle attacks) - that is why we wrap it into an object - * for later use. - */ - - state.csh = ClientServerHello.serverHello(state.softwareversion, sock.getInputStream(), sock.getOutputStream()); - - TransportConnection tc = new TransportConnection(sock.getInputStream(), sock.getOutputStream(), state.generator); - KexManager km = new ServerKexManager(state); - - super.init(tc, km); - - km.initiateKEX(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); - - this.startReceiver(); - } + public void connect(ServerConnectionState state) throws IOException { + /* Parse the client lin + e and say hello - important: this information is later needed for the + * key exchange (to stop man-in-the-middle attacks) - that is why we wrap it into an object + * for later use. + */ + state.csh = ClientServerHello.serverHello(state.softwareversion, sock.getInputStream(), sock.getOutputStream()); + TransportConnection tc = new TransportConnection(sock.getInputStream(), sock.getOutputStream(), state.generator); + KexManager km = new ServerKexManager(state); + super.init(tc, km); + km.initiateKEX(state.next_cryptoWishList, null, state.next_dsa_key, state.next_rsa_key, state.next_ec_key); + this.startReceiver(); + } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/transport/TransportConnection.java --- a/src/ch/ethz/ssh2/transport/TransportConnection.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/transport/TransportConnection.java Wed Jul 30 14:16:58 2014 -0700 @@ -38,7 +38,7 @@ boolean useRandomPadding; - /* Depends on current MAC and CIPHER */ + /* Depends on current MAC and CIPHER */ MAC send_mac; @@ -64,7 +64,7 @@ byte[] send_comp_buffer; - /* won't change */ + /* won't change */ final byte[] send_padding_buffer = new byte[256]; @@ -92,13 +92,14 @@ recv_mac_buffer = (mac != null) ? new byte[mac.size()] : null; recv_mac_buffer_cmp = (mac != null) ? new byte[mac.size()] : null; recv_padd_blocksize = bc.getBlockSize(); - if(recv_padd_blocksize < 8) { + + if (recv_padd_blocksize < 8) { recv_padd_blocksize = 8; } } public void changeSendCipher(BlockCipher bc, MAC mac) { - if((bc instanceof NullCipher) == false) { + if ((bc instanceof NullCipher) == false) { /* Only use zero byte padding for the first few packets */ useRandomPadding = true; /* Once we start encrypting, there is no way back */ @@ -108,7 +109,8 @@ send_mac = mac; send_mac_buffer = (mac != null) ? new byte[mac.size()] : null; send_padd_blocksize = bc.getBlockSize(); - if(send_padd_blocksize < 8) { + + if (send_padd_blocksize < 8) { send_padd_blocksize = 8; } } @@ -116,7 +118,7 @@ public void changeRecvCompression(Compressor comp) { recv_comp = comp; - if(comp != null) { + if (comp != null) { recv_comp_buffer = new byte[comp.getBufferSize()]; } } @@ -124,7 +126,7 @@ public void changeSendCompression(Compressor comp) { send_comp = comp; - if(comp != null) { + if (comp != null) { send_comp_buffer = new byte[comp.getBufferSize()]; } } @@ -143,83 +145,80 @@ } public void sendMessage(byte[] message, int off, int len, int padd) throws IOException { - if(padd < 4) { + if (padd < 4) { padd = 4; } - else if(padd > 64) { + else if (padd > 64) { padd = 64; } - if(send_comp != null && can_compress) { + if (send_comp != null && can_compress) { len = send_comp.compress(message, off, len, send_comp_buffer); message = send_comp_buffer; } int packet_len = 5 + len + padd; /* Minimum allowed padding is 4 */ - int slack = packet_len % send_padd_blocksize; - if(slack != 0) { + if (slack != 0) { packet_len += (send_padd_blocksize - slack); } - if(packet_len < 16) { + if (packet_len < 16) { packet_len = 16; } int padd_len = packet_len - (5 + len); - if(useRandomPadding) { - for(int i = 0; i < padd_len; i = i + 4) { + if (useRandomPadding) { + for (int i = 0; i < padd_len; i = i + 4) { /* * don't waste calls to rnd.nextInt() (by using only 8bit of the - * output). just believe me: even though we may write here up to 3 - * bytes which won't be used, there is no "buffer overflow" (i.e., - * arrayindexoutofbounds). the padding buffer is big enough =) (256 - * bytes, and that is bigger than any current cipher block size + 64). - */ - + * output). just believe me: even though we may write here up to 3 + * bytes which won't be used, there is no "buffer overflow" (i.e., + * arrayindexoutofbounds). the padding buffer is big enough =) (256 + * bytes, and that is bigger than any current cipher block size + 64). + */ int r = rnd.nextInt(); send_padding_buffer[i] = (byte) r; - send_padding_buffer[i + 1] = (byte) (r >> 8); - send_padding_buffer[i + 2] = (byte) (r >> 16); - send_padding_buffer[i + 3] = (byte) (r >> 24); + send_padding_buffer[i + 1] = (byte)(r >> 8); + send_padding_buffer[i + 2] = (byte)(r >> 16); + send_padding_buffer[i + 3] = (byte)(r >> 24); } } else { - /* use zero padding for unencrypted traffic */ - for(int i = 0; i < padd_len; i++) { + /* use zero padding for unencrypted traffic */ + for (int i = 0; i < padd_len; i++) { send_padding_buffer[i] = 0; } - /* Actually this code is paranoid: we never filled any - * bytes into the padding buffer so far, therefore it should - * consist of zeros only. - */ + + /* Actually this code is paranoid: we never filled any + * bytes into the padding buffer so far, therefore it should + * consist of zeros only. + */ } - send_packet_header_buffer[0] = (byte) ((packet_len - 4) >> 24); - send_packet_header_buffer[1] = (byte) ((packet_len - 4) >> 16); - send_packet_header_buffer[2] = (byte) ((packet_len - 4) >> 8); - send_packet_header_buffer[3] = (byte) ((packet_len - 4)); + send_packet_header_buffer[0] = (byte)((packet_len - 4) >> 24); + send_packet_header_buffer[1] = (byte)((packet_len - 4) >> 16); + send_packet_header_buffer[2] = (byte)((packet_len - 4) >> 8); + send_packet_header_buffer[3] = (byte)((packet_len - 4)); send_packet_header_buffer[4] = (byte) padd_len; - cos.write(send_packet_header_buffer, 0, 5); cos.write(message, off, len); cos.write(send_padding_buffer, 0, padd_len); - if(send_mac != null) { + if (send_mac != null) { send_mac.initMac(send_seq_number); send_mac.update(send_packet_header_buffer, 0, 5); send_mac.update(message, off, len); send_mac.update(send_padding_buffer, 0, padd_len); - send_mac.getMac(send_mac_buffer, 0); cos.writePlain(send_mac_buffer, 0, send_mac_buffer.length); } cos.flush(); - if(log.isDebugEnabled()) { + if (log.isDebugEnabled()) { log.debug("Sent " + Packets.getMessageName(message[off] & 0xff) + " " + len + " bytes payload"); } @@ -227,24 +226,23 @@ } public int peekNextMessageLength() throws IOException { - if(recv_packet_header_present == false) { + if (recv_packet_header_present == false) { cis.read(recv_packet_header_buffer, 0, 5); recv_packet_header_present = true; } int packet_length = ((recv_packet_header_buffer[0] & 0xff) << 24) - | ((recv_packet_header_buffer[1] & 0xff) << 16) | ((recv_packet_header_buffer[2] & 0xff) << 8) - | ((recv_packet_header_buffer[3] & 0xff)); - + | ((recv_packet_header_buffer[1] & 0xff) << 16) | ((recv_packet_header_buffer[2] & 0xff) << 8) + | ((recv_packet_header_buffer[3] & 0xff)); int padding_length = recv_packet_header_buffer[4] & 0xff; - if(packet_length > TransportManager.MAX_PACKET_SIZE || packet_length < 12) { + if (packet_length > TransportManager.MAX_PACKET_SIZE || packet_length < 12) { throw new PacketFormatException(String.format("Illegal packet size (%d)", packet_length)); } int payload_length = packet_length - padding_length - 1; - if(payload_length < 0) { + if (payload_length < 0) { throw new PacketFormatException(String.format("Illegal padding_length in packet from remote (%d)", padding_length)); } @@ -252,7 +250,7 @@ } public int receiveMessage(byte buffer[], int off, int len) throws IOException { - if(recv_packet_header_present == false) { + if (recv_packet_header_present == false) { cis.read(recv_packet_header_buffer, 0, 5); } else { @@ -260,39 +258,37 @@ } int packet_length = ((recv_packet_header_buffer[0] & 0xff) << 24) - | ((recv_packet_header_buffer[1] & 0xff) << 16) | ((recv_packet_header_buffer[2] & 0xff) << 8) - | ((recv_packet_header_buffer[3] & 0xff)); - + | ((recv_packet_header_buffer[1] & 0xff) << 16) | ((recv_packet_header_buffer[2] & 0xff) << 8) + | ((recv_packet_header_buffer[3] & 0xff)); int padding_length = recv_packet_header_buffer[4] & 0xff; - if(packet_length > TransportManager.MAX_PACKET_SIZE || packet_length < 12) { - throw new PacketFormatException(String.format("Illegal packet size (%d)", packet_length)); + if (packet_length > TransportManager.MAX_PACKET_SIZE || packet_length < 12) { + throw new PacketFormatException(String.format("Illegal packet size (%d)", packet_length)); } int payload_length = packet_length - padding_length - 1; - if(payload_length < 0) { + if (payload_length < 0) { throw new PacketFormatException(String.format("Illegal padding_length in packet from remote (%d)", padding_length)); } - if(payload_length >= len) { + if (payload_length >= len) { throw new IOException("Receive buffer too small (" + len + ", need " + payload_length + ")"); } cis.read(buffer, off, payload_length); cis.read(recv_padding_buffer, 0, padding_length); - if(recv_mac != null) { + if (recv_mac != null) { cis.readPlain(recv_mac_buffer, 0, recv_mac_buffer.length); - recv_mac.initMac(recv_seq_number); recv_mac.update(recv_packet_header_buffer, 0, 5); recv_mac.update(buffer, off, payload_length); recv_mac.update(recv_padding_buffer, 0, padding_length); recv_mac.getMac(recv_mac_buffer_cmp, 0); - for(int i = 0; i < recv_mac_buffer.length; i++) { - if(recv_mac_buffer[i] != recv_mac_buffer_cmp[i]) { + for (int i = 0; i < recv_mac_buffer.length; i++) { + if (recv_mac_buffer[i] != recv_mac_buffer_cmp[i]) { throw new IOException("Remote sent corrupt MAC."); } } @@ -300,13 +296,13 @@ recv_seq_number++; - if(log.isDebugEnabled()) { + if (log.isDebugEnabled()) { log.debug("Received " + Packets.getMessageName(buffer[off] & 0xff) + " " + payload_length - + " bytes payload"); + + " bytes payload"); } - if(recv_comp != null && can_compress) { - int[] uncomp_len = new int[]{payload_length}; + if (recv_comp != null && can_compress) { + int[] uncomp_len = new int[] {payload_length}; buffer = recv_comp.uncompress(buffer, off, uncomp_len); return uncomp_len[0]; } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/transport/TransportManager.java --- a/src/ch/ethz/ssh2/transport/TransportManager.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/transport/TransportManager.java Wed Jul 30 14:16:58 2014 -0700 @@ -55,7 +55,7 @@ public static final int MAX_PACKET_SIZE = 64 * 1024; private final List asynchronousQueue - = new ArrayList(); + = new ArrayList(); private Thread asynchronousThread = null; private boolean asynchronousPending = false; @@ -76,40 +76,41 @@ private final class AsynchronousWorker implements Runnable { public void run() { - while(true) { + while (true) { final AsynchronousEntry item; - synchronized(asynchronousQueue) { - if(asynchronousQueue.size() == 0) { + + synchronized (asynchronousQueue) { + if (asynchronousQueue.size() == 0) { // Only now we may reset the flag, since we are sure that all queued items // have been sent (there is a slight delay between de-queuing and sending, // this is why we need this flag! See code below. Sending takes place outside // of this lock, this is why a test for size()==0 (from another thread) does not ensure // that all messages have been sent. - asynchronousPending = false; - // Notify any senders that they can proceed, all async messages have been delivered - asynchronousQueue.notifyAll(); // After the queue is empty for about 2 seconds, stop this thread try { asynchronousQueue.wait(2000); } - catch(InterruptedException ignore) { + catch (InterruptedException ignore) { // } - if(asynchronousQueue.size() == 0) { + + if (asynchronousQueue.size() == 0) { asynchronousThread = null; return; } } + item = asynchronousQueue.remove(0); } + try { sendMessageImmediate(item.message); } - catch(IOException e) { + catch (IOException e) { // There is no point in handling it - it simply means that the connection has a problem and we should stop // sending asynchronously messages. We do not need to signal that we have exited (asynchronousThread = null): // further messages in the queue cannot be sent by this or any other thread. @@ -133,10 +134,10 @@ private KexManager km; private final List messageHandlers - = new ArrayList(); + = new ArrayList(); private List connectionMonitors - = new ArrayList(); + = new ArrayList(); protected void init(TransportConnection tc, KexManager km) { this.tc = tc; @@ -152,7 +153,7 @@ } public IOException getReasonClosedCause() { - synchronized(connectionSemaphore) { + synchronized (connectionSemaphore) { return reasonClosedCause; } } @@ -163,28 +164,32 @@ public void close() { // It is safe now to acquire the semaphore. - synchronized(connectionSemaphore) { - if(!connectionClosed) { + synchronized (connectionSemaphore) { + if (!connectionClosed) { try { tc.sendMessage(new PacketDisconnect( - PacketDisconnect.Reason.SSH_DISCONNECT_BY_APPLICATION, "").getPayload()); + PacketDisconnect.Reason.SSH_DISCONNECT_BY_APPLICATION, "").getPayload()); } - catch(IOException ignore) { + catch (IOException ignore) { // } + try { socket.close(); } - catch(IOException ignore) { + catch (IOException ignore) { // } + connectionClosed = true; - synchronized(this) { - for(ConnectionMonitor cmon : connectionMonitors) { + + synchronized (this) { + for (ConnectionMonitor cmon : connectionMonitors) { cmon.connectionLost(reasonClosedCause); } } } + connectionSemaphore.notifyAll(); } } @@ -195,16 +200,18 @@ try { socket.close(); } - catch(IOException ignore) { + catch (IOException ignore) { } + // It is safe now to acquire the semaphore. - synchronized(connectionSemaphore) { + synchronized (connectionSemaphore) { connectionClosed = true; reasonClosedCause = cause; connectionSemaphore.notifyAll(); } - synchronized(this) { - for(ConnectionMonitor cmon : connectionMonitors) { + + synchronized (this) { + for (ConnectionMonitor cmon : connectionMonitors) { cmon.connectionLost(reasonClosedCause); } } @@ -217,18 +224,21 @@ receiveLoop(); // Can only exit with exception } - catch(IOException e) { + catch (IOException e) { close(e); log.warning(e.getMessage()); + // Tell all handlers that it is time to say goodbye - if(km != null) { + if (km != null) { km.handleFailure(e); } - for(HandlerEntry he : messageHandlers) { + + for (HandlerEntry he : messageHandlers) { he.mh.handleFailure(e); } } - if(log.isDebugEnabled()) { + + if (log.isDebugEnabled()) { log.debug("Receive thread: back from receiveLoop"); } } @@ -244,16 +254,17 @@ he.low = low; he.high = high; - synchronized(messageHandlers) { + synchronized (messageHandlers) { messageHandlers.add(he); } } public void removeMessageHandler(MessageHandler handler) { - synchronized(messageHandlers) { - for(int i = 0; i < messageHandlers.size(); i++) { + synchronized (messageHandlers) { + for (int i = 0; i < messageHandlers.size(); i++) { HandlerEntry he = messageHandlers.get(i); - if(he.mh == handler) { + + if (he.mh == handler) { messageHandlers.remove(i); break; } @@ -262,15 +273,17 @@ } public void sendKexMessage(byte[] msg) throws IOException { - synchronized(connectionSemaphore) { - if(connectionClosed) { + synchronized (connectionSemaphore) { + if (connectionClosed) { throw reasonClosedCause; } + flagKexOngoing = true; + try { tc.sendMessage(msg); } - catch(IOException e) { + catch (IOException e) { close(e); throw e; } @@ -278,7 +291,7 @@ } public void kexFinished() throws IOException { - synchronized(connectionSemaphore) { + synchronized (connectionSemaphore) { flagKexOngoing = false; connectionSemaphore.notifyAll(); } @@ -292,13 +305,14 @@ * @throws IOException */ public void forceKeyExchange(CryptoWishList cwl, DHGexParameters dhgex, KeyPair dsa, KeyPair rsa, KeyPair ec) - throws IOException { - synchronized(connectionSemaphore) { - if(connectionClosed) { + throws IOException { + synchronized (connectionSemaphore) { + if (connectionClosed) { // Inform the caller that there is no point in triggering a new kex throw reasonClosedCause; } } + km.initiateKEX(cwl, dhgex, dsa, rsa, ec); } @@ -319,33 +333,34 @@ } public void sendAsynchronousMessage(byte[] msg) throws IOException { - synchronized(asynchronousQueue) { + synchronized (asynchronousQueue) { asynchronousQueue.add(new AsynchronousEntry(msg)); asynchronousPending = true; - /* This limit should be flexible enough. We need this, otherwise the peer + /* This limit should be flexible enough. We need this, otherwise the peer * can flood us with global requests (and other stuff where we have to reply - * with an asynchronous message) and (if the server just sends data and does not - * read what we send) this will probably put us in a low memory situation - * (our send queue would grow and grow and...) */ + * with an asynchronous message) and (if the server just sends data and does not + * read what we send) this will probably put us in a low memory situation + * (our send queue would grow and grow and...) */ - if(asynchronousQueue.size() > 100) { + if (asynchronousQueue.size() > 100) { throw new IOException("The peer is not consuming our asynchronous replies."); } // Check if we have an asynchronous sending thread - if(asynchronousThread == null) { + if (asynchronousThread == null) { asynchronousThread = new Thread(new AsynchronousWorker()); asynchronousThread.setDaemon(true); asynchronousThread.start(); // The thread will stop after 2 seconds of inactivity (i.e., empty queue) } + asynchronousQueue.notifyAll(); } } public void setConnectionMonitors(List monitors) { - synchronized(this) { + synchronized (this) { connectionMonitors = new ArrayList(); connectionMonitors.addAll(monitors); } @@ -358,16 +373,17 @@ * @throws IOException */ public void sendMessage(byte[] msg) throws IOException { - synchronized(asynchronousQueue) { - while(asynchronousPending) { + synchronized (asynchronousQueue) { + while (asynchronousPending) { try { asynchronousQueue.wait(); } - catch(InterruptedException e) { + catch (InterruptedException e) { throw new InterruptedIOException(e.getMessage()); } } } + sendMessageImmediate(msg); } @@ -379,18 +395,20 @@ * @throws IOException */ public void sendMessageImmediate(byte[] msg) throws IOException { - synchronized(connectionSemaphore) { - while(true) { - if(connectionClosed) { + synchronized (connectionSemaphore) { + while (true) { + if (connectionClosed) { throw reasonClosedCause; } - if(!flagKexOngoing) { + + if (!flagKexOngoing) { break; } + try { connectionSemaphore.wait(); } - catch(InterruptedException e) { + catch (InterruptedException e) { throw new InterruptedIOException(e.getMessage()); } } @@ -398,7 +416,7 @@ try { tc.sendMessage(msg); } - catch(IOException e) { + catch (IOException e) { close(e); throw e; } @@ -406,32 +424,39 @@ } private void receiveLoop() throws IOException { - while(true) { + while (true) { final byte[] buffer = new byte[MAX_PACKET_SIZE]; final int length = tc.receiveMessage(buffer, 0, buffer.length); final byte[] packet = new byte[length]; System.arraycopy(buffer, 0, packet, 0, length); final int type = packet[0] & 0xff; - switch(type) { + + switch (type) { case Packets.SSH_MSG_IGNORE: break; + case Packets.SSH_MSG_DEBUG: { - TypesReader tr = new TypesReader(packet); - tr.readByte(); - // always_display - tr.readBoolean(); - String message = tr.readString(); - if(log.isDebugEnabled()) { - log.debug(String.format("Debug message from remote: '%s'", message)); + TypesReader tr = new TypesReader(packet); + tr.readByte(); + // always_display + tr.readBoolean(); + String message = tr.readString(); + + if (log.isDebugEnabled()) { + log.debug(String.format("Debug message from remote: '%s'", message)); + } + + break; } - break; - } + case Packets.SSH_MSG_UNIMPLEMENTED: throw new PacketTypeException(type); + case Packets.SSH_MSG_DISCONNECT: { - final PacketDisconnect disconnect = new PacketDisconnect(packet); - throw new DisconnectException(disconnect.getReason(), disconnect.getMessage()); - } + final PacketDisconnect disconnect = new PacketDisconnect(packet); + throw new DisconnectException(disconnect.getReason(), disconnect.getMessage()); + } + case Packets.SSH_MSG_KEXINIT: case Packets.SSH_MSG_NEWKEYS: case Packets.SSH_MSG_KEXDH_INIT: @@ -442,24 +467,30 @@ // Is it a KEX Packet km.handleMessage(packet); break; + case Packets.SSH_MSG_USERAUTH_SUCCESS: tc.startCompression(); - // Continue with message handlers + + // Continue with message handlers default: boolean handled = false; - for(HandlerEntry handler : messageHandlers) { - if((handler.low <= type) && (type <= handler.high)) { + + for (HandlerEntry handler : messageHandlers) { + if ((handler.low <= type) && (type <= handler.high)) { handler.mh.handleMessage(packet); handled = true; break; } } - if(!handled) { + + if (!handled) { throw new PacketTypeException(type); } + break; } - if(log.isDebugEnabled()) { + + if (log.isDebugEnabled()) { log.debug(String.format("Handled packet %d", type)); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/util/StringEncoder.java --- a/src/ch/ethz/ssh2/util/StringEncoder.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/util/StringEncoder.java Wed Jul 30 14:16:58 2014 -0700 @@ -11,29 +11,25 @@ * @author Christian Plattner * @version $Id: StringEncoder.java 43 2011-06-21 18:34:06Z dkocher@sudo.ch $ */ -public class StringEncoder -{ - public static byte[] GetBytes(String data) - { +public class StringEncoder { + public static byte[] GetBytes(String data) { try { return data.getBytes("UTF-8"); } - catch(UnsupportedEncodingException e) { + catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } - public static String GetString(byte[] data) - { - return GetString(data, 0, data.length); - } + public static String GetString(byte[] data) { + return GetString(data, 0, data.length); + } - public static String GetString(byte[] data, int off, int len) - { + public static String GetString(byte[] data, int off, int len) { try { return new String(data, off, len, "UTF-8"); } - catch(UnsupportedEncodingException e) { + catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } diff -r d2b303406d63 -r 071eccdff8ea src/ch/ethz/ssh2/util/TimeoutService.java --- a/src/ch/ethz/ssh2/util/TimeoutService.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/ch/ethz/ssh2/util/TimeoutService.java Wed Jul 30 14:16:58 2014 -0700 @@ -20,136 +20,114 @@ * that rely on timeouts, then there will be only one timeout thread. Once all timeouts * have expired/are cancelled, the thread will (sooner or later) exit. * Only after new timeouts arrive a new thread (singleton) will be instantiated. - * + * * @author Christian Plattner * @version $Id: TimeoutService.java 89 2014-04-07 14:36:24Z dkocher@sudo.ch $ */ -public class TimeoutService -{ - private static final Logger log = Logger.getLogger(TimeoutService.class); +public class TimeoutService { + private static final Logger log = Logger.getLogger(TimeoutService.class); - public static class TimeoutToken - { - private long runTime; - private Runnable handler; + public static class TimeoutToken { + private long runTime; + private Runnable handler; - private TimeoutToken(long runTime, Runnable handler) - { - this.runTime = runTime; - this.handler = handler; - } - } + private TimeoutToken(long runTime, Runnable handler) { + this.runTime = runTime; + this.handler = handler; + } + } - private static class TimeoutThread extends Thread - { - @Override - public void run() - { - synchronized (todolist) - { - while (true) - { - if (todolist.size() == 0) - { - timeoutThread = null; - return; - } + private static class TimeoutThread extends Thread { + @Override + public void run() { + synchronized (todolist) { + while (true) { + if (todolist.size() == 0) { + timeoutThread = null; + return; + } - long now = System.currentTimeMillis(); - - TimeoutToken tt = todolist.getFirst(); + long now = System.currentTimeMillis(); + TimeoutToken tt = todolist.getFirst(); - if (tt.runTime > now) - { - /* Not ready yet, sleep a little bit */ + if (tt.runTime > now) { + /* Not ready yet, sleep a little bit */ + try { + todolist.wait(tt.runTime - now); + } + catch (InterruptedException ignored) { + } - try - { - todolist.wait(tt.runTime - now); - } - catch (InterruptedException ignored) - { - } + /* We cannot simply go on, since it could be that the token + * was removed (cancelled) or another one has been inserted in + * the meantime. + */ + continue; + } - /* We cannot simply go on, since it could be that the token - * was removed (cancelled) or another one has been inserted in - * the meantime. - */ - - continue; - } - - todolist.removeFirst(); + todolist.removeFirst(); - try - { - tt.handler.run(); - } - catch (Exception e) - { - StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); - log.warning("Exeception in Timeout handler:" + e.getMessage() + "(" + sw.toString() + ")"); - } - } - } - } - } + try { + tt.handler.run(); + } + catch (Exception e) { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw)); + log.warning("Exeception in Timeout handler:" + e.getMessage() + "(" + sw.toString() + ")"); + } + } + } + } + } - /* The list object is also used for locking purposes */ - private static final LinkedList todolist = new LinkedList(); + /* The list object is also used for locking purposes */ + private static final LinkedList todolist = new LinkedList(); - private static Thread timeoutThread = null; + private static Thread timeoutThread = null; - /** - * It is assumed that the passed handler will not execute for a long time. - * - * @param runTime - * @param handler - * @return a TimeoutToken that can be used to cancel the timeout. - */ - public static TimeoutToken addTimeoutHandler(long runTime, Runnable handler) - { - TimeoutToken token = new TimeoutToken(runTime, handler); - - synchronized (todolist) - { - todolist.add(token); + /** + * It is assumed that the passed handler will not execute for a long time. + * + * @param runTime + * @param handler + * @return a TimeoutToken that can be used to cancel the timeout. + */ + public static TimeoutToken addTimeoutHandler(long runTime, Runnable handler) { + TimeoutToken token = new TimeoutToken(runTime, handler); - Collections.sort(todolist, new Comparator() - { - public int compare(TimeoutToken o1, TimeoutToken o2) - { - if (o1.runTime > o2.runTime) - return 1; - if (o1.runTime == o2.runTime) - return 0; - return -1; - } - }); + synchronized (todolist) { + todolist.add(token); + Collections.sort(todolist, new Comparator() { + public int compare(TimeoutToken o1, TimeoutToken o2) { + if (o1.runTime > o2.runTime) + return 1; + + if (o1.runTime == o2.runTime) + return 0; + + return -1; + } + }); - if (timeoutThread != null) - timeoutThread.interrupt(); - else - { - timeoutThread = new TimeoutThread(); - timeoutThread.setDaemon(true); - timeoutThread.start(); - } - } + if (timeoutThread != null) + timeoutThread.interrupt(); + else { + timeoutThread = new TimeoutThread(); + timeoutThread.setDaemon(true); + timeoutThread.start(); + } + } - return token; - } + return token; + } - public static void cancelTimeoutHandler(TimeoutToken token) - { - synchronized (todolist) - { - todolist.remove(token); + public static void cancelTimeoutHandler(TimeoutToken token) { + synchronized (todolist) { + todolist.remove(token); - if (timeoutThread != null) - timeoutThread.interrupt(); - } - } + if (timeoutThread != null) + timeoutThread.interrupt(); + } + } } diff -r d2b303406d63 -r 071eccdff8ea src/com/five_ten_sg/connectbot/HelpActivity.java --- a/src/com/five_ten_sg/connectbot/HelpActivity.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/com/five_ten_sg/connectbot/HelpActivity.java Wed Jul 30 14:16:58 2014 -0700 @@ -50,6 +50,7 @@ getResources().getText(R.string.title_help))); AssetManager am = this.getAssets(); LinearLayout content = (LinearLayout)this.findViewById(R.id.topics); + try { for (String name : am.list(HELPDIR)) { if (name.endsWith(SUFFIX)) { diff -r d2b303406d63 -r 071eccdff8ea src/com/five_ten_sg/connectbot/HostEditorActivity.java --- a/src/com/five_ten_sg/connectbot/HostEditorActivity.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/com/five_ten_sg/connectbot/HostEditorActivity.java Wed Jul 30 14:16:58 2014 -0700 @@ -323,8 +323,11 @@ // get all the original text summaries for (String key : this.pref.values.keySet()) { Preference pref = this.findPreference(key); + if (pref == null) continue; + if (pref instanceof CheckBoxPreference) continue; + CharSequence value = pref.getSummary(); summaries.put(key, value); } @@ -334,8 +337,11 @@ // for all text preferences, set hint as current database value if it is non-empty for (String key : this.pref.values.keySet()) { Preference pref = this.findPreference(key); + if (pref == null) continue; + if (pref instanceof CheckBoxPreference) continue; + CharSequence value = this.pref.getString(key, ""); if (key.equals(HostDatabase.FIELD_HOST_PUBKEYID)) { @@ -358,10 +364,12 @@ else if ((pref instanceof ListPreference) && (value != null)) { ListPreference listPref = (ListPreference) pref; int entryIndex = listPref.findIndexOfValue(value.toString()); + if (entryIndex >= 0) value = listPref.getEntries()[entryIndex]; } if ((value == null) || (value.length() == 0)) value = summaries.get(key); + pref.setSummary(value); } } diff -r d2b303406d63 -r 071eccdff8ea src/com/five_ten_sg/connectbot/HostListActivity.java --- a/src/com/five_ten_sg/connectbot/HostListActivity.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/com/five_ten_sg/connectbot/HostListActivity.java Wed Jul 30 14:16:58 2014 -0700 @@ -403,21 +403,30 @@ File.separator + "deployment.connections"; BufferedReader reader = new BufferedReader(new FileReader(fn)); String line = null; + while ((line = reader.readLine()) != null) { if (line.length() == 0) continue; // empty - if (line.substring(0,1).equals("#")) continue; // comment + + if (line.substring(0, 1).equals("#")) continue; // comment + if (!line.contains("://")) continue; // invalid uri + Uri uri = Uri.parse(line); ContentValues values = null; + while ((line = reader.readLine()).length() > 0) { String [] parts = line.split("="); + if (parts.length != 2) continue; + if (values == null) values = new ContentValues(); + values.put(parts[0].trim(), parts[1].trim()); } + if (uri.getScheme().equals("global")) { Editor editor = prefs.edit(); - HashMap types = new HashMap(); + HashMap types = new HashMap(); types.put("memkeys", "boolean"); types.put("connPersist", "boolean"); types.put("emulation", "string"); @@ -451,30 +460,38 @@ types.put("upload_dest_prompt", "boolean"); types.put("background_file_transfer", "boolean"); types.put("debug_keycodes", "boolean"); + for (String key : values.keySet()) { if (types.containsKey(key)) { String sv = values.getAsString(key); editor.putString(key, sv); } } + editor.commit(); } else { HostBean host = TransportFactory.findHost(hostdb, uri); + if (host == null) { host = TransportFactory.getTransport(uri.getScheme()).createHost(uri); host.setColor(HostDatabase.COLOR_GRAY); host.setPubkeyId(HostDatabase.PUBKEYID_ANY); hostdb.saveHost(host); } + host = TransportFactory.findHost(hostdb, uri); + if (host == null) continue; + if (values == null) continue; + SQLiteDatabase db = hostdb.getWritableDatabase(); db.update(HostDatabase.TABLE_HOSTS, values, "_id = ?", new String[] { String.valueOf(host.getId()) }); db.close(); } } + reader.close(); (new File(fn)).delete(); } diff -r d2b303406d63 -r 071eccdff8ea src/com/five_ten_sg/connectbot/WizardActivity.java --- a/src/com/five_ten_sg/connectbot/WizardActivity.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/com/five_ten_sg/connectbot/WizardActivity.java Wed Jul 30 14:16:58 2014 -0700 @@ -48,7 +48,6 @@ // inflate the layout for EULA step LayoutInflater inflater = LayoutInflater.from(this); View helpView = inflater.inflate(R.layout.wiz_eula, this.flipper, false); - this.flipper.addView(helpView); // Add a view for each help topic we want the user to see. String[] topics = getResources().getStringArray(R.array.list_wizard_topics); diff -r d2b303406d63 -r 071eccdff8ea src/com/five_ten_sg/connectbot/service/TerminalBridge.java --- a/src/com/five_ten_sg/connectbot/service/TerminalBridge.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/com/five_ten_sg/connectbot/service/TerminalBridge.java Wed Jul 30 14:16:58 2014 -0700 @@ -332,7 +332,6 @@ // get proper font size setMyFontSize(); - // finally send any post-login string, if requested injectString(host.getPostLogin()); } @@ -445,6 +444,7 @@ */ final void setFontSize(float size) { if (size <= 0.0) size = 12.0f; + size = (float)(int)((size * 10.0f) + 0.5f) / 10.0f; defaultPaint.setTextSize(size); fontSize = size; @@ -782,6 +782,7 @@ this.columns = cols; this.rows = rows; forcedSize = true; + if (fixed) setFontSize(host.getFontSize()); else setFontSize(size); } @@ -1136,7 +1137,7 @@ */ public boolean showArrowsDialog() { final String []pickerStrings = {"←", "→", "↑", "↓", "tab", "ins", "del", "ret"}; - final HashMap keymap = new HashMap(); + final HashMap keymap = new HashMap(); keymap.put("←", vt320.KEY_LEFT); keymap.put("→", vt320.KEY_RIGHT); keymap.put("↑", vt320.KEY_UP); @@ -1145,15 +1146,14 @@ keymap.put("ins", vt320.KEY_INSERT); keymap.put("del", vt320.KEY_DELETE); keymap.put("ret", vt320.KEY_ENTER); - CharSequence str = ""; Editable content = Editable.Factory.getInstance().newEditable(str); if (parent == null) return false; StringPickerDialog cpd = new StringPickerDialog(parent.getContext(), - parent, content, - pickerStrings, true) { + parent, content, + pickerStrings, true) { private void buttonPressed(String s) { if (keymap.containsKey(s)) buffer.keyPressed(keymap.get(s), ' ', 0); } @@ -1165,6 +1165,7 @@ public void onClick(View v) { if (v instanceof Button) { final String s = ((Button) v).getText().toString(); + if (s.equals("")) dismiss(); else buttonPressed(s); } @@ -1260,7 +1261,7 @@ */ public boolean showFKeysDialog() { final String []pickerStrings = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", "←", "→", "↑", "↓", "tab", "ins", "del", "ret"}; - final HashMap keymap = new HashMap(); + final HashMap keymap = new HashMap(); keymap.put("F1", vt320.KEY_F1); keymap.put("F2", vt320.KEY_F2); keymap.put("F3", vt320.KEY_F3); @@ -1293,17 +1294,17 @@ keymap.put("ins", vt320.KEY_INSERT); keymap.put("del", vt320.KEY_DELETE); keymap.put("ret", vt320.KEY_ENTER); - CharSequence str = ""; Editable content = Editable.Factory.getInstance().newEditable(str); if (parent == null) return false; StringPickerDialog cpd = new StringPickerDialog(parent.getContext(), - parent, content, - pickerStrings, true) { + parent, content, + pickerStrings, true) { private void buttonPressed(String s) { if (keymap.containsKey(s)) buffer.keyPressed(keymap.get(s), ' ', 0); + dismiss(); } @Override @@ -1314,6 +1315,7 @@ public void onClick(View v) { if (v instanceof Button) { final String s = ((Button) v).getText().toString(); + if (s.equals("")) dismiss(); else buttonPressed(s); } diff -r d2b303406d63 -r 071eccdff8ea src/com/five_ten_sg/connectbot/service/TerminalKeyListener.java --- a/src/com/five_ten_sg/connectbot/service/TerminalKeyListener.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/com/five_ten_sg/connectbot/service/TerminalKeyListener.java Wed Jul 30 14:16:58 2014 -0700 @@ -569,40 +569,41 @@ private boolean handleShortcuts(View v, int keyCode, KeyEvent event, int repeat, boolean down) { String hwbuttonShortcut; + switch (keyCode) { case KeyEvent.KEYCODE_CAMERA: // check to see which shortcut the camera button triggers hwbuttonShortcut = manager.prefs.getString( - PreferenceConstants.CAMERA, - PreferenceConstants.HWBUTTON_SCREEN_CAPTURE); + PreferenceConstants.CAMERA, + PreferenceConstants.HWBUTTON_SCREEN_CAPTURE); return (handleShortcut(v, hwbuttonShortcut, repeat, down)); case KeyEvent.KEYCODE_VOLUME_UP: // check to see which shortcut the volume button triggers hwbuttonShortcut = manager.prefs.getString( - PreferenceConstants.VOLUP, - PreferenceConstants.HWBUTTON_FUNCTION_KEYS); + PreferenceConstants.VOLUP, + PreferenceConstants.HWBUTTON_FUNCTION_KEYS); return (handleShortcut(v, hwbuttonShortcut, repeat, down)); case KeyEvent.KEYCODE_VOLUME_DOWN: // check to see which shortcut the camera button triggers hwbuttonShortcut = manager.prefs.getString( - PreferenceConstants.VOLDN, - PreferenceConstants.HWBUTTON_TAB); + PreferenceConstants.VOLDN, + PreferenceConstants.HWBUTTON_TAB); return (handleShortcut(v, hwbuttonShortcut, repeat, down)); case KeyEvent.KEYCODE_SEARCH: // check to see which shortcut the search button triggers hwbuttonShortcut = manager.prefs.getString( - PreferenceConstants.SEARCH, - PreferenceConstants.HWBUTTON_ESC); + PreferenceConstants.SEARCH, + PreferenceConstants.HWBUTTON_ESC); return (handleShortcut(v, hwbuttonShortcut, repeat, down)); case KeyEvent.KEYCODE_BUTTON_L2: // check to see which shortcut the ptt button triggers hwbuttonShortcut = manager.prefs.getString( - PreferenceConstants.PTT, - PreferenceConstants.HWBUTTON_MONITOR); + PreferenceConstants.PTT, + PreferenceConstants.HWBUTTON_MONITOR); return (handleShortcut(v, hwbuttonShortcut, repeat, down)); default: return false; @@ -612,51 +613,64 @@ private boolean handleShortcut(View v, String shortcut, int repeat, boolean down) { if (PreferenceConstants.HWBUTTON_DECREASE_FONTSIZE.equals(shortcut)) { if (!down) return false; + bridge.decreaseFontSize(); } else if (PreferenceConstants.HWBUTTON_INCREASE_FONTSIZE.equals(shortcut)) { if (!down) return false; + bridge.increaseFontSize(); } else if (PreferenceConstants.HWBUTTON_FUNCTION_KEYS.equals(shortcut)) { if (repeat > 0) return false; + if (!down) return false; + bridge.showFKeysDialog(); } else if (PreferenceConstants.HWBUTTON_MONITOR.equals(shortcut)) { if (repeat > 0) return false; + buffer.monitorKey(down); } else if (PreferenceConstants.HWBUTTON_SCREEN_CAPTURE.equals(shortcut)) { if (repeat > 0) return false; + if (!down) return false; + bridge.captureScreen(); } else if (PreferenceConstants.HWBUTTON_CTRL.equals(shortcut)) { if (!down) return false; + showMetakeyToast(v, PreferenceConstants.HWBUTTON_CTRL); metaPress(META_CTRL_ON); } else if (PreferenceConstants.HWBUTTON_TAB.equals(shortcut)) { if (!down) return false; + buffer.keyPressed(vt320.KEY_TAB, ' ', getStateForBuffer()); } else if (PreferenceConstants.HWBUTTON_CTRLA_SPACE.equals(shortcut)) { if (!down) return false; + buffer.write(0x01); buffer.write(' '); } else if (PreferenceConstants.HWBUTTON_CTRLA.equals(shortcut)) { if (!down) return false; + buffer.write(0x01); } else if (PreferenceConstants.HWBUTTON_ESC.equals(shortcut)) { if (!down) return false; + showMetakeyToast(v, PreferenceConstants.HWBUTTON_ESC); sendEscape(); } else if (PreferenceConstants.HWBUTTON_ESC_A.equals(shortcut)) { if (!down) return false; + sendEscape(); buffer.write('a'); } diff -r d2b303406d63 -r 071eccdff8ea src/com/five_ten_sg/connectbot/service/TerminalMonitor.java --- a/src/com/five_ten_sg/connectbot/service/TerminalMonitor.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/com/five_ten_sg/connectbot/service/TerminalMonitor.java Wed Jul 30 14:16:58 2014 -0700 @@ -378,6 +378,7 @@ public synchronized void cursorMove(int l, int c) { if ((to_line != l) || (to_column != c)) moved = true; + to_line = l; to_column = c; } @@ -421,21 +422,23 @@ int len = data.length - offset; char[] da = new char[len]; System.arraycopy(data, offset, da, 0, len); + if ((l > 60000) || (c > 60000)) { l = -1; c = -1; } else { // ignore setfield outside screen boundaries - if ((l >= buffer.height) || (c+len >= buffer.width)) return; + if ((l >= buffer.height) || (c + len >= buffer.width)) return; } + buffer.setField(l, c, da); } public synchronized void showUrl(char [] data, int offset) { Log.i(TAG, "setField()"); char[] da = new char[data.length - offset]; - System.arraycopy(data, offset, da, 0, data.length-offset); + System.arraycopy(data, offset, da, 0, data.length - offset); String url = new String(da); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); parent.startActivity(intent); @@ -447,12 +450,14 @@ arg2[2] = (char)(l & 0x0000ffff); arg2[3] = (char)(c & 0x0000ffff); int base = 4; - if ((l >= buffer.height) || (c+len >= buffer.width)) { - Arrays.fill(arg2, base, len-1, ' '); + + if ((l >= buffer.height) || (c + len >= buffer.width)) { + Arrays.fill(arg2, base, len - 1, ' '); } else { System.arraycopy(buffer.charArray[buffer.screenBase + l], c, arg2, base, len); } + monitorWrite(MONITOR_CMD_FIELDVALUE, arg2); } @@ -467,6 +472,7 @@ public synchronized void depress(int vk_key) { Log.i(TAG, String.format("depress() %d", vk_key)); Integer x = keymap.get(new Integer(vk_key)); + if (x != null) buffer.keyDepressed(x, ' ', 0); } diff -r d2b303406d63 -r 071eccdff8ea src/com/five_ten_sg/connectbot/transport/TN5250.java --- a/src/com/five_ten_sg/connectbot/transport/TN5250.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/com/five_ten_sg/connectbot/transport/TN5250.java Wed Jul 30 14:16:58 2014 -0700 @@ -163,6 +163,7 @@ public void keyDepressed(int keyCode, char keyChar, int modifiers) { if (mnemonics.containsKey(keyCode)) { String s = mnemonics.get(keyCode); + if (s != "") screen52.sendKeys(s); } } @@ -177,17 +178,20 @@ @Override public void write(byte[] b) { screen52.sendKeys(new String(b)); + if (bridge.monitor != null) bridge.monitor.testMoved(); } @Override public void write(int b) { if (controls.containsKey(b)) keyPressed(controls.get(b), ' ', 0); else screen52.sendKeys(new String(new byte[] {(byte)b})); + if (bridge.monitor != null) bridge.monitor.testMoved(); } @Override public void keyPressed(int keyCode, char keyChar, int modifiers) { keyDepressed(keyCode, keyChar, modifiers); + if (bridge.monitor != null) bridge.monitor.testMoved(); } @@ -281,6 +285,7 @@ screen52.setBuffer(buffer); bridge.addFontSizeChangedListener(screen52); connected = handler.connect(host, homeDirectory, buffer); + if (connected) bridge.onConnected(); } @@ -435,8 +440,8 @@ if (nickname == null || nickname.length() == 0) { nickname = getDefaultNickname(host.getUsername(), host.getHostname(), host.getPort()); } + host.setNickname(nickname); - return host; } diff -r d2b303406d63 -r 071eccdff8ea src/com/five_ten_sg/connectbot/util/StringPickerDialog.java --- a/src/com/five_ten_sg/connectbot/util/StringPickerDialog.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/com/five_ten_sg/connectbot/util/StringPickerDialog.java Wed Jul 30 14:16:58 2014 -0700 @@ -38,7 +38,7 @@ * Dialog for choosing accented characters related to a base character. */ public class StringPickerDialog extends Dialog - implements OnItemClickListener, OnClickListener { + implements OnItemClickListener, OnClickListener { private View mView; private Editable mText; private String []mOptions; @@ -52,10 +52,9 @@ * the sense of insert) into text. */ public StringPickerDialog(Context context, View view, - Editable text, String []options, - boolean insert) { + Editable text, String []options, + boolean insert) { //super(context, com.android.internal.R.style.Theme_Panel); - //Resources res = Resources.getSystem(); //int id = res.getIdentifier("Theme_Panel", "style", "android"); //int id = android.R.style.Theme_Panel; @@ -70,18 +69,14 @@ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - WindowManager.LayoutParams params = getWindow().getAttributes(); params.token = mView.getApplicationWindowToken(); params.type = params.TYPE_APPLICATION_ATTACHED_DIALOG; params.flags = params.flags | Window.FEATURE_NO_TITLE; - setContentView(R.layout.string_picker); - GridView grid = (GridView) findViewById(R.id.stringPicker); grid.setAdapter(new OptionsAdapter(getContext())); grid.setOnItemClickListener(this); - mCancelButton = (Button) findViewById(R.id.cancel); mCancelButton.setOnClickListener(this); } @@ -96,9 +91,11 @@ private void replaceCharacterAndClose(CharSequence replace) { int selEnd = Selection.getSelectionEnd(mText); + if (mInsert || selEnd == 0) { mText.insert(selEnd, replace); - } else { + } + else { mText.replace(selEnd - 1, selEnd, replace); } @@ -111,7 +108,8 @@ public void onClick(View v) { if (v == mCancelButton) { dismiss(); - } else if (v instanceof Button) { + } + else if (v instanceof Button) { CharSequence result = ((Button) v).getText(); replaceCharacterAndClose(result); } @@ -125,7 +123,7 @@ public View getView(int position, View convertView, ViewGroup parent) { Button b = (Button) - mInflater.inflate(R.layout.string_picker_button, null); + mInflater.inflate(R.layout.string_picker_button, null); b.setText(mOptions[position]); b.setOnClickListener(StringPickerDialog.this); return b; diff -r d2b303406d63 -r 071eccdff8ea src/de/mud/terminal/VDUBuffer.java --- a/src/de/mud/terminal/VDUBuffer.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/de/mud/terminal/VDUBuffer.java Wed Jul 30 14:16:58 2014 -0700 @@ -159,7 +159,9 @@ public void putChar(int c, int l, char ch, int attributes) { int ll = screenBase + l; + if ((ll >= bufSize) || (c >= width)) return; // ignore characters outside our buffer + charArray[ll][c] = ch; charAttributes[ll][c] = attributes; @@ -588,8 +590,8 @@ * @param l line */ public void setCursorPosition(int c, int l) { - cursorX = (c > width-1) ? width-1 : c; - cursorY = (l > height-1) ? height-1 : l; + cursorX = (c > width - 1) ? width - 1 : c; + cursorY = (l > height - 1) ? height - 1 : l; } /** diff -r d2b303406d63 -r 071eccdff8ea src/org/tn5250j/framework/tn5250/Screen5250.java --- a/src/org/tn5250j/framework/tn5250/Screen5250.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/org/tn5250j/framework/tn5250/Screen5250.java Wed Jul 30 14:16:58 2014 -0700 @@ -1327,6 +1327,7 @@ break; case HOME: + // position to the home position set if (lastPos + numCols + 1 != homePos) { goto_XY(homePos - numCols - 1); @@ -2661,7 +2662,9 @@ if (l >= 0) { lastPos = l * numCols + c; + while (!isInField()) advancePos(); + setDirty(lastPos); fireCursorChanged(); } @@ -2673,12 +2676,14 @@ setDirty(lastPos); setDirty(lastPos + cf.getLength()); lastPos += data.length; + if (!isInField()) { gotoFieldNext(); isInField(); cf = screenFields.getCurrentField(); lastPos = cf.getStartPos(); } + setDirty(lastPos); fireCursorChanged(); } @@ -3568,7 +3573,9 @@ */ protected void changePos(int i) { lastPos += i; + while (lastPos < 0) lastPos += lenScreen; + while (lastPos >= lenScreen) lastPos -= lenScreen; } @@ -3745,7 +3752,7 @@ } public void onFontSizeChanged(float size) { - fireScreenChanged(0, 0, numRows-1, numCols-1); + fireScreenChanged(0, 0, numRows - 1, numCols - 1); } /** diff -r d2b303406d63 -r 071eccdff8ea src/org/tn5250j/framework/tn5250/tnvt.java --- a/src/org/tn5250j/framework/tn5250/tnvt.java Wed Jul 30 12:09:51 2014 -0700 +++ b/src/org/tn5250j/framework/tn5250/tnvt.java Wed Jul 30 14:16:58 2014 -0700 @@ -243,6 +243,7 @@ private String fixer(String value, String def) { if ((value == null) || (value.length() == 0)) return def; + return value; } @@ -1109,7 +1110,6 @@ cursorOn = false; buffer.testChanged(); } - } }