Пример #1
0
DWORD WinVerifySslCert(const QByteArray& cert) {
	DWORD errorStatus = -1;

	PCCERT_CONTEXT certContext = CertCreateCertificateContext(X509_ASN_ENCODING, reinterpret_cast<const BYTE*>(cert.constData()), cert.size());
	if (!certContext) {
		return errorStatus;
	}

	LPSTR usage[] = {
		szOID_PKIX_KP_SERVER_AUTH,
		szOID_SERVER_GATED_CRYPTO,
		szOID_SGC_NETSCAPE
	};

	CERT_CHAIN_PARA chainParameter;
	memset(&chainParameter, 0, sizeof(CERT_CHAIN_PARA));
	chainParameter.cbSize = sizeof(CERT_CHAIN_PARA);
	chainParameter.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
	chainParameter.RequestedUsage.Usage.cUsageIdentifier = ARRAYSIZE(usage);
	chainParameter.RequestedUsage.Usage.rgpszUsageIdentifier = usage;

	PCCERT_CHAIN_CONTEXT chainContext = NULL;
	CertGetCertificateChain(NULL, certContext, NULL, NULL, &chainParameter, 0, NULL, &chainContext);

	if (chainContext) {
		errorStatus = chainContext->TrustStatus.dwErrorStatus;
		CertFreeCertificateChain(chainContext);
	}

	CertFreeCertificateContext(certContext);

	return errorStatus;
}
Пример #2
0
DWORD VerifyCertificate(PCCERT_CONTEXT pCert,DWORD *CheckResult)
{
    CERT_CHAIN_PARA ChainPara;
    PCCERT_CHAIN_CONTEXT Chain=NULL;
	
    ChainPara.cbSize=sizeof(ChainPara);
    ChainPara.RequestedUsage.dwType=USAGE_MATCH_TYPE_AND;
    ChainPara.RequestedUsage.Usage.cUsageIdentifier=0;
    ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier=NULL;
    //ChainPara.RequestedIssuancePolicy=NULL;
    //ChainPara.fCheckRevocationFreshnessTime=FALSE;
    //ChainPara.dwUrlRetrievalTimeout=0;
	
    if(!CertGetCertificateChain(
								NULL,
								pCert,
								NULL,
								NULL,//?
								&ChainPara,
								CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
								NULL,
								&Chain))
        return CSP_GetLastError();
    *CheckResult=Chain->TrustStatus.dwErrorStatus;
    if(Chain)
        CertFreeCertificateChain(Chain);
    return 0;
}
Пример #3
0
SECURITY_STATUS SSL_SOCKET :: Verify(PCCERT_CONTEXT px)
	{
	if (px == 0)
		return SEC_E_WRONG_PRINCIPAL;

	// Time
	int iRc = CertVerifyTimeValidity(NULL,px->pCertInfo);
	if (iRc != 0) 
		return SEC_E_CERT_EXPIRED;

	// Chain
	CERT_CHAIN_PARA ChainPara = {0};
   PCCERT_CHAIN_CONTEXT pChainContext = NULL;
	ChainPara.cbSize = sizeof(ChainPara);
	if (!CertGetCertificateChain(0,px,0,0,&ChainPara,0,0,&pChainContext)) 
		return SEC_E_INVALID_TOKEN;

/*		ZeroMemory(&polHttps, sizeof(HTTPSPolicyCallbackData));
		polHttps.cbStruct           = sizeof(HTTPSPolicyCallbackData);
		polHttps.dwAuthType         = AUTHTYPE_SERVER;
		polHttps.fdwChecks          = dwCertFlags;
		polHttps.pwszServerName     = pwszServerName;

		memset(&PolicyPara, 0, sizeof(PolicyPara));
		PolicyPara.cbSize            = sizeof(PolicyPara);
		PolicyPara.pvExtraPolicyPara = &polHttps;

		memset(&PolicyStatus, 0, sizeof(PolicyStatus));
		PolicyStatus.cbSize = sizeof(PolicyStatus);

	    if (!CertVerifyCertificateChainPolicy(
                            CERT_CHAIN_POLICY_SSL,
                            pChainContext,
                            &PolicyPara,
                            &PolicyStatus)) {
			Status = ::GetLastError();
			SetLastError(Status);
			break;
		}
*/

	PCCERT_CONTEXT j[2];
	j[0] = px;
	CERT_REVOCATION_STATUS cs = {0};
	cs.cbSize = sizeof(cs);
	SECURITY_STATUS ss = 
		CertVerifyRevocation(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,CERT_CONTEXT_REVOCATION_TYPE,
		 1,(void**)j,0,0,&cs);





    if (pChainContext) 
		CertFreeCertificateChain(pChainContext);

	return ss;
	}
Пример #4
0
static void check_and_store_certs(HCERTSTORE from, HCERTSTORE to)
{
    DWORD root_count = 0;
    CERT_CHAIN_ENGINE_CONFIG chainEngineConfig =
     { sizeof(chainEngineConfig), 0 };
    HCERTCHAINENGINE engine;

    TRACE("\n");

    CertDuplicateStore(to);
    engine = CRYPT_CreateChainEngine(to, &chainEngineConfig);
    if (engine)
    {
        PCCERT_CONTEXT cert = NULL;

        do {
            cert = CertEnumCertificatesInStore(from, cert);
            if (cert)
            {
                CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
                PCCERT_CHAIN_CONTEXT chain;
                BOOL ret = CertGetCertificateChain(engine, cert, NULL, from,
                 &chainPara, 0, NULL, &chain);

                if (!ret)
                    TRACE("rejecting %s: %s\n", get_cert_common_name(cert),
                     "chain creation failed");
                else
                {
                    /* The only allowed error is CERT_TRUST_IS_UNTRUSTED_ROOT */
                    if (chain->TrustStatus.dwErrorStatus &
                     ~CERT_TRUST_IS_UNTRUSTED_ROOT)
                        TRACE("rejecting %s: %s\n", get_cert_common_name(cert),
                         trust_status_to_str(chain->TrustStatus.dwErrorStatus &
                         ~CERT_TRUST_IS_UNTRUSTED_ROOT));
                    else
                    {
                        DWORD i, j;

                        for (i = 0; i < chain->cChain; i++)
                            for (j = 0; j < chain->rgpChain[i]->cElement; j++)
                                if (CertAddCertificateContextToStore(to,
                                 chain->rgpChain[i]->rgpElement[j]->pCertContext,
                                 CERT_STORE_ADD_NEW, NULL))
                                    root_count++;
                    }
                    CertFreeCertificateChain(chain);
                }
            }
        } while (cert);
        CertFreeCertificateChainEngine(engine);
    }
    TRACE("Added %d root certificates\n", root_count);
}
Пример #5
0
/* Helper for windows_ssl_server_trust_first_credentials for validating
 * certificate using CryptoApi. Sets *OK_P to TRUE if base64 encoded ASCII_CERT
 * certificate considered as valid.
 */
static svn_error_t *
windows_validate_certificate(svn_boolean_t *ok_p,
                             const char *ascii_cert,
                             apr_pool_t *pool)
{
  PCCERT_CONTEXT cert_context = NULL;
  CERT_CHAIN_PARA chain_para;
  PCCERT_CHAIN_CONTEXT chain_context = NULL;

  *ok_p = FALSE;

  /* Parse the certificate into a context. */
  cert_context = certcontext_from_base64(ascii_cert, pool);

  if (cert_context)
    {
      /* Retrieve the certificate chain of the certificate
         (a certificate without a valid root does not have a chain). */
      memset(&chain_para, 0, sizeof(chain_para));
      chain_para.cbSize = sizeof(chain_para);

      if (CertGetCertificateChain(NULL, cert_context, NULL, NULL, &chain_para,
                                  CERT_CHAIN_CACHE_END_CERT |
                                  CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
                                  NULL, &chain_context))
        {
          CERT_CHAIN_POLICY_PARA policy_para;
          CERT_CHAIN_POLICY_STATUS policy_status;

          policy_para.cbSize = sizeof(policy_para);
          policy_para.dwFlags = 0;
          policy_para.pvExtraPolicyPara = NULL;

          policy_status.cbSize = sizeof(policy_status);

          if (CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
                                               chain_context, &policy_para,
                                               &policy_status))
            {
              if (policy_status.dwError == S_OK)
                {
                  /* Windows thinks the certificate is valid. */
                  *ok_p = TRUE;
                }
            }

          CertFreeCertificateChain(chain_context);
        }
      CertFreeCertificateContext(cert_context);
    }

  return SVN_NO_ERROR;
}
Пример #6
0
static BOOL WINTRUST_CreateChainForSigner(CRYPT_PROVIDER_DATA *data,
 DWORD signer, PWTD_GENERIC_CHAIN_POLICY_CREATE_INFO createInfo,
 PCERT_CHAIN_PARA chainPara)
{
    BOOL ret = TRUE;
    HCERTSTORE store = NULL;

    if (data->chStores)
    {
        store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
         CERT_STORE_CREATE_NEW_FLAG, NULL);
        if (store)
        {
            DWORD i;

            for (i = 0; i < data->chStores; i++)
                CertAddStoreToCollection(store, data->pahStores[i], 0, 0);
        }
    }
    /* Expect the end certificate for each signer to be the only cert in the
     * chain:
     */
    if (data->pasSigners[signer].csCertChain)
    {
        /* Create a certificate chain for each signer */
        ret = CertGetCertificateChain(createInfo->hChainEngine,
         data->pasSigners[signer].pasCertChain[0].pCert,
         &data->pasSigners[signer].sftVerifyAsOf, store,
         chainPara, createInfo->dwFlags, createInfo->pvReserved,
         &data->pasSigners[signer].pChainContext);
        if (ret)
        {
            if (data->pasSigners[signer].pChainContext->cChain != 1)
            {
                FIXME("unimplemented for more than 1 simple chain\n");
                ret = FALSE;
            }
            else
            {
                if ((ret = WINTRUST_CopyChain(data, signer)))
                {
                    if (data->psPfns->pfnCertCheckPolicy)
                        ret = data->psPfns->pfnCertCheckPolicy(data, signer,
                         FALSE, 0);
                    else
                        TRACE("no cert check policy, skipping policy check\n");
                }
            }
        }
    }
    CertCloseStore(store, 0);
    return ret;
}
   bool 
   CertificateVerifier::VerifyCertificate_( PCCERT_CONTEXT certificate, LPWSTR server_name,int &windows_error_code) const
   {
      windows_error_code = 0;

      LPSTR usage_identifier[] = { szOID_PKIX_KP_SERVER_AUTH, szOID_SERVER_GATED_CRYPTO, szOID_SGC_NETSCAPE };

      CERT_CHAIN_PARA params = { sizeof( params ) };
      params.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
      params.RequestedUsage.Usage.cUsageIdentifier = _countof( usage_identifier );
      params.RequestedUsage.Usage.rgpszUsageIdentifier = usage_identifier;

      PCCERT_CHAIN_CONTEXT chain_context = 0;

      if (!CertGetCertificateChain(NULL, 
                                   certificate,  
                                   NULL,
                                   NULL,
                                   &params,
                                   CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
                                   NULL,
                                   &chain_context))
      {
         windows_error_code = GetLastError();
         return false;
      }

      SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslPolicy = { sizeof( sslPolicy ) };
      sslPolicy.dwAuthType = AUTHTYPE_SERVER;
      sslPolicy.pwszServerName = server_name;

      CERT_CHAIN_POLICY_PARA policy = { sizeof( policy ) };
      policy.pvExtraPolicyPara = &sslPolicy;

      CERT_CHAIN_POLICY_STATUS status = { sizeof( status ) };

      BOOL policy_checked = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
                                                             chain_context,
                                                             &policy,
                                                             &status );

      CertFreeCertificateChain( chain_context );

      windows_error_code = status.dwError;
      bool certificate_ok = policy_checked && status.dwError == 0;
      return certificate_ok;
   }
