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: 565912 $ $Date: 2007-08-14 17:03:11 -0400 (Tue, 14 Aug 2007) $ 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 = ContextManager.getServerSideSubject(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 }