View Javadoc

1   /*
2    * SymmetricDS is an open source database synchronization solution.
3    *   
4    * Copyright (C) Dave Michels <dmichels2@users.sourceforge.net>,
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 3 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, see
18   * <http://www.gnu.org/licenses/>.
19   */
20  
21  package org.jumpmind.symmetric.transport;
22  
23  import java.net.Inet4Address;
24  import java.net.Inet6Address;
25  import java.net.InetAddress;
26  import java.net.UnknownHostException;
27  import java.util.Collections;
28  import java.util.List;
29  
30  import org.apache.commons.lang.StringUtils;
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.jumpmind.symmetric.common.ParameterConstants;
34  import org.jumpmind.symmetric.security.inet.IInetAddressAuthorizer;
35  import org.jumpmind.symmetric.security.inet.IInetAddressAuthorizerCompiler;
36  import org.jumpmind.symmetric.security.inet.IRawInetAddressAuthorizer;
37  import org.jumpmind.symmetric.service.IParameterService;
38  import org.jumpmind.symmetric.transport.handler.AbstractTransportResourceHandler;
39  
40  /***
41   * @author dmichels2
42   */
43  public class InetAddressResourceHandler extends AbstractTransportResourceHandler implements IInetAddressAuthorizer {
44      private static final Log logger = LogFactory.getLog(InetAddressResourceHandler.class);
45  
46      public static final String FILTER_DELIMITER = ",";
47  
48      private List<IRawInetAddressAuthorizer> filters;
49  
50      private IInetAddressAuthorizerCompiler addressCompiler;
51  
52      private IParameterService parameterService;
53  
54      private boolean isMulicastAllowed;
55  
56      /***
57       * 
58       */
59      public void clearFilters() {
60          filters = null;
61      }
62  
63      /***
64       * @param filterString
65       * @throws UnknownHostException
66       */
67      public synchronized void setAddressFilters(final String filterString) throws UnknownHostException {
68          String[] filtersTokens = null;
69          if (StringUtils.isBlank(filterString)) {
70              filters = Collections.emptyList();
71              logger.warn("No address filters were provided to be compiled");
72          } else {
73              filtersTokens = filterString.split(FILTER_DELIMITER);
74              filters = addressCompiler.compile(filtersTokens);
75          }
76      }
77  
78      /***
79       * @param sourceAddress
80       * @return
81       * @throws UnknownHostException
82       */
83      public boolean isAuthorized(final String sourceAddress) {
84          try {
85              final InetAddress inetAddress = InetAddress.getByName(sourceAddress);
86              return isAuthorized(inetAddress);
87          } catch (final UnknownHostException uhe) {
88              // TODO if we don't have a valid host/ip, should we just return
89              // 'false'?
90              throw new IllegalArgumentException(uhe.getMessage(), uhe);
91          }
92  
93      }
94  
95      /***
96       * @param checkAddress
97       * @return
98       */
99      public boolean isAuthorized(final InetAddress checkAddress) {
100         if (filters == null) {
101             final String filterString = parameterService.getString(ParameterConstants.IP_FILTERS);
102             if (logger.isDebugEnabled()) {
103                 logger.debug("Extracted IP filter string from ParameterService as: " + filterString);
104             }
105             try {
106                 setAddressFilters(filterString);
107             } catch (final UnknownHostException e) {
108                 throw new IllegalStateException("Could not initialize address filter string");
109             }
110         }
111         final boolean isMulticast = isMulticastAddress(checkAddress);
112 
113         if (isMulticast && !isMulicastAllowed) {
114             logger.info("Allow multicast is 'false'. Denying multicast address: " + checkAddress.toString());
115 
116             return false;
117         }
118 
119         final byte[] addressBytes = checkAddress.getAddress();
120         for (final IRawInetAddressAuthorizer filter : filters) {
121             if (filter.isAuthorized(addressBytes)) {
122                 return true;
123             }
124         }
125         if (logger.isInfoEnabled()) {
126             logger.info("Denying Address: " + checkAddress.toString());
127         }
128         return false;
129     }
130 
131     /***
132      * @return the isMulicastAllowed.
133      */
134     public boolean isMulicastAllowed() {
135         return isMulicastAllowed;
136     }
137 
138     /***
139      * @param isMulicastAllowed
140      *                the isMulicastAllowed to set
141      */
142     public void setMulicastAllowed(final boolean isMulicastAllowed) {
143         this.isMulicastAllowed = isMulicastAllowed;
144     }
145 
146     /***
147      * @param addressCompiler
148      *                the addressCompiler to set
149      */
150     public void setAddressCompiler(final IInetAddressAuthorizerCompiler addressCompiler) {
151         this.addressCompiler = addressCompiler;
152     }
153 
154     /***
155      * @param parameterService
156      *                the parameterService to set
157      */
158     public void setParameterService(final IParameterService parameterService) {
159         this.parameterService = parameterService;
160     }
161 
162     /***
163      * @param checkAddress
164      * @return
165      */
166     private boolean isMulticastAddress(final InetAddress checkAddress) {
167         // Have to cast as the address type as the default
168         // InetAddress.isMulticastAddress() always returns 'false'
169         if (checkAddress instanceof Inet4Address) {
170             final Inet4Address ip4Addr = (Inet4Address) checkAddress;
171             return ip4Addr.isMulticastAddress();
172         } else if (checkAddress instanceof Inet6Address) {
173             final Inet6Address ip6Addr = (Inet6Address) checkAddress;
174             return ip6Addr.isMulticastAddress();
175         }
176         return checkAddress.isMulticastAddress();
177     }
178 
179 }