/*
|
* 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
|
* or http://forgerock.org/license/CDDLv1.0.html.
|
* 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-2008 Sun Microsystems, Inc.
|
* Portions Copyright 2012-2014 ForgeRock AS
|
*/
|
package org.opends.server.admin;
|
|
|
|
import java.util.LinkedHashSet;
|
import java.util.LinkedList;
|
import java.util.List;
|
|
import org.opends.server.core.DirectoryServer;
|
import org.opends.server.protocols.internal.InternalClientConnection;
|
import org.opends.server.protocols.internal.InternalSearchOperation;
|
import org.opends.server.protocols.ldap.LDAPFilter;
|
import org.opends.server.schema.DirectoryStringSyntax;
|
import org.opends.server.types.Attribute;
|
import org.opends.server.types.AttributeType;
|
import org.opends.server.types.Attributes;
|
import org.forgerock.opendj.ldap.ByteString;
|
import org.opends.server.types.DN;
|
import org.opends.server.types.DereferencePolicy;
|
import org.opends.server.types.DirectoryException;
|
import org.opends.server.types.Entry;
|
import org.opends.server.types.LDAPException;
|
import org.opends.server.types.Modification;
|
import org.forgerock.opendj.ldap.ModificationType;
|
import org.opends.server.types.ResultCode;
|
import org.opends.server.types.SearchResultEntry;
|
import org.forgerock.opendj.ldap.SearchScope;
|
|
|
|
/**
|
* Check if information found in "cn=admin data" is coherent with
|
* cn=config. If and inconsistency is detected, we log a warning
|
* message and update "cn=admin data"
|
*/
|
public final class AdministrationDataSync
|
{
|
|
/**
|
* The root connection.
|
*/
|
private InternalClientConnection internalConnection;
|
|
/**
|
* The attribute name used to store the port. TODO Use the default
|
* one.
|
*/
|
private static final String LDAP_PORT = "ds-cfg-listen-port";
|
|
|
|
/**
|
* Create an object that will syncrhonize configuration and the
|
* admin data.
|
*
|
* @param internalConnection
|
* The root connection.
|
*/
|
public AdministrationDataSync(InternalClientConnection internalConnection)
|
{
|
this.internalConnection = internalConnection;
|
}
|
|
|
|
/**
|
* Check if information found in "cn=admin data" is coherent with
|
* cn=config. If and inconsistancy is detected, we log a warning
|
* message and update "cn=admin data"
|
*/
|
public void synchronize()
|
{
|
// Check if the admin connector is in sync
|
checkAdminConnector();
|
}
|
|
|
|
/**
|
* Check if the admin connector is in sync. The desynchronization
|
* could occurs after the upgrade from 1.0.
|
*/
|
private void checkAdminConnector()
|
{
|
// Look for the server registration in "cn=admin data"
|
DN serverEntryDN = searchServerEntry();
|
if (serverEntryDN == null)
|
{
|
// Nothing to do
|
return;
|
}
|
|
// Get the admin port
|
String adminPort = getAttr("cn=Administration Connector,cn=config",
|
LDAP_PORT);
|
if (adminPort == null)
|
{
|
// best effort.
|
return;
|
}
|
|
LinkedList<Modification> mods = new LinkedList<Modification>();
|
// adminport
|
String attName = "adminport";
|
AttributeType attrType = DirectoryServer.getAttributeType(attName
|
.toLowerCase());
|
if (attrType == null)
|
{
|
attrType = DirectoryServer.getDefaultAttributeType(attName.toLowerCase());
|
}
|
mods.add(new Modification(ModificationType.REPLACE, Attributes.create(
|
attrType, adminPort)));
|
|
// adminEnabled
|
attName = "adminEnabled";
|
attrType = DirectoryServer.getAttributeType(attName.toLowerCase());
|
if (attrType == null)
|
{
|
attrType = DirectoryServer.getDefaultAttributeType(attName.toLowerCase());
|
}
|
mods.add(new Modification(ModificationType.REPLACE, Attributes.create(
|
attrType, "true")));
|
|
// Process modification
|
internalConnection.processModify(serverEntryDN, mods);
|
}
|
|
|
|
/**
|
* Look for the DN of the local register server. Assumption: default
|
* Connection Handler naming is used.
|
*
|
* @return The DN of the local register server or null.
|
*/
|
private DN searchServerEntry()
|
{
|
DN returnDN = null;
|
|
// Get the LDAP and LDAPS port
|
String ldapPort = getAttr(
|
"cn=LDAP Connection Handler,cn=Connection Handlers,cn=config",
|
LDAP_PORT);
|
String ldapsPort = getAttr(
|
"cn=LDAPS Connection Handler,cn=Connection Handlers,cn=config",
|
LDAP_PORT);
|
boolean ldapsPortEnable = false;
|
String val = getAttr(
|
"cn=LDAPS Connection Handler,cn=Connection Handlers,cn=config",
|
"ds-cfg-enabled");
|
if (val != null)
|
{
|
ldapsPortEnable = val.toLowerCase().equals("true");
|
}
|
if ((ldapPort == null) && (ldapsPort == null))
|
{
|
// best effort (see assumption)
|
return null;
|
}
|
|
// Get the IP address of the local host.
|
String hostName;
|
try
|
{
|
hostName = java.net.InetAddress.getLocalHost().getCanonicalHostName();
|
}
|
catch (Throwable t)
|
{
|
// best effort.
|
return null;
|
}
|
|
// Look for a local server with the Ldap Port.
|
String attrName = "hostname";
|
AttributeType hostnameType = DirectoryServer.getAttributeType(attrName);
|
if (hostnameType == null)
|
{
|
hostnameType = DirectoryServer.getDefaultAttributeType(attrName);
|
}
|
try
|
{
|
InternalSearchOperation op = internalConnection.processSearch(
|
"cn=Servers,cn=admin data",
|
SearchScope.SINGLE_LEVEL, "objectclass=*");
|
if (op.getResultCode() == ResultCode.SUCCESS)
|
{
|
Entry entry = null;
|
for (Entry currentEntry : op.getSearchEntries())
|
{
|
String currentHostname = currentEntry.getAttributeValue(hostnameType,
|
DirectoryStringSyntax.DECODER);
|
try
|
{
|
String currentIPAddress = java.net.InetAddress.getByName(
|
currentHostname).getCanonicalHostName();
|
if (currentIPAddress.equals(hostName))
|
{
|
// Check if one of the port match
|
attrName = "ldapport";
|
AttributeType portType = DirectoryServer
|
.getAttributeType(attrName);
|
if (portType == null)
|
{
|
portType = DirectoryServer.getDefaultAttributeType(attrName);
|
}
|
String currentport = currentEntry.getAttributeValue(portType,
|
DirectoryStringSyntax.DECODER);
|
if (currentport.equals(ldapPort))
|
{
|
entry = currentEntry;
|
break;
|
}
|
if (ldapsPortEnable)
|
{
|
attrName = "ldapsport";
|
portType = DirectoryServer.getAttributeType(attrName);
|
if (portType == null)
|
{
|
portType = DirectoryServer.getDefaultAttributeType(attrName);
|
}
|
currentport = currentEntry.getAttributeValue(portType,
|
DirectoryStringSyntax.DECODER);
|
if (currentport.equals(ldapsPort))
|
{
|
entry = currentEntry;
|
break;
|
}
|
}
|
}
|
}
|
catch (Exception e)
|
{
|
// best effort.
|
continue;
|
}
|
}
|
|
if (entry != null)
|
{
|
returnDN = entry.getName();
|
}
|
}
|
|
}
|
catch (DirectoryException e)
|
{
|
// never happens because the filter is always valid.
|
return null;
|
}
|
return returnDN;
|
}
|
|
|
|
/**
|
* Gets an attribute value from an entry.
|
*
|
* @param DN
|
* The DN of the entry.
|
* @param attrName
|
* The attribute name.
|
* @return The attribute value or {@code null} if the value could
|
* not be retrieved.
|
*/
|
private String getAttr(String baseDN, String attrName)
|
{
|
// Prepare the ldap search
|
LDAPFilter filter;
|
try
|
{
|
filter = LDAPFilter.decode("objectclass=*");
|
}
|
catch (LDAPException e)
|
{
|
// can not happen
|
// best effort.
|
// TODO Log an Error.
|
return null;
|
}
|
|
LinkedHashSet<String> attributes = new LinkedHashSet<String>(1);
|
attributes.add(attrName);
|
InternalSearchOperation search = internalConnection.processSearch(
|
ByteString.valueOf(baseDN), SearchScope.BASE_OBJECT,
|
DereferencePolicy.DEREF_ALWAYS, 0, 0, false, filter, attributes);
|
|
if ((search.getResultCode() != ResultCode.SUCCESS))
|
{
|
// can not happen
|
// best effort.
|
// TODO Log an Error.
|
return null;
|
}
|
|
SearchResultEntry adminConnectorEntry = null;
|
|
/*
|
* Read the port from the PORT attribute
|
*/
|
LinkedList<SearchResultEntry> result = search.getSearchEntries();
|
if (!result.isEmpty())
|
{
|
adminConnectorEntry = result.getFirst();
|
}
|
|
AttributeType attrType = DirectoryServer.getAttributeType(attrName);
|
if (attrType == null)
|
{
|
attrType = DirectoryServer.getDefaultAttributeType(attrName);
|
}
|
|
List<Attribute> attrs = adminConnectorEntry.getAttribute(attrType);
|
|
if (attrs == null)
|
{
|
// can not happen
|
// best effort.
|
// TODO Log an Error.
|
return null;
|
}
|
|
// Get the attribute value
|
return attrs.get(0).iterator().next().toString();
|
}
|
|
}
|