Search in sources :

Example 36 with SaslException

use of javax.security.sasl.SaslException in project zookeeper by apache.

the class SecurityUtils method createSaslClient.

/**
 * Create an instance of a SaslClient. It will return null if there is an exception.
 *
 * @param subject subject
 * @param servicePrincipal principal
 * @param protocol name of the protocol for which the authentication is being performed
 * @param serverName name of the server to authenticate to
 * @param LOG logger
 * @param entity can be either zookeeper client or quorum learner
 *
 * @return saslclient object
 * @throws SaslException
 */
public static SaslClient createSaslClient(final Subject subject, final String servicePrincipal, final String protocol, final String serverName, final Logger LOG, final String entity) throws SaslException {
    SaslClient saslClient;
    // mechanism to use: if empty, use DIGEST-MD5; otherwise, use GSSAPI.
    if (subject.getPrincipals().isEmpty()) {
        // no principals: must not be GSSAPI: use DIGEST-MD5 mechanism
        // instead.
        LOG.info("{} will use DIGEST-MD5 as SASL mechanism.", entity);
        String[] mechs = { "DIGEST-MD5" };
        String username = (String) (subject.getPublicCredentials().toArray()[0]);
        String password = (String) (subject.getPrivateCredentials().toArray()[0]);
        // 'domain' parameter is hard-wired between the server and client
        saslClient = Sasl.createSaslClient(mechs, username, protocol, serverName, null, new SaslClientCallbackHandler(password, entity));
        return saslClient;
    } else {
        // GSSAPI.
        final Object[] principals = subject.getPrincipals().toArray();
        // determine client principal from subject.
        final Principal clientPrincipal = (Principal) principals[0];
        boolean usingNativeJgss = Boolean.getBoolean("sun.security.jgss.native");
        if (usingNativeJgss) {
            // """
            try {
                GSSManager manager = GSSManager.getInstance();
                Oid krb5Mechanism = new Oid("1.2.840.113554.1.2.2");
                GSSCredential cred = manager.createCredential(null, GSSContext.DEFAULT_LIFETIME, krb5Mechanism, GSSCredential.INITIATE_ONLY);
                subject.getPrivateCredentials().add(cred);
                LOG.debug("Added private credential to {} principal name: '{}'", entity, clientPrincipal);
            } catch (GSSException ex) {
                LOG.warn("Cannot add private credential to subject; " + "authentication at the server may fail", ex);
            }
        }
        final KerberosName clientKerberosName = new KerberosName(clientPrincipal.getName());
        // assume that server and client are in the same realm (by default;
        // unless the system property
        // "zookeeper.server.realm" is set).
        String serverRealm = System.getProperty("zookeeper.server.realm", clientKerberosName.getRealm());
        KerberosName serviceKerberosName = new KerberosName(servicePrincipal + "@" + serverRealm);
        final String serviceName = serviceKerberosName.getServiceName();
        final String serviceHostname = serviceKerberosName.getHostName();
        final String clientPrincipalName = clientKerberosName.toString();
        try {
            saslClient = Subject.doAs(subject, new PrivilegedExceptionAction<SaslClient>() {

                public SaslClient run() throws SaslException {
                    LOG.info("{} will use GSSAPI as SASL mechanism.", entity);
                    String[] mechs = { "GSSAPI" };
                    LOG.debug("creating sasl client: {}={};service={};serviceHostname={}", new Object[] { entity, clientPrincipalName, serviceName, serviceHostname });
                    SaslClient saslClient = Sasl.createSaslClient(mechs, clientPrincipalName, serviceName, serviceHostname, null, new SaslClientCallbackHandler(null, entity));
                    return saslClient;
                }
            });
            return saslClient;
        } catch (Exception e) {
            LOG.error("Exception while trying to create SASL client", e);
            return null;
        }
    }
}
Also used : Oid(org.ietf.jgss.Oid) KerberosName(org.apache.zookeeper.server.auth.KerberosName) PrivilegedExceptionAction(java.security.PrivilegedExceptionAction) PrivilegedActionException(java.security.PrivilegedActionException) GSSException(org.ietf.jgss.GSSException) SaslException(javax.security.sasl.SaslException) SaslClient(javax.security.sasl.SaslClient) GSSException(org.ietf.jgss.GSSException) GSSCredential(org.ietf.jgss.GSSCredential) GSSManager(org.ietf.jgss.GSSManager) SaslClientCallbackHandler(org.apache.zookeeper.SaslClientCallbackHandler) Principal(java.security.Principal)

