in sshd-core/src/main/java/org/apache/sshd/client/auth/pubkey/UserAuthPublicKey.java [123:259]
protected boolean sendAuthDataRequest(ClientSession session, String service) throws Exception {
boolean debugEnabled = log.isDebugEnabled();
String currentAlgorithm = null;
if (current == null) {
// Just to be safe. (Paranoia)
currentAlgorithms.clear();
chosenAlgorithm = null;
} else if (!currentAlgorithms.isEmpty()) {
currentAlgorithm = currentAlgorithms.poll();
if (chosenAlgorithm != null) {
Set<String> knownServerAlgorithms = session.getAttribute(
DefaultClientKexExtensionHandler.SERVER_ALGORITHMS);
if (knownServerAlgorithms != null
&& knownServerAlgorithms.contains(chosenAlgorithm)) {
// We've tried key 'current' with 'chosenAlgorithm', but it
// failed. However, the server had told us it supported
// 'chosenAlgorithm'. Thus it makes no sense to continue
// with this key and other signature algorithms. Skip to the
// next key, if any.
if (log.isDebugEnabled()) {
log.debug(
"sendAuthDataRequest({})[{}] server rejected publickey authentication with known signature algorithm {}",
session, service, chosenAlgorithm);
}
currentAlgorithm = null;
}
}
}
PublicKeyAuthenticationReporter reporter = session.getPublicKeyAuthenticationReporter();
KeyPair keyPair;
PublicKey pubKey;
do {
if (currentAlgorithm == null) {
try {
current = resolveAttemptedPublicKeyIdentity(session, service, reporter);
} catch (Error e) {
warn("sendAuthDataRequest({})[{}] failed ({}) to get next key: {}", session, service,
e.getClass().getSimpleName(), e.getMessage(), e);
throw new RuntimeSshException(e);
}
currentAlgorithms.clear();
chosenAlgorithm = null;
if (current == null) {
if (debugEnabled) {
log.debug("resolveAttemptedPublicKeyIdentity({})[{}] no more keys to send", session, service);
}
if (reporter != null) {
reporter.signalAuthenticationExhausted(session, service);
}
return false;
}
}
if (log.isTraceEnabled()) {
log.trace("sendAuthDataRequest({})[{}] current key details: {}", session, service, current);
}
try {
keyPair = current.getKeyIdentity();
} catch (Error e) {
warn("sendAuthDataRequest({})[{}] failed ({}) to retrieve key identity: {}",
session, service, e.getClass().getSimpleName(), e.getMessage(), e);
throw new RuntimeSshException(e);
}
pubKey = keyPair.getPublic();
if (currentAlgorithm == null) {
String keyType = KeyUtils.getKeyType(pubKey);
Set<String> aliases = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
aliases.addAll(KeyUtils.getAllEquivalentKeyTypes(keyType));
aliases.add(keyType);
List<NamedFactory<Signature>> existingFactories = null;
if (current instanceof SignatureFactoriesHolder) {
existingFactories = ((SignatureFactoriesHolder) current).getSignatureFactories();
}
if (GenericUtils.isEmpty(existingFactories)) {
existingFactories = getSignatureFactories();
}
if (GenericUtils.isEmpty(existingFactories)) {
existingFactories = session.getSignatureFactories();
}
if (existingFactories != null) {
// Select the factories by name and in order
existingFactories.forEach(f -> {
if (aliases.contains(f.getName())) {
currentAlgorithms.add(f.getName());
}
});
}
currentAlgorithm = currentAlgorithms.poll();
if (GenericUtils.isEmpty(currentAlgorithm)) {
currentAlgorithm = getDefaultSignatureAlgorithm(session, service, current, keyPair, keyType);
if (GenericUtils.isEmpty(currentAlgorithm)) {
currentAlgorithm = null;
if (debugEnabled) {
log.debug("sendAuthDataRequest({})[{}] skipping {} key {}; no signature algorithm", session,
service, keyType, KeyUtils.getFingerPrint(pubKey));
}
if (reporter != null) {
reporter.signalIdentitySkipped(session, service, keyPair);
}
}
}
}
} while (currentAlgorithm == null);
String name = getName();
Integer hostBoundPubKeyVersion = session.getAttribute(DefaultClientKexExtensionHandler.HOSTBOUND_AUTHENTICATION);
boolean doHostBoundAuth = hostBoundPubKeyVersion != null && hostBoundPubKeyVersion.intValue() == 0;
if (doHostBoundAuth) {
name = HostBoundPubkeyAuthentication.AUTH_NAME;
}
if (debugEnabled) {
log.debug("sendAuthDataRequest({})[{}] send SSH_MSG_USERAUTH_REQUEST request {} type={} - fingerprint={}",
session, service, name, currentAlgorithm, KeyUtils.getFingerPrint(pubKey));
}
if (reporter != null) {
reporter.signalAuthenticationAttempt(session, service, keyPair, currentAlgorithm);
}
chosenAlgorithm = currentAlgorithm;
Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_REQUEST);
buffer.putString(session.getUsername());
buffer.putString(service);
buffer.putString(name);
buffer.putBoolean(false);
buffer.putString(currentAlgorithm);
buffer.putPublicKey(pubKey);
if (doHostBoundAuth) {
buffer.putPublicKey(session.getServerKey());
}
setCancellable(true);
session.writePacket(buffer);
return true;
}