Initial Commit

This commit is contained in:
relikd
2020-02-07 16:08:57 +01:00
commit 017aa891ec
42 changed files with 2523 additions and 0 deletions

View File

@@ -0,0 +1,611 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objects = {
/* Begin PBXBuildFile section */
541A957623E602DF00C09C19 /* LaunchIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = 541A957523E602DF00C09C19 /* LaunchIcon.png */; };
541AC5D82399498A00A769D7 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 541AC5D72399498A00A769D7 /* AppDelegate.swift */; };
541AC5DD2399498A00A769D7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 541AC5DB2399498A00A769D7 /* Main.storyboard */; };
541AC5DF2399498B00A769D7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 541AC5DE2399498B00A769D7 /* Assets.xcassets */; };
541AC5E22399498B00A769D7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 541AC5E02399498B00A769D7 /* LaunchScreen.storyboard */; };
541AC5EB2399499A00A769D7 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 541AC5EA2399499A00A769D7 /* NetworkExtension.framework */; };
5433233423ECD3F5007C8052 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 541AC5EA2399499A00A769D7 /* NetworkExtension.framework */; };
548B1F8B23D3374F005B047C /* DNSProxyProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 548B1F8A23D3374F005B047C /* DNSProxyProvider.swift */; };
548B1F9023D3374F005B047C /* GlassDNS.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 548B1F8823D3374F005B047C /* GlassDNS.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
54953E3323DC752E0054345C /* SQDB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B7562223D7B2DC008F0C41 /* SQDB.swift */; };
54953E3423DC752F0054345C /* SQDB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54B7562223D7B2DC008F0C41 /* SQDB.swift */; };
54953E5F23DEBE840054345C /* TVCApps.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54953E5E23DEBE840054345C /* TVCApps.swift */; };
54953E6123E0D69A0054345C /* TVCRequests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54953E6023E0D69A0054345C /* TVCRequests.swift */; };
54953E6F23E44CD00054345C /* TVCRequestDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54953E6E23E44CD00054345C /* TVCRequestDetails.swift */; };
54953E7123E473F10054345C /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 54953E7023E473F10054345C /* Settings.bundle */; };
54B7560123D4EFDC008F0C41 /* DNS in Frameworks */ = {isa = PBXBuildFile; productRef = 54B7560023D4EFDC008F0C41 /* DNS */; };
54B7560323D4F5BC008F0C41 /* DNS in Frameworks */ = {isa = PBXBuildFile; productRef = 54B7560223D4F5BC008F0C41 /* DNS */; };
54C056DB23E9E36E00214A3F /* AppInfoType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54C056DA23E9E36E00214A3F /* AppInfoType.swift */; };
54C056DD23E9EEF700214A3F /* BundleIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54C056DC23E9EEF700214A3F /* BundleIcon.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
548B1F8E23D3374F005B047C /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 541AC5CC2399498A00A769D7 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 548B1F8723D3374F005B047C;
remoteInfo = DNS;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
541AC5FD239949BE00A769D7 /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
548B1F9023D3374F005B047C /* GlassDNS.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
541A957523E602DF00C09C19 /* LaunchIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = LaunchIcon.png; sourceTree = "<group>"; };
541AC5D42399498A00A769D7 /* AppCheck.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AppCheck.app; sourceTree = BUILT_PRODUCTS_DIR; };
541AC5D72399498A00A769D7 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
541AC5DC2399498A00A769D7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
541AC5DE2399498B00A769D7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
541AC5E12399498B00A769D7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
541AC5E32399498B00A769D7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
541AC5EA2399499A00A769D7 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; };
548B1F8823D3374F005B047C /* GlassDNS.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = GlassDNS.appex; sourceTree = BUILT_PRODUCTS_DIR; };
548B1F8A23D3374F005B047C /* DNSProxyProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSProxyProvider.swift; sourceTree = "<group>"; };
548B1F8C23D3374F005B047C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
548B1F8D23D3374F005B047C /* GlassDNS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = GlassDNS.entitlements; sourceTree = "<group>"; };
548B1F9423D338EC005B047C /* main.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = main.entitlements; sourceTree = "<group>"; };
54953E5E23DEBE840054345C /* TVCApps.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVCApps.swift; sourceTree = "<group>"; };
54953E6023E0D69A0054345C /* TVCRequests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVCRequests.swift; sourceTree = "<group>"; };
54953E6E23E44CD00054345C /* TVCRequestDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVCRequestDetails.swift; sourceTree = "<group>"; };
54953E7023E473F10054345C /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
54B7562223D7B2DC008F0C41 /* SQDB.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SQDB.swift; sourceTree = "<group>"; };
54C056DA23E9E36E00214A3F /* AppInfoType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppInfoType.swift; sourceTree = "<group>"; };
54C056DC23E9EEF700214A3F /* BundleIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleIcon.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
541AC5D12399498A00A769D7 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
54B7560123D4EFDC008F0C41 /* DNS in Frameworks */,
541AC5EB2399499A00A769D7 /* NetworkExtension.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
548B1F8523D3374F005B047C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
54B7560323D4F5BC008F0C41 /* DNS in Frameworks */,
5433233423ECD3F5007C8052 /* NetworkExtension.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
541AC5CB2399498A00A769D7 = {
isa = PBXGroup;
children = (
54B7562223D7B2DC008F0C41 /* SQDB.swift */,
541AC5D62399498A00A769D7 /* main */,
548B1F8923D3374F005B047C /* GlassDNS */,
541AC5D52399498A00A769D7 /* Products */,
541AC5E92399499A00A769D7 /* Frameworks */,
);
sourceTree = "<group>";
};
541AC5D52399498A00A769D7 /* Products */ = {
isa = PBXGroup;
children = (
541AC5D42399498A00A769D7 /* AppCheck.app */,
548B1F8823D3374F005B047C /* GlassDNS.appex */,
);
name = Products;
sourceTree = "<group>";
};
541AC5D62399498A00A769D7 /* main */ = {
isa = PBXGroup;
children = (
548B1F9423D338EC005B047C /* main.entitlements */,
541AC5D72399498A00A769D7 /* AppDelegate.swift */,
54C056DC23E9EEF700214A3F /* BundleIcon.swift */,
54C056DA23E9E36E00214A3F /* AppInfoType.swift */,
54953E5E23DEBE840054345C /* TVCApps.swift */,
54953E6023E0D69A0054345C /* TVCRequests.swift */,
54953E6E23E44CD00054345C /* TVCRequestDetails.swift */,
541AC5DB2399498A00A769D7 /* Main.storyboard */,
541A957523E602DF00C09C19 /* LaunchIcon.png */,
541AC5E02399498B00A769D7 /* LaunchScreen.storyboard */,
541AC5DE2399498B00A769D7 /* Assets.xcassets */,
541AC5E32399498B00A769D7 /* Info.plist */,
54953E7023E473F10054345C /* Settings.bundle */,
);
path = main;
sourceTree = "<group>";
};
541AC5E92399499A00A769D7 /* Frameworks */ = {
isa = PBXGroup;
children = (
541AC5EA2399499A00A769D7 /* NetworkExtension.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
548B1F8923D3374F005B047C /* GlassDNS */ = {
isa = PBXGroup;
children = (
548B1F8A23D3374F005B047C /* DNSProxyProvider.swift */,
548B1F8C23D3374F005B047C /* Info.plist */,
548B1F8D23D3374F005B047C /* GlassDNS.entitlements */,
);
path = GlassDNS;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
541AC5D32399498A00A769D7 /* AppCheck */ = {
isa = PBXNativeTarget;
buildConfigurationList = 541AC5E62399498B00A769D7 /* Build configuration list for PBXNativeTarget "AppCheck" */;
buildPhases = (
541AC5D02399498A00A769D7 /* Sources */,
541AC5D12399498A00A769D7 /* Frameworks */,
541AC5D22399498A00A769D7 /* Resources */,
541AC5FD239949BE00A769D7 /* Embed App Extensions */,
54C056E023EAFBDF00214A3F /* ShellScript */,
);
buildRules = (
);
dependencies = (
548B1F8F23D3374F005B047C /* PBXTargetDependency */,
);
name = AppCheck;
packageProductDependencies = (
54B7560023D4EFDC008F0C41 /* DNS */,
);
productName = PrivacyScore;
productReference = 541AC5D42399498A00A769D7 /* AppCheck.app */;
productType = "com.apple.product-type.application";
};
548B1F8723D3374F005B047C /* GlassDNS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 548B1F9123D3374F005B047C /* Build configuration list for PBXNativeTarget "GlassDNS" */;
buildPhases = (
548B1F8423D3374F005B047C /* Sources */,
548B1F8523D3374F005B047C /* Frameworks */,
548B1F8623D3374F005B047C /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = GlassDNS;
packageProductDependencies = (
54B7560223D4F5BC008F0C41 /* DNS */,
);
productName = DNS;
productReference = 548B1F8823D3374F005B047C /* GlassDNS.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
541AC5CC2399498A00A769D7 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1130;
LastUpgradeCheck = 1010;
ORGANIZATIONNAME = relikd;
TargetAttributes = {
541AC5D32399498A00A769D7 = {
CreatedOnToolsVersion = 10.1;
LastSwiftMigration = 1130;
SystemCapabilities = {
com.apple.NetworkExtensions.iOS = {
enabled = 1;
};
};
};
548B1F8723D3374F005B047C = {
CreatedOnToolsVersion = 11.3.1;
};
};
};
buildConfigurationList = 541AC5CF2399498A00A769D7 /* Build configuration list for PBXProject "AppCheck" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 541AC5CB2399498A00A769D7;
packageReferences = (
54B755FF23D4EFDC008F0C41 /* XCRemoteSwiftPackageReference "DNS" */,
);
productRefGroup = 541AC5D52399498A00A769D7 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
541AC5D32399498A00A769D7 /* AppCheck */,
548B1F8723D3374F005B047C /* GlassDNS */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
541AC5D22399498A00A769D7 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
54953E7123E473F10054345C /* Settings.bundle in Resources */,
541AC5E22399498B00A769D7 /* LaunchScreen.storyboard in Resources */,
541AC5DF2399498B00A769D7 /* Assets.xcassets in Resources */,
541AC5DD2399498A00A769D7 /* Main.storyboard in Resources */,
541A957623E602DF00C09C19 /* LaunchIcon.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
548B1F8623D3374F005B047C /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
54C056E023EAFBDF00214A3F /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "#agvtool next-version -all\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
541AC5D02399498A00A769D7 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
54953E3323DC752E0054345C /* SQDB.swift in Sources */,
54953E6123E0D69A0054345C /* TVCRequests.swift in Sources */,
54953E5F23DEBE840054345C /* TVCApps.swift in Sources */,
54C056DB23E9E36E00214A3F /* AppInfoType.swift in Sources */,
54953E6F23E44CD00054345C /* TVCRequestDetails.swift in Sources */,
54C056DD23E9EEF700214A3F /* BundleIcon.swift in Sources */,
541AC5D82399498A00A769D7 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
548B1F8423D3374F005B047C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
548B1F8B23D3374F005B047C /* DNSProxyProvider.swift in Sources */,
54953E3423DC752F0054345C /* SQDB.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
548B1F8F23D3374F005B047C /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 548B1F8723D3374F005B047C /* GlassDNS */;
targetProxy = 548B1F8E23D3374F005B047C /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
541AC5DB2399498A00A769D7 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
541AC5DC2399498A00A769D7 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
541AC5E02399498B00A769D7 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
541AC5E12399498B00A769D7 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
541AC5E42399498B00A769D7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = MY7CB4555Z;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
541AC5E52399498B00A769D7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = MY7CB4555Z;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
541AC5E72399498B00A769D7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = main/main.entitlements;
CURRENT_PROJECT_VERSION = 7;
INFOPLIST_FILE = main/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = "de.uni-bamberg.psi.AppCheck";
PRODUCT_NAME = AppCheck;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Debug;
};
541AC5E82399498B00A769D7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = main/main.entitlements;
CURRENT_PROJECT_VERSION = 7;
INFOPLIST_FILE = main/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = "de.uni-bamberg.psi.AppCheck";
PRODUCT_NAME = AppCheck;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Release;
};
548B1F9223D3374F005B047C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = GlassDNS/GlassDNS.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 7;
DEVELOPMENT_TEAM = MY7CB4555Z;
INFOPLIST_FILE = GlassDNS/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = "de.uni-bamberg.psi.AppCheck.DNS";
PRODUCT_NAME = GlassDNS;
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Debug;
};
548B1F9323D3374F005B047C /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = GlassDNS/GlassDNS.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 7;
DEVELOPMENT_TEAM = MY7CB4555Z;
INFOPLIST_FILE = GlassDNS/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = "de.uni-bamberg.psi.AppCheck.DNS";
PRODUCT_NAME = GlassDNS;
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
541AC5CF2399498A00A769D7 /* Build configuration list for PBXProject "AppCheck" */ = {
isa = XCConfigurationList;
buildConfigurations = (
541AC5E42399498B00A769D7 /* Debug */,
541AC5E52399498B00A769D7 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
541AC5E62399498B00A769D7 /* Build configuration list for PBXNativeTarget "AppCheck" */ = {
isa = XCConfigurationList;
buildConfigurations = (
541AC5E72399498B00A769D7 /* Debug */,
541AC5E82399498B00A769D7 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
548B1F9123D3374F005B047C /* Build configuration list for PBXNativeTarget "GlassDNS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
548B1F9223D3374F005B047C /* Debug */,
548B1F9323D3374F005B047C /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
54B755FF23D4EFDC008F0C41 /* XCRemoteSwiftPackageReference "DNS" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/Bouke/DNS";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.2.0;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
54B7560023D4EFDC008F0C41 /* DNS */ = {
isa = XCSwiftPackageProductDependency;
package = 54B755FF23D4EFDC008F0C41 /* XCRemoteSwiftPackageReference "DNS" */;
productName = DNS;
};
54B7560223D4F5BC008F0C41 /* DNS */ = {
isa = XCSwiftPackageProductDependency;
package = 54B755FF23D4EFDC008F0C41 /* XCRemoteSwiftPackageReference "DNS" */;
productName = DNS;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 541AC5CC2399498A00A769D7 /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,16 @@
{
"object": {
"pins": [
{
"package": "DNS",
"repositoryURL": "https://github.com/Bouke/DNS",
"state": {
"branch": null,
"revision": "78bbd1589890a90b202d11d5f9e1297050cf0eb2",
"version": "1.2.0"
}
}
]
},
"version": 1
}

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1130"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "541AC5D32399498A00A769D7"
BuildableName = "AppCheck.app"
BlueprintName = "AppCheck"
ReferencedContainer = "container:AppCheck.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "541AC5D32399498A00A769D7"
BuildableName = "AppCheck.app"
BlueprintName = "AppCheck"
ReferencedContainer = "container:AppCheck.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "541AC5D32399498A00A769D7"
BuildableName = "AppCheck.app"
BlueprintName = "AppCheck"
ReferencedContainer = "container:AppCheck.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1130"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "548B1F8723D3374F005B047C"
BuildableName = "GlassDNS.appex"
BlueprintName = "GlassDNS"
ReferencedContainer = "container:PrivacyScore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "541AC5D32399498A00A769D7"
BuildableName = "PrivacyScore.app"
BlueprintName = "PrivacyScore"
ReferencedContainer = "container:PrivacyScore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
askForAppToLaunch = "Yes"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "541AC5D32399498A00A769D7"
BuildableName = "PrivacyScore.app"
BlueprintName = "PrivacyScore"
ReferencedContainer = "container:PrivacyScore.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "541AC5D32399498A00A769D7"
BuildableName = "PrivacyScore.app"
BlueprintName = "PrivacyScore"
ReferencedContainer = "container:PrivacyScore.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -0,0 +1,210 @@
import NetworkExtension
import DNS
fileprivate var db: SQLiteDatabase?
class DNSProxyProvider: NEDNSProxyProvider {
override func startProxy(options:[String: Any]? = nil, completionHandler: @escaping (Error?) -> Void) {
// Add code here to start the DNS proxy.
simpleTunnelLog("startProxy")
do {
db = try SQLiteDatabase.open(path: DB_PATH)
try db!.createTable(table: DNSQuery.self)
} catch {
simpleTunnelLog("Error: \(error)")
completionHandler(error)
return
}
completionHandler(nil)
}
override func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
// Add code here to stop the DNS proxy.
simpleTunnelLog("stopProxy")
db = nil
completionHandler()
}
override func sleep(completionHandler: @escaping () -> Void) {
// Add code here to get ready to sleep.
simpleTunnelLog("sleep")
completionHandler()
}
override func wake() {
// Add code here to wake up.
simpleTunnelLog("wake")
}
override func handleNewUDPFlow(_ flow: NEAppProxyUDPFlow, initialRemoteEndpoint remoteEndpoint: NWEndpoint) -> Bool {
simpleTunnelLog("handleUDPFlow \(flow.metaData.sourceAppSigningIdentifier)")
simpleTunnelLog("handleUDPFlow \((remoteEndpoint as! NWHostEndpoint).hostname)")
let con = createUDPSession(to: remoteEndpoint, from: (flow.localEndpoint as! NWHostEndpoint))
let newConnection = ClientDNSProxy(newUDPFlow: flow)
newConnection.open(con)
return true
}
/*override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
// Add code here to handle the incoming flow.
NSLog("PSI: handleFlow %@", flow.metaData.sourceAppSigningIdentifier)
var newConnection: ClientAppProxyConnection?
guard let clientTunnel = tunnel else { return false }
if let tcpFlow = flow as? NEAppProxyTCPFlow {
let remoteHost = (tcpFlow.remoteEndpoint as! NWHostEndpoint).hostname
let remotePort = (tcpFlow.remoteEndpoint as! NWHostEndpoint).port
NSLog("PSI: TCP HOST : \(remoteHost)")
NSLog("PSI: TCP PORT : \(remotePort)")
newConnection = ClientAppProxyTCPConnection(tunnel: clientTunnel, newTCPFlow: tcpFlow)
} else if let udpFlow = flow as? NEAppProxyUDPFlow {
let localHost = (udpFlow.localEndpoint as! NWHostEndpoint).hostname
let localPort = (udpFlow.localEndpoint as! NWHostEndpoint).port
NSLog("PSI: UDP HOST : \(localHost)")
NSLog("PSI: UDP PORT : \(localPort)")
newConnection = ClientAppProxyUDPConnection(tunnel: clientTunnel, newUDPFlow: udpFlow)
}
guard newConnection != nil else { return false }
newConnection!.open()
return true
// return super.handleNewFlow(flow)
}*/
}
class ClientDNSProxy : NSObject {
public let identifier: Int
let appProxyFlow: NEAppProxyFlow
var datagramsOutstanding = 0
var conn: NWUDPSession?
/// The NEAppProxyUDPFlow object corresponding to this connection.
var UDPFlow: NEAppProxyUDPFlow {
return (appProxyFlow as! NEAppProxyUDPFlow)
}
init(newUDPFlow: NEAppProxyUDPFlow) {
appProxyFlow = newUDPFlow
identifier = newUDPFlow.hash
super.init()
}
/// Send an "Open" message to the SimpleTunnel server, to begin the process of establishing a flow of data in the SimpleTunnel protocol.
func open(_ connection: NWUDPSession) {
// open([
// TunnelMessageKey.TunnelType.rawValue: TunnelLayer.app.rawValue as AnyObject,
// TunnelMessageKey.AppProxyFlowType.rawValue: AppProxyFlowKind.udp.rawValue as AnyObject
// ])
connection.setReadHandler({ datas, error in
guard let datagrams = datas, error == nil else {
simpleTunnelLog("Failed to read UDP connection: \(String(describing: error))")
return
}
self.UDPFlow.writeDatagrams(datagrams, sentBy: [connection.endpoint]) { error in
if let error = error {
simpleTunnelLog("Failed to write datagrams to the UDP Flow: \(error)")
// self.tunnel?.sendCloseType(.read, forConnection: self.identifier)
self.UDPFlow.closeWriteWithError(nil)
}
}
}, maxDatagrams: 32)
self.conn = connection
UDPFlow.open(withLocalEndpoint: (UDPFlow.localEndpoint as! NWHostEndpoint)) { (e: Error?) in
self.handleSendResult(nil)
}
}
/// Handle the result of sending a "Data" message to the SimpleTunnel server.
func handleSendResult(_ error: NSError?) {
if let sendError = error {
simpleTunnelLog("Failed to send message to Tunnel Server. error = \(sendError)")
// handleErrorCondition(.hostUnreachable)
return
}
if datagramsOutstanding > 0 {
datagramsOutstanding -= 1
}
// Only read more datagrams from the source application if all outstanding datagrams have been sent on the network.
guard datagramsOutstanding == 0 else { return }
// Read a new set of datagrams from the source application.
UDPFlow.readDatagrams { datagrams, remoteEndPoints, readError in
guard let readDatagrams = datagrams,
let readEndpoints = remoteEndPoints
, readError == nil else
{
simpleTunnelLog("Failed to read data from the UDP flow. error = \(String(describing: readError))")
// self.handleErrorCondition(.peerReset)
return
}
guard !readDatagrams.isEmpty && readEndpoints.count == readDatagrams.count else {
simpleTunnelLog("\(self.identifier): Received EOF on the UDP flow. Closing the flow...")
// self.tunnel?.sendCloseType(.write, forConnection: self.identifier)
self.UDPFlow.closeReadWithError(nil)
return
}
self.datagramsOutstanding = readDatagrams.count
for (index, datagram) in readDatagrams.enumerated() {
guard let endpoint = readEndpoints[index] as? NWHostEndpoint else { continue }
let response = try! Message.init(deserialize: datagram)
for q in response.questions {
simpleTunnelLog("got name \(q.name)")
try? db?.insertDNSQuery(appId: self.UDPFlow.metaData.sourceAppSigningIdentifier as NSString,
dnsQuery: q.name as NSString)
}
simpleTunnelLog("(\(self.identifier)): Sending a \(datagram.count)-byte datagram to \(endpoint.hostname):\(endpoint.port)")
// Send a data message to the SimpleTunnel server.
// self.sendDataMessage(datagram, extraProperties:[
// TunnelMessageKey.Host.rawValue: endpoint.hostname as AnyObject,
// TunnelMessageKey.Port.rawValue: Int(endpoint.port)! as AnyObject
// ])
self.conn?.writeDatagram(datagram, completionHandler: { conError in
simpleTunnelLog("write con err: \(String(describing: conError))")
})
}
// self.UDPFlow.writeDatagrams(readDatagrams, sentBy: readEndpoints) { writeError in
// simpleTunnelLog("write error \(String(describing: writeError))")
// }
}
}
/// Send a datagram received from the SimpleTunnel server to the destination application.
func sendDataWithEndPoint(_ data: Data, host: String, port: Int) {
let datagrams = [ data ]
let endpoints = [ NWHostEndpoint(hostname: host, port: String(port)) ]
// Send the datagram to the destination application.
UDPFlow.writeDatagrams(datagrams, sentBy: endpoints) { error in
if let error = error {
simpleTunnelLog("Failed to write datagrams to the UDP Flow: \(error)")
// self.tunnel?.sendCloseType(.read, forConnection: self.identifier)
self.UDPFlow.closeWriteWithError(nil)
}
}
}
}
public func simpleTunnelLog(_ message: String) {
// NSLog("PSI: \(message)")
}

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>dns-proxy</string>
</array>
<key>com.apple.developer.networking.vpn.api</key>
<array>
<string>allow-vpn</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.de.uni-bamberg.psi.AppCheck</string>
</array>
</dict>
</plist>

31
GlassDNS/Info.plist Normal file
View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>GlassDNS</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>7</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.networkextension.dns-proxy</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).DNSProxyProvider</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.it.h4q.psi.PrivacyScore</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Tunnel</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.networkextension.packet-tunnel</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).PacketTunnelProvider</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,57 @@
import NetworkExtension
class PacketTunnelProvider: NEPacketTunnelProvider {
override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
NSLog("TUN: startTunnel")
// let endpoint = NWHostEndpoint(hostname:"127.0.0.1", port:"4000")
// self.createTCPConnection(to: endpoint, enableTLS: false, tlsParameters: nil, delegate: nil)
completionHandler(nil)
/*
let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "127.0.0.1")
let ip4set = NEIPv4Settings(addresses: ["127.0.0.1"], subnetMasks: ["255.255.255.0"])
let defaultRoute = NEIPv4Route.default()
let localRoute = NEIPv4Route(destinationAddress: "192.168.2.1", subnetMask: "255.255.255.0")
ip4set.includedRoutes = [defaultRoute, localRoute]
ip4set.excludedRoutes = []
settings.ipv4Settings = ip4set
// settings.mtu = 1500
settings.dnsSettings = NEDNSSettings(servers: ["8.8.8.8"])
settings.tunnelOverheadBytes = 150
self.setTunnelNetworkSettings(settings) { error in
guard error == nil else {
NSLog("setTunnelNetworkSettings error: \(String(describing: error))")
return
}
NSLog("setTunnelNetworkSettings success")
completionHandler(nil)
}*/
}
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
NSLog("TUN: stopTunnel")
completionHandler()
}
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
NSLog("TUN: handleAppMessage")
if let handler = completionHandler {
handler(messageData)
}
}
override func sleep(completionHandler: @escaping () -> Void) {
NSLog("TUN: sleep")
completionHandler()
}
override func wake() {
NSLog("TUN: wake")
}
override func createUDPSessionThroughTunnel(to remoteEndpoint: NWEndpoint, from localEndpoint: NWHostEndpoint?) -> NWUDPSession {
NSLog("TUN: createUDP")
return createUDPSession(to: remoteEndpoint, from: localEndpoint)
}
}

