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]