Annotation of embedaddon/curl/lib/vtls/sectransp.c, revision 1.1
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 */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>