173
SQDB.swift Normal file
View File

@@ -0,0 +1,173 @@
import Foundation
import SQLite3
//let basePath = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let basePath = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.de.uni-bamberg.psi.AppCheck")
public let DB_PATH = basePath!.appendingPathComponent("dnslog.sqlite").relativePath
enum SQLiteError: Error {
case OpenDatabase(message: String)
case Prepare(message: String)
case Step(message: String)
case Bind(message: String)
}
//: ## The Database Connection
class SQLiteDatabase {
private let dbPointer: OpaquePointer?
private init(dbPointer: OpaquePointer?) {
self.dbPointer = dbPointer
}
fileprivate var errorMessage: String {
if let errorPointer = sqlite3_errmsg(dbPointer) {
let errorMessage = String(cString: errorPointer)
return errorMessage
} else {
return "No error message provided from sqlite."
}
}
deinit {
sqlite3_close(dbPointer)
// SQLiteDatabase.destroyDatabase(path: DB_PATH)
}
static func destroyDatabase(path: String) {
do {
if FileManager.default.fileExists(atPath: path) {
try FileManager.default.removeItem(atPath: path)
}
} catch {
print("Could not destroy database file: \(path)")
}
}
func destroyContent() throws {
let deleteStatement = try prepareStatement(sql: "DELETE FROM req;")
defer {
sqlite3_finalize(deleteStatement)
}
guard sqlite3_step(deleteStatement) == SQLITE_DONE else {
throw SQLiteError.Step(message: errorMessage)
}
}
static func open(path: String) throws -> SQLiteDatabase {
var db: OpaquePointer?
//sqlite3_open_v2(path, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_SHAREDCACHE, nil)
if sqlite3_open(path, &db) == SQLITE_OK {
return SQLiteDatabase(dbPointer: db)
} else {
defer {
if db != nil {
sqlite3_close(db)
}
}
if let errorPointer = sqlite3_errmsg(db) {
let message = String(cString: errorPointer)
throw SQLiteError.OpenDatabase(message: message)
} else {
throw SQLiteError.OpenDatabase(message: "No error message provided from sqlite.")
}
}
}
func prepareStatement(sql: String) throws -> OpaquePointer? {
var statement: OpaquePointer?
guard sqlite3_prepare_v2(dbPointer, sql, -1, &statement, nil) == SQLITE_OK else {
throw SQLiteError.Prepare(message: errorMessage)
}
return statement
}
func createTable(table: SQLTable.Type) throws {
let createTableStatement = try prepareStatement(sql: table.createStatement)
defer {
sqlite3_finalize(createTableStatement)
}
guard sqlite3_step(createTableStatement) == SQLITE_DONE else {
throw SQLiteError.Step(message: errorMessage)
}
}
}
protocol SQLTable {
static var createStatement: String { get }
}
struct DNSQuery: SQLTable {
let app: String
let dns: String
let ts: Int64
static var createStatement: String {
return """
CREATE TABLE IF NOT EXISTS req(
app VARCHAR(255),
dns VARCHAR(2047),
ts BIGINT DEFAULT (strftime('%s','now'))
);
"""
}
}
extension SQLiteDatabase {
func insertDNSQuery(appId: NSString, dnsQuery: NSString) throws {
let insertSql = "INSERT INTO req (app, dns) VALUES (?, ?);"
let insertStatement = try prepareStatement(sql: insertSql)
defer {
sqlite3_finalize(insertStatement)
}
guard
sqlite3_bind_text(insertStatement, 1, appId.utf8String, -1, nil) == SQLITE_OK &&
sqlite3_bind_text(insertStatement, 2, dnsQuery.utf8String, -1, nil) == SQLITE_OK
else {
throw SQLiteError.Bind(message: errorMessage)
}
guard sqlite3_step(insertStatement) == SQLITE_DONE else {
throw SQLiteError.Step(message: errorMessage)
}
}
func dnsQueriesForApp(appIdentifier: NSString, _ body: @escaping (DNSQuery) -> Void) {
let querySql = "SELECT * FROM req WHERE app = ?;"
guard let queryStatement = try? prepareStatement(sql: querySql) else {
print("Error preparing statement for insert")
return
}
defer {
sqlite3_finalize(queryStatement)
}
guard sqlite3_bind_text(queryStatement, 1, appIdentifier.utf8String, -1, nil) == SQLITE_OK else {
print("Error binding insert key")
return
}
while (sqlite3_step(queryStatement) == SQLITE_ROW) {
let appId = sqlite3_column_text(queryStatement, 0)
let dnsQ = sqlite3_column_text(queryStatement, 1)
let ts = sqlite3_column_int64(queryStatement, 2)
let res = DNSQuery(app: String(cString: appId!),
dns: String(cString: dnsQ!),
ts: ts)
body(res)
}
}
func appList() -> [String] {
let querySql = "SELECT DISTINCT app FROM req;"
guard let queryStatement = try? prepareStatement(sql: querySql) else {
print("Error preparing statement for insert")
return []
}
defer {
sqlite3_finalize(queryStatement)
}
var res: [String] = []
while (sqlite3_step(queryStatement) == SQLITE_ROW) {
let appId = sqlite3_column_text(queryStatement, 0)
res.append(String(cString: appId!))
}
return res
}
}

