⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssh2transport.java

📁 一个非常好的ssh客户端实现
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
			      "disconnectInternal",			      "error writing disconnect msg: " + e);	    }	}	disableKeepAlive();	shutdownRx();	shutdownTx();	if(connection != null) {	    connection.terminate();	}	tpLog.close();    }    private void negotiateVersion() throws IOException, SSH2Exception {	String idString;	String ourVersion =	    SSH2.getVersionId(ourPrefs.getPreference(SSH2Preferences.						     PKG_VERSION));	if(weAreAServer) {	    serverVersion = ourVersion;	    idString =  serverVersion + "\r\n";	    tpOut.write(idString.getBytes());	    tpOut.flush();	    clientVersion = idString;	    tpLog.notice("SSH2Transport", "peer's version is '" +			 clientVersion + "'");	} else {	    clientVersion = ourVersion;	    idString =  clientVersion + "\r\n";	    tpOut.write(idString.getBytes());	    tpOut.flush();	    while(!(idString = readIdString()).startsWith("SSH-")) {		eventHandler.gotConnectInfoText(this, idString);	    }	    serverVersion = idString;	    tpLog.notice("SSH2Transport", "peer's version is '" +			 serverVersion + "'");	}	checkPeerVersion(clientVersion, serverVersion);    }    private void checkPeerVersion(String clientVersion, String serverVersion)	throws SSH2Exception    {	String cliPackage = extractPackageVersion(clientVersion);	String srvPackage = extractPackageVersion(serverVersion);	int cliMajor = extractMajor(clientVersion);	int cliMinor = extractMinor(clientVersion);	int srvMajor = extractMajor(serverVersion);	int srvMinor = extractMinor(serverVersion);	if(weAreAServer) {	    eventHandler.gotPeerVersion(this, clientVersion,					cliMajor, cliMinor, cliPackage);	} else {	    eventHandler.gotPeerVersion(this, serverVersion,					srvMajor, srvMinor, srvPackage);	}	if(cliMajor != srvMajor && !(srvMajor == 1 && srvMinor == 99)) {	    String msg;	    if(weAreAServer) {		msg = "Can't serve a client with version " + clientVersion;	    } else {		msg = "Can't connect to a server with version " + serverVersion;	    }	    throw new SSH2FatalException(msg);	}	String peerPackage = (weAreAServer ? cliPackage : srvPackage);	if(peerPackage.startsWith("2.0.7 ") ||	   peerPackage.startsWith("2.0.8 ") ||	   peerPackage.startsWith("2.0.9 ")) {	    throw new SSH2FatalException("Peer's version is too old: " + peerPackage);	}	incompatibleServiceAccept = peerPackage.startsWith("2.0.11 ") ||	    peerPackage.startsWith("2.0.12 ") ||	    peerPackage.startsWith("2.0.13 ");	incompatiblePublicKeyAuth = incompatibleServiceAccept;	incompatibleChannelOpenFail = incompatibleServiceAccept;	incompatibleSignature = peerPackage.startsWith("2.1.0 SSH") ||	    (peerPackage.startsWith("2.1.0") &&	     peerPackage.indexOf("F-SECURE") != -1) ||	    incompatibleServiceAccept;	incompatibleHMACKeyLength = incompatibleSignature ||	    peerPackage.startsWith("2.2.0 SSH") ||	    peerPackage.startsWith("2.3.0 SSH") ||	    ((peerPackage.startsWith("2.2.0") ||	      peerPackage.startsWith("2.3.0")) &&	     peerPackage.indexOf("F-SECURE") != -1);	incompatibleBuggyChannelClose = incompatibleHMACKeyLength ||	    peerPackage.startsWith("2.4.0 SSH");	incompatiblePublicKeyUserId = incompatibleSignature ||	    peerPackage.startsWith("OpenSSH_2.0") ||	    peerPackage.startsWith("OpenSSH_2.1") ||	    peerPackage.startsWith("OpenSSH_2.2");	incompatibleRijndael = peerPackage.startsWith("OpenSSH_2.5.1p1") ||	    peerPackage.startsWith("OpenSSH_2.5.0") ||	    peerPackage.startsWith("OpenSSH_2.3");	incompatibleCantReKey = incompatiblePublicKeyUserId ||	    peerPackage.startsWith("OpenSSH_2.3")   ||	    peerPackage.startsWith("OpenSSH_2.5.1") ||	    peerPackage.startsWith("OpenSSH_2.5.2") ||	    !("true".equals(ourPrefs.			    getPreference(SSH2Preferences.QUEUED_RX_CHAN)));	if(incompatibleServiceAccept) {	    tpLog.notice("SSH2Transport",			 "enabling draft incompatible SERVICE_ACCEPT");	    tpLog.notice("SSH2Transport",			 "enabling draft incompatible publickey method");	    tpLog.notice("SSH2Transport",			 "enabling draft incompatible CHANNEL_OPEN_FAILURE");	}	if(incompatibleSignature) {	    tpLog.notice("SSH2Transport",			 "enabling draft incompatible signature format");	}	if(incompatibleHMACKeyLength) {	    tpLog.notice("SSH2Transport",			 "enabling rfc incompatible hmac key length");	}	if(incompatiblePublicKeyUserId) {	    tpLog.notice("SSH2Transport",			 "enabling draft incompatible session id for signature");	}	if(incompatibleRijndael) {	    tpLog.notice("SSH2Transport",			 "disabling aes/rijndael cipher, peer has buggy implementation");	}	if(incompatibleCantReKey) {	    tpLog.notice("SSH2Transport",			 "disabling key re-exchange, not implemented in peer");	}    }    /**     * Extracts the major version from a version string (as defined in the     * protocol spec.)     *     * @param the full version string     *     * @return the major version number     *     * @exception SSH2Exception if there is a format error     */    public static int extractMajor(String versionStr) throws SSH2Exception {	try {	    int r = versionStr.indexOf('.', 4);	    return Integer.parseInt(versionStr.substring(4, r));	} catch (NumberFormatException e) {	    throw new SSH2FatalException("Corrupt version string: " +					 versionStr);	}    }    /**     * Extracts the minor version from a version string (as defined in the     * protocol spec.)     *     * @param the full version string     *     * @return the minor version number     *     * @exception SSH2Exception if there is a format error     */    public static int extractMinor(String versionStr) throws SSH2Exception {	try {	    int l = versionStr.indexOf('.', 4) + 1;	    int r = versionStr.indexOf('-', l);	    return Integer.parseInt(versionStr.substring(l, r));	} catch (NumberFormatException e) {	    throw new SSH2FatalException("Corrupt version string: " +					 versionStr);	}    }    /**     * Extracts the package version (defined as softwareversion and comments in     * the protocol spec.) from a version string.     *     * @param the full version string     *     * @return the package version (i.e. software version and comments)     *     * @exception SSH2Exception if there is a format error     */    public static String extractPackageVersion(String versionStr)	throws SSH2Exception    {	try {	    int i = versionStr.indexOf('-', 4) + 1;	    return versionStr.substring(i);	} catch (Exception e) {	    throw new SSH2FatalException("Corrupt version string: " +					 versionStr);	}    }    private String readIdString() throws IOException, SSH2Exception {	byte[] buf = new byte[256];	int    len = 0;	int    c;	while(true) {	    c = tpIn.read();	    if(c == -1) {		throw new SSH2EOFException("Server closed connection before sending identification");	    }	    if(c == '\r')	       continue;            if(c != '\n') {                if (len >= buf.length) {                    throw new SSH2FatalException("Too long id string: " +                                                 new String(buf));                }                buf[len++] = (byte)c;            } else {		return new String(buf, 0, len);            }	}    }    private void sendKEXINIT() throws SSH2Exception {	SSH2TransportPDU pdu =	    SSH2TransportPDU.createOutgoingPacket(SSH2.MSG_KEXINIT);	byte[] cookie = new byte[16];	tpRand.nextBytes(cookie);	pdu.writeRaw(cookie);	ourPrefs.writeTo(pdu);	pdu.writeBoolean(false);	pdu.writeInt(0);	if(weAreAServer) {	    serverKEXINITPkt = pdu.makeCopy();	} else {	    clientKEXINITPkt = pdu.makeCopy();	}	transmitInternal(pdu);	eventHandler.kexStart(this);    }    private void processKEXINIT(SSH2TransportPDU pdu) throws SSH2Exception {	startKeyExchange();	if(weAreAServer) {	    clientKEXINITPkt = pdu;	} else {	    serverKEXINITPkt = pdu;	}	pdu.readRaw(16); // Cookie, we don't need it	peerPrefs = new SSH2Preferences();	peerPrefs.readFrom(pdu);	boolean firstKEXFollows = pdu.readBoolean();	pdu.readInt(); // Reserved int, we don't need it	tpLog.info("SSH2Transport", "peer kex algorithms: " +	    peerPrefs.getPreference(SSH2Preferences.KEX_ALGORITHMS));	tpLog.info("SSH2Transport", "peer host key algorithms: " +	    peerPrefs.getPreference(SSH2Preferences.HOST_KEY_ALG));	tpLog.info("SSH2Transport", "peer enc. alg. cli2srv: " +	    peerPrefs.getPreference(SSH2Preferences.CIPHERS_C2S));	tpLog.info("SSH2Transport", "peer enc. alg. srv2cli: " +	    peerPrefs.getPreference(SSH2Preferences.CIPHERS_S2C));	tpLog.info("SSH2Transport", "peer mac alg. cli2srv: " +	    peerPrefs.getPreference(SSH2Preferences.MACS_C2S));	tpLog.info("SSH2Transport", "peer mac alg. srv2cli: " +	    peerPrefs.getPreference(SSH2Preferences.MACS_S2C));	tpLog.info("SSH2Transport", "peer comp. alg. cli2srv: " +	    peerPrefs.getPreference(SSH2Preferences.COMP_C2S));	tpLog.info("SSH2Transport", "peer comp. alg. srv2cli: " +	    peerPrefs.getPreference(SSH2Preferences.COMP_S2C));	tpLog.info("SSH2Transport", "our kex algorithms: " +	    ourPrefs.getPreference(SSH2Preferences.KEX_ALGORITHMS));	tpLog.info("SSH2Transport", "our host key algorithms: " +	    ourPrefs.getPreference(SSH2Preferences.HOST_KEY_ALG));	tpLog.info("SSH2Transport", "our enc. alg. cli2srv: " +	    ourPrefs.getPreference(SSH2Preferences.CIPHERS_C2S));	tpLog.info("SSH2Transport", "our enc. alg. srv2cli: " +	    ourPrefs.getPreference(SSH2Preferences.CIPHERS_S2C));	tpLog.info("SSH2Transport", "our mac alg. cli2srv: " +	    ourPrefs.getPreference(SSH2Preferences.MACS_C2S));	tpLog.info("SSH2Transport", "our mac alg. srv2cli: " +	    ourPrefs.getPreference(SSH2Preferences.MACS_S2C));	tpLog.info("SSH2Transport", "our comp. alg. cli2srv: " +	    ourPrefs.getPreference(SSH2Preferences.COMP_C2S));	tpLog.info("SSH2Transport", "our comp. alg. srv2cli: " +	    ourPrefs.getPreference(SSH2Preferences.COMP_S2C));	keyExchanger = ourPrefs.selectKEXAlgorithm(peerPrefs, weAreAServer);	tpLog.info("SSH2Transport", "KEX algorithm chosen: " +		     ourPrefs.getAgreedKEXAlgorithm());	tpLog.info("SSH2Transport", "same KEX guessed? " +		   ourPrefs.sameKEXGuess());	tpLog.info("SSH2Transport", "first KEX follows? " + firstKEXFollows);	if(!ourPrefs.canAgree(peerPrefs, weAreAServer)) {	    String errType = ourPrefs.getDisagreeType();            String errtxt  = "No match in kex params '" +  errType +		"', our's: " + ourPrefs.getPreference(errType) +		", peer's: " + peerPrefs.getPreference(errType);            throw new SSH2FatalException(errtxt);	}	if(firstKEXFollows && !ourPrefs.sameKEXGuess()) {	    // Discard next packet which is the incorrectly guessed KEX packet	    //	    try {		receiveInternal();	    } catch (IOException e) {		throw new SSH2FatalException("I/O error when reading guessed " +					     "packet", e);	    } catch (ShortBufferException e) {		throw new SSH2FatalException("Internal error/bug: " +					     e.getMessage());	    }	    tpLog.notice("SSH2Transport", "first KEX packet discarded, " +			 "wrong initial guess");	}	eventHandler.kexAgreed(this, ourPrefs, peerPrefs);	keyExchanger.init(this);    }    private void removeRijndael() {	boolean removedAES = false;	String l1, l2;	l1 = ourPrefs.getPreference(SSH2Preferences.CIPHERS_C2S);	l2 = ourPrefs.getPreference(SSH2Preferences.CIPHERS_S2C);	int l1l = l1.length();	int l2l = l2.length();	l1 = SSH2ListUtil.removeAllPrefixFromList(l1, "aes");	l1 = SSH2ListUtil.removeAllPrefixFromList(l1, "rijndael");	l2 = SSH2ListUtil.removeAllPrefixFromList(l2, "aes");	l2 = SSH2ListUtil.removeAllPrefixFromList(l2, "rijndael");	if(l1.length() != l1l) {	    ourPrefs.setPreference(SSH2Preferences.CIPHERS_C2S,				    l1);	    removedAES = true;	}	if(l2.length() != l2l) {	    ourPrefs.setPreference(SSH2Preferences.CIPHERS_S2C,				    l2);	    removedAES = true;	}	if(removedAES) {	    tpLog.warning("SSH2Transport",			  "removed AES cipher from our preferences" +			  " due to bug in peer's implementation");	}    }    /**     * Sends the NEWKEYS paket type and changes the transmitter keys according     * to the current prefs (as negotiated before). Typically used from a     * subclass to <code>SSH2KeyExchanger</code>.     *     * @exception SSH2Exception if an error occurs while sending the packet.     */    public void sendNewKeys() throws SSH2Exception {	SSH2TransportPDU pdu =	    SSH2TransportPDU.createOutgoingPacket(SSH2.MSG_NEWKEYS);	transmitInternal(pdu);	changeKeys(true);	txQueue.enable();    }    /**     * Authenticates the server through its host key. Typically used from a     * subclass to <code>SSH2KeyExchanger</code>.     *     * @param serverHostKey byte array containing server's host key (e.g. a     * public key blob or a certificate).     * @param serverSigH    byte array containing server's signature of the     * exchange hash which should be verified.     * @param the exchange hash     *     * @exception SSH2Exception if an error occurs     */    public void authenticateHost(byte[] serverHostKey, byte[] serverSigH,				 byte[] exchangeHash_H)	throws SSH2Exception    {	tpLog.debug2("SSH2Transport", "authenticateHost",		     "Server's public host key: ", serverHostKey);	tpLog.debug2("SSH2Transport", "authenticateHost",		     "Signature over H: ", serverSigH);	tpLog.debug2("SSH2Transport", "authenticateHost",		     "Exchange hash H", exchangeHash_H);	boolean       verified  = false;	SSH2Signature signature =	    SSH2Signature.getInstance(ourPrefs.getAgreedHostKeyAlgorithm());	signature.initVerify(serverHostKey);	signature.setIncompatibility(this);	verified = signature.verify(serverSigH, exchangeHash_H);	if(verified) {	    tpLog.info("SSH2Transport", "server's signature verified");	} else {	    String msg = "server's signature didn't verify";	    tpLog.error("SSH2Transport", "authenticateHost", msg);	    fatalDisconnect(SSH2.DISCONNECT_HOST_KEY_NOT_VERIFIABLE, msg);	    throw new SSH2FatalException(msg);	}	if (serverPublicKeyBlob == null) {	    if(!eventHandler.kexAuthenticateHost(this, signature)) {		throw new SSH2SignatureException("Host authentication failed");	    }	    serverPublicKeyBlob = signature.getPublicKeyBlob();	} else {	    byte[] blob = signature.getPublicKeyBlob();	    boolean equals = (blob.length == serverPublicKeyBlob.length);	    for (int i=0; equals && i < blob.length; i++) {		equals = (blob[i] == serverPublicKeyBlob[i]);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -