Just read the Submit Patch post and understand that - have
winCVS and am gettting aquainted with it ...

I am adding two new classes and patching two others heavily.

The attached files are my contribution to James for the CIDR
process we spoke of earlier.

It compiles and runs - I will be testing this more later on
this afternoon, but in the meantime, I thought I would pass
them off for review.

I can diff the RemoteAddressInNetwork and
RemortAddressNotInNetwork and pass those in as patches, but
without the other two classes, they are meaningless.

Thanks for your time ...
Alan



----- Message Forwarded on 2003-02-09 -----
From: "alan.gerhard" <[EMAIL PROTECTED]>
To: "James Users List" <[EMAIL PROTECTED]>
Subject: RE: CIDR Notation
Date: Sun, 02 Feb 2003 03:00:52 -0500

Noel -

You are suggesting to create a
apache.mailet.GenericAddressMatcher abstract that folds most
of the 'common' code of the RemoteAddrInNetwork and
RemoteAddrNotInNetwork classes - similar to the
GenericRecipientMatcher abstract ..

Okay - I'll have a good at it;
see what I can come up with.



> Alan,
>
> I don't believe that you are missing something.  It isn't
> an oversight, just nothing that anyone got around to.
> When I first picked up the code, it didn't accept domain
> names, either.  I think I have some code for CIDR around
> here somewhere, but never finished adding it to those
> matchers.
>
> Actually, if you're going to do it, I suggest that you
> take those matchers, factor out most of the code into
> GenericAddressMatcher, and then subclass them for the
> specific behavior.  That'll make it easier to enhance them
> in the future.
>
>     --- Noel
/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 */
package org.apache.james.util;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.math.BigInteger;
import java.util.StringTokenizer;

/**
  *   RFC 1518, 1519 - Classless Inter-Domain Routing (CIDR)
  *   Known as 'Slash Notation' where an IP address range is described as
  *   IPADDRESS / SUBMASK =>
  *       60.182.194.0/24 =>
  *           a Class C =>
  *               60.182.194.0 - 60.182.194.255
  *
  *   Simple class used to validate and check a given IP addresses against
  *   the allowed range as described above
  *
  *   As of 2003-02-08 System.out.println() needs to be either piped back to caller
  *   or switched with DEEP_DEBUG boolean; currently, with error, output is sent to 
the console
  *
  *   @author Alan Gerhard    <[EMAIL PROTECTED]>
  *   @version This is $Revision: 5 $
  */

public class CIDR  {
    /**
      *   Stirng constants based on the expected characters as defined for the CIDR 
Notation
      */
    private String  SLASH = "/";
    private String  DOT = ".";

    /**
      * Method to check whether or not the given InetAddress object falls within
      * the sub-net as described by the given CIDR String.
      * @param pInetObj - an InetAddress object to be tesed
      * @paran pCIDR - a String representation of a CIDR subnet definition
      * @param pValidate - boolean specifying weather to validate the CIDR or not
      * @return ( addressInSubnet(pInetObj.getHostAddress(), pCIDR, pValidate) )
      */
    public boolean addressInSubnet ( InetAddress pInetObj, String pCIDR, boolean 
pValidate ) {
        return( addressInSubnet ( pInetObj.getHostAddress(), pCIDR, pValidate) );
    }   //  EoM

