Create IP range helper class
[java-idp.git] / src / main / java / edu / internet2 / middleware / shibboleth / idp / authn / provider / IPAddressLoginHandler.java
1 /*
2  * Copyright 2006 University Corporation for Advanced Internet Development, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package edu.internet2.middleware.shibboleth.idp.authn.provider;
18
19 import java.net.InetAddress;
20 import java.net.UnknownHostException;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26
27 import org.opensaml.xml.util.DatatypeHelper;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30 import org.slf4j.helpers.MessageFormatter;
31
32 import edu.internet2.middleware.shibboleth.idp.authn.AuthenticationEngine;
33 import edu.internet2.middleware.shibboleth.idp.authn.AuthenticationException;
34 import edu.internet2.middleware.shibboleth.idp.authn.LoginHandler;
35 import edu.internet2.middleware.shibboleth.idp.util.IPRange;
36
37 /**
38  * IP Address authentication handler.
39  * 
40  * This "authenticates" a user based on their IP address. It operates in either default deny or default allow mode, and
41  * evaluates a given request against a list of blocked or permitted IPs. It supports both IPv4 and IPv6.
42  */
43 public class IPAddressLoginHandler extends AbstractLoginHandler {
44
45     /** Class logger. */
46     private final Logger log = LoggerFactory.getLogger(IPAddressLoginHandler.class);
47
48     /** The username to use for IP-address "authenticated" users. */
49     private String authenticatedUser;
50
51     /** List of configured IP ranged. */
52     private List<IPRange> ipRanges;
53
54     /** Whether a user is "authenticated" if their IP address is within a configured IP range. */
55     private boolean ipInRangeIsAuthenticated;
56
57     public IPAddressLoginHandler(String user, List<IPRange> ranges, boolean ipInRangeIsAuthenticated) {
58         authenticatedUser = DatatypeHelper.safeTrimOrNullString(user);
59         if (authenticatedUser == null) {
60             throw new IllegalArgumentException("The authenticated user ID may not be null or empty");
61         }
62
63         if (ranges == null || ranges.isEmpty()) {
64             throw new IllegalArgumentException("The list of IP ranges may not be null or empty");
65         }
66         ipRanges = new ArrayList<IPRange>(ranges);
67
68         this.ipInRangeIsAuthenticated = ipInRangeIsAuthenticated;
69     }
70
71     /** {@inheritDoc} */
72     public boolean supportsPassive() {
73         return true;
74     }
75
76     /** {@inheritDoc} */
77     public boolean supportsForceAuthentication() {
78         return true;
79     }
80
81     /** {@inheritDoc} */
82     public void login(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
83         log.debug("Attempting to authenticated client '{}'", httpRequest.getRemoteAddr());
84         try {
85             InetAddress clientAddress = InetAddress.getByName(httpRequest.getRemoteAddr());
86             if (authenticate(clientAddress)) {
87                 log.debug("Authenticated user by IP address");
88                 httpRequest.setAttribute(LoginHandler.PRINCIPAL_NAME_KEY, authenticatedUser);
89             } else {
90                 log.debug("Client IP address {} failed authentication.", httpRequest.getRemoteAddr());
91                 httpRequest.setAttribute(LoginHandler.AUTHENTICATION_ERROR_KEY, new AuthenticationException(
92                         "Client failed IP address authentication"));
93             }
94         } catch (UnknownHostException e) {
95             String msg = MessageFormatter.format("Unable to resolve {} in to an IP address", httpRequest
96                     .getRemoteAddr());
97             log.warn(msg);
98             httpRequest.setAttribute(LoginHandler.AUTHENTICATION_ERROR_KEY, new AuthenticationException(msg));
99         }
100
101         AuthenticationEngine.returnToAuthenticationEngine(httpRequest, httpResponse);
102     }
103
104     /**
105      * Authenticates the client address.
106      * 
107      * @param clientAddress the client address
108      * 
109      * @return true if the client address is authenticated, false it not
110      */
111     protected boolean authenticate(InetAddress clientAddress) {
112         if (ipInRangeIsAuthenticated) {
113             for (IPRange range : ipRanges) {
114                 if (range.contains(clientAddress)) {
115                     return true;
116                 }
117             }
118         } else {
119             for (IPRange range : ipRanges) {
120                 if (!range.contains(clientAddress)) {
121                     return true;
122                 }
123             }
124         }
125
126         return false;
127     }
128 }