From d9572cbdff869801cecc5bf653c3449062de07bc Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Sat, 17 Mar 2007 22:29:12 +0000
Subject: [PATCH] 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.

---
 opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java |   50 +++++++++++++++++++++++++
 opends/src/server/org/opends/server/authorization/dseecompat/DNS.java         |   69 ++++++++++++++++++++++++++++++++++
 2 files changed, 119 insertions(+), 0 deletions(-)

diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java b/opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java
index fba579b..76856ca 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/AciMessages.java
+++ b/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 " +
diff --git a/opends/src/server/org/opends/server/authorization/dseecompat/DNS.java b/opends/src/server/org/opends/server/authorization/dseecompat/DNS.java
index 9bb3171..a2856ff 100644
--- a/opends/src/server/org/opends/server/authorization/dseecompat/DNS.java
+++ b/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);

--
Gitblit v1.10.0