mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

neil_a_wilson
17.29.2007 d9572cbdff869801cecc5bf653c3449062de07bc
Update the dseecompat access control implementation to provide a mechanism for
detecting and warning administrators about the use of non-canonical hostnames
in the "dns" bind rule. The dns bind rule requires that all addresses be
provided in canonical form or they will not match the intended target.

This change also includes special handling for the "localhost" name. In the
event that it does not match its canonical representation, then the
corresponding rule will automatically allow the canonical name as well. This
may be needed in some environments because the canonical hostname for the
loopback address may be something else, like "localhost.localdomain", and the
hostname "localhost" is likely to appear more commonly than other kinds of
hostnames.

With these changes, a number of reported mysterious ACI failures should go away
and the AciTests should now pass cleanly.

OpenDS Issue Number: 1385
2 files modified
119 ■■■■■ changed files
opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java 50 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/DNS.java 69 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java
@@ -621,6 +621,38 @@
         CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_NOTICE | 60;
    /**
     * The message ID for the message that will be used if an "aci" attribute
     * includes a dns hostname of "localhost" that does not match the canonical
     * representation which means that it will likely never match.  This takes
     * three arguments, which are the DNS bind rule expression, the hostname
     * used in the access control rule, and the canonical hostname associated
     * with that name.
     */
    public static final int MSGID_ACI_LOCALHOST_DOESNT_MATCH_CANONICAL_VALUE =
        CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 61;
    /**
     * The message ID for the message that will be used if an "aci" attribute
     * includes a dns hostname that does not match the canonical representation,
     * which means that it will likely never match.  This takes four arguments,
     * which are the DNS bind rule expression, the hostname used in the access
     * control rule, an IP address to which that name resolves, and the
     * canonical hostname associated with that IP address.
     */
    public static final int MSGID_ACI_HOSTNAME_DOESNT_MATCH_CANONICAL_VALUE =
        CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 62;
    /**
     * The message ID for the message that will be used if an error occurs while
     * attempting to determine whether a DNS hostname used in an access control
     * rule matches its canonical representation.  This takes three arguments,
     * which are the hostname used in the access control rule, the DNS bind rule
     * expression, and a string representation of the exception that was caught.
     */
    public static final int MSGID_ACI_ERROR_CHECKING_CANONICAL_HOSTNAME =
        CATEGORY_MASK_ACCESS_CONTROL | SEVERITY_MASK_SEVERE_WARNING | 63;
    /**
     * Associates a set of generic messages with the message IDs defined in
     * this class.
     */
@@ -757,6 +789,24 @@
                "keyword wild-card expression value requires the '*' " +
                "character only be in the leftmost position of the " +
                "domain name.");
        registerMessage(MSGID_ACI_HOSTNAME_DOESNT_MATCH_CANONICAL_VALUE,
                "The provided Access Control Instruction (ACI) bind rule " +
                "dns expression value \"%s\" references hostname %s, but " +
                "the canonical representation for that hostname is " +
                "configured to be %s.  The server will attempt to " +
                "automatically interpret the correct localhost value.");
        registerMessage(MSGID_ACI_HOSTNAME_DOESNT_MATCH_CANONICAL_VALUE,
                "The provided Access Control Instruction (ACI) bind rule " +
                "dns expression value \"%s\" references hostname %s, which " +
                "resolves to IP address %s, but the canonical hostname for " +
                "that IP address is %s.  This likely means that the " +
                "provided hostname will never match any clients.");
        registerMessage(MSGID_ACI_ERROR_CHECKING_CANONICAL_HOSTNAME,
                "An error occurred while attempting to determine whether " +
                "hostname %s referenced in dns expression bind rule \"%s\" " +
                "used the correct canonical representation:  %s.  This " +
                "likely means that the provided hostname will never match " +
                "any clients.");
        registerMessage(MSGID_ACI_SYNTAX_INVALID_DAYOFWEEK,
                "The provided Access Control Instruction (ACI) bind rule " +
opends/src/server/org/opends/server/authorization/dseecompat/DNS.java
@@ -29,10 +29,17 @@
import static org.opends.server.authorization.dseecompat.AciMessages.*;
import static org.opends.server.authorization.dseecompat.Aci.*;
import static org.opends.server.loggers.Error.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.messages.MessageHandler.getMessage;
import static org.opends.server.util.StaticUtils.*;
import java.net.InetAddress;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
/**
 * This class implements the dns bind rule keyword.
@@ -101,6 +108,68 @@
                    throw new AciException(msgID, message);
                }
            }
            // If the provided hostname does not contain any wildcard
            // characters, then it must be the canonical hostname for the
            // associated IP address.  If it is not, then it will not match the
            // intended target, and we should generate a warning message to let
            // the administrator know about it.  If the provided value does not
            // match the canonical name for the associated IP address, and the
            // given hostname is "localhost", then we should treat it specially
            // and also match the canonical hostname.  This is necessary because
            // "localhost" is likely to be very commonly used in these kinds of
            // rules and on some systems the canonical representation is
            // configured to be "localhost.localdomain" which may not be known
            // to the administrator.
            if (hn.indexOf("*") < 0)
            {
              try
              {
                for (InetAddress addr : InetAddress.getAllByName(hn))
                {
                  String canonicalName = addr.getCanonicalHostName();
                  if (! hn.equalsIgnoreCase(canonicalName))
                  {
                    if (hn.equalsIgnoreCase("localhost") &&
                        (! dns.contains(canonicalName)))
                    {
                      dns.add(canonicalName);
                      int msgID =
                           MSGID_ACI_LOCALHOST_DOESNT_MATCH_CANONICAL_VALUE;
                      String message = getMessage(msgID, expr, hn,
                                                  canonicalName);
                      logError(ErrorLogCategory.ACCESS_CONTROL,
                               ErrorLogSeverity.SEVERE_WARNING, message, msgID);
                    }
                    else
                    {
                      int msgID =
                           MSGID_ACI_HOSTNAME_DOESNT_MATCH_CANONICAL_VALUE;
                      String message = getMessage(msgID, expr,
                                                  hn, addr.getHostAddress(),
                                                  addr.getCanonicalHostName());
                      logError(ErrorLogCategory.ACCESS_CONTROL,
                               ErrorLogSeverity.SEVERE_WARNING, message, msgID);
                    }
                  }
                }
              }
              catch (Exception e)
              {
                if (debugEnabled())
                {
                  debugCaught(DebugLogLevel.ERROR, e);
                }
                int msgID = MSGID_ACI_ERROR_CHECKING_CANONICAL_HOSTNAME;
                String message = getMessage(msgID, hn, expr,
                                            stackTraceToSingleLineString(e));
                logError(ErrorLogCategory.ACCESS_CONTROL,
                         ErrorLogSeverity.SEVERE_WARNING, message, msgID);
              }
            }
            dns.add(hn);
        }
        return new DNS(dns, type);