    /**
      * Method to check whether or not the given string IP Address ( 127.0.0.1 ) falls 
within
      * the sub-net as described by the given CIDR String.
      * @param pInetObj - a String representation of a valid IP address to be tesed
      * @paran pCIDR - a String representation of a CIDR subnet definition
      * @param pValidate - boolean specifying weather to validate the CIDR or not
      * @return true if pIPAddr is within the subnet as defined by pCIDR
      */
    public boolean addressInSubnet ( String pIPAddr, String pCIDR, boolean pValidate  
) {
        if (pValidate ) {
            if ( !validCIDR(pCIDR) ) {
                System.out.println("CIDR [" + pCIDR + "] is not valid");
                return (false);
            }
        }

        BigInteger theMask = new BigInteger ( mkBinaryMask(pCIDR),2 );

        BigInteger testIPAddress = new BigInteger 
(mkBinaryAddress(pIPAddr).substring(0,mkBinaryMask(pCIDR).length()), 2 );

        BigInteger theCIDR = new BigInteger (mkBinaryAddress(pCIDR.substring(0, 
pCIDR.indexOf(SLASH))).substring(0,mkBinaryMask(pCIDR).length()), 2 );

        return (testIPAddress.and(theMask).equals(theCIDR));

    }   //  EoM


    /** validCIDR will check the given CIDR string aginst it's defined mask such that
      * the given IPAddress & MASK shall equal 0
      * <BR>example:
      * <BR>  255.255.255.16/28                     256.256.132.0/11
      * <BR>  CIDR = FFFFFF10                       CIDR = FFFF8400
      * <BR>  MASK = 0000000F                       MASK = 000007FF
      * <BR>  CIDR & MASK == 0    => Good           MASK & CIDR != 0    =>  Bad
      * @paran pCIDR - a String representation of a CIDR subnet definition
      * @return true if pCIDR is valid as defined above
      */
    public boolean validCIDR ( String pCIDR ) {

        if ( (pCIDR.indexOf(SLASH) > 0 ) && (pCIDR.indexOf(DOT) > 0) ) {

            if ( Math.abs(Integer.parseInt(pCIDR.substring( pCIDR.indexOf(SLASH) + 1 
))) < 33) {

                BigInteger mask = new BigInteger ( mkBinaryTestMask(pCIDR),2 );
                BigInteger ipAddr = new BigInteger ( 
mkBinaryAddress(pCIDR.substring(0, pCIDR.indexOf(SLASH))),2 );

                return ( ipAddr.and(mask).longValue() == 0);

            } else {
                System.out.println("Invalid BIT Mask number\n\r");
            }
        } else {
                System.out.println("Invalid CIDR format\n\r");
        }

        return (false);
    }   //EoM


    /** Builds the binary string used to create a Big Integer
      * based on the validted CIDR string as follows -
      * number of bits to make = 32 - CIDR/N
      * This will mask off the bottom side and is used to validate the IP CIDR address
      * Please note special case for CIDR/0
      */
    private String mkBinaryTestMask ( String pCIDR ) {
        String rVal = new String("");
            //  Special case for 0 - needs to be ZERO
        if (Integer.parseInt(pCIDR.substring( pCIDR.indexOf(SLASH) + 1 )) > 0 ) {
            for ( int x=0; x < 32 - Integer.parseInt(pCIDR.substring( 
pCIDR.indexOf(SLASH) + 1 )); x++) {
                rVal = rVal.concat("1");
            }
        }
        return ((rVal.length() == 0) ? ("0") : (rVal) );
    }   //  EoM

   /** Builds the binary string used to create a Big Integer
     * based on the validted CIDR string
     * This is used to test the target IP with the sub-net
     */
    private String mkBinaryMask ( String pCIDR ) {
        String rVal = new String("");
        for ( int x=0; x < Integer.parseInt(pCIDR.substring( pCIDR.indexOf(SLASH) + 1 
)); x++) {
            rVal = rVal.concat("1");
        }
        return ((rVal.length() == 0) ? ("0") : (rVal) );
    }   //  EoM

    /** mkBinary will generate a binary representation string from an IP address 
represented
      * in string form as four octets in decimal notation
      *   Example => 66.181.193.2
      */
    private String mkBinaryAddress ( String pIPAdr ) {
        String rVal = new String("");
        StringTokenizer st = new StringTokenizer(pIPAdr,".");
        while (st.hasMoreTokens()) {
            int tInt = Integer.parseInt(st.nextToken());
            rVal = rVal.concat (
                    ("00000000").concat(Integer.toBinaryString(tInt)).substring(
                    ("00000000").concat(Integer.toBinaryString(tInt)).length()  - 8 )
            );
        }
        return ( rVal );
    }   //  EoM