261
main/AppDelegate.swift Normal file
View File

@@ -0,0 +1,261 @@
import UIKit
import NetworkExtension
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if UserDefaults.standard.bool(forKey: "kill_proxy") {
UserDefaults.standard.set(false, forKey: "kill_proxy")
disableDNS()
} else {
postDNSState()
}
if UserDefaults.standard.bool(forKey: "kill_db") {
UserDefaults.standard.set(false, forKey: "kill_db")
SQLiteDatabase.destroyDatabase(path: DB_PATH)
}
do {
let db = try SQLiteDatabase.open(path: DB_PATH)
try db.createTable(table: DNSQuery.self)
} catch {}
// loadVPN { self.startVPN() }
return true
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
postDNSState()
}
func setProxyEnabled(_ newState: Bool) {
// DNS:
if newState != managerDNS.isEnabled {
newState ? enableDNS() : disableDNS()
}
// VPN:
// let con = self.managerVPN?.connection
// if newState != (con?.status == NEVPNStatus.connected) {
// self.updateVPN {
// self.managerVPN?.isEnabled = newState
// newState ? try? con?.startVPNTunnel() : con?.stopVPNTunnel()
// }
// }
}
// MARK: DNS
let managerDNS = NEDNSProxyManager.shared()
private func enableDNS() {
updateDNS {
self.managerDNS.localizedDescription = "GlassDNS"
let proto = NEDNSProxyProviderProtocol()
proto.providerBundleIdentifier = "de.uni-bamberg.psi.AppCheck.DNS"
self.managerDNS.providerProtocol = proto
self.managerDNS.isEnabled = true
}
}
private func disableDNS() {
updateDNS {
self.managerDNS.isEnabled = false
}
}
private func updateDNS(_ body: @escaping () -> Void) {
managerDNS.loadFromPreferences { (error) in
guard error == nil else { return }
body()
self.managerDNS.saveToPreferences { (error) in
self.postDNSState()
guard error == nil else { return }
}
}
}
private func postDNSState() {
managerDNS.loadFromPreferences {_ in
NotificationCenter.default.post(name: .init("ChangedStateGlassDNS"), object: self.managerDNS.isEnabled)
}
}
// MARK: VPN
/*var managerVPN: NETunnelProviderManager?
private func loadVPN(_ finally: @escaping () -> Void) {
NETunnelProviderManager.loadAllFromPreferences { managers, error in
if managers?.count ?? 0 > 0 {
managers?.forEach({ mgr in
if let proto = (mgr.protocolConfiguration as? NETunnelProviderProtocol) {
if proto.providerBundleIdentifier == "de.uni-bamberg.psi.AppCheck.Tunnel" {
// self.managerVPN = mgr
mgr.removeFromPreferences()
}
}
})
}
if self.managerVPN != nil {
finally()
} else {
let mgr = NETunnelProviderManager()
mgr.localizedDescription = "GlassTunnel"
let proto = NETunnelProviderProtocol()
proto.providerBundleIdentifier = "de.uni-bamberg.psi.AppCheck.Tunnel"
proto.serverAddress = "127.0.0.1"
// proto.username = "none"
// proto.proxySettings = NEProxySettings()
// proto.proxySettings?.httpEnabled = true
// proto.proxySettings?.httpsEnabled = true
// proto.authenticationMethod = .sharedSecret
// proto.sharedSecretReference = try! VPNKeychain.persistentReferenceFor(service: "GlassTunnel", account:"none", password: "none".data(using: String.Encoding.utf8)!)
mgr.protocolConfiguration = proto
mgr.isEnabled = true
self.managerVPN = mgr
mgr.saveToPreferences { (error) in
guard error == nil else {
NSLog("VPN: save error: \(String(describing: error))")
return
}
finally()
}
}
}
}
private func startVPN() {
updateVPN {
do {
try self.managerVPN?.connection.startVPNTunnel()
} catch {
print("VPN: start error: \(error.localizedDescription)")
}
}
}
private func updateVPN(_ body: @escaping () -> Void) {
self.managerVPN?.loadFromPreferences { (error) in
guard error == nil else {
return
}
body()
self.managerVPN?.saveToPreferences { (error) in
guard error == nil else {
NSLog("VPN: save error: \(String(describing: error))")
return
}
}
}
}*/
}
// MARK: VPNKeychain
/*
/// Utility routines for working with the keychain.
enum VPNKeychain {
/// Returns a persistent reference for a generic password keychain item, adding it to
/// (or updating it in) the keychain if necessary.
///
/// This delegates the work to two helper routines depending on whether the item already
/// exists in the keychain or not.
///
/// - Parameters:
/// - service: The service name for the item.
/// - account: The account for the item.
/// - password: The desired password.
/// - Returns: A persistent reference to the item.
/// - Throws: Any error returned by the Security framework.
static func persistentReferenceFor(service: String, account: String, password: Data) throws -> Data {
var copyResult: CFTypeRef? = nil
let err = SecItemCopyMatching([
kSecClass: kSecClassGenericPassword,
kSecAttrService: service,
kSecAttrAccount: account,
kSecReturnPersistentRef: true,
kSecReturnData: true
] as NSDictionary, &copyResult)
switch err {
case errSecSuccess:
return try self.persistentReferenceByUpdating(copyResult: copyResult!, service: service, account: account, password: password)
case errSecItemNotFound:
return try self.persistentReferenceByAdding(service: service, account:account, password: password)
default:
try throwOSStatus(err)
// `throwOSStatus(_:)` only returns in the `errSecSuccess` case. We know we're
// not in that case but the compiler can't figure that out, alas.
fatalError()
}
}
/// Returns a persistent reference for a generic password keychain item by updating it
/// in the keychain if necessary.
///
/// - Parameters:
/// - copyResult: The result from the `SecItemCopyMatching` done by `persistentReferenceFor(service:account:password:)`.
/// - service: The service name for the item.
/// - account: The account for the item.
/// - password: The desired password.
/// - Returns: A persistent reference to the item.
/// - Throws: Any error returned by the Security framework.
private static func persistentReferenceByUpdating(copyResult: CFTypeRef, service: String, account: String, password: Data) throws -> Data {
let copyResult = copyResult as! [String:Any]
let persistentRef = copyResult[kSecValuePersistentRef as String] as! NSData as Data
let currentPassword = copyResult[kSecValueData as String] as! NSData as Data
if password != currentPassword {
let err = SecItemUpdate([
kSecClass: kSecClassGenericPassword,
kSecAttrService: service,
kSecAttrAccount: account,
] as NSDictionary, [
kSecValueData: password
] as NSDictionary)
try throwOSStatus(err)
}
return persistentRef
}
/// Returns a persistent reference for a generic password keychain item by adding it to
/// the keychain.
///
/// - Parameters:
/// - service: The service name for the item.
/// - account: The account for the item.
/// - password: The desired password.
/// - Returns: A persistent reference to the item.
/// - Throws: Any error returned by the Security framework.
private static func persistentReferenceByAdding(service: String, account: String, password: Data) throws -> Data {
var addResult: CFTypeRef? = nil
let err = SecItemAdd([
kSecClass: kSecClassGenericPassword,
kSecAttrService: service,
kSecAttrAccount: account,
kSecValueData: password,
kSecReturnPersistentRef: true,
] as NSDictionary, &addResult)
try throwOSStatus(err)
return addResult! as! NSData as Data
}
/// Throws an error if a Security framework call has failed.
///
/// - Parameter err: The error to check.
private static func throwOSStatus(_ err: OSStatus) throws {
guard err == errSecSuccess else {
throw NSError(domain: NSOSStatusErrorDomain, code: Int(err), userInfo: nil)
}
}
}
*/

