990828ffdbf5c0899d787f864f574b032257a59d
[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.getName());
48
49         /** the URI of the AuthnContextDeclRef or the AuthnContextClass */
50         private String authnMethodURI;
51
52         /** The return location */
53         private String returnLocation;
54
55         /** Are the IPs in ipList a permitted list or a deny list */
56         private boolean defaultDeny;
57
58         /** The list of denied or permitted IPs */
59         private List<InetAddress> ipList;
60
61         /** Creates a new instance of IPAddressHandler */
62         public IPAddressHandler() {
63         }
64
65         /**
66          * Set the permitted IP addresses.
67          * 
68          * If <code>defaultDeny</code> is <code>true</code> then only the IP
69          * addresses in <code>ipList</code> will be "authenticated." If
70          * <code>defaultDeny</code> is <code>false</code>, then all IP
71          * addresses except those in <code>ipList</code> will be authenticated.
72          * 
73          * @param ipList
74          *            A list of {@link InetAddress}es.
75          * @param defaultDeny
76          *            Does <code>ipList</code> contain a deny or permit list.
77          */
78         public void setIpList(final List<InetAddress> ipList, boolean defaultDeny) {
79
80                 this.ipList = new CopyOnWriteArrayList(ipList);
81                 this.defaultDeny = defaultDeny;
82         }
83
84         /** {@inheritDoc   */
85         public void setReturnLocation(String location) {
86                 this.returnLocation = location;
87         }
88
89         /** @{inheritDoc} */
90         public boolean supportsPassive() {
91                 return (true);
92         }
93
94         /** {@inheritDoc} */
95         public boolean supportsForceAuthentication() {
96                 return (true);
97         }
98
99         /** {@inheritDoc} */
100         public void logout(HttpServletRequest request,
101                         HttpServletResponse response, String principal) {
102
103                 RequestDispatcher dispatcher = request
104                                 .getRequestDispatcher(returnLocation);
105                 // dispatcher.forward(request, response);
106         }
107
108         /** {@inheritDoc} */
109         public void login(HttpServletRequest request, HttpServletResponse response,
110                         LoginContext loginCtx) {
111
112                 loginCtx.setAuthenticationAttempted();
113                 loginCtx.setAuthenticationInstant(new DateTime());
114
115                 if (defaultDeny) {
116                         handleDefaultDeny(request, response, loginCtx);
117                 } else {
118                         handleDefaultAllow(request, response, loginCtx);
119                 }
120         }
121
122         protected void handleDefaultDeny(HttpServletRequest request,
123                         HttpServletResponse response, LoginContext loginCtx) {
124
125                 boolean ipAllowed = searchIpList(request);
126
127                 if (ipAllowed) {
128                         loginCtx.setAuthenticationOK(true);
129                 } else {
130                         loginCtx.setAuthenticationOK(false);
131                         loginCtx.setAuthenticationFailureMessage("User's IP is not in the permitted list.");
132                 }
133         }
134
135         protected void handleDefaultAllow(HttpServletRequest request,
136                         HttpServletResponse response, LoginContext loginCtx) {
137
138                 boolean ipDenied = searchIpList(request);
139
140                 if (ipDenied) {
141                         loginCtx.setAuthenticationOK(false);
142                         loginCtx
143                                         .setAuthenticationFailureMessage("Users's IP is in the deny list.");
144                 } else {
145                         loginCtx.setAuthenticationOK(true);
146                 }
147         }
148
149         /**
150          * Search the list of InetAddresses for the client's address.
151          * 
152          * @param request
153          *            The ServletReqeust
154          * 
155          * @return <code>true</code> if the client's address is in
156          *         <code>this.ipList</code>
157          */
158         private boolean searchIpList(final ServletRequest request) {
159
160                 boolean found = false;
161
162                 try {
163                         InetAddress[] addrs = InetAddress.getAllByName(request
164                                         .getRemoteAddr());
165                         for (InetAddress a : addrs) {
166                                 if (ipList.contains(a)) {
167                                         found = true;
168                                         break;
169                                 }
170                         }
171                 } catch (UnknownHostException ex) {
172                         log.error("Error resolving hostname: ", ex);
173                 }
174
175                 return (found);
176         }
177
178 }