Example 37 with SaslException

use of javax.security.sasl.SaslException in project JGroups by belaban.

the class SASL method up.

@Override
public Object up(Message msg) {
    SaslHeader saslHeader = msg.getHeader(SASL_ID);
    GmsHeader gmsHeader = msg.getHeader(GMS_ID);
    Address remoteAddress = msg.getSrc();
    if (needsAuthentication(gmsHeader, remoteAddress)) {
        if (saslHeader == null)
            throw new IllegalStateException("Found GMS join or merge request but no SASL header");
        if (!serverChallenge(gmsHeader, saslHeader, msg))
            // failed auth, don't pass up
            return null;
    } else if (saslHeader != null) {
        SaslContext saslContext = sasl_context.get(remoteAddress);
        if (saslContext == null) {
            throw new IllegalStateException(String.format("Cannot find server context to challenge SASL request from %s", remoteAddress.toString()));
        }
        switch(saslHeader.getType()) {
            case CHALLENGE:
                try {
                    if (log.isTraceEnabled())
                        log.trace("%s: received CHALLENGE from %s", getAddress(), remoteAddress);
                    // the response computed can be null if the challenge-response cycle has ended
                    Message response = saslContext.nextMessage(remoteAddress, saslHeader);
                    if (response != null) {
                        if (log.isTraceEnabled())
                            log.trace("%s: sending RESPONSE to %s", getAddress(), remoteAddress);
                        down_prot.down(response);
                    } else {
                        if (!saslContext.isSuccessful()) {
                            throw new SaslException("computed response is null but challenge-response cycle not complete!");
                        }
                        if (log.isTraceEnabled())
                            log.trace("%s: authentication complete from %s", getAddress(), remoteAddress);
                    }
                } catch (SaslException e) {
                    disposeContext(remoteAddress);
                    if (log.isWarnEnabled()) {
                        log.warn(getAddress() + ": failed to validate CHALLENGE from " + remoteAddress + ", token", e);
                    }
                }
                break;
            case RESPONSE:
                try {
                    if (log.isTraceEnabled())
                        log.trace("%s: received RESPONSE from %s", getAddress(), remoteAddress);
                    Message challenge = saslContext.nextMessage(remoteAddress, saslHeader);
                    // the challenge computed can be null if the challenge-response cycle has ended
                    if (challenge != null) {
                        if (log.isTraceEnabled())
                            log.trace("%s: sending CHALLENGE to %s", getAddress(), remoteAddress);
                        down_prot.down(challenge);
                    } else {
                        if (!saslContext.isSuccessful()) {
                            throw new SaslException("computed challenge is null but challenge-response cycle not complete!");
                        }
                        if (log.isTraceEnabled())
                            log.trace("%s: authentication complete from %s", getAddress(), remoteAddress);
                    }
                } catch (SaslException e) {
                    disposeContext(remoteAddress);
                    if (log.isWarnEnabled()) {
                        log.warn("failed to validate RESPONSE from " + remoteAddress + ", token", e);
                    }
                }
                break;
        }
        return null;
    }
    return up_prot.up(msg);
}
Also used : Address(org.jgroups.Address) Message(org.jgroups.Message) GmsHeader(org.jgroups.protocols.pbcast.GMS.GmsHeader) SaslException(javax.security.sasl.SaslException) SaslContext(org.jgroups.auth.sasl.SaslContext)

Example 38 with SaslException

use of javax.security.sasl.SaslException in project JGroups by belaban.

the class SASL method serverChallenge.

