forked from spring-projects/spring-security-kerberos
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b434708
commit 958c705
Showing
3 changed files
with
242 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
139 changes: 139 additions & 0 deletions
139
...va/org/springframework/security/extensions/kerberos/client/KerberosLdapContextSource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
/* | ||
* Copyright 2015 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.springframework.security.extensions.kerberos.client; | ||
|
||
import java.security.PrivilegedAction; | ||
import java.util.Hashtable; | ||
import java.util.List; | ||
|
||
import javax.naming.AuthenticationException; | ||
import javax.naming.Context; | ||
import javax.naming.NamingException; | ||
import javax.naming.directory.DirContext; | ||
import javax.security.auth.Subject; | ||
import javax.security.auth.login.Configuration; | ||
import javax.security.auth.login.LoginContext; | ||
import javax.security.auth.login.LoginException; | ||
|
||
import org.springframework.beans.factory.InitializingBean; | ||
import org.springframework.ldap.core.support.LdapContextSource; | ||
import org.springframework.security.extensions.kerberos.client.config.SunJaasKrb5LoginConfig; | ||
import org.springframework.security.ldap.DefaultSpringSecurityContextSource; | ||
import org.springframework.util.Assert; | ||
|
||
/** | ||
* Implementation of an {@link LdapContextSource} that authenticates with the | ||
* ldap server using Kerberos. | ||
* | ||
* Example usage: | ||
* | ||
* <pre> | ||
* <bean id="authorizationContextSource" class="org.springframework.security.extensions.kerberos.ldap.KerberosLdapContextSource"> | ||
* <constructor-arg value="${authentication.ldap.ldapUrl}" /> | ||
* <property name="referral" value="ignore" /> | ||
* | ||
* <property name="loginConfig"> | ||
* <bean class="org.springframework.security.extensions.kerberos.client.config.SunJaasKrb5LoginConfig"> | ||
* <property name="servicePrincipal" value="${authentication.ldap.servicePrincipal}" /> | ||
* <property name="useTicketCache" value="true" /> | ||
* <property name="isInitiator" value="true" /> | ||
* <property name="debug" value="false" /> | ||
* </bean> | ||
* </property> | ||
* </bean> | ||
* | ||
* <sec:ldap-user-service id="ldapUserService" server-ref="authorizationContextSource" user-search-filter="(| (userPrincipalName={0}) (sAMAccountName={0}))" | ||
* group-search-filter="(member={0})" group-role-attribute="cn" role-prefix="none" /> | ||
* </pre> | ||
* | ||
* @see SunJaasKrb5LoginConfig | ||
* @author Nelson Rodrigues | ||
* | ||
*/ | ||
public class KerberosLdapContextSource extends DefaultSpringSecurityContextSource implements | ||
InitializingBean { | ||
|
||
private Configuration loginConfig; | ||
|
||
public KerberosLdapContextSource(String url) { | ||
super(url); | ||
} | ||
|
||
public KerberosLdapContextSource(List<String> urls, String baseDn) { | ||
super(urls, baseDn); | ||
} | ||
|
||
/** | ||
* The login configuration to get the serviceSubject from LoginContext | ||
* | ||
* @param loginConfig | ||
*/ | ||
public void setLoginConfig(Configuration loginConfig) { | ||
this.loginConfig = loginConfig; | ||
} | ||
|
||
@Override | ||
public void afterPropertiesSet() throws Exception { | ||
super.afterPropertiesSet(); | ||
|
||
Assert.notNull(this.loginConfig, "loginConfig must be specified"); | ||
} | ||
|
||
private Subject login() throws AuthenticationException { | ||
try { | ||
LoginContext lc = new LoginContext(KerberosLdapContextSource.class.getSimpleName(), | ||
null, null, this.loginConfig); | ||
|
||
lc.login(); | ||
|
||
return lc.getSubject(); | ||
} catch (LoginException e) { | ||
AuthenticationException ae = new AuthenticationException(e.getMessage()); | ||
ae.initCause(e); | ||
throw ae; | ||
} | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
@Override | ||
protected DirContext getDirContextInstance( | ||
final @SuppressWarnings("rawtypes") Hashtable environment) throws NamingException { | ||
environment.put(Context.SECURITY_AUTHENTICATION, "GSSAPI"); | ||
|
||
Subject serviceSubject = login(); | ||
|
||
final NamingException[] suppressedException = new NamingException[] { null }; | ||
DirContext dirContext = Subject.doAs(serviceSubject, new PrivilegedAction<DirContext>() { | ||
|
||
@Override | ||
public DirContext run() { | ||
try { | ||
return KerberosLdapContextSource.super.getDirContextInstance(environment); | ||
} catch (NamingException e) { | ||
suppressedException[0] = e; | ||
return null; | ||
} | ||
} | ||
}); | ||
|
||
if (suppressedException[0] != null) { | ||
throw suppressedException[0]; | ||
} | ||
|
||
return dirContext; | ||
} | ||
|
||
} |
102 changes: 102 additions & 0 deletions
102
...rg/springframework/security/extensions/kerberos/client/config/SunJaasKrb5LoginConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* Copyright 2015 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.springframework.security.extensions.kerberos.client.config; | ||
|
||
import java.util.HashMap; | ||
|
||
import javax.security.auth.login.AppConfigurationEntry; | ||
import javax.security.auth.login.Configuration; | ||
|
||
import org.springframework.beans.factory.InitializingBean; | ||
import org.springframework.core.io.Resource; | ||
import org.springframework.util.Assert; | ||
|
||
/** | ||
* Implementation of {@link Configuration} which uses Sun's JAAS | ||
* Krb5LoginModule. | ||
* | ||
* @author Nelson Rodrigues | ||
* | ||
*/ | ||
public class SunJaasKrb5LoginConfig extends Configuration implements InitializingBean { | ||
|
||
private String servicePrincipal; | ||
private Resource keyTabLocation; | ||
private Boolean useTicketCache = false; | ||
private Boolean isInitiator = false; | ||
private Boolean debug = false; | ||
|
||
private String keyTabExternalForm; | ||
|
||
public void setServicePrincipal(String servicePrincipal) { | ||
this.servicePrincipal = servicePrincipal; | ||
} | ||
|
||
public void setKeyTabLocation(Resource keyTabLocation) { | ||
this.keyTabLocation = keyTabLocation; | ||
} | ||
|
||
public void setUseTicketCache(Boolean useTicketCache) { | ||
this.useTicketCache = useTicketCache; | ||
} | ||
|
||
public void setIsInitiator(Boolean isInitiator) { | ||
this.isInitiator = isInitiator; | ||
} | ||
|
||
public void setDebug(Boolean debug) { | ||
this.debug = debug; | ||
} | ||
|
||
@Override | ||
public void afterPropertiesSet() throws Exception { | ||
Assert.hasText(servicePrincipal, "servicePrincipal must be specified"); | ||
|
||
if (!useTicketCache) { | ||
Assert.notNull(keyTabLocation, | ||
"keyTabLocation must be specified when useTicketCache is false"); | ||
this.keyTabExternalForm = keyTabLocation.getURL().toExternalForm(); | ||
} | ||
} | ||
|
||
@Override | ||
public AppConfigurationEntry[] getAppConfigurationEntry(String name) { | ||
HashMap<String, String> options = new HashMap<String, String>(); | ||
|
||
options.put("principal", this.servicePrincipal); | ||
|
||
if (this.keyTabLocation != null) { | ||
options.put("useKeyTab", "true"); | ||
options.put("keyTab", this.keyTabExternalForm); | ||
options.put("storeKey", "true"); | ||
} | ||
|
||
options.put("doNotPrompt", "true"); | ||
|
||
if (useTicketCache) { | ||
options.put("useTicketCache", "true"); | ||
options.put("renewTGT", "true"); | ||
} | ||
|
||
options.put("isInitiator", this.isInitiator.toString()); | ||
options.put("debug", this.debug.toString()); | ||
|
||
return new AppConfigurationEntry[] { new AppConfigurationEntry( | ||
"com.sun.security.auth.module.Krb5LoginModule", | ||
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, options), }; | ||
} | ||
|
||
} |