protected boolean sendAuthDataRequest()

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;
    }