protected boolean serverChallenge(GmsHeader gmsHeader, SaslHeader saslHeader, Message msg) {
    switch(gmsHeader.getType()) {
        case GmsHeader.JOIN_REQ:
        case GmsHeader.JOIN_REQ_WITH_STATE_TRANSFER:
        case GmsHeader.MERGE_REQ:
            Address remoteAddress = msg.getSrc();
            SaslServerContext ctx = null;
            try {
                ctx = new SaslServerContext(saslServerFactory, mech, server_name != null ? server_name : local_addr.toString(), server_callback_handler, sasl_props, server_subject);
                sasl_context.put(remoteAddress, ctx);
                this.getDownProtocol().down(ctx.nextMessage(remoteAddress, saslHeader));
                ctx.awaitCompletion(timeout);
                if (ctx.isSuccessful()) {
                    if (log.isDebugEnabled()) {
                        log.debug("Authentication successful for %s", ctx.getAuthorizationID());
                    }
                    return true;
                } else {
                    log.warn("failed to validate SaslHeader from %s, header: %s", msg.getSrc(), saslHeader);
                    sendRejectionMessage(gmsHeader.getType(), msg.getSrc(), "authentication failed");
                    return false;
                }
            } catch (SaslException e) {
                log.warn("failed to validate SaslHeader from %s, header: %s", msg.getSrc(), saslHeader);
                sendRejectionMessage(gmsHeader.getType(), msg.getSrc(), "authentication failed");
            } catch (InterruptedException e) {
                return false;
            } finally {
                if (ctx != null && !ctx.needsWrapping()) {
                    disposeContext(remoteAddress);
                }
            }
        default:
            // pass up
            return true;
    }
}
Also used : Address(org.jgroups.Address) SaslServerContext(org.jgroups.auth.sasl.SaslServerContext) SaslException(javax.security.sasl.SaslException)

Example 39 with SaslException

use of javax.security.sasl.SaslException in project hive by apache.

the class HiveConnection method createBinaryTransport.

/**
 * Create transport per the connection options
 * Supported transport options are:
 *   - SASL based transports over
 *      + Kerberos
 *      + Delegation token
 *      + SSL
 *      + non-SSL
 *   - Raw (non-SASL) socket
 *
 *   Kerberos and Delegation token supports SASL QOP configurations
 * @throws SQLException, TTransportException
 */
private TTransport createBinaryTransport() throws SQLException, TTransportException {
    try {
        TTransport socketTransport = createUnderlyingTransport();
        // handle secure connection if specified
        if (!JdbcConnectionParams.AUTH_SIMPLE.equals(sessConfMap.get(JdbcConnectionParams.AUTH_TYPE))) {
            // If Kerberos
            Map<String, String> saslProps = new HashMap<String, String>();
            SaslQOP saslQOP = SaslQOP.AUTH;
            if (sessConfMap.containsKey(JdbcConnectionParams.AUTH_QOP)) {
                try {
                    saslQOP = SaslQOP.fromString(sessConfMap.get(JdbcConnectionParams.AUTH_QOP));
                } catch (IllegalArgumentException e) {
                    throw new SQLException("Invalid " + JdbcConnectionParams.AUTH_QOP + " parameter. " + e.getMessage(), "42000", e);
                }
                saslProps.put(Sasl.QOP, saslQOP.toString());
            } else {
                // If the client did not specify qop then just negotiate the one supported by server
                saslProps.put(Sasl.QOP, "auth-conf,auth-int,auth");
            }
            saslProps.put(Sasl.SERVER_AUTH, "true");
            if (sessConfMap.containsKey(JdbcConnectionParams.AUTH_PRINCIPAL)) {
                transport = KerberosSaslHelper.getKerberosTransport(sessConfMap.get(JdbcConnectionParams.AUTH_PRINCIPAL), host, socketTransport, saslProps, assumeSubject);
            } else {
                // If there's a delegation token available then use token based connection
                String tokenStr = getClientDelegationToken(sessConfMap);
                if (tokenStr != null) {
                    transport = KerberosSaslHelper.getTokenTransport(tokenStr, host, socketTransport, saslProps);
                } else {
                    // we are using PLAIN Sasl connection with user/password
                    String userName = getUserName();
                    String passwd = getPassword();
                    // Overlay the SASL transport on top of the base socket transport (SSL or non-SSL)
                    transport = PlainSaslHelper.getPlainTransport(userName, passwd, socketTransport);
                }
            }
        } else {
            // Raw socket connection (non-sasl)
            transport = socketTransport;
        }
    } catch (SaslException e) {
        throw new SQLException("Could not create secure connection to " + jdbcUriString + ": " + e.getMessage(), " 08S01", e);
    }
    return transport;
}
Also used : HashMap(java.util.HashMap) SQLException(java.sql.SQLException) SaslQOP(org.apache.hive.service.auth.SaslQOP) TTransport(org.apache.thrift.transport.TTransport) SaslException(javax.security.sasl.SaslException)

