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