Пример #8
0
/*****************************************************************************
 wmain

*****************************************************************************/
DWORD
__cdecl
wmain(
    int     argc,
    LPWSTR  argv[]
    )
{
    HRESULT                     hr = S_OK;

    BOOL                        fSign = TRUE;        

    LPCWSTR                     pwszInputFile = NULL;
    LPCWSTR                     pwszOutputFile = NULL;

    BYTE                        *pbInput = NULL;
    DWORD                       cbInput = 0;    
    BYTE                        *pbOutput = NULL;
    DWORD                       cbOutput = 0;

    CERT_CHAIN_PARA             ChainPara         = {0};
    CERT_CHAIN_POLICY_PARA      ChainPolicy       = {0};
    CERT_CHAIN_POLICY_STATUS    PolicyStatus      = {0};
    PCCERT_CHAIN_CONTEXT        pChain = NULL;

    PCCERT_CONTEXT              pSignerCert = NULL;
    HCERTSTORE                  hStoreHandle = NULL;

    LPCWSTR                     pwszStoreName = L"MY";  // by default
    LPCWSTR                     pwszCName = L"Test";    // by default

    LPCWSTR                     wszHashAlgName = L"SHA1";

    int                         i;

    //
    // options
    //

    for( i=1; i<argc; i++ )
    {
        if ( lstrcmpW (argv[i], L"/?") == 0 ||
             lstrcmpW (argv[i], L"-?") == 0 ) 
        {
            Usage( L"cms_sign.exe" );
            goto CleanUp;
        }

        if( *argv[i] != L'-' )
            break;

        if ( lstrcmpW (argv[i], L"-s") == 0 )
        {
            if( i+1 >= argc )
            {
                hr = E_INVALIDARG;
                goto CleanUp;
            }

            pwszStoreName = argv[++i];
        }
        else
        if ( lstrcmpW (argv[i], L"-n") == 0 )
        {
            if( i+1 >= argc )
            {
                hr = E_INVALIDARG;
                goto CleanUp;
            }

            pwszCName = argv[++i];
        }
        else
        if ( lstrcmpW (argv[i], L"-a") == 0 )
        {
            if( i+1 >= argc )
            {
                hr = E_INVALIDARG;
                goto CleanUp;
            }

            wszHashAlgName = argv[++i];
        }
    }

    if( 0 == lstrcmpW (argv[i], L"SIGN"))
    {
        if( i+2 >= argc )
        {
            hr = E_INVALIDARG;
            goto CleanUp;
        }

        fSign = TRUE;
        pwszInputFile = argv[++i];
        pwszOutputFile = argv[++i];
    }
    else
    if( 0 == lstrcmpW (argv[i], L"VERIFY"))
    {
        if( i+1 >= argc )
        {
            hr = E_INVALIDARG;
            goto CleanUp;
        }

        fSign = FALSE;
        pwszInputFile = argv[++i];
    }
    else
    {
        hr = E_INVALIDARG;
        goto CleanUp;
    }

    if( i != argc-1 )
    {
        hr = E_INVALIDARG;
        goto CleanUp;
    }

    //-------------------------------------------------------------------
    // Open the certificate store to be searched.

    hStoreHandle = CertOpenStore(
                           CERT_STORE_PROV_SYSTEM,          // the store provider type
                           0,                               // the encoding type is not needed
                           NULL,                            // use the default HCRYPTPROV
                           CERT_SYSTEM_STORE_CURRENT_USER,  // set the store location in a 
                                                            //  registry location
                           pwszStoreName
                           );                               // the store name 

    if( NULL == hStoreHandle )
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        goto CleanUp;
    }

    //
    // Load file
    // 

    hr = HrLoadFile(
                                            pwszInputFile,
                                            &pbInput,
                                            &cbInput
                                            );
    if( FAILED(hr) )
    {
        wprintf( L"Unable to read file: %s\n", pwszInputFile );
        goto CleanUp;
    }


    if( fSign )
    {
        //-------------------------------------------------------------------
        // Sign Message

        PCCRYPT_OID_INFO pOidInfo = NULL;
        CRYPT_SIGN_MESSAGE_PARA  SigParams = {0};

        // Create the MessageArray and the MessageSizeArray.
        const BYTE* MessageArray[] = {pbInput};
        DWORD MessageSizeArray[] = {cbInput};

        //
        // Get a certificate that has the specified Subject Name
        //

        pSignerCert = CertFindCertificateInStore(
                               hStoreHandle,
                               X509_ASN_ENCODING ,        // Use X509_ASN_ENCODING
                               0,                         // No dwFlags needed
                               CERT_FIND_SUBJECT_STR,     // Find a certificate with a
                                                          //  subject that matches the 
                                                          //  string in the next parameter
                               pwszCName,                 // The Unicode string to be found
                                                          //  in a certificate's subject
                               NULL);                     // NULL for the first call to the
                                                          //  function; In all subsequent
                                                          //  calls, it is the last pointer
                                                          //  returned by the function
        if( NULL == pSignerCert )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            goto CleanUp;
        }

        //
        // Build a chain in order to include certs to the message
        //

        if( !CertGetCertificateChain(
                                    NULL,                  // use the default chain engine
                                    pSignerCert,           // pointer to the end certificate
                                    NULL,                  // use the default time
                                    NULL,                  // search no additional stores
                                    &ChainPara,            // use AND logic and enhanced key usage 
                                                           //  as indicated in the ChainPara 
                                                           //  data structure
                                    CERT_CHAIN_REVOCATION_CHECK_END_CERT,
                                    NULL,                  // currently reserved
                                    &pChain ))             // return a pointer to the chain created
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            goto CleanUp;
        }

        //
        // Verify that the chain complies with Base policy
        //

        ChainPolicy.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
        ChainPolicy.dwFlags = 0;

        PolicyStatus.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);

        ChainPolicy.pvExtraPolicyPara = NULL;
        if (!CertVerifyCertificateChainPolicy(
                                        CERT_CHAIN_POLICY_BASE,
                                        pChain,
                                        &ChainPolicy,
                                        &PolicyStatus))
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            goto CleanUp;
        }

        if( PolicyStatus.dwError != S_OK ) 
        {
            ReportError( L"Base Policy Chain Status Failure:", PolicyStatus.dwError  );
            hr = PolicyStatus.dwError;
        }

        // Initialize the signature structure.
        SigParams.cbSize = sizeof(SigParams);
        SigParams.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
        SigParams.pSigningCert = pSignerCert;
        SigParams.cAuthAttr = 0;
        SigParams.dwInnerContentType = 0;
        SigParams.cMsgCrl = 0;
        SigParams.cUnauthAttr = 0;
        SigParams.dwFlags = 0;
        SigParams.pvHashAuxInfo = NULL;
        SigParams.rgAuthAttr = NULL;

        //
        // Addd max of 8 certs to the message
        //

        PCCERT_CONTEXT   rgpMsgCert[8] = {NULL};
        SigParams.rgpMsgCert = rgpMsgCert;
        for( SigParams.cMsgCert=0; SigParams.cMsgCert<pChain->rgpChain[0]->cElement && SigParams.cMsgCert<8; SigParams.cMsgCert++ )
        {
            rgpMsgCert[SigParams.cMsgCert] = pChain->rgpChain[0]->rgpElement[SigParams.cMsgCert]->pCertContext;
        }

        //
        // Find OID
        //

        pOidInfo = CryptFindOIDInfo(
                                    CRYPT_OID_INFO_NAME_KEY,
                                    (void*)wszHashAlgName,
                                    CRYPT_HASH_ALG_OID_GROUP_ID
                                    );

        if( NULL == pOidInfo )
        {
            hr = CRYPT_E_UNKNOWN_ALGO;
            goto CleanUp;
        }

        SigParams.HashAlgorithm.pszObjId = (LPSTR)pOidInfo->pszOID;


        // First, get the size of the signed BLOB.
        if( !CryptSignMessage(
                                &SigParams,
                                FALSE,
                                1,
                                MessageArray,
                                &cbInput,
                                NULL,
                                &cbOutput ))
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            goto CleanUp;
        }

        // Allocate memory for the signed BLOB.
        pbOutput = (BYTE*)LocalAlloc( LPTR, cbOutput );
        if( NULL == pbOutput )
        {
            hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
            goto CleanUp;
        }

        // Get the signed message BLOB.
        if( !CryptSignMessage(
                                &SigParams,
                                FALSE,
                                1,
                                MessageArray,
                                MessageSizeArray,
                                pbOutput,
                                &cbOutput ))
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            goto CleanUp;
        }

        hr = HrSaveFile(
                                    pwszOutputFile,
                                    pbOutput,
                                    cbOutput
                                    );
        if( FAILED(hr) )
        {
            wprintf( L"Unable to save file: %s\n", pwszOutputFile );
            goto CleanUp;
        }

        wprintf( L"Successfully signed message using CryptSignMessage.\n");
    }
    else
    {
        //-------------------------------------------------------------------
        // Verify signed message

        CRYPT_VERIFY_MESSAGE_PARA   VerifyParams = {0};

        VerifyParams.cbSize = sizeof(VerifyParams);
        VerifyParams.dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
        VerifyParams.hCryptProv = 0;
        VerifyParams.pfnGetSignerCertificate = NULL;
        VerifyParams.pvGetArg = NULL;

        // First, call CryptVerifyMessageSignature to get the length 
        // of the buffer needed to hold the decoded message.
        if( !CryptVerifyMessageSignature(
                                        &VerifyParams,
                                        0,
                                        pbInput,
                                        cbInput,
                                        NULL,
                                        &cbOutput,
                                        NULL))
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            goto CleanUp;
        }

        pbOutput = (BYTE*)LocalAlloc( LPTR, cbOutput );
        if( NULL == pbOutput )
        {
            hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
            goto CleanUp;
        }

        //---------------------------------------------------------------
        // Call CryptVerifyMessageSignature again to verify the signature
        // and, if successful, copy the decoded message into the buffer. 
        if( !CryptVerifyMessageSignature(
                                        &VerifyParams,
                                        0,
                                        pbInput,
                                        cbInput,
                                        pbOutput,
                                        &cbOutput,
                                        &pSignerCert))
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            goto CleanUp;
        }

        wprintf( L"Successfully verified signed message using CryptVerifyMessageSignature.\n");

        //
        // Build a chain in order to verify certificate trust
        //

        //
        // Instruction :   Create a certificate store from the CMS message and provide as a parameter to 
        //                 CertGetCertificateChain. This will ensure that all additional certificates from
		//                 the CMS message are used in chain building
        //                 Otherwise chain will be build using the local stores only.
        // 

        if( !CertGetCertificateChain(
                                    NULL,                  // use the default chain engine
                                    pSignerCert,           // pointer to the end certificate
                                    NULL,                  // use the default time
                                    NULL,                  // search no additional stores
                                    &ChainPara,            // use AND logic and enhanced key usage 
                                                           //  as indicated in the ChainPara 
                                                           //  data structure
                                    CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
                                    NULL,                  // currently reserved
                                    &pChain ))             // return a pointer to the chain created
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            goto CleanUp;
        }

        //
        // Verify that the chain complies with Base policy
        //

        ChainPolicy.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
        ChainPolicy.dwFlags = 0;

        PolicyStatus.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);

        ChainPolicy.pvExtraPolicyPara = NULL;
        if (!CertVerifyCertificateChainPolicy(
                                        CERT_CHAIN_POLICY_BASE,
                                        pChain,
                                        &ChainPolicy,
                                        &PolicyStatus))
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            goto CleanUp;
        }

        if( PolicyStatus.dwError != S_OK ) 
        {
            ReportError( L"Base Policy Chain Status Failure:", PolicyStatus.dwError  );
            hr = PolicyStatus.dwError;
        }
    }

    hr = S_OK;

    //-------------------------------------------------------------------
    // Clean up memory.

CleanUp:

    if( NULL != pbInput )
    {
        LocalFree(pbInput);
    }

    if( NULL != pbOutput )
    {
        LocalFree(pbOutput);
    }

    if( NULL != pChain )
    {
        CertFreeCertificateChain(pChain);
    }

    if( NULL != pSignerCert )
    {
        CertFreeCertificateContext(pSignerCert);
    }

    if( NULL != hStoreHandle)
    {
        CertCloseStore( hStoreHandle, 0 );
    }

    if( FAILED( hr ))
    {
        ReportError( NULL, hr  );
    }

    return (DWORD)hr;
} // End of main
Пример #9
0
int CryptoAPI_verify_certificate(X509 *x509)
{
  int ret = -1;
  int len;
  unsigned char *buf = NULL;

  PCCERT_CONTEXT pCertContext = NULL;
  PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  CERT_ENHKEY_USAGE EnhkeyUsage;
  CERT_USAGE_MATCH CertUsage;  
  CERT_CHAIN_PARA ChainPara;

  /* Convert from internal X509 format to DER */
  len = i2d_X509(x509, &buf);
  if (len < 0) {
	SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
	goto err;
  }

#ifdef __MINGW32_VERSION
    /* MinGW w32api is incomplete when it comes to CryptoAPI, as per version 3.1
     * anyway. This is a hack around that problem. */
    if (crypt32dll == NULL) {
	crypt32dll = LoadLibrary("crypt32");
	if (crypt32dll == NULL) {
	    CRYPTOAPIerr(CRYPTOAPI_F_LOAD_LIBRARY);
	    goto err;
	}
    }
    if (CertCreateCertificateContext == NULL) {
	CertCreateCertificateContext = GetProcAddress(crypt32dll,
		"CertCreateCertificateContext");
	if (CertCreateCertificateContext == NULL) {
	    CRYPTOAPIerr(CRYPTOAPI_F_GET_PROC_ADDRESS);
	    goto err;
	}
    }
#endif

  /* Create a certificate context based on the above certificate */
  pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  	buf, len);
  if (pCertContext == NULL) {
	CRYPTOAPIerr(CRYPTOAPI_F_CERT_CREATE_CERT_CONTEXT);
	goto err;
  }

  /* Create an empty issuer list */
  EnhkeyUsage.cUsageIdentifier = 0;
  EnhkeyUsage.rgpszUsageIdentifier = NULL;
  CertUsage.dwType = USAGE_MATCH_TYPE_AND;
  CertUsage.Usage  = EnhkeyUsage;

  /* Searching and matching criteria to be used when building the chain */
  ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
  ChainPara.RequestedUsage = CertUsage;

  /* Get the certificate chain of our certificate */
  if (!CertGetCertificateChain(NULL, pCertContext, NULL, NULL, &ChainPara,
	0, NULL, &pChainContext)) {
	CRYPTOAPIerr(CRYPTOAPI_F_CERT_GET_CERT_CHAIN);
	goto err;
  }

  /* return 1 when the certificate is trusted, 0 when it's not; -1 on error */
  ret = (pChainContext->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR);

  err:
    if (buf)
	OPENSSL_free(buf);
    if (pChainContext)
	CertFreeCertificateChain(pChainContext);
    if (pCertContext)
	CertFreeCertificateContext(pCertContext);

  return ret;
}
Пример #10
0
/*
 * 'sspi_verify_certificate()' - Verify a server certificate
 */
