Search in sources :

Example 11 with GSSContext

use of org.ietf.jgss.GSSContext in project tomcat70 by apache.

the class SpnegoAuthenticator method authenticate.

@Override
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
    if (checkForCachedAuthentication(request, response, true)) {
        return true;
    }
    MessageBytes authorization = request.getCoyoteRequest().getMimeHeaders().getValue("authorization");
    if (authorization == null) {
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("authenticator.noAuthHeader"));
        }
        response.setHeader("WWW-Authenticate", "Negotiate");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        return false;
    }
    authorization.toBytes();
    ByteChunk authorizationBC = authorization.getByteChunk();
    if (!authorizationBC.startsWithIgnoreCase("negotiate ", 0)) {
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("spnegoAuthenticator.authHeaderNotNego"));
        }
        response.setHeader("WWW-Authenticate", "Negotiate");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        return false;
    }
    authorizationBC.setOffset(authorizationBC.getOffset() + 10);
    byte[] decoded = Base64.decodeBase64(authorizationBC.getBuffer(), authorizationBC.getOffset(), authorizationBC.getLength());
    if (getApplyJava8u40Fix()) {
        SpnegoTokenFixer.fix(decoded);
    }
    if (decoded.length == 0) {
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("spnegoAuthenticator.authHeaderNoToken"));
        }
        response.setHeader("WWW-Authenticate", "Negotiate");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        return false;
    }
    LoginContext lc = null;
    GSSContext gssContext = null;
    byte[] outToken = null;
    Principal principal = null;
    try {
        try {
            lc = new LoginContext(getLoginConfigName());
            lc.login();
        } catch (LoginException e) {
            log.error(sm.getString("spnegoAuthenticator.serviceLoginFail"), e);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return false;
        }
        Subject subject = lc.getSubject();
        // Assume the GSSContext is stateless
        // TODO: Confirm this assumption
        final GSSManager manager = GSSManager.getInstance();
        // IBM JDK only understands indefinite lifetime
        final int credentialLifetime;
        if (JreVendor.IS_IBM_JVM) {
            credentialLifetime = GSSCredential.INDEFINITE_LIFETIME;
        } else {
            credentialLifetime = GSSCredential.DEFAULT_LIFETIME;
        }
        final PrivilegedExceptionAction<GSSCredential> action = new PrivilegedExceptionAction<GSSCredential>() {

            @Override
            public GSSCredential run() throws GSSException {
                return manager.createCredential(null, credentialLifetime, new Oid("1.3.6.1.5.5.2"), GSSCredential.ACCEPT_ONLY);
            }
        };
        gssContext = manager.createContext(Subject.doAs(subject, action));
        outToken = Subject.doAs(lc.getSubject(), new AcceptAction(gssContext, decoded));
        if (outToken == null) {
            if (log.isDebugEnabled()) {
                log.debug(sm.getString("spnegoAuthenticator.ticketValidateFail"));
            }
            // Start again
            response.setHeader("WWW-Authenticate", "Negotiate");
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }
        principal = Subject.doAs(subject, new AuthenticateAction(context.getRealm(), gssContext, storeDelegatedCredential));
    } catch (GSSException e) {
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("spnegoAuthenticator.ticketValidateFail"), e);
        }
        response.setHeader("WWW-Authenticate", "Negotiate");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        return false;
    } catch (PrivilegedActionException e) {
        Throwable cause = e.getCause();
        if (cause instanceof GSSException) {
            if (log.isDebugEnabled()) {
                log.debug(sm.getString("spnegoAuthenticator.serviceLoginFail"), e);
            }
        } else {
            log.error(sm.getString("spnegoAuthenticator.serviceLoginFail"), e);
        }
        response.setHeader("WWW-Authenticate", "Negotiate");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        return false;
    } finally {
        if (gssContext != null) {
            try {
                gssContext.dispose();
            } catch (GSSException e) {
            // Ignore
            }
        }
        if (lc != null) {
            try {
                lc.logout();
            } catch (LoginException e) {
            // Ignore
            }
        }
    }
    // Send response token on success and failure
    response.setHeader("WWW-Authenticate", "Negotiate " + Base64.encodeBase64String(outToken));
    if (principal != null) {
        register(request, response, principal, Constants.SPNEGO_METHOD, principal.getName(), null);
        Pattern p = noKeepAliveUserAgents;
        if (p != null) {
            MessageBytes ua = request.getCoyoteRequest().getMimeHeaders().getValue("user-agent");
            if (ua != null && p.matcher(ua.toString()).matches()) {
                response.setHeader("Connection", "close");
            }
        }
        return true;
    }
    response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    return false;
}
Also used : Pattern(java.util.regex.Pattern) ByteChunk(org.apache.tomcat.util.buf.ByteChunk) PrivilegedActionException(java.security.PrivilegedActionException) MessageBytes(org.apache.tomcat.util.buf.MessageBytes) PrivilegedExceptionAction(java.security.PrivilegedExceptionAction) Oid(org.ietf.jgss.Oid) Subject(javax.security.auth.Subject) LoginContext(javax.security.auth.login.LoginContext) GSSException(org.ietf.jgss.GSSException) GSSCredential(org.ietf.jgss.GSSCredential) GSSContext(org.ietf.jgss.GSSContext) GSSManager(org.ietf.jgss.GSSManager) LoginException(javax.security.auth.login.LoginException) Principal(java.security.Principal)