129
main/AppInfoType.swift Normal file
View File

@@ -0,0 +1,129 @@
import Foundation
import UIKit
private let fm = FileManager.default
private let documentsDir = try! fm.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
private let bundleInfoDir = documentsDir.appendingPathComponent("bundleInfo", isDirectory:true)
struct AppInfoType : Decodable {
var id: String
var name: String?
var seller: String?
var imageURL: URL?
private var remoteImgURL: String?
private var cache: Bool?
private let localJSON: URL
private let localImgURL: URL
static func initWorkingDir() {
try? fm.createDirectory(at: bundleInfoDir, withIntermediateDirectories: true, attributes: nil)
// print("init dir: \(bundleInfoDir)")
}
init(id: String) {
self.id = id
if id == "" {
name = "?"
cache = true
localJSON = URL(fileURLWithPath: "")
localImgURL = localJSON
} else {
localJSON = bundleInfoDir.appendingPathComponent("\(id).json")
localImgURL = bundleInfoDir.appendingPathComponent("\(id).img")
reload()
}
}
mutating func reload() {
if fm.fileExists(atPath: localImgURL.path) {
imageURL = localImgURL
}
guard name == nil, seller == nil,
fm.fileExists(atPath: localJSON.path),
let attr = try? fm.attributesOfItem(atPath: localJSON.path),
attr[FileAttributeKey.size] as! UInt64 > 0 else
{
// process json only if attributes not set yet,
// OR json doesn't exist, OR json is empty
return
}
(name, seller, remoteImgURL) = parseJSON(localJSON)
if remoteImgURL == nil || imageURL != nil {
cache = true
}
}
func getImage() -> UIImage? {
if let img = imageURL, let data = try? Data(contentsOf: img) {
return UIImage(data: data, scale: 2.0)
} else if id.hasPrefix("com.apple.") {
return appIconApple
} else {
return appIconUnknown
}
}
private func parseJSON(_ location: URL) -> (name: String?, seller: String?, image: String?) {
do {
let data = try Data.init(contentsOf: location)
if
let json = try JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed) as? [String: Any],
let resAll = json["results"] as? [Any],
let res = resAll.first as? [String: Any]
{
let name = res["trackName"] as? String // trackCensoredName
let seller = res["sellerName"] as? String // artistName
let image = res["artworkUrl60"] as? String // artworkUrl100
return (name, seller, image)
} else if id.hasPrefix("com.apple.") {
return (String(id.dropFirst(10)), "Apple Inc.", nil)
}
} catch {}
return (nil, nil, nil)
}
mutating func updateIfNeeded(_ updateClosure: () -> Void) {
guard cache == nil,
let safeId = id.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
return
}
cache = false // meaning: hasn't downloaded yet, but is about to do
// print("downloading \(id)")
_ = downloadURL("https://itunes.apple.com/lookup?bundleId=\(safeId)", toFile: localJSON).flatMap{
// print("downloading \(id) done.")
reload()
updateClosure()
return downloadURL(remoteImgURL, toFile: localImgURL)
}.map{
// print("downloading \(id) image done.")
reload()
updateClosure()
}
}
enum NetworkError: Error {
case url
}
private func downloadURL(_ urlStr: String?, toFile: URL) -> Result<Void, Error> {
guard let urlStr = urlStr, let url = URL(string: urlStr) else {
return .failure(NetworkError.url)
}
var result: Result<Void, Error>!
let semaphore = DispatchSemaphore(value: 0)
URLSession.shared.downloadTask(with: url) { location, response, error in
if let loc = location {
try? fm.removeItem(at: toFile)
try? fm.moveItem(at: loc, to: toFile)
result = .success(())
} else {
result = .failure(error!)
}
semaphore.signal()
}.resume()
_ = semaphore.wait(wallTimeout: .distantFuture)
return result
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -0,0 +1,116 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "icon_40x40.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "icon_60x60.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "icon_58x58.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "icon_87x87.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "icon_80x80.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "icon_120x120.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "icon_120x120.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "icon_180x180.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "icon_20x20.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "icon_40x40.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "icon_29x29.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "icon_58x58.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "icon_40x40.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "icon_80x80.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "icon_76x76.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "icon_152x152.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "icon_167x167.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Artwork.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 837 B

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" fixedFrame="YES" image="LaunchIcon.png" translatesAutoresizingMaskIntoConstraints="NO" id="bF5-Lq-Xqf">
<rect key="frame" x="186" y="427" width="42" height="42"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
</imageView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="52.173913043478265" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchIcon.png" width="128" height="128"/>
</resources>
</document>

View File

@@ -0,0 +1,204 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="RcB-4v-fd4">
<device id="retina4_0" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Services-->
<scene sceneID="MN1-aZ-cZt">
<objects>
<tableViewController id="pdd-aM-sKl" customClass="TVCApps" customModule="AppCheck" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="60" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="kj3-8X-TyT">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<inset key="separatorInset" minX="15" minY="0.0" maxX="15" maxY="0.0"/>
<textView key="tableHeaderView" clipsSubviews="YES" multipleTouchEnabled="YES" userInteractionEnabled="NO" contentMode="scaleToFill" editable="NO" selectable="NO" id="QWn-iX-27k">
<rect key="frame" x="0.0" y="0.0" width="320" height="501"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<accessibility key="accessibilityConfiguration">
<accessibilityTraits key="traits" staticText="YES" notEnabled="YES"/>
<bool key="isElement" value="YES"/>
</accessibility>
<string key="text">AppCheck helps you identify which applications communicate with third parties. It does so by logging DNS network requests. AppCheck learns only the destination addresses, not the actual data that is exchanged.
For improved readability, AppCheck shows domain names in reversed order (org.example instead of example.org)
Requests to the same domain in quick succession cannot be monitored due to DNS caching (counters may be inaccurate).
Your data belongs to you. Therefore, monitoring and analysis take place on your device only. The app does not share any data with us or any other third-party. There is one exception to this rule: To display app icons, AppCheck sends the Bundle ID (e.g., com.apple.Music) of all monitored apps to `itunes.apple.com`.
⒈ Tap the red button in the upper right corner to start the DNS proxy. The proxy is only accessible locally to apps on this device.
⒉ The proxy monitors DNS requests in the background.
⒊ Use your apps as usual.
⒋ Come back to AppCheck to see the results.</string>
<color key="textColor" systemColor="labelColor" cocoaTouchSystemColor="darkTextColor"/>
<fontDescription key="fontDescription" name=".AppleSystemUIFont" family=".AppleSystemUIFont" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="AppBundleCell" textLabel="d1D-Z8-ddD" detailTextLabel="8LO-2o-dzK" imageView="zHu-V9-cbv" rowHeight="60" style="IBUITableViewCellStyleSubtitle" id="Jcl-oS-Z3B">
<rect key="frame" x="0.0" y="529" width="320" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Jcl-oS-Z3B" id="B7M-RN-vvx">
<rect key="frame" x="0.0" y="0.0" width="320" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" ambiguous="YES" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="d1D-Z8-ddD">
<rect key="frame" x="15" y="10" width="33.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" ambiguous="YES" insetsLayoutMarginsFromSafeArea="NO" text="Subtitle" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8LO-2o-dzK">
<rect key="frame" x="15" y="33.5" width="44" height="14.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" insetsLayoutMarginsFromSafeArea="NO" id="zHu-V9-cbv">
<rect key="frame" x="16" y="0.0" width="60" height="60"/>
<autoresizingMask key="autoresizingMask"/>
</imageView>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="WcC-nb-Vf5" kind="show" id="Z7t-Jy-aNR"/>
</connections>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="pdd-aM-sKl" id="4fX-iP-7Oa"/>
<outlet property="delegate" destination="pdd-aM-sKl" id="3RN-az-SYU"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Services" id="nY5-jL-QT9">
<barButtonItem key="leftBarButtonItem" systemItem="trash" id="PPO-Wv-RWf">
<connections>
<action selector="clickToolbarLeft:" destination="pdd-aM-sKl" id="iFj-4n-lvg"/>
</connections>
</barButtonItem>
<barButtonItem key="rightBarButtonItem" tag="-1" title="&lt;State&gt;" id="SfA-a1-N1w">
<connections>
<action selector="clickToolbarRight:" destination="pdd-aM-sKl" id="zgS-Wn-apQ"/>
</connections>
</barButtonItem>
</navigationItem>
<connections>
<outlet property="welcomeMessage" destination="QWn-iX-27k" id="jA3-Dz-7zu"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="jfx-iA-E0v" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="742.5" y="167.95774647887325"/>
</scene>
<!--Requests-->
<scene sceneID="ZCV-Yx-jjW">
<objects>
<tableViewController id="WcC-nb-Vf5" customClass="TVCRequests" customModule="AppCheck" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="nRF-dc-dC2">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="RequestCell" textLabel="Rnk-SP-UHm" detailTextLabel="ovQ-lJ-hWJ" style="IBUITableViewCellStyleValue1" id="uv0-9B-Zbb">
<rect key="frame" x="0.0" y="28" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="uv0-9B-Zbb" id="6vH-Du-gCg">
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Rnk-SP-UHm">
<rect key="frame" x="16" y="12" width="33.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Detail" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ovQ-lJ-hWJ">
<rect key="frame" x="260" y="12" width="44" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" systemColor="tertiaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.29999999999999999" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="h7Z-Qr-pJ5" kind="show" id="TPa-Zn-eOs"/>
</connections>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="WcC-nb-Vf5" id="szM-iI-Jgi"/>
<outlet property="delegate" destination="WcC-nb-Vf5" id="sBd-BW-Wg6"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Requests" prompt="com.app.Example" id="TvD-8U-F05"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Gdi-Xi-JUL" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1448" y="168"/>
</scene>
<!--Occurrences-->
<scene sceneID="ws3-sK-l8m">
<objects>
<tableViewController id="h7Z-Qr-pJ5" customClass="TVCRequestDetails" customModule="AppCheck" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" allowsSelection="NO" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="4ms-FO-Fge">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="RequestDetailCell" textLabel="J2P-mU-Vad" style="IBUITableViewCellStyleDefault" id="ZCA-Dz-i92">
<rect key="frame" x="0.0" y="28" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="ZCA-Dz-i92" id="nxe-48-jAQ">
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" enabled="NO" adjustsFontSizeToFit="NO" id="J2P-mU-Vad">
<rect key="frame" x="16" y="0.0" width="288" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="h7Z-Qr-pJ5" id="fyW-Av-fWY"/>
<outlet property="delegate" destination="h7Z-Qr-pJ5" id="gBq-jA-u5V"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Occurrences" prompt="com.domain.network.cdn" id="bys-2u-rHs"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="UxH-PH-KQy" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2147" y="168"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="bDO-X1-bCe">
<objects>
<navigationController id="RcB-4v-fd4" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="HWd-73-m8j">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="pdd-aM-sKl" kind="relationship" relationship="rootViewController" id="oMe-a0-xN7"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="8j4-AX-JBN" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="40" y="168"/>
</scene>
</scenes>
</document>

78
main/BundleIcon.swift Normal file
View File

@@ -0,0 +1,78 @@
import UIKit
let appIconApple = generateAppleIcon()
let appIconUnknown = generateUnknownIcon()
func generateAppleIcon() -> UIImage? {
let rect = CGRect(x: 0, y: 0, width: 30, height: 30)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
// #colorLiteral(red: 0.5843137503, green: 0.8235294223, blue: 0.4196078479, alpha: 1).setFill()
// UIBezierPath(roundedRect: rect, cornerRadius: 0).fill()
// print("drawing")
let fs = 36 as CGFloat
let hFont = UIFont.systemFont(ofSize: fs)
var attrib = [
NSAttributedString.Key.font: hFont,
NSAttributedString.Key.foregroundColor: UIColor.gray
]
let str = "" as NSString
let actualHeight = str.size(withAttributes: attrib).height
attrib[NSAttributedString.Key.font] = hFont.withSize(fs * fs / actualHeight)
let strW = str.size(withAttributes: attrib).width
str.draw(at: CGPoint(x: (rect.size.width - strW) / 2.0, y: -3), withAttributes: attrib)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
func generateUnknownIcon() -> UIImage? {
let rect = CGRect(x: 0, y: 0, width: 30, height: 30)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
let context = UIGraphicsGetCurrentContext()!
let lineWidth: CGFloat = 0.5
let corner: CGFloat = 6.75
let c = corner / CGFloat.pi + lineWidth/2
let sz: CGFloat = rect.height
let m = sz / 2
let r1 = 0.2 * sz, r2 = sqrt(2 * r1 * r1)
// diagonal
context.lineFromTo(x1: c, y1: c, x2: sz-c, y2: sz-c)
context.lineFromTo(x1: c, y1: sz-c, x2: sz-c, y2: c)
// horizontal
context.lineFromTo(x1: 0, y1: m, x2: sz, y2: m)
context.lineFromTo(x1: 0, y1: m + r1, x2: sz, y2: m + r1)
context.lineFromTo(x1: 0, y1: m - r1, x2: sz, y2: m - r1)
// vertical
context.lineFromTo(x1: m, y1: 0, x2: m, y2: sz)
context.lineFromTo(x1: m + r1, y1: 0, x2: m + r1, y2: sz)
context.lineFromTo(x1: m - r1, y1: 0, x2: m - r1, y2: sz)
// circles
context.addEllipse(in: CGRect(x: m - r1, y: m - r1, width: 2*r1, height: 2*r1))
context.addEllipse(in: CGRect(x: m - r2, y: m - r2, width: 2*r2, height: 2*r2))
let r3 = CGRect(x: c, y: c, width: sz - 2*c, height: sz - 2*c)
context.addEllipse(in: r3)
context.addRect(r3)
UIColor.clear.setFill()
UIColor.gray.setStroke()
let rounded = UIBezierPath(roundedRect: rect.insetBy(dx: lineWidth/2, dy: lineWidth/2), cornerRadius: corner)
rounded.lineWidth = lineWidth
rounded.stroke()
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
extension CGContext {
func lineFromTo(x1: CGFloat, y1: CGFloat, x2: CGFloat, y2: CGFloat) {
self.move(to: CGPoint(x: x1, y: y1))
self.addLine(to: CGPoint(x: x2, y: y2))
}
}

45
main/Info.plist Normal file
View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>7</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

BIN
main/LaunchIcon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

23
main/ProxyState.swift Normal file
View File

@@ -0,0 +1,23 @@
import UIKit
enum ProxyState {
case stopped, unkown, running
}
@IBDesignable
class DotState: UIImage {
var status: ProxyState = .stopped // { didSet { }}
override func draw(in rect: CGRect) {
let pt = CGPoint(x: rect.midX, y: rect.midY)
let r = min(rect.size.width, rect.size.height) / 2.0 * 0.6
switch status {
case .stopped: #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1).setFill()
case .unkown: #colorLiteral(red: 0.9529411793, green: 0.6862745285, blue: 0.1333333403, alpha: 1).setFill()
case .running: #colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1).setFill()
}
UIBezierPath(arcCenter: pt, radius: r, startAngle: 0, endAngle: 10, clockwise: true).fill()
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Kill proxy on startup</string>
<key>Key</key>
<string>kill_proxy</string>
<key>DefaultValue</key>
<false/>
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<key>Title</key>
<string>Delete DB on startup</string>
<key>Key</key>
<string>kill_db</string>
<key>DefaultValue</key>
<false/>
</dict>
</array>
</dict>
</plist>

Binary file not shown.

139
main/TVCApps.swift Normal file
View File

@@ -0,0 +1,139 @@
import UIKit
class TVCApps: UITableViewController {
private let appDelegate = UIApplication.shared.delegate as! AppDelegate
private var dataSource: [AppInfoType] = []
@IBOutlet private var welcomeMessage: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
self.welcomeMessage.frame.size.height = 0
AppInfoType.initWorkingDir()
NotificationCenter.default.addObserver(forName: .init("ChangedStateGlassDNS"), object: nil, queue: OperationQueue.main) { [weak self] notification in
// let stateView = self.navigationItem.rightBarButtonItem?.customView as? ProxyStateView
// stateView?.status = (notification.object as! Bool ? .running : .stopped)
// let active = notification.object as! Bool
self?.changeState(notification.object as! Bool)
}
// pull-to-refresh
// tableView.refreshControl = UIRefreshControl()
// tableView.refreshControl?.addTarget(self, action: #selector(reloadDataSource(_:)), for: .valueChanged)
// performSelector(inBackground: #selector(reloadDataSource(_:)), with: nil)
NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: OperationQueue.main) { [weak self] _ in
self?.reloadDataSource(nil)
}
// navigationItem.leftBarButtonItem?.title = "\u{2699}\u{0000FE0E}"
// navigationItem.leftBarButtonItem?.setTitleTextAttributes([NSAttributedString.Key.font : UIFont.systemFont(ofSize: 32)], for: .normal)
}
@IBAction func clickToolbarLeft(_ sender: Any) {
let alert = UIAlertController(title: "Clear results?",
message: "You are about to delete all results that have been logged in the past. Continue?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
alert.addAction(UIAlertAction(title: "Delete", style: .destructive, handler: { [weak self] _ in
try? SQLiteDatabase.open(path: DB_PATH).destroyContent()
self?.reloadDataSource(nil)
}))
self.present(alert, animated: true, completion: nil)
}
@IBAction func clickToolbarRight(_ sender: Any) {
let inactive = (self.navigationItem.rightBarButtonItem?.tag == 0)
let alert = UIAlertController(title: "\(inactive ? "En" : "Dis")able Proxy?",
message: "The DNS proxy is currently \(inactive ? "dis" : "en")abled, do you want to proceed and \(inactive ? "en" : "dis")able logging?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
alert.addAction(UIAlertAction(title: inactive ? "Enable" : "Disable", style: .default, handler: { [weak self] _ in
self?.changeState(inactive)
self?.appDelegate.setProxyEnabled(inactive)
}))
self.present(alert, animated: true, completion: nil)
}
func changeState(_ active: Bool) {
let stateView = self.navigationItem.rightBarButtonItem
if stateView?.tag == 0 && !active,
stateView?.tag == 1 && active {
return // don't need to change, already correct state
}
stateView?.tag = (active ? 1 : 0)
stateView?.title = (active ? "Active" : "Inactive")
stateView?.tintColor = (active ? .systemGreen : .systemRed)
// let newButton = UIBarButtonItem(barButtonSystemItem: (active ? .pause : .play), target: self, action: #selector(clickToolbarRight(_:)))
// newButton.tintColor = (active ? .systemRed : .systemGreen)
// newButton.tag = (active ? 1 : 0)
// self.navigationItem.setRightBarButton(newButton, animated: true)
}
private func updateCellAt(_ index: Int) {
DispatchQueue.main.async {
guard index >= 0 else {
self.welcomeMessage.frame.size.height = (self.dataSource.count == 0 ? self.view.frame.size.height : 0)
self.tableView.reloadData()
return
}
if let idx = self.tableView.indexPathsForVisibleRows?.first(where: { indexPath -> Bool in
indexPath.row == index
}) {
self.tableView.reloadRows(at: [idx], with: .automatic)
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let index = tableView.indexPathForSelectedRow?.row {
let info = dataSource[index]
segue.destination.navigationItem.prompt = info.name ?? info.id
(segue.destination as? TVCRequests)?.appBundleId = info.id
}
}
// MARK: - Table View Delegate
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "AppBundleCell")!
let appBundle = dataSource[indexPath.row]
cell.textLabel?.text = appBundle.name ?? appBundle.id
cell.detailTextLabel?.text = appBundle.seller
cell.imageView?.image = appBundle.getImage()
cell.imageView?.layer.cornerRadius = 6.75
cell.imageView?.layer.masksToBounds = true
return cell
}
// MARK: - Data Source
@objc private func reloadDataSource(_ sender : Any?) {
DispatchQueue.global().async {
self.dataSource = self.sqliteAppList().map { AppInfoType(id: $0) } // will load from HD
self.updateCellAt(-1)
for i in self.dataSource.indices {
self.dataSource[i].updateIfNeeded { [weak self] in
self?.updateCellAt(i)
}
}
if let refreshControl = sender as? UIRefreshControl {
refreshControl.endRefreshing()
}
}
}
private func sqliteAppList() -> [String] {
// return ["unkown", "com.apple.Fitness", "com.apple.AppStore", "com.apple.store.Jolly", "com.apple.supportapp", "com.apple.TVRemote", "com.apple.Bridge", "com.apple.calculator", "com.apple.mobilecal", "com.apple.camera", "com.apple.classroom", "com.apple.clips", "com.apple.mobiletimer", "com.apple.compass", "com.apple.MobileAddressBook", "com.apple.facetime", "com.apple.appleseed.FeedbackAssistant", "com.apple.mobileme.fmf1", "com.apple.mobileme.fmip1", "com.apple.findmy", "com.apple.DocumentsApp", "com.apple.gamecenter", "com.apple.mobilegarageband", "com.apple.Health", "com.apple.Antimony", "com.apple.Home", "com.apple.iBooks", "com.apple.iCloudDriveApp", "com.apple.iMovie", "com.apple.itunesconnect.mobile", "com.apple.MobileStore", "com.apple.itunesu", "com.apple.Keynote", "com.apple.musicapps.remote", "com.apple.mobilemail", "com.apple.Maps", "com.apple.measure", "com.apple.MobileSMS", "com.apple.Music", "com.apple.musicmemos", "com.apple.news", "com.apple.mobilenotes", "com.apple.Numbers", "com.apple.Pages", "com.apple.mobilephone", "com.apple.Photo-Booth", "com.apple.mobileslideshow", "com.apple.Playgrounds", "com.apple.podcasts", "com.apple.reminders", "com.apple.Remote", "com.apple.mobilesafari", "com.apple.Preferences", "is.workflow.my.app", "com.apple.shortcuts", "com.apple.SiriViewService", "com.apple.stocks", "com.apple.tips", "com.apple.movietrailers", "com.apple.tv", "com.apple.videos", "com.apple.VoiceMemos", "com.apple.Passbook", "com.apple.weather", "com.apple.wwdc"]
// return ["com.apple.backupd", "com.apple.searchd", "com.apple.SafariBookmarksSyncAgent", "com.apple.AppStore", "com.apple.mobilemail", "com.apple.iBooks", "com.apple.icloud.searchpartyd", "com.apple.ap.adprivacyd", "com.apple.bluetoothd", "com.apple.commcentermobilehelper", "com.apple", "com.apple.coreidv.coreidvd", "com.apple.online-auth-agent", "com.apple.tipsd", "com.apple.wifid", "com.apple.captiveagent", "com.apple.pipelined", "com.apple.bird", "com.apple.amfid", "com.apple.nsurlsessiond", "com.apple.Preferences", "com.apple.sharingd", "com.apple.UserEventAgent", "com.apple.healthappd"]
guard let db = try? SQLiteDatabase.open(path: DB_PATH) else {
return []
}
return db.appList()
}
}

View File

@@ -0,0 +1,24 @@
import UIKit
class TVCRequestDetails: UITableViewController {
public var dataSource: [Int64] = []
private let dateFormatter = DateFormatter()
override func viewDidLoad() {
super.viewDidLoad()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RequestDetailCell")!
let intVal = dataSource[indexPath.row]
let date = Date.init(timeIntervalSince1970: Double(intVal))
cell.textLabel?.text = dateFormatter.string(from: date)
return cell
}
}

64
main/TVCRequests.swift Normal file
View File

@@ -0,0 +1,64 @@
import UIKit
class TVCRequests: UITableViewController {
public var appBundleId: String? = nil
private var dataSource: [(String, [Int64])] = []
override func viewDidLoad() {
super.viewDidLoad()
// pull-to-refresh
tableView.refreshControl = UIRefreshControl()
tableView.refreshControl?.addTarget(self, action: #selector(reloadDataSource(_:)), for: .valueChanged)
performSelector(inBackground: #selector(reloadDataSource(_:)), with: nil)
NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: OperationQueue.main) { [weak self] _ in
self?.reloadDataSource(nil)
}
}
@objc private func reloadDataSource(_ sender : Any?) {
// dataSource = [("hi", [1, 2]), ("there", [2, 4, 8, 1580472632]), ("dude", [1, 2, 3])]
// return ()
dataSource = []
guard let bundleId = appBundleId, let db = try? SQLiteDatabase.open(path: DB_PATH) else {
return
}
var list: [String: [Int64]] = [:]
db.dnsQueriesForApp(appIdentifier: bundleId as NSString) { query in
let x = query.dns.split(separator: ".").reversed().joined(separator: ".")
if list[x] == nil {
list[x] = []
}
list[x]?.append(query.ts)
}
dataSource = list.sorted{ $0.0 < $1.0 }
DispatchQueue.main.async {
self.tableView.reloadData()
if let refreshControl = sender as? UIRefreshControl {
refreshControl.endRefreshing()
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let index = tableView.indexPathForSelectedRow?.row {
let info = dataSource[index]
segue.destination.navigationItem.prompt = info.0
(segue.destination as? TVCRequestDetails)?.dataSource = info.1
}
}
// MARK: - Data Source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RequestCell")!
let info = dataSource[indexPath.row]
cell.textLabel?.text = info.0
cell.detailTextLabel?.text = "\(info.1.count)"
return cell
}
}

18
main/main.entitlements Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>dns-proxy</string>
</array>
<key>com.apple.developer.networking.vpn.api</key>
<array>
<string>allow-vpn</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.de.uni-bamberg.psi.AppCheck</string>
</array>
</dict>
</plist>