static DWORD				/* 0  - Error code (0 == No error) */
sspi_verify_certificate(PCCERT_CONTEXT  serverCert,
					/* I  - Server certificate */
                        const CHAR      *serverName,
					/* I  - Server name */
                        DWORD           dwCertFlags)
					/* I  - Verification flags */
{
  HTTPSPolicyCallbackData	httpsPolicy;
					/* HTTPS Policy Struct */
  CERT_CHAIN_POLICY_PARA	policyPara;
					/* Cert chain policy parameters */
  CERT_CHAIN_POLICY_STATUS	policyStatus;
					/* Cert chain policy status */
  CERT_CHAIN_PARA		chainPara;
					/* Used for searching and matching criteria */
  PCCERT_CHAIN_CONTEXT		chainContext = NULL;
					/* Certificate chain */
  PWSTR				serverNameUnicode = NULL;
					/* Unicode server name */
  LPSTR				rgszUsages[] = { szOID_PKIX_KP_SERVER_AUTH,
                                                 szOID_SERVER_GATED_CRYPTO,
                                                 szOID_SGC_NETSCAPE };
					/* How are we using this certificate? */
  DWORD				cUsages = sizeof(rgszUsages) / sizeof(LPSTR);
					/* Number of ites in rgszUsages */
  DWORD				count;	/* 32 bit count variable */
  DWORD				status;	/* Return value */

  if (!serverCert)
  {
    status = SEC_E_WRONG_PRINCIPAL;
    goto cleanup;
  }

 /*
  *  Convert server name to unicode.
  */
  if (!serverName || (strlen(serverName) == 0))
  {
    status = SEC_E_WRONG_PRINCIPAL;
    goto cleanup;
  }

  count = MultiByteToWideChar(CP_ACP, 0, serverName, -1, NULL, 0);
  serverNameUnicode = LocalAlloc(LMEM_FIXED, count * sizeof(WCHAR));
  if (!serverNameUnicode)
  {
    status = SEC_E_INSUFFICIENT_MEMORY;
    goto cleanup;
  }
  count = MultiByteToWideChar(CP_ACP, 0, serverName, -1, serverNameUnicode, count);
  if (count == 0)
  {
    status = SEC_E_WRONG_PRINCIPAL;
    goto cleanup;
  }

 /*
  * Build certificate chain.
  */
  ZeroMemory(&chainPara, sizeof(chainPara));
  chainPara.cbSize					= sizeof(chainPara);
  chainPara.RequestedUsage.dwType			= USAGE_MATCH_TYPE_OR;
  chainPara.RequestedUsage.Usage.cUsageIdentifier	= cUsages;
  chainPara.RequestedUsage.Usage.rgpszUsageIdentifier	= rgszUsages;

  if (!CertGetCertificateChain(NULL, serverCert, NULL, serverCert->hCertStore,
                               &chainPara, 0, NULL, &chainContext))
  {
    status = GetLastError();
    DEBUG_printf(("CertGetCertificateChain returned 0x%x\n", status));
    goto cleanup;
  }

 /*
  * Validate certificate chain.
  */
  ZeroMemory(&httpsPolicy, sizeof(HTTPSPolicyCallbackData));
  httpsPolicy.cbStruct		= sizeof(HTTPSPolicyCallbackData);
  httpsPolicy.dwAuthType	= AUTHTYPE_SERVER;
  httpsPolicy.fdwChecks		= dwCertFlags;
  httpsPolicy.pwszServerName	= serverNameUnicode;

  memset(&policyPara, 0, sizeof(policyPara));
  policyPara.cbSize		= sizeof(policyPara);
  policyPara.pvExtraPolicyPara	= &httpsPolicy;

  memset(&policyStatus, 0, sizeof(policyStatus));
  policyStatus.cbSize = sizeof(policyStatus);

  if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, chainContext,
                                        &policyPara, &policyStatus))
  {
    status = GetLastError();
    DEBUG_printf(("CertVerifyCertificateChainPolicy returned %d", status));
    goto cleanup;
  }

  if (policyStatus.dwError)
  {
    status = policyStatus.dwError;
    goto cleanup;
  }

  status = SEC_E_OK;

cleanup:

  if (chainContext)
    CertFreeCertificateChain(chainContext);

  if (serverNameUnicode)
    LocalFree(serverNameUnicode);

  return (status);
}
Пример #11
0
/* Helper function to trace the signing cert to a trusted CA root
 * in the Windows Certificate Store. */
static int checkCertCryptoAPI(const GTPublicationsFile *publications_file)
{
	int res = GT_UNKNOWN_ERROR;
	unsigned char *cert_der = NULL;
	size_t cert_der_len;
	PCCERT_CONTEXT pCertContext = NULL;
	PCCERT_CHAIN_CONTEXT pChainContext = NULL;
	CERT_ENHKEY_USAGE enhkeyUsage;
	CERT_USAGE_MATCH certUsage;
	CERT_CHAIN_PARA chainPara;
	CERT_CHAIN_POLICY_PARA policyPara;
	CERT_CHAIN_POLICY_STATUS policyStatus;
	char tmp_name[256];

	res = GTPublicationsFile_getSigningCert(publications_file, &cert_der, &cert_der_len);
	if (res != GT_OK) {
		goto cleanup;
	}

	/* Create a certificate context based on the above certificate. */
	pCertContext = CertCreateCertificateContext(
			X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, cert_der, cert_der_len);
	if (pCertContext == NULL) {
		res = GT_CRYPTO_FAILURE;
		goto cleanup;
	}

#ifdef MAGIC_EMAIL
	CertGetNameStringA(pCertContext, CERT_NAME_EMAIL_TYPE, 0, NULL,
			tmp_name, sizeof(tmp_name));
	if (strcmp(tmp_name, MAGIC_EMAIL) != 0) {
		return GT_INVALID_SIGNATURE;
	}
#endif

	/* Get the certificate chain of our certificate. */
	enhkeyUsage.cUsageIdentifier = 0;
	enhkeyUsage.rgpszUsageIdentifier = NULL;
	certUsage.dwType = USAGE_MATCH_TYPE_AND;
	certUsage.Usage = enhkeyUsage;
	chainPara.cbSize = sizeof(CERT_CHAIN_PARA);
	chainPara.RequestedUsage = certUsage;

	if (!CertGetCertificateChain(NULL, pCertContext, NULL, NULL,
			&chainPara, 0, NULL, &pChainContext)) {
		res = GT_CRYPTO_FAILURE;
		goto cleanup;
	}

	if (pChainContext->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR) {
		res = GT_CERT_NOT_TRUSTED;
		goto cleanup;
	}

	/* Verify certificate chain. */
	policyPara.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
	policyPara.dwFlags = 0;
	policyPara.pvExtraPolicyPara = NULL;

	if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE,
			pChainContext, &policyPara, &policyStatus)) {
		res = GT_CRYPTO_FAILURE;
		goto cleanup;
	}

	if (policyStatus.dwError) {
		res = GT_CERT_NOT_TRUSTED;
		goto cleanup;
	}

	res = GT_OK;

cleanup:
	GT_free(cert_der);
	if (pChainContext != NULL) {
		CertFreeCertificateChain(pChainContext);
	}
	if (pCertContext != NULL) {
		CertFreeCertificateContext(pCertContext);
	}

	return res;
}
Пример #12
0
SECURITY_STATUS SchannelContext::validateServerCertificate()
{
	SchannelCertificate::ref pServerCert = boost::dynamic_pointer_cast<SchannelCertificate>( getPeerCertificate() );
	if (!pServerCert)
		return SEC_E_WRONG_PRINCIPAL;

	const LPSTR usage[] = 
	{
		szOID_PKIX_KP_SERVER_AUTH,
		szOID_SERVER_GATED_CRYPTO,
		szOID_SGC_NETSCAPE
	};

	CERT_CHAIN_PARA chainParams = {0};
	chainParams.cbSize = sizeof(chainParams);
	chainParams.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
	chainParams.RequestedUsage.Usage.cUsageIdentifier = ARRAYSIZE(usage);
	chainParams.RequestedUsage.Usage.rgpszUsageIdentifier = const_cast<LPSTR*>(usage);

	DWORD chainFlags = CERT_CHAIN_CACHE_END_CERT | CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;

	ScopedCertChainContext pChainContext;

	BOOL success = CertGetCertificateChain(
		NULL, // Use the chain engine for the current user (assumes a user is logged in)
		pServerCert->getCertContext(),
		NULL,
		NULL,
		&chainParams,
		chainFlags,
		NULL,
		pChainContext.Reset());

	if (!success)
		return GetLastError();

	SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslChainPolicy = {0};
	sslChainPolicy.cbSize = sizeof(sslChainPolicy);
	sslChainPolicy.dwAuthType = AUTHTYPE_SERVER;
	sslChainPolicy.fdwChecks = SECURITY_FLAG_IGNORE_CERT_CN_INVALID; // Swiften checks the server name for us. Is this the correct way to disable server name checking?
	sslChainPolicy.pwszServerName = NULL;

	CERT_CHAIN_POLICY_PARA certChainPolicy = {0};
	certChainPolicy.cbSize = sizeof(certChainPolicy);
	certChainPolicy.dwFlags = CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG; // Swiften checks the server name for us. Is this the correct way to disable server name checking?
	certChainPolicy.pvExtraPolicyPara = &sslChainPolicy;

	CERT_CHAIN_POLICY_STATUS certChainPolicyStatus = {0};
	certChainPolicyStatus.cbSize = sizeof(certChainPolicyStatus);

	// Verify the chain
	if (!CertVerifyCertificateChainPolicy(
		CERT_CHAIN_POLICY_SSL,
		pChainContext,
		&certChainPolicy,
		&certChainPolicyStatus))
	{
		return GetLastError();
	}

	if (certChainPolicyStatus.dwError != S_OK)
		return certChainPolicyStatus.dwError;

	return S_OK;
}
Пример #13
0
// Return an indication of whether a certificate is trusted by asking Windows to validate the
// trust chain (basically asking is the certificate issuer trusted)
HRESULT CertTrusted(PCCERT_CONTEXT pCertContext)
{
   HTTPSPolicyCallbackData  polHttps;
   CERT_CHAIN_POLICY_PARA   PolicyPara;
   CERT_CHAIN_POLICY_STATUS PolicyStatus;
   CERT_CHAIN_PARA          ChainPara;
   PCCERT_CHAIN_CONTEXT     pChainContext = NULL;
   HRESULT                  Status;
   LPSTR rgszUsages[] = { szOID_PKIX_KP_CLIENT_AUTH,
      szOID_SERVER_GATED_CRYPTO,
      szOID_SGC_NETSCAPE };
   DWORD cUsages = _countof(rgszUsages);

   // Build certificate chain.
   ZeroMemory(&ChainPara, sizeof(ChainPara));
   ChainPara.cbSize = sizeof(ChainPara);
   ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
   ChainPara.RequestedUsage.Usage.cUsageIdentifier = cUsages;
   ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = rgszUsages;

   if (!CertGetCertificateChain(NULL,
      pCertContext,
      NULL,
      pCertContext->hCertStore,
      &ChainPara,
      0,
      NULL,
      &pChainContext))
   {
      Status = GetLastError();
      DebugMsg("Error %#x returned by CertGetCertificateChain!", Status);
      goto cleanup;
   }


   // Validate certificate chain.
   ZeroMemory(&polHttps, sizeof(HTTPSPolicyCallbackData));
   polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData);
   polHttps.dwAuthType = AUTHTYPE_SERVER;
   polHttps.fdwChecks = 0;    // dwCertFlags;
   polHttps.pwszServerName = NULL; // ServerName - checked elsewhere

   ZeroMemory(&PolicyPara, sizeof(PolicyPara));
   PolicyPara.cbSize = sizeof(PolicyPara);
   PolicyPara.pvExtraPolicyPara = &polHttps;

   ZeroMemory(&PolicyStatus, sizeof(PolicyStatus));
   PolicyStatus.cbSize = sizeof(PolicyStatus);

   if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
      pChainContext,
      &PolicyPara,
      &PolicyStatus))
   {
      Status = HRESULT_FROM_WIN32(GetLastError());
      DebugMsg("Error %#x returned by CertVerifyCertificateChainPolicy!", Status);
      goto cleanup;
   }

   if (PolicyStatus.dwError)
   {
      Status = S_FALSE;
      //DisplayWinVerifyTrustError(PolicyStatus.dwError); 
      goto cleanup;
   }

   Status = SEC_E_OK;