Example 12 with GSSContext

use of org.ietf.jgss.GSSContext in project registry by hortonworks.

the class KerberosAuthenticationHandler method authenticate.

/**
 * It enforces the the Kerberos SPNEGO authentication sequence returning an {@link AuthenticationToken} only
 * after the Kerberos SPNEGO sequence has completed successfully.
 *
 * @param request the HTTP client request.
 * @param response the HTTP client response.
 *
 * @return an authentication token if the Kerberos SPNEGO sequence is complete and valid,
 *         <code>null</code> if it is in progress (in this case the handler handles the response to the client).
 *
 * @throws IOException thrown if an IO error occurred.
 * @throws AuthenticationException thrown if Kerberos SPNEGO sequence failed.
 */
@Override
public AuthenticationToken authenticate(HttpServletRequest request, final HttpServletResponse response) throws IOException, AuthenticationException {
    AuthenticationToken token = null;
    String authorization = request.getHeader(KerberosAuthenticator.AUTHORIZATION);
    if (authorization == null || !authorization.startsWith(KerberosAuthenticator.NEGOTIATE)) {
        response.setHeader(WWW_AUTHENTICATE, KerberosAuthenticator.NEGOTIATE);
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        if (authorization == null) {
            LOG.trace("SPNEGO starting");
        } else {
            LOG.warn("'" + KerberosAuthenticator.AUTHORIZATION + "' does not start with '" + KerberosAuthenticator.NEGOTIATE + "' :  {}", authorization);
        }
    } else {
        authorization = authorization.substring(KerberosAuthenticator.NEGOTIATE.length()).trim();
        final byte[] clientToken = Base64.getDecoder().decode(authorization);
        final String serverName = request.getServerName();
        try {
            token = Subject.doAs(serverSubject, new PrivilegedExceptionAction<AuthenticationToken>() {

                @Override
                public AuthenticationToken run() throws Exception {
                    AuthenticationToken token = null;
                    GSSContext gssContext = null;
                    GSSCredential gssCreds = null;
                    try {
                        gssCreds = gssManager.createCredential(gssManager.createName(KerberosUtil.getServicePrincipal("HTTP", serverName), KerberosUtil.getOidInstance("NT_GSS_KRB5_PRINCIPAL")), GSSCredential.INDEFINITE_LIFETIME, new Oid[] { KerberosUtil.getOidInstance("GSS_SPNEGO_MECH_OID"), KerberosUtil.getOidInstance("GSS_KRB5_MECH_OID") }, GSSCredential.ACCEPT_ONLY);
                        gssContext = gssManager.createContext(gssCreds);
                        byte[] serverToken = gssContext.acceptSecContext(clientToken, 0, clientToken.length);
                        if (serverToken != null && serverToken.length > 0) {
                            String authenticate = Base64.getEncoder().encodeToString(serverToken);
                            response.setHeader(KerberosAuthenticator.WWW_AUTHENTICATE, KerberosAuthenticator.NEGOTIATE + " " + authenticate);
                        }
                        if (!gssContext.isEstablished()) {
                            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                            LOG.trace("SPNEGO in progress");
                        } else {
                            String clientPrincipal = gssContext.getSrcName().toString();
                            KerberosName kerberosName = new KerberosName(clientPrincipal);
                            String userName = kerberosName.getShortName();
                            token = new AuthenticationToken(userName, clientPrincipal, getType());
                            response.setStatus(HttpServletResponse.SC_OK);
                            LOG.trace("SPNEGO completed for principal [{}]", clientPrincipal);
                        }
                    } finally {
                        if (gssContext != null) {
                            gssContext.dispose();
                        }
                        if (gssCreds != null) {
                            gssCreds.dispose();
                        }
                    }
                    return token;
                }
            });
        } catch (PrivilegedActionException ex) {
            if (ex.getException() instanceof IOException) {
                throw (IOException) ex.getException();
            } else {
                throw new AuthenticationException(ex.getException());
            }
        }
    }
    return token;
}
Also used : GSSCredential(org.ietf.jgss.GSSCredential) PrivilegedActionException(java.security.PrivilegedActionException) AuthenticationException(com.hortonworks.registries.auth.client.AuthenticationException) GSSContext(org.ietf.jgss.GSSContext) PrivilegedExceptionAction(java.security.PrivilegedExceptionAction) Oid(org.ietf.jgss.Oid) KerberosName(com.hortonworks.registries.auth.util.KerberosName) IOException(java.io.IOException)

