protected Boolean doAuth()

in sshd-core/src/main/java/org/apache/sshd/server/auth/gss/UserAuthGSS.java [67:193]


    protected Boolean doAuth(Buffer buffer, boolean initial) throws Exception {
        ServerSession session = getServerSession();
        GSSAuthenticator auth = Objects.requireNonNull(session.getGSSAuthenticator(), "No GSSAuthenticator configured");
        String user = getUsername();
        boolean debugEnabled = log.isDebugEnabled();

        if (initial) {
            // Get mechanism count from buffer and look for Kerberos 5.
            int num = buffer.getInt();
            // Protect against malicious or corrupted packets
            if ((num < 0) || (num > SshConstants.SSH_REQUIRED_PAYLOAD_PACKET_LENGTH_SUPPORT)) {
                log.error("doAuth({}@{}) Illogical OID entries count: {}", user, session, num);
                throw new IndexOutOfBoundsException("Illogical OID entries count: " + num);
            }

            boolean traceEnabled = log.isTraceEnabled();
            for (int i = 1; i <= num; i++) {
                Oid oid = new Oid(buffer.getBytes());
                if (!oid.equals(KRB5_MECH)) {
                    if (traceEnabled) {
                        log.trace("doAuth({}@{}) skip OID {}/{}: {}", user, session, i, num, oid);
                    }
                    continue;
                }
                if (debugEnabled) {
                    log.debug("doAuth({}@{}) found Kerberos 5 after {}/{} OID(s)", user, session, i, num);
                }

                // Validate initial user before proceeding
                if (!auth.validateInitialUser(session, user)) {
                    return Boolean.FALSE;
                }

                GSSManager mgr = auth.getGSSManager();
                GSSCredential creds = auth.getGSSCredential(mgr);
                if (creds == null) {
                    return Boolean.FALSE;
                }

                context = mgr.createContext(creds);

                // Send the matching mechanism back to the client

                byte[] out = oid.getDER();
                Buffer b = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_INFO_REQUEST, out.length + Integer.SIZE);
                b.putBytes(out);
                session.writePacket(b);

                return null;
            }

            // No matching mechanism found
            return Boolean.FALSE;
        } else {
            int msg = buffer.getUByte();
            if (!((msg == SshConstants.SSH_MSG_USERAUTH_INFO_RESPONSE)
                    || ((msg == SshConstants.SSH_MSG_USERAUTH_GSSAPI_MIC) && context.isEstablished()))) {
                throw new SshException(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR,
                        "Packet not supported by user authentication method: " + SshConstants.getCommandMessageName(msg));
            }

            if (debugEnabled) {
                log.debug("doAuth({}@{}) In krb5.next: msg = {}", user, session, SshConstants.getCommandMessageName(msg));
            }

            // If the context is established, this must be a MIC message

            if (context.isEstablished()) {
                if (msg != SshConstants.SSH_MSG_USERAUTH_GSSAPI_MIC) {
                    return Boolean.FALSE;
                }

                // Make the MIC message so the token can be verified

                Buffer msgbuf = new ByteArrayBuffer();
                msgbuf.putBytes(ValidateUtils.checkNotNullAndNotEmpty(session.getSessionId(), "No current session ID"));
                msgbuf.putByte(SshConstants.SSH_MSG_USERAUTH_REQUEST);
                msgbuf.putString(getUsername());
                msgbuf.putString(getService());
                msgbuf.putString(getName());

                byte[] msgbytes = msgbuf.getCompactData();
                byte[] inmic = buffer.getBytes();
                try {
                    context.verifyMIC(inmic, 0, inmic.length, msgbytes, 0, msgbytes.length, new MessageProp(false));
                    if (debugEnabled) {
                        log.debug("doAuth({}@{}) MIC verified", getUsername(), session);
                    }
                    return Boolean.TRUE;
                } catch (GSSException e) {
                    if (debugEnabled) {
                        log.debug("doAuth({}@{}) GSS verification {} error: {}",
                                user, session, e.getClass().getSimpleName(), e.getMessage());
                    }
                    return Boolean.FALSE;
                }
            } else {
                // Not established - new token to process
                byte[] tok = buffer.getBytes();
                byte[] out = context.acceptSecContext(tok, 0, tok.length);
                boolean established = context.isEstablished();

                // Validate identity if context is now established
                if (established && (identity == null)) {
                    GSSName srcName = context.getSrcName();
                    identity = srcName.toString();
                    if (debugEnabled) {
                        log.debug("doAuth({}@{}) GSS identity is {}", user, session, identity);
                    }

                    if (!auth.validateIdentity(session, identity)) {
                        return Boolean.FALSE;
                    }
                }

                // Send return token if necessary
                if (NumberUtils.length(out) > 0) {
                    Buffer b = session.createBuffer(SshConstants.SSH_MSG_USERAUTH_INFO_RESPONSE, out.length + Integer.SIZE);
                    b.putBytes(out);
                    session.writePacket(b);
                    return null;
                } else {
                    return established;
                }
            }
        }
    }