@Override public TransportException chain(Throwable t) { if (t instanceof TransportException) return (TransportException) t; else return new TransportException(t); } };
@SuppressWarnings("PMD.CompareObjectsWithEquals") private static void ensureReceivedMatchesExpected(Message got, Message expected) throws TransportException { if (got != expected) throw new TransportException(DisconnectReason.PROTOCOL_ERROR, "Was expecting " + expected); }
private static String firstMatch(List<String> a, List<String> b) throws TransportException { for (String aa : a) for (String bb : b) if (aa.equals(bb)) return aa; throw new TransportException("Unable to reach a settlement: " + a + " and " + b); }
private synchronized void ensureKexOngoing() throws TransportException { if (!isKexOngoing()) throw new TransportException(DisconnectReason.PROTOCOL_ERROR, "Key exchange packet received when key exchange was not ongoing"); }
private void checkPacketLength(int len) throws TransportException { if (len < 5 || len > MAX_PACKET_LEN) { // Check packet length validity log.error("Error decoding packet (invalid length) {}", inputBuffer.printHex()); throw new TransportException(DisconnectReason.PROTOCOL_ERROR, "invalid packet length: " + len); } }
@Override public boolean next(Message msg, SSHPacket buffer) throws GeneralSecurityException, TransportException { log.debug("Got message {}", msg); try { switch (msg) { case KEXDH_31: return parseGexGroup(buffer); case KEX_DH_GEX_REPLY: return parseGexReply(buffer); } } catch (Buffer.BufferException be) { throw new TransportException(be); } throw new TransportException("Unexpected message " + msg); }
private void gotDisconnect(SSHPacket buf) throws TransportException { try { final DisconnectReason code = DisconnectReason.fromInt(buf.readUInt32AsInt()); final String message = buf.readString(); log.info("Received SSH_MSG_DISCONNECT (reason={}, msg={})", code, message); throw new TransportException(code, message); } catch (Buffer.BufferException be) { throw new TransportException(be); } }
private void gotDebug(SSHPacket buf) throws TransportException { try { final boolean display = buf.readBoolean(); final String message = buf.readString(); log.debug("Received SSH_MSG_DEBUG (display={}) '{}'", display, message); } catch (Buffer.BufferException be) { throw new TransportException(be); } }
private void receiveServerIdent() throws IOException { final Buffer.PlainBuffer buf = new Buffer.PlainBuffer(); while ((serverID = readIdentification(buf)).isEmpty()) { int b = connInfo.in.read(); if (b == -1) { log.error("Received end of connection, but no identification received. "); throw new TransportException("Server closed connection during identification exchange"); } buf.putByte((byte) b); } }
private String readIdentification(Buffer.PlainBuffer lineBuffer) throws Buffer.BufferException, TransportException { byte[] bytes = new byte[lineBuffer.available()]; lineBuffer.readRawBytes(bytes); if (bytes.length > 255) { log.error("Incorrect identification String received, line was longer than expected: {}", new String(bytes)); log.error("Just for good measure, bytes were: {}", ByteArrayUtils.printHex(bytes, 0, bytes.length)); throw new TransportException("Incorrect identification: line too long: " + ByteArrayUtils.printHex(bytes, 0, bytes.length)); } if (bytes[bytes.length - 2] != '\r') { String ident = new String(bytes, 0, bytes.length - 1); log.warn("Server identification has bad line ending, was expecting a '\\r\\n' however got: '{}' (hex: {})", (char) (bytes[bytes.length - 2] & 0xFF), Integer.toHexString(bytes[bytes.length - 2] & 0xFF)); log.warn("Will treat the identification of this server '{}' leniently", ident); return ident; // log.error("Data received up til here was: {}", new String(bytes)); // throw new TransportException("Incorrect identification: bad line ending: " + ByteArrayUtils.toHex(bytes, 0, bytes.length)); } // Strip off the \r\n return new String(bytes, 0, bytes.length - 2); }
private int decryptLength() throws TransportException { decryptBuffer(0, cipherSize); final int len; // Read packet length try { len = inputBuffer.readUInt32AsInt(); } catch (Buffer.BufferException be) { throw new TransportException(be); } checkPacketLength(len); return len; }
/** * Got an SSH_MSG_UNIMPLEMENTED, so lets see where we're at and act accordingly. * * @param packet The 'unimplemented' packet received * @throws TransportException */ private void gotUnimplemented(SSHPacket packet) throws SSHException { long seqNum = packet.readUInt32(); log.debug("Received SSH_MSG_UNIMPLEMENTED #{}", seqNum); if (kexer.isKexOngoing()) throw new TransportException("Received SSH_MSG_UNIMPLEMENTED while exchanging keys"); getService().notifyUnimplemented(seqNum); }
private void gotServiceAccept() throws TransportException { serviceAccept.lock(); try { if (!serviceAccept.hasWaiters()) throw new TransportException(DisconnectReason.PROTOCOL_ERROR, "Got a service accept notification when none was awaited"); serviceAccept.set(); } finally { serviceAccept.unlock(); } }
private void checkMAC(final byte[] data) throws TransportException { mac.update(seq); // seq num mac.update(data, 0, packetLength + 4); // packetLength+4 = entire packet w/o mac mac.doFinal(macResult, 0); // compute // Check against the received MAC if (!ByteArrayUtils.equals(macResult, 0, data, packetLength + 4, mac.getBlockSize())) { throw new TransportException(DisconnectReason.MAC_ERROR, "MAC Error"); } }
@Override public void init(String remoteHost, int remotePort, InputStream in, OutputStream out) throws TransportException { connInfo = new ConnInfo(remoteHost, remotePort, in, out); try { if (config.isWaitForServerIdentBeforeSendingClientIdent()) { receiveServerIdent(); sendClientIdent(); } else { sendClientIdent(); receiveServerIdent(); } log.info("Server identity string: {}", serverID); } catch (IOException e) { throw new TransportException(e); } reader.start(); }
private void gotKexInit(SSHPacket buf) throws TransportException { buf.rpos(buf.rpos() - 1); final Proposal serverProposal = new Proposal(buf); negotiatedAlgs = clientProposal.negotiate(serverProposal); log.debug("Negotiated algorithms: {}", negotiatedAlgs); for(AlgorithmsVerifier v: algorithmVerifiers) { log.debug("Trying to verify algorithms with {}", v); if(!v.verify(negotiatedAlgs)) { throw new TransportException(DisconnectReason.KEY_EXCHANGE_FAILED, "Failed to verify negotiated algorithms `" + negotiatedAlgs + "`"); } } kex = Factory.Named.Util.create(transport.getConfig().getKeyExchangeFactories(), negotiatedAlgs.getKeyExchangeAlgorithm()); try { kex.init(transport, transport.getServerID(), transport.getClientID(), serverProposal.getPacket().getCompactData(), clientProposal.getPacket().getCompactData()); } catch (GeneralSecurityException e) { throw new TransportException(DisconnectReason.KEY_EXCHANGE_FAILED, e); } }
@Override public void disconnect(DisconnectReason reason, String message) { close.lock(); try { if (isRunning()) { disconnectListener.notifyDisconnect(reason, message); getService().notifyError(new TransportException(reason, "Disconnected")); sendDisconnect(reason, message); finishOff(); close.set(); } } finally { close.unlock(); } }
@Override public void handle(Message cmd, SSHPacket buf) throws UserAuthException, TransportException { if (cmd == Message.USERAUTH_60 && newPasswordProvider != null) { log.info("Received SSH_MSG_USERAUTH_PASSWD_CHANGEREQ."); try { String prompt = buf.readString(); buf.readString(); // lang-tag AccountResource resource = makeAccountResource(); char[] newPassword = newPasswordProvider.provideNewPassword(resource, prompt); SSHPacket sshPacket = super.buildReq().putBoolean(true).putSensitiveString(pwdf.reqPassword(resource)).putSensitiveString(newPassword); params.getTransport().write(sshPacket); } catch (Buffer.BufferException e) { throw new TransportException(e); } } else if (cmd == Message.USERAUTH_60) { throw new UserAuthException("Password change request received; unsupported operation (newPassword was 'null')"); } else { super.handle(cmd, buf); } }
@Override public void uncompress(Buffer from, Buffer to) throws TransportException { inflater.setNextIn(from.array()); inflater.setNextInIndex(from.rpos()); inflater.setAvailIn(from.available()); while (true) { inflater.setNextOut(tempBuf); inflater.setNextOutIndex(0); inflater.setAvailOut(BUF_SIZE); final int status = inflater.inflate(JZlib.Z_PARTIAL_FLUSH); switch (status) { case JZlib.Z_OK: to.putRawBytes(tempBuf, 0, BUF_SIZE - inflater.getAvailOut()); break; case JZlib.Z_BUF_ERROR: return; default: throw new TransportException(DisconnectReason.COMPRESSION_ERROR, "uncompress: inflate returned " + status); } } }
public Proposal(SSHPacket packet) throws TransportException { this.packet = packet; final int savedPos = packet.rpos(); packet.rpos(packet.rpos() + 17); // Skip message ID & cookie try { kex = fromCommaString(packet.readString()); sig = fromCommaString(packet.readString()); c2sCipher = fromCommaString(packet.readString()); s2cCipher = fromCommaString(packet.readString()); c2sMAC = fromCommaString(packet.readString()); s2cMAC = fromCommaString(packet.readString()); c2sComp = fromCommaString(packet.readString()); s2cComp = fromCommaString(packet.readString()); } catch (Buffer.BufferException be) { throw new TransportException(be); } packet.rpos(savedPos); }