    /** mkBinary will generate a binary representation string from an IP address as 
returned from
      * InetAddress.getLocalHost() in a byte array in Network Byte Order.
      * Note the signed byte values ...
      * Not used in this class but provided here for future expansion
      */
    private String mkBinaryAddress ( byte[] bRay) {
        String rVal = new String("");
        for ( int x = 0; x < bRay.length; x++ ) {
            rVal = rVal.concat (
                    ("00000000").concat(Integer.toBinaryString( ((int)bRay[x]) & 
255)).substring(
                    ("00000000").concat(Integer.toBinaryString( ((int)bRay[x]) & 
255)).length() - 8 )
            );
        }
        return (rVal);
    }   //  EoM

}   //  EoC


/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 */
package org.apache.mailet;

import org.apache.james.util.CIDR;

import javax.mail.MessagingException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;
import java.util.StringTokenizer;
import java.net.InetAddress;
import java.net.UnknownHostException;


/**
  * GenericAddressMatcher makes writing IPAddress based matchers easier.
  * <BR>See <I>GenericMatcher</I> for reference.
  * <P>This implments the CIDR ( slash notation ) method for determining sub-networks.
  * <UL>Networks can be indicated with
  *   <LI>wildcards(*) 192.168.*
  *   <LI>by name 'domain.tld'
  *   <LI>slash notation 192.168.100.0/24
  *   </UL>
  * <BR>Note: All representations will be converted to CIDR notation and matches are 
made
  *   based on a target IPAddress against a CIDR string.
  * <BR>Multiple addresses can be indicated, e.g: '127.0.0.1,192.168.*,domain.tld'
  *
  * @version 1.0.0, 02/08/2003
  * @author Alan Gerhard <[EMAIL PROTECTED]>
  */
public abstract class GenericAddressMatcher extends GenericMatcher {

    protected Collection lstCIDR = null;        //  Contains only VALID CIDR string 
representations
    protected   CIDR objCIDR = null;

    public final void init() throws MessagingException {
        StringTokenizer st = new StringTokenizer(getCondition(), ", ", false);
        lstCIDR = new Vector();
        objCIDR = new CIDR();
        while (st.hasMoreTokens()) {
            String addr = st.nextToken();
            try {

                // 1st  -   Add address of local machine as a match
                if (addr.equals("127.0.0.1")) {
                    InetAddress localaddr = InetAddress.getLocalHost();
                    addr = localaddr.getHostAddress().concat("/32");
                }
                // 2nd  -    A name or an explicit address,
                if (addr.indexOf("/") == -1) {
                    //  otherwise an exception should be thrown
                    addr = InetAddress.getByName(addr).getHostAddress().concat("/32");
                }
                //  3rd -   An asterisk  mask
                if (addr.endsWith("*")) {
                    //  Expand out to CIDR Notation
                    //  *               =>  255.255.255.255/0
                    //  xxx.*           =>  255.255.255.255/8
                    //  xxx.xxx.*       =>  255.255.255.255/16
                    //  xxx.xxx.xxx.*   =>  255.255.255.255/24
                    //  xxx.xxx.xxx.x*  =>  255.255.255.2??/?? -> this is not allowed
                    //                                            it becomes 
=>xxx.xxx.xxx.*
                    String[] masks = {  "0.0.0.0/0", "0.0.0/8", "0.0/16", "0/24" };
                    int[] iPositions = { 0,0,0 };
                    int iPos = 0;
                    for (int x=0; x < addr.length(); x++){
                        if ( addr.substring(x,x+1).equalsIgnoreCase(".") ) {
                            iPositions [ iPos++ ] = x;
                        }
                    }
                    addr = (iPos > 0)
                            ? ( addr.substring(0,iPositions [ iPos -1 ] + 
1).concat(masks[iPos]) )
                            : (masks[iPos]);
                }

                if ( objCIDR.validCIDR(addr)) {
                    lstCIDR.add( addr );
                } else {
                    log("Invalid CIDR String [" + addr + "]");
                }

            } catch (UnknownHostException uhe) {
                log("Cannot resolve address: " + uhe.getMessage());
            }
        }

    }   //  EoM

}
org\apache\james\util\CIDR - new

