public void receiveLoop() throws IOException { byte[] msg = new byte[35000]; while (true) { int msglen; try { msglen = tc.receiveMessage(msg, 0, msg.length); } catch (SocketTimeoutException e) { // Timeout in read if (idle) { log.debug("Ignoring socket timeout"); continue; } throw e; } idle = true; int type = msg[0] & 0xff; if (type == Packets.SSH_MSG_IGNORE) { continue; } if (type == Packets.SSH_MSG_DEBUG) { if (log.isDebugEnabled()) { TypesReader tr = new TypesReader(msg, 0, msglen); tr.readByte(); tr.readBoolean(); StringBuilder debugMessageBuffer = new StringBuilder(); debugMessageBuffer.append(tr.readString("UTF-8")); for (int i = 0; i < debugMessageBuffer.length(); i++) { char c = debugMessageBuffer.charAt(i); if ((c >= 32) && (c <= 126)) { continue; } debugMessageBuffer.setCharAt(i, '\uFFFD'); } log.debug("DEBUG Message from remote: '" + debugMessageBuffer.toString() + "'"); } continue; } if (type == Packets.SSH_MSG_UNIMPLEMENTED) { throw new IOException("Peer sent UNIMPLEMENTED message, that should not happen."); } if (type == Packets.SSH_MSG_DISCONNECT) { TypesReader tr = new TypesReader(msg, 0, msglen); tr.readByte(); int reason_code = tr.readUINT32(); StringBuilder reasonBuffer = new StringBuilder(); reasonBuffer.append(tr.readString("UTF-8")); /* * Do not get fooled by servers that send abnormal long error * messages */ if (reasonBuffer.length() > 255) { reasonBuffer.setLength(255); reasonBuffer.setCharAt(254, '.'); reasonBuffer.setCharAt(253, '.'); reasonBuffer.setCharAt(252, '.'); } /* * Also, check that the server did not send characters that may * screw up the receiver -> restrict to reasonable US-ASCII * subset -> "printable characters" (ASCII 32 - 126). Replace * all others with 0xFFFD (UNICODE replacement character). */ for (int i = 0; i < reasonBuffer.length(); i++) { char c = reasonBuffer.charAt(i); if ((c >= 32) && (c <= 126)) { continue; } reasonBuffer.setCharAt(i, '\uFFFD'); } throw new IOException( "Peer sent DISCONNECT message (reason code " + reason_code + "): " + reasonBuffer.toString()); } /* * Is it a KEX Packet? */ if ((type == Packets.SSH_MSG_KEXINIT) || (type == Packets.SSH_MSG_NEWKEYS) || ((type >= 30) && (type <= 49))) { km.handleMessage(msg, msglen); continue; } MessageHandler mh = null; for (int i = 0; i < messageHandlers.size(); i++) { HandlerEntry he = messageHandlers.get(i); if ((he.low <= type) && (type <= he.high)) { mh = he.mh; break; } } if (mh == null) { throw new IOException("Unexpected SSH message (type " + type + ")"); } mh.handleMessage(msg, msglen); } }
public void initialize( String identification, CryptoWishList cwl, ServerHostKeyVerifier verifier, DHGexParameters dhgex, int connectTimeout, SecureRandom rnd, ProxyData proxyData) throws IOException { /* First, establish the TCP connection to the SSH-2 server */ establishConnection(proxyData, 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 = new ClientServerHello(identification, sock.getInputStream(), sock.getOutputStream()); tc = new TransportConnection(sock.getInputStream(), sock.getOutputStream(), rnd); km = new KexManager(this, csh, cwl, hostname, port, verifier, rnd); km.initiateKEX(cwl, dhgex); receiveThread = new Thread( new Runnable() { public void run() { try { receiveLoop(); } catch (IOException e) { close(e, false); log.warning("Receive thread: error in receiveLoop: " + e.getMessage()); } if (log.isDebugEnabled()) { log.debug("Receive thread: back from receiveLoop"); } /* Tell all handlers that it is time to say goodbye */ if (km != null) { try { km.handleMessage(null, 0); } catch (IOException ignored) { } } for (HandlerEntry he : messageHandlers) { try { he.mh.handleMessage(null, 0); } catch (Exception ignore) { } } } }); receiveThread.setDaemon(true); receiveThread.start(); }
public void forceKeyExchange(CryptoWishList cwl, DHGexParameters dhgex) throws IOException { km.initiateKEX(cwl, dhgex); }
public ConnectionInfo getConnectionInfo(int kexNumber) throws IOException { return km.getOrWaitForConnectionInfo(kexNumber); }