| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -130,6 +130,104 @@ namespace
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        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
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				namespace ix
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -153,6 +251,63 @@ namespace ix
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        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
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    bool SocketAppleSSL::connect(const std::string& host,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                                 int port,
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@@ -173,6 +328,8 @@ namespace ix
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            SSLSetProtocolVersionMin(_sslContext, kTLSProtocol12);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            SSLSetPeerDomainName(_sslContext, host.c_str(), host.size());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (!handleTLSOptions(errMsg)) return false; // FIXME not calling close()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if (_tlsOptions.isPeerVerifyDisabled())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                Boolean option(1);
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				 
 |