cleanup:
   if (pChainContext)
      CertFreeCertificateChain(pChainContext);

   return Status;
}
Пример #14
0
static DWORD netconn_verify_cert(netconn_t *conn, PCCERT_CONTEXT cert, HCERTSTORE store)
{
    BOOL ret;
    CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
    PCCERT_CHAIN_CONTEXT chain;
    char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
    char *server_auth[] = { oid_server_auth };
    DWORD err = ERROR_SUCCESS, errors;

    static const DWORD supportedErrors =
        CERT_TRUST_IS_NOT_TIME_VALID |
        CERT_TRUST_IS_UNTRUSTED_ROOT |
        CERT_TRUST_IS_PARTIAL_CHAIN |
        CERT_TRUST_IS_NOT_VALID_FOR_USAGE;

    TRACE("verifying %s\n", debugstr_w(conn->server->name));

    chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
    chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
    if (!(ret = CertGetCertificateChain(NULL, cert, NULL, store, &chainPara, 0, NULL, &chain))) {
        TRACE("failed\n");
        return GetLastError();
    }

    errors = chain->TrustStatus.dwErrorStatus;

    do {
        /* This seems strange, but that's what tests show */
        if(errors & CERT_TRUST_IS_PARTIAL_CHAIN) {
            WARN("ERROR_INTERNET_SEC_CERT_REV_FAILED\n");
            err = ERROR_INTERNET_SEC_CERT_REV_FAILED;
            if(conn->mask_errors)
                conn->security_flags |= _SECURITY_FLAG_CERT_REV_FAILED;
            if(!(conn->security_flags & SECURITY_FLAG_IGNORE_REVOCATION))
                break;
        }

        if (chain->TrustStatus.dwErrorStatus & ~supportedErrors) {
            WARN("error status %x\n", chain->TrustStatus.dwErrorStatus & ~supportedErrors);
            err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_INVALID_CERT;
            errors &= supportedErrors;
            if(!conn->mask_errors)
                break;
            WARN("unknown error flags\n");
        }

        if(errors & CERT_TRUST_IS_NOT_TIME_VALID) {
            WARN("CERT_TRUST_IS_NOT_TIME_VALID\n");
            if(!(conn->security_flags & SECURITY_FLAG_IGNORE_CERT_DATE_INVALID)) {
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_CERT_DATE_INVALID;
                if(!conn->mask_errors)
                    break;
                conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_DATE;
            }
            errors &= ~CERT_TRUST_IS_NOT_TIME_VALID;
        }

        if(errors & CERT_TRUST_IS_UNTRUSTED_ROOT) {
            WARN("CERT_TRUST_IS_UNTRUSTED_ROOT\n");
            if(!(conn->security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA)) {
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_INVALID_CA;
                if(!conn->mask_errors)
                    break;
                conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_CA;
            }
            errors &= ~CERT_TRUST_IS_UNTRUSTED_ROOT;
        }

        if(errors & CERT_TRUST_IS_PARTIAL_CHAIN) {
            WARN("CERT_TRUST_IS_PARTIAL_CHAIN\n");
            if(!(conn->security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA)) {
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_INVALID_CA;
                if(!conn->mask_errors)
                    break;
                conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_CA;
            }
            errors &= ~CERT_TRUST_IS_PARTIAL_CHAIN;
        }

        if(errors & CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
            WARN("CERT_TRUST_IS_NOT_VALID_FOR_USAGE\n");
            if(!(conn->security_flags & SECURITY_FLAG_IGNORE_WRONG_USAGE)) {
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_INVALID_CERT;
                if(!conn->mask_errors)
                    break;
                WARN("CERT_TRUST_IS_NOT_VALID_FOR_USAGE, unknown error flags\n");
            }
            errors &= ~CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
        }

        if(err == ERROR_INTERNET_SEC_CERT_REV_FAILED) {
            assert(conn->security_flags & SECURITY_FLAG_IGNORE_REVOCATION);
            err = ERROR_SUCCESS;
        }
    }while(0);

    if(!err || conn->mask_errors) {
        CERT_CHAIN_POLICY_PARA policyPara;
        SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
        CERT_CHAIN_POLICY_STATUS policyStatus;
        CERT_CHAIN_CONTEXT chainCopy;

        /* Clear chain->TrustStatus.dwErrorStatus so
         * CertVerifyCertificateChainPolicy will verify additional checks
         * rather than stopping with an existing, ignored error.
         */
        memcpy(&chainCopy, chain, sizeof(chainCopy));
        chainCopy.TrustStatus.dwErrorStatus = 0;
        sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
        sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
        sslExtraPolicyPara.pwszServerName = conn->server->name;
        sslExtraPolicyPara.fdwChecks = conn->security_flags;
        policyPara.cbSize = sizeof(policyPara);
        policyPara.dwFlags = 0;
        policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
        ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
                &chainCopy, &policyPara, &policyStatus);
        /* Any error in the policy status indicates that the
         * policy couldn't be verified.
         */
        if(ret) {
            if(policyStatus.dwError == CERT_E_CN_NO_MATCH) {
                WARN("CERT_E_CN_NO_MATCH\n");
                if(conn->mask_errors)
                    conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_CN;
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_CERT_CN_INVALID;
            }else if(policyStatus.dwError) {
                WARN("policyStatus.dwError %x\n", policyStatus.dwError);
                if(conn->mask_errors)
                    WARN("unknown error flags for policy status %x\n", policyStatus.dwError);
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_INVALID_CERT;
            }
        }else {
            err = GetLastError();
        }
    }

    if(err) {
        WARN("failed %u\n", err);
        CertFreeCertificateChain(chain);
        if(conn->server->cert_chain) {
            CertFreeCertificateChain(conn->server->cert_chain);
            conn->server->cert_chain = NULL;
        }
        if(conn->mask_errors)
            conn->server->security_flags |= conn->security_flags & _SECURITY_ERROR_FLAGS_MASK;
        return err;
    }

    /* FIXME: Reuse cached chain */
    if(conn->server->cert_chain)
        CertFreeCertificateChain(chain);
    else
        conn->server->cert_chain = chain;
    return ERROR_SUCCESS;
}
Пример #15
0
int sserver_auth_protocol_connect(const struct protocol_interface *protocol, const char *auth_string)
{
	CScramble scramble;
	char *tmp;
	int certonly;
	char *client_version = NULL;
	char keyfile[256];
	const char *hostname = NULL;

    if (!strcmp (auth_string, "BEGIN SSL VERIFICATION REQUEST"))
		sserver_protocol_interface.verify_only = 1;
    else if (!strcmp (auth_string, "BEGIN SSL AUTH REQUEST"))
		sserver_protocol_interface.verify_only = 0;
	else
		return CVSPROTO_NOTME;

	write(current_server()->out_fd,SSERVER_INIT_STRING,sizeof(SSERVER_INIT_STRING)-1);

	if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CertificatesOnly",keyfile,sizeof(keyfile)))
		certonly = atoi(keyfile);
	if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","ServerDnsName",keyfile,sizeof(keyfile)))
		hostname = keyfile;

	if(!ServerAuthenticate(hostname))
		return CVSPROTO_AUTHFAIL;

	QueryContextAttributes(&contextHandle,SECPKG_ATTR_STREAM_SIZES,&secSizes);

	g_sslBufferInPos=g_sslBufferOutPos=0;
	g_sslBufferInLen=g_sslBufferOutLen=0;

    set_encrypted_channel(1); /* Error must go through us now */

	PCERT_CONTEXT sc;
	PCCERT_CHAIN_CONTEXT pcc;
	CERT_SIMPLE_CHAIN  *psc;
	CERT_CHAIN_PARA para = { sizeof(CERT_CHAIN_PARA) };
	DWORD trust,rc;
	BOOL cert = FALSE;
	
	rc = QueryContextAttributes(&contextHandle,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&sc);
	if(rc && rc!=SEC_E_NO_CREDENTIALS)
		server_error(1,"Couldn't get client certificate");

	if(rc!=SEC_E_NO_CREDENTIALS) /* The client doesn't have to send us a cert. as cvs uses passwords normally */
	{
		if(!CertGetCertificateChain(NULL, sc, NULL, NULL, &para, 0, NULL, &pcc))
			server_error(1,"Couldn't get client certificate chain");

		psc = pcc->rgpChain[0];
		trust = psc->TrustStatus.dwErrorStatus;
	 
		if (trust)
		{
			if (trust & (CERT_TRUST_IS_PARTIAL_CHAIN | CERT_TRUST_IS_UNTRUSTED_ROOT))
				server_error(1,"Client sent self signed certificate");
			else if (trust & (CERT_TRUST_IS_NOT_TIME_VALID))
				server_error(1,"Client certificate expired");
			else
				server_error(1,"Client certificate verification failed - %08x",trust);
		}

		CertFreeCertificateChain(pcc);
		FreeContextBuffer(sc);

		cert = TRUE;
	}
 
    /* Get the three important pieces of information in order. */
    /* See above comment about error handling.  */

	/* get version, if sent.  1.0 clients didn't have this handshake so we have to handle that. */
	server_getline (protocol, &client_version, MAX_PATH);
	if(strncmp(client_version,"SSERVER-CLIENT ",15))
	{
		sserver_protocol_interface.auth_repository = client_version;
		client_version = NULL;
	}
	else
    	server_getline (protocol, &sserver_protocol_interface.auth_repository, MAX_PATH);
    server_getline (protocol, &sserver_protocol_interface.auth_username, MAX_PATH);
	server_getline (protocol, &sserver_protocol_interface.auth_password, MAX_PATH);

	if(client_version) free(client_version);
	client_version = NULL;

    /* ... and make sure the protocol ends on the right foot. */
    /* See above comment about error handling.  */
    server_getline(protocol, &tmp, MAX_PATH);
    if (strcmp (tmp,
		sserver_protocol_interface.verify_only ?
		"END SSL VERIFICATION REQUEST" : "END SSL AUTH REQUEST")
	!= 0)
    {
		server_printf ("bad auth protocol end: %s\n", tmp);
		free(tmp);
		return CVSPROTO_FAIL;
    }

	strcpy(sserver_protocol_interface.auth_password, scramble.Unscramble(sserver_protocol_interface.auth_password));

	free(tmp);

	switch(certonly)
	{
	case 0:
		break;
	case 1:
		if(!cert)
		{
			server_error(0,"E Login requires a valid client certificate.\n");
			return CVSPROTO_AUTHFAIL;
		}
		free(sserver_protocol_interface.auth_password);
		sserver_protocol_interface.auth_password = NULL;
		break;
	case 2:
		if(!cert)
		{
			server_error(0,"E Login requires a valid client certificate.\n");
			return CVSPROTO_AUTHFAIL;
		}
		break;
	};

	return CVSPROTO_SUCCESS;
}
Пример #16
0
/*****************************************************************************
 HrGetSignerKeyAndChain

  This function retrieves a signing certificate from the local user’s 
  certificate store, builds certificates chain and returns key handle 
  for the signing key.”

  NOTE:
  The phCryptProvOrNCryptKey is cached and must not be released by the caller.

*****************************************************************************/
static
HRESULT
HrGetSignerKeyAndChain(
    LPCWSTR                 wszSubject,
    PCCERT_CHAIN_CONTEXT    *ppChainContext,
    HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* phCryptProvOrNCryptKey,    
    DWORD                   *pdwKeySpec
    )
{
    HRESULT         hr = S_FALSE;
    HCERTSTORE      hStore = NULL;
    PCCERT_CONTEXT  pCert = NULL;
    BOOL            fCallerFreeProvOrNCryptKey = FALSE;

    CERT_CHAIN_PARA  ChainPara         = {0};
    ChainPara.cbSize = sizeof(ChainPara);

    *ppChainContext = NULL;
    *phCryptProvOrNCryptKey = NULL;
    *pdwKeySpec = 0;

    //
    // Open the local user store to search for certificates
    //

    hStore = CertOpenStore(
                            CERT_STORE_PROV_SYSTEM_W,
                            X509_ASN_ENCODING,
                            NULL,
                            CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
                            L"MY"
                            );
    
    if( NULL == hStore )
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        goto CleanUp;
    }

    if( NULL != wszSubject && 0 != *wszSubject )
    {
        //
        // Search by Name
        //

        while( NULL != ( pCert = CertFindCertificateInStore(
                            hStore,
                            X509_ASN_ENCODING,
                            0,
                            CERT_FIND_SUBJECT_STR,
                            wszSubject,
                            pCert
                            )))
        {
            if( CryptAcquireCertificatePrivateKey(
                            pCert,
                            CRYPT_ACQUIRE_CACHE_FLAG,
                            NULL,
                            phCryptProvOrNCryptKey,
                            pdwKeySpec,
                            &fCallerFreeProvOrNCryptKey
                            ))
            {
                break;
            }
        }
    }
    else
    {
        //
        // Get the first available certificate in the store
        //

        while( NULL != ( pCert = CertEnumCertificatesInStore(
                            hStore,
                            pCert
                            )))
        {
            if( CryptAcquireCertificatePrivateKey(
                            pCert,
                            CRYPT_ACQUIRE_CACHE_FLAG,
                            NULL,
                            phCryptProvOrNCryptKey,
                            pdwKeySpec,
                            &fCallerFreeProvOrNCryptKey
                            ))
            {
                break;
            }
        }
    }

    if( NULL == pCert )
    {
        hr = CRYPT_XML_E_SIGNER;
        goto CleanUp;
    }

    //
    // Build the certificate chain without revocation check.
    //

    if( !CertGetCertificateChain(
                                NULL,                   // use the default chain engine
                                pCert,                  // pointer to the end certificate
                                NULL,                   // use the default time
                                NULL,                   // search no additional stores
                                &ChainPara,            
                                0,                      // no revocation check
                                NULL,                   // currently reserved
                                ppChainContext ))       // return a pointer to the chain created
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        goto CleanUp;
    }

