Skip to content

Commit 37e5d58

Browse files
authored
ZCS-8286 Add whitelist (blacklist exceptions) for FeedManager. (#993)
* Improvements on FeedManager blacklist logging.
1 parent 19b2681 commit 37e5d58

File tree

3 files changed

+122
-14
lines changed

3 files changed

+122
-14
lines changed

common/src/java/com/zimbra/common/localconfig/LC.java

+3
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,9 @@ public enum PUBLIC_SHARE_VISIBILITY { samePrimaryDomain, all, none };
13071307
// Feed Manager comma-separated blacklist. addresses can be CIDR notation, or single ip. no wild-cards (default blacklist private networks)
13081308
public static final KnownKey zimbra_feed_manager_blacklist = KnownKey.newKey("10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fd00::/8");
13091309

1310+
// Feed Manager comma-separated whitelist (exceptions to the blacklist). addresses can be CIDR notation, or single ip. no wild-cards
1311+
public static final KnownKey zimbra_feed_manager_whitelist = KnownKey.newKey("");
1312+
13101313
// Zimbra valid class list to de-serialize
13111314
public static final KnownKey zimbra_deserialize_classes = KnownKey.newKey("");
13121315

store/src/java-test/com/zimbra/cs/service/FeedManagerTest.java

+88
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.apache.http.client.utils.URIBuilder;
3030
import org.eclipse.jetty.http.HttpStatus;
3131
import org.junit.Assert;
32+
import org.junit.Before;
3233
import org.junit.BeforeClass;
3334
import org.junit.Test;
3435

@@ -43,6 +44,12 @@
4344

4445
public class FeedManagerTest {
4546

47+
@Before
48+
public void setUp() {
49+
LC.zimbra_feed_manager_blacklist.setDefault("10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fd00::/8");
50+
LC.zimbra_feed_manager_whitelist.setDefault("");
51+
}
52+
4653
@BeforeClass
4754
public static void init() throws Exception {
4855
MailboxTestUtil.initServer();
@@ -248,6 +255,87 @@ public void testIsBlockedFeedAddressDefaultBlacklist() throws Exception {
248255
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://10.15.150.140/feed")));
249256
}
250257

258+
@Test
259+
public void testIsBlockedFeedAddressDefaultBlacklistWithWhitelistedIp() throws Exception {
260+
LC.zimbra_feed_manager_whitelist.setDefault("192.168.1.106");
261+
262+
Assert.assertFalse(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.1.106/feed")));
263+
Assert.assertFalse(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.1.106:8080/feed")));
264+
Assert.assertFalse(FeedManager.isBlockedFeedAddress(new URIBuilder("http://user:[email protected]/feed")));
265+
266+
// loopback
267+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://localhost/feed")));
268+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://localhost:8085/feed")));
269+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://127.0.0.1/feed")));
270+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://127.0.0.1:8085/feed")));
271+
272+
// private
273+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://172.16.150.140/feed")));
274+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://172.25.150.140/feed")));
275+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://user:[email protected]/feed")));
276+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.5.1:8080/feed")));
277+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.166.150/feed")));
278+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.166.150:8081/feed")));
279+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://10.0.0.1/feed")));
280+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://10.15.150.140/feed")));
281+
}
282+
283+
@Test
284+
public void testIsBlockedFeedAddressDefaultBlacklistWithWhitelistedRange() throws Exception {
285+
LC.zimbra_feed_manager_whitelist.setDefault("192.168.100.0/25");
286+
287+
Assert.assertFalse(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.100.0/feed")));
288+
for (int i = 1; i < 128; i++) {
289+
Assert.assertFalse(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.100." + i + "/feed")));
290+
}
291+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.100.128/feed")));
292+
293+
// loopback
294+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://localhost/feed")));
295+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://localhost:8085/feed")));
296+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://127.0.0.1/feed")));
297+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://127.0.0.1:8085/feed")));
298+
299+
// private
300+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://172.16.150.140/feed")));
301+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://172.25.150.140/feed")));
302+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://user:[email protected]/feed")));
303+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.5.1:8080/feed")));
304+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.166.150/feed")));
305+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.166.150:8081/feed")));
306+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://10.0.0.1/feed")));
307+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://10.15.150.140/feed")));
308+
}
309+
310+
@Test
311+
public void testIsBlockedFeedAddressDefaultBlacklistWithWhitelistedMultiple() throws Exception {
312+
LC.zimbra_feed_manager_whitelist.setDefault("192.168.100.0/25,192.168.105.122,10.12.150.101");
313+
314+
Assert.assertFalse(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.105.122/feed")));
315+
Assert.assertFalse(FeedManager.isBlockedFeedAddress(new URIBuilder("http://10.12.150.101/feed")));
316+
Assert.assertFalse(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.100.0/feed")));
317+
for (int i = 1; i < 128; i++) {
318+
Assert.assertFalse(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.100." + i + "/feed")));
319+
}
320+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.100.128/feed")));
321+
322+
// loopback
323+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://localhost/feed")));
324+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://localhost:8085/feed")));
325+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://127.0.0.1/feed")));
326+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://127.0.0.1:8085/feed")));
327+
328+
// private
329+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://172.16.150.140/feed")));
330+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://172.25.150.140/feed")));
331+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://user:[email protected]/feed")));
332+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.5.1:8080/feed")));
333+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.166.150/feed")));
334+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://192.168.166.150:8081/feed")));
335+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://10.0.0.1/feed")));
336+
Assert.assertTrue(FeedManager.isBlockedFeedAddress(new URIBuilder("http://10.15.150.140/feed")));
337+
}
338+
251339
@Test
252340
public void testIsBlockedFeedAddressPublicBlacklisted() throws Exception {
253341
Assert.assertFalse(FeedManager.isBlockedFeedAddress(new URIBuilder("http://198.51.100.230:8081/feed")));

store/src/java/com/zimbra/cs/service/FeedManager.java

+31-14
Original file line numberDiff line numberDiff line change
@@ -274,27 +274,39 @@ protected static boolean isAddressInRange(InetAddress targetAddress, String pref
274274
}
275275

276276
/**
277-
* Returns true if target address is link-local, loopback, or blacklisted.
277+
* Returns true if target address is not whitelisted,
278+
* and is link-local, loopback, or blacklisted.
278279
* @param url The target
279280
* @return True if address is blocked for feed manager
280281
*/
281282
protected static boolean isBlockedFeedAddress(URIBuilder url) {
282-
String blacklistString = LC.zimbra_feed_manager_blacklist.value();
283-
List<String> blacklist = new ArrayList<String>();
284-
if (!StringUtil.isNullOrEmpty(blacklistString)) {
285-
blacklist.addAll(Arrays.asList(blacklistString.split(",")));
286-
}
283+
InetAddress targetAddress;
287284
try {
288-
InetAddress targetAddress = InetAddress.getByName(url.getHost());
289-
return targetAddress.isAnyLocalAddress()
290-
|| targetAddress.isLinkLocalAddress()
291-
|| targetAddress.isLoopbackAddress()
292-
|| blacklist.stream()
293-
.anyMatch(ip -> isAddressInRange(targetAddress, ip));
285+
targetAddress = InetAddress.getByName(url.getHost());
294286
} catch (UnknownHostException e) {
295287
ZimbraLog.misc.warn("unable to identify feed manager target url host: %s", url);
288+
return false;
289+
}
290+
291+
String whitelistString = LC.zimbra_feed_manager_whitelist.value();
292+
List<String> whitelist = new ArrayList<String>();
293+
if (!StringUtil.isNullOrEmpty(whitelistString)) {
294+
whitelist.addAll(Arrays.asList(whitelistString.trim().split(",")));
295+
}
296+
if (whitelist.stream().anyMatch(ip -> isAddressInRange(targetAddress, ip))) {
297+
return false;
298+
}
299+
300+
String blacklistString = LC.zimbra_feed_manager_blacklist.value();
301+
List<String> blacklist = new ArrayList<String>();
302+
if (!StringUtil.isNullOrEmpty(blacklistString)) {
303+
blacklist.addAll(Arrays.asList(blacklistString.trim().split(",")));
296304
}
297-
return false;
305+
return targetAddress.isAnyLocalAddress()
306+
|| targetAddress.isLinkLocalAddress()
307+
|| targetAddress.isLoopbackAddress()
308+
|| blacklist.stream()
309+
.anyMatch(ip -> isAddressInRange(targetAddress, ip));
298310
}
299311

300312
private static RemoteDataInfo retrieveRemoteData(String url, Folder.SyncData fsd)
@@ -342,7 +354,12 @@ private static RemoteDataInfo retrieveRemoteData(String url, Folder.SyncData fsd
342354

343355
// validate target address (also handles followed `location` header addresses)
344356
if (isBlockedFeedAddress(httpurl)) {
345-
throw ServiceException.INVALID_REQUEST(String.format("invalid url for feed: %s", url), null);
357+
ZimbraLog.misc.info(
358+
"Feed ip address blocked: %s. See localconfig for comma-separated ip list configuration: "
359+
+ "zimbra_feed_manager_blacklist, zimbra_feed_manager_whitelist",
360+
url);
361+
throw ServiceException.INVALID_REQUEST(
362+
String.format("Address for feed is blocked: %s. See mailbox logs for details.", url), null);
346363
}
347364
// username and password are encoded in the URL as http://user:pass@host/...
348365
if (url.indexOf('@') != -1) {

0 commit comments

Comments
 (0)