Example 13 with GSSContext

use of org.ietf.jgss.GSSContext in project drill by apache.

the class TestSpnegoAuthentication method testDrillSpnegoLoginService.

/**
 * Validate successful {@link DrillSpnegoLoginService#login(String, Object, javax.servlet.ServletRequest)}
 * when provided with client token for a configured service principal.
 */
@Test
public void testDrillSpnegoLoginService() throws Exception {
    // Create client subject using it's principal and keytab
    final Subject clientSubject = JaasKrbUtil.loginUsingKeytab(spnegoHelper.CLIENT_PRINCIPAL, spnegoHelper.clientKeytab.getAbsoluteFile());
    // Generate a SPNEGO token for the peer SERVER_PRINCIPAL from this CLIENT_PRINCIPAL
    final String token = Subject.doAs(clientSubject, new PrivilegedExceptionAction<String>() {

        @Override
        public String run() throws Exception {
            final GSSManager gssManager = GSSManager.getInstance();
            GSSContext gssContext = null;
            try {
                final Oid oid = GSSUtil.GSS_SPNEGO_MECH_OID;
                final GSSName serviceName = gssManager.createName(spnegoHelper.SERVER_PRINCIPAL, GSSName.NT_USER_NAME, oid);
                gssContext = gssManager.createContext(serviceName, oid, null, GSSContext.DEFAULT_LIFETIME);
                gssContext.requestCredDeleg(true);
                gssContext.requestMutualAuth(true);
                byte[] outToken = new byte[0];
                outToken = gssContext.initSecContext(outToken, 0, outToken.length);
                return Base64.encodeBase64String(outToken);
            } finally {
                if (gssContext != null) {
                    gssContext.dispose();
                }
            }
        }
    });
    // Create a DrillbitContext with service principal and keytab for DrillSpnegoLoginService
    final DrillConfig newConfig = new DrillConfig(DrillConfig.create().withValue(ExecConstants.HTTP_AUTHENTICATION_MECHANISMS, ConfigValueFactory.fromIterable(Lists.newArrayList("spnego"))).withValue(ExecConstants.HTTP_SPNEGO_PRINCIPAL, ConfigValueFactory.fromAnyRef(spnegoHelper.SERVER_PRINCIPAL)).withValue(ExecConstants.HTTP_SPNEGO_KEYTAB, ConfigValueFactory.fromAnyRef(spnegoHelper.serverKeytab.toString())));
    final SystemOptionManager optionManager = Mockito.mock(SystemOptionManager.class);
    Mockito.when(optionManager.getOption(ExecConstants.ADMIN_USERS_VALIDATOR)).thenReturn(ExecConstants.ADMIN_USERS_VALIDATOR.DEFAULT_ADMIN_USERS);
    Mockito.when(optionManager.getOption(ExecConstants.ADMIN_USER_GROUPS_VALIDATOR)).thenReturn(ExecConstants.ADMIN_USER_GROUPS_VALIDATOR.DEFAULT_ADMIN_USER_GROUPS);
    final DrillbitContext drillbitContext = Mockito.mock(DrillbitContext.class);
    Mockito.when(drillbitContext.getConfig()).thenReturn(newConfig);
    Mockito.when(drillbitContext.getOptionManager()).thenReturn(optionManager);
    final DrillSpnegoLoginService loginService = new DrillSpnegoLoginService(drillbitContext);
    // Authenticate the client using its SPNEGO token
    final UserIdentity user = loginService.login(null, token, null);
    // Validate the UserIdentity of authenticated client
    assertNotNull(user);
    assertEquals(user.getUserPrincipal().getName(), spnegoHelper.CLIENT_SHORT_NAME);
    assertTrue(user.isUserInRole("authenticated", null));
}
Also used : DrillbitContext(org.apache.drill.exec.server.DrillbitContext) GSSName(org.ietf.jgss.GSSName) SystemOptionManager(org.apache.drill.exec.server.options.SystemOptionManager) UserIdentity(org.eclipse.jetty.server.UserIdentity) Oid(org.ietf.jgss.Oid) DrillSpnegoLoginService(org.apache.drill.exec.server.rest.auth.DrillSpnegoLoginService) Subject(javax.security.auth.Subject) DrillbitStartupException(org.apache.drill.exec.exception.DrillbitStartupException) DrillConfig(org.apache.drill.common.config.DrillConfig) GSSManager(org.ietf.jgss.GSSManager) GSSContext(org.ietf.jgss.GSSContext) BaseTest(org.apache.drill.test.BaseTest) SecurityTest(org.apache.drill.categories.SecurityTest) Test(org.junit.Test)

