001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with 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, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020 021 package org.apache.geronimo.security.jaas; 022 023 import java.security.Principal; 024 import java.util.Arrays; 025 import java.util.Collections; 026 import java.util.HashSet; 027 import java.util.List; 028 import java.util.Map; 029 import java.util.Set; 030 031 import javax.security.auth.Subject; 032 import javax.security.auth.callback.CallbackHandler; 033 import javax.security.auth.login.LoginException; 034 import javax.security.auth.spi.LoginModule; 035 036 import org.apache.geronimo.security.DomainPrincipal; 037 import org.apache.geronimo.security.RealmPrincipal; 038 039 /** 040 * @version $Revision: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 041 */ 042 public class WrappingLoginModule implements LoginModule { 043 public static final String CLASS_OPTION = WrappingLoginModule.class.getName() + ".LoginModuleClass"; 044 public static final String DOMAIN_OPTION = WrappingLoginModule.class.getName() + ".DomainName"; 045 public static final String REALM_OPTION = WrappingLoginModule.class.getName() + ".RealmName"; 046 public static final List<String> supportedOptions = Collections.unmodifiableList(Arrays.asList(CLASS_OPTION, DOMAIN_OPTION, REALM_OPTION)); 047 private String loginDomainName; 048 private String realmName; 049 private final Subject localSubject = new Subject(); 050 private Subject subject; 051 private LoginModule delegate; 052 private final Set<Principal> wrapped = new HashSet<Principal>(); 053 054 055 public WrappingLoginModule() { 056 } 057 058 public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) { 059 this.subject = subject; 060 Class lmClass = (Class) options.get(CLASS_OPTION); 061 try { 062 delegate = (LoginModule) lmClass.newInstance(); 063 } catch (Exception e) { 064 throw new RuntimeException("Could not create login module instance", e); 065 } 066 delegate.initialize(localSubject, callbackHandler, sharedState, options); 067 loginDomainName = (String) options.get(DOMAIN_OPTION); 068 realmName = (String) options.get(REALM_OPTION); 069 } 070 071 public boolean login() throws LoginException { 072 return delegate.login(); 073 } 074 075 public boolean abort() throws LoginException { 076 return delegate.abort(); 077 } 078 079 public boolean commit() throws LoginException { 080 boolean result = delegate.commit(); 081 082 for (Principal principal: localSubject.getPrincipals()) { 083 wrapped.add(new DomainPrincipal(loginDomainName, principal)); 084 wrapped.add(new RealmPrincipal(realmName, loginDomainName, principal)); 085 } 086 subject.getPrincipals().addAll(wrapped); 087 subject.getPrincipals().addAll(localSubject.getPrincipals()); 088 subject.getPrivateCredentials().addAll(localSubject.getPrivateCredentials()); 089 subject.getPublicCredentials().addAll(localSubject.getPublicCredentials()); 090 return result; 091 } 092 093 public boolean logout() throws LoginException { 094 if(!subject.isReadOnly()) { 095 subject.getPrincipals().removeAll(wrapped); 096 subject.getPrincipals().removeAll(localSubject.getPrincipals()); 097 subject.getPrivateCredentials().removeAll(localSubject.getPrivateCredentials()); 098 subject.getPublicCredentials().removeAll(localSubject.getPublicCredentials()); 099 wrapped.clear(); 100 } else { 101 wrapped.clear(); 102 localSubject.getPrincipals().clear(); 103 localSubject.setReadOnly(); // This will ensure that credentails are destroyed by the delegate's logout method 104 } 105 106 return delegate.logout(); 107 } 108 }