OriginMatcher.java

1
package com.yubico.webauthn;
2
3
import java.net.MalformedURLException;
4
import java.net.URL;
5
import java.util.Set;
6
import lombok.experimental.UtilityClass;
7
import lombok.extern.slf4j.Slf4j;
8
9
@Slf4j
10
@UtilityClass
11
class OriginMatcher {
12
13
  static boolean isAllowed(
14
      String origin, Set<String> allowedOrigins, boolean allowPort, boolean allowSubdomain) {
15
    log.trace("isAllowed({}, {}, {}, {})", origin, allowedOrigins, allowPort, allowSubdomain);
16
17
    URL tmpOriginUrl;
18
    try {
19
      tmpOriginUrl = new URL(origin);
20
    } catch (MalformedURLException e) {
21
      log.debug("Origin in client data is not a valid URL; will only match exactly: {}", origin);
22
      tmpOriginUrl = null;
23
    }
24
    final URL originUrl = tmpOriginUrl;
25
26 2 1. isAllowed : replaced boolean return with true for com/yubico/webauthn/OriginMatcher::isAllowed → KILLED
2. isAllowed : replaced boolean return with false for com/yubico/webauthn/OriginMatcher::isAllowed → KILLED
    return allowedOrigins.stream()
27
        .anyMatch(
28
            allowedOriginString -> {
29 1 1. lambda$isAllowed$0 : negated conditional → KILLED
              if (allowedOriginString.equals(origin)) {
30
                log.debug("Exact match: {} == {}", origin, allowedOriginString);
31 1 1. lambda$isAllowed$0 : replaced boolean return with false for com/yubico/webauthn/OriginMatcher::lambda$isAllowed$0 → KILLED
                return true;
32 3 1. lambda$isAllowed$0 : negated conditional → KILLED
2. lambda$isAllowed$0 : negated conditional → KILLED
3. lambda$isAllowed$0 : negated conditional → KILLED
              } else if (originUrl != null && (allowPort || allowSubdomain)) {
33
                final URL allowedOrigin;
34
                try {
35
                  allowedOrigin = new URL(allowedOriginString);
36
                } catch (MalformedURLException e) {
37
                  log.error(
38
                      "Allowed origin is not a valid URL; skipping port/subdomain matching: {}",
39
                      allowedOriginString);
40 1 1. lambda$isAllowed$0 : replaced boolean return with true for com/yubico/webauthn/OriginMatcher::lambda$isAllowed$0 → KILLED
                  return false;
41
                }
42
43
                final boolean portAccepted = isPortAccepted(allowPort, allowedOrigin, originUrl);
44
                final boolean domainAccepted =
45
                    isDomainAccepted(allowSubdomain, allowedOrigin, originUrl);
46
47
                log.debug("portAccepted: {}, domainAccepted: {}", portAccepted, domainAccepted);
48 3 1. lambda$isAllowed$0 : negated conditional → KILLED
2. lambda$isAllowed$0 : negated conditional → KILLED
3. lambda$isAllowed$0 : replaced boolean return with true for com/yubico/webauthn/OriginMatcher::lambda$isAllowed$0 → KILLED
                return portAccepted && domainAccepted;
49
              } else {
50
                log.debug("No match: {} != {}", origin, allowedOriginString);
51 1 1. lambda$isAllowed$0 : replaced boolean return with true for com/yubico/webauthn/OriginMatcher::lambda$isAllowed$0 → KILLED
                return false;
52
              }
53
            });
54
  }
55
56
  private static boolean isPortAccepted(boolean allowAnyPort, URL allowedOrigin, URL origin) {
57 1 1. isPortAccepted : negated conditional → KILLED
    if (allowAnyPort) {
58 1 1. isPortAccepted : replaced boolean return with false for com/yubico/webauthn/OriginMatcher::isPortAccepted → KILLED
      return true;
59
    } else {
60 2 1. isPortAccepted : replaced boolean return with true for com/yubico/webauthn/OriginMatcher::isPortAccepted → KILLED
2. isPortAccepted : negated conditional → KILLED
      return origin.getPort() == allowedOrigin.getPort();
61
    }
62
  }
63
64
  private static boolean isDomainAccepted(boolean allowSubdomain, URL allowedOrigin, URL origin) {
65
    final String allowedDomain = allowedOrigin.getHost();
66
    final String originDomain = origin.getHost();
67
68 1 1. isDomainAccepted : negated conditional → KILLED
    if (allowSubdomain) {
69 3 1. isDomainAccepted : negated conditional → KILLED
2. isDomainAccepted : replaced boolean return with true for com/yubico/webauthn/OriginMatcher::isDomainAccepted → KILLED
3. isDomainAccepted : negated conditional → KILLED
      return originDomain.equals(allowedDomain) || originDomain.endsWith("." + allowedDomain);
70
    } else {
71 2 1. isDomainAccepted : replaced boolean return with false for com/yubico/webauthn/OriginMatcher::isDomainAccepted → KILLED
2. isDomainAccepted : replaced boolean return with true for com/yubico/webauthn/OriginMatcher::isDomainAccepted → KILLED
      return originDomain.equals(allowedDomain);
72
    }
73
  }
74
}

