GSSAPISASLMechanismHandler.java revision ea1068c292e9b341af6d6b563cd8988a96be20a9
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2006-2009 Sun Microsystems, Inc.
* Portions Copyright 2011-2015 ForgeRock AS
*/
/**
* This class provides an implementation of a SASL mechanism that
* authenticates clients through Kerberos v5 over GSSAPI.
*/
public class GSSAPISASLMechanismHandler extends
SASLMechanismHandler<GSSAPISASLMechanismHandlerCfg> implements
{
// The DN of the configuration entry for this SASL mechanism handler.
private DN configEntryDN;
// The current configuration for this SASL mechanism handler.
// The identity mapper that will be used to map identities.
private IdentityMapper<?> identityMapper;
// The properties to use when creating a SASL server to process the
// GSSAPI authentication.
// The fully qualified domain name used when creating the SASL server.
private String serverFQDN;
// The login context used to perform server-side authentication.
private volatile LoginContext loginContext;
/**
* Creates a new instance of this SASL mechanism handler. No
* initialization should be done in this method, as it should all be
* performed in the <CODE>initializeSASLMechanismHandler</CODE>
* method.
*/
public GSSAPISASLMechanismHandler()
{
super();
}
/**
* {@inheritDoc}
*/
public void initializeSASLMechanismHandler(
try {
this.configuration = configuration;
}
catch (UnknownHostException unhe)
{
LocalizableMessage message = ERR_SASL_CANNOT_GET_SERVER_FQDN.get(configEntryDN, getExceptionMessage(unhe));
}
catch (IOException ioe)
{
}
}
/**
* Checks to make sure that the ds-cfg-kdc-address and dc-cfg-realm
* are both defined in the configuration. If only one is set, then
* that is an error. If both are defined, or, both are null that is
* fine.
*
* @param configuration
* The configuration to use.
* @throws InitializationException
* If the properties violate the requirements.
*/
throws InitializationException
{
{
throw new InitializationException(message);
}
else if (kdcAddress != null)
{
}
}
/**
* During login, callbacks are usually used to prompt for passwords.
* All of the GSSAPI login information is provided in the properties
* and login.conf file, so callbacks are ignored.
*
* @param callbacks
* An array of callbacks to process.
* @throws UnsupportedCallbackException
* if an error occurs.
*/
{
}
/**
* Returns the fully qualified name either defined in the
* configuration, or, determined by examining the system
* configuration.
*
* @param configuration
* The configuration to check.
* @return The fully qualified hostname of the server.
* @throws UnknownHostException
* If the name cannot be determined from the system
* configuration.
*/
throws UnknownHostException
{
if (serverName == null)
{
}
return serverName;
}
/**
*
* Return the login context. If it's not been initialized yet,
* create a login context or login using the principal and keytab
* information specified in the configuration.
*
* @return the login context
* @throws LoginException
* If a login context cannot be created.
*/
{
if (loginContext == null)
{
synchronized (loginContextLock)
{
if (loginContext == null)
{
loginContext = new LoginContext(
GSSAPISASLMechanismHandler.class.getName(), this);
}
}
}
return loginContext;
}
/**
* Logout of the current login context.
*/
private void logout()
{
try
{
synchronized (loginContextLock)
{
if (loginContext != null)
{
loginContext = null;
}
}
}
catch (LoginException e)
{
logger.traceException(e);
}
}
/**
* Creates an login.conf file from information in the specified
* configuration. This file is used during the login phase.
*
* @param configuration
* The new configuration to use.
* @return The filename of the new configuration file.
* @throws IOException
* If the configuration file cannot be created.
*/
private String configureLoginConfFile(
throws IOException, InitializationException {
w.newLine();
w.write(" com.sun.security.auth.module.Krb5LoginModule required "
+ "storeKey=true useKeyTab=true doNotPrompt=true ");
if(keyTabFilePath == null) {
}
if(!keyTabFile.exists()) {
throw new InitializationException(msg);
}
if (principalName != null)
{
}
else
{
}
{
}
w.write("\" isInitiator=false;");
w.newLine();
w.write("};");
w.newLine();
w.flush();
w.close();
return configFileName;
}
/**
* {@inheritDoc}
*/
public void finalizeSASLMechanismHandler() {
logout();
if(configuration != null)
{
}
}
private void clearProperties() {
}
/**
* {@inheritDoc}
*/
{
if (connection == null)
{
return;
}
if (saslContext == null) {
try {
} catch (SaslException ex) {
} else {
}
return;
}
}
try
{
}
catch (LoginException ex)
{
// Log a configuration error.
}
}
/**
* Get the underlying GSSException messages that really tell what the
* problem is. The major code is the GSS-API status and the minor is the
* mechanism specific error.
*
* @param gex The GSSException thrown.
*
* @return The message containing the major and (optional) minor codes and
* strings.
*/
}
/**
* {@inheritDoc}
*/
{
// This is not a password-based mechanism.
return false;
}
/**
* {@inheritDoc}
*/
{
// This may be considered a secure mechanism.
return true;
}
/**
* {@inheritDoc}
*/
public boolean isConfigurationAcceptable(
{
}
/**
* {@inheritDoc}
*/
public boolean isConfigurationChangeAcceptable(
boolean isAcceptable = true;
try
{
}
catch (UnknownHostException ex)
{
isAcceptable = false;
}
if(keyTabFilePath == null) {
}
if(!keyTabFile.exists()) {
isAcceptable = false;
}
{
isAcceptable = false;
}
return isAcceptable;
}
/**
* {@inheritDoc}
*/
{
try
{
logout();
this.configuration = newConfiguration;
}
catch (InitializationException ex) {
} catch (UnknownHostException ex) {
} catch (IOException ex) {
}
return ccr;
}
/**
* Try to initialize the GSSAPI mechanism handler with the specified config.
*
* @param config The configuration to use.
*
* @throws UnknownHostException
* If a host name does not resolve.
* @throws IOException
* If there was a problem creating the login file.
* @throws InitializationException
* If the keytab file does not exist.
*/
{
}
/**
* Retrieves the QOP (quality-of-protection) from the specified
* configuration.
*
* @param configuration
* The new configuration to use.
* @return A string representing the quality-of-protection.
*/
{
return "auth-conf";
return "auth-int";
else
return "auth";
}
}