Autopsy  4.19.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
CorrelationAttributeNormalizer.java
Go to the documentation of this file.
1 /*
2  *
3  * Autopsy Forensic Browser
4  *
5  * Copyright 2019 Basis Technology Corp.
6  * Contact: carrier <at> sleuthkit <dot> org
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 package org.sleuthkit.autopsy.centralrepository.datamodel;
21 
22 import java.util.Arrays;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Optional;
26 import java.util.Set;
27 import org.apache.commons.lang.StringUtils;
28 import org.apache.commons.validator.routines.DomainValidator;
29 import org.apache.commons.validator.routines.EmailValidator;
31 
36 final public class CorrelationAttributeNormalizer {
37 
38  //common seperators that may be removed for normalizing
39  private static final String SEPERATORS_REGEX = "[\\s-:]";
40 
50  public static String normalize(CorrelationAttributeInstance.Type attributeType, String data) throws CorrelationAttributeNormalizationException {
51 
52  if (attributeType == null) {
53  throw new CorrelationAttributeNormalizationException("Attribute type was null.");
54  }
55  if (data == null) {
56  throw new CorrelationAttributeNormalizationException("Correlation value was null.");
57  }
58 
59  String trimmedData = data.trim();
60 
61  switch (attributeType.getId()) {
63  return normalizeMd5(trimmedData);
65  return normalizeDomain(trimmedData);
67  return normalizeEmail(trimmedData);
69  return normalizePhone(trimmedData);
71  return normalizeUsbId(trimmedData);
73  return verifySsid(trimmedData);
75  return normalizeMac(trimmedData);
77  return normalizeImei(trimmedData);
79  return normalizeImsi(trimmedData);
81  return normalizeIccid(trimmedData);
82 
83  default:
84  try {
85  // If the atttribute is not one of the above
86  // but is one of the other default correlation types, then let the data go as is
88  for (CorrelationAttributeInstance.Type defaultCorrelationType : defaultCorrelationTypes) {
89  if (defaultCorrelationType.getId() == attributeType.getId()) {
90  return trimmedData;
91  }
92  }
93  final String errorMessage = String.format(
94  "Validator function not found for attribute type: %s",
95  attributeType.getDisplayName());
96  throw new CorrelationAttributeNormalizationException(errorMessage);
97  } catch (CentralRepoException ex) {
98  throw new CorrelationAttributeNormalizationException("Failed to get default correlation types.", ex);
99  }
100  }
101  }
102 
112  public static String normalize(int attributeTypeId, String data) throws CorrelationAttributeNormalizationException {
113  try {
115  Optional<CorrelationAttributeInstance.Type> typeOption = defaultTypes.stream().filter(attributeType -> attributeType.getId() == attributeTypeId).findAny();
116 
117  if (typeOption.isPresent()) {
118  CorrelationAttributeInstance.Type type = typeOption.get();
119  return CorrelationAttributeNormalizer.normalize(type, data);
120  } else {
121  throw new CorrelationAttributeNormalizationException(String.format("Given attributeTypeId did not correspond to any known Attribute: %s", attributeTypeId));
122  }
123  } catch (CentralRepoException ex) {
125  }
126  }
127 
131  private static String normalizeMd5(String data) throws CorrelationAttributeNormalizationException {
132  final String validMd5Regex = "^[a-f0-9]{32}$";
133  final String dataLowered = data.toLowerCase();
134  if (dataLowered.matches(validMd5Regex)) {
135  return dataLowered;
136  } else {
137  throw new CorrelationAttributeNormalizationException(String.format("Data purporting to be an MD5 was found not to comform to expected format: %s", data));
138  }
139  }
140 
145  private static String normalizeDomain(String data) throws CorrelationAttributeNormalizationException {
146  DomainValidator validator = DomainValidator.getInstance(true);
147  if (validator.isValid(data)) {
148  return NetworkUtils.extractDomain(data.toLowerCase());
149  } else {
150  final String validIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";
151  if (data.matches(validIpAddressRegex)) {
152  return NetworkUtils.extractDomain(data);
153  } else {
154  throw new CorrelationAttributeNormalizationException(String.format("Data was expected to be a valid domain: %s", data));
155  }
156  }
157  }
158 
168  static String normalizeEmail(String emailAddress) throws CorrelationAttributeNormalizationException {
169  if (isValidEmailAddress(emailAddress)) {
170  return emailAddress.toLowerCase().trim();
171  } else {
172  throw new CorrelationAttributeNormalizationException(String.format("Data was expected to be a valid email address: %s", emailAddress));
173  }
174  }
175 
185  static String normalizePhone(String phoneNumber) throws CorrelationAttributeNormalizationException {
186  if (isValidPhoneNumber(phoneNumber)) {
187  String normalizedNumber = phoneNumber.replaceAll("\\s+", ""); // remove spaces.
188  normalizedNumber = normalizedNumber.replaceAll("[\\-()]", ""); // remove parens & dashes.
189 
190  // ensure a min length
191  if (normalizedNumber.length() < MIN_PHONENUMBER_LEN) {
192  throw new CorrelationAttributeNormalizationException(String.format("Phone number string %s is too short ", phoneNumber));
193  }
194  return normalizedNumber;
195 
196  } else {
197  throw new CorrelationAttributeNormalizationException(String.format("Data was expected to be a valid phone number: %s", phoneNumber));
198  }
199  }
200 
204  private static String normalizeUsbId(String data) throws CorrelationAttributeNormalizationException {
205  //TODO replace with correct usb id validation at a later date
206  return data;
207  }
208 
222  private static String verifySsid(String data) throws CorrelationAttributeNormalizationException {
223  if (data.length() <= 32) {
224  return data;
225  } else {
226  throw new CorrelationAttributeNormalizationException("Name provided was longer than the maximum valid SSID (32 characters). Name: " + data);
227  }
228  }
229 
252  private static String normalizeIccid(String data) throws CorrelationAttributeNormalizationException {
253  final String validIccidRegex = "^89[f0-9]{17,22}$";
254  final String iccidWithoutSeperators = data.toLowerCase().replaceAll(SEPERATORS_REGEX, "");
255  if (iccidWithoutSeperators.matches(validIccidRegex)) {
256  return iccidWithoutSeperators;
257  } else {
258  throw new CorrelationAttributeNormalizationException("Data provided was not a valid ICCID. : " + data);
259  }
260  }
261 
279  private static String normalizeImsi(String data) throws CorrelationAttributeNormalizationException {
280  final String validImsiRegex = "^[0-9]{14,15}$";
281  final String imsiWithoutSeperators = data.replaceAll(SEPERATORS_REGEX, "");
282  if (imsiWithoutSeperators.matches(validImsiRegex)) {
283  return imsiWithoutSeperators;
284  } else {
285  throw new CorrelationAttributeNormalizationException("Data provided was not a valid Imsi. : " + data);
286  }
287  }
288 
303  private static String normalizeMac(String data) throws CorrelationAttributeNormalizationException {
304  final String validMacRegex = "^([a-f0-9]{12}|[a-f0-9]{16})$";
305  final String macWithoutSeperators = data.toLowerCase().replaceAll(SEPERATORS_REGEX, "");
306  if (macWithoutSeperators.matches(validMacRegex)) {
307  return macWithoutSeperators;
308  } else {
309  throw new CorrelationAttributeNormalizationException("Data provided was not a valid Imsi. : " + data);
310  }
311  }
312 
332  private static String normalizeImei(String data) throws CorrelationAttributeNormalizationException {
333  final String validImeiRegex = "^[0-9]{14,16}$";
334  final String imeiWithoutSeperators = data.replaceAll(SEPERATORS_REGEX, "");
335  if (imeiWithoutSeperators.matches(validImeiRegex)) {
336  return imeiWithoutSeperators;
337  } else {
338  throw new CorrelationAttributeNormalizationException("Data provided was not a valid Imsi. : " + data);
339  }
340  }
341 
342  // These symbols are allowed in written form of phone numbers.
343  // A '+' is allowed only as a leading digit and hence not inlcuded here.
344  // While a dialed sequence may have additonal special characters, such as #, * or ',',
345  // CR attributes represent accounts and hence those chatracter are not allowed.
346  private static final Set<String> PHONENUMBER_CHARS = new HashSet<>(Arrays.asList(
347  "-", "(", ")"
348  ));
349 
350  private static final int MIN_PHONENUMBER_LEN = 5;
351 
360  static boolean isValidPhoneNumber(String phoneNumber) {
361 
362  // A phone number may have a leading '+', special telephony chars, or digits.
363  // Anything else implies an invalid phone number.
364  for (int i = 0; i < phoneNumber.length(); i++) {
365  if ( !((i == 0 && phoneNumber.charAt(i) == '+')
366  || Character.isSpaceChar(phoneNumber.charAt(i))
367  || Character.isDigit(phoneNumber.charAt(i))
368  || PHONENUMBER_CHARS.contains(String.valueOf(phoneNumber.charAt(i))))) {
369  return false;
370  }
371  }
372 
373  // ensure a min length
374  return phoneNumber.length() >= MIN_PHONENUMBER_LEN;
375  }
376 
385  static boolean isValidEmailAddress(String emailAddress) {
386  if (!StringUtils.isEmpty(emailAddress)) {
387  EmailValidator validator = EmailValidator.getInstance(true, true);
388  return validator.isValid(emailAddress);
389  }
390 
391  return false;
392  }
393 
398  //Empty constructor
399  }
400 }
static String extractDomain(String urlString)
static String normalize(CorrelationAttributeInstance.Type attributeType, String data)

Copyright © 2012-2021 Basis Technology. Generated on: Fri Aug 6 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.