Mutations

26

1.1
Location : isAllowed
Killed by : com.yubico.webauthn.OriginMatcherSpec
replaced boolean return with true for com/yubico/webauthn/OriginMatcher::isAllowed → KILLED

2.2
Location : isAllowed
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced boolean return with false for com/yubico/webauthn/OriginMatcher::isAllowed → KILLED

29

1.1
Location : lambda$isAllowed$0
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
negated conditional → KILLED

31

1.1
Location : lambda$isAllowed$0
Killed by : com.yubico.webauthn.RelyingPartyUserIdentificationSpec
replaced boolean return with false for com/yubico/webauthn/OriginMatcher::lambda$isAllowed$0 → KILLED

32

1.1
Location : lambda$isAllowed$0
Killed by : com.yubico.webauthn.OriginMatcherSpec
negated conditional → KILLED

2.2
Location : lambda$isAllowed$0
Killed by : com.yubico.webauthn.OriginMatcherSpec
negated conditional → KILLED

3.3
Location : lambda$isAllowed$0
Killed by : com.yubico.webauthn.OriginMatcherSpec
negated conditional → KILLED

40

1.1
Location : lambda$isAllowed$0
Killed by : com.yubico.webauthn.OriginMatcherSpec
replaced boolean return with true for com/yubico/webauthn/OriginMatcher::lambda$isAllowed$0 → KILLED

48

1.1
Location : lambda$isAllowed$0
Killed by : com.yubico.webauthn.OriginMatcherSpec
negated conditional → KILLED

2.2
Location : lambda$isAllowed$0
Killed by : com.yubico.webauthn.OriginMatcherSpec
negated conditional → KILLED

3.3
Location : lambda$isAllowed$0
Killed by : com.yubico.webauthn.OriginMatcherSpec
replaced boolean return with true for com/yubico/webauthn/OriginMatcher::lambda$isAllowed$0 → KILLED

51

1.1
Location : lambda$isAllowed$0
Killed by : com.yubico.webauthn.OriginMatcherSpec
replaced boolean return with true for com/yubico/webauthn/OriginMatcher::lambda$isAllowed$0 → KILLED

57

1.1
Location : isPortAccepted
Killed by : com.yubico.webauthn.OriginMatcherSpec
negated conditional → KILLED

58

1.1
Location : isPortAccepted
Killed by : com.yubico.webauthn.OriginMatcherSpec
replaced boolean return with false for com/yubico/webauthn/OriginMatcher::isPortAccepted → KILLED

60

1.1
Location : isPortAccepted
Killed by : com.yubico.webauthn.OriginMatcherSpec
replaced boolean return with true for com/yubico/webauthn/OriginMatcher::isPortAccepted → KILLED

2.2
Location : isPortAccepted
Killed by : com.yubico.webauthn.OriginMatcherSpec
negated conditional → KILLED

68

1.1
Location : isDomainAccepted
Killed by : com.yubico.webauthn.OriginMatcherSpec
negated conditional → KILLED

69

1.1
Location : isDomainAccepted
Killed by : com.yubico.webauthn.OriginMatcherSpec
negated conditional → KILLED

2.2
Location : isDomainAccepted
Killed by : com.yubico.webauthn.OriginMatcherSpec
replaced boolean return with true for com/yubico/webauthn/OriginMatcher::isDomainAccepted → KILLED

3.3
Location : isDomainAccepted
Killed by : com.yubico.webauthn.OriginMatcherSpec
negated conditional → KILLED

71

1.1
Location : isDomainAccepted
Killed by : com.yubico.webauthn.OriginMatcherSpec
replaced boolean return with false for com/yubico/webauthn/OriginMatcher::isDomainAccepted → KILLED

2.2
Location : isDomainAccepted
Killed by : com.yubico.webauthn.OriginMatcherSpec
replaced boolean return with true for com/yubico/webauthn/OriginMatcher::isDomainAccepted → KILLED

Active mutators

Tests examined


Report generated by PIT 1.15.0