View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  package org.apache.geronimo.jetty;
19  
20  import java.security.AccessControlContext;
21  import java.security.AccessControlException;
22  import java.security.Principal;
23  import java.security.cert.X509Certificate;
24  import java.util.HashMap;
25  
26  import javax.security.auth.Subject;
27  import javax.security.auth.login.LoginContext;
28  import javax.security.auth.login.LoginException;
29  import javax.security.jacc.WebRoleRefPermission;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.geronimo.security.ContextManager;
34  import org.apache.geronimo.security.realm.providers.CertificateCallbackHandler;
35  import org.apache.geronimo.security.realm.providers.ClearableCallbackHandler;
36  import org.apache.geronimo.security.realm.providers.PasswordCallbackHandler;
37  import org.mortbay.http.HttpRequest;
38  
39  
40  /**
41   * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
42   */
43  public class InternalJAASJettyRealm {
44      private static Log log = LogFactory.getLog(InternalJAASJettyRealm.class);
45  
46      private final String securityRealmName;
47      private final HashMap userMap = new HashMap();
48      private int count = 1;
49  
50      public InternalJAASJettyRealm(String geronimoRealmName) {
51          this.securityRealmName = geronimoRealmName;
52      }
53  
54      public String getSecurityRealmName() {
55          return securityRealmName;
56      }
57  
58      public Principal getPrincipal(String username) {
59          return (Principal) userMap.get(username);
60      }
61  
62      public Principal authenticate(String username, Object credentials, HttpRequest request) {
63          try {
64              if ((username != null) && (!username.equals(""))) {
65  
66                  JAASJettyPrincipal userPrincipal = (JAASJettyPrincipal) userMap.get(username);
67  
68                  //user has been previously authenticated, but
69                  //re-authentication has been requested, so remove them
70                  if (userPrincipal != null) {
71                      userMap.remove(username);
72                  }
73  
74                  ClearableCallbackHandler callbackHandler;
75                  if (credentials instanceof char[]) {
76                      char[] password = (char[]) credentials;
77                      callbackHandler = new PasswordCallbackHandler(username, password);
78                  } else if (credentials instanceof String) {
79                      char[] password = ((String) credentials).toCharArray();
80                      callbackHandler = new PasswordCallbackHandler(username, password);
81                  } else if (credentials instanceof X509Certificate[]) {
82                      X509Certificate[] certs = (X509Certificate[]) credentials;
83                      if (certs.length < 1) {
84                          throw new LoginException("no certificates supplied");
85                      }
86                      callbackHandler = new CertificateCallbackHandler(certs[0]);
87                  } else {
88                      throw new LoginException("Cannot extract credentials from class: " + credentials.getClass().getName());
89                  }
90  
91                  //set up the login context
92                  LoginContext loginContext = new LoginContext(securityRealmName, callbackHandler);
93                  loginContext.login();
94                  callbackHandler.clear();
95  
96                  Subject subject = ContextManager.getServerSideSubject(loginContext.getSubject());
97                  //TODO use the run-as subject as nextCaller
98                  ContextManager.setCallers(subject, subject);
99                  ContextManager.setNextCaller(subject);
100 
101                 //login success
102                 userPrincipal = new JAASJettyPrincipal(username);
103                 userPrincipal.setSubject(subject);
104 
105                 userMap.put(username, userPrincipal);
106 
107                 return userPrincipal;
108             } else {
109                 log.debug("Login Failed - null userID");
110                 return null;
111             }
112 
113         } catch (LoginException e) {
114 //          log.warn("Login Failed", e);
115             log.debug("Login Failed", e);
116             return null;
117         }
118     }
119 
120     public void logout(Principal user) {
121         JAASJettyPrincipal principal = (JAASJettyPrincipal) user;
122 
123         userMap.remove(principal.getName());
124         ContextManager.unregisterSubject(principal.getSubject());
125     }
126 
127     public boolean reauthenticate(Principal user) {
128         // TODO This is not correct if auth can expire! We need to
129 
130         Subject subject = ((JAASJettyPrincipal) user).getSubject();
131         ContextManager.setCallers(subject, subject);
132 
133         // get the user out of the cache
134         return (userMap.get(user.getName()) != null);
135     }
136 
137     public void disassociate(Principal user) {
138         // do nothing
139     }
140 
141     public boolean isUserInRole(Principal user, String role) {
142         if (user == null || role == null) {
143             return false;
144         }
145 
146         AccessControlContext acc = ContextManager.getCurrentContext();
147         try {
148             // JACC v1.0 secion B.19
149             String servletName = JettyServletHolder.getCurrentServletName();
150             if (servletName.equals("jsp")) {
151                 servletName = "";
152             }
153             acc.checkPermission(new WebRoleRefPermission(servletName, role));
154         } catch (AccessControlException e) {
155             return false;
156         }
157         return true;
158     }
159 
160     public Principal pushRole(Principal user, String role) {
161         //handled by JettyServletHolder and its runAsSubject
162         return user;
163     }
164 
165     public Principal popRole(Principal user) {
166         return user;
167     }
168 
169     public void addUse() {
170         count++;
171     }
172 
173     public int removeUse() {
174         return count--;
175     }
176 
177 }