ip address handler
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / idp / authn / impl / IPAddressHandler.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
18 package edu.internet2.middleware.shibboleth.idp.authn.impl;
19
20 import java.net.InetAddress;
21 import java.net.UnknownHostException;
22 import java.util.List;
23
24 import javax.servlet.RequestDispatcher;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27 import javax.servlet.http.HttpSession;
28 import javax.servlet.ServletRequest;
29
30 import javolution.util.FastList;
31
32 import edu.internet2.middleware.shibboleth.idp.authn.AuthenticationHandler;
33 import edu.internet2.middleware.shibboleth.idp.authn.LoginContext;
34
35 import org.apache.log4j.Logger;
36
37 import org.joda.time.DateTime;
38
39
40 /**
41  * IP Address authentication handler.
42  *
43  * This "authenticates" a user based on their IP address.
44  * It operates in either default deny or default allow mode,
45  * and evaluates a given request against a list of blocked or permitted IPs.
46  * It supports both IPv4 and IPv6.
47  */
48 public class IPAddressHandler implements AuthenticationHandler {
49     
50     private static final Logger log =
51             Logger.getLogger(IPAddressHandler.class.getName());
52     
53     /** the URI of the AuthnContextDeclRef or the AuthnContextClass */
54     private String authnMethodURI;
55     
56     /** The return location */
57     private String returnLocation;
58     
59     /** Are the IPs in ipList a permitted list or a deny list */
60     private boolean defaultDeny;
61     
62     /** The list of denied or permitted IPs */
63     private List<InetAddress> ipList;
64     
65     
66     /** Creates a new instance of IPAddressHandler */
67     public IPAddressHandler() {
68     }
69     
70     
71     /**
72      * Set the permitted IP addresses.
73      *
74      * If <code>defaultDeny</code> is <code>true</code> then only the IP
75      * addresses in <code>ipList</code> will be "authenticated." If
76      * <code>defaultDeny</code> is <code>false</code>, then all IP addresses
77      * except those in <code>ipList</code> will be authenticated.
78      *
79      * @param ipList A list of {@link InetAddress}es.
80      * @param defaultDeny Does <code>ipList</code> contain a deny or permit list.
81      */
82     public void setIpList(final List<InetAddress> ipList, boolean defaultDeny) {
83         
84         this.ipList = new FastList(ipList);
85         this.defaultDeny = defaultDeny;
86     }
87     
88     
89     /** {@inheritDoc */
90     public void setReturnLocation(String location) {
91         this.returnLocation = location;
92     }
93     
94     
95     /** @{inheritDoc} */
96     public boolean supportsPassive() {
97         return (true);
98     }
99     
100     
101     /** {@inheritDoc} */
102     public boolean supportsForceAuthentication() {
103         return (true);
104     }
105     
106     
107     /** {@inheritDoc} */
108     public void logout(HttpServletRequest request,
109             HttpServletResponse response, String principal) {
110         
111         RequestDispatcher dispatcher =
112                 request.getRequestDispatcher(this.returnLocation);
113         dispatcher.forward(request, response);
114     }
115     
116     
117     /** {@inheritDoc} */
118     public void login(HttpServletRequest request,
119             HttpServletResponse response, boolean passive, boolean force) {
120         
121         HttpSession httpSession = request.getSession();
122         if (httpSession == null) {
123             log.error("Unable to retrieve HttpSession from request.");
124             return;
125         }
126         Object o = httpSession.getAttribute(LoginContext.LOGIN_CONTEXT_KEY);
127         if (! (o instanceof LoginContext)) {
128             log.error("Invalid login context object -- object is not an instance of LoginContext.");
129             return;
130         }
131         LoginContext loginContext = (LoginContext)o;
132         
133         loginContext.setAuthenticationAttempted();
134         loginContext.setAuthenticationInstant(new DateTime());
135         
136         if (this.defaultDeny) {
137             this.handleDefaultDeny(request, response, loginContext);
138         } else {
139             this.handleDefaultAllow(request, response, loginContext);
140         }
141         
142     }
143     
144     
145     private void handleDefaultDeny(HttpServletRequest request,
146             HttpServletResponse response, LoginContext loginCtx) {
147         
148         boolean ipAllowed = this.searchIpList(request);
149         
150         if (ipAllowed) {
151             loginCtx.setAuthenticationOK(true);
152         } else {
153             loginCtx.setAuthenticationOK(false);
154             loginCtx.setAuthenticationFailureMessage("User's IP is not in the permitted list.");
155         }
156     }
157     
158     
159     private void handleDefaultAllow(HttpServletRequest request,
160             HttpServletResponse response, LoginContext loginCtx) {
161         
162         boolean ipDenied = this.searchIpList(request);
163         
164         if (ipDenied) {
165             loginCtx.setAuthenticationOK(false);
166             loginCtx.setAuthenticationFailureMessage("Users's IP is in the deny list.");
167         } else {
168             loginCtx.setAuthenticationOK(true);
169         }
170     }
171     
172     
173     /**
174      * Search the list of InetAddresses for the client's address.
175      *
176      * @param request The ServletReqeust
177      *
178      * @return <code>true</code> if the client's address is in <code>this.ipList</code>
179      */
180     private boolean searchIpList(final ServletRequest request) {
181         
182         boolean found = false;
183         
184         try {
185             InetAddress[] addrs = InetAddress.getAllByName(request.getRemoteAddr());
186             for (InetAddress a : addrs) {
187                 if (this.ipList.contains(a)) {
188                     found = true;
189                     break;
190                 }
191             }
192         } catch (UnknownHostException ex) {
193             log.error("Error resolving hostname: ", ex);
194         }
195         
196         return (found);
197     }
198     
199 }