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

dugan
05.35.2007 4834c06ae25b70b8b6fc7e84987dafd0e71d6c4e
Fix for unresolved issue 670 that can be fixed  using some code from from a previous fix for issue 471. Issue 670.
3 files modified
288 ■■■■■ changed files
opends/src/server/org/opends/server/messages/ProtocolMessages.java patch | view | raw | blame | history
opends/src/server/org/opends/server/types/AddressMask.java 158 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestAddressMask.java 130 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/messages/ProtocolMessages.java
opends/src/server/org/opends/server/types/AddressMask.java
@@ -30,19 +30,14 @@
import static org.opends.server.messages.ProtocolMessages.*;
import static org.opends.server.messages.MessageHandler.*;
import java.util.BitSet;
//This import statements causes problems in checkstyles so
//it has been turned off until issue #??? is fixed.
//import sun.net.util.IPAddressUtil;
//import java.net.Inet6Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
 * This class defines an address mask, which can be used to perform
 * efficient comparisons against IP addresses to determine whether a
 * particular IP address is in a given range.
 * Currently IPV6 is not supported. Issue #670 will track IPV6
 * support.
 */
public final class AddressMask
@@ -52,7 +47,7 @@
     * Types of rules we have.
     *
     * IPv4 - ipv4 rule
     * IPv6 - ipv6 rule (begin with '['). Not supported see issue #670
     * IPv6 - ipv6 rule (begin with '[' or contains an ':').
     * HOST - hostname match (foo.sun.com)
     * HOSTPATTERN - host pattern match (begin with '.')
     * ALLWILDCARD - *.*.*.* (first HOST is applied then ipv4)
@@ -61,7 +56,7 @@
     enum RuleType
    {
        IPv4, IPv6, HOSTPATTERN, ALLWILDCARD, HOST;
        IPv4, IPv6, HOSTPATTERN, ALLWILDCARD, HOST
    }
    // Type of rule determined
@@ -75,8 +70,8 @@
    private  int IPV4MAXPREFIX = 32;
    // IPv6 values for number of bytes and max CIDR prefix
    //private  int IN6ADDRSZ = 16;
    //private  int IPV6MAXPREFIX = 128;
    private  int IN6ADDRSZ = 16;
    private  int IPV6MAXPREFIX = 128;
    //Holds binary representations of rule and mask respectively.
    private  byte[] ruleMask, prefixMask;
