View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.security.jaspi.modules;
20  
21  import java.io.IOException;
22  import java.nio.charset.StandardCharsets;
23  import java.util.Map;
24  import java.util.Set;
25  
26  import javax.security.auth.Subject;
27  import javax.security.auth.callback.Callback;
28  import javax.security.auth.callback.CallbackHandler;
29  import javax.security.auth.callback.UnsupportedCallbackException;
30  import javax.security.auth.message.AuthException;
31  import javax.security.auth.message.AuthStatus;
32  import javax.security.auth.message.MessageInfo;
33  import javax.security.auth.message.MessagePolicy;
34  import javax.security.auth.message.callback.CallerPrincipalCallback;
35  import javax.security.auth.message.callback.GroupPrincipalCallback;
36  import javax.security.auth.message.config.ServerAuthContext;
37  import javax.security.auth.message.module.ServerAuthModule;
38  import javax.servlet.http.HttpServletRequest;
39  import javax.servlet.http.HttpServletResponse;
40  
41  import org.eclipse.jetty.security.authentication.LoginCallbackImpl;
42  import org.eclipse.jetty.security.jaspi.JaspiMessageInfo;
43  import org.eclipse.jetty.security.jaspi.callback.CredentialValidationCallback;
44  import org.eclipse.jetty.util.B64Code;
45  import org.eclipse.jetty.util.security.Credential;
46  import org.eclipse.jetty.util.security.Password;
47  
48  /**
49   * @version $Rev: 4792 $ $Date: 2009-03-18 22:55:52 +0100 (Wed, 18 Mar 2009) $
50   */
51  public class BaseAuthModule implements ServerAuthModule, ServerAuthContext
52  {
53      private static final Class[] SUPPORTED_MESSAGE_TYPES = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
54  
55      protected static final String LOGIN_SERVICE_KEY = "org.eclipse.jetty.security.jaspi.modules.LoginService";
56  
57      protected CallbackHandler callbackHandler;
58  
59      public Class[] getSupportedMessageTypes()
60      {
61          return SUPPORTED_MESSAGE_TYPES;
62      }
63  
64      public BaseAuthModule()
65      {
66      }
67  
68      public BaseAuthModule(CallbackHandler callbackHandler)
69      {
70          this.callbackHandler = callbackHandler;
71      }
72  
73      public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, Map options) throws AuthException
74      {
75          this.callbackHandler = handler;
76      }
77  
78      public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException
79      {
80          // TODO apparently we either get the LoginCallback or the LoginService
81          // but not both :-(
82          // Set<LoginCallback> loginCallbacks =
83          // subject.getPrivateCredentials(LoginCallback.class);
84          // if (!loginCallbacks.isEmpty()) {
85          // LoginCallback loginCallback = loginCallbacks.iterator().next();
86          // }
87          // try {
88          // loginService.logout(subject);
89          // } catch (ServerAuthException e) {
90          // throw new AuthException(e.getMessage());
91          // }
92      }
93  
94      public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException
95      {
96          // servlets do not need secured responses
97          return AuthStatus.SEND_SUCCESS;
98      }
99  
100     public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException
101     {
102         return AuthStatus.SEND_FAILURE;
103     }
104 
105     /**
106      * @param messageInfo message info to examine for mandatory flag
107      * @return whether authentication is mandatory or optional
108      */
109     protected boolean isMandatory(MessageInfo messageInfo)
110     {
111         String mandatory = (String) messageInfo.getMap().get(JaspiMessageInfo.MANDATORY_KEY);
112         if (mandatory == null) return false;
113         return Boolean.valueOf(mandatory);
114     }
115 
116     protected boolean login(Subject clientSubject, String credentials, 
117                             String authMethod, MessageInfo messageInfo) 
118     throws IOException, UnsupportedCallbackException
119     {
120         credentials = credentials.substring(credentials.indexOf(' ')+1);
121         credentials = B64Code.decode(credentials, StandardCharsets.ISO_8859_1);
122         int i = credentials.indexOf(':');
123         String userName = credentials.substring(0,i);
124         String password = credentials.substring(i+1);
125         return login(clientSubject, userName, new Password(password), authMethod, messageInfo);
126     }
127 
128     protected boolean login(Subject clientSubject, String username, 
129                             Credential credential, String authMethod, 
130                             MessageInfo messageInfo) 
131     throws IOException, UnsupportedCallbackException
132     {
133         CredentialValidationCallback credValidationCallback = new CredentialValidationCallback(clientSubject, username, credential);
134         callbackHandler.handle(new Callback[] { credValidationCallback });
135         if (credValidationCallback.getResult())
136         {
137             Set<LoginCallbackImpl> loginCallbacks = clientSubject.getPrivateCredentials(LoginCallbackImpl.class);
138             if (!loginCallbacks.isEmpty())
139             {
140                 LoginCallbackImpl loginCallback = loginCallbacks.iterator().next();
141                 CallerPrincipalCallback callerPrincipalCallback = new CallerPrincipalCallback(clientSubject, loginCallback.getUserPrincipal());
142                 GroupPrincipalCallback groupPrincipalCallback = new GroupPrincipalCallback(clientSubject, loginCallback.getRoles());
143                 callbackHandler.handle(new Callback[] { callerPrincipalCallback, groupPrincipalCallback });
144             }
145             messageInfo.getMap().put(JaspiMessageInfo.AUTH_METHOD_KEY, authMethod);
146         }
147         return credValidationCallback.getResult();
148 
149     }
150 }