001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.geronimo.jetty6;
018
019 import java.security.AccessControlContext;
020 import java.security.AccessControlException;
021 import java.security.Principal;
022 import java.security.cert.X509Certificate;
023 import java.util.HashMap;
024
025 import javax.security.auth.Subject;
026 import javax.security.auth.login.LoginContext;
027 import javax.security.auth.login.LoginException;
028 import javax.security.jacc.WebRoleRefPermission;
029
030 import org.apache.commons.logging.Log;
031 import org.apache.commons.logging.LogFactory;
032 import org.apache.geronimo.security.ContextManager;
033 import org.apache.geronimo.security.realm.providers.CertificateCallbackHandler;
034 import org.apache.geronimo.security.realm.providers.ClearableCallbackHandler;
035 import org.apache.geronimo.security.realm.providers.PasswordCallbackHandler;
036 import org.mortbay.jetty.Request;
037
038
039 /**
040 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
041 */
042 public class InternalJAASJettyRealm {
043 private static Log log = LogFactory.getLog(InternalJAASJettyRealm.class);
044
045 private final String securityRealmName;
046 private final HashMap<String, Principal> userMap = new HashMap<String, Principal>();
047 private int count = 1;
048
049 public InternalJAASJettyRealm(String geronimoRealmName) {
050 this.securityRealmName = geronimoRealmName;
051 }
052
053 public String getSecurityRealmName() {
054 return securityRealmName;
055 }
056
057 public Principal getPrincipal(String username) {
058 return userMap.get(username);
059 }
060
061 public Principal authenticate(String username, Object credentials, Request request) {
062 try {
063 if ((username != null) && (!username.equals(""))) {
064
065 JAASJettyPrincipal userPrincipal = (JAASJettyPrincipal) userMap.get(username);
066
067 //user has been previously authenticated, but
068 //re-authentication has been requested, so remove them
069 if (userPrincipal != null) {
070 userMap.remove(username);
071 }
072
073 ClearableCallbackHandler callbackHandler;
074 if (credentials instanceof char[]) {
075 char[] password = (char[]) credentials;
076 callbackHandler = new PasswordCallbackHandler(username, password);
077 } else if (credentials instanceof String) {
078 char[] password = ((String) credentials).toCharArray();
079 callbackHandler = new PasswordCallbackHandler(username, password);
080 } else if (credentials instanceof X509Certificate[]) {
081 X509Certificate[] certs = (X509Certificate[]) credentials;
082 if (certs.length < 1) {
083 throw new LoginException("no certificates supplied");
084 }
085 callbackHandler = new CertificateCallbackHandler(certs[0]);
086 } else {
087 throw new LoginException("Cannot extract credentials from class: " + credentials.getClass().getName());
088 }
089
090 //set up the login context
091 LoginContext loginContext = ContextManager.login(securityRealmName, callbackHandler);
092 callbackHandler.clear();
093
094 Subject subject = loginContext.getSubject();
095 ContextManager.setCallers(subject, subject);
096
097 //login success
098 userPrincipal = new JAASJettyPrincipal(username);
099 userPrincipal.setSubject(subject);
100
101 userMap.put(username, userPrincipal);
102
103 return userPrincipal;
104 } else {
105 log.debug("Login Failed - null userID");
106 return null;
107 }
108
109 } catch (LoginException e) {
110 log.debug("Login Failed", e);
111 return null;
112 }
113 }
114
115 public void logout(Principal user) {
116 JAASJettyPrincipal principal = (JAASJettyPrincipal) user;
117
118 userMap.remove(principal.getName());
119 ContextManager.unregisterSubject(principal.getSubject());
120 }
121
122 public boolean reauthenticate(Principal user) {
123 // TODO This is not correct if auth can expire! We need to
124
125 Subject subject = ((JAASJettyPrincipal) user).getSubject();
126 ContextManager.setCallers(subject, subject);
127
128 // get the user out of the cache
129 return (userMap.get(user.getName()) != null);
130 }
131
132 public void disassociate(Principal user) {
133 // do nothing
134 }
135
136 public boolean isUserInRole(Principal user, String role) {
137 if (user == null || role == null) {
138 return false;
139 }
140
141 AccessControlContext acc = ContextManager.getCurrentContext();
142 try {
143 // JACC v1.0 secion B.19
144 String servletName = InternalJettyServletHolder.getCurrentServletName();
145 if (servletName == null || servletName.equals("jsp")) {
146 servletName = "";
147 }
148 acc.checkPermission(new WebRoleRefPermission(servletName, role));
149 } catch (AccessControlException e) {
150 return false;
151 }
152 return true;
153 }
154
155 public Principal pushRole(Principal user, String role) {
156 //handled by JettyServletHolder and its runAsSubject
157 return user;
158 }
159
160 public Principal popRole(Principal user) {
161 return user;
162 }
163
164 public void addUse() {
165 count++;
166 }
167
168 public int removeUse() {
169 return count--;
170 }
171
172 }