Commit 6f1f7e5d authored by Nick Zitzmann's avatar Nick Zitzmann
Browse files

darwinssl: disable ECC ciphers under Mountain Lion by default

I found out that ECC doesn't work as of OS X 10.8.3, so those ciphers are
turned off until the next point release of OS X.
parent 91ab2497
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ This release includes the following bugfixes:
 o curlbuild.h.dist: enhance non-configure GCC ABI detection logic
 o sasl: Fixed null pointer reference when decoding empty digest challenge [8]
 o easy: do not ignore poll() failures other than EINTR
 o darwinssl: disable ECC ciphers under Mountain Lion by default

This release includes the following known bugs:

+62 −17
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@

/* From MacTypes.h (which we can't include because it isn't present in iOS: */
#define ioErr -36
#define paramErr -50

/* In Mountain Lion and iOS 5, Apple made some changes to the API. They
   added TLS 1.1 and 1.2 support, and deprecated and replaced some
@@ -628,40 +629,36 @@ CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher) {
  return "TLS_NULL_WITH_NULL_NULL";
}

CF_INLINE bool IsRunningMountainLionOrLater(void)
{
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
{
  int mib[2];
  char *os_version;
  size_t os_version_len;
  char *os_version_major/*, *os_version_minor, *os_version_point*/;
  int os_version_major_int;
  char *os_version_major, *os_version_minor/*, *os_version_point*/;

  /* Get the Darwin kernel version from the kernel using sysctl(): */
  mib[0] = CTL_KERN;
  mib[1] = KERN_OSRELEASE;
  if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1)
    return false;
    return;
  os_version = malloc(os_version_len*sizeof(char));
  if(!os_version)
    return false;
    return;
  if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) {
    free(os_version);
    return false;
    return;
  }

  /* Parse the version. If it's version 12.0.0 or later, then this user is
     using Mountain Lion. */
  /* Parse the version: */
  os_version_major = strtok(os_version, ".");
  /*os_version_minor = strtok(NULL, ".");
  os_version_point = strtok(NULL, ".");*/
  os_version_major_int = atoi(os_version_major);
  os_version_minor = strtok(NULL, ".");
  /*os_version_point = strtok(NULL, ".");*/
  *major = atoi(os_version_major);
  *minor = atoi(os_version_minor);
  free(os_version);
  return os_version_major_int >= 12;
#else
  return true;  /* iOS users: this doesn't concern you */
#endif
}
#endif

/* Apple provides a myriad of ways of getting information about a certificate
   into a string. Some aren't available under iOS or newer cats. So here's
@@ -707,6 +704,13 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
#endif
  /*SSLConnectionRef ssl_connection;*/
  OSStatus err = noErr;
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
  size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
  SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
  int darwinver_maj = 0, darwinver_min = 0;

  GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
#endif

#if defined(__MAC_10_8) || defined(__IPHONE_5_0)
  if(SSLCreateContext != NULL) {  /* use the newer API if avaialble */
@@ -851,7 +855,12 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
     to disable certificate validation if the user turned that off.
     (SecureTransport will always validate the certificate chain by
     default.) */
  if(SSLSetSessionOption != NULL && IsRunningMountainLionOrLater()) {
  /* (Note: Darwin 12.x.x is Mountain Lion.) */
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
  if(SSLSetSessionOption != NULL && darwinver_maj >= 12) {
#else
  if(SSLSetSessionOption != NULL) {
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
    err = SSLSetSessionOption(connssl->ssl_ctx,
                              kSSLSessionOptionBreakOnServerAuth,
                              data->set.ssl.verifypeer?false:true);
@@ -895,6 +904,31 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
    }
  }

  /* There's a known bug in early versions of Mountain Lion where ST's ECC
     ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
     Work around the problem here by disabling those ciphers if we are running
     in an affected version of OS X. */
#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
  if(darwinver_maj == 12 && darwinver_min <= 3) {
    (void)SSLGetNumberSupportedCiphers(connssl->ssl_ctx, &all_ciphers_count);
    all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
    allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
    if(all_ciphers && allowed_ciphers &&
       SSLGetSupportedCiphers(connssl->ssl_ctx, all_ciphers,
         &all_ciphers_count) == noErr) {
      for(i = 0UL ; i < all_ciphers_count ; i++) {
        if(all_ciphers[i] < 0xC001 || all_ciphers[i] > 0xC032) {
          allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
        }
      }
      (void)SSLSetEnabledCiphers(connssl->ssl_ctx, allowed_ciphers,
                                 allowed_ciphers_count);
    }
    Curl_safefree(all_ciphers);
    Curl_safefree(allowed_ciphers);
  }
#endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */

  err = SSLSetIOFuncs(connssl->ssl_ctx, SocketRead, SocketWrite);
  if(err != noErr) {
    failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
@@ -947,6 +981,7 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
        /* the documentation says we need to call SSLHandshake() again */
        return darwinssl_connect_step2(conn, sockindex);

      /* These are all certificate problems with the server: */
      case errSSLXCertChainInvalid:
        failf(data, "SSL certificate problem: Invalid certificate chain");
        return CURLE_SSL_CACERT;
@@ -961,14 +996,24 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
              "expired certificate");
        return CURLE_SSL_CACERT;

      /* This error is raised if the server's cert didn't match the server's
         host name: */
      case errSSLHostNameMismatch:
        failf(data, "SSL certificate peer verification failed, the "
              "certificate did not match \"%s\"\n", conn->host.dispname);
        return CURLE_PEER_FAILED_VERIFICATION;

      /* Generic handshake errors: */
      case errSSLConnectionRefused:
        failf(data, "Server dropped the connection during the SSL handshake");
        return CURLE_SSL_CONNECT_ERROR;
      case errSSLClosedAbort:
        failf(data, "Server aborted the SSL handshake");
        return CURLE_SSL_CONNECT_ERROR;
      case paramErr: /* if you're getting this, it could be a cipher problem */
        failf(data, "Internal SSL engine error encountered during the "
              "SSL handshake");
        return CURLE_SSL_CONNECT_ERROR;
      default:
        failf(data, "Unknown SSL protocol error in connection to %s:%d",
              conn->host.name, err);