001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2008 Sun Microsystems, Inc.
026     */
027    
028    package org.opends.server.authorization.dseecompat;
029    import org.opends.messages.Message;
030    
031    import static org.opends.messages.AccessControlMessages.*;
032    import java.util.regex.Pattern;
033    import java.util.*;
034    import java.net.InetAddress;
035    
036    /**
037     * This class represents a single ACI's IP bind rule expression. It is possble
038     * for that expression to contain several IP addresses to evaluate, so the
039     * class contains a list of classes that can evaluate a remote clients IP
040     * address for each IP address parsed from the bind rule.
041     */
042    public class IP implements KeywordBindRule {
043    
044        /*
045          Regular expression used to do a quick check on the characters in a
046          bind rule address. These are all of the valid characters that may
047          appear in an bind rule address part.
048        */
049        private  static final String ipRegEx =
050                "((?i)[\\.{1}[a-f]\\d:\\+{1}\\*/{1}\\t\\[{1}\\]{1}]+(?-i))";
051    
052        /*
053          List of the pattern classes, one for each address decoded from the
054          bind rule.
055        */
056        private List<PatternIP> patternIPList=null;
057    
058        /*
059          The type of the bind rule (!= or =).
060         */
061        private EnumBindRuleType type=null;
062    
063        /**
064         * Create a class representing the IP bind rule expressions for this ACI.
065         * @param patternIPList A list of PatternIP objects representing the IP
066         *                      bind rule expressions decoded from ACI.
067         * @param type An enumeration representing the expression type.
068         */
069        private IP(List<PatternIP> patternIPList, EnumBindRuleType type) {
070            this.patternIPList=patternIPList;
071            this.type=type;
072        }
073    
074        /**
075         * Decodes the provided IP bind rule expression string and returns an
076         * IP class the can be used to evaluate remote clients IP addresses.
077         *
078         * @param expr The expression string from the ACI IP bind rule.
079         * @param type An enmumeration representing the expression type.
080         * @return  A class that can be used to evaluate remote clients IP
081         *          addresses.
082         * @throws AciException  If there is a parsing error.
083         */
084        public static KeywordBindRule decode(String expr, EnumBindRuleType type)
085                throws AciException  {
086            //Split on the ','.
087            String[] ipStrs=expr.split("\\,", -1);
088            List<PatternIP> patternIPList= new LinkedList<PatternIP>();
089            for (String ipStr : ipStrs) {
090                if (!Pattern.matches(ipRegEx, ipStr)) {
091                    Message message =
092                        WARN_ACI_SYNTAX_INVALID_IP_EXPRESSION.get(expr);
093                    throw new AciException(message);
094                }
095                PatternIP ipPattern = PatternIP.decode(ipStr);
096                patternIPList.add(ipPattern);
097            }
098            return new IP(patternIPList, type);
099        }
100    
101        /**
102         * Perform an evaluation using the provided evaluation context's remote
103         * IP address information.
104         *
105         * @param evalCtx An evaluation context containing the remote clients
106         * IP address information.
107         *
108         * @return An enumeration representing if the address matched.
109         */
110        public EnumEvalResult evaluate(AciEvalContext evalCtx) {
111            InetAddress remoteAddr=evalCtx.getRemoteAddress();
112            return evaluate(remoteAddr);
113        }
114    
115        /**
116         * Perform an evaluation using the InetAddress.
117         *
118         * @param addr  The InetAddress to evaluate against PatternIP classes.
119         * @return  An enumeration representing if the address matched one
120         *          of the patterns.
121         */
122        EnumEvalResult evaluate(InetAddress addr) {
123            EnumEvalResult matched=EnumEvalResult.FALSE;
124            Iterator<PatternIP> it=patternIPList.iterator();
125            for(; it.hasNext() && matched != EnumEvalResult.TRUE &&
126                    matched != EnumEvalResult.ERR;) {
127                PatternIP patternIP=it.next();
128                matched=patternIP.evaluate(addr);
129            }
130            return matched.getRet(type, false);
131        }
132    }