org\apache\mailet\GenericAddressMatcher -       new

org\apache\james\transport\matchers\RemoteAddrInNetwork -       modified to use the 
new GenericAddressMatcher
org\apache\james\transport\matchers\RemoteAddrNotInNetwork -    modified to use the 
new GenericAddressMatcher



config.xml
find -
         <!-- matcher can be configured with a comma separated list of IP addresses  
-->
         <!-- wildcarded IP subnets, and wildcarded hostname subnets. -->
         <!-- e.g. "RemoteAddrNotInNetwork=127.0.0.1, abc.de.*, 192.168.0.*" -->
         <!-- -->
                
replace with
         <!-- matcher can be configured with a comma separated list of IP addresses,  
-->
         <!-- host names, wildcarded IP subnets, wildcarded hostname subnets, 
         <!--   and CIDR subnet specifications. -->
         <!-- e.g. "RemoteAddrNotInNetwork=127.0.0.1, doamain.com, 192.168.0.*, 
168.192.100.0/24" -->
         <!-- All addresses will be converted to CIDR notation; only valid CIDR 
representations will be used -->
         <!-- -->
/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 */
package org.apache.james.transport.matchers;

import org.apache.mailet.GenericAddressMatcher;
import org.apache.mailet.Mail;

import java.util.Collection;
import java.util.Iterator;


/**
 * Checks the IP address of the sending server against the CIDR Collection
 * as defined by lstCIDR (see GenericAddressMatcher init())
 * @author  Serge Knystautas <[EMAIL PROTECTED]>
 * @author  Alan Gerhard <[EMAIL PROTECTED]>
 */
public class RemoteAddrInNetwork extends GenericAddressMatcher {
    private boolean VALIDATE = false;       //  Only valid CIDR's are in the lstCIDR 
collection

    public Collection match(Mail mail) {
        String hostIP = mail.getRemoteAddr();
        //Check to see whether it's in any of the networks
        for (Iterator i = lstCIDR.iterator(); i.hasNext(); ) {
            if (objCIDR.addressInSubnet (hostIP, i.next().toString(), VALIDATE)) {
                //This is in this network... that's all we need for a match
                return mail.getRecipients();
            }
        }
        //Could not match this to any network
        return null;
    }
}
/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 */
package org.apache.james.transport.matchers;

import org.apache.mailet.GenericAddressMatcher;
import org.apache.mailet.Mail;

import javax.mail.MessagingException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.Vector;

/**
 * Checks the IP address of the sending server against the CIDR Collection
 * as defined by lstCIDR (see GenericAddressMatcher init())
 * @author  Serge Knystautas <[EMAIL PROTECTED]>
 * @author  Alan Gerhard <[EMAIL PROTECTED]>
 */
public class RemoteAddrNotInNetwork extends GenericAddressMatcher {

    private boolean VALIDATE = false;       //  Only valid CIDR's are in the lstCIDR 
collection

    public Collection match(Mail mail) {
        String hostIP = mail.getRemoteAddr();
        //Check to see whether it's in any of the networks
        for (Iterator i = lstCIDR.iterator(); i.hasNext(); ) {
            if (objCIDR.addressInSubnet (hostIP, i.next().toString(), VALIDATE)) {
                //This is in this network... that's all we need for a failed match
                return null;
            }
        }
        //Could not match this to any network
        return mail.getRecipients();
    }
}

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to