001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    package org.apache.shiro.web.filter.authz;
020    
021    import org.apache.shiro.util.StringUtils;
022    
023    import javax.servlet.ServletRequest;
024    import javax.servlet.ServletResponse;
025    import java.util.regex.Pattern;
026    import java.util.Map;
027    
028    /**
029     * A Filter that can allow or deny access based on the host that sent the request.
030     *
031     * <b>WARNING:</b> NOT YET FULLY IMPLEMENTED!!!  Work in progress.
032     *
033     * @since 1.0
034     */
035    public class HostFilter extends AuthorizationFilter {
036    
037        public static final String IPV4_QUAD_REGEX = "(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2(?:[0-4][0-9]|5[0-5]))";
038    
039        public static final String IPV4_REGEX = "(?:" + IPV4_QUAD_REGEX + "\\.){3}" + IPV4_QUAD_REGEX + "$";
040        public static final Pattern IPV4_PATTERN = Pattern.compile(IPV4_REGEX);
041    
042        public static final String PRIVATE_CLASS_B_SUBSET = "(?:1[6-9]|2[0-9]|3[0-1])";
043    
044        public static final String PRIVATE_CLASS_A_REGEX = "10\\.(?:" + IPV4_QUAD_REGEX + "\\.){2}" + IPV4_QUAD_REGEX + "$";
045    
046        public static final String PRIVATE_CLASS_B_REGEX =
047                "172\\." + PRIVATE_CLASS_B_SUBSET + "\\." + IPV4_QUAD_REGEX + "\\." + IPV4_QUAD_REGEX + "$";
048    
049        public static final String PRIVATE_CLASS_C_REGEX = "192\\.168\\." + IPV4_QUAD_REGEX + "\\." + IPV4_QUAD_REGEX + "$";
050    
051        Map<String, String> authorizedIps; //user-configured IP (which can be wildcarded) to constructed regex mapping
052        Map<String, String> deniedIps;
053        Map<String, String> authorizedHostnames;
054        Map<String, String> deniedHostnames;
055    
056    
057        public void setAuthorizedHosts(String authorizedHosts) {
058            if (!StringUtils.hasText(authorizedHosts)) {
059                throw new IllegalArgumentException("authorizedHosts argument cannot be null or empty.");
060            }
061            String[] hosts = StringUtils.tokenizeToStringArray(authorizedHosts, ", \t");
062    
063            for (String host : hosts) {
064                //replace any periods with \\. to ensure the regex works:
065                String periodsReplaced = host.replace(".", "\\.");
066                //check for IPv4:
067                String wildcardsReplaced = periodsReplaced.replace("*", IPV4_QUAD_REGEX);
068    
069                if (IPV4_PATTERN.matcher(wildcardsReplaced).matches()) {
070                    authorizedIps.put(host, wildcardsReplaced);
071                } else {
072    
073                }
074    
075    
076            }
077    
078        }
079    
080        public void setDeniedHosts(String deniedHosts) {
081            if (!StringUtils.hasText(deniedHosts)) {
082                throw new IllegalArgumentException("deniedHosts argument cannot be null or empty.");
083            }
084        }
085    
086        protected boolean isIpv4Candidate(String host) {
087            String[] quads = StringUtils.tokenizeToStringArray(host, ".");
088            if (quads == null || quads.length != 4) {
089                return false;
090            }
091            for (String quad : quads) {
092                if (!quad.equals("*")) {
093                    try {
094                        Integer.parseInt(quad);
095                    } catch (NumberFormatException nfe) {
096                        return false;
097                    }
098                }
099            }
100            return true;
101        }
102    
103        protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
104            throw new UnsupportedOperationException("Not yet fully implemented!!!" );
105        }
106    }