diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-03-09 13:19:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-03-09 13:19:22 +0000 |
commit | c21c3b0befeb46a51b6bf3758ffa30813bea0ff0 (patch) | |
tree | 9754ff1ca740f6346cf8483ec915d4054bc5da2d /web/server/h2o/libh2o/deps/ssl-conservatory | |
parent | Adding upstream version 1.43.2. (diff) | |
download | netdata-c21c3b0befeb46a51b6bf3758ffa30813bea0ff0.tar.xz netdata-c21c3b0befeb46a51b6bf3758ffa30813bea0ff0.zip |
Adding upstream version 1.44.3.upstream/1.44.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
30 files changed, 1828 insertions, 0 deletions
diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/.gitattributes b/web/server/h2o/libh2o/deps/ssl-conservatory/.gitattributes new file mode 100644 index 000000000..7d61439d0 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/.gitattributes @@ -0,0 +1,5 @@ +# These files are text and should be normalized (convert crlf => lf)
+*.c text
+*.h text
+*.txt text
+*.md text
diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/.gitignore b/web/server/h2o/libh2o/deps/ssl-conservatory/.gitignore new file mode 100644 index 000000000..3b15853bd --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/.gitignore @@ -0,0 +1,34 @@ +# Compiled Object files +*.slo +*.lo +*.o + +# Compiled Dynamic libraries +*.so + +# Compiled Static libraries +*.lai +*.la +*.a + +# Windows binaries +*.exe + +# Xcode +.DS_Store +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +*.xcworkspace +!default.xcworkspace +xcuserdata +profile +*.moved-aside +DerivedData +.idea/ diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/LICENSE b/web/server/h2o/libh2o/deps/ssl-conservatory/LICENSE new file mode 100644 index 000000000..fe3a4167b --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2012, iSEC Partners. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/README.md b/web/server/h2o/libh2o/deps/ssl-conservatory/README.md new file mode 100644 index 000000000..8000ec473 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/README.md @@ -0,0 +1,28 @@ +The SSL Conservatory +==================== + +Correct implementation of SSL is crucial to secure transmission of data +between clients and servers. However, this crucial task is frequently done +improperly, due to complex APIs and lack of understanding of SSL fundamentals. + +This is intended to be a clearinghouse for well-documented and secure sample +code to correctly implement SSL clients. Pull requests with examples for +other languages or frameworks are encouraged. + + +Content +------- + +### openssl/ + +Whitepaper and sample code on how to perform certificate validation within an +SSL client using the OpenSSL library. + +### ios/ +SSL certificate pinning implementation for iOS applications. + + +License +------- + +See LICENSE.
\ No newline at end of file diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/README.md b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/README.md new file mode 100644 index 000000000..34bf4eda8 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/README.md @@ -0,0 +1,89 @@ +The SSL Conservatory: iOS Certificate Pinning +============================================= + + +When an iOS application only needs to communicate to a well-defined set of +servers over SSL or HTTPS, the security of the app's network communications can +be improved through SSL pinning. By requiring a specific certificate to be part +of the server's certificate chain, the threat of a rogue CA or a CA compromise +is significantly reduced. + + +### The ISPCertificatePinning class + +#### Description + +This class allows developers to whitelist a list of certificates for a given +domain in order to require at least one these "pinned" certificates to be part +of the server's certificate chain received when connecting to the domain over +SSL or HTTPS. + +This gives developers the flexibility to pin the CA/anchor certificate, the +server/leaf certificate, or any intermediate certificate for a given domain. +Each option has different advantages and limitations; for example, pinning the +server/leaf certificate provides the best security but this certificate is going +to change more often than the CA/anchor certificate. + +A change in the certificate presented by the server (for example because the +previous certificate expired) will result in the application being unable to +connect to the server until its pinned certificate has been updated as well. +To address this scenario, multiple certificates can be pinned to a single +domain. This gives developers the ability to transition from an expiring +certificate to a new one by releasing a new version of their application that +pins both certificates to the server's domain. + + +#### API + +The ISPCertificatePinning class exposes two methods: + +##### +(BOOL)setupSSLPinsUsingDictionnary:(NSDictionary*)domainsAndCertificates +This method takes a dictionary with domain names as keys and arrays of +DER-encoded certificates as values, and stores them in a pre-defined location on +the filesystem. The ability to specify multiple certificates for a single +domain is useful when transitioning from an expiring certificate to a new one + +##### +(BOOL)verifyPinnedCertificateForTrust:(SecTrustRef)trust andDomain:(NSString*)domain +This method accesses the certificates previously loaded using the +setupSSLPinsUsingDictionnary: method and inspects the trust object's +certificate chain in order to find at least one certificate pinned to the +given domain. SecTrustEvaluate() should always be called before this method to +ensure that the certificate chain is valid. + + +### Convenience delegate classes for NSURLConnection and NSURLSession + +This library also provides convenience classes for connections relying on +NSURLConnection and NSURLSession. The ISPPinnedNSURLConnectionDelegate and +ISPPinnedNSURLSessionDelegate implement the connection authentication methods +within respectively the NSURLConnectionDelegate and NSURLSessionDelegate +protocols, in order to automatically validate the server's certificate based on +SSL pins loaded using the setupSSLPinsUsingDictionnary: method. + +To implement certificate pinning in their Apps, developers should simply extend +these classes when creating their own connection delegates. + + +### Sample code + +The Xcode unit tests within SSLCertificatePinningTests contain sample code +demonstrating how to implement certificate pinning when using NSURLConnection +and NSURLSession. + + +### Changelog + +* v3: Turned the Xcode project into a static library. + Added certificate pinning delegate class for NSURLSession connections. +* v2: Added the ability to pin multiple certificates to a single domain. +* v1: Initial release. + + +### License + +See ../LICENSE. + + +### Author + +Alban Diquet - https://github.com/nabla-c0d3 diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning.xcodeproj/project.pbxproj b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning.xcodeproj/project.pbxproj new file mode 100644 index 000000000..84ee1521b --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning.xcodeproj/project.pbxproj @@ -0,0 +1,456 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 8C40DA3C188600A600A231CD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C40DA3B188600A600A231CD /* Foundation.framework */; }; + 8C40DA41188600A600A231CD /* ISPCertificatePinning.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8C40DA40188600A600A231CD /* ISPCertificatePinning.h */; }; + 8C40DA43188600A600A231CD /* ISPCertificatePinning.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C40DA42188600A600A231CD /* ISPCertificatePinning.m */; }; + 8C40DA4A188600A600A231CD /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C40DA49188600A600A231CD /* XCTest.framework */; }; + 8C40DA4B188600A600A231CD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C40DA3B188600A600A231CD /* Foundation.framework */; }; + 8C40DA4D188600A600A231CD /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C40DA4C188600A600A231CD /* UIKit.framework */; }; + 8C40DA50188600A600A231CD /* libSSLCertificatePinning.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C40DA38188600A600A231CD /* libSSLCertificatePinning.a */; }; + 8C40DA56188600A600A231CD /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8C40DA54188600A600A231CD /* InfoPlist.strings */; }; + 8C40DA631886017400A231CD /* ISPPinnedNSURLConnectionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C40DA621886017400A231CD /* ISPPinnedNSURLConnectionDelegate.m */; }; + 8C40DA661886045C00A231CD /* ISPPinnedNSURLSessionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C40DA651886045C00A231CD /* ISPPinnedNSURLSessionDelegate.m */; }; + 8C40DA681886071000A231CD /* NSURLConnectionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C40DA671886071000A231CD /* NSURLConnectionTests.m */; }; + 8C40DA6A1886071C00A231CD /* NSURLSessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C40DA691886071C00A231CD /* NSURLSessionTests.m */; }; + 8C40DA6D1886080800A231CD /* VeriSignClass3PublicPrimaryCertificationAuthority-G5.der in Resources */ = {isa = PBXBuildFile; fileRef = 8C40DA6C1886080800A231CD /* VeriSignClass3PublicPrimaryCertificationAuthority-G5.der */; }; + 8C40DA6F1886142800A231CD /* www.isecpartners.com.der in Resources */ = {isa = PBXBuildFile; fileRef = 8C40DA6E1886142800A231CD /* www.isecpartners.com.der */; }; + 8CC9C1F9189EF097000525D6 /* SSLPinsTestUtility.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CC9C1F8189EF097000525D6 /* SSLPinsTestUtility.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 8C40DA4E188600A600A231CD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8C40DA30188600A600A231CD /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8C40DA37188600A600A231CD; + remoteInfo = SSLCertificatePinning; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8C40DA36188600A600A231CD /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + 8C40DA41188600A600A231CD /* ISPCertificatePinning.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 8C40DA38188600A600A231CD /* libSSLCertificatePinning.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSSLCertificatePinning.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 8C40DA3B188600A600A231CD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 8C40DA3F188600A600A231CD /* SSLCertificatePinning-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SSLCertificatePinning-Prefix.pch"; sourceTree = "<group>"; }; + 8C40DA40188600A600A231CD /* ISPCertificatePinning.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ISPCertificatePinning.h; sourceTree = "<group>"; }; + 8C40DA42188600A600A231CD /* ISPCertificatePinning.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ISPCertificatePinning.m; sourceTree = "<group>"; }; + 8C40DA48188600A600A231CD /* SSLCertificatePinningTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SSLCertificatePinningTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 8C40DA49188600A600A231CD /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 8C40DA4C188600A600A231CD /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 8C40DA53188600A600A231CD /* SSLCertificatePinningTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "SSLCertificatePinningTests-Info.plist"; sourceTree = "<group>"; }; + 8C40DA55188600A600A231CD /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + 8C40DA611886017400A231CD /* ISPPinnedNSURLConnectionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISPPinnedNSURLConnectionDelegate.h; sourceTree = "<group>"; }; + 8C40DA621886017400A231CD /* ISPPinnedNSURLConnectionDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ISPPinnedNSURLConnectionDelegate.m; sourceTree = "<group>"; }; + 8C40DA641886045C00A231CD /* ISPPinnedNSURLSessionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ISPPinnedNSURLSessionDelegate.h; sourceTree = "<group>"; }; + 8C40DA651886045C00A231CD /* ISPPinnedNSURLSessionDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ISPPinnedNSURLSessionDelegate.m; sourceTree = "<group>"; }; + 8C40DA671886071000A231CD /* NSURLConnectionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSURLConnectionTests.m; sourceTree = "<group>"; }; + 8C40DA691886071C00A231CD /* NSURLSessionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSURLSessionTests.m; sourceTree = "<group>"; }; + 8C40DA6C1886080800A231CD /* VeriSignClass3PublicPrimaryCertificationAuthority-G5.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = "VeriSignClass3PublicPrimaryCertificationAuthority-G5.der"; sourceTree = "<group>"; }; + 8C40DA6E1886142800A231CD /* www.isecpartners.com.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = www.isecpartners.com.der; sourceTree = "<group>"; }; + 8CC9C1F7189EF097000525D6 /* SSLPinsTestUtility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSLPinsTestUtility.h; sourceTree = "<group>"; }; + 8CC9C1F8189EF097000525D6 /* SSLPinsTestUtility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSLPinsTestUtility.m; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8C40DA35188600A600A231CD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C40DA3C188600A600A231CD /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8C40DA45188600A600A231CD /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C40DA50188600A600A231CD /* libSSLCertificatePinning.a in Frameworks */, + 8C40DA4A188600A600A231CD /* XCTest.framework in Frameworks */, + 8C40DA4D188600A600A231CD /* UIKit.framework in Frameworks */, + 8C40DA4B188600A600A231CD /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8C40DA2F188600A600A231CD = { + isa = PBXGroup; + children = ( + 8C40DA3D188600A600A231CD /* SSLCertificatePinning */, + 8C40DA51188600A600A231CD /* SSLCertificatePinningTests */, + 8C40DA3A188600A600A231CD /* Frameworks */, + 8C40DA39188600A600A231CD /* Products */, + ); + sourceTree = "<group>"; + }; + 8C40DA39188600A600A231CD /* Products */ = { + isa = PBXGroup; + children = ( + 8C40DA38188600A600A231CD /* libSSLCertificatePinning.a */, + 8C40DA48188600A600A231CD /* SSLCertificatePinningTests.xctest */, + ); + name = Products; + sourceTree = "<group>"; + }; + 8C40DA3A188600A600A231CD /* Frameworks */ = { + isa = PBXGroup; + children = ( + 8C40DA3B188600A600A231CD /* Foundation.framework */, + 8C40DA49188600A600A231CD /* XCTest.framework */, + 8C40DA4C188600A600A231CD /* UIKit.framework */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + 8C40DA3D188600A600A231CD /* SSLCertificatePinning */ = { + isa = PBXGroup; + children = ( + 8C40DA40188600A600A231CD /* ISPCertificatePinning.h */, + 8C40DA42188600A600A231CD /* ISPCertificatePinning.m */, + 8C40DA3E188600A600A231CD /* Supporting Files */, + 8C40DA611886017400A231CD /* ISPPinnedNSURLConnectionDelegate.h */, + 8C40DA641886045C00A231CD /* ISPPinnedNSURLSessionDelegate.h */, + 8C40DA651886045C00A231CD /* ISPPinnedNSURLSessionDelegate.m */, + 8C40DA621886017400A231CD /* ISPPinnedNSURLConnectionDelegate.m */, + ); + path = SSLCertificatePinning; + sourceTree = "<group>"; + }; + 8C40DA3E188600A600A231CD /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 8C40DA3F188600A600A231CD /* SSLCertificatePinning-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = "<group>"; + }; + 8C40DA51188600A600A231CD /* SSLCertificatePinningTests */ = { + isa = PBXGroup; + children = ( + 8C40DA6E1886142800A231CD /* www.isecpartners.com.der */, + 8C40DA6C1886080800A231CD /* VeriSignClass3PublicPrimaryCertificationAuthority-G5.der */, + 8C40DA671886071000A231CD /* NSURLConnectionTests.m */, + 8C40DA691886071C00A231CD /* NSURLSessionTests.m */, + 8CC9C1F7189EF097000525D6 /* SSLPinsTestUtility.h */, + 8CC9C1F8189EF097000525D6 /* SSLPinsTestUtility.m */, + 8C40DA52188600A600A231CD /* Supporting Files */, + ); + path = SSLCertificatePinningTests; + sourceTree = "<group>"; + }; + 8C40DA52188600A600A231CD /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 8C40DA53188600A600A231CD /* SSLCertificatePinningTests-Info.plist */, + 8C40DA54188600A600A231CD /* InfoPlist.strings */, + ); + name = "Supporting Files"; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8C40DA37188600A600A231CD /* SSLCertificatePinning */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8C40DA5B188600A600A231CD /* Build configuration list for PBXNativeTarget "SSLCertificatePinning" */; + buildPhases = ( + 8C40DA34188600A600A231CD /* Sources */, + 8C40DA35188600A600A231CD /* Frameworks */, + 8C40DA36188600A600A231CD /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SSLCertificatePinning; + productName = SSLCertificatePinning; + productReference = 8C40DA38188600A600A231CD /* libSSLCertificatePinning.a */; + productType = "com.apple.product-type.library.static"; + }; + 8C40DA47188600A600A231CD /* SSLCertificatePinningTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8C40DA5E188600A600A231CD /* Build configuration list for PBXNativeTarget "SSLCertificatePinningTests" */; + buildPhases = ( + 8C40DA44188600A600A231CD /* Sources */, + 8C40DA45188600A600A231CD /* Frameworks */, + 8C40DA46188600A600A231CD /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 8C40DA4F188600A600A231CD /* PBXTargetDependency */, + ); + name = SSLCertificatePinningTests; + productName = SSLCertificatePinningTests; + productReference = 8C40DA48188600A600A231CD /* SSLCertificatePinningTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8C40DA30188600A600A231CD /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "iSEC Partners"; + }; + buildConfigurationList = 8C40DA33188600A600A231CD /* Build configuration list for PBXProject "SSLCertificatePinning" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 8C40DA2F188600A600A231CD; + productRefGroup = 8C40DA39188600A600A231CD /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8C40DA37188600A600A231CD /* SSLCertificatePinning */, + 8C40DA47188600A600A231CD /* SSLCertificatePinningTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 8C40DA46188600A600A231CD /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C40DA6D1886080800A231CD /* VeriSignClass3PublicPrimaryCertificationAuthority-G5.der in Resources */, + 8C40DA6F1886142800A231CD /* www.isecpartners.com.der in Resources */, + 8C40DA56188600A600A231CD /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8C40DA34188600A600A231CD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C40DA43188600A600A231CD /* ISPCertificatePinning.m in Sources */, + 8C40DA631886017400A231CD /* ISPPinnedNSURLConnectionDelegate.m in Sources */, + 8C40DA661886045C00A231CD /* ISPPinnedNSURLSessionDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8C40DA44188600A600A231CD /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8C40DA681886071000A231CD /* NSURLConnectionTests.m in Sources */, + 8C40DA6A1886071C00A231CD /* NSURLSessionTests.m in Sources */, + 8CC9C1F9189EF097000525D6 /* SSLPinsTestUtility.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 8C40DA4F188600A600A231CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8C40DA37188600A600A231CD /* SSLCertificatePinning */; + targetProxy = 8C40DA4E188600A600A231CD /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 8C40DA54188600A600A231CD /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 8C40DA55188600A600A231CD /* en */, + ); + name = InfoPlist.strings; + sourceTree = "<group>"; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 8C40DA59188600A600A231CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + 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; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 8C40DA5A188600A600A231CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + 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; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 8C40DA5C188600A600A231CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/SSLCertificatePinning.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "SSLCertificatePinning/SSLCertificatePinning-Prefix.pch"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 8C40DA5D188600A600A231CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DSTROOT = /tmp/SSLCertificatePinning.dst; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "SSLCertificatePinning/SSLCertificatePinning-Prefix.pch"; + OTHER_LDFLAGS = "-ObjC"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 8C40DA5F188600A600A231CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "SSLCertificatePinning/SSLCertificatePinning-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "SSLCertificatePinningTests/SSLCertificatePinningTests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = xctest; + }; + name = Debug; + }; + 8C40DA60188600A600A231CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "SSLCertificatePinning/SSLCertificatePinning-Prefix.pch"; + INFOPLIST_FILE = "SSLCertificatePinningTests/SSLCertificatePinningTests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = xctest; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8C40DA33188600A600A231CD /* Build configuration list for PBXProject "SSLCertificatePinning" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8C40DA59188600A600A231CD /* Debug */, + 8C40DA5A188600A600A231CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8C40DA5B188600A600A231CD /* Build configuration list for PBXNativeTarget "SSLCertificatePinning" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8C40DA5C188600A600A231CD /* Debug */, + 8C40DA5D188600A600A231CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8C40DA5E188600A600A231CD /* Build configuration list for PBXNativeTarget "SSLCertificatePinningTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8C40DA5F188600A600A231CD /* Debug */, + 8C40DA60188600A600A231CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8C40DA30188600A600A231CD /* Project object */; +} diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPCertificatePinning.h b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPCertificatePinning.h new file mode 100644 index 000000000..fddc504e2 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPCertificatePinning.h @@ -0,0 +1,62 @@ +// +// ISPCertificatePinning.h +// SSLCertificatePinning v3 +// +// Created by Alban Diquet on 1/14/14. +// Copyright (c) 2014 iSEC Partners. All rights reserved. +// + + +/** This class implements certificate pinning utility functions. + + First, the certificates and domains to pin should be loaded using + setupSSLPinsUsingDictionnary:. This method will store them in + "~/Library/SSLPins.plist". + + Then, the verifyPinnedCertificateForTrust:andDomain: method can be + used to validate that at least one the certificates pinned to a + specific domain is in the server's certificate chain when connecting to + it. This method should be used for example in the + connection:willSendRequestForAuthenticationChallenge: method of the + NSURLConnectionDelegate object that is used to perform the connection. + + Alternatively, the ISPPinnedNSURLSessionDelegate or + ISPPinnedNSURLConnectionDelegate classes can be directly used + to create a delegate class performing certificate pinning. + + */ +@interface ISPCertificatePinning : NSObject + + +/** + Certificate pinning loading method + + This method takes a dictionary with domain names as keys and arrays of DER- + encoded certificates as values, and stores them in a pre-defined location on + the filesystem. The ability to specify multiple certificates for a single + domain is useful when transitioning from an expiring certificate to a new one. + + @param certificates a dictionnary with domain names as keys and arrays of DER-encoded certificates as values + @return BOOL successfully loaded the public keys and domains + + */ ++ (BOOL)setupSSLPinsUsingDictionnary:(NSDictionary*)domainsAndCertificates; + + +/** + Certificate pinning validation method + + This method accesses the certificates previously loaded using the + setupSSLPinsUsingDictionnary: method and inspects the trust object's + certificate chain in order to find at least one certificate pinned to the + given domain. SecTrustEvaluate() should always be called before this method to + ensure that the certificate chain is valid. + + @param trust the trust object whose certificate chain must contain the certificate previously pinned to the given domain + @param domain the domain we're trying to connect to + @return BOOL found the domain's pinned certificate in the trust object's certificate chain + + */ ++ (BOOL)verifyPinnedCertificateForTrust:(SecTrustRef)trust andDomain:(NSString*)domain; + +@end diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPCertificatePinning.m b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPCertificatePinning.m new file mode 100644 index 000000000..584b974ff --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPCertificatePinning.m @@ -0,0 +1,112 @@ +// +// ISPCertificatePinning.m +// SSLCertificatePinning +// +// Created by Alban Diquet on 1/14/14. +// Copyright (c) 2014 iSEC Partners. All rights reserved. +// + +#import "ISPCertificatePinning.h" + + +// All the pinned certificate are stored in this plist on the filesystem +#define PINNED_KEYS_FILE_PATH "~/Library/SSLPins.plist" + + +@implementation ISPCertificatePinning + + + ++ (BOOL)setupSSLPinsUsingDictionnary:(NSDictionary*)domainsAndCertificates { + if (domainsAndCertificates == nil) { + return NO; + } + + // Serialize the dictionary to a plist + NSError *error; + NSData *plistData = [NSPropertyListSerialization dataWithPropertyList:domainsAndCertificates + format:NSPropertyListXMLFormat_v1_0 + options:0 + error:&error]; + if (plistData == nil) { + NSLog(@"Error serializing plist: %@", error); + return NO; + } + + // Write the plist to a pre-defined location on the filesystem + NSError *writeError; + if ([plistData writeToFile:[@PINNED_KEYS_FILE_PATH stringByExpandingTildeInPath] + options:NSDataWritingAtomic + error:&writeError] == NO) { + NSLog(@"Error saving plist to the filesystem: %@", writeError); + return NO; + } + + return YES; +} + + ++ (BOOL)verifyPinnedCertificateForTrust:(SecTrustRef)trust andDomain:(NSString*)domain { + if ((trust == NULL) || (domain == nil)) { + return NO; + } + + // Deserialize the plist that contains our SSL pins + NSDictionary *SSLPinsDict = [NSDictionary dictionaryWithContentsOfFile:[@PINNED_KEYS_FILE_PATH stringByExpandingTildeInPath]]; + if (SSLPinsDict == nil) { + NSLog(@"Error accessing the SSL Pins plist at %@", @PINNED_KEYS_FILE_PATH); + return NO; + } + + // Do we have certificates pinned for this domain ? + NSArray *trustedCertificates = [SSLPinsDict objectForKey:domain]; + if ((trustedCertificates == nil) || ([trustedCertificates count] < 1)) { + return NO; + } + + // For each pinned certificate, check if it is part of the server's cert trust chain + // We only need one of the pinned certificates to be in the server's trust chain + for (NSData *pinnedCertificate in trustedCertificates) { + + // Check each certificate in the server's trust chain (the trust object) + // Unfortunately the anchor/CA certificate cannot be accessed this way + CFIndex certsNb = SecTrustGetCertificateCount(trust); + for(int i=0;i<certsNb;i++) { + + // Extract the certificate + SecCertificateRef certificate = SecTrustGetCertificateAtIndex(trust, i); + NSData* DERCertificate = (__bridge NSData*) SecCertificateCopyData(certificate); + + // Compare the two certificates + if ([pinnedCertificate isEqualToData:DERCertificate]) { + return YES; + } + } + + // Check the anchor/CA certificate separately + SecCertificateRef anchorCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)(pinnedCertificate)); + if (anchorCertificate == NULL) { + break; + } + + NSArray *anchorArray = [NSArray arrayWithObject:(__bridge id)(anchorCertificate)]; + if (SecTrustSetAnchorCertificates(trust, (__bridge CFArrayRef)(anchorArray)) != 0) { + CFRelease(anchorCertificate); + break; + } + + SecTrustResultType trustResult; + SecTrustEvaluate(trust, &trustResult); + if (trustResult == kSecTrustResultUnspecified) { + // The anchor certificate was pinned + CFRelease(anchorCertificate); + return YES; + } + CFRelease(anchorCertificate); + } + + // If we get here, we didn't find any matching certificate in the chain + return NO; +} + +@end diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPPinnedNSURLConnectionDelegate.h b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPPinnedNSURLConnectionDelegate.h new file mode 100644 index 000000000..13537455c --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPPinnedNSURLConnectionDelegate.h @@ -0,0 +1,23 @@ +// +// ISPPinnedNSURLConnectionDelegate.h +// SSLCertificatePinning +// +// Created by Alban Diquet on 1/14/14. +// Copyright (c) 2014 iSEC Partners. All rights reserved. +// + + +/** Convenience class to automatically perform certificate pinning for NSURLConnection. + + ISPPinnedNSURLConnectionDelegate is designed to be subclassed in order to + implement an NSURLConnectionDelegate class. The + connection:willSendRequestForAuthenticationChallenge: method it implements + will automatically validate that at least one the certificates pinned to the domain the + connection is accessing is part of the server's certificate chain. + + */ +@interface ISPPinnedNSURLConnectionDelegate : NSObject + +- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge; + +@end diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPPinnedNSURLConnectionDelegate.m b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPPinnedNSURLConnectionDelegate.m new file mode 100644 index 000000000..c67a8d0c6 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPPinnedNSURLConnectionDelegate.m @@ -0,0 +1,49 @@ +// +// ISPPinnedNSURLConnectionDelegate.m +// SSLCertificatePinning +// +// Created by Alban Diquet on 1/14/14. +// Copyright (c) 2014 iSEC Partners. All rights reserved. +// + +#import "ISPPinnedNSURLConnectionDelegate.h" +#import "ISPCertificatePinning.h" + + +@implementation ISPPinnedNSURLConnectionDelegate + + +- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { + + if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { + + SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust]; + NSString *domain = [[challenge protectionSpace] host]; + SecTrustResultType trustResult; + + // Validate the certificate chain with the device's trust store anyway + // This *might* give use revocation checking + SecTrustEvaluate(serverTrust, &trustResult); + if (trustResult == kSecTrustResultUnspecified) { + + // Look for a pinned certificate in the server's certificate chain + if ([ISPCertificatePinning verifyPinnedCertificateForTrust:serverTrust andDomain:domain]) { + + // Found the certificate; continue connecting + [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] + forAuthenticationChallenge:challenge]; + } + else { + // The certificate wasn't found in the certificate chain; cancel the connection + [[challenge sender] cancelAuthenticationChallenge: challenge]; + } + } + else { + // Certificate chain validation failed; cancel the connection + [[challenge sender] cancelAuthenticationChallenge: challenge]; + } + } +} + + +@end diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPPinnedNSURLSessionDelegate.h b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPPinnedNSURLSessionDelegate.h new file mode 100644 index 000000000..1fb3a292d --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPPinnedNSURLSessionDelegate.h @@ -0,0 +1,23 @@ +// +// ISPPinnedNSURLSessionDelegate.h +// SSLCertificatePinning +// +// Created by Alban Diquet on 1/14/14. +// Copyright (c) 2014 iSEC Partners. All rights reserved. +// + + +/** Convenience class to automatically perform certificate pinning for NSURLSession. + + ISPPinnedNSURLSessionDelegate is designed to be subclassed in order to + implement an NSURLSession class. The + URLSession:didReceiveChallenge:completionHandler: method it implements + will automatically validate that at least one the certificates pinned to the domain the + connection is accessing is part of the server's certificate chain. + + */ +@interface ISPPinnedNSURLSessionDelegate : NSObject + +- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler; + +@end diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPPinnedNSURLSessionDelegate.m b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPPinnedNSURLSessionDelegate.m new file mode 100644 index 000000000..601af6abd --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/ISPPinnedNSURLSessionDelegate.m @@ -0,0 +1,47 @@ +// +// ISPPinnedNSURLSessionDelegate.m +// SSLCertificatePinning +// +// Created by Alban Diquet on 1/14/14. +// Copyright (c) 2014 iSEC Partners. All rights reserved. +// +#import <Foundation/NSURLSession.h> + +#import "ISPPinnedNSURLSessionDelegate.h" +#import "ISPCertificatePinning.h" + + +@implementation ISPPinnedNSURLSessionDelegate + +- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { + + if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { + + SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust]; + NSString *domain = [[challenge protectionSpace] host]; + SecTrustResultType trustResult; + + // Validate the certificate chain with the device's trust store anyway + // This *might* give use revocation checking + SecTrustEvaluate(serverTrust, &trustResult); + if (trustResult == kSecTrustResultUnspecified) { + + // Look for a pinned certificate in the server's certificate chain + if ([ISPCertificatePinning verifyPinnedCertificateForTrust:serverTrust andDomain:domain]) { + + // Found the certificate; continue connecting + completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]); + } + else { + // The certificate wasn't found in the certificate chain; cancel the connection + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]); + } + } + else { + // Certificate chain validation failed; cancel the connection + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]); + } + } +} + +@end diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/SSLCertificatePinning-Prefix.pch b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/SSLCertificatePinning-Prefix.pch new file mode 100644 index 000000000..eb2007ecd --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinning/SSLCertificatePinning-Prefix.pch @@ -0,0 +1,9 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#ifdef __OBJC__ + #import <Foundation/Foundation.h> +#endif diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/NSURLConnectionTests.m b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/NSURLConnectionTests.m new file mode 100644 index 000000000..53d860785 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/NSURLConnectionTests.m @@ -0,0 +1,154 @@ +// +// NSURLConnectionTests.m +// SSLCertificatePinning +// +// Created by Alban Diquet on 1/14/14. +// Copyright (c) 2014 iSEC Partners. All rights reserved. +// + +#import <XCTest/XCTest.h> + +#import "ISPPinnedNSURLConnectionDelegate.h" +#import "ISPCertificatePinning.h" +#import "SSLPinsTestUtility.h" + + +// Delegate we'll use for our tests +@interface NSURLConnectionDelegateTest : ISPPinnedNSURLConnectionDelegate <NSURLConnectionDelegate> + @property BOOL connectionFinished; + @property BOOL connectionSucceeded; +@end + + + +@interface NSURLConnectionTests : XCTestCase + +@end + + +@implementation NSURLConnectionTests + + +- (void)setUp +{ + [super setUp]; +} + +- (void)tearDown +{ + [super tearDown]; +} + +#pragma mark SSL pinning test + + +// This is sample code to demonstrate how to implement certificate pinning with NSURLConnection +- (void)testNSURLConnectionSSLPinning +{ + + // Create our SSL pins dictionnary for Twitter, iSEC and NCC + NSDictionary *domainsToPin = [SSLPinsTestUtility setupTestSSLPinsDictionnary]; + if (domainsToPin == nil) { + NSLog(@"Failed to pin a certificate"); + } + + + // Save the SSL pins so that our connection delegates automatically use them + if ([ISPCertificatePinning setupSSLPinsUsingDictionnary:domainsToPin] != YES) { + NSLog(@"Failed to pin the certificates"); + } + + // Connect to Twitter + NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://twitter.com/"]]; + NSURLConnectionDelegateTest *connectionDelegate = [[NSURLConnectionDelegateTest alloc] init]; + NSURLConnection *connection=[[NSURLConnection alloc] initWithRequest:request delegate:connectionDelegate]; + [connection start]; + + // Connect to iSEC + NSURLRequest *request2 = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.isecpartners.com/"]]; + NSURLConnectionDelegateTest *connectionDelegate2 = [[NSURLConnectionDelegateTest alloc] init]; + NSURLConnection *connection2 = [[NSURLConnection alloc] initWithRequest:request2 delegate:connectionDelegate2]; + [connection2 start]; + + // Connect to NCC Group => will fail because we pinned a wrong certificate + NSURLRequest *request3 = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.nccgroup.com/"]]; + NSURLConnectionDelegateTest *connectionDelegate3 = [[NSURLConnectionDelegateTest alloc] init]; + NSURLConnection *connection3 = [[NSURLConnection alloc] initWithRequest:request3 delegate:connectionDelegate3]; + [connection3 start]; + + + // Do some polling to wait for the connections to complete +#define POLL_INTERVAL 0.2 // 200ms +#define N_SEC_TO_POLL 3.0 // poll for 3s +#define MAX_POLL_COUNT N_SEC_TO_POLL / POLL_INTERVAL + + NSUInteger pollCount = 0; + while (!(connectionDelegate.connectionFinished && connectionDelegate2.connectionFinished && connectionDelegate3.connectionFinished) && (pollCount < MAX_POLL_COUNT)) { + NSDate* untilDate = [NSDate dateWithTimeIntervalSinceNow:POLL_INTERVAL]; + [[NSRunLoop currentRunLoop] runUntilDate:untilDate]; + pollCount++; + } + + if (pollCount == MAX_POLL_COUNT) { + XCTFail(@"Could not connect in time"); + } + + + // The first two connections should succeed + XCTAssertTrue(connectionDelegate.connectionSucceeded, @"Connection to Twitter failed"); + XCTAssertTrue(connectionDelegate2.connectionSucceeded, @"Connection to iSEC Partners failed"); + + // The last connection should fail + XCTAssertFalse(connectionDelegate3.connectionSucceeded, @"Connection to NCC succeeded"); +} + + +@end + + +#pragma mark Delegate class + +@implementation NSURLConnectionDelegateTest + +@synthesize connectionSucceeded; +@synthesize connectionFinished; + +-(instancetype) init { + if (self = [super init]) + { + self.connectionSucceeded = NO; + self.connectionFinished = NO; + } + return self; +} + + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { + self.connectionSucceeded = YES; + self.connectionFinished = YES; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + self.connectionSucceeded = NO; + self.connectionFinished = YES; +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + self.connectionSucceeded = YES; + self.connectionFinished = YES; +} + +- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { + return cachedResponse; +} + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { + self.connectionSucceeded = YES; + self.connectionFinished = YES; +} + +- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse { + return request; +} + +@end
\ No newline at end of file diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/NSURLSessionTests.m b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/NSURLSessionTests.m new file mode 100644 index 000000000..5f1da51ba --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/NSURLSessionTests.m @@ -0,0 +1,145 @@ +// +// NSURLSessionTests.m +// SSLCertificatePinning +// +// Created by Alban Diquet on 1/14/14. +// Copyright (c) 2014 iSEC Partners. All rights reserved. +// + +#import <XCTest/XCTest.h> + +#import "ISPPinnedNSURLSessionDelegate.h" +#import "ISPCertificatePinning.h" +#import "SSLPinsTestUtility.h" + + +// Delegate we'll use for our tests +@interface NSURLSessionTaskDelegateTest : ISPPinnedNSURLSessionDelegate <NSURLSessionTaskDelegate, NSURLSessionDataDelegate> +@property BOOL connectionFinished; +@property BOOL connectionSucceeded; +@end + + +@interface NSURLSessionTests : XCTestCase + +@end + +@implementation NSURLSessionTests + +- (void)setUp +{ + [super setUp]; +} + +- (void)tearDown +{ + [super tearDown]; +} + + +#pragma mark SSL pinning test +- (void)testNSURLSessionSSLPinning +{ + + // Create our SSL pins dictionnary for Twitter, iSEC and NCC + NSDictionary *domainsToPin = [SSLPinsTestUtility setupTestSSLPinsDictionnary]; + if (domainsToPin == nil) { + NSLog(@"Failed to pin a certificate"); + } + + // Save the SSL pins so that our session delegates automatically use them + if ([ISPCertificatePinning setupSSLPinsUsingDictionnary:domainsToPin] != YES) { + NSLog(@"Failed to pin the certificates"); + } + + + // Connect to Twitter + NSURLSessionTaskDelegateTest *sessionDelegate1 = [[NSURLSessionTaskDelegateTest alloc] init]; + NSURLSession *session1 = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration] delegate:sessionDelegate1 delegateQueue:nil]; + + NSURLSessionDataTask *dataTask1 = [session1 dataTaskWithURL:[NSURL URLWithString:@"https://twitter.com/"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + + sessionDelegate1.connectionFinished = YES; + if (!error) { + sessionDelegate1.connectionSucceeded = YES; + } + }]; + [dataTask1 resume]; + + + // Connect to iSEC + NSURLSessionTaskDelegateTest *sessionDelegate2 = [[NSURLSessionTaskDelegateTest alloc] init]; + NSURLSession *session2 = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration] delegate:sessionDelegate2 delegateQueue:nil]; + + NSURLSessionDataTask *dataTask2 = [session2 dataTaskWithURL:[NSURL URLWithString:@"https://www.isecpartners.com/"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + + sessionDelegate2.connectionFinished = YES; + if (!error) { + sessionDelegate2.connectionSucceeded = YES; + } + }]; + [dataTask2 resume]; + + + // Connect to NCC Group => will fail because we pinned a wrong certificate + NSURLSessionTaskDelegateTest *sessionDelegate3 = [[NSURLSessionTaskDelegateTest alloc] init]; + NSURLSession *session3 = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration] delegate:sessionDelegate3 delegateQueue:nil]; + + NSURLSessionDataTask *dataTask3 = [session3 dataTaskWithURL:[NSURL URLWithString:@"https://www.nccgroup.com/"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + + sessionDelegate3.connectionFinished = YES; + if (!error) { + sessionDelegate3.connectionSucceeded = YES; + } + }]; + [dataTask3 resume]; + + + // Do some polling to wait for the connections to complete +#define POLL_INTERVAL 0.2 // 200ms +#define N_SEC_TO_POLL 3.0 // poll for 3s +#define MAX_POLL_COUNT N_SEC_TO_POLL / POLL_INTERVAL + + NSUInteger pollCount = 0; + while (!(sessionDelegate1.connectionFinished && sessionDelegate2.connectionFinished && sessionDelegate3.connectionFinished) && (pollCount < MAX_POLL_COUNT)) { + NSDate* untilDate = [NSDate dateWithTimeIntervalSinceNow:POLL_INTERVAL]; + [[NSRunLoop currentRunLoop] runUntilDate:untilDate]; + pollCount++; + } + + if (pollCount == MAX_POLL_COUNT) { + XCTFail(@"Could not connect in time"); + } + + + // The first two connections should succeed + XCTAssertTrue(sessionDelegate1.connectionSucceeded, @"Connection to Twitter failed"); + XCTAssertTrue(sessionDelegate2.connectionSucceeded, @"Connection to iSEC Partners failed"); + + // The last connection should fail + XCTAssertFalse(sessionDelegate3.connectionSucceeded, @"Connection to NCC succeeded"); +} + + +@end + + + + +#pragma mark Delegate class + +@implementation NSURLSessionTaskDelegateTest + + @synthesize connectionSucceeded; + @synthesize connectionFinished; + + -(instancetype) init { + if (self = [super init]) + { + self.connectionSucceeded = NO; + self.connectionFinished = NO; + } + return self; + } + +@end diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/SSLCertificatePinningTests-Info.plist b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/SSLCertificatePinningTests-Info.plist new file mode 100644 index 000000000..ccba61f8e --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/SSLCertificatePinningTests-Info.plist @@ -0,0 +1,22 @@ +<?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>en</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>com.isecpartners.${PRODUCT_NAME:rfc1034identifier}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> +</dict> +</plist> diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/SSLPinsTestUtility.h b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/SSLPinsTestUtility.h new file mode 100644 index 000000000..56dde1ac7 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/SSLPinsTestUtility.h @@ -0,0 +1,15 @@ +// +// SSLPinsTestUtility.h +// SSLCertificatePinning +// +// Created by Alban Diquet on 2/2/14. +// Copyright (c) 2014 iSEC Partners. All rights reserved. +// + +#import <Foundation/Foundation.h> + +@interface SSLPinsTestUtility : NSObject + ++ (NSDictionary*) setupTestSSLPinsDictionnary; + +@end diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/SSLPinsTestUtility.m b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/SSLPinsTestUtility.m new file mode 100644 index 000000000..7a5eb22c5 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/SSLPinsTestUtility.m @@ -0,0 +1,57 @@ +// +// SSLPinsTestUtility.m +// SSLCertificatePinning +// +// Created by Alban Diquet on 2/2/14. +// Copyright (c) 2014 iSEC Partners. All rights reserved. +// + +#import "SSLPinsTestUtility.h" +#import "ISPCertificatePinning.h" + +@implementation SSLPinsTestUtility + + ++ (NSData*)loadCertificateFromFile:(NSString*)fileName { + NSString *certPath = [[NSBundle bundleForClass:[self class]] pathForResource:fileName ofType:@"der"]; + NSData *certData = [[NSData alloc] initWithContentsOfFile:certPath]; + return certData; +} + + ++ (NSDictionary*) setupTestSSLPinsDictionnary { + // Build our dictionnary of domain => certificates + NSMutableDictionary *domainsToPin = [[NSMutableDictionary alloc] init]; + + + // For Twitter, we pin the anchor/CA certificate + NSData *twitterCertData = [SSLPinsTestUtility loadCertificateFromFile:@"VeriSignClass3PublicPrimaryCertificationAuthority-G5"]; + if (twitterCertData == nil) { + NSLog(@"Failed to load a certificate"); + return nil; + } + NSArray *twitterTrustedCerts = [NSArray arrayWithObject:twitterCertData]; + [domainsToPin setObject:twitterTrustedCerts forKey:@"twitter.com"]; + + + // For iSEC, we pin the server/leaf certificate + NSData *isecCertData = [SSLPinsTestUtility loadCertificateFromFile:@"www.isecpartners.com"]; + if (isecCertData == nil) { + NSLog(@"Failed to load a certificate"); + return nil; + } + // We also pin Twitter's CA cert just to show that you can pin multiple certs to a single domain + // This is useful when transitioning between two certificates on the server + // The connection will be succesful if at least one of the pinned certs is found in the server's certificate trust chain + NSArray *iSECTrustedCerts = [NSArray arrayWithObjects:isecCertData, twitterCertData, nil]; + [domainsToPin setObject:iSECTrustedCerts forKey:@"www.isecpartners.com"]; + + + // For NCC group, we pin an invalid certificate (Twitter's) + NSArray *NCCTrustedCerts = [NSArray arrayWithObject:twitterCertData]; + [domainsToPin setObject:NCCTrustedCerts forKey:@"www.nccgroup.com"]; + + return domainsToPin; +} + +@end diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/VeriSignClass3PublicPrimaryCertificationAuthority-G5.der b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/VeriSignClass3PublicPrimaryCertificationAuthority-G5.der Binary files differnew file mode 100644 index 000000000..9818d19d0 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/VeriSignClass3PublicPrimaryCertificationAuthority-G5.der diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/en.lproj/InfoPlist.strings b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/en.lproj/InfoPlist.strings new file mode 100644 index 000000000..477b28ff8 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/www.isecpartners.com.der b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/www.isecpartners.com.der Binary files differnew file mode 100644 index 000000000..886cf483e --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/ios/SSLCertificatePinning/SSLCertificatePinningTests/www.isecpartners.com.der diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/DigiCertHighAssuranceEVRootCA.pem b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/DigiCertHighAssuranceEVRootCA.pem new file mode 100644 index 000000000..4b1bc66be --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/DigiCertHighAssuranceEVRootCA.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----
diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile new file mode 100644 index 000000000..0edaa7cbc --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile @@ -0,0 +1,12 @@ +# Tested on FreeBSD, Ubuntu 10.04 and Cygwin +CC=gcc +CFLAGS=-c -Wall -std=c99 -pedantic +LDFLAGS=-lcrypto -lssl + +all: test_client + +test_client: test_client.o openssl_hostname_validation.o + $(CC) test_client.o openssl_hostname_validation.o -o test_client $(LDFLAGS) + +clean: + rm -rf *.o test_client diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile_mingw b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile_mingw new file mode 100644 index 000000000..00f631443 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/Makefile_mingw @@ -0,0 +1,18 @@ +# Tested on Windows 7 with MinGW-w64 +CC=gcc +CFLAGS=-c -Wall +LDFLAGS= -leay32 -lssl32 + +all: test_client + +test_client: test_client.o openssl_hostname_validation.o + $(CC) test_client.o openssl_hostname_validation.o -o test_client $(LDFLAGS) + +test_client.o: test_client.c + $(CC) $(CFLAGS) test_client.c + +openssl_hostname_validation.o: openssl_hostname_validation.c + $(CC) $(CFLAGS) openssl_hostname_validation.c + +clean: + rm -rf *.o test_client.exe diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/README.md b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/README.md new file mode 100644 index 000000000..14ca84aee --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/README.md @@ -0,0 +1,61 @@ +The SSL Conservatory: OpenSSL Certificate Validation +==================================================== + +This sample code demonstrates how to perform certificate validation when using +the OpenSSL library to connect to an SSL/TLS server. It was tested on Windows +7, OS X and Linux. + + +Read The Whitepaper +------------------- + +Before using this code, please read the white paper "Everything you've always +wanted to know about certificate validation with OpenSSL (but were afraid to +ask)" available at ./everything-you-wanted-to-know-about-openssl.pdf. + + +OS-Specific Instructions +------------------------ + +### Linux + +The code was compiled and tested on Ubuntu 11.04. + +You will have to install the libssl and libcrypto development libraries and +header files. In most Linux distros they are part of the "libssl-dev" package. + + +### OS X + +The code was compiled and tested on OS X Mountain Lion. + +OS X comes the OpenSSL development libraries pre-installed. However, libssl has +been modified by Apple to automatically use the system's trust store when +validating certificate chains; this behavior cannot be changed. Therefore, +specifying a trust store using SSL_CTX_load_verify_locations() will always be +ignored on OS X. + +Additionally, compiling the code on OS X will generate a lot of "is +deprecated" warnings because Apple is migrating from OpenSSL to the Common +Crypto framework. + + +### Windows + +The code was compiled using minGW and tested on Windows 7. + +You will have to install minGW as well as the OpenSSL development libraries. +The OpenSSL project provides a link to pre-compiled libraries for Windows at +the following URL: http://www.openssl.org/related/binaries.html + +If you used those binaries, here are additional instructions to compile the +sample code. First add the OpenSSL headers and libraries to MinGW: + + Copy <OpenSSL_Folder>/include/ to <MinGW_Folder>/include/ + Copy <OpenSSL_Folder>/libeay32.dll to <MinGW_Folder>/lib/libeay32.dll + Copy <OpenSSL_Folder>/libssl32.dll to <MinGW_Folder>/lib/libssl32.dll + +Then compile the test_client: + + make -f Makefile_mingw + diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/everything-you-wanted-to-know-about-openssl.pdf b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/everything-you-wanted-to-know-about-openssl.pdf Binary files differnew file mode 100644 index 000000000..9e6524f6a --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/everything-you-wanted-to-know-about-openssl.pdf diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.c b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.c new file mode 100644 index 000000000..066fd6dd6 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.c @@ -0,0 +1,181 @@ +/* + * Helper functions to perform basic hostname validation using OpenSSL. + * + * Please read "everything-you-wanted-to-know-about-openssl.pdf" before + * attempting to use this code. This whitepaper describes how the code works, + * how it should be used, and what its limitations are. + * + * Author: Alban Diquet + * License: See LICENSE + * + */ + + +#include <strings.h> +#include <openssl/x509v3.h> +#include <openssl/ssl.h> + +#include "openssl_hostname_validation.h" + + +#define HOSTNAME_MAX_SIZE 255 + +static int lowercase(int ch) { + if ('A' <= ch && ch <= 'Z') + return ch - 'A' + 'a'; + return ch; +} + +static int memeq_ncase(const char *x, const char *y, size_t l) { + if (l == 0) + return 1; + do { + if (lowercase(*x++) != lowercase(*y++)) + return 0; + } while (--l != 0); + return 1; +} + +static int has_nul(const char *s, size_t l) { + if (l == 0) + return 0; + do { + if (*s++ == '\0') + return 1; + } while (--l != 0); + return 0; +} + +static HostnameValidationResult validate_name(const char *hostname, ASN1_STRING *certname_asn1) { +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) + char *certname_s = (char *) ASN1_STRING_get0_data(certname_asn1); +#else + char *certname_s = (char *) ASN1_STRING_data(certname_asn1); +#endif + int certname_len = ASN1_STRING_length(certname_asn1), hostname_len = strlen(hostname); + + // Make sure there isn't an embedded NUL character in the DNS name + if (has_nul(certname_s, certname_len)) { + return MalformedCertificate; + } + // remove last '.' from hostname + if (hostname_len != 0 && hostname[hostname_len - 1] == '.') + --hostname_len; + // skip the first segment if wildcard + if (certname_len > 2 && certname_s[0] == '*' && certname_s[1] == '.') { + if (hostname_len != 0) { + do { + --hostname_len; + if (*hostname++ == '.') + break; + } while (hostname_len != 0); + } + certname_s += 2; + certname_len -= 2; + } + // Compare expected hostname with the DNS name + if (certname_len != hostname_len) { + return MatchNotFound; + } + return memeq_ncase(hostname, certname_s, hostname_len) ? MatchFound : MatchNotFound; +} + +/** +* Tries to find a match for hostname in the certificate's Common Name field. +* +* Returns MatchFound if a match was found. +* Returns MatchNotFound if no matches were found. +* Returns MalformedCertificate if the Common Name had a NUL character embedded in it. +* Returns Error if the Common Name could not be extracted. +*/ +static HostnameValidationResult matches_common_name(const char *hostname, const X509 *server_cert) { + int common_name_loc = -1; + X509_NAME_ENTRY *common_name_entry = NULL; + ASN1_STRING *common_name_asn1 = NULL; + + // Find the position of the CN field in the Subject field of the certificate + common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name((X509 *) server_cert), NID_commonName, -1); + if (common_name_loc < 0) { + return Error; + } + + // Extract the CN field + common_name_entry = X509_NAME_get_entry(X509_get_subject_name((X509 *) server_cert), common_name_loc); + if (common_name_entry == NULL) { + return Error; + } + common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry); + if (common_name_asn1 == NULL) { + return Error; + } + + // validate the names + return validate_name(hostname, common_name_asn1); +} + + +/** +* Tries to find a match for hostname in the certificate's Subject Alternative Name extension. +* +* Returns MatchFound if a match was found. +* Returns MatchNotFound if no matches were found. +* Returns MalformedCertificate if any of the hostnames had a NUL character embedded in it. +* Returns NoSANPresent if the SAN extension was not present in the certificate. +*/ +static HostnameValidationResult matches_subject_alternative_name(const char *hostname, const X509 *server_cert) { + HostnameValidationResult result = MatchNotFound; + int i; + int san_names_nb = -1; + STACK_OF(GENERAL_NAME) *san_names = NULL; + + // Try to extract the names within the SAN extension from the certificate + san_names = X509_get_ext_d2i((X509 *) server_cert, NID_subject_alt_name, NULL, NULL); + if (san_names == NULL) { + return NoSANPresent; + } + san_names_nb = sk_GENERAL_NAME_num(san_names); + + // Check each name within the extension + for (i=0; i<san_names_nb; i++) { + const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(san_names, i); + + if (current_name->type == GEN_DNS) { + // Current name is a DNS name, let's check it + result = validate_name(hostname, current_name->d.dNSName); + if (result != MatchNotFound) { + break; + } + } + } + sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free); + + return result; +} + + +/** +* Validates the server's identity by looking for the expected hostname in the +* server's certificate. As described in RFC 6125, it first tries to find a match +* in the Subject Alternative Name extension. If the extension is not present in +* the certificate, it checks the Common Name instead. +* +* Returns MatchFound if a match was found. +* Returns MatchNotFound if no matches were found. +* Returns MalformedCertificate if any of the hostnames had a NUL character embedded in it. +* Returns Error if there was an error. +*/ +HostnameValidationResult validate_hostname(const char *hostname, const X509 *server_cert) { + HostnameValidationResult result; + + if((hostname == NULL) || (server_cert == NULL)) + return Error; + + // First try the Subject Alternative Names extension + result = matches_subject_alternative_name(hostname, server_cert); + if (result == NoSANPresent) { + // Extension was not found: try the Common Name + result = matches_common_name(hostname, server_cert); + } + + return result; +} diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.h b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.h new file mode 100644 index 000000000..ca4b9be9f --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/openssl_hostname_validation.h @@ -0,0 +1,40 @@ +/* + * Helper functions to perform basic hostname validation using OpenSSL. + * + * Please read "everything-you-wanted-to-know-about-openssl.pdf" before + * attempting to use this code. This whitepaper describes how the code works, + * how it should be used, and what its limitations are. + * + * Author: Alban Diquet + * License: See LICENSE + * + */ +#ifndef openssl_hostname_validation_h +#define openssl_hostname_validation_h + +#ifndef OPENSSL_HOSTNAME_VALIDATION_LINKAGE +#define OPENSSL_HOSTNAME_VALIDATION_LINKAGE extern +#endif + +typedef enum { + MatchFound, + MatchNotFound, + NoSANPresent, + MalformedCertificate, + Error +} HostnameValidationResult; + +/** +* Validates the server's identity by looking for the expected hostname in the +* server's certificate. As described in RFC 6125, it first tries to find a match +* in the Subject Alternative Name extension. If the extension is not present in +* the certificate, it checks the Common Name instead. +* +* Returns MatchFound if a match was found. +* Returns MatchNotFound if no matches were found. +* Returns MalformedCertificate if any of the hostnames had a NUL character embedded in it. +* Returns Error if there was an error. +*/ +OPENSSL_HOSTNAME_VALIDATION_LINKAGE HostnameValidationResult validate_hostname(const char *hostname, const X509 *server_cert); + +#endif diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client Binary files differnew file mode 100755 index 000000000..054fd8cdc --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client diff --git a/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client.c b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client.c new file mode 100644 index 000000000..916a22ed8 --- /dev/null +++ b/web/server/h2o/libh2o/deps/ssl-conservatory/openssl/test_client.c @@ -0,0 +1,142 @@ +/* + * Sample HTTPS client to demonstrate how to do certificate validation using + * OpenSSL. + * This client will securely connect to www.isecpartners.com:443 and print the + * server's response to an HTTP GET request. + * + * Please read "everything-you-wanted-to-know-about-openssl.pdf" before + * attempting to use this code. This whitepaper describes how the code works, + * how it should be used, and what its limitations are. + * + * Author: Alban Diquet + * License: See LICENSE + * + */ + +#include <stdio.h> +#include <openssl/ssl.h> +#include <openssl/err.h> +#include <openssl/rand.h> + +#include "openssl_hostname_validation.h" + + +// Sample SSL client for https://www.isecpartners.com +#define TARGET_HOST "www.isecpartners.com" +#define TARGET_PORT "443" + +// CA certificate that signed www.isecpartners.com's certificate +#define TRUSTED_CA_PATHNAME "DigiCertHighAssuranceEVRootCA.pem" + + + +#define TARGET_SERVER TARGET_HOST":"TARGET_PORT +// 'High' cipher suites minus Anonymous DH and Camellia +#define SECURE_CIPHER_LIST "RC4-SHA:HIGH:!ADH:!AECDH:!CAMELLIA" + +/* Sends an HTTP GET and prints the server's response */ +static void send_http_get_and_print(BIO * sbio) { + int len; + char tmpbuf[1024]; + BIO * out = BIO_new_fp(stdout, BIO_NOCLOSE); + + BIO_puts(sbio, "GET / HTTP/1.0\n\n"); + for(;;) { + len = BIO_read(sbio, tmpbuf, 1024); + if(len <= 0) break; + BIO_write(out, tmpbuf, len); + } + BIO_free(out); +} + + +int main(int argc, char *argv[]) { + BIO *sbio; + SSL_CTX *ssl_ctx; + SSL *ssl; + X509 *server_cert; + + // Initialize OpenSSL + SSL_library_init(); + SSL_load_error_strings(); + + // Check OpenSSL PRNG + if(RAND_status() != 1) { + fprintf(stderr, "OpenSSL PRNG not seeded with enough data."); + goto error_1; + } + + ssl_ctx = SSL_CTX_new(TLSv1_client_method()); + + // Enable certificate validation + SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL); + // Configure the CA trust store to be used + if (SSL_CTX_load_verify_locations(ssl_ctx, TRUSTED_CA_PATHNAME, NULL) != 1) { + fprintf(stderr, "Couldn't load certificate trust store.\n"); + goto error_2; + } + + // Only support secure cipher suites + if (SSL_CTX_set_cipher_list(ssl_ctx, SECURE_CIPHER_LIST) != 1) + goto error_2; + + // Create the SSL connection + sbio = BIO_new_ssl_connect(ssl_ctx); + BIO_get_ssl(sbio, &ssl); + if(!ssl) { + fprintf(stderr, "Can't locate SSL pointer\n"); + goto error_3; + } + + // Do the SSL handshake + BIO_set_conn_hostname(sbio, TARGET_SERVER); + if(SSL_do_handshake(ssl) <= 0) { + // SSL Handshake failed + long verify_err = SSL_get_verify_result(ssl); + if (verify_err != X509_V_OK) { + // It failed because the certificate chain validation failed + fprintf(stderr, "Certificate chain validation failed: %s\n", X509_verify_cert_error_string(verify_err)); + } + else { + // It failed for another reason + ERR_print_errors_fp(stderr); + } + goto error_3; + } + + // Recover the server's certificate + server_cert = SSL_get_peer_certificate(ssl); + if (server_cert == NULL) { + // The handshake was successful although the server did not provide a certificate + // Most likely using an insecure anonymous cipher suite... get out! + goto error_4; + } + + // Validate the hostname + if (validate_hostname(TARGET_HOST, server_cert) != MatchFound) { + fprintf(stderr, "Hostname validation failed.\n"); + goto error_5; + } + + // Hostname validation succeeded; we can start sending data + send_http_get_and_print(sbio); + + +error_5: + X509_free(server_cert); + +error_4: + BIO_ssl_shutdown(sbio); + +error_3: + BIO_free_all(sbio); + +error_2: + SSL_CTX_free(ssl_ctx); + +error_1: // OpenSSL cleanup + EVP_cleanup(); + ERR_free_strings(); + + return 0; +} |