Compare commits
	
		
			1 Commits
		
	
	
		
			v7.8.4
			...
			feature/ma
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 84361c16a9 | 
| @@ -130,6 +130,104 @@ namespace | |||||||
|         return errMsg; |         return errMsg; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | #undef CURL_BUILD_IOS | ||||||
|  |     OSStatus CopyIdentityFromPKCS12File( | ||||||
|  |         const char *cPath, | ||||||
|  |         const char *cPassword, | ||||||
|  |         SecIdentityRef *out_cert_and_key) | ||||||
|  |     { | ||||||
|  |         OSStatus status = errSecItemNotFound; | ||||||
|  |         CFURLRef pkcs_url = CFURLCreateFromFileSystemRepresentation( | ||||||
|  |             NULL, (const UInt8 *)cPath, strlen(cPath), false); | ||||||
|  |         CFStringRef password = cPassword ? CFStringCreateWithCString(NULL, | ||||||
|  |             cPassword, kCFStringEncodingUTF8) : NULL; | ||||||
|  |         CFDataRef pkcs_data = NULL; | ||||||
|  |  | ||||||
|  |         /* We can import P12 files on iOS or OS X 10.7 or later: */ | ||||||
|  |         /* These constants are documented as having first appeared in 10.6 but they | ||||||
|  |            raise linker errors when used on that cat for some reason. */ | ||||||
|  |         if (CFURLCreateDataAndPropertiesFromResource( | ||||||
|  |             NULL, pkcs_url, &pkcs_data, NULL, NULL, &status)) { | ||||||
|  |             CFArrayRef items = NULL; | ||||||
|  |  | ||||||
|  |             /* On iOS SecPKCS12Import will never add the client certificate to the | ||||||
|  |              * Keychain. | ||||||
|  |              * | ||||||
|  |              * It gives us back a SecIdentityRef that we can use directly. */ | ||||||
|  | #if CURL_BUILD_IOS | ||||||
|  |             const void *cKeys[] = {kSecImportExportPassphrase}; | ||||||
|  |             const void *cValues[] = {password}; | ||||||
|  |             CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues, | ||||||
|  |                     password ? 1L : 0L, NULL, NULL); | ||||||
|  |  | ||||||
|  |             if (options != NULL) { | ||||||
|  |                 status = SecPKCS12Import(pkcs_data, options, &items); | ||||||
|  |                 CFRelease(options); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             /* On macOS SecPKCS12Import will always add the client certificate to | ||||||
|  |              * the Keychain. | ||||||
|  |              * | ||||||
|  |              * As this doesn't match iOS, and apps may not want to see their client | ||||||
|  |              * certificate saved in the the user's keychain, we use SecItemImport | ||||||
|  |              * with a NULL keychain to avoid importing it. | ||||||
|  |              * | ||||||
|  |              * This returns a SecCertificateRef from which we can construct a | ||||||
|  |              * SecIdentityRef. | ||||||
|  |              */ | ||||||
|  | #else | ||||||
|  |             SecItemImportExportKeyParameters keyParams; | ||||||
|  |             SecExternalFormat inputFormat = kSecFormatPKCS12; | ||||||
|  |             SecExternalItemType inputType = kSecItemTypeCertificate; | ||||||
|  |  | ||||||
|  |             memset(&keyParams, 0x00, sizeof(keyParams)); | ||||||
|  |             keyParams.version    = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; | ||||||
|  |             keyParams.passphrase = password; | ||||||
|  |  | ||||||
|  |             status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType, | ||||||
|  |                                    0, &keyParams, NULL, &items); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |             /* Extract the SecIdentityRef */ | ||||||
|  |             if (status == errSecSuccess && items && CFArrayGetCount(items)) | ||||||
|  |             { | ||||||
|  |                 CFIndex i, count; | ||||||
|  |                 count = CFArrayGetCount(items); | ||||||
|  |  | ||||||
|  |                 for (i = 0; i < count; i++) | ||||||
|  |                 { | ||||||
|  |                     CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(items, i); | ||||||
|  |                     CFTypeID  itemID = CFGetTypeID(item); | ||||||
|  |  | ||||||
|  |                     if (itemID == CFDictionaryGetTypeID()) | ||||||
|  |                     { | ||||||
|  |                         CFTypeRef identity = (CFTypeRef) CFDictionaryGetValue( | ||||||
|  |                                 (CFDictionaryRef) item, | ||||||
|  |                                 kSecImportItemIdentity); | ||||||
|  |                         CFRetain(identity); | ||||||
|  |                         *out_cert_and_key = (SecIdentityRef) identity; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                     else if (itemID == SecCertificateGetTypeID()) | ||||||
|  |                     { | ||||||
|  |                         status = SecIdentityCreateWithCertificate(NULL, | ||||||
|  |                                 (SecCertificateRef) item, | ||||||
|  |                                 out_cert_and_key); | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (items) CFRelease(items); | ||||||
|  |             CFRelease(pkcs_data); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (password) CFRelease(password); | ||||||
|  |         CFRelease(pkcs_url); | ||||||
|  |         return status; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| } // anonymous namespace | } // anonymous namespace | ||||||
|  |  | ||||||
| namespace ix | namespace ix | ||||||
| @@ -153,6 +251,63 @@ namespace ix | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     bool SocketAppleSSL::handleTLSOptions(std::string& errMsg) | ||||||
|  |     { | ||||||
|  |         SecIdentityRef cert_and_key = NULL; | ||||||
|  |  | ||||||
|  |         const char* ssl_cert = _tlsOptions.certFile.c_str(); | ||||||
|  |  | ||||||
|  |         OSStatus err = CopyIdentityFromPKCS12File(ssl_cert, "foobar", &cert_and_key); | ||||||
|  |  | ||||||
|  |         if (err == noErr && cert_and_key) | ||||||
|  |         { | ||||||
|  |             SecCertificateRef cert = NULL; | ||||||
|  |             CFTypeRef certs_c[1]; | ||||||
|  |             CFArrayRef certs; | ||||||
|  |  | ||||||
|  |             err = SecIdentityCopyCertificate(cert_and_key, &cert); | ||||||
|  |  | ||||||
|  |             certs_c[0] = cert_and_key; | ||||||
|  |             certs = CFArrayCreate(NULL, (const void **)certs_c, 1L, | ||||||
|  |                     &kCFTypeArrayCallBacks); | ||||||
|  |             err = SSLSetCertificate(_sslContext, certs); | ||||||
|  |             if (err != noErr) | ||||||
|  |             { | ||||||
|  |                 errMsg = "SSLSetCertificate failed"; | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             switch(err) { | ||||||
|  |                 case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ | ||||||
|  |                     errMsg = "SSL: Incorrect password for the certificate \"%s\" " | ||||||
|  |                             "and its private key."; // , ssl_cert); | ||||||
|  |                     break; | ||||||
|  |                 case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ | ||||||
|  |                     errMsg = "SSL: Couldn't make sense of the data in the " | ||||||
|  |                             "certificate \"%s\" and its private key."; | ||||||
|  |                             ; // ssl_cert); | ||||||
|  |                     break; | ||||||
|  |                 case -25260: /* errSecPassphraseRequired */ | ||||||
|  |                     errMsg = "SSL The certificate \"%s\" requires a password."; | ||||||
|  |                             // ssl_cert); | ||||||
|  |                     break; | ||||||
|  |                 case errSecItemNotFound: | ||||||
|  |                     errMsg = "SSL: Can't find the certificate \"%s\" and its private " | ||||||
|  |                             "key in the Keychain."; // , ssl_cert); | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     errMsg = "SSL: Can't load the certificate \"%s\" and its private " | ||||||
|  |                             "key: OSStatus %d" ; // , ssl_cert, err); | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // No wait support |     // No wait support | ||||||
|     bool SocketAppleSSL::connect(const std::string& host, |     bool SocketAppleSSL::connect(const std::string& host, | ||||||
|                                  int port, |                                  int port, | ||||||
| @@ -173,6 +328,8 @@ namespace ix | |||||||
|             SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12); |             SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12); | ||||||
|             SSLSetPeerDomainName(_sslContext, host.c_str(), host.size()); |             SSLSetPeerDomainName(_sslContext, host.c_str(), host.size()); | ||||||
|  |  | ||||||
|  |             if (!handleTLSOptions(errMsg)) return false; // FIXME not calling close() | ||||||
|  |  | ||||||
|             if (_tlsOptions.isPeerVerifyDisabled()) |             if (_tlsOptions.isPeerVerifyDisabled()) | ||||||
|             { |             { | ||||||
|                 Boolean option(1); |                 Boolean option(1); | ||||||
|   | |||||||
| @@ -34,6 +34,8 @@ namespace ix | |||||||
|         virtual ssize_t recv(void* buffer, size_t length) final; |         virtual ssize_t recv(void* buffer, size_t length) final; | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
|  |         bool handleTLSOptions(std::string& errMsg); | ||||||
|  |  | ||||||
|         SSLContextRef _sslContext; |         SSLContextRef _sslContext; | ||||||
|         mutable std::mutex _mutex; // AppleSSL routines are not thread-safe |         mutable std::mutex _mutex; // AppleSSL routines are not thread-safe | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user