Example 40 with SaslException

use of javax.security.sasl.SaslException in project Openfire by igniterealtime.

the class SASLAuthentication method handle.

/**
     * Handles the SASL authentication packet. The entity may be sending an initial
     * authentication request or a response to a challenge made by the server. The returned
     * value indicates whether the authentication has finished either successfully or not or
     * if the entity is expected to send a response to a challenge.
     *
     * @param session the session that is authenticating with the server.
     * @param doc the stanza sent by the authenticating entity.
     * @return value that indicates whether the authentication has finished either successfully
     *         or not or if the entity is expected to send a response to a challenge.
     */
public static Status handle(LocalSession session, Element doc) {
    try {
        if (!doc.getNamespaceURI().equals(SASL_NAMESPACE)) {
            throw new IllegalStateException("Unexpected data received while negotiating SASL authentication. Name of the offending root element: " + doc.getName() + " Namespace: " + doc.getNamespaceURI());
        }
        switch(ElementType.valueOfCaseInsensitive(doc.getName())) {
            case ABORT:
                throw new SaslFailureException(Failure.ABORTED);
            case AUTH:
                if (doc.attributeValue("mechanism") == null) {
                    throw new SaslFailureException(Failure.INVALID_MECHANISM, "Peer did not specify a mechanism.");
                }
                final String mechanismName = doc.attributeValue("mechanism").toUpperCase();
                // See if the mechanism is supported by configuration as well as by implementation.
                if (!mechanisms.contains(mechanismName)) {
                    throw new SaslFailureException(Failure.INVALID_MECHANISM, "The configuration of Openfire does not contain or allow the mechanism.");
                }
                // OF-477: The SASL implementation requires the fully qualified host name (not the domain name!) of this server,
                // yet, most of the XMPP implemenations of DIGEST-MD5 will actually use the domain name. To account for that,
                // here, we'll use the host name, unless DIGEST-MD5 is being negotiated!
                final XMPPServerInfo serverInfo = XMPPServer.getInstance().getServerInfo();
                final String serverName = (mechanismName.equals("DIGEST-MD5") ? serverInfo.getXMPPDomain() : serverInfo.getHostname());
                // Construct the configuration properties
                final Map<String, Object> props = new HashMap<>();
                props.put(LocalSession.class.getCanonicalName(), session);
                props.put(Sasl.POLICY_NOANONYMOUS, Boolean.toString(!JiveGlobals.getBooleanProperty("xmpp.auth.anonymous")));
                props.put("com.sun.security.sasl.digest.realm", serverInfo.getXMPPDomain());
                SaslServer saslServer = Sasl.createSaslServer(mechanismName, "xmpp", serverName, props, new XMPPCallbackHandler());
                if (saslServer == null) {
                    throw new SaslFailureException(Failure.INVALID_MECHANISM, "There is no provider that can provide a SASL server for the desired mechanism and properties.");
                }
                session.setSessionData("SaslServer", saslServer);
                if (mechanismName.equals("DIGEST-MD5")) {
                    // RFC2831 (DIGEST-MD5) says the client MAY provide data in the initial response. Java SASL does
                    // not (currently) support this and throws an exception. For XMPP, such data violates
                    // the RFC, so we just strip any initial token.
                    doc.setText("");
                }
            // intended fall-through
            case RESPONSE:
                saslServer = (SaslServer) session.getSessionData("SaslServer");
                if (saslServer == null) {
                    // Client sends response without a preceding auth?
                    throw new IllegalStateException("A SaslServer instance was not initialized and/or stored on the session.");
                }
                // Decode any data that is provided in the client response.
                final String encoded = doc.getTextTrim();
                final byte[] decoded;
                if (// java SaslServer cannot handle a null.
                encoded == null || encoded.isEmpty() || encoded.equals("=")) {
                    decoded = new byte[0];
                } else {
                    // TODO: We shouldn't depend on regex-based validation. Instead, use a proper decoder implementation and handle any exceptions that it throws.
                    if (!BASE64_ENCODED.matcher(encoded).matches()) {
                        throw new SaslFailureException(Failure.INCORRECT_ENCODING);
                    }
                    decoded = StringUtils.decodeBase64(encoded);
                }
                // Process client response.
                // Either a challenge or success data.
                final byte[] challenge = saslServer.evaluateResponse(decoded);
                if (!saslServer.isComplete()) {
                    // Not complete: client is challenged for additional steps.
                    sendChallenge(session, challenge);
                    return Status.needResponse;
                }
                // Success!
                if (session instanceof IncomingServerSession) {
                    // Flag that indicates if certificates of the remote server should be validated.
                    final boolean verify = JiveGlobals.getBooleanProperty(ConnectionSettings.Server.TLS_CERTIFICATE_VERIFY, true);
                    if (verify) {
                        if (verifyCertificates(session.getConnection().getPeerCertificates(), saslServer.getAuthorizationID(), true)) {
                            ((LocalIncomingServerSession) session).tlsAuth();
                        } else {
                            throw new SaslFailureException(Failure.NOT_AUTHORIZED, "Server-to-Server certificate verification failed.");
                        }
                    }
                }
                authenticationSuccessful(session, saslServer.getAuthorizationID(), challenge);
                session.removeSessionData("SaslServer");
                return Status.authenticated;
            default:
                throw new IllegalStateException("Unexpected data received while negotiating SASL authentication. Name of the offending root element: " + doc.getName() + " Namespace: " + doc.getNamespaceURI());
        }
    } catch (SaslException ex) {
        Log.debug("SASL negotiation failed for session: {}", session, ex);
        final Failure failure;
        if (ex instanceof SaslFailureException && ((SaslFailureException) ex).getFailure() != null) {
            failure = ((SaslFailureException) ex).getFailure();
        } else {
            failure = Failure.NOT_AUTHORIZED;
        }
        authenticationFailed(session, failure);
        session.removeSessionData("SaslServer");
        return Status.failed;
    } catch (Exception ex) {
        Log.warn("An unexpected exception occurred during SASL negotiation. Affected session: {}", session, ex);
        authenticationFailed(session, Failure.NOT_AUTHORIZED);
        session.removeSessionData("SaslServer");
        return Status.failed;
    }
}
Also used : JiveSharedSecretSaslServer(org.jivesoftware.openfire.sasl.JiveSharedSecretSaslServer) SaslServer(javax.security.sasl.SaslServer) SaslException(javax.security.sasl.SaslException) SaslFailureException(org.jivesoftware.openfire.sasl.SaslFailureException) SaslException(javax.security.sasl.SaslException) SaslFailureException(org.jivesoftware.openfire.sasl.SaslFailureException) Failure(org.jivesoftware.openfire.sasl.Failure) XMPPServerInfo(org.jivesoftware.openfire.XMPPServerInfo)

Aggregations

SaslException (javax.security.sasl.SaslException)75 IOException (java.io.IOException)24 NameCallback (javax.security.auth.callback.NameCallback)11 UnsupportedCallbackException (javax.security.auth.callback.UnsupportedCallbackException)11 SaslClient (javax.security.sasl.SaslClient)7 PrivilegedActionException (java.security.PrivilegedActionException)6 Callback (javax.security.auth.callback.Callback)6 PasswordCallback (javax.security.auth.callback.PasswordCallback)6 LoginException (javax.security.auth.login.LoginException)6 SaslServer (javax.security.sasl.SaslServer)6 UndeclaredThrowableException (java.lang.reflect.UndeclaredThrowableException)5 InvalidKeyException (java.security.InvalidKeyException)5 AuthorizeCallback (javax.security.sasl.AuthorizeCallback)5 RpcException (org.apache.drill.exec.rpc.RpcException)5 GSSException (org.ietf.jgss.GSSException)5 DataOutputStream (java.io.DataOutputStream)4 NoSuchAlgorithmException (java.security.NoSuchAlgorithmException)4 Principal (java.security.Principal)4 CallbackHandler (javax.security.auth.callback.CallbackHandler)4 GSSCredential (org.ietf.jgss.GSSCredential)4