private void doSaslHandshake()

in kerby-kerb/kerb-admin-server/src/main/java/org/apache/kerby/kerberos/kerb/admin/server/kadmin/impl/DefaultAdminServerHandler.java [105:172]


    private void doSaslHandshake() throws Exception {
        File keytabFile = new File(adminServerContext.getConfig().getKeyTabFile());
        String principal = adminServerContext.getConfig().getProtocol() + "/"
            + adminServerContext.getConfig().getAdminHost();
        String fixedPrincipal = AdminServerUtil.fixPrincipal(principal, adminServerContext.getAdminServerSetting());
        String adminPrincipal = KrbUtil.makeKadminPrincipal(
                adminServerContext.getAdminServerSetting().getKdcRealm()).getName();
        
        Subject subject = AuthUtil.loginUsingKeytab(fixedPrincipal, keytabFile);
        Subject.doAs(subject, (PrivilegedExceptionAction<Object>) () -> {
            boolean success = false;
            try {
                ByteBuffer message;
                try {
                    message = transport.receiveMessage();
                } catch (SocketTimeoutException ignore) {
                    // Ignore time out, wake up to see if should continue to run.
                    // When client create a new tpc transport, socket always timeout,
                    // because the first connection will not send message to the server.
                    // SASL handshake is not performed until the connection is established.
                    return null;
                }

                Map<String, Object> props = new HashMap<>();
                props.put(Sasl.QOP, "auth-conf");
                props.put(Sasl.SERVER_AUTH, "true");
                String protocol = adminServerContext.getConfig().getProtocol();
                String serverName = adminServerContext.getConfig().getServerName();
                CallbackHandler callbackHandler = new SaslGssCallbackHandler(adminPrincipal);
                SaslServer saslServer = Sasl.createSaslServer(MECHANISM, protocol,
                        serverName, props, callbackHandler);

                if (saslServer == null) {
                    throw new Exception("Unable to find server implementation for: GSSAPI");
                }

                setSaslServerWrapper(SaslWrapper.create(saslServer));

                while (!saslServer.isComplete()) {
                    int scComplete = message.getInt();
                    if (scComplete == NegotiationStatus.SUCCESS.getValue()) {
                        logger.info("Sasl Client completed");
                    }

                    byte[] challenge = null;
                    try {
                        challenge = SaslUtils.evaluateResponse(saslServer, message);
                    } catch (SaslException e) {
                        throw new Exception("Sasl server evaluate challenge failed. " + e);
                    }

                    if (!saslServer.isComplete()) {
                        // Send message to client only when SASL server is not complete
                        sendMessage(challenge, saslServer);

                        logger.info("Waiting receive message");
                        message = transport.receiveMessage();
                    }
                }
                success = true;
            } finally {
                if (!success) {
                    transport.release();
                }
            }
            return null;
        });
    }