2 * Copyright 2006 University Corporation for Advanced Internet Development, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package edu.internet2.middleware.shibboleth.idp.authn.provider;
19 import java.net.InetAddress;
20 import java.net.UnknownHostException;
21 import java.util.ArrayList;
22 import java.util.List;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
27 import org.opensaml.xml.util.DatatypeHelper;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30 import org.slf4j.helpers.MessageFormatter;
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;
38 * IP Address authentication handler.
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.
43 public class IPAddressLoginHandler extends AbstractLoginHandler {
46 private final Logger log = LoggerFactory.getLogger(IPAddressLoginHandler.class);
48 /** The username to use for IP-address "authenticated" users. */
49 private String authenticatedUser;
51 /** List of configured IP ranged. */
52 private List<IPRange> ipRanges;
54 /** Whether a user is "authenticated" if their IP address is within a configured IP range. */
55 private boolean ipInRangeIsAuthenticated;
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");
63 if (ranges == null || ranges.isEmpty()) {
64 throw new IllegalArgumentException("The list of IP ranges may not be null or empty");
66 ipRanges = new ArrayList<IPRange>(ranges);
68 this.ipInRangeIsAuthenticated = ipInRangeIsAuthenticated;
72 public boolean supportsPassive() {
77 public boolean supportsForceAuthentication() {
82 public void login(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
83 log.debug("Attempting to authenticated client '{}'", httpRequest.getRemoteAddr());
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);
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"));
94 } catch (UnknownHostException e) {
95 String msg = MessageFormatter.format("Unable to resolve {} in to an IP address", httpRequest
98 httpRequest.setAttribute(LoginHandler.AUTHENTICATION_ERROR_KEY, new AuthenticationException(msg));
101 AuthenticationEngine.returnToAuthenticationEngine(httpRequest, httpResponse);
105 * Authenticates the client address.
107 * @param clientAddress the client address
109 * @return true if the client address is authenticated, false it not
111 protected boolean authenticate(InetAddress clientAddress) {
112 if (ipInRangeIsAuthenticated) {
113 for (IPRange range : ipRanges) {
114 if (range.contains(clientAddress)) {
119 for (IPRange range : ipRanges) {
120 if (!range.contains(clientAddress)) {