Return to sectransp.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / vtls |
1.1 ! misho 1: /*************************************************************************** ! 2: * _ _ ____ _ ! 3: * Project ___| | | | _ \| | ! 4: * / __| | | | |_) | | ! 5: * | (__| |_| | _ <| |___ ! 6: * \___|\___/|_| \_\_____| ! 7: * ! 8: * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>. ! 9: * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. ! 10: * ! 11: * This software is licensed as described in the file COPYING, which ! 12: * you should have received as part of this distribution. The terms ! 13: * are also available at https://curl.haxx.se/docs/copyright.html. ! 14: * ! 15: * You may opt to use, copy, modify, merge, publish, distribute and/or sell ! 16: * copies of the Software, and permit persons to whom the Software is ! 17: * furnished to do so, under the terms of the COPYING file. ! 18: * ! 19: * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY ! 20: * KIND, either express or implied. ! 21: * ! 22: ***************************************************************************/ ! 23: ! 24: /* ! 25: * Source file for all iOS and macOS SecureTransport-specific code for the ! 26: * TLS/SSL layer. No code but vtls.c should ever call or use these functions. ! 27: */ ! 28: ! 29: #include "curl_setup.h" ! 30: ! 31: #include "urldata.h" /* for the Curl_easy definition */ ! 32: #include "curl_base64.h" ! 33: #include "strtok.h" ! 34: #include "multiif.h" ! 35: ! 36: #ifdef USE_SECTRANSP ! 37: ! 38: #ifdef __clang__ ! 39: #pragma clang diagnostic push ! 40: #pragma clang diagnostic ignored "-Wtautological-pointer-compare" ! 41: #endif /* __clang__ */ ! 42: ! 43: #include <limits.h> ! 44: ! 45: #include <Security/Security.h> ! 46: /* For some reason, when building for iOS, the omnibus header above does ! 47: * not include SecureTransport.h as of iOS SDK 5.1. */ ! 48: #include <Security/SecureTransport.h> ! 49: #include <CoreFoundation/CoreFoundation.h> ! 50: #include <CommonCrypto/CommonDigest.h> ! 51: ! 52: /* The Security framework has changed greatly between iOS and different macOS ! 53: versions, and we will try to support as many of them as we can (back to ! 54: Leopard and iOS 5) by using macros and weak-linking. ! 55: ! 56: In general, you want to build this using the most recent OS SDK, since some ! 57: features require curl to be built against the latest SDK. TLS 1.1 and 1.2 ! 58: support, for instance, require the macOS 10.8 SDK or later. TLS 1.3 ! 59: requires the macOS 10.13 or iOS 11 SDK or later. */ ! 60: #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) ! 61: ! 62: #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 ! 63: #error "The Secure Transport back-end requires Leopard or later." ! 64: #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */ ! 65: ! 66: #define CURL_BUILD_IOS 0 ! 67: #define CURL_BUILD_IOS_7 0 ! 68: #define CURL_BUILD_IOS_9 0 ! 69: #define CURL_BUILD_IOS_11 0 ! 70: #define CURL_BUILD_MAC 1 ! 71: /* This is the maximum API level we are allowed to use when building: */ ! 72: #define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 ! 73: #define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 ! 74: #define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 ! 75: #define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 ! 76: #define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 ! 77: #define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 ! 78: #define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 ! 79: /* These macros mean "the following code is present to allow runtime backward ! 80: compatibility with at least this cat or earlier": ! 81: (You set this at build-time using the compiler command line option ! 82: "-mmacosx-version-min.") */ ! 83: #define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050 ! 84: #define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060 ! 85: #define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 ! 86: #define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080 ! 87: #define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090 ! 88: ! 89: #elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE ! 90: #define CURL_BUILD_IOS 1 ! 91: #define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 ! 92: #define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 ! 93: #define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 ! 94: #define CURL_BUILD_MAC 0 ! 95: #define CURL_BUILD_MAC_10_5 0 ! 96: #define CURL_BUILD_MAC_10_6 0 ! 97: #define CURL_BUILD_MAC_10_7 0 ! 98: #define CURL_BUILD_MAC_10_8 0 ! 99: #define CURL_BUILD_MAC_10_9 0 ! 100: #define CURL_BUILD_MAC_10_11 0 ! 101: #define CURL_BUILD_MAC_10_13 0 ! 102: #define CURL_SUPPORT_MAC_10_5 0 ! 103: #define CURL_SUPPORT_MAC_10_6 0 ! 104: #define CURL_SUPPORT_MAC_10_7 0 ! 105: #define CURL_SUPPORT_MAC_10_8 0 ! 106: #define CURL_SUPPORT_MAC_10_9 0 ! 107: ! 108: #else ! 109: #error "The Secure Transport back-end requires iOS or macOS." ! 110: #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */ ! 111: ! 112: #if CURL_BUILD_MAC ! 113: #include <sys/sysctl.h> ! 114: #endif /* CURL_BUILD_MAC */ ! 115: ! 116: #include "urldata.h" ! 117: #include "sendf.h" ! 118: #include "inet_pton.h" ! 119: #include "connect.h" ! 120: #include "select.h" ! 121: #include "vtls.h" ! 122: #include "sectransp.h" ! 123: #include "curl_printf.h" ! 124: #include "strdup.h" ! 125: ! 126: #include "curl_memory.h" ! 127: /* The last #include file should be: */ ! 128: #include "memdebug.h" ! 129: ! 130: /* From MacTypes.h (which we can't include because it isn't present in iOS: */ ! 131: #define ioErr -36 ! 132: #define paramErr -50 ! 133: ! 134: struct ssl_backend_data { ! 135: SSLContextRef ssl_ctx; ! 136: curl_socket_t ssl_sockfd; ! 137: bool ssl_direction; /* true if writing, false if reading */ ! 138: size_t ssl_write_buffered_length; ! 139: }; ! 140: ! 141: /* pinned public key support tests */ ! 142: ! 143: /* version 1 supports macOS 10.12+ and iOS 10+ */ ! 144: #if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \ ! 145: (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)) ! 146: #define SECTRANSP_PINNEDPUBKEY_V1 1 ! 147: #endif ! 148: ! 149: /* version 2 supports MacOSX 10.7+ */ ! 150: #if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070) ! 151: #define SECTRANSP_PINNEDPUBKEY_V2 1 ! 152: #endif ! 153: ! 154: #if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2) ! 155: /* this backend supports CURLOPT_PINNEDPUBLICKEY */ ! 156: #define SECTRANSP_PINNEDPUBKEY 1 ! 157: #endif /* SECTRANSP_PINNEDPUBKEY */ ! 158: ! 159: #ifdef SECTRANSP_PINNEDPUBKEY ! 160: /* both new and old APIs return rsa keys missing the spki header (not DER) */ ! 161: static const unsigned char rsa4096SpkiHeader[] = { ! 162: 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, ! 163: 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, ! 164: 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, ! 165: 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00}; ! 166: ! 167: static const unsigned char rsa2048SpkiHeader[] = { ! 168: 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, ! 169: 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, ! 170: 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, ! 171: 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00}; ! 172: #ifdef SECTRANSP_PINNEDPUBKEY_V1 ! 173: /* the *new* version doesn't return DER encoded ecdsa certs like the old... */ ! 174: static const unsigned char ecDsaSecp256r1SpkiHeader[] = { ! 175: 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, ! 176: 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, ! 177: 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, ! 178: 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, ! 179: 0x42, 0x00}; ! 180: ! 181: static const unsigned char ecDsaSecp384r1SpkiHeader[] = { ! 182: 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, ! 183: 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, ! 184: 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, ! 185: 0x00, 0x22, 0x03, 0x62, 0x00}; ! 186: #endif /* SECTRANSP_PINNEDPUBKEY_V1 */ ! 187: #endif /* SECTRANSP_PINNEDPUBKEY */ ! 188: ! 189: /* The following two functions were ripped from Apple sample code, ! 190: * with some modifications: */ ! 191: static OSStatus SocketRead(SSLConnectionRef connection, ! 192: void *data, /* owned by ! 193: * caller, data ! 194: * RETURNED */ ! 195: size_t *dataLength) /* IN/OUT */ ! 196: { ! 197: size_t bytesToGo = *dataLength; ! 198: size_t initLen = bytesToGo; ! 199: UInt8 *currData = (UInt8 *)data; ! 200: /*int sock = *(int *)connection;*/ ! 201: struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; ! 202: struct ssl_backend_data *backend = connssl->backend; ! 203: int sock = backend->ssl_sockfd; ! 204: OSStatus rtn = noErr; ! 205: size_t bytesRead; ! 206: ssize_t rrtn; ! 207: int theErr; ! 208: ! 209: *dataLength = 0; ! 210: ! 211: for(;;) { ! 212: bytesRead = 0; ! 213: rrtn = read(sock, currData, bytesToGo); ! 214: if(rrtn <= 0) { ! 215: /* this is guesswork... */ ! 216: theErr = errno; ! 217: if(rrtn == 0) { /* EOF = server hung up */ ! 218: /* the framework will turn this into errSSLClosedNoNotify */ ! 219: rtn = errSSLClosedGraceful; ! 220: } ! 221: else /* do the switch */ ! 222: switch(theErr) { ! 223: case ENOENT: ! 224: /* connection closed */ ! 225: rtn = errSSLClosedGraceful; ! 226: break; ! 227: case ECONNRESET: ! 228: rtn = errSSLClosedAbort; ! 229: break; ! 230: case EAGAIN: ! 231: rtn = errSSLWouldBlock; ! 232: backend->ssl_direction = false; ! 233: break; ! 234: default: ! 235: rtn = ioErr; ! 236: break; ! 237: } ! 238: break; ! 239: } ! 240: else { ! 241: bytesRead = rrtn; ! 242: } ! 243: bytesToGo -= bytesRead; ! 244: currData += bytesRead; ! 245: ! 246: if(bytesToGo == 0) { ! 247: /* filled buffer with incoming data, done */ ! 248: break; ! 249: } ! 250: } ! 251: *dataLength = initLen - bytesToGo; ! 252: ! 253: return rtn; ! 254: } ! 255: ! 256: static OSStatus SocketWrite(SSLConnectionRef connection, ! 257: const void *data, ! 258: size_t *dataLength) /* IN/OUT */ ! 259: { ! 260: size_t bytesSent = 0; ! 261: /*int sock = *(int *)connection;*/ ! 262: struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection; ! 263: struct ssl_backend_data *backend = connssl->backend; ! 264: int sock = backend->ssl_sockfd; ! 265: ssize_t length; ! 266: size_t dataLen = *dataLength; ! 267: const UInt8 *dataPtr = (UInt8 *)data; ! 268: OSStatus ortn; ! 269: int theErr; ! 270: ! 271: *dataLength = 0; ! 272: ! 273: do { ! 274: length = write(sock, ! 275: (char *)dataPtr + bytesSent, ! 276: dataLen - bytesSent); ! 277: } while((length > 0) && ! 278: ( (bytesSent += length) < dataLen) ); ! 279: ! 280: if(length <= 0) { ! 281: theErr = errno; ! 282: if(theErr == EAGAIN) { ! 283: ortn = errSSLWouldBlock; ! 284: backend->ssl_direction = true; ! 285: } ! 286: else { ! 287: ortn = ioErr; ! 288: } ! 289: } ! 290: else { ! 291: ortn = noErr; ! 292: } ! 293: *dataLength = bytesSent; ! 294: return ortn; ! 295: } ! 296: ! 297: #ifndef CURL_DISABLE_VERBOSE_STRINGS ! 298: CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher) ! 299: { ! 300: switch(cipher) { ! 301: /* SSL version 3.0 */ ! 302: case SSL_RSA_WITH_NULL_MD5: ! 303: return "SSL_RSA_WITH_NULL_MD5"; ! 304: break; ! 305: case SSL_RSA_WITH_NULL_SHA: ! 306: return "SSL_RSA_WITH_NULL_SHA"; ! 307: break; ! 308: case SSL_RSA_EXPORT_WITH_RC4_40_MD5: ! 309: return "SSL_RSA_EXPORT_WITH_RC4_40_MD5"; ! 310: break; ! 311: case SSL_RSA_WITH_RC4_128_MD5: ! 312: return "SSL_RSA_WITH_RC4_128_MD5"; ! 313: break; ! 314: case SSL_RSA_WITH_RC4_128_SHA: ! 315: return "SSL_RSA_WITH_RC4_128_SHA"; ! 316: break; ! 317: case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: ! 318: return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5"; ! 319: break; ! 320: case SSL_RSA_WITH_IDEA_CBC_SHA: ! 321: return "SSL_RSA_WITH_IDEA_CBC_SHA"; ! 322: break; ! 323: case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: ! 324: return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"; ! 325: break; ! 326: case SSL_RSA_WITH_DES_CBC_SHA: ! 327: return "SSL_RSA_WITH_DES_CBC_SHA"; ! 328: break; ! 329: case SSL_RSA_WITH_3DES_EDE_CBC_SHA: ! 330: return "SSL_RSA_WITH_3DES_EDE_CBC_SHA"; ! 331: break; ! 332: case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: ! 333: return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"; ! 334: break; ! 335: case SSL_DH_DSS_WITH_DES_CBC_SHA: ! 336: return "SSL_DH_DSS_WITH_DES_CBC_SHA"; ! 337: break; ! 338: case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA: ! 339: return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA"; ! 340: break; ! 341: case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: ! 342: return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"; ! 343: break; ! 344: case SSL_DH_RSA_WITH_DES_CBC_SHA: ! 345: return "SSL_DH_RSA_WITH_DES_CBC_SHA"; ! 346: break; ! 347: case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA: ! 348: return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA"; ! 349: break; ! 350: case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: ! 351: return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"; ! 352: break; ! 353: case SSL_DHE_DSS_WITH_DES_CBC_SHA: ! 354: return "SSL_DHE_DSS_WITH_DES_CBC_SHA"; ! 355: break; ! 356: case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA: ! 357: return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; ! 358: break; ! 359: case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: ! 360: return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"; ! 361: break; ! 362: case SSL_DHE_RSA_WITH_DES_CBC_SHA: ! 363: return "SSL_DHE_RSA_WITH_DES_CBC_SHA"; ! 364: break; ! 365: case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA: ! 366: return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; ! 367: break; ! 368: case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: ! 369: return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"; ! 370: break; ! 371: case SSL_DH_anon_WITH_RC4_128_MD5: ! 372: return "SSL_DH_anon_WITH_RC4_128_MD5"; ! 373: break; ! 374: case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: ! 375: return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"; ! 376: break; ! 377: case SSL_DH_anon_WITH_DES_CBC_SHA: ! 378: return "SSL_DH_anon_WITH_DES_CBC_SHA"; ! 379: break; ! 380: case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: ! 381: return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA"; ! 382: break; ! 383: case SSL_FORTEZZA_DMS_WITH_NULL_SHA: ! 384: return "SSL_FORTEZZA_DMS_WITH_NULL_SHA"; ! 385: break; ! 386: case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: ! 387: return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA"; ! 388: break; ! 389: /* TLS 1.0 with AES (RFC 3268) ! 390: (Apparently these are used in SSLv3 implementations as well.) */ ! 391: case TLS_RSA_WITH_AES_128_CBC_SHA: ! 392: return "TLS_RSA_WITH_AES_128_CBC_SHA"; ! 393: break; ! 394: case TLS_DH_DSS_WITH_AES_128_CBC_SHA: ! 395: return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; ! 396: break; ! 397: case TLS_DH_RSA_WITH_AES_128_CBC_SHA: ! 398: return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; ! 399: break; ! 400: case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: ! 401: return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; ! 402: break; ! 403: case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: ! 404: return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; ! 405: break; ! 406: case TLS_DH_anon_WITH_AES_128_CBC_SHA: ! 407: return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; ! 408: break; ! 409: case TLS_RSA_WITH_AES_256_CBC_SHA: ! 410: return "TLS_RSA_WITH_AES_256_CBC_SHA"; ! 411: break; ! 412: case TLS_DH_DSS_WITH_AES_256_CBC_SHA: ! 413: return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; ! 414: break; ! 415: case TLS_DH_RSA_WITH_AES_256_CBC_SHA: ! 416: return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; ! 417: break; ! 418: case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: ! 419: return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; ! 420: break; ! 421: case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: ! 422: return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; ! 423: break; ! 424: case TLS_DH_anon_WITH_AES_256_CBC_SHA: ! 425: return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; ! 426: break; ! 427: /* SSL version 2.0 */ ! 428: case SSL_RSA_WITH_RC2_CBC_MD5: ! 429: return "SSL_RSA_WITH_RC2_CBC_MD5"; ! 430: break; ! 431: case SSL_RSA_WITH_IDEA_CBC_MD5: ! 432: return "SSL_RSA_WITH_IDEA_CBC_MD5"; ! 433: break; ! 434: case SSL_RSA_WITH_DES_CBC_MD5: ! 435: return "SSL_RSA_WITH_DES_CBC_MD5"; ! 436: break; ! 437: case SSL_RSA_WITH_3DES_EDE_CBC_MD5: ! 438: return "SSL_RSA_WITH_3DES_EDE_CBC_MD5"; ! 439: break; ! 440: } ! 441: return "SSL_NULL_WITH_NULL_NULL"; ! 442: } ! 443: ! 444: CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) ! 445: { ! 446: switch(cipher) { ! 447: /* TLS 1.0 with AES (RFC 3268) */ ! 448: case TLS_RSA_WITH_AES_128_CBC_SHA: ! 449: return "TLS_RSA_WITH_AES_128_CBC_SHA"; ! 450: break; ! 451: case TLS_DH_DSS_WITH_AES_128_CBC_SHA: ! 452: return "TLS_DH_DSS_WITH_AES_128_CBC_SHA"; ! 453: break; ! 454: case TLS_DH_RSA_WITH_AES_128_CBC_SHA: ! 455: return "TLS_DH_RSA_WITH_AES_128_CBC_SHA"; ! 456: break; ! 457: case TLS_DHE_DSS_WITH_AES_128_CBC_SHA: ! 458: return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"; ! 459: break; ! 460: case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: ! 461: return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"; ! 462: break; ! 463: case TLS_DH_anon_WITH_AES_128_CBC_SHA: ! 464: return "TLS_DH_anon_WITH_AES_128_CBC_SHA"; ! 465: break; ! 466: case TLS_RSA_WITH_AES_256_CBC_SHA: ! 467: return "TLS_RSA_WITH_AES_256_CBC_SHA"; ! 468: break; ! 469: case TLS_DH_DSS_WITH_AES_256_CBC_SHA: ! 470: return "TLS_DH_DSS_WITH_AES_256_CBC_SHA"; ! 471: break; ! 472: case TLS_DH_RSA_WITH_AES_256_CBC_SHA: ! 473: return "TLS_DH_RSA_WITH_AES_256_CBC_SHA"; ! 474: break; ! 475: case TLS_DHE_DSS_WITH_AES_256_CBC_SHA: ! 476: return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"; ! 477: break; ! 478: case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: ! 479: return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"; ! 480: break; ! 481: case TLS_DH_anon_WITH_AES_256_CBC_SHA: ! 482: return "TLS_DH_anon_WITH_AES_256_CBC_SHA"; ! 483: break; ! 484: #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS ! 485: /* TLS 1.0 with ECDSA (RFC 4492) */ ! 486: case TLS_ECDH_ECDSA_WITH_NULL_SHA: ! 487: return "TLS_ECDH_ECDSA_WITH_NULL_SHA"; ! 488: break; ! 489: case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: ! 490: return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"; ! 491: break; ! 492: case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: ! 493: return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"; ! 494: break; ! 495: case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: ! 496: return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"; ! 497: break; ! 498: case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: ! 499: return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"; ! 500: break; ! 501: case TLS_ECDHE_ECDSA_WITH_NULL_SHA: ! 502: return "TLS_ECDHE_ECDSA_WITH_NULL_SHA"; ! 503: break; ! 504: case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: ! 505: return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"; ! 506: break; ! 507: case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: ! 508: return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"; ! 509: break; ! 510: case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: ! 511: return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"; ! 512: break; ! 513: case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: ! 514: return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"; ! 515: break; ! 516: case TLS_ECDH_RSA_WITH_NULL_SHA: ! 517: return "TLS_ECDH_RSA_WITH_NULL_SHA"; ! 518: break; ! 519: case TLS_ECDH_RSA_WITH_RC4_128_SHA: ! 520: return "TLS_ECDH_RSA_WITH_RC4_128_SHA"; ! 521: break; ! 522: case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: ! 523: return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"; ! 524: break; ! 525: case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: ! 526: return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"; ! 527: break; ! 528: case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: ! 529: return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"; ! 530: break; ! 531: case TLS_ECDHE_RSA_WITH_NULL_SHA: ! 532: return "TLS_ECDHE_RSA_WITH_NULL_SHA"; ! 533: break; ! 534: case TLS_ECDHE_RSA_WITH_RC4_128_SHA: ! 535: return "TLS_ECDHE_RSA_WITH_RC4_128_SHA"; ! 536: break; ! 537: case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: ! 538: return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"; ! 539: break; ! 540: case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: ! 541: return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"; ! 542: break; ! 543: case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: ! 544: return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"; ! 545: break; ! 546: case TLS_ECDH_anon_WITH_NULL_SHA: ! 547: return "TLS_ECDH_anon_WITH_NULL_SHA"; ! 548: break; ! 549: case TLS_ECDH_anon_WITH_RC4_128_SHA: ! 550: return "TLS_ECDH_anon_WITH_RC4_128_SHA"; ! 551: break; ! 552: case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA: ! 553: return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"; ! 554: break; ! 555: case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: ! 556: return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"; ! 557: break; ! 558: case TLS_ECDH_anon_WITH_AES_256_CBC_SHA: ! 559: return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"; ! 560: break; ! 561: #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ ! 562: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS ! 563: /* TLS 1.2 (RFC 5246) */ ! 564: case TLS_RSA_WITH_NULL_MD5: ! 565: return "TLS_RSA_WITH_NULL_MD5"; ! 566: break; ! 567: case TLS_RSA_WITH_NULL_SHA: ! 568: return "TLS_RSA_WITH_NULL_SHA"; ! 569: break; ! 570: case TLS_RSA_WITH_RC4_128_MD5: ! 571: return "TLS_RSA_WITH_RC4_128_MD5"; ! 572: break; ! 573: case TLS_RSA_WITH_RC4_128_SHA: ! 574: return "TLS_RSA_WITH_RC4_128_SHA"; ! 575: break; ! 576: case TLS_RSA_WITH_3DES_EDE_CBC_SHA: ! 577: return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; ! 578: break; ! 579: case TLS_RSA_WITH_NULL_SHA256: ! 580: return "TLS_RSA_WITH_NULL_SHA256"; ! 581: break; ! 582: case TLS_RSA_WITH_AES_128_CBC_SHA256: ! 583: return "TLS_RSA_WITH_AES_128_CBC_SHA256"; ! 584: break; ! 585: case TLS_RSA_WITH_AES_256_CBC_SHA256: ! 586: return "TLS_RSA_WITH_AES_256_CBC_SHA256"; ! 587: break; ! 588: case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA: ! 589: return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"; ! 590: break; ! 591: case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA: ! 592: return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"; ! 593: break; ! 594: case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA: ! 595: return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"; ! 596: break; ! 597: case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: ! 598: return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"; ! 599: break; ! 600: case TLS_DH_DSS_WITH_AES_128_CBC_SHA256: ! 601: return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"; ! 602: break; ! 603: case TLS_DH_RSA_WITH_AES_128_CBC_SHA256: ! 604: return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"; ! 605: break; ! 606: case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256: ! 607: return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"; ! 608: break; ! 609: case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: ! 610: return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"; ! 611: break; ! 612: case TLS_DH_DSS_WITH_AES_256_CBC_SHA256: ! 613: return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"; ! 614: break; ! 615: case TLS_DH_RSA_WITH_AES_256_CBC_SHA256: ! 616: return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"; ! 617: break; ! 618: case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256: ! 619: return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"; ! 620: break; ! 621: case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: ! 622: return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"; ! 623: break; ! 624: case TLS_DH_anon_WITH_RC4_128_MD5: ! 625: return "TLS_DH_anon_WITH_RC4_128_MD5"; ! 626: break; ! 627: case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA: ! 628: return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; ! 629: break; ! 630: case TLS_DH_anon_WITH_AES_128_CBC_SHA256: ! 631: return "TLS_DH_anon_WITH_AES_128_CBC_SHA256"; ! 632: break; ! 633: case TLS_DH_anon_WITH_AES_256_CBC_SHA256: ! 634: return "TLS_DH_anon_WITH_AES_256_CBC_SHA256"; ! 635: break; ! 636: /* TLS 1.2 with AES GCM (RFC 5288) */ ! 637: case TLS_RSA_WITH_AES_128_GCM_SHA256: ! 638: return "TLS_RSA_WITH_AES_128_GCM_SHA256"; ! 639: break; ! 640: case TLS_RSA_WITH_AES_256_GCM_SHA384: ! 641: return "TLS_RSA_WITH_AES_256_GCM_SHA384"; ! 642: break; ! 643: case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256: ! 644: return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"; ! 645: break; ! 646: case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384: ! 647: return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"; ! 648: break; ! 649: case TLS_DH_RSA_WITH_AES_128_GCM_SHA256: ! 650: return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"; ! 651: break; ! 652: case TLS_DH_RSA_WITH_AES_256_GCM_SHA384: ! 653: return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"; ! 654: break; ! 655: case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256: ! 656: return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"; ! 657: break; ! 658: case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384: ! 659: return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"; ! 660: break; ! 661: case TLS_DH_DSS_WITH_AES_128_GCM_SHA256: ! 662: return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"; ! 663: break; ! 664: case TLS_DH_DSS_WITH_AES_256_GCM_SHA384: ! 665: return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"; ! 666: break; ! 667: case TLS_DH_anon_WITH_AES_128_GCM_SHA256: ! 668: return "TLS_DH_anon_WITH_AES_128_GCM_SHA256"; ! 669: break; ! 670: case TLS_DH_anon_WITH_AES_256_GCM_SHA384: ! 671: return "TLS_DH_anon_WITH_AES_256_GCM_SHA384"; ! 672: break; ! 673: /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */ ! 674: case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: ! 675: return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"; ! 676: break; ! 677: case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: ! 678: return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"; ! 679: break; ! 680: case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: ! 681: return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"; ! 682: break; ! 683: case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: ! 684: return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"; ! 685: break; ! 686: case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: ! 687: return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"; ! 688: break; ! 689: case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: ! 690: return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"; ! 691: break; ! 692: case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: ! 693: return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"; ! 694: break; ! 695: case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: ! 696: return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"; ! 697: break; ! 698: case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: ! 699: return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"; ! 700: break; ! 701: case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: ! 702: return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; ! 703: break; ! 704: case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: ! 705: return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"; ! 706: break; ! 707: case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: ! 708: return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"; ! 709: break; ! 710: case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: ! 711: return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"; ! 712: break; ! 713: case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: ! 714: return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"; ! 715: break; ! 716: case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: ! 717: return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"; ! 718: break; ! 719: case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: ! 720: return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"; ! 721: break; ! 722: case TLS_EMPTY_RENEGOTIATION_INFO_SCSV: ! 723: return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"; ! 724: break; ! 725: #else ! 726: case SSL_RSA_WITH_NULL_MD5: ! 727: return "TLS_RSA_WITH_NULL_MD5"; ! 728: break; ! 729: case SSL_RSA_WITH_NULL_SHA: ! 730: return "TLS_RSA_WITH_NULL_SHA"; ! 731: break; ! 732: case SSL_RSA_WITH_RC4_128_MD5: ! 733: return "TLS_RSA_WITH_RC4_128_MD5"; ! 734: break; ! 735: case SSL_RSA_WITH_RC4_128_SHA: ! 736: return "TLS_RSA_WITH_RC4_128_SHA"; ! 737: break; ! 738: case SSL_RSA_WITH_3DES_EDE_CBC_SHA: ! 739: return "TLS_RSA_WITH_3DES_EDE_CBC_SHA"; ! 740: break; ! 741: case SSL_DH_anon_WITH_RC4_128_MD5: ! 742: return "TLS_DH_anon_WITH_RC4_128_MD5"; ! 743: break; ! 744: case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: ! 745: return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"; ! 746: break; ! 747: #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ ! 748: #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 ! 749: /* TLS PSK (RFC 4279): */ ! 750: case TLS_PSK_WITH_RC4_128_SHA: ! 751: return "TLS_PSK_WITH_RC4_128_SHA"; ! 752: break; ! 753: case TLS_PSK_WITH_3DES_EDE_CBC_SHA: ! 754: return "TLS_PSK_WITH_3DES_EDE_CBC_SHA"; ! 755: break; ! 756: case TLS_PSK_WITH_AES_128_CBC_SHA: ! 757: return "TLS_PSK_WITH_AES_128_CBC_SHA"; ! 758: break; ! 759: case TLS_PSK_WITH_AES_256_CBC_SHA: ! 760: return "TLS_PSK_WITH_AES_256_CBC_SHA"; ! 761: break; ! 762: case TLS_DHE_PSK_WITH_RC4_128_SHA: ! 763: return "TLS_DHE_PSK_WITH_RC4_128_SHA"; ! 764: break; ! 765: case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA: ! 766: return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"; ! 767: break; ! 768: case TLS_DHE_PSK_WITH_AES_128_CBC_SHA: ! 769: return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"; ! 770: break; ! 771: case TLS_DHE_PSK_WITH_AES_256_CBC_SHA: ! 772: return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"; ! 773: break; ! 774: case TLS_RSA_PSK_WITH_RC4_128_SHA: ! 775: return "TLS_RSA_PSK_WITH_RC4_128_SHA"; ! 776: break; ! 777: case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA: ! 778: return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"; ! 779: break; ! 780: case TLS_RSA_PSK_WITH_AES_128_CBC_SHA: ! 781: return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"; ! 782: break; ! 783: case TLS_RSA_PSK_WITH_AES_256_CBC_SHA: ! 784: return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"; ! 785: break; ! 786: /* More TLS PSK (RFC 4785): */ ! 787: case TLS_PSK_WITH_NULL_SHA: ! 788: return "TLS_PSK_WITH_NULL_SHA"; ! 789: break; ! 790: case TLS_DHE_PSK_WITH_NULL_SHA: ! 791: return "TLS_DHE_PSK_WITH_NULL_SHA"; ! 792: break; ! 793: case TLS_RSA_PSK_WITH_NULL_SHA: ! 794: return "TLS_RSA_PSK_WITH_NULL_SHA"; ! 795: break; ! 796: /* Even more TLS PSK (RFC 5487): */ ! 797: case TLS_PSK_WITH_AES_128_GCM_SHA256: ! 798: return "TLS_PSK_WITH_AES_128_GCM_SHA256"; ! 799: break; ! 800: case TLS_PSK_WITH_AES_256_GCM_SHA384: ! 801: return "TLS_PSK_WITH_AES_256_GCM_SHA384"; ! 802: break; ! 803: case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256: ! 804: return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"; ! 805: break; ! 806: case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384: ! 807: return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"; ! 808: break; ! 809: case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256: ! 810: return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"; ! 811: break; ! 812: case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384: ! 813: return "TLS_PSK_WITH_AES_256_GCM_SHA384"; ! 814: break; ! 815: case TLS_PSK_WITH_AES_128_CBC_SHA256: ! 816: return "TLS_PSK_WITH_AES_128_CBC_SHA256"; ! 817: break; ! 818: case TLS_PSK_WITH_AES_256_CBC_SHA384: ! 819: return "TLS_PSK_WITH_AES_256_CBC_SHA384"; ! 820: break; ! 821: case TLS_PSK_WITH_NULL_SHA256: ! 822: return "TLS_PSK_WITH_NULL_SHA256"; ! 823: break; ! 824: case TLS_PSK_WITH_NULL_SHA384: ! 825: return "TLS_PSK_WITH_NULL_SHA384"; ! 826: break; ! 827: case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256: ! 828: return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"; ! 829: break; ! 830: case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384: ! 831: return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"; ! 832: break; ! 833: case TLS_DHE_PSK_WITH_NULL_SHA256: ! 834: return "TLS_DHE_PSK_WITH_NULL_SHA256"; ! 835: break; ! 836: case TLS_DHE_PSK_WITH_NULL_SHA384: ! 837: return "TLS_RSA_PSK_WITH_NULL_SHA384"; ! 838: break; ! 839: case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256: ! 840: return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"; ! 841: break; ! 842: case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384: ! 843: return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"; ! 844: break; ! 845: case TLS_RSA_PSK_WITH_NULL_SHA256: ! 846: return "TLS_RSA_PSK_WITH_NULL_SHA256"; ! 847: break; ! 848: case TLS_RSA_PSK_WITH_NULL_SHA384: ! 849: return "TLS_RSA_PSK_WITH_NULL_SHA384"; ! 850: break; ! 851: #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ ! 852: #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 ! 853: /* New ChaCha20+Poly1305 cipher-suites used by TLS 1.3: */ ! 854: case TLS_AES_128_GCM_SHA256: ! 855: return "TLS_AES_128_GCM_SHA256"; ! 856: break; ! 857: case TLS_AES_256_GCM_SHA384: ! 858: return "TLS_AES_256_GCM_SHA384"; ! 859: break; ! 860: case TLS_CHACHA20_POLY1305_SHA256: ! 861: return "TLS_CHACHA20_POLY1305_SHA256"; ! 862: break; ! 863: case TLS_AES_128_CCM_SHA256: ! 864: return "TLS_AES_128_CCM_SHA256"; ! 865: break; ! 866: case TLS_AES_128_CCM_8_SHA256: ! 867: return "TLS_AES_128_CCM_8_SHA256"; ! 868: break; ! 869: case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: ! 870: return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"; ! 871: break; ! 872: case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: ! 873: return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"; ! 874: break; ! 875: #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ ! 876: } ! 877: return "TLS_NULL_WITH_NULL_NULL"; ! 878: } ! 879: #endif /* !CURL_DISABLE_VERBOSE_STRINGS */ ! 880: ! 881: #if CURL_BUILD_MAC ! 882: CF_INLINE void GetDarwinVersionNumber(int *major, int *minor) ! 883: { ! 884: int mib[2]; ! 885: char *os_version; ! 886: size_t os_version_len; ! 887: char *os_version_major, *os_version_minor; ! 888: char *tok_buf; ! 889: ! 890: /* Get the Darwin kernel version from the kernel using sysctl(): */ ! 891: mib[0] = CTL_KERN; ! 892: mib[1] = KERN_OSRELEASE; ! 893: if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1) ! 894: return; ! 895: os_version = malloc(os_version_len*sizeof(char)); ! 896: if(!os_version) ! 897: return; ! 898: if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) { ! 899: free(os_version); ! 900: return; ! 901: } ! 902: ! 903: /* Parse the version: */ ! 904: os_version_major = strtok_r(os_version, ".", &tok_buf); ! 905: os_version_minor = strtok_r(NULL, ".", &tok_buf); ! 906: *major = atoi(os_version_major); ! 907: *minor = atoi(os_version_minor); ! 908: free(os_version); ! 909: } ! 910: #endif /* CURL_BUILD_MAC */ ! 911: ! 912: /* Apple provides a myriad of ways of getting information about a certificate ! 913: into a string. Some aren't available under iOS or newer cats. So here's ! 914: a unified function for getting a string describing the certificate that ! 915: ought to work in all cats starting with Leopard. */ ! 916: CF_INLINE CFStringRef getsubject(SecCertificateRef cert) ! 917: { ! 918: CFStringRef server_cert_summary = CFSTR("(null)"); ! 919: ! 920: #if CURL_BUILD_IOS ! 921: /* iOS: There's only one way to do this. */ ! 922: server_cert_summary = SecCertificateCopySubjectSummary(cert); ! 923: #else ! 924: #if CURL_BUILD_MAC_10_7 ! 925: /* Lion & later: Get the long description if we can. */ ! 926: if(SecCertificateCopyLongDescription != NULL) ! 927: server_cert_summary = ! 928: SecCertificateCopyLongDescription(NULL, cert, NULL); ! 929: else ! 930: #endif /* CURL_BUILD_MAC_10_7 */ ! 931: #if CURL_BUILD_MAC_10_6 ! 932: /* Snow Leopard: Get the certificate summary. */ ! 933: if(SecCertificateCopySubjectSummary != NULL) ! 934: server_cert_summary = SecCertificateCopySubjectSummary(cert); ! 935: else ! 936: #endif /* CURL_BUILD_MAC_10_6 */ ! 937: /* Leopard is as far back as we go... */ ! 938: (void)SecCertificateCopyCommonName(cert, &server_cert_summary); ! 939: #endif /* CURL_BUILD_IOS */ ! 940: return server_cert_summary; ! 941: } ! 942: ! 943: static CURLcode CopyCertSubject(struct Curl_easy *data, ! 944: SecCertificateRef cert, char **certp) ! 945: { ! 946: CFStringRef c = getsubject(cert); ! 947: CURLcode result = CURLE_OK; ! 948: const char *direct; ! 949: char *cbuf = NULL; ! 950: *certp = NULL; ! 951: ! 952: if(!c) { ! 953: failf(data, "SSL: invalid CA certificate subject"); ! 954: return CURLE_PEER_FAILED_VERIFICATION; ! 955: } ! 956: ! 957: /* If the subject is already available as UTF-8 encoded (ie 'direct') then ! 958: use that, else convert it. */ ! 959: direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8); ! 960: if(direct) { ! 961: *certp = strdup(direct); ! 962: if(!*certp) { ! 963: failf(data, "SSL: out of memory"); ! 964: result = CURLE_OUT_OF_MEMORY; ! 965: } ! 966: } ! 967: else { ! 968: size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1; ! 969: cbuf = calloc(cbuf_size, 1); ! 970: if(cbuf) { ! 971: if(!CFStringGetCString(c, cbuf, cbuf_size, ! 972: kCFStringEncodingUTF8)) { ! 973: failf(data, "SSL: invalid CA certificate subject"); ! 974: result = CURLE_PEER_FAILED_VERIFICATION; ! 975: } ! 976: else ! 977: /* pass back the buffer */ ! 978: *certp = cbuf; ! 979: } ! 980: else { ! 981: failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size); ! 982: result = CURLE_OUT_OF_MEMORY; ! 983: } ! 984: } ! 985: if(result) ! 986: free(cbuf); ! 987: CFRelease(c); ! 988: return result; ! 989: } ! 990: ! 991: #if CURL_SUPPORT_MAC_10_6 ! 992: /* The SecKeychainSearch API was deprecated in Lion, and using it will raise ! 993: deprecation warnings, so let's not compile this unless it's necessary: */ ! 994: static OSStatus CopyIdentityWithLabelOldSchool(char *label, ! 995: SecIdentityRef *out_c_a_k) ! 996: { ! 997: OSStatus status = errSecItemNotFound; ! 998: SecKeychainAttributeList attr_list; ! 999: SecKeychainAttribute attr; ! 1000: SecKeychainSearchRef search = NULL; ! 1001: SecCertificateRef cert = NULL; ! 1002: ! 1003: /* Set up the attribute list: */ ! 1004: attr_list.count = 1L; ! 1005: attr_list.attr = &attr; ! 1006: ! 1007: /* Set up our lone search criterion: */ ! 1008: attr.tag = kSecLabelItemAttr; ! 1009: attr.data = label; ! 1010: attr.length = (UInt32)strlen(label); ! 1011: ! 1012: /* Start searching: */ ! 1013: status = SecKeychainSearchCreateFromAttributes(NULL, ! 1014: kSecCertificateItemClass, ! 1015: &attr_list, ! 1016: &search); ! 1017: if(status == noErr) { ! 1018: status = SecKeychainSearchCopyNext(search, ! 1019: (SecKeychainItemRef *)&cert); ! 1020: if(status == noErr && cert) { ! 1021: /* If we found a certificate, does it have a private key? */ ! 1022: status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k); ! 1023: CFRelease(cert); ! 1024: } ! 1025: } ! 1026: ! 1027: if(search) ! 1028: CFRelease(search); ! 1029: return status; ! 1030: } ! 1031: #endif /* CURL_SUPPORT_MAC_10_6 */ ! 1032: ! 1033: static OSStatus CopyIdentityWithLabel(char *label, ! 1034: SecIdentityRef *out_cert_and_key) ! 1035: { ! 1036: OSStatus status = errSecItemNotFound; ! 1037: ! 1038: #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS ! 1039: CFArrayRef keys_list; ! 1040: CFIndex keys_list_count; ! 1041: CFIndex i; ! 1042: CFStringRef common_name; ! 1043: ! 1044: /* SecItemCopyMatching() was introduced in iOS and Snow Leopard. ! 1045: kSecClassIdentity was introduced in Lion. If both exist, let's use them ! 1046: to find the certificate. */ ! 1047: if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) { ! 1048: CFTypeRef keys[5]; ! 1049: CFTypeRef values[5]; ! 1050: CFDictionaryRef query_dict; ! 1051: CFStringRef label_cf = CFStringCreateWithCString(NULL, label, ! 1052: kCFStringEncodingUTF8); ! 1053: ! 1054: /* Set up our search criteria and expected results: */ ! 1055: values[0] = kSecClassIdentity; /* we want a certificate and a key */ ! 1056: keys[0] = kSecClass; ! 1057: values[1] = kCFBooleanTrue; /* we want a reference */ ! 1058: keys[1] = kSecReturnRef; ! 1059: values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the ! 1060: * label matching below worked correctly */ ! 1061: keys[2] = kSecMatchLimit; ! 1062: /* identity searches need a SecPolicyRef in order to work */ ! 1063: values[3] = SecPolicyCreateSSL(false, NULL); ! 1064: keys[3] = kSecMatchPolicy; ! 1065: /* match the name of the certificate (doesn't work in macOS 10.12.1) */ ! 1066: values[4] = label_cf; ! 1067: keys[4] = kSecAttrLabel; ! 1068: query_dict = CFDictionaryCreate(NULL, (const void **)keys, ! 1069: (const void **)values, 5L, ! 1070: &kCFCopyStringDictionaryKeyCallBacks, ! 1071: &kCFTypeDictionaryValueCallBacks); ! 1072: CFRelease(values[3]); ! 1073: ! 1074: /* Do we have a match? */ ! 1075: status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list); ! 1076: ! 1077: /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity, ! 1078: * we need to find the correct identity ourselves */ ! 1079: if(status == noErr) { ! 1080: keys_list_count = CFArrayGetCount(keys_list); ! 1081: *out_cert_and_key = NULL; ! 1082: status = 1; ! 1083: for(i = 0; i<keys_list_count; i++) { ! 1084: OSStatus err = noErr; ! 1085: SecCertificateRef cert = NULL; ! 1086: SecIdentityRef identity = ! 1087: (SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i); ! 1088: err = SecIdentityCopyCertificate(identity, &cert); ! 1089: if(err == noErr) { ! 1090: #if CURL_BUILD_IOS ! 1091: common_name = SecCertificateCopySubjectSummary(cert); ! 1092: #elif CURL_BUILD_MAC_10_7 ! 1093: SecCertificateCopyCommonName(cert, &common_name); ! 1094: #endif ! 1095: if(CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) { ! 1096: CFRelease(cert); ! 1097: CFRelease(common_name); ! 1098: CFRetain(identity); ! 1099: *out_cert_and_key = identity; ! 1100: status = noErr; ! 1101: break; ! 1102: } ! 1103: CFRelease(common_name); ! 1104: } ! 1105: CFRelease(cert); ! 1106: } ! 1107: } ! 1108: ! 1109: if(keys_list) ! 1110: CFRelease(keys_list); ! 1111: CFRelease(query_dict); ! 1112: CFRelease(label_cf); ! 1113: } ! 1114: else { ! 1115: #if CURL_SUPPORT_MAC_10_6 ! 1116: /* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */ ! 1117: status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key); ! 1118: #endif /* CURL_SUPPORT_MAC_10_6 */ ! 1119: } ! 1120: #elif CURL_SUPPORT_MAC_10_6 ! 1121: /* For developers building on older cats, we have no choice but to fall back ! 1122: to SecKeychainSearch. */ ! 1123: status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key); ! 1124: #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ ! 1125: return status; ! 1126: } ! 1127: ! 1128: static OSStatus CopyIdentityFromPKCS12File(const char *cPath, ! 1129: const char *cPassword, ! 1130: SecIdentityRef *out_cert_and_key) ! 1131: { ! 1132: OSStatus status = errSecItemNotFound; ! 1133: CFURLRef pkcs_url = CFURLCreateFromFileSystemRepresentation(NULL, ! 1134: (const UInt8 *)cPath, strlen(cPath), false); ! 1135: CFStringRef password = cPassword ? CFStringCreateWithCString(NULL, ! 1136: cPassword, kCFStringEncodingUTF8) : NULL; ! 1137: CFDataRef pkcs_data = NULL; ! 1138: ! 1139: /* We can import P12 files on iOS or OS X 10.7 or later: */ ! 1140: /* These constants are documented as having first appeared in 10.6 but they ! 1141: raise linker errors when used on that cat for some reason. */ ! 1142: #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS ! 1143: if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data, ! 1144: NULL, NULL, &status)) { ! 1145: CFArrayRef items = NULL; ! 1146: ! 1147: /* On iOS SecPKCS12Import will never add the client certificate to the ! 1148: * Keychain. ! 1149: * ! 1150: * It gives us back a SecIdentityRef that we can use directly. */ ! 1151: #if CURL_BUILD_IOS ! 1152: const void *cKeys[] = {kSecImportExportPassphrase}; ! 1153: const void *cValues[] = {password}; ! 1154: CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues, ! 1155: password ? 1L : 0L, NULL, NULL); ! 1156: ! 1157: if(options != NULL) { ! 1158: status = SecPKCS12Import(pkcs_data, options, &items); ! 1159: CFRelease(options); ! 1160: } ! 1161: ! 1162: ! 1163: /* On macOS SecPKCS12Import will always add the client certificate to ! 1164: * the Keychain. ! 1165: * ! 1166: * As this doesn't match iOS, and apps may not want to see their client ! 1167: * certificate saved in the user's keychain, we use SecItemImport ! 1168: * with a NULL keychain to avoid importing it. ! 1169: * ! 1170: * This returns a SecCertificateRef from which we can construct a ! 1171: * SecIdentityRef. ! 1172: */ ! 1173: #elif CURL_BUILD_MAC_10_7 ! 1174: SecItemImportExportKeyParameters keyParams; ! 1175: SecExternalFormat inputFormat = kSecFormatPKCS12; ! 1176: SecExternalItemType inputType = kSecItemTypeCertificate; ! 1177: ! 1178: memset(&keyParams, 0x00, sizeof(keyParams)); ! 1179: keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; ! 1180: keyParams.passphrase = password; ! 1181: ! 1182: status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType, ! 1183: 0, &keyParams, NULL, &items); ! 1184: #endif ! 1185: ! 1186: ! 1187: /* Extract the SecIdentityRef */ ! 1188: if(status == errSecSuccess && items && CFArrayGetCount(items)) { ! 1189: CFIndex i, count; ! 1190: count = CFArrayGetCount(items); ! 1191: ! 1192: for(i = 0; i < count; i++) { ! 1193: CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(items, i); ! 1194: CFTypeID itemID = CFGetTypeID(item); ! 1195: ! 1196: if(itemID == CFDictionaryGetTypeID()) { ! 1197: CFTypeRef identity = (CFTypeRef) CFDictionaryGetValue( ! 1198: (CFDictionaryRef) item, ! 1199: kSecImportItemIdentity); ! 1200: CFRetain(identity); ! 1201: *out_cert_and_key = (SecIdentityRef) identity; ! 1202: break; ! 1203: } ! 1204: #if CURL_BUILD_MAC_10_7 ! 1205: else if(itemID == SecCertificateGetTypeID()) { ! 1206: status = SecIdentityCreateWithCertificate(NULL, ! 1207: (SecCertificateRef) item, ! 1208: out_cert_and_key); ! 1209: break; ! 1210: } ! 1211: #endif ! 1212: } ! 1213: } ! 1214: ! 1215: if(items) ! 1216: CFRelease(items); ! 1217: CFRelease(pkcs_data); ! 1218: } ! 1219: #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ ! 1220: if(password) ! 1221: CFRelease(password); ! 1222: CFRelease(pkcs_url); ! 1223: return status; ! 1224: } ! 1225: ! 1226: /* This code was borrowed from nss.c, with some modifications: ! 1227: * Determine whether the nickname passed in is a filename that needs to ! 1228: * be loaded as a PEM or a regular NSS nickname. ! 1229: * ! 1230: * returns 1 for a file ! 1231: * returns 0 for not a file ! 1232: */ ! 1233: CF_INLINE bool is_file(const char *filename) ! 1234: { ! 1235: struct_stat st; ! 1236: ! 1237: if(filename == NULL) ! 1238: return false; ! 1239: ! 1240: if(stat(filename, &st) == 0) ! 1241: return S_ISREG(st.st_mode); ! 1242: return false; ! 1243: } ! 1244: ! 1245: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS ! 1246: static CURLcode sectransp_version_from_curl(SSLProtocol *darwinver, ! 1247: long ssl_version) ! 1248: { ! 1249: switch(ssl_version) { ! 1250: case CURL_SSLVERSION_TLSv1_0: ! 1251: *darwinver = kTLSProtocol1; ! 1252: return CURLE_OK; ! 1253: case CURL_SSLVERSION_TLSv1_1: ! 1254: *darwinver = kTLSProtocol11; ! 1255: return CURLE_OK; ! 1256: case CURL_SSLVERSION_TLSv1_2: ! 1257: *darwinver = kTLSProtocol12; ! 1258: return CURLE_OK; ! 1259: case CURL_SSLVERSION_TLSv1_3: ! 1260: /* TLS 1.3 support first appeared in iOS 11 and macOS 10.13 */ ! 1261: #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 ! 1262: if(__builtin_available(macOS 10.13, iOS 11.0, *)) { ! 1263: *darwinver = kTLSProtocol13; ! 1264: return CURLE_OK; ! 1265: } ! 1266: #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && ! 1267: HAVE_BUILTIN_AVAILABLE == 1 */ ! 1268: break; ! 1269: } ! 1270: return CURLE_SSL_CONNECT_ERROR; ! 1271: } ! 1272: #endif ! 1273: ! 1274: static CURLcode ! 1275: set_ssl_version_min_max(struct connectdata *conn, int sockindex) ! 1276: { ! 1277: struct Curl_easy *data = conn->data; ! 1278: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 1279: struct ssl_backend_data *backend = connssl->backend; ! 1280: long ssl_version = SSL_CONN_CONFIG(version); ! 1281: long ssl_version_max = SSL_CONN_CONFIG(version_max); ! 1282: long max_supported_version_by_os; ! 1283: ! 1284: /* macOS 10.5-10.7 supported TLS 1.0 only. ! 1285: macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2. ! 1286: macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */ ! 1287: #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 ! 1288: if(__builtin_available(macOS 10.13, iOS 11.0, *)) { ! 1289: max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3; ! 1290: } ! 1291: else { ! 1292: max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2; ! 1293: } ! 1294: #else ! 1295: max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2; ! 1296: #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && ! 1297: HAVE_BUILTIN_AVAILABLE == 1 */ ! 1298: ! 1299: switch(ssl_version) { ! 1300: case CURL_SSLVERSION_DEFAULT: ! 1301: case CURL_SSLVERSION_TLSv1: ! 1302: ssl_version = CURL_SSLVERSION_TLSv1_0; ! 1303: break; ! 1304: } ! 1305: ! 1306: switch(ssl_version_max) { ! 1307: case CURL_SSLVERSION_MAX_NONE: ! 1308: case CURL_SSLVERSION_MAX_DEFAULT: ! 1309: ssl_version_max = max_supported_version_by_os; ! 1310: break; ! 1311: } ! 1312: ! 1313: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS ! 1314: if(SSLSetProtocolVersionMax != NULL) { ! 1315: SSLProtocol darwin_ver_min = kTLSProtocol1; ! 1316: SSLProtocol darwin_ver_max = kTLSProtocol1; ! 1317: CURLcode result = sectransp_version_from_curl(&darwin_ver_min, ! 1318: ssl_version); ! 1319: if(result) { ! 1320: failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); ! 1321: return result; ! 1322: } ! 1323: result = sectransp_version_from_curl(&darwin_ver_max, ! 1324: ssl_version_max >> 16); ! 1325: if(result) { ! 1326: failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); ! 1327: return result; ! 1328: } ! 1329: ! 1330: (void)SSLSetProtocolVersionMin(backend->ssl_ctx, darwin_ver_min); ! 1331: (void)SSLSetProtocolVersionMax(backend->ssl_ctx, darwin_ver_max); ! 1332: return result; ! 1333: } ! 1334: else { ! 1335: #if CURL_SUPPORT_MAC_10_8 ! 1336: long i = ssl_version; ! 1337: (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1338: kSSLProtocolAll, ! 1339: false); ! 1340: for(; i <= (ssl_version_max >> 16); i++) { ! 1341: switch(i) { ! 1342: case CURL_SSLVERSION_TLSv1_0: ! 1343: (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1344: kTLSProtocol1, ! 1345: true); ! 1346: break; ! 1347: case CURL_SSLVERSION_TLSv1_1: ! 1348: (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1349: kTLSProtocol11, ! 1350: true); ! 1351: break; ! 1352: case CURL_SSLVERSION_TLSv1_2: ! 1353: (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1354: kTLSProtocol12, ! 1355: true); ! 1356: break; ! 1357: case CURL_SSLVERSION_TLSv1_3: ! 1358: failf(data, "Your version of the OS does not support TLSv1.3"); ! 1359: return CURLE_SSL_CONNECT_ERROR; ! 1360: } ! 1361: } ! 1362: return CURLE_OK; ! 1363: #endif /* CURL_SUPPORT_MAC_10_8 */ ! 1364: } ! 1365: #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ ! 1366: failf(data, "Secure Transport: cannot set SSL protocol"); ! 1367: return CURLE_SSL_CONNECT_ERROR; ! 1368: } ! 1369: ! 1370: ! 1371: static CURLcode sectransp_connect_step1(struct connectdata *conn, ! 1372: int sockindex) ! 1373: { ! 1374: struct Curl_easy *data = conn->data; ! 1375: curl_socket_t sockfd = conn->sock[sockindex]; ! 1376: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 1377: struct ssl_backend_data *backend = connssl->backend; ! 1378: const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); ! 1379: const bool verifypeer = SSL_CONN_CONFIG(verifypeer); ! 1380: char * const ssl_cert = SSL_SET_OPTION(cert); ! 1381: const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : ! 1382: conn->host.name; ! 1383: const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; ! 1384: #ifdef ENABLE_IPV6 ! 1385: struct in6_addr addr; ! 1386: #else ! 1387: struct in_addr addr; ! 1388: #endif /* ENABLE_IPV6 */ ! 1389: size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i; ! 1390: SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL; ! 1391: OSStatus err = noErr; ! 1392: #if CURL_BUILD_MAC ! 1393: int darwinver_maj = 0, darwinver_min = 0; ! 1394: ! 1395: GetDarwinVersionNumber(&darwinver_maj, &darwinver_min); ! 1396: #endif /* CURL_BUILD_MAC */ ! 1397: ! 1398: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS ! 1399: if(SSLCreateContext != NULL) { /* use the newer API if available */ ! 1400: if(backend->ssl_ctx) ! 1401: CFRelease(backend->ssl_ctx); ! 1402: backend->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); ! 1403: if(!backend->ssl_ctx) { ! 1404: failf(data, "SSL: couldn't create a context!"); ! 1405: return CURLE_OUT_OF_MEMORY; ! 1406: } ! 1407: } ! 1408: else { ! 1409: /* The old ST API does not exist under iOS, so don't compile it: */ ! 1410: #if CURL_SUPPORT_MAC_10_8 ! 1411: if(backend->ssl_ctx) ! 1412: (void)SSLDisposeContext(backend->ssl_ctx); ! 1413: err = SSLNewContext(false, &(backend->ssl_ctx)); ! 1414: if(err != noErr) { ! 1415: failf(data, "SSL: couldn't create a context: OSStatus %d", err); ! 1416: return CURLE_OUT_OF_MEMORY; ! 1417: } ! 1418: #endif /* CURL_SUPPORT_MAC_10_8 */ ! 1419: } ! 1420: #else ! 1421: if(backend->ssl_ctx) ! 1422: (void)SSLDisposeContext(backend->ssl_ctx); ! 1423: err = SSLNewContext(false, &(backend->ssl_ctx)); ! 1424: if(err != noErr) { ! 1425: failf(data, "SSL: couldn't create a context: OSStatus %d", err); ! 1426: return CURLE_OUT_OF_MEMORY; ! 1427: } ! 1428: #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ ! 1429: backend->ssl_write_buffered_length = 0UL; /* reset buffered write length */ ! 1430: ! 1431: /* check to see if we've been told to use an explicit SSL/TLS version */ ! 1432: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS ! 1433: if(SSLSetProtocolVersionMax != NULL) { ! 1434: switch(conn->ssl_config.version) { ! 1435: case CURL_SSLVERSION_TLSv1: ! 1436: (void)SSLSetProtocolVersionMin(backend->ssl_ctx, kTLSProtocol1); ! 1437: #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 ! 1438: if(__builtin_available(macOS 10.13, iOS 11.0, *)) { ! 1439: (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol13); ! 1440: } ! 1441: else { ! 1442: (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12); ! 1443: } ! 1444: #else ! 1445: (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12); ! 1446: #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && ! 1447: HAVE_BUILTIN_AVAILABLE == 1 */ ! 1448: break; ! 1449: case CURL_SSLVERSION_DEFAULT: ! 1450: case CURL_SSLVERSION_TLSv1_0: ! 1451: case CURL_SSLVERSION_TLSv1_1: ! 1452: case CURL_SSLVERSION_TLSv1_2: ! 1453: case CURL_SSLVERSION_TLSv1_3: ! 1454: { ! 1455: CURLcode result = set_ssl_version_min_max(conn, sockindex); ! 1456: if(result != CURLE_OK) ! 1457: return result; ! 1458: break; ! 1459: } ! 1460: case CURL_SSLVERSION_SSLv3: ! 1461: err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol3); ! 1462: if(err != noErr) { ! 1463: failf(data, "Your version of the OS does not support SSLv3"); ! 1464: return CURLE_SSL_CONNECT_ERROR; ! 1465: } ! 1466: (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol3); ! 1467: break; ! 1468: case CURL_SSLVERSION_SSLv2: ! 1469: err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol2); ! 1470: if(err != noErr) { ! 1471: failf(data, "Your version of the OS does not support SSLv2"); ! 1472: return CURLE_SSL_CONNECT_ERROR; ! 1473: } ! 1474: (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol2); ! 1475: break; ! 1476: default: ! 1477: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); ! 1478: return CURLE_SSL_CONNECT_ERROR; ! 1479: } ! 1480: } ! 1481: else { ! 1482: #if CURL_SUPPORT_MAC_10_8 ! 1483: (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1484: kSSLProtocolAll, ! 1485: false); ! 1486: switch(conn->ssl_config.version) { ! 1487: case CURL_SSLVERSION_DEFAULT: ! 1488: case CURL_SSLVERSION_TLSv1: ! 1489: (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1490: kTLSProtocol1, ! 1491: true); ! 1492: (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1493: kTLSProtocol11, ! 1494: true); ! 1495: (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1496: kTLSProtocol12, ! 1497: true); ! 1498: break; ! 1499: case CURL_SSLVERSION_TLSv1_0: ! 1500: case CURL_SSLVERSION_TLSv1_1: ! 1501: case CURL_SSLVERSION_TLSv1_2: ! 1502: case CURL_SSLVERSION_TLSv1_3: ! 1503: { ! 1504: CURLcode result = set_ssl_version_min_max(conn, sockindex); ! 1505: if(result != CURLE_OK) ! 1506: return result; ! 1507: break; ! 1508: } ! 1509: case CURL_SSLVERSION_SSLv3: ! 1510: err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1511: kSSLProtocol3, ! 1512: true); ! 1513: if(err != noErr) { ! 1514: failf(data, "Your version of the OS does not support SSLv3"); ! 1515: return CURLE_SSL_CONNECT_ERROR; ! 1516: } ! 1517: break; ! 1518: case CURL_SSLVERSION_SSLv2: ! 1519: err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1520: kSSLProtocol2, ! 1521: true); ! 1522: if(err != noErr) { ! 1523: failf(data, "Your version of the OS does not support SSLv2"); ! 1524: return CURLE_SSL_CONNECT_ERROR; ! 1525: } ! 1526: break; ! 1527: default: ! 1528: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); ! 1529: return CURLE_SSL_CONNECT_ERROR; ! 1530: } ! 1531: #endif /* CURL_SUPPORT_MAC_10_8 */ ! 1532: } ! 1533: #else ! 1534: if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) { ! 1535: failf(data, "Your version of the OS does not support to set maximum" ! 1536: " SSL/TLS version"); ! 1537: return CURLE_SSL_CONNECT_ERROR; ! 1538: } ! 1539: (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocolAll, false); ! 1540: switch(conn->ssl_config.version) { ! 1541: case CURL_SSLVERSION_DEFAULT: ! 1542: case CURL_SSLVERSION_TLSv1: ! 1543: case CURL_SSLVERSION_TLSv1_0: ! 1544: (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1545: kTLSProtocol1, ! 1546: true); ! 1547: break; ! 1548: case CURL_SSLVERSION_TLSv1_1: ! 1549: failf(data, "Your version of the OS does not support TLSv1.1"); ! 1550: return CURLE_SSL_CONNECT_ERROR; ! 1551: case CURL_SSLVERSION_TLSv1_2: ! 1552: failf(data, "Your version of the OS does not support TLSv1.2"); ! 1553: return CURLE_SSL_CONNECT_ERROR; ! 1554: case CURL_SSLVERSION_TLSv1_3: ! 1555: failf(data, "Your version of the OS does not support TLSv1.3"); ! 1556: return CURLE_SSL_CONNECT_ERROR; ! 1557: case CURL_SSLVERSION_SSLv2: ! 1558: err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1559: kSSLProtocol2, ! 1560: true); ! 1561: if(err != noErr) { ! 1562: failf(data, "Your version of the OS does not support SSLv2"); ! 1563: return CURLE_SSL_CONNECT_ERROR; ! 1564: } ! 1565: break; ! 1566: case CURL_SSLVERSION_SSLv3: ! 1567: err = SSLSetProtocolVersionEnabled(backend->ssl_ctx, ! 1568: kSSLProtocol3, ! 1569: true); ! 1570: if(err != noErr) { ! 1571: failf(data, "Your version of the OS does not support SSLv3"); ! 1572: return CURLE_SSL_CONNECT_ERROR; ! 1573: } ! 1574: break; ! 1575: default: ! 1576: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); ! 1577: return CURLE_SSL_CONNECT_ERROR; ! 1578: } ! 1579: #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ ! 1580: ! 1581: #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 ! 1582: if(conn->bits.tls_enable_alpn) { ! 1583: if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { ! 1584: CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0, ! 1585: &kCFTypeArrayCallBacks); ! 1586: ! 1587: #ifdef USE_NGHTTP2 ! 1588: if(data->set.httpversion >= CURL_HTTP_VERSION_2 && ! 1589: (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) { ! 1590: CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID)); ! 1591: infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); ! 1592: } ! 1593: #endif ! 1594: ! 1595: CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1)); ! 1596: infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); ! 1597: ! 1598: /* expects length prefixed preference ordered list of protocols in wire ! 1599: * format ! 1600: */ ! 1601: err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr); ! 1602: if(err != noErr) ! 1603: infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n", ! 1604: err); ! 1605: CFRelease(alpnArr); ! 1606: } ! 1607: } ! 1608: #endif ! 1609: ! 1610: if(SSL_SET_OPTION(key)) { ! 1611: infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure " ! 1612: "Transport. The private key must be in the Keychain.\n"); ! 1613: } ! 1614: ! 1615: if(ssl_cert) { ! 1616: SecIdentityRef cert_and_key = NULL; ! 1617: bool is_cert_file = is_file(ssl_cert); ! 1618: ! 1619: /* User wants to authenticate with a client cert. Look for it: ! 1620: If we detect that this is a file on disk, then let's load it. ! 1621: Otherwise, assume that the user wants to use an identity loaded ! 1622: from the Keychain. */ ! 1623: if(is_cert_file) { ! 1624: if(!SSL_SET_OPTION(cert_type)) ! 1625: infof(data, "WARNING: SSL: Certificate type not set, assuming " ! 1626: "PKCS#12 format.\n"); ! 1627: else if(strncmp(SSL_SET_OPTION(cert_type), "P12", ! 1628: strlen(SSL_SET_OPTION(cert_type))) != 0) ! 1629: infof(data, "WARNING: SSL: The Security framework only supports " ! 1630: "loading identities that are in PKCS#12 format.\n"); ! 1631: ! 1632: err = CopyIdentityFromPKCS12File(ssl_cert, ! 1633: SSL_SET_OPTION(key_passwd), &cert_and_key); ! 1634: } ! 1635: else ! 1636: err = CopyIdentityWithLabel(ssl_cert, &cert_and_key); ! 1637: ! 1638: if(err == noErr && cert_and_key) { ! 1639: SecCertificateRef cert = NULL; ! 1640: CFTypeRef certs_c[1]; ! 1641: CFArrayRef certs; ! 1642: ! 1643: /* If we found one, print it out: */ ! 1644: err = SecIdentityCopyCertificate(cert_and_key, &cert); ! 1645: if(err == noErr) { ! 1646: char *certp; ! 1647: CURLcode result = CopyCertSubject(data, cert, &certp); ! 1648: if(!result) { ! 1649: infof(data, "Client certificate: %s\n", certp); ! 1650: free(certp); ! 1651: } ! 1652: ! 1653: CFRelease(cert); ! 1654: if(result == CURLE_PEER_FAILED_VERIFICATION) ! 1655: return CURLE_SSL_CERTPROBLEM; ! 1656: if(result) ! 1657: return result; ! 1658: } ! 1659: certs_c[0] = cert_and_key; ! 1660: certs = CFArrayCreate(NULL, (const void **)certs_c, 1L, ! 1661: &kCFTypeArrayCallBacks); ! 1662: err = SSLSetCertificate(backend->ssl_ctx, certs); ! 1663: if(certs) ! 1664: CFRelease(certs); ! 1665: if(err != noErr) { ! 1666: failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err); ! 1667: return CURLE_SSL_CERTPROBLEM; ! 1668: } ! 1669: CFRelease(cert_and_key); ! 1670: } ! 1671: else { ! 1672: switch(err) { ! 1673: case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */ ! 1674: failf(data, "SSL: Incorrect password for the certificate \"%s\" " ! 1675: "and its private key.", ssl_cert); ! 1676: break; ! 1677: case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */ ! 1678: failf(data, "SSL: Couldn't make sense of the data in the " ! 1679: "certificate \"%s\" and its private key.", ! 1680: ssl_cert); ! 1681: break; ! 1682: case -25260: /* errSecPassphraseRequired */ ! 1683: failf(data, "SSL The certificate \"%s\" requires a password.", ! 1684: ssl_cert); ! 1685: break; ! 1686: case errSecItemNotFound: ! 1687: failf(data, "SSL: Can't find the certificate \"%s\" and its private " ! 1688: "key in the Keychain.", ssl_cert); ! 1689: break; ! 1690: default: ! 1691: failf(data, "SSL: Can't load the certificate \"%s\" and its private " ! 1692: "key: OSStatus %d", ssl_cert, err); ! 1693: break; ! 1694: } ! 1695: return CURLE_SSL_CERTPROBLEM; ! 1696: } ! 1697: } ! 1698: ! 1699: /* SSL always tries to verify the peer, this only says whether it should ! 1700: * fail to connect if the verification fails, or if it should continue ! 1701: * anyway. In the latter case the result of the verification is checked with ! 1702: * SSL_get_verify_result() below. */ ! 1703: #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS ! 1704: /* Snow Leopard introduced the SSLSetSessionOption() function, but due to ! 1705: a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag ! 1706: works, it doesn't work as expected under Snow Leopard, Lion or ! 1707: Mountain Lion. ! 1708: So we need to call SSLSetEnableCertVerify() on those older cats in order ! 1709: to disable certificate validation if the user turned that off. ! 1710: (SecureTransport will always validate the certificate chain by ! 1711: default.) ! 1712: Note: ! 1713: Darwin 11.x.x is Lion (10.7) ! 1714: Darwin 12.x.x is Mountain Lion (10.8) ! 1715: Darwin 13.x.x is Mavericks (10.9) ! 1716: Darwin 14.x.x is Yosemite (10.10) ! 1717: Darwin 15.x.x is El Capitan (10.11) ! 1718: */ ! 1719: #if CURL_BUILD_MAC ! 1720: if(SSLSetSessionOption != NULL && darwinver_maj >= 13) { ! 1721: #else ! 1722: if(SSLSetSessionOption != NULL) { ! 1723: #endif /* CURL_BUILD_MAC */ ! 1724: bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile; ! 1725: err = SSLSetSessionOption(backend->ssl_ctx, ! 1726: kSSLSessionOptionBreakOnServerAuth, ! 1727: break_on_auth); ! 1728: if(err != noErr) { ! 1729: failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err); ! 1730: return CURLE_SSL_CONNECT_ERROR; ! 1731: } ! 1732: } ! 1733: else { ! 1734: #if CURL_SUPPORT_MAC_10_8 ! 1735: err = SSLSetEnableCertVerify(backend->ssl_ctx, ! 1736: conn->ssl_config.verifypeer?true:false); ! 1737: if(err != noErr) { ! 1738: failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); ! 1739: return CURLE_SSL_CONNECT_ERROR; ! 1740: } ! 1741: #endif /* CURL_SUPPORT_MAC_10_8 */ ! 1742: } ! 1743: #else ! 1744: err = SSLSetEnableCertVerify(backend->ssl_ctx, ! 1745: conn->ssl_config.verifypeer?true:false); ! 1746: if(err != noErr) { ! 1747: failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err); ! 1748: return CURLE_SSL_CONNECT_ERROR; ! 1749: } ! 1750: #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */ ! 1751: ! 1752: if(ssl_cafile && verifypeer) { ! 1753: bool is_cert_file = is_file(ssl_cafile); ! 1754: ! 1755: if(!is_cert_file) { ! 1756: failf(data, "SSL: can't load CA certificate file %s", ssl_cafile); ! 1757: return CURLE_SSL_CACERT_BADFILE; ! 1758: } ! 1759: } ! 1760: ! 1761: /* Configure hostname check. SNI is used if available. ! 1762: * Both hostname check and SNI require SSLSetPeerDomainName(). ! 1763: * Also: the verifyhost setting influences SNI usage */ ! 1764: if(conn->ssl_config.verifyhost) { ! 1765: err = SSLSetPeerDomainName(backend->ssl_ctx, hostname, ! 1766: strlen(hostname)); ! 1767: ! 1768: if(err != noErr) { ! 1769: infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n", ! 1770: err); ! 1771: } ! 1772: ! 1773: if((Curl_inet_pton(AF_INET, hostname, &addr)) ! 1774: #ifdef ENABLE_IPV6 ! 1775: || (Curl_inet_pton(AF_INET6, hostname, &addr)) ! 1776: #endif ! 1777: ) { ! 1778: infof(data, "WARNING: using IP address, SNI is being disabled by " ! 1779: "the OS.\n"); ! 1780: } ! 1781: } ! 1782: else { ! 1783: infof(data, "WARNING: disabling hostname validation also disables SNI.\n"); ! 1784: } ! 1785: ! 1786: /* Disable cipher suites that ST supports but are not safe. These ciphers ! 1787: are unlikely to be used in any case since ST gives other ciphers a much ! 1788: higher priority, but it's probably better that we not connect at all than ! 1789: to give the user a false sense of security if the server only supports ! 1790: insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */ ! 1791: err = SSLGetNumberSupportedCiphers(backend->ssl_ctx, &all_ciphers_count); ! 1792: if(err != noErr) { ! 1793: failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d", ! 1794: err); ! 1795: return CURLE_SSL_CIPHER; ! 1796: } ! 1797: all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); ! 1798: if(!all_ciphers) { ! 1799: failf(data, "SSL: Failed to allocate memory for all ciphers"); ! 1800: return CURLE_OUT_OF_MEMORY; ! 1801: } ! 1802: allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite)); ! 1803: if(!allowed_ciphers) { ! 1804: Curl_safefree(all_ciphers); ! 1805: failf(data, "SSL: Failed to allocate memory for allowed ciphers"); ! 1806: return CURLE_OUT_OF_MEMORY; ! 1807: } ! 1808: err = SSLGetSupportedCiphers(backend->ssl_ctx, all_ciphers, ! 1809: &all_ciphers_count); ! 1810: if(err != noErr) { ! 1811: Curl_safefree(all_ciphers); ! 1812: Curl_safefree(allowed_ciphers); ! 1813: return CURLE_SSL_CIPHER; ! 1814: } ! 1815: for(i = 0UL ; i < all_ciphers_count ; i++) { ! 1816: #if CURL_BUILD_MAC ! 1817: /* There's a known bug in early versions of Mountain Lion where ST's ECC ! 1818: ciphers (cipher suite 0xC001 through 0xC032) simply do not work. ! 1819: Work around the problem here by disabling those ciphers if we are ! 1820: running in an affected version of OS X. */ ! 1821: if(darwinver_maj == 12 && darwinver_min <= 3 && ! 1822: all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) { ! 1823: continue; ! 1824: } ! 1825: #endif /* CURL_BUILD_MAC */ ! 1826: switch(all_ciphers[i]) { ! 1827: /* Disable NULL ciphersuites: */ ! 1828: case SSL_NULL_WITH_NULL_NULL: ! 1829: case SSL_RSA_WITH_NULL_MD5: ! 1830: case SSL_RSA_WITH_NULL_SHA: ! 1831: case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */ ! 1832: case SSL_FORTEZZA_DMS_WITH_NULL_SHA: ! 1833: case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */ ! 1834: case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */ ! 1835: case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */ ! 1836: case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */ ! 1837: case 0x002C: /* TLS_PSK_WITH_NULL_SHA */ ! 1838: case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */ ! 1839: case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */ ! 1840: case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */ ! 1841: case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */ ! 1842: case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */ ! 1843: case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */ ! 1844: case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */ ! 1845: case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */ ! 1846: /* Disable anonymous ciphersuites: */ ! 1847: case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5: ! 1848: case SSL_DH_anon_WITH_RC4_128_MD5: ! 1849: case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: ! 1850: case SSL_DH_anon_WITH_DES_CBC_SHA: ! 1851: case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA: ! 1852: case TLS_DH_anon_WITH_AES_128_CBC_SHA: ! 1853: case TLS_DH_anon_WITH_AES_256_CBC_SHA: ! 1854: case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */ ! 1855: case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */ ! 1856: case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */ ! 1857: case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */ ! 1858: case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */ ! 1859: case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */ ! 1860: case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */ ! 1861: case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */ ! 1862: case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */ ! 1863: /* Disable weak key ciphersuites: */ ! 1864: case SSL_RSA_EXPORT_WITH_RC4_40_MD5: ! 1865: case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: ! 1866: case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: ! 1867: case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: ! 1868: case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: ! 1869: case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: ! 1870: case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: ! 1871: case SSL_RSA_WITH_DES_CBC_SHA: ! 1872: case SSL_DH_DSS_WITH_DES_CBC_SHA: ! 1873: case SSL_DH_RSA_WITH_DES_CBC_SHA: ! 1874: case SSL_DHE_DSS_WITH_DES_CBC_SHA: ! 1875: case SSL_DHE_RSA_WITH_DES_CBC_SHA: ! 1876: /* Disable IDEA: */ ! 1877: case SSL_RSA_WITH_IDEA_CBC_SHA: ! 1878: case SSL_RSA_WITH_IDEA_CBC_MD5: ! 1879: /* Disable RC4: */ ! 1880: case SSL_RSA_WITH_RC4_128_MD5: ! 1881: case SSL_RSA_WITH_RC4_128_SHA: ! 1882: case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */ ! 1883: case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/ ! 1884: case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */ ! 1885: case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */ ! 1886: case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */ ! 1887: case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */ ! 1888: case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */ ! 1889: break; ! 1890: default: /* enable everything else */ ! 1891: allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i]; ! 1892: break; ! 1893: } ! 1894: } ! 1895: err = SSLSetEnabledCiphers(backend->ssl_ctx, allowed_ciphers, ! 1896: allowed_ciphers_count); ! 1897: Curl_safefree(all_ciphers); ! 1898: Curl_safefree(allowed_ciphers); ! 1899: if(err != noErr) { ! 1900: failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err); ! 1901: return CURLE_SSL_CIPHER; ! 1902: } ! 1903: ! 1904: #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 ! 1905: /* We want to enable 1/n-1 when using a CBC cipher unless the user ! 1906: specifically doesn't want us doing that: */ ! 1907: if(SSLSetSessionOption != NULL) { ! 1908: SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionSendOneByteRecord, ! 1909: !data->set.ssl.enable_beast); ! 1910: SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionFalseStart, ! 1911: data->set.ssl.falsestart); /* false start support */ ! 1912: } ! 1913: #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */ ! 1914: ! 1915: /* Check if there's a cached ID we can/should use here! */ ! 1916: if(SSL_SET_OPTION(primary.sessionid)) { ! 1917: char *ssl_sessionid; ! 1918: size_t ssl_sessionid_len; ! 1919: ! 1920: Curl_ssl_sessionid_lock(conn); ! 1921: if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid, ! 1922: &ssl_sessionid_len, sockindex)) { ! 1923: /* we got a session id, use it! */ ! 1924: err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len); ! 1925: Curl_ssl_sessionid_unlock(conn); ! 1926: if(err != noErr) { ! 1927: failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); ! 1928: return CURLE_SSL_CONNECT_ERROR; ! 1929: } ! 1930: /* Informational message */ ! 1931: infof(data, "SSL re-using session ID\n"); ! 1932: } ! 1933: /* If there isn't one, then let's make one up! This has to be done prior ! 1934: to starting the handshake. */ ! 1935: else { ! 1936: CURLcode result; ! 1937: ssl_sessionid = ! 1938: aprintf("%s:%d:%d:%s:%hu", ssl_cafile, ! 1939: verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port); ! 1940: ssl_sessionid_len = strlen(ssl_sessionid); ! 1941: ! 1942: err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len); ! 1943: if(err != noErr) { ! 1944: Curl_ssl_sessionid_unlock(conn); ! 1945: failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err); ! 1946: return CURLE_SSL_CONNECT_ERROR; ! 1947: } ! 1948: ! 1949: result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len, ! 1950: sockindex); ! 1951: Curl_ssl_sessionid_unlock(conn); ! 1952: if(result) { ! 1953: failf(data, "failed to store ssl session"); ! 1954: return result; ! 1955: } ! 1956: } ! 1957: } ! 1958: ! 1959: err = SSLSetIOFuncs(backend->ssl_ctx, SocketRead, SocketWrite); ! 1960: if(err != noErr) { ! 1961: failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err); ! 1962: return CURLE_SSL_CONNECT_ERROR; ! 1963: } ! 1964: ! 1965: /* pass the raw socket into the SSL layers */ ! 1966: /* We need to store the FD in a constant memory address, because ! 1967: * SSLSetConnection() will not copy that address. I've found that ! 1968: * conn->sock[sockindex] may change on its own. */ ! 1969: backend->ssl_sockfd = sockfd; ! 1970: err = SSLSetConnection(backend->ssl_ctx, connssl); ! 1971: if(err != noErr) { ! 1972: failf(data, "SSL: SSLSetConnection() failed: %d", err); ! 1973: return CURLE_SSL_CONNECT_ERROR; ! 1974: } ! 1975: ! 1976: connssl->connecting_state = ssl_connect_2; ! 1977: return CURLE_OK; ! 1978: } ! 1979: ! 1980: static long pem_to_der(const char *in, unsigned char **out, size_t *outlen) ! 1981: { ! 1982: char *sep_start, *sep_end, *cert_start, *cert_end; ! 1983: size_t i, j, err; ! 1984: size_t len; ! 1985: unsigned char *b64; ! 1986: ! 1987: /* Jump through the separators at the beginning of the certificate. */ ! 1988: sep_start = strstr(in, "-----"); ! 1989: if(sep_start == NULL) ! 1990: return 0; ! 1991: cert_start = strstr(sep_start + 1, "-----"); ! 1992: if(cert_start == NULL) ! 1993: return -1; ! 1994: ! 1995: cert_start += 5; ! 1996: ! 1997: /* Find separator after the end of the certificate. */ ! 1998: cert_end = strstr(cert_start, "-----"); ! 1999: if(cert_end == NULL) ! 2000: return -1; ! 2001: ! 2002: sep_end = strstr(cert_end + 1, "-----"); ! 2003: if(sep_end == NULL) ! 2004: return -1; ! 2005: sep_end += 5; ! 2006: ! 2007: len = cert_end - cert_start; ! 2008: b64 = malloc(len + 1); ! 2009: if(!b64) ! 2010: return -1; ! 2011: ! 2012: /* Create base64 string without linefeeds. */ ! 2013: for(i = 0, j = 0; i < len; i++) { ! 2014: if(cert_start[i] != '\r' && cert_start[i] != '\n') ! 2015: b64[j++] = cert_start[i]; ! 2016: } ! 2017: b64[j] = '\0'; ! 2018: ! 2019: err = Curl_base64_decode((const char *)b64, out, outlen); ! 2020: free(b64); ! 2021: if(err) { ! 2022: free(*out); ! 2023: return -1; ! 2024: } ! 2025: ! 2026: return sep_end - in; ! 2027: } ! 2028: ! 2029: static int read_cert(const char *file, unsigned char **out, size_t *outlen) ! 2030: { ! 2031: int fd; ! 2032: ssize_t n, len = 0, cap = 512; ! 2033: unsigned char buf[512], *data; ! 2034: ! 2035: fd = open(file, 0); ! 2036: if(fd < 0) ! 2037: return -1; ! 2038: ! 2039: data = malloc(cap); ! 2040: if(!data) { ! 2041: close(fd); ! 2042: return -1; ! 2043: } ! 2044: ! 2045: for(;;) { ! 2046: n = read(fd, buf, sizeof(buf)); ! 2047: if(n < 0) { ! 2048: close(fd); ! 2049: free(data); ! 2050: return -1; ! 2051: } ! 2052: else if(n == 0) { ! 2053: close(fd); ! 2054: break; ! 2055: } ! 2056: ! 2057: if(len + n >= cap) { ! 2058: cap *= 2; ! 2059: data = Curl_saferealloc(data, cap); ! 2060: if(!data) { ! 2061: close(fd); ! 2062: return -1; ! 2063: } ! 2064: } ! 2065: ! 2066: memcpy(data + len, buf, n); ! 2067: len += n; ! 2068: } ! 2069: data[len] = '\0'; ! 2070: ! 2071: *out = data; ! 2072: *outlen = len; ! 2073: ! 2074: return 0; ! 2075: } ! 2076: ! 2077: static int append_cert_to_array(struct Curl_easy *data, ! 2078: unsigned char *buf, size_t buflen, ! 2079: CFMutableArrayRef array) ! 2080: { ! 2081: CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen); ! 2082: char *certp; ! 2083: CURLcode result; ! 2084: if(!certdata) { ! 2085: failf(data, "SSL: failed to allocate array for CA certificate"); ! 2086: return CURLE_OUT_OF_MEMORY; ! 2087: } ! 2088: ! 2089: SecCertificateRef cacert = ! 2090: SecCertificateCreateWithData(kCFAllocatorDefault, certdata); ! 2091: CFRelease(certdata); ! 2092: if(!cacert) { ! 2093: failf(data, "SSL: failed to create SecCertificate from CA certificate"); ! 2094: return CURLE_SSL_CACERT_BADFILE; ! 2095: } ! 2096: ! 2097: /* Check if cacert is valid. */ ! 2098: result = CopyCertSubject(data, cacert, &certp); ! 2099: switch(result) { ! 2100: case CURLE_OK: ! 2101: break; ! 2102: case CURLE_PEER_FAILED_VERIFICATION: ! 2103: return CURLE_SSL_CACERT_BADFILE; ! 2104: case CURLE_OUT_OF_MEMORY: ! 2105: default: ! 2106: return result; ! 2107: } ! 2108: free(certp); ! 2109: ! 2110: CFArrayAppendValue(array, cacert); ! 2111: CFRelease(cacert); ! 2112: ! 2113: return CURLE_OK; ! 2114: } ! 2115: ! 2116: static CURLcode verify_cert(const char *cafile, struct Curl_easy *data, ! 2117: SSLContextRef ctx) ! 2118: { ! 2119: int n = 0, rc; ! 2120: long res; ! 2121: unsigned char *certbuf, *der; ! 2122: size_t buflen, derlen, offset = 0; ! 2123: ! 2124: if(read_cert(cafile, &certbuf, &buflen) < 0) { ! 2125: failf(data, "SSL: failed to read or invalid CA certificate"); ! 2126: return CURLE_SSL_CACERT_BADFILE; ! 2127: } ! 2128: ! 2129: /* ! 2130: * Certbuf now contains the contents of the certificate file, which can be ! 2131: * - a single DER certificate, ! 2132: * - a single PEM certificate or ! 2133: * - a bunch of PEM certificates (certificate bundle). ! 2134: * ! 2135: * Go through certbuf, and convert any PEM certificate in it into DER ! 2136: * format. ! 2137: */ ! 2138: CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, ! 2139: &kCFTypeArrayCallBacks); ! 2140: if(array == NULL) { ! 2141: free(certbuf); ! 2142: failf(data, "SSL: out of memory creating CA certificate array"); ! 2143: return CURLE_OUT_OF_MEMORY; ! 2144: } ! 2145: ! 2146: while(offset < buflen) { ! 2147: n++; ! 2148: ! 2149: /* ! 2150: * Check if the certificate is in PEM format, and convert it to DER. If ! 2151: * this fails, we assume the certificate is in DER format. ! 2152: */ ! 2153: res = pem_to_der((const char *)certbuf + offset, &der, &derlen); ! 2154: if(res < 0) { ! 2155: free(certbuf); ! 2156: CFRelease(array); ! 2157: failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle", ! 2158: n, offset); ! 2159: return CURLE_SSL_CACERT_BADFILE; ! 2160: } ! 2161: offset += res; ! 2162: ! 2163: if(res == 0 && offset == 0) { ! 2164: /* This is not a PEM file, probably a certificate in DER format. */ ! 2165: rc = append_cert_to_array(data, certbuf, buflen, array); ! 2166: free(certbuf); ! 2167: if(rc != CURLE_OK) { ! 2168: CFRelease(array); ! 2169: return rc; ! 2170: } ! 2171: break; ! 2172: } ! 2173: else if(res == 0) { ! 2174: /* No more certificates in the bundle. */ ! 2175: free(certbuf); ! 2176: break; ! 2177: } ! 2178: ! 2179: rc = append_cert_to_array(data, der, derlen, array); ! 2180: free(der); ! 2181: if(rc != CURLE_OK) { ! 2182: free(certbuf); ! 2183: CFRelease(array); ! 2184: return rc; ! 2185: } ! 2186: } ! 2187: ! 2188: SecTrustRef trust; ! 2189: OSStatus ret = SSLCopyPeerTrust(ctx, &trust); ! 2190: if(trust == NULL) { ! 2191: failf(data, "SSL: error getting certificate chain"); ! 2192: CFRelease(array); ! 2193: return CURLE_PEER_FAILED_VERIFICATION; ! 2194: } ! 2195: else if(ret != noErr) { ! 2196: CFRelease(array); ! 2197: failf(data, "SSLCopyPeerTrust() returned error %d", ret); ! 2198: return CURLE_PEER_FAILED_VERIFICATION; ! 2199: } ! 2200: ! 2201: ret = SecTrustSetAnchorCertificates(trust, array); ! 2202: if(ret != noErr) { ! 2203: CFRelease(array); ! 2204: CFRelease(trust); ! 2205: failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret); ! 2206: return CURLE_PEER_FAILED_VERIFICATION; ! 2207: } ! 2208: ret = SecTrustSetAnchorCertificatesOnly(trust, true); ! 2209: if(ret != noErr) { ! 2210: CFRelease(array); ! 2211: CFRelease(trust); ! 2212: failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret); ! 2213: return CURLE_PEER_FAILED_VERIFICATION; ! 2214: } ! 2215: ! 2216: SecTrustResultType trust_eval = 0; ! 2217: ret = SecTrustEvaluate(trust, &trust_eval); ! 2218: CFRelease(array); ! 2219: CFRelease(trust); ! 2220: if(ret != noErr) { ! 2221: failf(data, "SecTrustEvaluate() returned error %d", ret); ! 2222: return CURLE_PEER_FAILED_VERIFICATION; ! 2223: } ! 2224: ! 2225: switch(trust_eval) { ! 2226: case kSecTrustResultUnspecified: ! 2227: case kSecTrustResultProceed: ! 2228: return CURLE_OK; ! 2229: ! 2230: case kSecTrustResultRecoverableTrustFailure: ! 2231: case kSecTrustResultDeny: ! 2232: default: ! 2233: failf(data, "SSL: certificate verification failed (result: %d)", ! 2234: trust_eval); ! 2235: return CURLE_PEER_FAILED_VERIFICATION; ! 2236: } ! 2237: } ! 2238: ! 2239: #ifdef SECTRANSP_PINNEDPUBKEY ! 2240: static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, ! 2241: SSLContextRef ctx, ! 2242: const char *pinnedpubkey) ! 2243: { /* Scratch */ ! 2244: size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24; ! 2245: unsigned char *pubkey = NULL, *realpubkey = NULL; ! 2246: const unsigned char *spkiHeader = NULL; ! 2247: CFDataRef publicKeyBits = NULL; ! 2248: ! 2249: /* Result is returned to caller */ ! 2250: CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; ! 2251: ! 2252: /* if a path wasn't specified, don't pin */ ! 2253: if(!pinnedpubkey) ! 2254: return CURLE_OK; ! 2255: ! 2256: ! 2257: if(!ctx) ! 2258: return result; ! 2259: ! 2260: do { ! 2261: SecTrustRef trust; ! 2262: OSStatus ret = SSLCopyPeerTrust(ctx, &trust); ! 2263: if(ret != noErr || trust == NULL) ! 2264: break; ! 2265: ! 2266: SecKeyRef keyRef = SecTrustCopyPublicKey(trust); ! 2267: CFRelease(trust); ! 2268: if(keyRef == NULL) ! 2269: break; ! 2270: ! 2271: #ifdef SECTRANSP_PINNEDPUBKEY_V1 ! 2272: ! 2273: publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL); ! 2274: CFRelease(keyRef); ! 2275: if(publicKeyBits == NULL) ! 2276: break; ! 2277: ! 2278: #elif SECTRANSP_PINNEDPUBKEY_V2 ! 2279: ! 2280: OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL, ! 2281: &publicKeyBits); ! 2282: CFRelease(keyRef); ! 2283: if(success != errSecSuccess || publicKeyBits == NULL) ! 2284: break; ! 2285: ! 2286: #endif /* SECTRANSP_PINNEDPUBKEY_V2 */ ! 2287: ! 2288: pubkeylen = CFDataGetLength(publicKeyBits); ! 2289: pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits); ! 2290: ! 2291: switch(pubkeylen) { ! 2292: case 526: ! 2293: /* 4096 bit RSA pubkeylen == 526 */ ! 2294: spkiHeader = rsa4096SpkiHeader; ! 2295: break; ! 2296: case 270: ! 2297: /* 2048 bit RSA pubkeylen == 270 */ ! 2298: spkiHeader = rsa2048SpkiHeader; ! 2299: break; ! 2300: #ifdef SECTRANSP_PINNEDPUBKEY_V1 ! 2301: case 65: ! 2302: /* ecDSA secp256r1 pubkeylen == 65 */ ! 2303: spkiHeader = ecDsaSecp256r1SpkiHeader; ! 2304: spkiHeaderLength = 26; ! 2305: break; ! 2306: case 97: ! 2307: /* ecDSA secp384r1 pubkeylen == 97 */ ! 2308: spkiHeader = ecDsaSecp384r1SpkiHeader; ! 2309: spkiHeaderLength = 23; ! 2310: break; ! 2311: default: ! 2312: infof(data, "SSL: unhandled public key length: %d\n", pubkeylen); ! 2313: #elif SECTRANSP_PINNEDPUBKEY_V2 ! 2314: default: ! 2315: /* ecDSA secp256r1 pubkeylen == 91 header already included? ! 2316: * ecDSA secp384r1 header already included too ! 2317: * we assume rest of algorithms do same, so do nothing ! 2318: */ ! 2319: result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey, ! 2320: pubkeylen); ! 2321: #endif /* SECTRANSP_PINNEDPUBKEY_V2 */ ! 2322: continue; /* break from loop */ ! 2323: } ! 2324: ! 2325: realpubkeylen = pubkeylen + spkiHeaderLength; ! 2326: realpubkey = malloc(realpubkeylen); ! 2327: if(!realpubkey) ! 2328: break; ! 2329: ! 2330: memcpy(realpubkey, spkiHeader, spkiHeaderLength); ! 2331: memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen); ! 2332: ! 2333: result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey, ! 2334: realpubkeylen); ! 2335: ! 2336: } while(0); ! 2337: ! 2338: Curl_safefree(realpubkey); ! 2339: if(publicKeyBits != NULL) ! 2340: CFRelease(publicKeyBits); ! 2341: ! 2342: return result; ! 2343: } ! 2344: #endif /* SECTRANSP_PINNEDPUBKEY */ ! 2345: ! 2346: static CURLcode ! 2347: sectransp_connect_step2(struct connectdata *conn, int sockindex) ! 2348: { ! 2349: struct Curl_easy *data = conn->data; ! 2350: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 2351: struct ssl_backend_data *backend = connssl->backend; ! 2352: OSStatus err; ! 2353: SSLCipherSuite cipher; ! 2354: SSLProtocol protocol = 0; ! 2355: const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : ! 2356: conn->host.name; ! 2357: ! 2358: DEBUGASSERT(ssl_connect_2 == connssl->connecting_state ! 2359: || ssl_connect_2_reading == connssl->connecting_state ! 2360: || ssl_connect_2_writing == connssl->connecting_state); ! 2361: ! 2362: /* Here goes nothing: */ ! 2363: err = SSLHandshake(backend->ssl_ctx); ! 2364: ! 2365: if(err != noErr) { ! 2366: switch(err) { ! 2367: case errSSLWouldBlock: /* they're not done with us yet */ ! 2368: connssl->connecting_state = backend->ssl_direction ? ! 2369: ssl_connect_2_writing : ssl_connect_2_reading; ! 2370: return CURLE_OK; ! 2371: ! 2372: /* The below is errSSLServerAuthCompleted; it's not defined in ! 2373: Leopard's headers */ ! 2374: case -9841: ! 2375: if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { ! 2376: CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data, ! 2377: backend->ssl_ctx); ! 2378: if(result) ! 2379: return result; ! 2380: } ! 2381: /* the documentation says we need to call SSLHandshake() again */ ! 2382: return sectransp_connect_step2(conn, sockindex); ! 2383: ! 2384: /* Problem with encrypt / decrypt */ ! 2385: case errSSLPeerDecodeError: ! 2386: failf(data, "Decode failed"); ! 2387: break; ! 2388: case errSSLDecryptionFail: ! 2389: case errSSLPeerDecryptionFail: ! 2390: failf(data, "Decryption failed"); ! 2391: break; ! 2392: case errSSLPeerDecryptError: ! 2393: failf(data, "A decryption error occurred"); ! 2394: break; ! 2395: case errSSLBadCipherSuite: ! 2396: failf(data, "A bad SSL cipher suite was encountered"); ! 2397: break; ! 2398: case errSSLCrypto: ! 2399: failf(data, "An underlying cryptographic error was encountered"); ! 2400: break; ! 2401: #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9 ! 2402: case errSSLWeakPeerEphemeralDHKey: ! 2403: failf(data, "Indicates a weak ephemeral Diffie-Hellman key"); ! 2404: break; ! 2405: #endif ! 2406: ! 2407: /* Problem with the message record validation */ ! 2408: case errSSLBadRecordMac: ! 2409: case errSSLPeerBadRecordMac: ! 2410: failf(data, "A record with a bad message authentication code (MAC) " ! 2411: "was encountered"); ! 2412: break; ! 2413: case errSSLRecordOverflow: ! 2414: case errSSLPeerRecordOverflow: ! 2415: failf(data, "A record overflow occurred"); ! 2416: break; ! 2417: ! 2418: /* Problem with zlib decompression */ ! 2419: case errSSLPeerDecompressFail: ! 2420: failf(data, "Decompression failed"); ! 2421: break; ! 2422: ! 2423: /* Problem with access */ ! 2424: case errSSLPeerAccessDenied: ! 2425: failf(data, "Access was denied"); ! 2426: break; ! 2427: case errSSLPeerInsufficientSecurity: ! 2428: failf(data, "There is insufficient security for this operation"); ! 2429: break; ! 2430: ! 2431: /* These are all certificate problems with the server: */ ! 2432: case errSSLXCertChainInvalid: ! 2433: failf(data, "SSL certificate problem: Invalid certificate chain"); ! 2434: return CURLE_PEER_FAILED_VERIFICATION; ! 2435: case errSSLUnknownRootCert: ! 2436: failf(data, "SSL certificate problem: Untrusted root certificate"); ! 2437: return CURLE_PEER_FAILED_VERIFICATION; ! 2438: case errSSLNoRootCert: ! 2439: failf(data, "SSL certificate problem: No root certificate"); ! 2440: return CURLE_PEER_FAILED_VERIFICATION; ! 2441: case errSSLCertNotYetValid: ! 2442: failf(data, "SSL certificate problem: The certificate chain had a " ! 2443: "certificate that is not yet valid"); ! 2444: return CURLE_PEER_FAILED_VERIFICATION; ! 2445: case errSSLCertExpired: ! 2446: case errSSLPeerCertExpired: ! 2447: failf(data, "SSL certificate problem: Certificate chain had an " ! 2448: "expired certificate"); ! 2449: return CURLE_PEER_FAILED_VERIFICATION; ! 2450: case errSSLBadCert: ! 2451: case errSSLPeerBadCert: ! 2452: failf(data, "SSL certificate problem: Couldn't understand the server " ! 2453: "certificate format"); ! 2454: return CURLE_PEER_FAILED_VERIFICATION; ! 2455: case errSSLPeerUnsupportedCert: ! 2456: failf(data, "SSL certificate problem: An unsupported certificate " ! 2457: "format was encountered"); ! 2458: return CURLE_PEER_FAILED_VERIFICATION; ! 2459: case errSSLPeerCertRevoked: ! 2460: failf(data, "SSL certificate problem: The certificate was revoked"); ! 2461: return CURLE_PEER_FAILED_VERIFICATION; ! 2462: case errSSLPeerCertUnknown: ! 2463: failf(data, "SSL certificate problem: The certificate is unknown"); ! 2464: return CURLE_PEER_FAILED_VERIFICATION; ! 2465: ! 2466: /* These are all certificate problems with the client: */ ! 2467: case errSecAuthFailed: ! 2468: failf(data, "SSL authentication failed"); ! 2469: break; ! 2470: case errSSLPeerHandshakeFail: ! 2471: failf(data, "SSL peer handshake failed, the server most likely " ! 2472: "requires a client certificate to connect"); ! 2473: break; ! 2474: case errSSLPeerUnknownCA: ! 2475: failf(data, "SSL server rejected the client certificate due to " ! 2476: "the certificate being signed by an unknown certificate " ! 2477: "authority"); ! 2478: break; ! 2479: ! 2480: /* This error is raised if the server's cert didn't match the server's ! 2481: host name: */ ! 2482: case errSSLHostNameMismatch: ! 2483: failf(data, "SSL certificate peer verification failed, the " ! 2484: "certificate did not match \"%s\"\n", conn->host.dispname); ! 2485: return CURLE_PEER_FAILED_VERIFICATION; ! 2486: ! 2487: /* Problem with SSL / TLS negotiation */ ! 2488: case errSSLNegotiation: ! 2489: failf(data, "Could not negotiate an SSL cipher suite with the server"); ! 2490: break; ! 2491: case errSSLBadConfiguration: ! 2492: failf(data, "A configuration error occurred"); ! 2493: break; ! 2494: case errSSLProtocol: ! 2495: failf(data, "SSL protocol error"); ! 2496: break; ! 2497: case errSSLPeerProtocolVersion: ! 2498: failf(data, "A bad protocol version was encountered"); ! 2499: break; ! 2500: case errSSLPeerNoRenegotiation: ! 2501: failf(data, "No renegotiation is allowed"); ! 2502: break; ! 2503: ! 2504: /* Generic handshake errors: */ ! 2505: case errSSLConnectionRefused: ! 2506: failf(data, "Server dropped the connection during the SSL handshake"); ! 2507: break; ! 2508: case errSSLClosedAbort: ! 2509: failf(data, "Server aborted the SSL handshake"); ! 2510: break; ! 2511: case errSSLClosedGraceful: ! 2512: failf(data, "The connection closed gracefully"); ! 2513: break; ! 2514: case errSSLClosedNoNotify: ! 2515: failf(data, "The server closed the session with no notification"); ! 2516: break; ! 2517: /* Sometimes paramErr happens with buggy ciphers: */ ! 2518: case paramErr: ! 2519: case errSSLInternal: ! 2520: case errSSLPeerInternalError: ! 2521: failf(data, "Internal SSL engine error encountered during the " ! 2522: "SSL handshake"); ! 2523: break; ! 2524: case errSSLFatalAlert: ! 2525: failf(data, "Fatal SSL engine error encountered during the SSL " ! 2526: "handshake"); ! 2527: break; ! 2528: /* Unclassified error */ ! 2529: case errSSLBufferOverflow: ! 2530: failf(data, "An insufficient buffer was provided"); ! 2531: break; ! 2532: case errSSLIllegalParam: ! 2533: failf(data, "An illegal parameter was encountered"); ! 2534: break; ! 2535: case errSSLModuleAttach: ! 2536: failf(data, "Module attach failure"); ! 2537: break; ! 2538: case errSSLSessionNotFound: ! 2539: failf(data, "An attempt to restore an unknown session failed"); ! 2540: break; ! 2541: case errSSLPeerExportRestriction: ! 2542: failf(data, "An export restriction occurred"); ! 2543: break; ! 2544: case errSSLPeerUserCancelled: ! 2545: failf(data, "The user canceled the operation"); ! 2546: break; ! 2547: case errSSLPeerUnexpectedMsg: ! 2548: failf(data, "Peer rejected unexpected message"); ! 2549: break; ! 2550: #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9 ! 2551: /* Treaing non-fatal error as fatal like before */ ! 2552: case errSSLClientHelloReceived: ! 2553: failf(data, "A non-fatal result for providing a server name " ! 2554: "indication"); ! 2555: break; ! 2556: #endif ! 2557: ! 2558: /* Error codes defined in the enum but should never be returned. ! 2559: We list them here just in case. */ ! 2560: #if CURL_BUILD_MAC_10_6 ! 2561: /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */ ! 2562: case errSSLClientCertRequested: ! 2563: failf(data, "The server has requested a client certificate"); ! 2564: break; ! 2565: #endif ! 2566: #if CURL_BUILD_MAC_10_9 ! 2567: /* Alias for errSSLLast, end of error range */ ! 2568: case errSSLUnexpectedRecord: ! 2569: failf(data, "Unexpected (skipped) record in DTLS"); ! 2570: break; ! 2571: #endif ! 2572: default: ! 2573: /* May also return codes listed in Security Framework Result Codes */ ! 2574: failf(data, "Unknown SSL protocol error in connection to %s:%d", ! 2575: hostname, err); ! 2576: break; ! 2577: } ! 2578: return CURLE_SSL_CONNECT_ERROR; ! 2579: } ! 2580: else { ! 2581: /* we have been connected fine, we're not waiting for anything else. */ ! 2582: connssl->connecting_state = ssl_connect_3; ! 2583: ! 2584: #ifdef SECTRANSP_PINNEDPUBKEY ! 2585: if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) { ! 2586: CURLcode result = pkp_pin_peer_pubkey(data, backend->ssl_ctx, ! 2587: data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]); ! 2588: if(result) { ! 2589: failf(data, "SSL: public key does not match pinned public key!"); ! 2590: return result; ! 2591: } ! 2592: } ! 2593: #endif /* SECTRANSP_PINNEDPUBKEY */ ! 2594: ! 2595: /* Informational message */ ! 2596: (void)SSLGetNegotiatedCipher(backend->ssl_ctx, &cipher); ! 2597: (void)SSLGetNegotiatedProtocolVersion(backend->ssl_ctx, &protocol); ! 2598: switch(protocol) { ! 2599: case kSSLProtocol2: ! 2600: infof(data, "SSL 2.0 connection using %s\n", ! 2601: SSLCipherNameForNumber(cipher)); ! 2602: break; ! 2603: case kSSLProtocol3: ! 2604: infof(data, "SSL 3.0 connection using %s\n", ! 2605: SSLCipherNameForNumber(cipher)); ! 2606: break; ! 2607: case kTLSProtocol1: ! 2608: infof(data, "TLS 1.0 connection using %s\n", ! 2609: TLSCipherNameForNumber(cipher)); ! 2610: break; ! 2611: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS ! 2612: case kTLSProtocol11: ! 2613: infof(data, "TLS 1.1 connection using %s\n", ! 2614: TLSCipherNameForNumber(cipher)); ! 2615: break; ! 2616: case kTLSProtocol12: ! 2617: infof(data, "TLS 1.2 connection using %s\n", ! 2618: TLSCipherNameForNumber(cipher)); ! 2619: break; ! 2620: #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ ! 2621: #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 ! 2622: case kTLSProtocol13: ! 2623: infof(data, "TLS 1.3 connection using %s\n", ! 2624: TLSCipherNameForNumber(cipher)); ! 2625: break; ! 2626: #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */ ! 2627: default: ! 2628: infof(data, "Unknown protocol connection\n"); ! 2629: break; ! 2630: } ! 2631: ! 2632: #if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1 ! 2633: if(conn->bits.tls_enable_alpn) { ! 2634: if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) { ! 2635: CFArrayRef alpnArr = NULL; ! 2636: CFStringRef chosenProtocol = NULL; ! 2637: err = SSLCopyALPNProtocols(backend->ssl_ctx, &alpnArr); ! 2638: ! 2639: if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1) ! 2640: chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0); ! 2641: ! 2642: #ifdef USE_NGHTTP2 ! 2643: if(chosenProtocol && ! 2644: !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID), ! 2645: 0)) { ! 2646: conn->negnpn = CURL_HTTP_VERSION_2; ! 2647: } ! 2648: else ! 2649: #endif ! 2650: if(chosenProtocol && ! 2651: !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) { ! 2652: conn->negnpn = CURL_HTTP_VERSION_1_1; ! 2653: } ! 2654: else ! 2655: infof(data, "ALPN, server did not agree to a protocol\n"); ! 2656: ! 2657: Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ? ! 2658: BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); ! 2659: ! 2660: /* chosenProtocol is a reference to the string within alpnArr ! 2661: and doesn't need to be freed separately */ ! 2662: if(alpnArr) ! 2663: CFRelease(alpnArr); ! 2664: } ! 2665: } ! 2666: #endif ! 2667: ! 2668: return CURLE_OK; ! 2669: } ! 2670: } ! 2671: ! 2672: #ifndef CURL_DISABLE_VERBOSE_STRINGS ! 2673: /* This should be called during step3 of the connection at the earliest */ ! 2674: static void ! 2675: show_verbose_server_cert(struct connectdata *conn, ! 2676: int sockindex) ! 2677: { ! 2678: struct Curl_easy *data = conn->data; ! 2679: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 2680: struct ssl_backend_data *backend = connssl->backend; ! 2681: CFArrayRef server_certs = NULL; ! 2682: SecCertificateRef server_cert; ! 2683: OSStatus err; ! 2684: CFIndex i, count; ! 2685: SecTrustRef trust = NULL; ! 2686: ! 2687: if(!backend->ssl_ctx) ! 2688: return; ! 2689: ! 2690: #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS ! 2691: #if CURL_BUILD_IOS ! 2692: #pragma unused(server_certs) ! 2693: err = SSLCopyPeerTrust(backend->ssl_ctx, &trust); ! 2694: /* For some reason, SSLCopyPeerTrust() can return noErr and yet return ! 2695: a null trust, so be on guard for that: */ ! 2696: if(err == noErr && trust) { ! 2697: count = SecTrustGetCertificateCount(trust); ! 2698: for(i = 0L ; i < count ; i++) { ! 2699: CURLcode result; ! 2700: char *certp; ! 2701: server_cert = SecTrustGetCertificateAtIndex(trust, i); ! 2702: result = CopyCertSubject(data, server_cert, &certp); ! 2703: if(!result) { ! 2704: infof(data, "Server certificate: %s\n", certp); ! 2705: free(certp); ! 2706: } ! 2707: } ! 2708: CFRelease(trust); ! 2709: } ! 2710: #else ! 2711: /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion. ! 2712: The function SecTrustGetCertificateAtIndex() is officially present ! 2713: in Lion, but it is unfortunately also present in Snow Leopard as ! 2714: private API and doesn't work as expected. So we have to look for ! 2715: a different symbol to make sure this code is only executed under ! 2716: Lion or later. */ ! 2717: if(SecTrustEvaluateAsync != NULL) { ! 2718: #pragma unused(server_certs) ! 2719: err = SSLCopyPeerTrust(backend->ssl_ctx, &trust); ! 2720: /* For some reason, SSLCopyPeerTrust() can return noErr and yet return ! 2721: a null trust, so be on guard for that: */ ! 2722: if(err == noErr && trust) { ! 2723: count = SecTrustGetCertificateCount(trust); ! 2724: for(i = 0L ; i < count ; i++) { ! 2725: char *certp; ! 2726: CURLcode result; ! 2727: server_cert = SecTrustGetCertificateAtIndex(trust, i); ! 2728: result = CopyCertSubject(data, server_cert, &certp); ! 2729: if(!result) { ! 2730: infof(data, "Server certificate: %s\n", certp); ! 2731: free(certp); ! 2732: } ! 2733: } ! 2734: CFRelease(trust); ! 2735: } ! 2736: } ! 2737: else { ! 2738: #if CURL_SUPPORT_MAC_10_8 ! 2739: err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs); ! 2740: /* Just in case SSLCopyPeerCertificates() returns null too... */ ! 2741: if(err == noErr && server_certs) { ! 2742: count = CFArrayGetCount(server_certs); ! 2743: for(i = 0L ; i < count ; i++) { ! 2744: char *certp; ! 2745: CURLcode result; ! 2746: server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, ! 2747: i); ! 2748: result = CopyCertSubject(data, server_cert, &certp); ! 2749: if(!result) { ! 2750: infof(data, "Server certificate: %s\n", certp); ! 2751: free(certp); ! 2752: } ! 2753: } ! 2754: CFRelease(server_certs); ! 2755: } ! 2756: #endif /* CURL_SUPPORT_MAC_10_8 */ ! 2757: } ! 2758: #endif /* CURL_BUILD_IOS */ ! 2759: #else ! 2760: #pragma unused(trust) ! 2761: err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs); ! 2762: if(err == noErr) { ! 2763: count = CFArrayGetCount(server_certs); ! 2764: for(i = 0L ; i < count ; i++) { ! 2765: CURLcode result; ! 2766: char *certp; ! 2767: server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i); ! 2768: result = CopyCertSubject(data, server_cert, &certp); ! 2769: if(!result) { ! 2770: infof(data, "Server certificate: %s\n", certp); ! 2771: free(certp); ! 2772: } ! 2773: } ! 2774: CFRelease(server_certs); ! 2775: } ! 2776: #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */ ! 2777: } ! 2778: #endif /* !CURL_DISABLE_VERBOSE_STRINGS */ ! 2779: ! 2780: static CURLcode ! 2781: sectransp_connect_step3(struct connectdata *conn, ! 2782: int sockindex) ! 2783: { ! 2784: struct Curl_easy *data = conn->data; ! 2785: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 2786: ! 2787: /* There is no step 3! ! 2788: * Well, okay, if verbose mode is on, let's print the details of the ! 2789: * server certificates. */ ! 2790: #ifndef CURL_DISABLE_VERBOSE_STRINGS ! 2791: if(data->set.verbose) ! 2792: show_verbose_server_cert(conn, sockindex); ! 2793: #endif ! 2794: ! 2795: connssl->connecting_state = ssl_connect_done; ! 2796: return CURLE_OK; ! 2797: } ! 2798: ! 2799: static Curl_recv sectransp_recv; ! 2800: static Curl_send sectransp_send; ! 2801: ! 2802: static CURLcode ! 2803: sectransp_connect_common(struct connectdata *conn, ! 2804: int sockindex, ! 2805: bool nonblocking, ! 2806: bool *done) ! 2807: { ! 2808: CURLcode result; ! 2809: struct Curl_easy *data = conn->data; ! 2810: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 2811: curl_socket_t sockfd = conn->sock[sockindex]; ! 2812: timediff_t timeout_ms; ! 2813: int what; ! 2814: ! 2815: /* check if the connection has already been established */ ! 2816: if(ssl_connection_complete == connssl->state) { ! 2817: *done = TRUE; ! 2818: return CURLE_OK; ! 2819: } ! 2820: ! 2821: if(ssl_connect_1 == connssl->connecting_state) { ! 2822: /* Find out how much more time we're allowed */ ! 2823: timeout_ms = Curl_timeleft(data, NULL, TRUE); ! 2824: ! 2825: if(timeout_ms < 0) { ! 2826: /* no need to continue if time already is up */ ! 2827: failf(data, "SSL connection timeout"); ! 2828: return CURLE_OPERATION_TIMEDOUT; ! 2829: } ! 2830: ! 2831: result = sectransp_connect_step1(conn, sockindex); ! 2832: if(result) ! 2833: return result; ! 2834: } ! 2835: ! 2836: while(ssl_connect_2 == connssl->connecting_state || ! 2837: ssl_connect_2_reading == connssl->connecting_state || ! 2838: ssl_connect_2_writing == connssl->connecting_state) { ! 2839: ! 2840: /* check allowed time left */ ! 2841: timeout_ms = Curl_timeleft(data, NULL, TRUE); ! 2842: ! 2843: if(timeout_ms < 0) { ! 2844: /* no need to continue if time already is up */ ! 2845: failf(data, "SSL connection timeout"); ! 2846: return CURLE_OPERATION_TIMEDOUT; ! 2847: } ! 2848: ! 2849: /* if ssl is expecting something, check if it's available. */ ! 2850: if(connssl->connecting_state == ssl_connect_2_reading || ! 2851: connssl->connecting_state == ssl_connect_2_writing) { ! 2852: ! 2853: curl_socket_t writefd = ssl_connect_2_writing == ! 2854: connssl->connecting_state?sockfd:CURL_SOCKET_BAD; ! 2855: curl_socket_t readfd = ssl_connect_2_reading == ! 2856: connssl->connecting_state?sockfd:CURL_SOCKET_BAD; ! 2857: ! 2858: what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, ! 2859: nonblocking?0:(time_t)timeout_ms); ! 2860: if(what < 0) { ! 2861: /* fatal error */ ! 2862: failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); ! 2863: return CURLE_SSL_CONNECT_ERROR; ! 2864: } ! 2865: else if(0 == what) { ! 2866: if(nonblocking) { ! 2867: *done = FALSE; ! 2868: return CURLE_OK; ! 2869: } ! 2870: else { ! 2871: /* timeout */ ! 2872: failf(data, "SSL connection timeout"); ! 2873: return CURLE_OPERATION_TIMEDOUT; ! 2874: } ! 2875: } ! 2876: /* socket is readable or writable */ ! 2877: } ! 2878: ! 2879: /* Run transaction, and return to the caller if it failed or if this ! 2880: * connection is done nonblocking and this loop would execute again. This ! 2881: * permits the owner of a multi handle to abort a connection attempt ! 2882: * before step2 has completed while ensuring that a client using select() ! 2883: * or epoll() will always have a valid fdset to wait on. ! 2884: */ ! 2885: result = sectransp_connect_step2(conn, sockindex); ! 2886: if(result || (nonblocking && ! 2887: (ssl_connect_2 == connssl->connecting_state || ! 2888: ssl_connect_2_reading == connssl->connecting_state || ! 2889: ssl_connect_2_writing == connssl->connecting_state))) ! 2890: return result; ! 2891: ! 2892: } /* repeat step2 until all transactions are done. */ ! 2893: ! 2894: ! 2895: if(ssl_connect_3 == connssl->connecting_state) { ! 2896: result = sectransp_connect_step3(conn, sockindex); ! 2897: if(result) ! 2898: return result; ! 2899: } ! 2900: ! 2901: if(ssl_connect_done == connssl->connecting_state) { ! 2902: connssl->state = ssl_connection_complete; ! 2903: conn->recv[sockindex] = sectransp_recv; ! 2904: conn->send[sockindex] = sectransp_send; ! 2905: *done = TRUE; ! 2906: } ! 2907: else ! 2908: *done = FALSE; ! 2909: ! 2910: /* Reset our connect state machine */ ! 2911: connssl->connecting_state = ssl_connect_1; ! 2912: ! 2913: return CURLE_OK; ! 2914: } ! 2915: ! 2916: static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn, ! 2917: int sockindex, bool *done) ! 2918: { ! 2919: return sectransp_connect_common(conn, sockindex, TRUE, done); ! 2920: } ! 2921: ! 2922: static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex) ! 2923: { ! 2924: CURLcode result; ! 2925: bool done = FALSE; ! 2926: ! 2927: result = sectransp_connect_common(conn, sockindex, FALSE, &done); ! 2928: ! 2929: if(result) ! 2930: return result; ! 2931: ! 2932: DEBUGASSERT(done); ! 2933: ! 2934: return CURLE_OK; ! 2935: } ! 2936: ! 2937: static void Curl_sectransp_close(struct connectdata *conn, int sockindex) ! 2938: { ! 2939: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 2940: struct ssl_backend_data *backend = connssl->backend; ! 2941: ! 2942: if(backend->ssl_ctx) { ! 2943: (void)SSLClose(backend->ssl_ctx); ! 2944: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS ! 2945: if(SSLCreateContext != NULL) ! 2946: CFRelease(backend->ssl_ctx); ! 2947: #if CURL_SUPPORT_MAC_10_8 ! 2948: else ! 2949: (void)SSLDisposeContext(backend->ssl_ctx); ! 2950: #endif /* CURL_SUPPORT_MAC_10_8 */ ! 2951: #else ! 2952: (void)SSLDisposeContext(backend->ssl_ctx); ! 2953: #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */ ! 2954: backend->ssl_ctx = NULL; ! 2955: } ! 2956: backend->ssl_sockfd = 0; ! 2957: } ! 2958: ! 2959: static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex) ! 2960: { ! 2961: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 2962: struct ssl_backend_data *backend = connssl->backend; ! 2963: struct Curl_easy *data = conn->data; ! 2964: ssize_t nread; ! 2965: int what; ! 2966: int rc; ! 2967: char buf[120]; ! 2968: ! 2969: if(!backend->ssl_ctx) ! 2970: return 0; ! 2971: ! 2972: #ifndef CURL_DISABLE_FTP ! 2973: if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE) ! 2974: return 0; ! 2975: #endif ! 2976: ! 2977: Curl_sectransp_close(conn, sockindex); ! 2978: ! 2979: rc = 0; ! 2980: ! 2981: what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT); ! 2982: ! 2983: for(;;) { ! 2984: if(what < 0) { ! 2985: /* anything that gets here is fatally bad */ ! 2986: failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); ! 2987: rc = -1; ! 2988: break; ! 2989: } ! 2990: ! 2991: if(!what) { /* timeout */ ! 2992: failf(data, "SSL shutdown timeout"); ! 2993: break; ! 2994: } ! 2995: ! 2996: /* Something to read, let's do it and hope that it is the close ! 2997: notify alert from the server. No way to SSL_Read now, so use read(). */ ! 2998: ! 2999: nread = read(conn->sock[sockindex], buf, sizeof(buf)); ! 3000: ! 3001: if(nread < 0) { ! 3002: failf(data, "read: %s", strerror(errno)); ! 3003: rc = -1; ! 3004: } ! 3005: ! 3006: if(nread <= 0) ! 3007: break; ! 3008: ! 3009: what = SOCKET_READABLE(conn->sock[sockindex], 0); ! 3010: } ! 3011: ! 3012: return rc; ! 3013: } ! 3014: ! 3015: static void Curl_sectransp_session_free(void *ptr) ! 3016: { ! 3017: /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a ! 3018: cached session ID inside the Security framework. There is a private ! 3019: function that does this, but I don't want to have to explain to you why I ! 3020: got your application rejected from the App Store due to the use of a ! 3021: private API, so the best we can do is free up our own char array that we ! 3022: created way back in sectransp_connect_step1... */ ! 3023: Curl_safefree(ptr); ! 3024: } ! 3025: ! 3026: static size_t Curl_sectransp_version(char *buffer, size_t size) ! 3027: { ! 3028: return msnprintf(buffer, size, "SecureTransport"); ! 3029: } ! 3030: ! 3031: /* ! 3032: * This function uses SSLGetSessionState to determine connection status. ! 3033: * ! 3034: * Return codes: ! 3035: * 1 means the connection is still in place ! 3036: * 0 means the connection has been closed ! 3037: * -1 means the connection status is unknown ! 3038: */ ! 3039: static int Curl_sectransp_check_cxn(struct connectdata *conn) ! 3040: { ! 3041: struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET]; ! 3042: struct ssl_backend_data *backend = connssl->backend; ! 3043: OSStatus err; ! 3044: SSLSessionState state; ! 3045: ! 3046: if(backend->ssl_ctx) { ! 3047: err = SSLGetSessionState(backend->ssl_ctx, &state); ! 3048: if(err == noErr) ! 3049: return state == kSSLConnected || state == kSSLHandshake; ! 3050: return -1; ! 3051: } ! 3052: return 0; ! 3053: } ! 3054: ! 3055: static bool Curl_sectransp_data_pending(const struct connectdata *conn, ! 3056: int connindex) ! 3057: { ! 3058: const struct ssl_connect_data *connssl = &conn->ssl[connindex]; ! 3059: struct ssl_backend_data *backend = connssl->backend; ! 3060: OSStatus err; ! 3061: size_t buffer; ! 3062: ! 3063: if(backend->ssl_ctx) { /* SSL is in use */ ! 3064: err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer); ! 3065: if(err == noErr) ! 3066: return buffer > 0UL; ! 3067: return false; ! 3068: } ! 3069: else ! 3070: return false; ! 3071: } ! 3072: ! 3073: static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM, ! 3074: unsigned char *entropy, size_t length) ! 3075: { ! 3076: /* arc4random_buf() isn't available on cats older than Lion, so let's ! 3077: do this manually for the benefit of the older cats. */ ! 3078: size_t i; ! 3079: u_int32_t random_number = 0; ! 3080: ! 3081: (void)data; ! 3082: ! 3083: for(i = 0 ; i < length ; i++) { ! 3084: if(i % sizeof(u_int32_t) == 0) ! 3085: random_number = arc4random(); ! 3086: entropy[i] = random_number & 0xFF; ! 3087: random_number >>= 8; ! 3088: } ! 3089: i = random_number = 0; ! 3090: return CURLE_OK; ! 3091: } ! 3092: ! 3093: static CURLcode Curl_sectransp_md5sum(unsigned char *tmp, /* input */ ! 3094: size_t tmplen, ! 3095: unsigned char *md5sum, /* output */ ! 3096: size_t md5len) ! 3097: { ! 3098: (void)md5len; ! 3099: (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum); ! 3100: return CURLE_OK; ! 3101: } ! 3102: ! 3103: static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */ ! 3104: size_t tmplen, ! 3105: unsigned char *sha256sum, /* output */ ! 3106: size_t sha256len) ! 3107: { ! 3108: assert(sha256len >= CURL_SHA256_DIGEST_LENGTH); ! 3109: (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum); ! 3110: return CURLE_OK; ! 3111: } ! 3112: ! 3113: static bool Curl_sectransp_false_start(void) ! 3114: { ! 3115: #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 ! 3116: if(SSLSetSessionOption != NULL) ! 3117: return TRUE; ! 3118: #endif ! 3119: return FALSE; ! 3120: } ! 3121: ! 3122: static ssize_t sectransp_send(struct connectdata *conn, ! 3123: int sockindex, ! 3124: const void *mem, ! 3125: size_t len, ! 3126: CURLcode *curlcode) ! 3127: { ! 3128: /*struct Curl_easy *data = conn->data;*/ ! 3129: struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ! 3130: struct ssl_backend_data *backend = connssl->backend; ! 3131: size_t processed = 0UL; ! 3132: OSStatus err; ! 3133: ! 3134: /* The SSLWrite() function works a little differently than expected. The ! 3135: fourth argument (processed) is currently documented in Apple's ! 3136: documentation as: "On return, the length, in bytes, of the data actually ! 3137: written." ! 3138: ! 3139: Now, one could interpret that as "written to the socket," but actually, ! 3140: it returns the amount of data that was written to a buffer internal to ! 3141: the SSLContextRef instead. So it's possible for SSLWrite() to return ! 3142: errSSLWouldBlock and a number of bytes "written" because those bytes were ! 3143: encrypted and written to a buffer, not to the socket. ! 3144: ! 3145: So if this happens, then we need to keep calling SSLWrite() over and ! 3146: over again with no new data until it quits returning errSSLWouldBlock. */ ! 3147: ! 3148: /* Do we have buffered data to write from the last time we were called? */ ! 3149: if(backend->ssl_write_buffered_length) { ! 3150: /* Write the buffered data: */ ! 3151: err = SSLWrite(backend->ssl_ctx, NULL, 0UL, &processed); ! 3152: switch(err) { ! 3153: case noErr: ! 3154: /* processed is always going to be 0 because we didn't write to ! 3155: the buffer, so return how much was written to the socket */ ! 3156: processed = backend->ssl_write_buffered_length; ! 3157: backend->ssl_write_buffered_length = 0UL; ! 3158: break; ! 3159: case errSSLWouldBlock: /* argh, try again */ ! 3160: *curlcode = CURLE_AGAIN; ! 3161: return -1L; ! 3162: default: ! 3163: failf(conn->data, "SSLWrite() returned error %d", err); ! 3164: *curlcode = CURLE_SEND_ERROR; ! 3165: return -1L; ! 3166: } ! 3167: } ! 3168: else { ! 3169: /* We've got new data to write: */ ! 3170: err = SSLWrite(backend->ssl_ctx, mem, len, &processed); ! 3171: if(err != noErr) { ! 3172: switch(err) { ! 3173: case errSSLWouldBlock: ! 3174: /* Data was buffered but not sent, we have to tell the caller ! 3175: to try sending again, and remember how much was buffered */ ! 3176: backend->ssl_write_buffered_length = len; ! 3177: *curlcode = CURLE_AGAIN; ! 3178: return -1L; ! 3179: default: ! 3180: failf(conn->data, "SSLWrite() returned error %d", err); ! 3181: *curlcode = CURLE_SEND_ERROR; ! 3182: return -1L; ! 3183: } ! 3184: } ! 3185: } ! 3186: return (ssize_t)processed; ! 3187: } ! 3188: ! 3189: static ssize_t sectransp_recv(struct connectdata *conn, ! 3190: int num, ! 3191: char *buf, ! 3192: size_t buffersize, ! 3193: CURLcode *curlcode) ! 3194: { ! 3195: /*struct Curl_easy *data = conn->data;*/ ! 3196: struct ssl_connect_data *connssl = &conn->ssl[num]; ! 3197: struct ssl_backend_data *backend = connssl->backend; ! 3198: size_t processed = 0UL; ! 3199: OSStatus err; ! 3200: ! 3201: again: ! 3202: err = SSLRead(backend->ssl_ctx, buf, buffersize, &processed); ! 3203: ! 3204: if(err != noErr) { ! 3205: switch(err) { ! 3206: case errSSLWouldBlock: /* return how much we read (if anything) */ ! 3207: if(processed) ! 3208: return (ssize_t)processed; ! 3209: *curlcode = CURLE_AGAIN; ! 3210: return -1L; ! 3211: break; ! 3212: ! 3213: /* errSSLClosedGraceful - server gracefully shut down the SSL session ! 3214: errSSLClosedNoNotify - server hung up on us instead of sending a ! 3215: closure alert notice, read() is returning 0 ! 3216: Either way, inform the caller that the server disconnected. */ ! 3217: case errSSLClosedGraceful: ! 3218: case errSSLClosedNoNotify: ! 3219: *curlcode = CURLE_OK; ! 3220: return -1L; ! 3221: break; ! 3222: ! 3223: /* The below is errSSLPeerAuthCompleted; it's not defined in ! 3224: Leopard's headers */ ! 3225: case -9841: ! 3226: if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) { ! 3227: CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), conn->data, ! 3228: backend->ssl_ctx); ! 3229: if(result) ! 3230: return result; ! 3231: } ! 3232: goto again; ! 3233: default: ! 3234: failf(conn->data, "SSLRead() return error %d", err); ! 3235: *curlcode = CURLE_RECV_ERROR; ! 3236: return -1L; ! 3237: break; ! 3238: } ! 3239: } ! 3240: return (ssize_t)processed; ! 3241: } ! 3242: ! 3243: static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl, ! 3244: CURLINFO info UNUSED_PARAM) ! 3245: { ! 3246: struct ssl_backend_data *backend = connssl->backend; ! 3247: (void)info; ! 3248: return backend->ssl_ctx; ! 3249: } ! 3250: ! 3251: const struct Curl_ssl Curl_ssl_sectransp = { ! 3252: { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */ ! 3253: ! 3254: #ifdef SECTRANSP_PINNEDPUBKEY ! 3255: SSLSUPP_PINNEDPUBKEY, ! 3256: #else ! 3257: 0, ! 3258: #endif /* SECTRANSP_PINNEDPUBKEY */ ! 3259: ! 3260: sizeof(struct ssl_backend_data), ! 3261: ! 3262: Curl_none_init, /* init */ ! 3263: Curl_none_cleanup, /* cleanup */ ! 3264: Curl_sectransp_version, /* version */ ! 3265: Curl_sectransp_check_cxn, /* check_cxn */ ! 3266: Curl_sectransp_shutdown, /* shutdown */ ! 3267: Curl_sectransp_data_pending, /* data_pending */ ! 3268: Curl_sectransp_random, /* random */ ! 3269: Curl_none_cert_status_request, /* cert_status_request */ ! 3270: Curl_sectransp_connect, /* connect */ ! 3271: Curl_sectransp_connect_nonblocking, /* connect_nonblocking */ ! 3272: Curl_sectransp_get_internals, /* get_internals */ ! 3273: Curl_sectransp_close, /* close_one */ ! 3274: Curl_none_close_all, /* close_all */ ! 3275: Curl_sectransp_session_free, /* session_free */ ! 3276: Curl_none_set_engine, /* set_engine */ ! 3277: Curl_none_set_engine_default, /* set_engine_default */ ! 3278: Curl_none_engines_list, /* engines_list */ ! 3279: Curl_sectransp_false_start, /* false_start */ ! 3280: Curl_sectransp_md5sum, /* md5sum */ ! 3281: Curl_sectransp_sha256sum /* sha256sum */ ! 3282: }; ! 3283: ! 3284: #ifdef __clang__ ! 3285: #pragma clang diagnostic pop ! 3286: #endif ! 3287: ! 3288: #endif /* USE_SECTRANSP */