1""" 2This module uses ctypes to bind a whole bunch of functions and constants from 3SecureTransport. The goal here is to provide the low-level API to 4SecureTransport. These are essentially the C-level functions and constants, and 5they're pretty gross to work with. 6 7This code is a bastardised version of the code found in Will Bond's oscrypto 8library. An enormous debt is owed to him for blazing this trail for us. For 9that reason, this code should be considered to be covered both by urllib3's 10license and by oscrypto's: 11 12 Copyright (c) 2015-2016 Will Bond <will@wbond.net> 13 14 Permission is hereby granted, free of charge, to any person obtaining a 15 copy of this software and associated documentation files (the "Software"), 16 to deal in the Software without restriction, including without limitation 17 the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 and/or sell copies of the Software, and to permit persons to whom the 19 Software is furnished to do so, subject to the following conditions: 20 21 The above copyright notice and this permission notice shall be included in 22 all copies or substantial portions of the Software. 23 24 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 30 DEALINGS IN THE SOFTWARE. 31""" 32from __future__ import absolute_import 33 34import platform 35from ctypes import ( 36 CDLL, 37 CFUNCTYPE, 38 POINTER, 39 c_bool, 40 c_byte, 41 c_char_p, 42 c_int32, 43 c_long, 44 c_size_t, 45 c_uint32, 46 c_ulong, 47 c_void_p, 48) 49from ctypes.util import find_library 50 51from urllib3.packages.six import raise_from 52 53if platform.system() != "Darwin": 54 raise ImportError("Only macOS is supported") 55 56version = platform.mac_ver()[0] 57version_info = tuple(map(int, version.split("."))) 58if version_info < (10, 8): 59 raise OSError( 60 "Only OS X 10.8 and newer are supported, not %s.%s" 61 % (version_info[0], version_info[1]) 62 ) 63 64 65def load_cdll(name, macos10_16_path): 66 """Loads a CDLL by name, falling back to known path on 10.16+""" 67 try: 68 # Big Sur is technically 11 but we use 10.16 due to the Big Sur 69 # beta being labeled as 10.16. 70 if version_info >= (10, 16): 71 path = macos10_16_path 72 else: 73 path = find_library(name) 74 if not path: 75 raise OSError # Caught and reraised as 'ImportError' 76 return CDLL(path, use_errno=True) 77 except OSError: 78 raise_from(ImportError("The library %s failed to load" % name), None) 79 80 81Security = load_cdll( 82 "Security", "/System/Library/Frameworks/Security.framework/Security" 83) 84CoreFoundation = load_cdll( 85 "CoreFoundation", 86 "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", 87) 88 89 90Boolean = c_bool 91CFIndex = c_long 92CFStringEncoding = c_uint32 93CFData = c_void_p 94CFString = c_void_p 95CFArray = c_void_p 96CFMutableArray = c_void_p 97CFDictionary = c_void_p 98CFError = c_void_p 99CFType = c_void_p 100CFTypeID = c_ulong 101 102CFTypeRef = POINTER(CFType) 103CFAllocatorRef = c_void_p 104 105OSStatus = c_int32 106 107CFDataRef = POINTER(CFData) 108CFStringRef = POINTER(CFString) 109CFArrayRef = POINTER(CFArray) 110CFMutableArrayRef = POINTER(CFMutableArray) 111CFDictionaryRef = POINTER(CFDictionary) 112CFArrayCallBacks = c_void_p 113CFDictionaryKeyCallBacks = c_void_p 114CFDictionaryValueCallBacks = c_void_p 115 116SecCertificateRef = POINTER(c_void_p) 117SecExternalFormat = c_uint32 118SecExternalItemType = c_uint32 119SecIdentityRef = POINTER(c_void_p) 120SecItemImportExportFlags = c_uint32 121SecItemImportExportKeyParameters = c_void_p 122SecKeychainRef = POINTER(c_void_p) 123SSLProtocol = c_uint32 124SSLCipherSuite = c_uint32 125SSLContextRef = POINTER(c_void_p) 126SecTrustRef = POINTER(c_void_p) 127SSLConnectionRef = c_uint32 128SecTrustResultType = c_uint32 129SecTrustOptionFlags = c_uint32 130SSLProtocolSide = c_uint32 131SSLConnectionType = c_uint32 132SSLSessionOption = c_uint32 133 134 135try: 136 Security.SecItemImport.argtypes = [ 137 CFDataRef, 138 CFStringRef, 139 POINTER(SecExternalFormat), 140 POINTER(SecExternalItemType), 141 SecItemImportExportFlags, 142 POINTER(SecItemImportExportKeyParameters), 143 SecKeychainRef, 144 POINTER(CFArrayRef), 145 ] 146 Security.SecItemImport.restype = OSStatus 147 148 Security.SecCertificateGetTypeID.argtypes = [] 149 Security.SecCertificateGetTypeID.restype = CFTypeID 150 151 Security.SecIdentityGetTypeID.argtypes = [] 152 Security.SecIdentityGetTypeID.restype = CFTypeID 153 154 Security.SecKeyGetTypeID.argtypes = [] 155 Security.SecKeyGetTypeID.restype = CFTypeID 156 157 Security.SecCertificateCreateWithData.argtypes = [CFAllocatorRef, CFDataRef] 158 Security.SecCertificateCreateWithData.restype = SecCertificateRef 159 160 Security.SecCertificateCopyData.argtypes = [SecCertificateRef] 161 Security.SecCertificateCopyData.restype = CFDataRef 162 163 Security.SecCopyErrorMessageString.argtypes = [OSStatus, c_void_p] 164 Security.SecCopyErrorMessageString.restype = CFStringRef 165 166 Security.SecIdentityCreateWithCertificate.argtypes = [ 167 CFTypeRef, 168 SecCertificateRef, 169 POINTER(SecIdentityRef), 170 ] 171 Security.SecIdentityCreateWithCertificate.restype = OSStatus 172 173 Security.SecKeychainCreate.argtypes = [ 174 c_char_p, 175 c_uint32, 176 c_void_p, 177 Boolean, 178 c_void_p, 179 POINTER(SecKeychainRef), 180 ] 181 Security.SecKeychainCreate.restype = OSStatus 182 183 Security.SecKeychainDelete.argtypes = [SecKeychainRef] 184 Security.SecKeychainDelete.restype = OSStatus 185 186 Security.SecPKCS12Import.argtypes = [ 187 CFDataRef, 188 CFDictionaryRef, 189 POINTER(CFArrayRef), 190 ] 191 Security.SecPKCS12Import.restype = OSStatus 192 193 SSLReadFunc = CFUNCTYPE(OSStatus, SSLConnectionRef, c_void_p, POINTER(c_size_t)) 194 SSLWriteFunc = CFUNCTYPE( 195 OSStatus, SSLConnectionRef, POINTER(c_byte), POINTER(c_size_t) 196 ) 197 198 Security.SSLSetIOFuncs.argtypes = [SSLContextRef, SSLReadFunc, SSLWriteFunc] 199 Security.SSLSetIOFuncs.restype = OSStatus 200 201 Security.SSLSetPeerID.argtypes = [SSLContextRef, c_char_p, c_size_t] 202 Security.SSLSetPeerID.restype = OSStatus 203 204 Security.SSLSetCertificate.argtypes = [SSLContextRef, CFArrayRef] 205 Security.SSLSetCertificate.restype = OSStatus 206 207 Security.SSLSetCertificateAuthorities.argtypes = [SSLContextRef, CFTypeRef, Boolean] 208 Security.SSLSetCertificateAuthorities.restype = OSStatus 209 210 Security.SSLSetConnection.argtypes = [SSLContextRef, SSLConnectionRef] 211 Security.SSLSetConnection.restype = OSStatus 212 213 Security.SSLSetPeerDomainName.argtypes = [SSLContextRef, c_char_p, c_size_t] 214 Security.SSLSetPeerDomainName.restype = OSStatus 215 216 Security.SSLHandshake.argtypes = [SSLContextRef] 217 Security.SSLHandshake.restype = OSStatus 218 219 Security.SSLRead.argtypes = [SSLContextRef, c_char_p, c_size_t, POINTER(c_size_t)] 220 Security.SSLRead.restype = OSStatus 221 222 Security.SSLWrite.argtypes = [SSLContextRef, c_char_p, c_size_t, POINTER(c_size_t)] 223 Security.SSLWrite.restype = OSStatus 224 225 Security.SSLClose.argtypes = [SSLContextRef] 226 Security.SSLClose.restype = OSStatus 227 228 Security.SSLGetNumberSupportedCiphers.argtypes = [SSLContextRef, POINTER(c_size_t)] 229 Security.SSLGetNumberSupportedCiphers.restype = OSStatus 230 231 Security.SSLGetSupportedCiphers.argtypes = [ 232 SSLContextRef, 233 POINTER(SSLCipherSuite), 234 POINTER(c_size_t), 235 ] 236 Security.SSLGetSupportedCiphers.restype = OSStatus 237 238 Security.SSLSetEnabledCiphers.argtypes = [ 239 SSLContextRef, 240 POINTER(SSLCipherSuite), 241 c_size_t, 242 ] 243 Security.SSLSetEnabledCiphers.restype = OSStatus 244 245 Security.SSLGetNumberEnabledCiphers.argtype = [SSLContextRef, POINTER(c_size_t)] 246 Security.SSLGetNumberEnabledCiphers.restype = OSStatus 247 248 Security.SSLGetEnabledCiphers.argtypes = [ 249 SSLContextRef, 250 POINTER(SSLCipherSuite), 251 POINTER(c_size_t), 252 ] 253 Security.SSLGetEnabledCiphers.restype = OSStatus 254 255 Security.SSLGetNegotiatedCipher.argtypes = [SSLContextRef, POINTER(SSLCipherSuite)] 256 Security.SSLGetNegotiatedCipher.restype = OSStatus 257 258 Security.SSLGetNegotiatedProtocolVersion.argtypes = [ 259 SSLContextRef, 260 POINTER(SSLProtocol), 261 ] 262 Security.SSLGetNegotiatedProtocolVersion.restype = OSStatus 263 264 Security.SSLCopyPeerTrust.argtypes = [SSLContextRef, POINTER(SecTrustRef)] 265 Security.SSLCopyPeerTrust.restype = OSStatus 266 267 Security.SecTrustSetAnchorCertificates.argtypes = [SecTrustRef, CFArrayRef] 268 Security.SecTrustSetAnchorCertificates.restype = OSStatus 269 270 Security.SecTrustSetAnchorCertificatesOnly.argstypes = [SecTrustRef, Boolean] 271 Security.SecTrustSetAnchorCertificatesOnly.restype = OSStatus 272 273 Security.SecTrustEvaluate.argtypes = [SecTrustRef, POINTER(SecTrustResultType)] 274 Security.SecTrustEvaluate.restype = OSStatus 275 276 Security.SecTrustGetCertificateCount.argtypes = [SecTrustRef] 277 Security.SecTrustGetCertificateCount.restype = CFIndex 278 279 Security.SecTrustGetCertificateAtIndex.argtypes = [SecTrustRef, CFIndex] 280 Security.SecTrustGetCertificateAtIndex.restype = SecCertificateRef 281 282 Security.SSLCreateContext.argtypes = [ 283 CFAllocatorRef, 284 SSLProtocolSide, 285 SSLConnectionType, 286 ] 287 Security.SSLCreateContext.restype = SSLContextRef 288 289 Security.SSLSetSessionOption.argtypes = [SSLContextRef, SSLSessionOption, Boolean] 290 Security.SSLSetSessionOption.restype = OSStatus 291 292 Security.SSLSetProtocolVersionMin.argtypes = [SSLContextRef, SSLProtocol] 293 Security.SSLSetProtocolVersionMin.restype = OSStatus 294 295 Security.SSLSetProtocolVersionMax.argtypes = [SSLContextRef, SSLProtocol] 296 Security.SSLSetProtocolVersionMax.restype = OSStatus 297 298 try: 299 Security.SSLSetALPNProtocols.argtypes = [SSLContextRef, CFArrayRef] 300 Security.SSLSetALPNProtocols.restype = OSStatus 301 except AttributeError: 302 # Supported only in 10.12+ 303 pass 304 305 Security.SecCopyErrorMessageString.argtypes = [OSStatus, c_void_p] 306 Security.SecCopyErrorMessageString.restype = CFStringRef 307 308 Security.SSLReadFunc = SSLReadFunc 309 Security.SSLWriteFunc = SSLWriteFunc 310 Security.SSLContextRef = SSLContextRef 311 Security.SSLProtocol = SSLProtocol 312 Security.SSLCipherSuite = SSLCipherSuite 313 Security.SecIdentityRef = SecIdentityRef 314 Security.SecKeychainRef = SecKeychainRef 315 Security.SecTrustRef = SecTrustRef 316 Security.SecTrustResultType = SecTrustResultType 317 Security.SecExternalFormat = SecExternalFormat 318 Security.OSStatus = OSStatus 319 320 Security.kSecImportExportPassphrase = CFStringRef.in_dll( 321 Security, "kSecImportExportPassphrase" 322 ) 323 Security.kSecImportItemIdentity = CFStringRef.in_dll( 324 Security, "kSecImportItemIdentity" 325 ) 326 327 # CoreFoundation time! 328 CoreFoundation.CFRetain.argtypes = [CFTypeRef] 329 CoreFoundation.CFRetain.restype = CFTypeRef 330 331 CoreFoundation.CFRelease.argtypes = [CFTypeRef] 332 CoreFoundation.CFRelease.restype = None 333 334 CoreFoundation.CFGetTypeID.argtypes = [CFTypeRef] 335 CoreFoundation.CFGetTypeID.restype = CFTypeID 336 337 CoreFoundation.CFStringCreateWithCString.argtypes = [ 338 CFAllocatorRef, 339 c_char_p, 340 CFStringEncoding, 341 ] 342 CoreFoundation.CFStringCreateWithCString.restype = CFStringRef 343 344 CoreFoundation.CFStringGetCStringPtr.argtypes = [CFStringRef, CFStringEncoding] 345 CoreFoundation.CFStringGetCStringPtr.restype = c_char_p 346 347 CoreFoundation.CFStringGetCString.argtypes = [ 348 CFStringRef, 349 c_char_p, 350 CFIndex, 351 CFStringEncoding, 352 ] 353 CoreFoundation.CFStringGetCString.restype = c_bool 354 355 CoreFoundation.CFDataCreate.argtypes = [CFAllocatorRef, c_char_p, CFIndex] 356 CoreFoundation.CFDataCreate.restype = CFDataRef 357 358 CoreFoundation.CFDataGetLength.argtypes = [CFDataRef] 359 CoreFoundation.CFDataGetLength.restype = CFIndex 360 361 CoreFoundation.CFDataGetBytePtr.argtypes = [CFDataRef] 362 CoreFoundation.CFDataGetBytePtr.restype = c_void_p 363 364 CoreFoundation.CFDictionaryCreate.argtypes = [ 365 CFAllocatorRef, 366 POINTER(CFTypeRef), 367 POINTER(CFTypeRef), 368 CFIndex, 369 CFDictionaryKeyCallBacks, 370 CFDictionaryValueCallBacks, 371 ] 372 CoreFoundation.CFDictionaryCreate.restype = CFDictionaryRef 373 374 CoreFoundation.CFDictionaryGetValue.argtypes = [CFDictionaryRef, CFTypeRef] 375 CoreFoundation.CFDictionaryGetValue.restype = CFTypeRef 376 377 CoreFoundation.CFArrayCreate.argtypes = [ 378 CFAllocatorRef, 379 POINTER(CFTypeRef), 380 CFIndex, 381 CFArrayCallBacks, 382 ] 383 CoreFoundation.CFArrayCreate.restype = CFArrayRef 384 385 CoreFoundation.CFArrayCreateMutable.argtypes = [ 386 CFAllocatorRef, 387 CFIndex, 388 CFArrayCallBacks, 389 ] 390 CoreFoundation.CFArrayCreateMutable.restype = CFMutableArrayRef 391 392 CoreFoundation.CFArrayAppendValue.argtypes = [CFMutableArrayRef, c_void_p] 393 CoreFoundation.CFArrayAppendValue.restype = None 394 395 CoreFoundation.CFArrayGetCount.argtypes = [CFArrayRef] 396 CoreFoundation.CFArrayGetCount.restype = CFIndex 397 398 CoreFoundation.CFArrayGetValueAtIndex.argtypes = [CFArrayRef, CFIndex] 399 CoreFoundation.CFArrayGetValueAtIndex.restype = c_void_p 400 401 CoreFoundation.kCFAllocatorDefault = CFAllocatorRef.in_dll( 402 CoreFoundation, "kCFAllocatorDefault" 403 ) 404 CoreFoundation.kCFTypeArrayCallBacks = c_void_p.in_dll( 405 CoreFoundation, "kCFTypeArrayCallBacks" 406 ) 407 CoreFoundation.kCFTypeDictionaryKeyCallBacks = c_void_p.in_dll( 408 CoreFoundation, "kCFTypeDictionaryKeyCallBacks" 409 ) 410 CoreFoundation.kCFTypeDictionaryValueCallBacks = c_void_p.in_dll( 411 CoreFoundation, "kCFTypeDictionaryValueCallBacks" 412 ) 413 414 CoreFoundation.CFTypeRef = CFTypeRef 415 CoreFoundation.CFArrayRef = CFArrayRef 416 CoreFoundation.CFStringRef = CFStringRef 417 CoreFoundation.CFDictionaryRef = CFDictionaryRef 418 419except (AttributeError): 420 raise ImportError("Error initializing ctypes") 421 422 423class CFConst(object): 424 """ 425 A class object that acts as essentially a namespace for CoreFoundation 426 constants. 427 """ 428 429 kCFStringEncodingUTF8 = CFStringEncoding(0x08000100) 430 431 432class SecurityConst(object): 433 """ 434 A class object that acts as essentially a namespace for Security constants. 435 """ 436 437 kSSLSessionOptionBreakOnServerAuth = 0 438 439 kSSLProtocol2 = 1 440 kSSLProtocol3 = 2 441 kTLSProtocol1 = 4 442 kTLSProtocol11 = 7 443 kTLSProtocol12 = 8 444 # SecureTransport does not support TLS 1.3 even if there's a constant for it 445 kTLSProtocol13 = 10 446 kTLSProtocolMaxSupported = 999 447 448 kSSLClientSide = 1 449 kSSLStreamType = 0 450 451 kSecFormatPEMSequence = 10 452 453 kSecTrustResultInvalid = 0 454 kSecTrustResultProceed = 1 455 # This gap is present on purpose: this was kSecTrustResultConfirm, which 456 # is deprecated. 457 kSecTrustResultDeny = 3 458 kSecTrustResultUnspecified = 4 459 kSecTrustResultRecoverableTrustFailure = 5 460 kSecTrustResultFatalTrustFailure = 6 461 kSecTrustResultOtherError = 7 462 463 errSSLProtocol = -9800 464 errSSLWouldBlock = -9803 465 errSSLClosedGraceful = -9805 466 errSSLClosedNoNotify = -9816 467 errSSLClosedAbort = -9806 468 469 errSSLXCertChainInvalid = -9807 470 errSSLCrypto = -9809 471 errSSLInternal = -9810 472 errSSLCertExpired = -9814 473 errSSLCertNotYetValid = -9815 474 errSSLUnknownRootCert = -9812 475 errSSLNoRootCert = -9813 476 errSSLHostNameMismatch = -9843 477 errSSLPeerHandshakeFail = -9824 478 errSSLPeerUserCancelled = -9839 479 errSSLWeakPeerEphemeralDHKey = -9850 480 errSSLServerAuthCompleted = -9841 481 errSSLRecordOverflow = -9847 482 483 errSecVerifyFailed = -67808 484 errSecNoTrustSettings = -25263 485 errSecItemNotFound = -25300 486 errSecInvalidTrustSettings = -25262 487 488 # Cipher suites. We only pick the ones our default cipher string allows. 489 # Source: https://developer.apple.com/documentation/security/1550981-ssl_cipher_suite_values 490 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C 491 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030 492 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B 493 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F 494 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9 495 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8 496 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F 497 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E 498 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024 499 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028 500 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A 501 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014 502 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B 503 TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039 504 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023 505 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027 506 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009 507 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013 508 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067 509 TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033 510 TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D 511 TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C 512 TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D 513 TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C 514 TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035 515 TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F 516 TLS_AES_128_GCM_SHA256 = 0x1301 517 TLS_AES_256_GCM_SHA384 = 0x1302 518 TLS_AES_128_CCM_8_SHA256 = 0x1305 519 TLS_AES_128_CCM_SHA256 = 0x1304 520