@@ -104,14 +99,14 @@
        determineRuleType(rule);
        switch (ruleType)
        {
        case IPv6:
            processIPv6(rule);
             break;
        case IPv4:
            processIpv4(rule);
            break;
            /*            case IPv6:
                processIPv6(rule);
                break;
             */
        case HOST:
            processHost(rule);
            break;
@@ -148,13 +143,10 @@
        {
            ruleType=RuleType.HOSTPATTERN;
        }
        else if(ruleString.startsWith("["))
        else if(ruleString.startsWith("[") ||
                (ruleString.indexOf(':') != -1))
        {
            int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
            String message = getMessage(msgID);
            throw new ConfigException(msgID, message);
            //IPV6 is not supported see issue #670
            //ruleType=RuleType.IPv6;
           ruleType=RuleType.IPv6;
        }
        else
        {
@@ -164,16 +156,13 @@
            // hostname (can't begin with digit) or ipv4 address.
            //Default to IPv4 ruletype.
            ruleType=RuleType.HOST;
            for(int i=0;i<s.length;i++)
            {
                if(s[i].equals("*"))
                {
            for (String value : s) {
                if (value.equals("*")) {
                    wildCount++;
                    continue;
                }
                //Looks like an ipv4 address
                if(Character.isDigit(s[i].charAt(0)))
                {
                if (Character.isDigit(value.charAt(0))) {
                    ruleType=RuleType.IPv4;
                    break;
                }
@@ -196,10 +185,10 @@
    private void processIpv4(String rule)
    throws ConfigException {
        String[] s = rule.split("/", -1);
        ruleMask=new byte[IN4ADDRSZ];
        prefixMask=new byte[IN4ADDRSZ];
        this.ruleMask=new byte[IN4ADDRSZ];
        this.prefixMask=new byte[IN4ADDRSZ];
        prefixMask(processPrefix(s,IPV4MAXPREFIX));
        processIpv4Subnet((s.length == 0) ? rule : s[0]);
        processIPv4Subnet((s.length == 0) ? rule : s[0]);
    }
    /**
@@ -266,13 +255,13 @@
     */
    private void prefixMask(int prefix)
    {
        int i=0;
        int i;
        for( i=0;prefix > 8 ; i++)
        {
            prefixMask[i] = (byte) 0xff;
            this.prefixMask[i] = (byte) 0xff;
            prefix -= 8;
        }
        prefixMask[i] = (byte) ((0xff) << (8 - prefix));
        this.prefixMask[i] = (byte) ((0xff) << (8 - prefix));
    }
    /**
@@ -282,7 +271,7 @@
     * @throws ConfigException If the subnet string is not a valid
     *         IPv4 subnet string.
     */
    private void  processIpv4Subnet(String subnet)
    private void  processIPv4Subnet(String subnet)
    throws ConfigException {
        String[] s = subnet.split("\\.", -1);
        try {
@@ -400,9 +389,8 @@
            String remoteName,
            AddressMask[] masks)
    {
        for(int i=0; i < masks.length; i++)
        {
            if(masks[i].match(remoteAddr, remoteName))
        for (AddressMask mask : masks) {
            if(mask.match(remoteAddr, remoteName))
                return true;
        }
        return false;
@@ -431,6 +419,7 @@
        boolean ret=false;
        switch(ruleType) {
        case IPv6:
        case IPv4:
            //this Address mask is an IPv4 rule
            ret=matchAddress(remoteAddr);
@@ -441,15 +430,6 @@
            ret=matchHostName(remoteName);
            break;
            /*
          case IPv6:
              //IPv6 rule only valid of addr is an Inet6Address
              if(addr instanceof Inet6Address) {
                  Inet6Address addr6 = (Inet6Address) addr;
                  ret=match(addr6.getAddress());
              }
              break;
             */
        case HOSTPATTERN:
            //HOSTPATTERN rule
            ret=matchPattern(remoteName);
@@ -473,13 +453,9 @@
     */
    private boolean matchPattern(String remoteHostName) {
        int len=remoteHostName.length() - hostPattern.length();
        if(len > 0)
        {
            return remoteHostName.regionMatches(true,len,
        return len > 0 && remoteHostName.regionMatches(true, len,
                    hostPattern,0,hostPattern.length());
        }
        return false;
    }
    /**
     * Try to match remote client host name against rule host name.
@@ -532,48 +508,44 @@
        return true;
    }
    /* Turned off until IPV6 issue #670 is fixed.
  private void processIPv6(String rule)
  throws ConfigException {
      String[] s = rule.split("/", -1);
      //ipv6 rule must end with ']''
      if(!s[0].endsWith("]"))
      {
          int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
          String message = getMessage(msgID);
          throw new ConfigException(msgID,message);
      }
      String subnet  = s[0].substring(1, s[0].length() -1);
      byte[] tmpMask=IPAddressUtil.textToNumericFormatV6(subnet);
      //don't have a vaild ipv6 address bail
      if (tmpMask == null)
      {
          int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
          String message = getMessage(msgID);
          throw new ConfigException(msgID, message);remoteMask
      }
      //we were returned an ipv4-mapped address ::ffff:<ipv4 addr>
      //make sure we don't have a prefix
      if((tmpMask.length == IN4ADDRSZ)  &&
              (s.length == 2)) {
          int msgID = MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
          String message = getMessage(msgID);
          throw new ConfigException(msgID,  message);
       //build a ipv4 structure using a 32-bit prefix
      } else if (tmpMask.length == IN4ADDRSZ) {
          setRuleType(Rtype.IPv4);
          setRuleMask(tmpMask);
          setPrefixMask(new byte[IN4ADDRSZ]);
          prefixMask(32);
      } else { //plain Ipv6 address
          setRuleMask(tmpMask);
          setPrefixMask(new byte[IN6ADDRSZ]);
          prefixMask(processPrefix(s,IPV6MAXPREFIX));
          setRuleType(Rtype.IPv6);
      }
  }
    /**
     * The rule string is an IPv6 rule. Build both the prefix
     * mask array and rule mask from the string.
     *
     * @param rule The rule string containing the IPv6 rule.
     * @throws ConfigException If the rule string is not a valid
     *         IPv6 rule.
     */
     private void processIPv6(String rule) throws ConfigException {
        String[] s = rule.split("/", -1);
        InetAddress addr;
        try {
            addr = InetAddress.getByName(s[0]);
        } catch (UnknownHostException ex) {
            int msgID=MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
            String message = getMessage(msgID);
            throw new ConfigException(msgID, message);
        }
        if(addr instanceof Inet6Address) {
            this.ruleType=RuleType.IPv6;
            Inet6Address addr6 = (Inet6Address) addr;
            this.ruleMask=addr6.getAddress();
            this.prefixMask=new byte[IN6ADDRSZ];
            prefixMask(processPrefix(s,IPV6MAXPREFIX));
        } else {
           //The address might be an IPv4-compat address.
           //Throw an error if the rule has a prefix.
            if(s.length == 2) {
                int msgID = MSGID_ADDRESSMASK_FORMAT_DECODE_ERROR;
                String message = getMessage(msgID);
                throw new ConfigException(msgID,  message);
            }
            this.ruleMask=addr.getAddress();
            this.ruleType=RuleType.IPv4;
            this.prefixMask=new byte[IN4ADDRSZ];
            prefixMask(processPrefix(s,IPV4MAXPREFIX));
        }
    }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/types/TestAddressMask.java
@@ -26,12 +26,14 @@
 */
package org.opends.server.types;
import org.opends.server.types.AddressMask;
import org.opends.server.config.ConfigException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class TestAddressMask extends TypesTestCase {
    /* These are all valid rules -- should all pass. */
@@ -70,7 +72,6 @@
         {"129.**.56.67"},
         {"foo bar.com"},
         {"12foo.example.com"},
         {"[2001:fecd:ba23:cd1f:dcb1:1010:9234:4088]/124"},
         {"123.45."},
         {".central.sun day.com"},
         {"129.34.45.45/4/3/"}
@@ -206,7 +207,7 @@
 @Test(dataProvider = "matchRules")
 public void testMatch(String[] rules, String[] addrs, String[]hostNames) {
     boolean ret=true;
     boolean ret;
     ret=match(rules,addrs,hostNames);
     assertTrue(ret);
 }
@@ -214,7 +215,7 @@
 @Test(dataProvider = "matchWCRules")
 public void testWildCardMatch(String[] rules, String[] addrs,
         String[]hostNames) {
     boolean ret=true;
     boolean ret;
     ret=match(rules,addrs,hostNames);
     assertTrue(ret);
 }
@@ -222,7 +223,7 @@
 @Test(dataProvider = "noMatchRules")
 public void testNoMatch(String[] rules, String[] addrs,
         String[] hostNames) {
     boolean ret=false;
     boolean ret;
     ret=match(rules,addrs,hostNames);
     assertFalse(ret);
 }
@@ -239,22 +240,7 @@
     }
 }
 private byte[] getAddress(String remote) {
     byte[] addr=new byte[AddressMask.IN4ADDRSZ];
     String[] s = remote.split("\\.", -1);
     try {
         for(int i=0;i<AddressMask.IN4ADDRSZ;i++) {
             long val = Integer.parseInt(s[i]);
             addr[i] = (byte) (val & 0xff);
         }
     }  catch (NumberFormatException nfex) {
         return addr;
     }
     return addr;
 }
 private boolean match(String[] rules, String[] addrs,
         String[]hostNames) {
  private boolean match(String[] rules, String[] addrs,  String[]hostNames) {
     boolean ret=true;
     int i=0;
@@ -269,12 +255,110 @@
                 "> all data must be valid for this test");
     }
     for(int j =0; j < addrs.length; j++) {
         if(!AddressMask.maskListContains(getAddress(addrs[j]),
                 hostNames[j],m)) {
      try  {
        InetAddress addr = InetAddress.getByName(addrs[j]);
        if(!AddressMask.maskListContains(addr.getAddress(), hostNames[j], m)) {
             ret=false;
             break;
         }
      } catch (UnknownHostException ex) {
        ret=false;
      }
     }
     return ret;
 }
  /*
    IPV6 data and tests.
  */
  //Invalid IPv6 expressions.
  @DataProvider(name = "invalid6Rules")
  public Object[][] inValid6Data() {
        return new Object[][] {
                {"2001:feca:ba23:cd1f:dcb1:1010:9234:4088///124"},
                {"2001:feca:ba23:cd1f:dcb1:1010:9234:4088?124"},
                {"2001:fecz:ba23:cd1f:dcb1:1010:9234:4088/124"},
                {"2001:fecd:ba23:cd1ff:dcb1:1010:9234:4088/46"},
                {"0:0:0:0:0:ffff:101..45.75.219"},
                {"0:0:0:0:0:0:101.45.75.700"},
                {"1080::8:800:200C:417A/500"},
                {"1080::8:800:*:417A/66"},
                 {"2001:fecd:ba23:cd1ff:dcb1:1010:202.45.66.20"},
        };
  }
  //Valid IPv6 expressions.
  @DataProvider(name = "valid6Rules")
  public Object[][] valid6Data() {
      return new Object[][] {
              {"2001:fecd:ba23:cd1f:dcb1:1010:9234:4088/124"},
              {"2001:fecd:ba23:cd1f:dcb1:1010:9234:4088"},
              {"[2001:fecd:ba23:cd1f:dcb1:1010:9234:4088]/45"},
              {"::/128"},
              {"::1/128"},
              {"::"},
              {"0:0:0:0:0:ffff:101.45.75.219"},
              {"1080::8:800:200C:417A"},
              {"0:0:0:0:0:0:101.45.75.219"},
              {"::101.45.75.219"}
      };
  }
  @DataProvider(name = "match6Rules")
  public Object[][] ruleMatch6Data() {
     return new Object[][] {
             {
                 //IPV6 Rules
                 new String[] {
                         "[12ab:0:0:cd30::]/60",
                         "::ffff:72.56.78.9",
                         "::",
                         "42ab:0:0:dd30::"},
                //IPv6 Addresses
                new String[] {
                         "12ab:0:0:cd3f:0000:0000:23DC:DC30",
                         "72.56.78.9",
                         "::",
                         "42ab:0000:0000:dd30:0000:0000:0000:0000"},
              //ignored Hostnames
              new String[]  {
                         "ignored.host.name",
                         "ignored.host.name",
                         "ignored.host.name",
                         "ignored.host.name"
                         }
             }
     };
 }
 @Test(dataProvider = "valid6Rules")
  public void testValid6Decode(String mask)
          throws Exception {
    AddressMask.decode(mask);
  }
  @Test(expectedExceptions=ConfigException.class, dataProvider="invalid6Rules")
  public void testInvalid6Decode(String mask)
          throws Exception {
    try {
      AddressMask.decode(mask);
    } catch (ConfigException e) {
      throw e;
    } catch (Exception e) {
      System.out.println(
              "Invalid mask  <" + mask + "> threw wrong exception type.");
      throw e;
    }
    throw new RuntimeException(
            "Invalid mask <" + mask + "> did not throw an exception.");
  }
  @Test(dataProvider = "match6Rules")
  public void testMatch6(String[] rules, String[] addrs, String[]hostNames) {
      boolean ret;
      ret=match(rules,addrs,hostNames);
      assertTrue(ret);
  }
}