configuration_utils.m 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. configuration_utils.m
  3. TrustKit
  4. Copyright 2017 The TrustKit Project Authors
  5. Licensed under the MIT license, see associated LICENSE file for terms.
  6. See AUTHORS file for the list of project authors.
  7. */
  8. #import "configuration_utils.h"
  9. #import "TSKTrustKitConfig.h"
  10. #import "Dependencies/domain_registry/domain_registry.h"
  11. #import "TSKLog.h"
  12. static NSUInteger isSubdomain(NSString *domain, NSString *subdomain)
  13. {
  14. // Ensure that the TLDs are the same; this can get tricky with TLDs like .co.uk so we take a cautious approach
  15. size_t domainRegistryLength = GetRegistryLength([domain UTF8String]);
  16. size_t subdomainRegistryLength = GetRegistryLength([subdomain UTF8String]);
  17. if (subdomainRegistryLength != domainRegistryLength)
  18. {
  19. return 0;
  20. }
  21. NSString *domainTld = [domain substringFromIndex: [domain length] - domainRegistryLength];
  22. NSString *subdomainTld = [subdomain substringFromIndex: [subdomain length] - subdomainRegistryLength];
  23. if (![domainTld isEqualToString:subdomainTld])
  24. {
  25. return 0;
  26. }
  27. // Retrieve the main domain without the TLD but append a . at the beginning
  28. // When initializing TrustKit, we check that [domain length] > domainRegistryLength
  29. NSString *domainLabel = [@"." stringByAppendingString:[domain substringToIndex:([domain length] - domainRegistryLength - 1)]];
  30. // Retrieve the subdomain's domain without the TLD
  31. NSString *subdomainLabel = [subdomain substringToIndex:([subdomain length] - domainRegistryLength - 1)];
  32. // Does the subdomain contain the domain
  33. NSArray *subComponents = [subdomainLabel componentsSeparatedByString:domainLabel];
  34. if ([[subComponents lastObject] isEqualToString:@""])
  35. {
  36. // This is a subdomain
  37. return [domainLabel length];
  38. }
  39. return 0;
  40. }
  41. NSString * _Nullable getPinningConfigurationKeyForDomain(NSString * _Nonnull hostname , NSDictionary<NSString *, TKSDomainPinningPolicy *> * _Nonnull domainPinningPolicies)
  42. {
  43. NSString *notedHostname = nil;
  44. if (domainPinningPolicies[hostname] == nil)
  45. {
  46. NSUInteger bestMatch = 0;
  47. // No pins explicitly configured for this domain
  48. // Look for an includeSubdomain pin that applies
  49. for (NSString *pinnedServerName in domainPinningPolicies)
  50. {
  51. // Check each domain configured with the includeSubdomain flag
  52. if ([domainPinningPolicies[pinnedServerName][kTSKIncludeSubdomains] boolValue])
  53. {
  54. // Is the server a subdomain of this pinned server?
  55. TSKLog(@"Checking includeSubdomains configuration for %@", pinnedServerName);
  56. NSUInteger currentMatch = isSubdomain(pinnedServerName, hostname);
  57. if (currentMatch > 0 && currentMatch > bestMatch)
  58. {
  59. // Yes; let's use the parent domain's pinning configuration
  60. TSKLog(@"Applying includeSubdomains configuration from %@ to %@ (new best match of %d chars)", pinnedServerName, hostname, currentMatch);
  61. bestMatch = currentMatch;
  62. notedHostname = pinnedServerName;
  63. }
  64. else if (currentMatch > 0)
  65. {
  66. TSKLog(@"Not applying includeSubdomains configuration from %@ to %@ (current match of %d chars does not exceed best match)", pinnedServerName, hostname, currentMatch);
  67. }
  68. }
  69. }
  70. }
  71. else
  72. {
  73. // This hostname has a pinnning configuration
  74. notedHostname = hostname;
  75. }
  76. if (notedHostname == nil)
  77. {
  78. TSKLog(@"Domain %@ is not pinned", hostname);
  79. }
  80. return notedHostname;
  81. }