List of usage examples for javax.security.auth.kerberos KerberosPrincipal KerberosPrincipal
public KerberosPrincipal(String name)
From source file:net.shibboleth.idp.authn.spnego.impl.SPNEGOAuthnController.java
/** * Process an input GSS token from the client and attempt to complete the context establishment process. * /* w ww. ja v a 2 s . c om*/ * @param conversationKey the conversation key * @param authorizationHeader the token from the client * @param httpRequest the HTTP request * @param httpResponse the HTTP response * * @return the response view * @throws ExternalAuthenticationException * @throws IOException */ @RequestMapping(value = "/{conversationKey}", method = RequestMethod.GET, headers = "Authorization") @Nullable public ModelAndView continueSPNEGO(@PathVariable @Nonnull @NotEmpty final String conversationKey, @RequestHeader(HttpHeaders.AUTHORIZATION) @Nonnull @NotEmpty final String authorizationHeader, @Nonnull final HttpServletRequest httpRequest, @Nonnull final HttpServletResponse httpResponse) throws ExternalAuthenticationException, IOException { final ProfileRequestContext prc = ExternalAuthentication.getProfileRequestContext(conversationKey, httpRequest); if (!authorizationHeader.startsWith("Negotiate ")) { return replyUnauthorizedNegotiate(prc, httpRequest, httpResponse); } final SPNEGOContext spnegoCtx = getSPNEGOContext(prc); if (spnegoCtx == null || spnegoCtx.getKerberosSettings() == null) { log.error("Kerberos settings not found in profile request context"); finishWithError(conversationKey, httpRequest, httpResponse, AuthnEventIds.INVALID_AUTHN_CTX); return null; } GSSContextAcceptor acceptor = spnegoCtx.getContextAcceptor(); if (acceptor == null) { try { acceptor = createGSSContextAcceptor(spnegoCtx); spnegoCtx.setContextAcceptor(acceptor); } catch (final GSSException e) { log.error("Unable to create GSSContextAcceptor", e); finishWithException(conversationKey, httpRequest, httpResponse, new ExternalAuthenticationException(SPNEGO_NOT_AVAILABLE, e)); return null; } } final byte[] gssapiData = Base64.decodeBase64(authorizationHeader.substring(10).getBytes()); log.trace("SPNEGO negotiation, Authorization header received, gssapi-data: {}", gssapiData); // NTLM Authentication is not supported. if (isNTLMMechanism(gssapiData)) { log.warn("NTLM is unsupported, failing context negotiation"); acceptor.logout(); finishWithError(conversationKey, httpRequest, httpResponse, NTLM_UNSUPPORTED); return null; } byte[] tokenBytes; try { tokenBytes = acceptor.acceptSecContext(gssapiData, 0, gssapiData.length); log.trace("GSS token accepted"); } catch (final Exception e) { log.debug("Exception processing GSS token", e); acceptor.logout(); finishWithException(conversationKey, httpRequest, httpResponse, new ExternalAuthenticationException(SPNEGO_NOT_AVAILABLE, e)); return null; } // If the context is established, we can attempt to retrieve the name of the "context initiator." // In the case of the Kerberos mechanism, the context initiator is the Kerberos principal of the client. if (acceptor.getContext() != null && acceptor.getContext().isEstablished()) { log.debug("GSS security context is complete"); try { final GSSName clientGSSName = acceptor.getContext().getSrcName(); if (clientGSSName == null) { // This case should never happen, but we observed it. Handle it as authentication failure. log.error("Error extracting principal name from security context"); acceptor.logout(); finishWithException(conversationKey, httpRequest, httpResponse, new ExternalAuthenticationException(SPNEGO_NOT_AVAILABLE)); return null; } final KerberosPrincipal kerberosPrincipal = new KerberosPrincipal(clientGSSName.toString()); log.info("SPNEGO/Kerberos authentication succeeded for principal: {}", clientGSSName.toString()); acceptor.logout(); finishWithSuccess(conversationKey, httpRequest, httpResponse, kerberosPrincipal); } catch (final GSSException e) { log.error("Error extracting principal name from security context", e); acceptor.logout(); finishWithException(conversationKey, httpRequest, httpResponse, new ExternalAuthenticationException(SPNEGO_NOT_AVAILABLE, e)); } } else { // The context is not complete yet. // return "WWW-Authenticate: Negotiate <data>" to the browser log.trace("SPNEGO negotiation in process, output token: {}", tokenBytes); return replyUnauthorizedNegotiate(prc, httpRequest, httpResponse, Base64.encodeBase64String(tokenBytes)); } return null; }
From source file:com.example.ManualSpnegoNegotiateServlet.java
/** * Use of Kerberos is wrapped in an HTTP auth-scheme of "Negotiate" [RFC 4559]. * * The auth-params exchanged use data formats defined for use with the GSS-API [RFC 2743]. In particular, they follow the formats set for the SPNEGO [RFC 4178] and * Kerberos [RFC 4121] mechanisms for GSSAPI. The "Negotiate" auth-scheme calls for the use of SPNEGO GSSAPI tokens that the specific mechanism type specifies. * * The current implementation of this protocol is limited to the use of SPNEGO with the Kerberos protocol. * * @param request//from w w w . ja va 2s .c o m * @param response * @throws ServletException * * @return true upon successful authentication, false otherwise */ protected boolean attemptNegotiation(HttpServletRequest request, HttpServletResponse response) throws ServletException, UnsupportedEncodingException, IOException { log.debug("Attempting negotiation."); String header = request.getHeader("Authorization"); /** * Guard clause to check for Negotiate header. * * If the server receives a request for an access-protected object, and if an acceptable Authorization header has not been sent, the server responds with a "401 * Unauthorized" status code, and a "WWW-Authenticate:" header as per the framework described in [RFC 2616]. The initial WWW-Authenticate header will not carry * any gssapi-data. */ if (header == null || header.length() < 10 || !header.startsWith("Negotiate ")) { response.setHeader("WWW-Authenticate", "Negotiate"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); log.debug("Proper authorization header not found, returning challenge."); return false; } /** * A client may initiate a connection to the server with an "Authorization" header containing the initial token for the server. This form will bypass the initial * 401 error from the server when the client knows that the server will accept the Negotiate HTTP authentication type. */ log.debug("Authorization header found, continuing negotiation."); /** * The data following the word Negotiate is the GSS-API data to process. */ byte gssapiData[] = Base64.decode(header.substring(10)); log.debug("GSS API data: " + Arrays.toString(gssapiData)); /** * Guard clause to check for the unsupported NTLM authentication mechanism. */ if (isNtlmMechanism(gssapiData)) { log.warn("Got request for unsupported NTLM mechanism, aborting negotiation."); return false; } /** * The server attempts to establish a security context. Establishment may result in tokens that the server must return to the client. Tokens are BASE-64 encoded * GSS-API data. */ GSSContext gssContext = null; LoginContext loginContext = null; String outToken = null; try { final String domainUsername = "Zeus"; final String domainUserPassword = "Z3usP@55"; final CallbackHandler handler = SpnegoProvider.getUsernamePasswordHandler(domainUsername, domainUserPassword); loginContext = new LoginContext("spnego-server", handler); loginContext.login(); Subject subject = loginContext.getSubject(); Oid spnegoOid = new Oid("1.3.6.1.5.5.2"); // for spnego answers Oid kerbv5Oid = new Oid("1.2.840.113554.1.2.2"); // for chromium (they send a kerbv5 token instead of spnego) final Oid[] oids = new Oid[] { spnegoOid, kerbv5Oid }; final GSSManager manager = GSSManager.getInstance(); final PrivilegedExceptionAction<GSSCredential> action = new PrivilegedExceptionAction<GSSCredential>() { public GSSCredential run() throws GSSException { return manager.createCredential(null, GSSCredential.INDEFINITE_LIFETIME, oids, GSSCredential.ACCEPT_ONLY); } }; GSSCredential serverCreds = Subject.doAs(subject, action); log.debug("Mechs: " + Arrays.toString(serverCreds.getMechs())); gssContext = manager.createContext(serverCreds); log.debug("Context created. " + gssContext); byte tokenBytes[] = gssContext.acceptSecContext(gssapiData, 0, gssapiData.length); outToken = Base64.encode(tokenBytes); } catch (PrivilegedActionException ex) { log.error("", ex); } catch (LoginException ex) { log.error("", ex); } catch (GSSException gsse) { gsse.printStackTrace(); log.error("GSSException: " + gsse.getMessage()); log.error("GSSException major: " + gsse.getMajorString()); log.error("GSSException minor: " + gsse.getMinorString()); throw new ServletException(gsse); } /** * If the context is established, we can attempt to retrieve the name of the "context initiator." In the case of the Kerberos mechanism, the context initiator is * the Kerberos principal of the client. Additionally, the client may be delegating credentials. */ if (gssContext != null && gssContext.isEstablished()) { log.debug("Context established, attempting Kerberos principal retrieval."); try { Subject subject = new Subject(); GSSName clientGSSName = gssContext.getSrcName(); KerberosPrincipal clientPrincipal = new KerberosPrincipal(clientGSSName.toString()); subject.getPrincipals().add(clientPrincipal); log.info("Got client Kerberos principal: " + clientGSSName); response.getWriter().println("Hello, " + clientPrincipal); /** * Retrieve LogonInfo (for example, GroupSIDs) from the PAC Authorization Data * from a Kerberos Ticket that was issued by Active Directory. */ byte[] kerberosTokenData = gssapiData; try { SpnegoToken token = SpnegoToken.parse(gssapiData); kerberosTokenData = token.getMechanismToken(); } catch (DecodingException dex) { // Chromium bug: sends a Kerberos response instead of an spnego response with a Kerberos mechanism } catch (Exception ex) { log.error("", ex); } try { Object[] keyObjs = IteratorUtils .toArray(loginContext.getSubject().getPrivateCredentials(KerberosKey.class).iterator()); KerberosKey[] keys = new KerberosKey[keyObjs.length]; System.arraycopy(keyObjs, 0, keys, 0, keyObjs.length); KerberosToken token = new KerberosToken(kerberosTokenData, keys); log.info("Authorizations: "); for (KerberosAuthData authData : token.getTicket().getEncData().getUserAuthorizations()) { if (authData instanceof KerberosPacAuthData) { PacSid[] groupSIDs = ((KerberosPacAuthData) authData).getPac().getLogonInfo() .getGroupSids(); log.info("GroupSids: " + Arrays.toString(groupSIDs)); response.getWriter().println("Found group SIDs: " + Arrays.toString(groupSIDs)); } else { log.info("AuthData without PAC: " + authData.toString()); } } } catch (Exception ex) { log.error("", ex); } if (gssContext.getCredDelegState()) { GSSCredential delegateCredential = gssContext.getDelegCred(); GSSName delegateGSSName = delegateCredential.getName(); Principal delegatePrincipal = new KerberosPrincipal(delegateGSSName.toString()); subject.getPrincipals().add(delegatePrincipal); subject.getPrivateCredentials().add(delegateCredential); log.info("Got delegated Kerberos principal: " + delegateGSSName); } /** * A status code 200 status response can also carry a "WWW-Authenticate" response header containing the final leg of an authentication. In this case, the * gssapi-data will be present. */ if (outToken != null && outToken.length() > 0) { response.setHeader("WWW-Authenticate", "Negotiate " + outToken.getBytes()); response.setStatus(HttpServletResponse.SC_OK); log.debug("Returning final authentication data to client to complete context."); log.debug("Negotiation completed."); return true; } } catch (GSSException gsse) { log.error("GSSException: " + gsse.getMessage()); log.error("GSSException major: " + gsse.getMajorString()); log.error("GSSException minor: " + gsse.getMinorString()); response.addHeader("Client-Warning", gsse.getMessage()); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); } } else { /** * Any returned code other than a success 2xx code represents an authentication error. If a 401 containing a "WWW-Authenticate" header with "Negotiate" and * gssapi-data is returned from the server, it is a continuation of the authentication request. */ if (outToken != null && outToken.length() > 0) { response.setHeader("WWW-Authenticate", "Negotiate " + outToken.getBytes()); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); log.debug("Additional authentication processing required, returning token."); return false; } else { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); log.warn("Kerberos negotiation failed."); } } log.debug("Negotiation completed."); return true; }
From source file:com.sonymobile.jenkins.plugins.kerberossso.KerberosFilterTest.java
private void fakePrincipal(String principal) throws LoginException, IOException, ServletException { if (!principal.contains("@")) { throw new AssertionError( "Principal name must have realm specified as system may not be configured with default one"); }/*from ww w. j a v a2s . c om*/ KerberosAuthenticator mockAuthenticator = mock(KerberosAuthenticator.class); when(mockAuthenticator.authenticate(any(HttpServletRequest.class), any(HttpServletResponse.class))) .thenReturn(new KerberosPrincipal(principal)); registerFilter(mockAuthenticator); }
From source file:ddf.security.assertion.impl.SecurityAssertionImpl.java
@Override public Principal getPrincipal() { if (securityToken != null) { if (principal == null || !principal.getName().equals(name)) { String authMethod = null; if (authenticationStatements != null) { for (AuthnStatement authnStatement : authenticationStatements) { AuthnContext authnContext = authnStatement.getAuthnContext(); if (authnContext != null) { AuthnContextClassRef authnContextClassRef = authnContext.getAuthnContextClassRef(); if (authnContextClassRef != null) { authMethod = authnContextClassRef.getAuthnContextClassRef(); }// ww w .j a va 2s. c o m } } } if (SAML2Constants.AUTH_CONTEXT_CLASS_REF_X509.equals(authMethod) || SAML2Constants.AUTH_CONTEXT_CLASS_REF_SMARTCARD_PKI.equals(authMethod) || SAML2Constants.AUTH_CONTEXT_CLASS_REF_SOFTWARE_PKI.equals(authMethod) || SAML2Constants.AUTH_CONTEXT_CLASS_REF_SPKI.equals(authMethod) || SAML2Constants.AUTH_CONTEXT_CLASS_REF_TLS_CLIENT.equals(authMethod)) { principal = new X500Principal(name); } else if (SAML2Constants.AUTH_CONTEXT_CLASS_REF_KERBEROS.equals(authMethod)) { principal = new KerberosPrincipal(name); } else if (principal instanceof GuestPrincipal || name.startsWith(GuestPrincipal.GUEST_NAME_PREFIX)) { principal = new GuestPrincipal(name); } else { principal = new AssertionPrincipal(name); } } return principal; } return null; }
From source file:com.xebialabs.overthere.cifs.winrm.WinRmClient.java
private void configureHttpClient(final DefaultHttpClient httpclient) throws GeneralSecurityException { configureTrust(httpclient);/*from w w w .ja v a 2s . c om*/ configureAuthentication(httpclient, BASIC, new BasicUserPrincipal(username)); if (enableKerberos) { String spnServiceClass = kerberosUseHttpSpn ? "HTTP" : "WSMAN"; httpclient.getAuthSchemes().register(KERBEROS, new WsmanKerberosSchemeFactory(!kerberosAddPortToSpn, spnServiceClass, unmappedAddress, unmappedPort)); httpclient.getAuthSchemes().register(SPNEGO, new WsmanSPNegoSchemeFactory(!kerberosAddPortToSpn, spnServiceClass, unmappedAddress, unmappedPort)); configureAuthentication(httpclient, KERBEROS, new KerberosPrincipal(username)); configureAuthentication(httpclient, SPNEGO, new KerberosPrincipal(username)); } httpclient.getParams().setBooleanParameter(HANDLE_AUTHENTICATION, true); }
From source file:com.xebialabs.overthere.winrm.WinRmClient.java
private void configureHttpClient(final HttpClientBuilder httpclient) throws GeneralSecurityException { configureTrust(httpclient);/*from w w w . j a v a 2 s. c om*/ BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); httpclient.setDefaultCredentialsProvider(credentialsProvider); configureAuthentication(credentialsProvider, BASIC, new BasicUserPrincipal(username)); if (enableKerberos) { String spnServiceClass = kerberosUseHttpSpn ? "HTTP" : "WSMAN"; RegistryBuilder<AuthSchemeProvider> authSchemeRegistryBuilder = RegistryBuilder.create(); authSchemeRegistryBuilder.register(KERBEROS, new WsmanKerberosSchemeFactory(!kerberosAddPortToSpn, spnServiceClass, unmappedAddress, unmappedPort)); authSchemeRegistryBuilder.register(SPNEGO, new WsmanSPNegoSchemeFactory(!kerberosAddPortToSpn, spnServiceClass, unmappedAddress, unmappedPort)); httpclient.setDefaultAuthSchemeRegistry(authSchemeRegistryBuilder.build()); configureAuthentication(credentialsProvider, KERBEROS, new KerberosPrincipal(username)); configureAuthentication(credentialsProvider, SPNEGO, new KerberosPrincipal(username)); } httpclient.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(soTimeout).build()); httpclient.setDefaultRequestConfig( RequestConfig.custom().setAuthenticationEnabled(true).setConnectTimeout(connectionTimeout).build()); }
From source file:net.java.jaspicoil.MSPacSpnegoServerAuthModule.java
private Subject fetchSubjectFromLoginModuleWithPrincipal(String jaasContextName, String servicePrincipal, Krb5LoginConfig loginConfig) throws LoginException { final Set<Principal> princ = new HashSet<Principal>(1); princ.add(new KerberosPrincipal(servicePrincipal)); // Create a new editable Subject final Subject sub = new Subject(false, princ, new HashSet<Object>(), new HashSet<Object>()); return fetchSubjectFromLoginModule(jaasContextName, sub, loginConfig); }
From source file:io.druid.security.kerberos.KerberosAuthenticator.java
private String getPrincipalFromRequestNew(HttpServletRequest req) { String authorization = req//w w w . ja va 2s .co m .getHeader(org.apache.hadoop.security.authentication.client.KerberosAuthenticator.AUTHORIZATION); if (authorization == null || !authorization .startsWith(org.apache.hadoop.security.authentication.client.KerberosAuthenticator.NEGOTIATE)) { return null; } else { authorization = authorization.substring( org.apache.hadoop.security.authentication.client.KerberosAuthenticator.NEGOTIATE.length()) .trim(); final Base64 base64 = new Base64(0); final byte[] clientToken = base64.decode(authorization); try { DerInputStream ticketStream = new DerInputStream(clientToken); DerValue[] values = ticketStream.getSet(clientToken.length, true); // see this link for AP-REQ format: https://tools.ietf.org/html/rfc1510#section-5.5.1 for (DerValue value : values) { if (isValueAPReq(value)) { APReq apReq = new APReq(value); Ticket ticket = apReq.ticket; EncryptedData encData = ticket.encPart; int eType = encData.getEType(); // find the server's key EncryptionKey finalKey = null; Subject serverSubj = loginContext.getSubject(); Set<Object> serverCreds = serverSubj.getPrivateCredentials(Object.class); for (Object cred : serverCreds) { if (cred instanceof KeyTab) { KeyTab serverKeyTab = (KeyTab) cred; KerberosPrincipal serverPrincipal = new KerberosPrincipal(this.serverPrincipal); KerberosKey[] serverKeys = serverKeyTab.getKeys(serverPrincipal); for (KerberosKey key : serverKeys) { if (key.getKeyType() == eType) { finalKey = new EncryptionKey(key.getKeyType(), key.getEncoded()); break; } } } } if (finalKey == null) { log.error("Could not find matching key from server creds."); return null; } // decrypt the ticket with the server's key byte[] decryptedBytes = encData.decrypt(finalKey, KeyUsage.KU_TICKET); decryptedBytes = encData.reset(decryptedBytes); EncTicketPart decrypted = new EncTicketPart(decryptedBytes); String clientPrincipal = decrypted.cname.toString(); return clientPrincipal; } } } catch (Exception ex) { Throwables.propagate(ex); } } return null; }
From source file:io.druid.security.kerberos.KerberosAuthenticator.java
private void initializeKerberosLogin() throws ServletException { String principal;/*w ww . j a v a 2 s . c o m*/ String keytab; try { principal = SecurityUtil.getServerPrincipal(serverPrincipal, node.getHost()); if (principal == null || principal.trim().length() == 0) { throw new ServletException("Principal not defined in configuration"); } keytab = serverKeytab; if (keytab == null || keytab.trim().length() == 0) { throw new ServletException("Keytab not defined in configuration"); } if (!new File(keytab).exists()) { throw new ServletException("Keytab does not exist: " + keytab); } Set<Principal> principals = new HashSet<Principal>(); principals.add(new KerberosPrincipal(principal)); Subject subject = new Subject(false, principals, new HashSet<Object>(), new HashSet<Object>()); DruidKerberosConfiguration kerberosConfiguration = new DruidKerberosConfiguration(keytab, principal); log.info("Login using keytab " + keytab + ", for principal " + principal); loginContext = new LoginContext("", subject, null, kerberosConfiguration); loginContext.login(); log.info("Initialized, principal %s from keytab %s", principal, keytab); } catch (Exception ex) { throw new ServletException(ex); } }
From source file:net.java.jaspicoil.MSPacSpnegoServerAuthModule.java
/** * Authenticate a received service request. * <p/>/*from w w w .jav a2 s. c o m*/ * This method is called to transform the mechanism-specific request message * acquired by calling getRequestMessage (on messageInfo) into the validated * application message to be returned to the message processing runtime. If * the received message is a (mechanism-specific) meta-message, the method * implementation must attempt to transform the meta-message into a * corresponding mechanism-specific response message, or to the validated * application request message. The runtime will bind a validated * application message into the the corresponding service invocation. * <p> * This method conveys the outcome of its message processing either by * returning an AuthStatus value or by throwing an AuthException. * <p/> * From a performance point of view this method will be called twice for * each resource with a security constraint on it. Resources with no * security constraint do not result in a call to this method. * * @param messageInfo * A contextual object that encapsulates the client request and * server response objects, and that may be used to save state * across a sequence of calls made to the methods of this * interface for the purpose of completing a secure message * exchange. * @param clientSubject * A Subject that represents the source of the service request. * It is used by the method implementation to store Principals * and credentials validated in the request. * @param serviceSubject * A Subject that represents the recipient of the service * request, or null. It may be used by the method implementation * as the source of Principals or credentials to be used to * validate the request. If the Subject is not null, the method * implementation may add additional Principals or credentials * (pertaining to the recipient of the service request) to the * Subject. * @return An AuthStatus object representing the completion status of the * processing performed by the method. The AuthStatus values that * may be returned by this method are defined as follows: * <p/> * <ul> * <li>AuthStatus.SUCCESS when the application request message was * successfully validated. The validated request message is * available by calling getRequestMessage on messageInfo. * <p/> * <li>AuthStatus.SEND_SUCCESS to indicate that * validation/processing of the request message successfully * produced the secured application response message (in * messageInfo). The secured response message is available by * calling getResponseMessage on messageInfo. * <p/> * <li>AuthStatus.SEND_CONTINUE to indicate that message validation * is incomplete, and that a preliminary response was returned as * the response message in messageInfo. * <p/> * When this status value is returned to challenge an application * request message, the challenged request must be saved by the * authentication module such that it can be recovered when the * module's validateRequest message is called to process the request * returned for the challenge. * <p/> * <li>AuthStatus.SEND_FAILURE to indicate that message validation * failed and that an appropriate failure response message is * available by calling getResponseMessage on messageInfo. * </ul> * @throws AuthException When the message processing failed without * establishing a failure response message (in messageInfo). */ @SuppressWarnings("unchecked") public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { // Extra check (disabled withour -ea) if mandatory value is consistent // with initialize phase assert messageInfo.getMap().containsKey(IS_MANDATORY_INFO_KEY) == this.mandatory; // Get the servlet context final HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage(); final HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage(); // Invalidate any existing session to prevent session fixture attempt HttpSession session = request.getSession(false); if (session != null) { final SessionState state = (SessionState) session.getAttribute(MAGIC_SESSION_STATE_KEY); if (state == null) { // Session was not created by us, we will invalidate an existing // session that was not created by us session.invalidate(); LOG.warning( "An existing session was invalidated. This might be a session fixture attempt, so failing the authentication."); return AuthStatus.SEND_FAILURE; } else if (SessionState.ESTABLISHED.equals(state)) { // The context was already fully established once within this // session. return AuthStatus.SUCCESS; } } debugRequest(request); // should specify encoder final String authorization = request.getHeader(AUTHORIZATION_HEADER); if (authorization != null && authorization.startsWith(NEGOTIATE)) { final String negotiateString = authorization.substring(NEGOTIATE.length() + 1); final byte[] requestToken = Base64.decodeBase64(negotiateString); if (serviceSubject == null) { // If no service subject was provided by the container then set // a service subject // from the global context. serviceSubject = this.serviceSubject; } try { // Create a validation action byte[] gssToken = null; final KerberosValidateAction kva = new KerberosValidateAction(this.servicePrincipal, requestToken, serviceSubject); try { // Validate using the service (server) Subject gssToken = Subject.doAs(this.serviceSubject, kva); } catch (final PrivilegedActionException e) { final GSSException gex = new GSSException(GSSException.DEFECTIVE_TOKEN); gex.initCause(e); gex.setMinor(GSSException.UNAVAILABLE, "Unable to perform Kerberos validation"); throw gex; } if (kva.getContext() != null) { final String responseToken = Base64.encodeBase64String(gssToken); response.setHeader(AUTHENTICATION_HEADER, "Negotiate " + responseToken); debugToken("GSS Response token set to {0}", gssToken); } if (!kva.isEstablished()) { debug("GSS Dialog must continue to succeed"); session.setAttribute(MAGIC_SESSION_STATE_KEY, SessionState.IN_PROGRESS); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return AuthStatus.SEND_CONTINUE; } else { final Oid mechId = kva.getMech(); final GSSName name = kva.getSrcName(); if (!authorizeCaller(request, requestToken, name, clientSubject)) { return sendFailureMessage(response, "Failed to authorize the caller/client"); } // As no valid session should exist anymore, simply create a // new one session = request.getSession(true); final Principal clientPrincipal = new KerberosPrincipal( name.canonicalize(GSS_KRB5_MECH_OID).toString()); updateSessionAndHeader(request, session, clientPrincipal); session.setAttribute(MAGIC_SESSION_STATE_KEY, SessionState.ESTABLISHED); /* * Store the mechId in the MessageInfo to indicate which * authentication mechanism was used successfully (JASPIC * Requirement) */ messageInfo.getMap().put(AUTH_TYPE_INFO_KEY, mechId != null ? mechId.toString() : "Undefined GSS Mechanism"); debug("GSS Dialog is complete"); } } catch (final GSSException gsse) { debug("GSS Dialog has failed : {0}", gsse); if (requestToken != null) { debug("Bad token detected {0}", gsse); debugToken("Bad token was {0}", requestToken); if (isNTLMToken(requestToken)) { // There is a high probability it was a NTLM SPNEGO // token return sendFailureMessage(response, "No support for NTLM"); } } // for other errors throw an AuthException final AuthException ae = new AuthException(); ae.initCause(gsse); throw ae; } } else if (this.mandatory) { response.setHeader(AUTHENTICATION_HEADER, NEGOTIATE); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); debug("Negotiate was added to the HTTP header : {0}", NEGOTIATE); return AuthStatus.SEND_CONTINUE; } else if (authorization != null) { LOG.warning("An authorization header was ignored."); } return AuthStatus.SUCCESS; }