Commit 14f79581 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

Georg Horn's fixes to do different CA cert verifications. They can now be

done even if the result is ignored, as some sites seem to require that.
parent 59877915
Loading
Loading
Loading
Loading
+60 −27
Original line number Original line Diff line number Diff line
@@ -975,21 +975,46 @@ Curl_SSLConnect(struct connectdata *conn)
    }
    }
  }
  }


  if(data->set.ssl.verifypeer) {
  if (data->set.ssl.CAfile || data->set.ssl.CApath) {
    SSL_CTX_set_verify(conn->ssl.ctx,
    /* tell SSL where to find CA certificates that are used to verify
                       SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
       the servers certificate. */
                       SSL_VERIFY_CLIENT_ONCE,
    if (!SSL_CTX_load_verify_locations(conn->ssl.ctx, data->set.ssl.CAfile,
                       cert_verify_callback);
    if((data->set.ssl.CAfile || data->set.ssl.CApath) &&
       !SSL_CTX_load_verify_locations(conn->ssl.ctx,
                                      data->set.ssl.CAfile,
                                       data->set.ssl.CApath)) {
                                       data->set.ssl.CApath)) {
      failf(data,"error setting certificate verify locations");
      if (data->set.ssl.verifypeer) {
 	/* Fail if we insist on successfully verifying the server. */
        failf(data,"error setting certificate verify locations:\n"
              "  CAfile: %s\n  CApath: %s\n",
              data->set.ssl.CAfile ? data->set.ssl.CAfile : "none",
              data->set.ssl.CApath ? data->set.ssl.CApath : "none");
        return CURLE_SSL_CACERT;
        return CURLE_SSL_CACERT;
      }
      }
      else {
        /* Just continue with a warning if no strict  certificate verification
           is required. */
        infof(data,"error setting certificate verify locations,"
              " continuing anyway:\n");
        infof(data, "  CAfile: %s\n",
              data->set.ssl.CAfile ? data->set.ssl.CAfile : "none");
        infof(data, "  CApath: %s\n",
              data->set.ssl.CApath ? data->set.ssl.CApath : "none");
      }
      }
  else
    }
    SSL_CTX_set_verify(conn->ssl.ctx, SSL_VERIFY_NONE, cert_verify_callback);
    else {
      /* Everything is fine. */
      infof(data,"successfully set certificate verify locations:\n");
      infof(data, "  CAfile: %s\n",
            data->set.ssl.CAfile ? data->set.ssl.CAfile : "none");
      infof(data, "  CApath: %s\n",
            data->set.ssl.CApath ? data->set.ssl.CApath : "none");
    }
  }
  /* SSL always tries to verify the peer, this only says whether it should
   * fail to connect if the verification fails, or if it should continue
   * anyway. In the latter case the result of the verification is checked with
   * SSL_get_verify_result() below. */
  SSL_CTX_set_verify(conn->ssl.ctx,
                     data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
                     cert_verify_callback);


  /* give application a chance to interfere with SSL set up. */
  /* give application a chance to interfere with SSL set up. */
  if(data->set.ssl.fsslctx) {
  if(data->set.ssl.fsslctx) {
@@ -1175,33 +1200,41 @@ Curl_SSLConnect(struct connectdata *conn)


  if(data->set.ssl.verifyhost) {
  if(data->set.ssl.verifyhost) {
    retcode = verifyhost(conn);
    retcode = verifyhost(conn);
    if(retcode)
    if(retcode) {
      X509_free(conn->ssl.server_cert);
      return retcode;
      return retcode;
    }
    }
  }


  str = X509_NAME_oneline(X509_get_issuer_name(conn->ssl.server_cert),
  str = X509_NAME_oneline(X509_get_issuer_name(conn->ssl.server_cert),
                          NULL, 0);
                          NULL, 0);
  if(!str) {
  if(!str) {
    failf(data, "SSL: couldn't get X509-issuer name!");
    failf(data, "SSL: couldn't get X509-issuer name!");
    X509_free(conn->ssl.server_cert);
    retcode = CURLE_SSL_CONNECT_ERROR;
    return CURLE_SSL_CONNECT_ERROR;
  }
  }
  else {
    infof(data, "\t issuer: %s\n", str);
    infof(data, "\t issuer: %s\n", str);
    CRYPTO_free(str);
    CRYPTO_free(str);


    /* We could do all sorts of certificate verification stuff here before
    /* We could do all sorts of certificate verification stuff here before
       deallocating the certificate. */
       deallocating the certificate. */
    
    
  if(data->set.ssl.verifypeer) {
    data->set.ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle);
    data->set.ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle);
    if(data->set.ssl.certverifyresult != X509_V_OK) {
    if(data->set.ssl.certverifyresult != X509_V_OK) {
      if(data->set.ssl.verifypeer) {
        /* We probably never reach this, because SSL_connect() will fail
           and we return earlyer if verifypeer is set? */
        failf(data, "SSL certificate verify result: %d",
        failf(data, "SSL certificate verify result: %d",
              data->set.ssl.certverifyresult);
              data->set.ssl.certverifyresult);
        retcode = CURLE_SSL_PEER_CERTIFICATE;
        retcode = CURLE_SSL_PEER_CERTIFICATE;
      }
      }
      else
        infof(data, "SSL certificate verify result: %d, continuing anyway.\n",
              data->set.ssl.certverifyresult);
    }
    }
    else
    else
    data->set.ssl.certverifyresult=0;
      infof(data, "SSL certificate verify ok.\n");
  }


  X509_free(conn->ssl.server_cert);
  X509_free(conn->ssl.server_cert);
#else /* USE_SSLEAY */
#else /* USE_SSLEAY */