CleanUp:

    if( FAILED(hr) )
    {
        *phCryptProvOrNCryptKey = NULL;
        *pdwKeySpec = 0;
    }

    if( NULL != pCert )
    {
        CertFreeCertificateContext( pCert );
    }

    if( NULL != hStore )
    {
        CertCloseStore( hStore, 0 );
    }

    return hr;
}
Пример #17
0
static int KSI_PKITruststore_verifyCertificate(const KSI_PKITruststore *pki, const PCCERT_CONTEXT cert){
	int res = KSI_UNKNOWN_ERROR;
	KSI_CTX *ctx = NULL;
	CERT_ENHKEY_USAGE enhkeyUsage;
	CERT_USAGE_MATCH certUsage;
	CERT_CHAIN_PARA chainPara;
	PCCERT_CHAIN_CONTEXT pChainContext = NULL;
	CERT_CHAIN_POLICY_PARA policyPara;
	CERT_CHAIN_POLICY_STATUS policyStatus;
	char buf[1024];

	if (pki == NULL || cert == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	ctx = pki->ctx;
	KSI_ERR_clearErrors(ctx);

	/* Get the certificate chain of certificate under verification. */
	/*OID List for certificate trust list extensions*/
	enhkeyUsage.cUsageIdentifier = 0;
	enhkeyUsage.rgpszUsageIdentifier = NULL;
	/*Criteria for identifying issuer certificate for chain building*/
	certUsage.dwType = USAGE_MATCH_TYPE_AND;
	certUsage.Usage = enhkeyUsage;
	/*Searching and matching criteria for chain building*/
	chainPara.cbSize = sizeof(CERT_CHAIN_PARA);
	chainPara.RequestedUsage = certUsage;

	/*Use CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL for no automatic cert store update by windows.
	 It is useful when there is need to remove default cert from system store*/
	/*Build Certificate Chain from top to root certificate*/
	if (!CertGetCertificateChain(NULL, cert, NULL, pki->collectionStore, &chainPara, 0, NULL, &pChainContext)) {
		KSI_LOG_debug(pki->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Unable to get PKI certificate chain");
		goto cleanup;
	}
//TODO: debugging
//	printCertChain(pChainContext);

	/*TODO: REMOVE*/
	/*If chain is based on untrusted root, determine if it's in pki->collectionStore.
	 If it is, enable chain verification to trust untrusted roots*/
	if (pChainContext->TrustStatus.dwErrorStatus&CERT_TRUST_IS_UNTRUSTED_ROOT){
		KSI_LOG_debug(ctx, "CryptoAPI: Root certificate is not present under Windows 'Trusted Root Certification Authorities'.");
		KSI_LOG_debug(ctx, "CryptoAPI: Searching if it is present under PKI Trust Store from files.");
		if (isUntrustedRootCertInStore(pki, pChainContext)){
			policyPara.dwFlags =  CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG;
			KSI_LOG_debug(ctx, "CryptoAPI: Certificate is present. Allow untrusted root certificates");
		}
		else{
			policyPara.dwFlags = 0;
			KSI_LOG_debug(ctx, "CryptoAPI: Certificate is not present.");
		}
	}
	else if (pChainContext->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR) {
		KSI_LOG_debug(ctx, "%s", getCertificateChainErrorStr(pChainContext));
		KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, getCertificateChainErrorStr(pChainContext));
		goto cleanup;
	}
	else{
		policyPara.dwFlags = 0;
	}

	/* Verify certificate chain. */
	policyPara.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
	policyPara.pvExtraPolicyPara = 0;

	if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE, pChainContext, &policyPara, &policyStatus)) {
		KSI_LOG_debug(pki->ctx, "%s", getMSError(GetLastError(), buf, sizeof(buf)));
		KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, NULL);
		goto cleanup;
	}

	if (policyStatus.dwError) {
		KSI_LOG_debug(ctx, "CryptoAPI: PKI chain policy error %X.", policyStatus.dwError);
 		KSI_pushError(ctx, res = KSI_PKI_CERTIFICATE_NOT_TRUSTED, NULL);
		goto cleanup;
	}

	res = KSI_OK;

