| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.catalina.util; |
| |
| import java.net.InetAddress; |
| import java.net.UnknownHostException; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.apache.tomcat.util.buf.StringUtils; |
| import org.apache.tomcat.util.res.StringManager; |
| |
| |
| /** |
| * This class maintains a Set of NetMask objects and allows to check if a given IP address is matched by any of the |
| * NetMasks, making it easy to create Allow and Deny lists of CIDR networks and hosts. |
| */ |
| public class NetMaskSet { |
| |
| private static final StringManager sm = StringManager.getManager(NetMaskSet.class); |
| |
| private final Set<NetMask> netmasks = new HashSet<>(); |
| |
| /** |
| * Tests if the provided InetAddress matches any of the {@link NetMask}s in the set. |
| * |
| * @param inetAddress An InetAddress to check |
| * |
| * @return {@code true} if the passed inetAddress is matched by any of the {@link NetMask}s in the set |
| */ |
| public boolean contains(InetAddress inetAddress) { |
| |
| for (NetMask nm : netmasks) { |
| if (nm.matches(inetAddress)) { |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * Tests if the provided IP address matches any of the {@link NetMask}s in the set. |
| * |
| * @param ipAddress an IP address to check |
| * |
| * @return {@code true} if the passed IP address is matched by any of the {@link NetMask}s in the set |
| * |
| * @throws UnknownHostException if the passed input is not a valid IP address |
| */ |
| public boolean contains(String ipAddress) throws UnknownHostException { |
| |
| InetAddress inetAddress = InetAddress.getByName(ipAddress); |
| return this.contains(inetAddress); |
| } |
| |
| /** |
| * Adds a NetMask object to the set if the set does not contain it |
| * |
| * @param netmask The NetMask to add |
| * |
| * @return true if the object was added |
| */ |
| public boolean add(NetMask netmask) { |
| return netmasks.add(netmask); |
| } |
| |
| /** |
| * Creates a NetMask object from the input string and adds it to the set. |
| * |
| * @param input The string from which to construct the NetMask |
| * |
| * @return true if the object was added |
| * |
| * @throws IllegalArgumentException if the input is not a valid CIDR format. |
| */ |
| public boolean add(String input) { |
| NetMask netmask = new NetMask(input); |
| return netmasks.add(netmask); |
| } |
| |
| /** |
| * removes all entries from the set |
| */ |
| public void clear() { |
| netmasks.clear(); |
| } |
| |
| /** |
| * Tests if the set is empty. |
| * |
| * @return {@code true} if the set is empty, otherwise {@code false} |
| */ |
| public boolean isEmpty() { |
| return netmasks.isEmpty(); |
| } |
| |
| /** |
| * Adds a {@link NetMask} list from a string input containing a comma-separated list of (hopefully valid) |
| * {@link NetMask}s. |
| * |
| * @param input The input string |
| * |
| * @return a list of processing error messages (empty when no errors) |
| */ |
| public List<String> addAll(String input) { |
| |
| if (input == null || input.isEmpty()) { |
| return Collections.emptyList(); |
| } |
| |
| List<String> errMessages = new ArrayList<>(); |
| |
| for (String s : StringUtils.splitCommaSeparated(input)) { |
| try { |
| this.add(s); |
| } catch (IllegalArgumentException e) { |
| errMessages.add(s + ": " + e.getMessage()); |
| } |
| } |
| |
| return Collections.unmodifiableList(errMessages); |
| } |
| |
| /** |
| * Provides a string representation of this NetMaskSet. The format of the String is not guaranteed to remain fixed. |
| * |
| * @return a comma separated list of the <code>NetMask</code>s in this set |
| */ |
| @Override |
| public String toString() { |
| |
| String result = netmasks.toString(); |
| |
| // remove open and close brackets if exist |
| if (result.startsWith("[")) { |
| result = result.substring(1); |
| } |
| |
| if (result.endsWith("]")) { |
| result = result.substring(0, result.length() - 1); |
| } |
| |
| return result; |
| } |
| |
| |
| public static NetMaskSet parse(String input) { |
| NetMaskSet result = new NetMaskSet(); |
| |
| List<String> errors = result.addAll(input); |
| if (!errors.isEmpty()) { |
| StringBuilder sb = new StringBuilder(); |
| for (String error : errors) { |
| sb.append(error).append("; "); |
| } |
| throw new IllegalArgumentException(sm.getString("netmaskSet.invalidNetMask", sb.toString())); |
| } |
| |
| return result; |
| } |
| } |