001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.geronimo.jetty; 019 020 import java.security.AccessControlContext; 021 import java.security.AccessControlException; 022 import java.security.Principal; 023 import java.security.cert.X509Certificate; 024 import java.util.HashMap; 025 026 import javax.security.auth.Subject; 027 import javax.security.auth.login.LoginContext; 028 import javax.security.auth.login.LoginException; 029 import javax.security.jacc.WebRoleRefPermission; 030 031 import org.apache.commons.logging.Log; 032 import org.apache.commons.logging.LogFactory; 033 import org.apache.geronimo.security.ContextManager; 034 import org.apache.geronimo.security.realm.providers.CertificateCallbackHandler; 035 import org.apache.geronimo.security.realm.providers.ClearableCallbackHandler; 036 import org.apache.geronimo.security.realm.providers.PasswordCallbackHandler; 037 import org.mortbay.http.HttpRequest; 038 039 040 /** 041 * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $ 042 */ 043 public class InternalJAASJettyRealm { 044 private static Log log = LogFactory.getLog(InternalJAASJettyRealm.class); 045 046 private final String securityRealmName; 047 private final HashMap userMap = new HashMap(); 048 private int count = 1; 049 050 public InternalJAASJettyRealm(String geronimoRealmName) { 051 this.securityRealmName = geronimoRealmName; 052 } 053 054 public String getSecurityRealmName() { 055 return securityRealmName; 056 } 057 058 public Principal getPrincipal(String username) { 059 return (Principal) userMap.get(username); 060 } 061 062 public Principal authenticate(String username, Object credentials, HttpRequest request) { 063 try { 064 if ((username != null) && (!username.equals(""))) { 065 066 JAASJettyPrincipal userPrincipal = (JAASJettyPrincipal) userMap.get(username); 067 068 //user has been previously authenticated, but 069 //re-authentication has been requested, so remove them 070 if (userPrincipal != null) { 071 userMap.remove(username); 072 } 073 074 ClearableCallbackHandler callbackHandler; 075 if (credentials instanceof char[]) { 076 char[] password = (char[]) credentials; 077 callbackHandler = new PasswordCallbackHandler(username, password); 078 } else if (credentials instanceof String) { 079 char[] password = ((String) credentials).toCharArray(); 080 callbackHandler = new PasswordCallbackHandler(username, password); 081 } else if (credentials instanceof X509Certificate[]) { 082 X509Certificate[] certs = (X509Certificate[]) credentials; 083 if (certs.length < 1) { 084 throw new LoginException("no certificates supplied"); 085 } 086 callbackHandler = new CertificateCallbackHandler(certs[0]); 087 } else { 088 throw new LoginException("Cannot extract credentials from class: " + credentials.getClass().getName()); 089 } 090 091 //set up the login context 092 LoginContext loginContext = new LoginContext(securityRealmName, callbackHandler); 093 loginContext.login(); 094 callbackHandler.clear(); 095 096 Subject subject = ContextManager.getServerSideSubject(loginContext.getSubject()); 097 //TODO use the run-as subject as nextCaller 098 ContextManager.setCallers(subject, subject); 099 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 }