cleanup:

	if (pChainContext) CertFreeCertificateChain(pChainContext);

	return res;
}
Пример #18
0
static SSLSTREAM *ssl_start (TCPSTREAM *tstream,char *host,unsigned long flags)
{
  SECURITY_STATUS e;
  ULONG a;
  TimeStamp t;
  SecBuffer ibuf[2],obuf[1];
  SecBufferDesc ibufs,obufs;
  SCHANNEL_CRED tlscred;
  CERT_CONTEXT *cert;
  CERT_CHAIN_PARA chparam;
  CERT_CHAIN_CONTEXT *chain;
  SSL_EXTRA_CERT_CHAIN_POLICY_PARA policy;
  CERT_CHAIN_POLICY_PARA polparam;
  CERT_CHAIN_POLICY_STATUS status;
  char tmp[MAILTMPLEN],certname[256];
  char *reason = NIL;
  ULONG req = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT |
    ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY |
      ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_EXTENDED_ERROR |
	ISC_REQ_MANUAL_CRED_VALIDATION;
  LPSTR usage[] = {
    szOID_PKIX_KP_SERVER_AUTH,
    szOID_SERVER_GATED_CRYPTO,
    szOID_SGC_NETSCAPE
  };
  PWSTR whost = NIL;
  char *buf = (char *) fs_get (ssltsz);
  unsigned long size = 0;
  sslcertificatequery_t scq =
    (sslcertificatequery_t) mail_parameters (NIL,GET_SSLCERTIFICATEQUERY,NIL);
  sslfailure_t sf = (sslfailure_t) mail_parameters (NIL,GET_SSLFAILURE,NIL);
  SSLSTREAM *stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0,
					    sizeof (SSLSTREAM));
  stream->tcpstream = tstream;	/* bind TCP stream */
				/* initialize TLS credential */
  memset (&tlscred,0,sizeof (SCHANNEL_CRED));
  tlscred.dwVersion = SCHANNEL_CRED_VERSION;
  tlscred.grbitEnabledProtocols = SP_PROT_TLS1;

				/* acquire credentials */
  if (AcquireCredentialsHandle
      (NIL,UNISP_NAME,SECPKG_CRED_OUTBOUND,NIL,(flags & NET_TLSCLIENT) ?
       &tlscred : NIL,NIL,NIL,&stream->cred,&t)
      != SEC_E_OK) reason = "Acquire credentials handle failed";
  else while (!reason) {	/* negotiate security context */
				/* initialize buffers */
    ibuf[0].cbBuffer = size; ibuf[0].pvBuffer = buf;
    ibuf[1].cbBuffer = 0; ibuf[1].pvBuffer = NIL;
    obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NIL;
    ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN;
    ibuf[1].BufferType = SECBUFFER_EMPTY;
				/* initialize buffer descriptors */
    ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION;
    ibufs.cBuffers = 2; obufs.cBuffers = 1;
    ibufs.pBuffers = ibuf; obufs.pBuffers = obuf;
				/* negotiate security */
    e = InitializeSecurityContext
      (&stream->cred,size ? &stream->context : NIL,host,req,0,
       SECURITY_NETWORK_DREP,size? &ibufs:NIL,0,&stream->context,&obufs,&a,&t);
				/* have an output buffer we need to send? */
    if (obuf[0].pvBuffer && obuf[0].cbBuffer) {
      if (!tcp_sout (stream->tcpstream,obuf[0].pvBuffer,obuf[0].cbBuffer))
	reason = "Unexpected TCP output disconnect";
				/* free the buffer */
      FreeContextBuffer (obuf[0].pvBuffer);
    }
    if (!reason) switch (e) {	/* negotiation state */
    case SEC_I_INCOMPLETE_CREDENTIALS:
      break;			/* server wants client auth */
    case SEC_I_CONTINUE_NEEDED:
      if (size) {		/* continue, read any data? */
				/* yes, anything regurgiated back to us? */
	if (ibuf[1].BufferType == SECBUFFER_EXTRA) {
				/* yes, set this as the new data */
	  memmove (buf,buf + size - ibuf[1].cbBuffer,ibuf[1].cbBuffer);
	  size = ibuf[1].cbBuffer;
	  break;
	}
	size = 0;		/* otherwise, read more stuff from server */
      }
    case SEC_E_INCOMPLETE_MESSAGE:
				/* need to read more data from server */
      if (!tcp_getdata (stream->tcpstream))
	reason = "Unexpected TCP input disconnect";
      else {
	memcpy (buf+size,stream->tcpstream->iptr,stream->tcpstream->ictr);
	size += stream->tcpstream->ictr;
				/* empty it from TCP's buffers */
	stream->tcpstream->iptr += stream->tcpstream->ictr;
	stream->tcpstream->ictr = 0;
      }
      break;

    case SEC_E_OK:		/* success, any data to be regurgitated? */
      if (ibuf[1].BufferType == SECBUFFER_EXTRA) {
				/* yes, set this as the new data */
	memmove (stream->tcpstream->iptr = stream->tcpstream->ibuf,
		 buf + size - ibuf[1].cbBuffer,ibuf[1].cbBuffer);
	stream->tcpstream->ictr = ibuf[1].cbBuffer;
      }
      if (!(flags & NET_NOVALIDATECERT)) {
				/* need validation, make wchar of host */
	if (!((size = MultiByteToWideChar (CP_ACP,0,host,-1,NIL,0)) &&
	      (whost = (PWSTR) fs_get (size*sizeof (WCHAR))) &&
	      MultiByteToWideChar (CP_ACP,0,host,-1,whost,size)))
	  fatal ("Can't make wchar of host name!");
				/* get certificate */
	if ((QueryContextAttributes
	     (&stream->context,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&cert) !=
	     SEC_E_OK) || !cert) {
	  reason = "*Unable to get certificate";
	  strcpy (certname,"<no certificate>");
	}
	else {			/* get certificate subject name */
	  CertNameToStr (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
			 &cert->pCertInfo->Subject,CERT_X500_NAME_STR,
			 certname,255);
				/* build certificate chain */
	  memset (&chparam,0,sizeof (chparam));
	  chparam.cbSize = sizeof (chparam);
	  chparam.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
	  chparam.RequestedUsage.Usage.rgpszUsageIdentifier = usage;
	  chparam.RequestedUsage.Usage.cUsageIdentifier =
	    sizeof (usage) / sizeof (LPSTR);
	  if (!CertGetCertificateChain
	      (NIL,cert,NIL,cert->hCertStore,&chparam,NIL,NIL,&chain))
	    reason = ssl_analyze_status (GetLastError (),tmp);
	  else {		/* validate certificate chain */
	    memset (&policy,0,sizeof (SSL_EXTRA_CERT_CHAIN_POLICY_PARA));
	    policy.cbStruct = sizeof (SSL_EXTRA_CERT_CHAIN_POLICY_PARA);
	    policy.dwAuthType = AUTHTYPE_SERVER;
	    policy.fdwChecks = NIL;
	    policy.pwszServerName = whost;
	    memset (&polparam,0,sizeof (polparam));
	    polparam.cbSize = sizeof (polparam);
	    polparam.pvExtraPolicyPara = &policy;
	    memset (&status,0,sizeof (status));
	    status.cbSize = sizeof (status);
	    if (!CertVerifyCertificateChainPolicy
		(CERT_CHAIN_POLICY_SSL,chain,&polparam,&status))
	      reason = ssl_analyze_status (GetLastError (),tmp);
	    else if (status.dwError)
	      reason = ssl_analyze_status (status.dwError,tmp);
	    CertFreeCertificateChain (chain);
	  }
	}
	if (whost) fs_give ((void **) &whost);

	if (reason) {		/* got an error? */
				/* application callback */
	  if (scq) reason = (*scq) ((*reason == '*') ? reason + 1 : reason,
				    host,certname) ? NIL : "";
	  else if (*certname) {	/* error message to return via mm_log() */
	    sprintf (buf,"*%.128s: %.255s",
		     (*reason == '*') ? reason + 1 : reason,certname);
	    reason = buf;
	  }
	}
      }
      if (reason ||
	  (reason = ssl_analyze_status
	   (QueryContextAttributes
	    (&stream->context,SECPKG_ATTR_STREAM_SIZES,&stream->sizes),buf)))
	break;			/* error in certificate or getting sizes */
      fs_give ((void **) &buf);	/* flush temporary buffer */
				/* make maximum-sized buffers */
      stream->bufsize = stream->sizes.cbHeader +
	stream->sizes.cbMaximumMessage + stream->sizes.cbTrailer;
      if (stream->sizes.cbMaximumMessage < SSLBUFLEN)
	fatal ("cbMaximumMessage is less than SSLBUFLEN!");
      else if (stream->sizes.cbMaximumMessage < 16384) {
	sprintf (tmp,"WINDOWS BUG: cbMaximumMessage = %ld, should be 16384",
		 (long) stream->sizes.cbMaximumMessage);
	mm_log (tmp,NIL);
      }
      stream->ibuf = (char *) fs_get (stream->bufsize);
      stream->obuf = (char *) fs_get (stream->bufsize);
      return stream;
    default:
      reason = ssl_analyze_status (e,buf);
    }
  }
  ssl_close (stream);		/* failed to do SSL */
  stream = NIL;			/* no stream returned */
  switch (*reason) {		/* analyze reason */
  case '*':			/* certificate failure */
    ++reason;			/* skip over certificate failure indication */
				/* pass to error callback */
    if (sf) (*sf) (host,reason,flags);
    else {			/* no error callback, build error message */
      sprintf (tmp,"Certificate failure for %.80s: %.512s",host,reason);
      mm_log (tmp,ERROR);
    }
  case '\0':			/* user answered no to certificate callback */
    if (flags & NET_TRYSSL)	/* return dummy stream to stop tryssl */
      stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0,
				     sizeof (SSLSTREAM));
    break;
  default:			/* non-certificate failure */
    if (flags & NET_TRYSSL);	/* no error output if tryssl */
				/* pass to error callback */
    else if (sf) (*sf) (host,reason,flags);
    else {			/* no error callback, build error message */
      sprintf (tmp,"TLS/SSL failure for %.80s: %.512s",host,reason);
      mm_log (tmp,ERROR);
    }
    break;
  }
  fs_give ((void **) &buf);	/* flush temporary buffer */
  return stream;
}
Пример #19
0
/* sqVerifyCert: Verify the validity of the remote certificate */
static int sqVerifyCert(sqSSL *ssl, int isServer) {
	SECURITY_STATUS ret;
	PCCERT_CONTEXT certHandle = NULL;
	PCCERT_CHAIN_CONTEXT chainContext = NULL;
	CERT_CHAIN_PARA chainPara;
	SSL_EXTRA_CERT_CHAIN_POLICY_PARA epp;
	CERT_CHAIN_POLICY_PARA policyPara;
	CERT_CHAIN_POLICY_STATUS policyStatus;
	
	static LPSTR serverUsage[] = {
		szOID_PKIX_KP_SERVER_AUTH,
		szOID_SERVER_GATED_CRYPTO,
		szOID_SGC_NETSCAPE
	};
	static LPSTR clientUsage[] = {
		szOID_PKIX_KP_CLIENT_AUTH
	};
	
	ret = QueryContextAttributes(&ssl->sslCtxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&certHandle);
	/* No credentials were provided */
	if(ret == SEC_E_NO_CREDENTIALS) {
		ssl->certFlags = SQSSL_NO_CERTIFICATE;
		return 1;
	}

	memset(&chainPara, 0, sizeof(chainPara));
	chainPara.cbSize = sizeof(chainPara);
	chainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
	if(!isServer) {
		chainPara.RequestedUsage.Usage.cUsageIdentifier = 3;
		chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = serverUsage;
	} else {
		chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
		chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = clientUsage;
	}
	if(!CertGetCertificateChain(NULL, certHandle, NULL,
                                certHandle->hCertStore,
								&chainPara, 0, NULL, &chainContext)) {
		CertFreeCertificateContext(certHandle);
		ssl->certFlags = SQSSL_OTHER_ISSUE;
		goto done;
	}
	
	memset(&epp, 0, sizeof(epp));
	epp.cbSize = sizeof(epp);
	epp.dwAuthType = AUTHTYPE_SERVER;
	epp.fdwChecks = 0;
	epp.pwszServerName = NULL;

	memset(&policyPara, 0, sizeof(policyPara));
	policyPara.cbSize = sizeof(policyPara);
	policyPara.dwFlags = 0;
	policyPara.pvExtraPolicyPara = &epp;
	memset(&policyStatus, 0, sizeof(policyStatus));
	policyStatus.cbSize = sizeof(policyStatus);

	/* We loop here CertVerifyCertificateChainPolicy() returns only a 
	   single error even if there is more than one issue with the cert. */
	ssl->certFlags = 0;
	while(true) {
		if (!CertVerifyCertificateChainPolicy(
           CERT_CHAIN_POLICY_SSL,
           chainContext,
           &policyPara,
           &policyStatus)) {
				ssl->certFlags |= SQSSL_OTHER_ISSUE;
				goto done;
		}
		switch(policyStatus.dwError) {
			case SEC_E_OK:
				goto done;
			case CERT_E_UNTRUSTEDROOT:
				if(ssl->certFlags & SQSSL_UNTRUSTED_ROOT) goto done;
				ssl->certFlags |= SQSSL_UNTRUSTED_ROOT;
				epp.fdwChecks  |= 0x00000100; /* SECURITY_FLAG_IGNORE_UNKNOWN_CA */
				break;
			case CERT_E_EXPIRED:
				if(ssl->certFlags & SQSSL_CERT_EXPIRED) goto done;
				ssl->certFlags |= SQSSL_CERT_EXPIRED;
				epp.fdwChecks  |= 0x00002000;  /* SECURITY_FLAG_IGNORE_CERT_DATE_INVALID */
				break;
			case CERT_E_WRONG_USAGE:
				if(ssl->certFlags & SQSSL_WRONG_USAGE) goto done;
				ssl->certFlags |= SQSSL_WRONG_USAGE;
				epp.fdwChecks  |= 0x00000200;   /* SECURITY_FLAG_IGNORE_WRONG_USAGE */
			case CERT_E_REVOKED:
				if(ssl->certFlags & SQSSL_CERT_REVOKED) goto done;
				ssl->certFlags |= SQSSL_CERT_REVOKED;
				epp.fdwChecks  |= 0x00000080;   /* SECURITY_FLAG_IGNORE_REVOCATION */
				break;
			default:
				ssl->certFlags |= SQSSL_OTHER_ISSUE;
				goto done;
		}
	}
done:
	CertFreeCertificateChain(chainContext);
	CertFreeCertificateContext(certHandle);
	return 1;
}
Пример #20
0
int sserver_connect(const struct protocol_interface *protocol, int verify_only)
{
	char crypt_password[64];
	char server_version[128];
	char tmp_keyname[256];
	const char *begin_request = "BEGIN SSL AUTH REQUEST";
	const char *end_request = "END SSL AUTH REQUEST";
	const char *username = NULL;
	const char *cert = current_server()->current_root->optional_3;
	int l;
	int sserver_version = 0;
	int strict = 0;
	CScramble scramble;
	bool send_client_version = false;

	if(current_server()->current_root->optional_1)
	{
	  sserver_version = atoi(current_server()->current_root->optional_1);
	  if(sserver_version != 0 && sserver_version != 1)
	  {
	    server_error(0,"version must be one of:");
	    server_error(0,"0 - All CVSNT-type servers");
	    server_error(0,"1 - Unix server using Corey Minards' sserver patches");
	    server_error(1,"Please specify a valid value");
	  }
	}

	if(!CGlobalSettings::GetUserValue("cvsnt","sserver","StrictChecking",server_version,sizeof(server_version)))
	{
	  strict = atoi(server_version);
	}

	if(!cert && !CGlobalSettings::GetUserValue("cvsnt","sserver","ClientCert",tmp_keyname,sizeof(tmp_keyname)))
	{
	  cert = tmp_keyname;
	}

	if(current_server()->current_root->optional_2)
		strict = atoi(current_server()->current_root->optional_2);

	if(sserver_version == 1) /* Old sserver */
	{
	  begin_request = verify_only?"BEGIN SSL VERIFICATION REQUEST":"BEGIN SSL REQUEST";
	  end_request = verify_only?"END SSL VERIFICATION REQUEST":"END SSL REQUEST";
	}
	else if(verify_only)
	{
		begin_request = "BEGIN SSL VERIFICATION REQUEST";
		end_request = "END SSL VERIFICATION REQUEST";
	}
	username = get_username(current_server()->current_root);

	if(!username || !current_server()->current_root->hostname || !current_server()->current_root->directory)
		return CVSPROTO_BADPARMS;

	if(tcp_connect(current_server()->current_root))
		return CVSPROTO_FAIL;
	if(current_server()->current_root->password)
		strncpy(crypt_password,scramble.Scramble(current_server()->current_root->password),sizeof(crypt_password));
	else
	{
		if(sserver_get_user_password(username,current_server()->current_root->hostname,current_server()->current_root->port,current_server()->current_root->directory,crypt_password,sizeof(crypt_password)))
		{
			/* Using null password - trace something out here */
			server_error(0,"Using an empty password; you may need to do 'cvs login' with a real password\n");
			strncpy(crypt_password,scramble.Scramble(""),sizeof(crypt_password));
		}
	}

	if(sserver_version == 0) /* Pre-CVSNT had no version check */
	{
	  if(tcp_printf("%s\n",begin_request)<0)
		return CVSPROTO_FAIL;
	  for(;;)
	  {
		*server_version='\0';
		if((l=tcp_readline(server_version,sizeof(server_version))<0))
			return CVSPROTO_FAIL;
		if(*server_version)
			break;
#ifdef _WIN32
		Sleep(10);
#else
		usleep(10);
#endif
	  }
	  if(strncmp(server_version,"SSERVER ",8))
	  {
	  	  server_error(0,"%s\n",server_version);
		  return CVSPROTO_FAIL;
	  }
	  if(strncmp(server_version+8,"1.0 ",4))
		  send_client_version = true;
	}

	if(!ClientAuthenticate(cert,current_server()->current_root->hostname))
		return CVSPROTO_AUTHFAIL;

	QueryContextAttributes(&contextHandle,SECPKG_ATTR_STREAM_SIZES,&secSizes);

	PCERT_CONTEXT sc;
	PCCERT_CHAIN_CONTEXT pcc;
	CERT_SIMPLE_CHAIN  *psc;
	CERT_CHAIN_PARA para = { sizeof(CERT_CHAIN_PARA) };
	DWORD trust,rc;
	
	rc = QueryContextAttributes(&contextHandle,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&sc);
	if(rc)
		server_error(1,"Couldn't get server certificate");

	if(!CertGetCertificateChain(NULL, sc, NULL, NULL, &para, 0, NULL, &pcc))
		server_error(1,"Couldn't get server certificate chain");

    psc = pcc->rgpChain[0];
	trust = psc->TrustStatus.dwErrorStatus;
 
    if (trust)
    {
        if (trust & (CERT_TRUST_IS_PARTIAL_CHAIN | CERT_TRUST_IS_UNTRUSTED_ROOT))
            ; // Seld signed
        else if (trust & (CERT_TRUST_IS_NOT_TIME_VALID))
			server_error(1,"Server certificate expired");
        else
			server_error(1,"Server certificate verification failed - %08x",trust);
    }

	if(strict)
	{
		char certname[256];

		CertGetNameString(sc, CERT_NAME_DNS_TYPE, 0, NULL, certname, sizeof(certname));
		  if(strcasecmp(certname,current_server()->current_root->hostname))
			server_error(1, "Certificate CommonName '%s' does not match server name '%s'\n",certname,current_server()->current_root->hostname);
	}

	CertFreeCertificateChain(pcc);
	FreeContextBuffer(sc);
 
	g_sslBufferInPos=g_sslBufferOutPos=0;
	g_sslBufferInLen=g_sslBufferOutLen=0;

	if(sserver_version == 1)
	{
	  if(sserver_printf("%s\n",begin_request)<0)
		return CVSPROTO_FAIL;
	}

    // For server versions 1.1+ send CLIENT_VERSION_STRING
	if(send_client_version && sserver_printf(SSERVER_CLIENT_VERSION_STRING)<0)
		return CVSPROTO_FAIL;
	if(sserver_printf("%s\n%s\n",current_server()->current_root->directory,username)<0)
		return CVSPROTO_FAIL;
	if(sserver_printf("%s\n",crypt_password)<0)
		return CVSPROTO_FAIL;
	if(sserver_printf("%s\n",end_request)<0)
		return CVSPROTO_FAIL;
	return CVSPROTO_SUCCESS;
}
Пример #21
0
Файл: net.c Проект: bilboed/wine
static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, HCERTSTORE store,
                                  WCHAR *server )
{
    BOOL ret;
    CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
    PCCERT_CHAIN_CONTEXT chain;
    char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
    char *server_auth[] = { oid_server_auth };
    DWORD err = ERROR_SUCCESS;

    TRACE("verifying %s\n", debugstr_w( server ));
    chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
    chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
    if ((ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara, 0,
                                        NULL, &chain )))
    {
        if (chain->TrustStatus.dwErrorStatus)
        {
            if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID)
                err = ERROR_WINHTTP_SECURE_CERT_DATE_INVALID;
            else if (chain->TrustStatus.dwErrorStatus &
                     CERT_TRUST_IS_UNTRUSTED_ROOT)
                err = ERROR_WINHTTP_SECURE_INVALID_CA;
            else if ((chain->TrustStatus.dwErrorStatus &
                      CERT_TRUST_IS_OFFLINE_REVOCATION) ||
                     (chain->TrustStatus.dwErrorStatus &
                      CERT_TRUST_REVOCATION_STATUS_UNKNOWN))
                err = ERROR_WINHTTP_SECURE_CERT_REV_FAILED;
            else if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED)
                err = ERROR_WINHTTP_SECURE_CERT_REVOKED;
            else if (chain->TrustStatus.dwErrorStatus &
                CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
                err = ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE;
            else
                err = ERROR_WINHTTP_SECURE_INVALID_CERT;
        }
        else
        {
            CERT_CHAIN_POLICY_PARA policyPara;
            SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
            CERT_CHAIN_POLICY_STATUS policyStatus;

            sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
            sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
            sslExtraPolicyPara.pwszServerName = server;
            policyPara.cbSize = sizeof(policyPara);
            policyPara.dwFlags = 0;
            policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
            ret = CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL,
                                                    chain, &policyPara,
                                                    &policyStatus );
            /* Any error in the policy status indicates that the
             * policy couldn't be verified.
             */
            if (ret && policyStatus.dwError)
            {
                if (policyStatus.dwError == CERT_E_CN_NO_MATCH)
                    err = ERROR_WINHTTP_SECURE_CERT_CN_INVALID;
                else
                    err = ERROR_WINHTTP_SECURE_INVALID_CERT;
            }
        }
        CertFreeCertificateChain( chain );
    }
    else
        err = ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
    TRACE("returning %08x\n", err);
    return err;
}
Пример #22
0
static CURLcode verify_certificate(struct connectdata *conn, int sockindex)
{
  SECURITY_STATUS status;
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  CURLcode result = CURLE_OK;
  CERT_CONTEXT *pCertContextServer = NULL;
  const CERT_CHAIN_CONTEXT *pChainContext = NULL;

  status = s_pSecFn->QueryContextAttributes(&connssl->ctxt->ctxt_handle,
                                            SECPKG_ATTR_REMOTE_CERT_CONTEXT,
                                            &pCertContextServer);

  if((status != SEC_E_OK) || (pCertContextServer == NULL)) {
    failf(data, "schannel: Failed to read remote certificate context: %s",
          Curl_sspi_strerror(conn, status));
    result = CURLE_PEER_FAILED_VERIFICATION;
  }

  if(result == CURLE_OK) {
    CERT_CHAIN_PARA ChainPara;
    memset(&ChainPara, 0, sizeof(ChainPara));
    ChainPara.cbSize = sizeof(ChainPara);

    if(!CertGetCertificateChain(NULL,
                                pCertContextServer,
                                NULL,
                                pCertContextServer->hCertStore,
                                &ChainPara,
                                0,
                                NULL,
                                &pChainContext)) {
      failf(data, "schannel: CertGetCertificateChain failed: %s",
            Curl_sspi_strerror(conn, GetLastError()));
      pChainContext = NULL;
      result = CURLE_PEER_FAILED_VERIFICATION;
    }

    if(result == CURLE_OK) {
      CERT_SIMPLE_CHAIN *pSimpleChain = pChainContext->rgpChain[0];
      DWORD dwTrustErrorMask = ~(DWORD)(CERT_TRUST_IS_NOT_TIME_NESTED|
                                 CERT_TRUST_REVOCATION_STATUS_UNKNOWN);
      dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus;
      if(dwTrustErrorMask) {
        if(dwTrustErrorMask & CERT_TRUST_IS_PARTIAL_CHAIN)
          failf(data, "schannel: CertGetCertificateChain trust error"
                      " CERT_TRUST_IS_PARTIAL_CHAIN");
        if(dwTrustErrorMask & CERT_TRUST_IS_UNTRUSTED_ROOT)
          failf(data, "schannel: CertGetCertificateChain trust error"
                      " CERT_TRUST_IS_UNTRUSTED_ROOT");
        if(dwTrustErrorMask & CERT_TRUST_IS_NOT_TIME_VALID)
          failf(data, "schannel: CertGetCertificateChain trust error"
                      " CERT_TRUST_IS_NOT_TIME_VALID");
        failf(data, "schannel: CertGetCertificateChain error mask: 0x%08x",
              dwTrustErrorMask);
        result = CURLE_PEER_FAILED_VERIFICATION;
      }
    }
  }

  if(result == CURLE_OK) {
    if(data->set.ssl.verifyhost) {
      TCHAR cert_hostname_buff[128];
      xcharp_u hostname;
      xcharp_u cert_hostname;
      DWORD len;

      cert_hostname.const_tchar_ptr = cert_hostname_buff;
      hostname.tchar_ptr = Curl_convert_UTF8_to_tchar(conn->host.name);

      len = CertGetNameString(pCertContextServer,
                              CERT_NAME_DNS_TYPE,
                              0,
                              NULL,
                              cert_hostname.tchar_ptr,
                              128);
      if(len > 0 && *cert_hostname.tchar_ptr == '*') {
        /* this is a wildcard cert.  try matching the last len - 1 chars */
        int hostname_len = strlen(conn->host.name);
        cert_hostname.tchar_ptr++;
        if(_tcsicmp(cert_hostname.const_tchar_ptr,
                    hostname.const_tchar_ptr + hostname_len - len + 2) != 0)
          result = CURLE_PEER_FAILED_VERIFICATION;
      }
      else if(len == 0 || _tcsicmp(hostname.const_tchar_ptr,
                                   cert_hostname.const_tchar_ptr) != 0) {
        result = CURLE_PEER_FAILED_VERIFICATION;
      }
      if(result == CURLE_PEER_FAILED_VERIFICATION) {
        char *_cert_hostname;
        _cert_hostname = Curl_convert_tchar_to_UTF8(cert_hostname.tchar_ptr);
        failf(data, "schannel: CertGetNameString() certificate hostname "
              "(%s) did not match connection (%s)",
              _cert_hostname, conn->host.name);
        Curl_unicodefree(_cert_hostname);
      }
      Curl_unicodefree(hostname.tchar_ptr);
    }
  }

  if(pChainContext)
    CertFreeCertificateChain(pChainContext);

  if(pCertContextServer)
    CertFreeCertificateContext(pCertContextServer);

  return result;
}
Пример #23
0
static bool VerifyCertificate(SslHandle *ssl, PCSTR pszServerName, DWORD dwCertFlags)
{
	static LPSTR rgszUsages[] =
	{
		szOID_PKIX_KP_SERVER_AUTH,
		szOID_SERVER_GATED_CRYPTO,
		szOID_SGC_NETSCAPE
	};

	CERT_CHAIN_PARA          ChainPara = { 0 };
	HTTPSPolicyCallbackData  polHttps = { 0 };
	CERT_CHAIN_POLICY_PARA   PolicyPara = { 0 };
	CERT_CHAIN_POLICY_STATUS PolicyStatus = { 0 };
	PCCERT_CHAIN_CONTEXT     pChainContext = NULL;
	PCCERT_CONTEXT           pServerCert = NULL;
	DWORD scRet;

	PWSTR pwszServerName = mir_a2u(pszServerName);

	scRet = g_pSSPI->QueryContextAttributes(&ssl->hContext, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &pServerCert);
	if (scRet != SEC_E_OK)
		goto cleanup;

	if (pServerCert == NULL) {
		scRet = SEC_E_WRONG_PRINCIPAL;
		goto cleanup;
	}

	ChainPara.cbSize = sizeof(ChainPara);
	ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
	ChainPara.RequestedUsage.Usage.cUsageIdentifier = _countof(rgszUsages);
	ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = rgszUsages;

	if (!CertGetCertificateChain(NULL, pServerCert, NULL, pServerCert->hCertStore, &ChainPara, 0, NULL, &pChainContext)) {
		scRet = GetLastError();
		goto cleanup;
	}

	polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData);
	polHttps.dwAuthType = AUTHTYPE_SERVER;
	polHttps.fdwChecks = dwCertFlags;
	polHttps.pwszServerName = pwszServerName;

	PolicyPara.cbSize = sizeof(PolicyPara);
	PolicyPara.pvExtraPolicyPara = &polHttps;

	PolicyStatus.cbSize = sizeof(PolicyStatus);

	if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, pChainContext, &PolicyPara, &PolicyStatus)) {
		scRet = GetLastError();
		goto cleanup;
	}

	if (PolicyStatus.dwError) {
		scRet = PolicyStatus.dwError;
		goto cleanup;
	}

	scRet = SEC_E_OK;