Example 14 with GSSContext

use of org.ietf.jgss.GSSContext in project presto by prestodb.

the class SpnegoHandler method generateToken.

private byte[] generateToken(String servicePrincipal) {
    GSSContext context = null;
    try {
        Session session = getSession();
        context = doAs(session.getLoginContext().getSubject(), () -> {
            GSSContext result = GSS_MANAGER.createContext(GSS_MANAGER.createName(servicePrincipal, NT_HOSTBASED_SERVICE), SPNEGO_OID, session.getClientCredential(), INDEFINITE_LIFETIME);
            result.requestMutualAuth(true);
            result.requestConf(true);
            result.requestInteg(true);
            result.requestCredDeleg(false);
            return result;
        });
        byte[] token = context.initSecContext(new byte[0], 0, 0);
        if (token == null) {
            throw new LoginException("No token generated from GSS context");
        }
        return token;
    } catch (GSSException | LoginException e) {
        throw new ClientException(format("Kerberos error for [%s]: %s", servicePrincipal, e.getMessage()), e);
    } finally {
        try {
            if (context != null) {
                context.dispose();
            }
        } catch (GSSException ignored) {
        }
    }
}
Also used : GSSException(org.ietf.jgss.GSSException) GSSContext(org.ietf.jgss.GSSContext) LoginException(javax.security.auth.login.LoginException)

Example 15 with GSSContext

use of org.ietf.jgss.GSSContext in project hbase by apache.

the class HttpDoAsClient method generateTicket.

private String generateTicket() throws GSSException {
    final GSSManager manager = GSSManager.getInstance();
    // Oid for kerberos principal name
    Oid krb5PrincipalOid = new Oid("1.2.840.113554.1.2.2.1");
    Oid KERB_V5_OID = new Oid("1.2.840.113554.1.2.2");
    final GSSName clientName = manager.createName(principal, krb5PrincipalOid);
    final GSSCredential clientCred = manager.createCredential(clientName, 8 * 3600, KERB_V5_OID, GSSCredential.INITIATE_ONLY);
    final GSSName serverName = manager.createName(principal, krb5PrincipalOid);
    final GSSContext context = manager.createContext(serverName, KERB_V5_OID, clientCred, GSSContext.DEFAULT_LIFETIME);
    context.requestMutualAuth(true);
    context.requestConf(false);
    context.requestInteg(true);
    final byte[] outToken = context.initSecContext(new byte[0], 0, 0);
    StringBuffer outputBuffer = new StringBuffer();
    outputBuffer.append("Negotiate ");
    outputBuffer.append(Bytes.toString(Base64.getEncoder().encode(outToken)));
    System.out.print("Ticket is: " + outputBuffer);
    return outputBuffer.toString();
}
Also used : GSSName(org.ietf.jgss.GSSName) GSSCredential(org.ietf.jgss.GSSCredential) GSSManager(org.ietf.jgss.GSSManager) GSSContext(org.ietf.jgss.GSSContext) Oid(org.ietf.jgss.Oid)

Aggregations

GSSContext (org.ietf.jgss.GSSContext)53 GSSManager (org.ietf.jgss.GSSManager)36 GSSName (org.ietf.jgss.GSSName)35 Oid (org.ietf.jgss.Oid)34 GSSException (org.ietf.jgss.GSSException)28 GSSCredential (org.ietf.jgss.GSSCredential)23 Subject (javax.security.auth.Subject)19 PrivilegedActionException (java.security.PrivilegedActionException)13 LoginException (javax.security.auth.login.LoginException)12 IOException (java.io.IOException)10 LoginContext (javax.security.auth.login.LoginContext)8 Principal (java.security.Principal)5 PrivilegedExceptionAction (java.security.PrivilegedExceptionAction)5 AuthenticationException (org.apache.hadoop.security.authentication.client.AuthenticationException)5 Test (org.junit.Test)5 HttpServletRequest (javax.servlet.http.HttpServletRequest)4 HttpServletResponse (javax.servlet.http.HttpServletResponse)4 SecurityTest (org.apache.drill.categories.SecurityTest)3 SystemOptionManager (org.apache.drill.exec.server.options.SystemOptionManager)3 AuthenticationException (com.hortonworks.registries.auth.client.AuthenticationException)2