/** * Checks the internal hostkey database for the given hostkey. If no matching key can be found, * then the hostname is resolved to an IP address and the search is repeated using that IP * address. * * @param hostname the server's hostname, will be matched with all hostname patterns * @param serverHostKeyAlgorithm type of hostkey, either <code>ssh-rsa</code> or <code>ssh-dss * </code> * @param serverHostKey the key blob * @return * <ul> * <li><code>HOSTKEY_IS_OK</code>: the given hostkey matches an entry for the given hostname * <li><code>HOSTKEY_IS_NEW</code>: no entries found for this hostname and this type of * hostkey * <li><code>HOSTKEY_HAS_CHANGED</code>: hostname is known, but with another key of the same * type (man-in-the-middle attack?) * </ul> * * @throws IOException if the supplied key blob cannot be parsed or does not match the given * hostkey type. */ public int verifyHostkey(String hostname, String serverHostKeyAlgorithm, byte[] serverHostKey) throws IOException { Object remoteKey = null; if ("ssh-rsa".equals(serverHostKeyAlgorithm)) { remoteKey = RSASHA1Verify.decodeSSHRSAPublicKey(serverHostKey); } else if ("ssh-dss".equals(serverHostKeyAlgorithm)) { remoteKey = DSASHA1Verify.decodeSSHDSAPublicKey(serverHostKey); } else throw new IllegalArgumentException("Unknown hostkey type " + serverHostKeyAlgorithm); int result = checkKey(hostname, remoteKey); if (result == HOSTKEY_IS_OK) return result; InetAddress[] ipAdresses = null; try { ipAdresses = InetAddress.getAllByName(hostname); } catch (UnknownHostException e) { return result; } for (int i = 0; i < ipAdresses.length; i++) { int newresult = checkKey(ipAdresses[i].getHostAddress(), remoteKey); if (newresult == HOSTKEY_IS_OK) return newresult; if (newresult == HOSTKEY_HAS_CHANGED) result = HOSTKEY_HAS_CHANGED; } return result; }
private boolean verifySignature(byte[] sig, byte[] hostkey) throws IOException { if (kxs.np.server_host_key_algo.equals("ssh-rsa")) { RSASignature rs = RSASHA1Verify.decodeSSHRSASignature(sig); RSAPublicKey rpk = RSASHA1Verify.decodeSSHRSAPublicKey(hostkey); log.log(50, "Verifying ssh-rsa signature"); return RSASHA1Verify.verifySignature(kxs.H, rs, rpk); } if (kxs.np.server_host_key_algo.equals("ssh-dss")) { DSASignature ds = DSASHA1Verify.decodeSSHDSASignature(sig); DSAPublicKey dpk = DSASHA1Verify.decodeSSHDSAPublicKey(hostkey); log.log(50, "Verifying ssh-dss signature"); return DSASHA1Verify.verifySignature(kxs.H, ds, dpk); } throw new IOException( "Unknown server host key algorithm '" + kxs.np.server_host_key_algo + "'"); }
/** * Adds a single public key entry to the database. Note: this will NOT add the public key to any * physical file (e.g., "~/.ssh/known_hosts") - use <code>addHostkeyToFile()</code> for that * purpose. This method is designed to be used in a {@link ServerHostKeyVerifier}. * * @param hostnames a list of hostname patterns - at least one most be specified. Check out the * OpenSSH sshd man page for a description of the pattern matching algorithm. * @param serverHostKeyAlgorithm as passed to the {@link ServerHostKeyVerifier}. * @param serverHostKey as passed to the {@link ServerHostKeyVerifier}. * @throws IOException */ public void addHostkey(String hostnames[], String serverHostKeyAlgorithm, byte[] serverHostKey) throws IOException { if (hostnames == null) throw new IllegalArgumentException("hostnames may not be null"); if ("ssh-rsa".equals(serverHostKeyAlgorithm)) { RSAPublicKey rpk = RSASHA1Verify.decodeSSHRSAPublicKey(serverHostKey); synchronized (publicKeys) { publicKeys.add(new KnownHostsEntry(hostnames, rpk)); } } else if ("ssh-dss".equals(serverHostKeyAlgorithm)) { DSAPublicKey dpk = DSASHA1Verify.decodeSSHDSAPublicKey(serverHostKey); synchronized (publicKeys) { publicKeys.add(new KnownHostsEntry(hostnames, dpk)); } } else throw new IOException("Unknwon host key type (" + serverHostKeyAlgorithm + ")"); }