cleanup:
	if (pChainContext)
		CertFreeCertificateChain(pChainContext);
	if (pServerCert)
		CertFreeCertificateContext(pServerCert);
	mir_free(pwszServerName);

	ReportSslError(scRet, __LINE__, true);
	return scRet == SEC_E_OK;
}
Пример #24
0
/***********************************************************************
 *		CertTrustFinalPolicy (CRYPTDLG.@)
 */
HRESULT WINAPI CertTrustFinalPolicy(CRYPT_PROVIDER_DATA *data)
{
    BOOL ret;
    DWORD err = S_OK;
    CERT_VERIFY_CERTIFICATE_TRUST *pCert = CRYPTDLG_GetVerifyData(data);

    TRACE("(%p)\n", data);

    if (data->pWintrustData->dwUIChoice != WTD_UI_NONE)
        FIXME("unimplemented for UI choice %d\n",
         data->pWintrustData->dwUIChoice);
    if (pCert)
    {
        DWORD flags = 0;
        CERT_CHAIN_PARA chainPara;
        HCERTCHAINENGINE engine;

        memset(&chainPara, 0, sizeof(chainPara));
        chainPara.cbSize = sizeof(chainPara);
        if (CRYPTDLG_CheckOnlineCRL())
            flags |= CERT_CHAIN_REVOCATION_CHECK_END_CERT;
        engine = CRYPTDLG_MakeEngine(pCert);
        GetSystemTimeAsFileTime(&data->sftSystemTime);
        ret = CRYPTDLG_IsCertAllowed(pCert->pccert);
        if (ret)
        {
            PCCERT_CHAIN_CONTEXT chain;

            ret = CertGetCertificateChain(engine, pCert->pccert,
             &data->sftSystemTime, NULL, &chainPara, flags, NULL, &chain);
            if (ret)
            {
                if (chain->cChain != 1)
                {
                    FIXME("unimplemented for more than 1 simple chain\n");
                    err = TRUST_E_SUBJECT_FORM_UNKNOWN;
                    ret = FALSE;
                }
                else if ((ret = CRYPTDLG_CopyChain(data, chain)))
                {
                    if (CertVerifyTimeValidity(&data->sftSystemTime,
                     pCert->pccert->pCertInfo))
                    {
                        ret = FALSE;
                        err = CERT_E_EXPIRED;
                    }
                }
                else
                    err = TRUST_E_SYSTEM_ERROR;
                CertFreeCertificateChain(chain);
            }
            else
                err = TRUST_E_SUBJECT_NOT_TRUSTED;
        }
        CertFreeCertificateChainEngine(engine);
    }
    else
    {
        ret = FALSE;
        err = TRUST_E_NOSIGNATURE;
    }
    /* Oddly, native doesn't set the error in the trust step error location,
     * probably because this action is more advisory than anything else.
     * Instead it stores it as the final error, but the function "succeeds" in
     * any case.
     */
    if (!ret)
        data->dwFinalError = err;
    TRACE("returning %d (%08x)\n", S_OK, data->dwFinalError);
    return S_OK;
}
Пример #25
0
static void check_and_store_certs(HCERTSTORE from, HCERTSTORE to)
{
    DWORD root_count = 0;
    CERT_CHAIN_ENGINE_CONFIG chainEngineConfig =
     { sizeof(chainEngineConfig), 0 };
    HCERTCHAINENGINE engine;

    TRACE("\n");

    CertDuplicateStore(to);
    engine = CRYPT_CreateChainEngine(to, CERT_SYSTEM_STORE_CURRENT_USER, &chainEngineConfig);
    if (engine)
    {
        PCCERT_CONTEXT cert = NULL;

        do {
            cert = CertEnumCertificatesInStore(from, cert);
            if (cert)
            {
                CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
                PCCERT_CHAIN_CONTEXT chain;
                BOOL ret;

                ret = CertGetCertificateChain(engine, cert, NULL, from,
                 &chainPara, CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL, NULL, &chain);
                if (!ret)
                    TRACE("rejecting %s: %s\n", get_cert_common_name(cert),
                     "chain creation failed");
                else
                {
                    DWORD allowedErrors = CERT_TRUST_IS_UNTRUSTED_ROOT |
                     CERT_TRUST_IS_NOT_VALID_FOR_USAGE |
                     CERT_TRUST_INVALID_BASIC_CONSTRAINTS |
                     CERT_TRUST_IS_NOT_TIME_VALID;

                    /* The certificate chain verification only allows certain
                     * invalid CA certs if they're installed locally:  CA
                     * certs missing the key usage extension, and CA certs
                     * missing the basic constraints extension.  Of course
                     * there's a chicken and egg problem:  we have to accept
                     * them here in order for them to be accepted later.
                     * Expired, locally installed certs are also allowed here,
                     * because we don't know (yet) what date will be checked
                     * for an item signed by one of these certs.
                     * Thus, accept certs with any of the allowed errors.
                     */
                    if (chain->TrustStatus.dwErrorStatus & ~allowedErrors)
                        TRACE("rejecting %s: %s\n", get_cert_common_name(cert),
                         trust_status_to_str(chain->TrustStatus.dwErrorStatus &
                         ~CERT_TRUST_IS_UNTRUSTED_ROOT));
                    else
                    {
                        DWORD i, j;

                        for (i = 0; i < chain->cChain; i++)
                            for (j = 0; j < chain->rgpChain[i]->cElement; j++)
                                if (CertAddCertificateContextToStore(to,
                                 chain->rgpChain[i]->rgpElement[j]->pCertContext,
                                 CERT_STORE_ADD_NEW, NULL))
                                    root_count++;
                    }
                    CertFreeCertificateChain(chain);
                }
            }
        } while (cert);
        CertFreeCertificateChainEngine(engine);
    }
    TRACE("Added %d root certificates\n", root_count);
}
Пример #26
0
Файл: net.c Проект: mikekap/wine
static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, HCERTSTORE store,
                                  WCHAR *server, DWORD security_flags )
{
    BOOL ret;
    CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
    PCCERT_CHAIN_CONTEXT chain;
    char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
    char *server_auth[] = { oid_server_auth };
    DWORD err = ERROR_SUCCESS;

    TRACE("verifying %s\n", debugstr_w( server ));
    chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
    chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
    if ((ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara,
                                        CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
                                        NULL, &chain )))
    {
        if (chain->TrustStatus.dwErrorStatus)
        {
            static const DWORD supportedErrors =
                CERT_TRUST_IS_NOT_TIME_VALID |
                CERT_TRUST_IS_UNTRUSTED_ROOT |
                CERT_TRUST_IS_NOT_VALID_FOR_USAGE;

            if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID)
            {
                if (!(security_flags & SECURITY_FLAG_IGNORE_CERT_DATE_INVALID))
                    err = ERROR_WINHTTP_SECURE_CERT_DATE_INVALID;
            }
            else if (chain->TrustStatus.dwErrorStatus &
                     CERT_TRUST_IS_UNTRUSTED_ROOT)
            {
                if (!(security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA))
                    err = ERROR_WINHTTP_SECURE_INVALID_CA;
            }
            else if ((chain->TrustStatus.dwErrorStatus &
                      CERT_TRUST_IS_OFFLINE_REVOCATION) ||
                     (chain->TrustStatus.dwErrorStatus &
                      CERT_TRUST_REVOCATION_STATUS_UNKNOWN))
                err = ERROR_WINHTTP_SECURE_CERT_REV_FAILED;
            else if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED)
                err = ERROR_WINHTTP_SECURE_CERT_REVOKED;
            else if (chain->TrustStatus.dwErrorStatus &
                CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
            {
                if (!(security_flags & SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE))
                    err = ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE;
            }
            else if (chain->TrustStatus.dwErrorStatus & ~supportedErrors)
                err = ERROR_WINHTTP_SECURE_INVALID_CERT;
        }
        if (!err)
        {
            CERT_CHAIN_POLICY_PARA policyPara;
            SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
            CERT_CHAIN_POLICY_STATUS policyStatus;
            CERT_CHAIN_CONTEXT chainCopy;

            /* Clear chain->TrustStatus.dwErrorStatus so
             * CertVerifyCertificateChainPolicy will verify additional checks
             * rather than stopping with an existing, ignored error.
             */
            memcpy(&chainCopy, chain, sizeof(chainCopy));
            chainCopy.TrustStatus.dwErrorStatus = 0;
            sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
            sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
            sslExtraPolicyPara.pwszServerName = server;
            sslExtraPolicyPara.fdwChecks = security_flags;
            policyPara.cbSize = sizeof(policyPara);
            policyPara.dwFlags = 0;
            policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
            ret = CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL,
                                                    &chainCopy, &policyPara,
                                                    &policyStatus );
            /* Any error in the policy status indicates that the
             * policy couldn't be verified.
             */
            if (ret && policyStatus.dwError)
            {
                if (policyStatus.dwError == CERT_E_CN_NO_MATCH)
                    err = ERROR_WINHTTP_SECURE_CERT_CN_INVALID;
                else
                    err = ERROR_WINHTTP_SECURE_INVALID_CERT;
            }
        }
        CertFreeCertificateChain( chain );
    }
    else
        err = ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
    TRACE("returning %08x\n", err);
    return err;
}
/*****************************************************************************
 wmain

*****************************************************************************/
DWORD
__cdecl
wmain(
    int     argc,
    LPWSTR  argv[]
    )
{
    HRESULT                     hr = S_OK;
    int                         i = 0;

    BOOL                        fPeerTrust      = FALSE;
    DWORD                       dwChainFlags    = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
    LPCWSTR                     wsCertFile      = NULL;
    LPCWSTR                     wsStoreFile     = NULL;
    PCCERT_CONTEXT              pCert           = NULL;
    HCERTSTORE                  hStore          = NULL;
    HCERTCHAINENGINE            hChainEngine    = NULL;
    PCCERT_CHAIN_CONTEXT        pChainContext   = NULL;

	CERT_ENHKEY_USAGE           EnhkeyUsage     = {0};
	CERT_USAGE_MATCH            CertUsage       = {0};  
	CERT_CHAIN_PARA             ChainPara       = {0};
	CERT_CHAIN_POLICY_PARA      ChainPolicy     = {0};
	CERT_CHAIN_POLICY_STATUS    PolicyStatus    = {0};
    CERT_CHAIN_ENGINE_CONFIG    EngineConfig    = {0};

	//---------------------------------------------------------
    // Initialize data structures for chain building.

    EnhkeyUsage.cUsageIdentifier = 0;
    EnhkeyUsage.rgpszUsageIdentifier=NULL;
    
	CertUsage.dwType = USAGE_MATCH_TYPE_AND;
    CertUsage.Usage  = EnhkeyUsage;

    ChainPara.cbSize = sizeof(ChainPara);
    ChainPara.RequestedUsage=CertUsage;

    ChainPolicy.cbSize = sizeof(ChainPolicy);

    PolicyStatus.cbSize = sizeof(PolicyStatus);

    EngineConfig.cbSize = sizeof(EngineConfig);
    EngineConfig.dwUrlRetrievalTimeout = 0;

    //
    // options
    //

    for( i=1; i<argc; i++ )
    {
        if ( lstrcmpW (argv[i], L"/?") == 0 ||
             lstrcmpW (argv[i], L"-?") == 0 ) 
        {
            Usage(argv[0]);
            goto CleanUp;
        }

        if( *argv[i] != L'-' )
            break;

        if ( lstrcmpW (argv[i], L"-fc") == 0 )
        {
            if( i+1 >= argc )
            {
                goto InvalidCommandLine;
            }
            
            dwChainFlags = (DWORD)wcstoul( argv[++i], NULL, 0 );
        }
        else
        if ( lstrcmpW (argv[i], L"-fe") == 0 )
        {
            if( i+1 >= argc )
            {
                goto InvalidCommandLine;
            }
            
            EngineConfig.dwFlags = (DWORD)wcstoul( argv[++i], NULL, 0 );
        }
        else
        if ( lstrcmpW (argv[i], L"-p") == 0 )
        {
            fPeerTrust = TRUE;
        }
        else
        {
            goto InvalidCommandLine;
        }
    }

    if( i >= argc )
    {
        goto InvalidCommandLine;
    }

    wsStoreFile = argv[i++];

    if( i < argc )
    {
        wsCertFile = argv[i];
    }

    hStore = CertOpenStore(
                            CERT_STORE_PROV_FILENAME_W,
                            X509_ASN_ENCODING,
                            NULL,
                            CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
                            wsStoreFile
                            );
    if( NULL == hStore )
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        goto CleanUp;
    }

    if( NULL != wsCertFile && 0 != *wsCertFile )
    {
        if( !CryptQueryObject(
                            CERT_QUERY_OBJECT_FILE,
                            wsCertFile,
                            CERT_QUERY_CONTENT_FLAG_CERT |
                            CERT_QUERY_CONTENT_SERIALIZED_CERT
                            ,
                            CERT_QUERY_FORMAT_FLAG_ALL,
                            0,      // dwFlags,
                            0,      // pdwMsgAndCertEncodingType,
                            0,      // pdwContentType,
                            0,      // pdwFormatType,
                            0,      // phCertStore,
                            0,      // phMsg,
                            (const void**)&pCert
                            ))
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            goto CleanUp;
        }
    }
    else
    {
        pCert = CertFindCertificateInStore(
                            hStore,
                            X509_ASN_ENCODING,
                            0,
                            CERT_FIND_ANY,
                            NULL,
                            NULL
                            );
        if( NULL == pCert )
        {
            hr = CRYPT_E_NOT_FOUND;
            goto CleanUp;
        }
    }

    if( fPeerTrust )
    {
        EngineConfig.hExclusiveTrustedPeople = hStore;      // Exclusive peer trust
        dwChainFlags |= CERT_CHAIN_ENABLE_PEER_TRUST;
    }
    else
    {
        EngineConfig.hExclusiveRoot = hStore;               // Exclusive root
    }

	//---------------------------------------------------------
    // Create chain engine.
    
    if( !CertCreateCertificateChainEngine(
                                &EngineConfig,
                                &hChainEngine
                                ))
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        goto CleanUp;
    }

    //-------------------------------------------------------------------
    // Build a chain using CertGetCertificateChain
    
    if( !CertGetCertificateChain(
                                hChainEngine,           
                                pCert,                 // pointer to the end certificate
                                NULL,                  // use the default time
                                NULL,                  // search no additional stores
                                &ChainPara,            // use AND logic and enhanced key usage 
                                                       //  as indicated in the ChainPara 
                                                       //  data structure
                                dwChainFlags,
                                NULL,                  // currently reserved
                                &pChainContext ))      // return a pointer to the chain created
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        goto CleanUp;
    }

    //---------------------------------------------------------------
    // Verify that the chain complies with policy

    if( !CertVerifyCertificateChainPolicy(
                                CERT_CHAIN_POLICY_BASE, // use the base policy
                                pChainContext,          // pointer to the chain    
                                &ChainPolicy,             
                                &PolicyStatus ))        // return a pointer to the policy status
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        goto CleanUp;
    }

    if( PolicyStatus.dwError != S_OK ) 
    {
        hr = PolicyStatus.dwError;

		// Instruction: If the PolicyStatus.dwError is CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, it indicates errors in obtaining
		//				revocation information. These can be ignored since the retrieval of revocation information depends on network availability

        goto CleanUp;
	}

    wprintf( L"CertVerifyCertificateChainPolicy succeeded.\n" );

    hr = S_OK;

    //
    // END
    //

    goto CleanUp;

    //
    // Invalid Command Line
    //

InvalidCommandLine:

    if( i < argc )
    {
        wprintf( L"Invalid command line '%s'\n", argv[i] );
    }
    else
        Usage(argv[0]);

    hr = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );

CleanUp:

    if( FAILED(hr) )
    {
        ReportError( NULL, hr );
    }

    if( NULL != pChainContext )
    {
        CertFreeCertificateChain( pChainContext );
    }

    if( NULL != hChainEngine )
    {
        CertFreeCertificateChainEngine( hChainEngine );
    }

    if( NULL != pCert )
    {
        CertFreeCertificateContext( pCert );
    }

    if( NULL != hStore )
    {
        CertCloseStore( hStore, 0 );
    }

    return (DWORD)hr;
} // end main