📄 ssh2transport.java
字号:
} if (!equals) { disconnectInternal(SSH2.DISCONNECT_CONNECTION_LOST, "Server host key changed", "", false); } } } private void transportTransmitLoop() { isTxUp = true; tpLog.debug("SSH2Transport", "transportTransmitLoop", "starting"); try { SSH2TransportPDU pdu; while((pdu = (SSH2TransportPDU)txQueue.getFirst()) != null) { if(DEBUG_ALL_TX) tpLog.debug2("SSH2Transport", "transportTransmitLoop", "sending message of type: " + SSH2.msgTypeString(pdu.pktType), pdu.getData(), pdu.getPayloadOffset(), pdu.getPayloadLength()); txNumPacketsSinceKEX++; txNumBytesSinceKEX += pdu.getPayloadLength(); // Note, we don't use transmitInternal since we don't want to // loop over the exception handler here // pdu.writeTo(tpOut, txSeqNum++, txContext, tpRand); activity = true; // Initiate rekey if needed if (txNumPacketsSinceKEX >= PACKETS_BEFORE_REKEY || txNumBytesSinceKEX >= BYTES_BEFORE_REKEY) { startKeyExchange(); } } } catch (ShortBufferException e) { String msg = "Internal error/bug: " + e.getMessage(); tpLog.error("SSH2Transport", "transportTransmitLoop", msg); disconnectInternal(SSH2.DISCONNECT_CONNECTION_LOST, msg, /* !!! TODO: languageTag, from ourPrefs? */ "", false); } catch (IOException e) { String msg = "I/O error: " + e.getMessage(); if(isTxUp) { tpLog.error("SSH2Transport", "transportTransmitLoop", msg); } disconnectInternal(SSH2.DISCONNECT_CONNECTION_LOST, msg, /* !!! TODO: languageTag, from ourPrefs? */ "", false); } catch (SSH2CompressionException e) { String msg = "Internal error/bug: " + e.getMessage(); tpLog.error("SSH2Transport", "transportTransmitLoop", msg); disconnectInternal(SSH2.DISCONNECT_COMPRESSION_ERROR, msg, /* !!! TODO: languageTag, from ourPrefs? */ "", false); } catch (SSH2Exception e) { String msg = "Key reexchange failed: " + e.getMessage(); tpLog.error("SSH2Transport", "transportTransmitLoop", msg); disconnectInternal(SSH2.DISCONNECT_COMPRESSION_ERROR, msg, /* !!! TODO: languageTag, from ourPrefs? */ "", false); } finally { shutdownTx(); kexComplete(false); authTerminate(); } tpLog.debug("SSH2Transport", "transportTransmitLoop", "stopping"); } private void transportReceiveLoop() { isRxUp = true; tpLog.debug("SSH2Transport", "transportReceiveLoop", "starting"); try { while(isRxUp) { processRxPacket(receiveInternal()); } } catch (ShortBufferException e) { String msg = "Internal error/bug: " + e.getMessage(); disconnectInternal(SSH2.DISCONNECT_CONNECTION_LOST, msg, /* !!! TODO: languageTag, from ourPrefs? */ "", false); } catch (SSH2MacCheckException e) { String msg = e.getMessage(); disconnectInternal(SSH2.DISCONNECT_MAC_ERROR, msg, /* !!! TODO: languageTag, from ourPrefs? */ "", false); } catch (SSH2CompressionException e) { String msg = e.getMessage(); disconnectInternal(SSH2.DISCONNECT_COMPRESSION_ERROR, msg, /* !!! TODO: languageTag, from ourPrefs? */ "", false); } catch (SSH2SignatureException e) { String msg = e.getMessage(); disconnectInternal(SSH2.DISCONNECT_KEY_EXCHANGE_FAILED, msg, /* !!! TODO: languageTag, from ourPrefs? */ "", false); } catch (SSH2Exception e) { if(isRxUp) { String msg = e.getMessage(); if(e.getRootCause() != null) { msg += " (rootcause: " + e.getRootCause() + ")"; } disconnectInternal(SSH2.DISCONNECT_PROTOCOL_ERROR, msg, /* !!! TODO: languageTag, from ourPrefs? */ "", false); } } catch (IOException e) { if(isRxUp) { String msg = "I/O error: " + e.getMessage(); disconnectInternal(SSH2.DISCONNECT_CONNECTION_LOST, msg, /* !!! TODO: languageTag, from ourPrefs? */ "", false); } } finally { shutdownRx(); kexComplete(false); authTerminate(); } tpLog.debug("SSH2Transport", "transportReceiveLoop", "stopping"); } private void processRxPacket(SSH2TransportPDU pdu) throws ShortBufferException, IOException, SSH2Exception { rxNumPacketsSinceKEX++; rxNumBytesSinceKEX += pdu.getPayloadLength(); switch(pdu.pktType) { case SSH2.MSG_DISCONNECT: { int reason = pdu.readInt(); String description = pdu.readJavaString(); String languageTag = pdu.readJavaString(); disconnectInternal(reason, description, languageTag, true); break; } case SSH2.MSG_IGNORE: byte[] data = pdu.readString(); eventHandler.msgIgnore(this, data); break; case SSH2.MSG_UNIMPLEMENTED: int rejectedSeqNum = pdu.readInt(); eventHandler.msgUnimplemented(this, rejectedSeqNum); break; case SSH2.MSG_DEBUG: { boolean alwaysDisplay = pdu.readBoolean(); String message = pdu.readJavaString(); String languageTag = pdu.readJavaString(); eventHandler.msgDebug(this, alwaysDisplay, message, languageTag); break; } case SSH2.MSG_SERVICE_REQUEST: break; case SSH2.MSG_SERVICE_ACCEPT: userAuth.processMessage(pdu); pdu = null; break; case SSH2.MSG_KEXINIT: processKEXINIT(pdu); pdu = null; break; case SSH2.MSG_NEWKEYS: if(!keyExchangeInProgress) throw new SSH2CorruptPacketException( "Received MSG_NEWKEYS while not doing key exchange"); changeKeys(false); kexComplete(true); break; case SSH2.FIRST_KEX_PACKET: case 31: case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39: case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case SSH2.LAST_KEX_PACKET: if(!keyExchangeInProgress) throw new SSH2CorruptPacketException( "Received KEX packet while not doing key exchange"); keyExchanger.processKEXMethodPDU(pdu); break; case SSH2.MSG_USERAUTH_REQUEST: case SSH2.MSG_USERAUTH_FAILURE: case SSH2.MSG_USERAUTH_SUCCESS: case SSH2.MSG_USERAUTH_BANNER: case SSH2.FIRST_USERAUTH_METHOD_PACKET: case 61: case 62: case 63: case 64: case 65: case 66: case 67: case 68: case 69: case 70: case 71: case 72: case 73: case 74: case 75: case 76: case 77: case 78: case SSH2.LAST_USERAUTH_METHOD_PACKET: userAuth.processMessage(pdu); pdu = null; break; case SSH2.MSG_GLOBAL_REQUEST: case SSH2.MSG_REQUEST_SUCCESS: case SSH2.MSG_REQUEST_FAILURE: case SSH2.MSG_CHANNEL_OPEN: connection.processGlobalMessage(pdu); pdu = null; break; case SSH2.MSG_CHANNEL_DATA: case SSH2.MSG_CHANNEL_EXTENDED_DATA: case SSH2.MSG_CHANNEL_OPEN_CONFIRMATION: case SSH2.MSG_CHANNEL_OPEN_FAILURE: case SSH2.MSG_CHANNEL_WINDOW_ADJUST: case SSH2.MSG_CHANNEL_EOF: case SSH2.MSG_CHANNEL_CLOSE: case SSH2.MSG_CHANNEL_REQUEST: case SSH2.MSG_CHANNEL_SUCCESS: case SSH2.MSG_CHANNEL_FAILURE: connection.processChannelMessage(pdu); pdu = null; break; default: tpLog.warning("SSH2Transport", "received packet of unknown type: " + pdu.pktType); SSH2TransportPDU pduUnimp = SSH2TransportPDU.createOutgoingPacket(SSH2.MSG_UNIMPLEMENTED); pduUnimp.writeInt(rxSeqNum); if(keyExchangeInProgress) { transmitInternal(pduUnimp); } else { transmit(pduUnimp); } eventHandler.peerSentUnknownMessage(this, pdu.pktType); break; } if(pdu != null) { pdu.release(); } // Initiate rekey if needed if (rxNumPacketsSinceKEX >= PACKETS_BEFORE_REKEY || rxNumBytesSinceKEX >= BYTES_BEFORE_REKEY) { startKeyExchange(); } } /** * Receives a PDU directly from the <code>InputStream</code> from the peer * without checking if we are connected. This method can only be used when * the receiver is not running. * * @return the PDU which was read * * @exception SSH2Exception * @exception ShortBufferException * @exception IOException */ public SSH2TransportPDU receiveInternal() throws SSH2Exception, ShortBufferException, IOException { SSH2TransportPDU pdu = SSH2TransportPDU.createIncomingPacket(); pdu.readFrom(tpIn, rxSeqNum++, rxContext); activity = true; if(DEBUG_ALL_RX) tpLog.debug2("SSH2Transport", "receiveInternal", "received message of type: " + SSH2.msgTypeString(pdu.pktType), pdu.getData(), pdu.getPayloadOffset(), pdu.getPayloadLength()); return pdu; } private void shutdownTx() { if(isTxUp) { isTxUp = false; try { tpOut.close(); } catch (IOException e) { /* don't care */ } txQueue.disable(); txQueue.setBlocking(false); } } private void shutdownRx() { if(isRxUp) { isRxUp = false; try { tpIn.close(); } catch (IOException e) { /* don't care */ } } } private synchronized void changeKeys(boolean transmitter) throws SSH2Exception { try { String cipherName = ourPrefs.getAgreedCipher(transmitter, weAreAServer); String macName = ourPrefs.getAgreedMac(transmitter, weAreAServer); String compName = ourPrefs.getAgreedCompression(transmitter, weAreAServer); int cKeyLen = ourPrefs.getCipherKeyLen(cipherName); int mKeyLen = ourPrefs.getMacKeyLen(macName); tpLog.info("SSH2Transport", "new " + (transmitter ? "transmitter" : "receiver") + " context (" + cipherName + "," + macName + "," + compName + ")"); cipherName = ourPrefs.ssh2ToJCECipher(cipherName); macName = ourPrefs.ssh2ToJCEMac(macName); TranceiverContext ctx = SSH2TransportPDU.createTranceiverContext(cipherName, macName, compName); initTranceiverContext(ctx, cKeyLen, (incompatibleHMACKeyLength ? 16 : mKeyLen), transmitter); if(transmitter) { txContext = ctx; } else { rxContext = ctx; } } catch (Exception e) { throw new SSH2FatalException("Error in changeKeys", e); } } private void initTranceiverContext(TranceiverContext context, int ckLen, int mkLen, boolean transmitter) throws SSH2Exception { byte[] iv, cKey, mKey; char[] ids; if(weAreAServer ^ transmitter) { ids = new char[] { 'A', 'C', 'E' }; } else { ids = new char[] { 'B', 'D', 'F' }; } iv = deriveKey(ids[0], context.getCipherBlockSize()); cKey = deriveKey(ids[1], ckLen); mKey = deriveKey(ids[2], mkLen); int compressionLevel = 6; try { compressionLevel = Integer.parseInt(ourPrefs.getPreference(SSH2Preferences. COMP_LEVEL)); } catch (Exception e) { compressionLevel = 6; } context.init(cKey, iv, mKey, compressionLevel, transmitter); } byte[] deriveKey(char id, int len) { byte[] key = new byte[len]; byte[] sharedSecret_K = keyExchanger.getSharedSecret_K(); byte[] exchangeHash_H = keyExchanger.getExchangeHash_H(); if(sessionId == null) { sessionId = new byte[exchangeHash_H.length]; System.arraycopy(exchangeHash_H, 0, sessionId, 0, sessionId.length); } MessageDigest sha1 = keyExchanger.getExchangeHashAlgorithm(); sha1.update(sharedSecret_K); sha1.update(exchangeHash_H); sha1.update(new byte[] { (byte)id }); sha1.update(sessionId); byte[] material = sha1.digest(); int curLen = material.length; System.arraycopy(material, 0, key, 0, (curLen < len ? curLen : len)); while(curLen < len) { sha1.reset(); sha1.update(sharedSecret_K); sha1.update(exchangeHash_H); sha1.update(key, 0, curLen); material = sha1.digest(); if(len - curLen > material.length) System.arraycopy(material, 0, key, curLen, material.length); else System.arraycopy(material, 0, key, curLen, len - curLen); curLen += material.length; } tpLog.debug2("SSH2Transport", "deriveKey", "key id " + id, key); return key; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -