Merge "Store CRCs as Integer rather than as hex strings."
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.net.watchlist;
|
||||
|
||||
import com.android.internal.util.HexDump;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Helper class to store a set of harmful CRC32s in memory.
|
||||
* TODO: Optimize memory usage using int array with binary search.
|
||||
*/
|
||||
class HarmfulCrcs {
|
||||
|
||||
private final Set<Integer> mCrcSet;
|
||||
|
||||
HarmfulCrcs(List<byte[]> digests) {
|
||||
final HashSet<Integer> crcSet = new HashSet<>();
|
||||
final int size = digests.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
byte[] bytes = digests.get(i);
|
||||
if (bytes.length <= 4) {
|
||||
int crc = 0;
|
||||
for (byte b : bytes) {
|
||||
// Remember byte is signed
|
||||
crc = (crc << 8) | (b & 0xff);
|
||||
}
|
||||
crcSet.add(crc);
|
||||
}
|
||||
}
|
||||
mCrcSet = Collections.unmodifiableSet(crcSet);
|
||||
}
|
||||
|
||||
public boolean contains(int crc) {
|
||||
return mCrcSet.contains(crc);
|
||||
}
|
||||
|
||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
for (int crc : mCrcSet) {
|
||||
pw.println(HexDump.toHexString(crc));
|
||||
}
|
||||
pw.println("");
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ package com.android.server.net.watchlist;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.os.FileUtils;
|
||||
import android.util.AtomicFile;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
import android.util.Xml;
|
||||
@@ -66,11 +65,11 @@ class WatchlistConfig {
|
||||
}
|
||||
|
||||
private static class CrcShaDigests {
|
||||
final HarmfulDigests crc32Digests;
|
||||
final HarmfulDigests sha256Digests;
|
||||
public final HarmfulCrcs crc32s;
|
||||
public final HarmfulDigests sha256Digests;
|
||||
|
||||
public CrcShaDigests(HarmfulDigests crc32Digests, HarmfulDigests sha256Digests) {
|
||||
this.crc32Digests = crc32Digests;
|
||||
CrcShaDigests(HarmfulCrcs crc32s, HarmfulDigests sha256Digests) {
|
||||
this.crc32s = crc32s;
|
||||
this.sha256Digests = sha256Digests;
|
||||
}
|
||||
}
|
||||
@@ -140,9 +139,9 @@ class WatchlistConfig {
|
||||
}
|
||||
}
|
||||
parser.require(XmlPullParser.END_TAG, null, XmlTags.WATCHLIST_CONFIG);
|
||||
mDomainDigests = new CrcShaDigests(new HarmfulDigests(crc32DomainList),
|
||||
mDomainDigests = new CrcShaDigests(new HarmfulCrcs(crc32DomainList),
|
||||
new HarmfulDigests(sha256DomainList));
|
||||
mIpDigests = new CrcShaDigests(new HarmfulDigests(crc32IpList),
|
||||
mIpDigests = new CrcShaDigests(new HarmfulCrcs(crc32IpList),
|
||||
new HarmfulDigests(sha256IpList));
|
||||
Log.i(TAG, "Reload watchlist done");
|
||||
} catch (IllegalStateException | NullPointerException | NumberFormatException |
|
||||
@@ -171,8 +170,8 @@ class WatchlistConfig {
|
||||
return false;
|
||||
}
|
||||
// First it does a quick CRC32 check.
|
||||
final byte[] crc32 = getCrc32(domain);
|
||||
if (!domainDigests.crc32Digests.contains(crc32)) {
|
||||
final int crc32 = getCrc32(domain);
|
||||
if (!domainDigests.crc32s.contains(crc32)) {
|
||||
return false;
|
||||
}
|
||||
// Now we do a slow SHA256 check.
|
||||
@@ -187,8 +186,8 @@ class WatchlistConfig {
|
||||
return false;
|
||||
}
|
||||
// First it does a quick CRC32 check.
|
||||
final byte[] crc32 = getCrc32(ip);
|
||||
if (!ipDigests.crc32Digests.contains(crc32)) {
|
||||
final int crc32 = getCrc32(ip);
|
||||
if (!ipDigests.crc32s.contains(crc32)) {
|
||||
return false;
|
||||
}
|
||||
// Now we do a slow SHA256 check.
|
||||
@@ -198,15 +197,11 @@ class WatchlistConfig {
|
||||
|
||||
|
||||
/** Get CRC32 of a string
|
||||
*
|
||||
* TODO: Review if we should use CRC32 or other algorithms
|
||||
*/
|
||||
private byte[] getCrc32(String str) {
|
||||
private int getCrc32(String str) {
|
||||
final CRC32 crc = new CRC32();
|
||||
crc.update(str.getBytes());
|
||||
final long tmp = crc.getValue();
|
||||
return new byte[]{(byte) (tmp >> 24 & 255), (byte) (tmp >> 16 & 255),
|
||||
(byte) (tmp >> 8 & 255), (byte) (tmp & 255)};
|
||||
return (int) crc.getValue();
|
||||
}
|
||||
|
||||
/** Get SHA256 of a string */
|
||||
@@ -279,7 +274,7 @@ class WatchlistConfig {
|
||||
pw.println("Domain CRC32 digest list:");
|
||||
// mDomainDigests won't go from non-null to null so it's safe
|
||||
if (mDomainDigests != null) {
|
||||
mDomainDigests.crc32Digests.dump(fd, pw, args);
|
||||
mDomainDigests.crc32s.dump(fd, pw, args);
|
||||
}
|
||||
pw.println("Domain SHA256 digest list:");
|
||||
if (mDomainDigests != null) {
|
||||
@@ -288,7 +283,7 @@ class WatchlistConfig {
|
||||
pw.println("Ip CRC32 digest list:");
|
||||
// mIpDigests won't go from non-null to null so it's safe
|
||||
if (mIpDigests != null) {
|
||||
mIpDigests.crc32Digests.dump(fd, pw, args);
|
||||
mIpDigests.crc32s.dump(fd, pw, args);
|
||||
}
|
||||
pw.println("Ip SHA256 digest list:");
|
||||
if (mIpDigests != null) {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.net.watchlist;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.util.HexDump;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* runtest frameworks-services -c com.android.server.net.watchlist.HarmfulCrcTests
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public class HarmfulCrcsTests {
|
||||
|
||||
private static final byte[] TEST_DIGEST = HexDump.hexStringToByteArray("AABBCCDD");
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHarmfulCrcs_setAndContains() throws Exception {
|
||||
HarmfulCrcs harmfulCrcs = new HarmfulCrcs(
|
||||
Arrays.asList(new byte[][] {TEST_DIGEST}));
|
||||
assertTrue(harmfulCrcs.contains(0xaabbccdd));
|
||||
assertFalse(harmfulCrcs.contains(0xbbbbbbbb));
|
||||
assertFalse(harmfulCrcs.contains(0x01020304));
|
||||
assertFalse(harmfulCrcs.contains(0xddccbbaa));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user