Ejemplo n.º 1
0
DWORD StoreUserCert (PCCERT_CONTEXT pCertContext, unsigned char KeyUsageBits, CK_BYTE* cardSerialNumber, CK_ULONG cardSerialNumberLen)
{
	unsigned long dwFlags 		= CERT_STORE_NO_CRYPT_RELEASE_FLAG;
	PCCERT_CONTEXT  pDesiredCert	= NULL;
	PCCERT_CONTEXT  pPrevCert		= NULL;
	DWORD dwRet					= 0;
	wchar_t* pContainerName		= NULL;
	size_t pContainerNameCharLen = cardSerialNumberLen+20;
	CK_CHAR_PTR pcardSerialNrString = NULL;
	wchar_t* pProviderName		= NULL;
	CK_ULONG counter=0;
	HCERTSTORE hMyStore 		= CertOpenSystemStore((HCRYPTPROV_LEGACY)NULL, TEXT("MY"));


	CRYPT_KEY_PROV_INFO cryptKeyProvInfo;
	unsigned long dwPropId = CERT_KEY_PROV_INFO_PROP_ID;

	if (hMyStore == NULL)
	{
		dwRet = GetLastError();
		printf("StoreUserCerts: Unable to open the system certificate store. Error code: %d.\n",dwRet);
		return dwRet;
	}

		// ----------------------------------------------------
		// look if we already have a certificate with the same 
		// subject (contains name and NNR) in the store
		// If the certificate is not found --> NULL
		// ----------------------------------------------------
		do
		{
			if( NULL != (pDesiredCert = CertFindCertificateInStore(hMyStore, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_NAME, &(pCertContext->pCertInfo->Subject) , pPrevCert)))
			{
				// ----------------------------------------------------
				// If the certificates are identical and function 
				// succeeds, the return value is nonzero, or TRUE.
				// ----------------------------------------------------
				if(FALSE == CertCompareCertificate(X509_ASN_ENCODING,pCertContext->pCertInfo,pDesiredCert->pCertInfo) || !ProviderNameCorrect(pDesiredCert) )
				{
					// ----------------------------------------------------
					// certificates are not identical, but have the same 
					// subject (contains name and NNR),
					// so we remove the one that was already in the store
					// ----------------------------------------------------
					if(FALSE == CertDeleteCertificateFromStore(pDesiredCert))
					{
						if (E_ACCESSDENIED == GetLastError())
						{
							continue;
						}
					}
					pPrevCert = NULL;
					continue;
				}
			}
			pPrevCert = pDesiredCert;
		}while (NULL != pDesiredCert);

	// ----------------------------------------------------
	// look if we already have the certificate in the store
	// If the certificate is not found --> NULL
	// ----------------------------------------------------
	if( NULL != (pDesiredCert = CertFindCertificateInStore(hMyStore, X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, pCertContext , NULL)))
	{
		// ----------------------------------------------------
		// certificate is already in the store, then just return
		// ----------------------------------------------------
		CertFreeCertificateContext(pDesiredCert);
		CertCloseStore (hMyStore, CERT_CLOSE_STORE_FORCE_FLAG);
		return 0;
	}

	pContainerName = (wchar_t*)malloc(sizeof(wchar_t) * (pContainerNameCharLen));
	if(pContainerName == NULL)
		return E_OUTOFMEMORY;
	pcardSerialNrString = (CK_CHAR_PTR)malloc(cardSerialNumberLen*2 + 1);
	if(pcardSerialNrString == NULL)
		return E_OUTOFMEMORY;

	if(-1 == ByteArrayToString( &pcardSerialNrString, cardSerialNumberLen*2 + 1,cardSerialNumber ,cardSerialNumberLen))
		return -1;

	if(pContainerName == NULL)
	{
		CertFreeCertificateContext(pDesiredCert);
		CertCloseStore (hMyStore, CERT_CLOSE_STORE_FORCE_FLAG);
		return -1;
	}
	if (UseMinidriver())
	{
		if (KeyUsageBits & CERT_NON_REPUDIATION_KEY_USAGE)
		{
			swprintf_s(pContainerName,pContainerNameCharLen,L"NR_%hS",pcardSerialNrString);
		}
		else
		{
			swprintf_s(pContainerName,pContainerNameCharLen,L"DS_%hS",pcardSerialNrString);
		}
		cryptKeyProvInfo.pwszProvName			= L"Microsoft Base Smart Card Crypto Provider";
		cryptKeyProvInfo.dwKeySpec			= AT_SIGNATURE;
	}
	else
	{
		if (KeyUsageBits & CERT_NON_REPUDIATION_KEY_USAGE)
		{
			swprintf_s(pContainerName,pContainerNameCharLen,L"Signature(%hS)",pcardSerialNrString);
		}
		else
		{
			swprintf_s(pContainerName,pContainerNameCharLen,L"Authentication(%hS)",pcardSerialNrString);
		}

		cryptKeyProvInfo.pwszProvName		= L"Belgium Identity Card CSP";
		cryptKeyProvInfo.dwKeySpec		= AT_KEYEXCHANGE;
	}
	cryptKeyProvInfo.pwszContainerName	= pContainerName;

	cryptKeyProvInfo.dwProvType = PROV_RSA_FULL;
	cryptKeyProvInfo.dwFlags = 0;
	cryptKeyProvInfo.cProvParam = 0;
	cryptKeyProvInfo.rgProvParam = NULL;


/*
			// Set friendly names for the certificates
			DWORD dwsize = 0;
			dwsize = CertGetNameStringW(pCertContext, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, NULL, dwsize);
			auto_vec<WCHAR> pname(new WCHAR[dwsize]);
			dwsize = CertGetNameStringW(pCertContext, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, pname.get(), dwsize);
			CRYPT_DATA_BLOB tpFriendlyName = {0, 0};
			tpFriendlyName.pbData = (BYTE *)pname.get();
			tpFriendlyName.cbData = dwsize * sizeof(WCHAR);

			if (CertSetCertificateContextProperty(
				pCertContext,       // A pointer to the certificate
				// where the propertiy will be set.
				CERT_FRIENDLY_NAME_PROP_ID,           // An identifier of the property to be set. 
				// In this case, CERT_KEY_PROV_INFO_PROP_ID
				// is to be set to provide a pointer with the
				// certificate to its associated private key 
				// container.
				dwFlags,            // The flag used in this case is   
				// CERT_STORE_NO_CRYPT_RELEASE_FLAG
				// indicating that the cryptographic 
				// context aquired should not
				// be released when the function finishes.
				&tpFriendlyName   // A pointer to a data structure that holds
				// infomation on the private key container to
				// be associated with this certificate.
				))
*/

	// Set the property.
	if (CertSetCertificateContextProperty(
		pCertContext, 		// A pointer to the certificate where the property will be set.
		dwPropId, 			// An identifier of the property to be set.
		// In this case, CERT_KEY_PROV_INFO_PROP_ID is to be set to provide a pointer with the certificate to its associated private key container.
		dwFlags, 			// The flag used in this case is
		// CERT_STORE_NO_CRYPT_RELEASE_FLAG indicating that the cryptographic context acquired should not be released when the function finishes.
		&cryptKeyProvInfo 	// A pointer to a data structure that holds infomation on the private key container to be associated with this certificate.
		))
	{
		if (KeyUsageBits & CERT_NON_REPUDIATION_KEY_USAGE)
		{
			CertAddEnhancedKeyUsageIdentifier (pCertContext, szOID_PKIX_KP_EMAIL_PROTECTION);
		}
		else
		{
			CertAddEnhancedKeyUsageIdentifier (pCertContext, szOID_PKIX_KP_EMAIL_PROTECTION);
			CertAddEnhancedKeyUsageIdentifier (pCertContext, szOID_PKIX_KP_CLIENT_AUTH);
		}
		if (CertAddCertificateContextToStore(hMyStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL))
		{
			printf("StoreUserCerts: Certificate context added to store.");
			dwRet = 0;
		}
		else
		{
			dwRet = GetLastError();
			printf("StoreUserCerts: Unable to add certificate context to store. Error code: %d.",dwRet);
		}
		CertCloseStore (hMyStore, CERT_CLOSE_STORE_FORCE_FLAG);
		hMyStore = NULL;
	}

	if(pContainerName != NULL)
		free (pContainerName);

	return dwRet;
}
Ejemplo n.º 2
0
my_bool ma_tls_connect(MARIADB_TLS *ctls)
{
  my_bool blocking;
  MYSQL *mysql;
  SCHANNEL_CRED Cred;
  MARIADB_PVIO *pvio;
  my_bool rc= 1;
  SC_CTX *sctx;
  SECURITY_STATUS sRet;
  PCCERT_CONTEXT pRemoteCertContext = NULL,
                 pLocalCertContext= NULL;
  ALG_ID AlgId[MAX_ALG_ID]= {0};
  
  if (!ctls || !ctls->pvio)
    return 1;;
  
  pvio= ctls->pvio;
  sctx= (SC_CTX *)ctls->ssl;

  /* Set socket to blocking if not already set */
  if (!(blocking= pvio->methods->is_blocking(pvio)))
    pvio->methods->blocking(pvio, TRUE, 0);

  mysql= pvio->mysql;
 
  if (ma_tls_set_client_certs(ctls))
    goto end;

  ZeroMemory(&Cred, sizeof(SCHANNEL_CRED));

  /* Set cipher */
  if (mysql->options.ssl_cipher)
  {
    WORD validTokens = 0;
    char *token = strtok(mysql->options.ssl_cipher, ":");
    while (token)
    {
      struct st_cipher_suite *valid;
      for (valid = valid_ciphers; valid && valid->aid; valid++)
      {
        if (!strcmp(token, valid->cipher))
        {
          AlgId[validTokens++] = valid->aid;
          break;
        }
      }
      token = strtok(NULL, ":");
    }
  }
  Cred.palgSupportedAlgs = (ALG_ID *)&AlgId;
  
  Cred.dwVersion= SCHANNEL_CRED_VERSION;
  if (mysql->options.extension)
    Cred.dwMinimumCipherStrength = MAX(128, mysql->options.extension->tls_cipher_strength);
  else
    Cred.dwMinimumCipherStrength = 128;
  Cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK | SCH_SEND_ROOT_CERT |
    SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_MANUAL_CRED_VALIDATION;
  if (sctx->client_cert_ctx)
  {
    Cred.cCreds = 1;
    Cred.paCred = &sctx->client_cert_ctx;
  }
  if (mysql->options.extension && mysql->options.extension->tls_version)
  {
    Cred.grbitEnabledProtocols= 0;
    if (strstr("TLSv1.0", mysql->options.extension->tls_version))
      Cred.grbitEnabledProtocols|= SP_PROT_TLS1_0;
    if (strstr("TLSv1.1", mysql->options.extension->tls_version))
      Cred.grbitEnabledProtocols|= SP_PROT_TLS1_1;
    if (strstr("TLSv1.2", mysql->options.extension->tls_version))
      Cred.grbitEnabledProtocols|= SP_PROT_TLS1_2;
  }
  else
    Cred.grbitEnabledProtocols = SP_PROT_TLS1_0 |
                                 SP_PROT_TLS1_1 |
                                 SP_PROT_TLS1_2;

  if ((sRet= AcquireCredentialsHandleA(NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND,
                                       NULL, &Cred, NULL, NULL, &sctx->CredHdl, NULL)) != SEC_E_OK)
  {
    ma_schannel_set_sec_error(pvio, sRet);
    goto end;
  }
  sctx->FreeCredHdl= 1;

  if (ma_schannel_client_handshake(ctls) != SEC_E_OK)
    goto end;

  sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pRemoteCertContext);
  if (sRet != SEC_E_OK)
  {
    ma_schannel_set_sec_error(pvio, sRet);
    goto end;
  }
  
  if (!ma_schannel_verify_certs(sctx, 0))
    goto end;
 
  return 0;

end:
  if (pRemoteCertContext)
    CertFreeCertificateContext(pRemoteCertContext);
  if (rc && sctx->IoBufferSize)
    LocalFree(sctx->IoBuffer);
  sctx->IoBufferSize= 0;
  if (sctx->client_cert_ctx)
    CertFreeCertificateContext(sctx->client_cert_ctx);
  sctx->client_cert_ctx= 0;
  return 1;
}
Ejemplo n.º 3
0
static void test_getObjectUrl(void)
{
    BOOL ret;
    DWORD urlArraySize = 0, infoSize = 0;
    PCCERT_CONTEXT cert;

    SetLastError(0xdeadbeef);
    ret = CryptGetObjectUrl(NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
    ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
     "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
    /* Crash
    ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, NULL, 0, NULL, NULL,
     NULL, NULL, NULL);
    ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, NULL, 0, NULL, NULL,
     NULL, &infoSize, NULL);
    ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, NULL, 0, NULL,
     &urlArraySize, NULL, &infoSize, NULL);
     */
    /* A cert with no CRL dist point extension fails.. */
    cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
     sizeof(bigCert));
    SetLastError(0xdeadbeef);
    ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert, 0, NULL,
     NULL, NULL, NULL, NULL);
    ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
     "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
    CertFreeCertificateContext(cert);

    cert = CertCreateCertificateContext(X509_ASN_ENCODING,
     certWithIssuingDistPoint, sizeof(certWithIssuingDistPoint));
    if (cert)
    {
        /* This cert has no AIA extension, so expect this to fail */
        SetLastError(0xdeadbeef);
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert, 0,
         NULL, NULL, NULL, NULL, NULL);
        ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
         "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
        SetLastError(0xdeadbeef);
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert,
         CRYPT_GET_URL_FROM_PROPERTY, NULL, NULL, NULL, NULL, NULL);
        ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
         "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
        SetLastError(0xdeadbeef);
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert,
         CRYPT_GET_URL_FROM_EXTENSION, NULL, NULL, NULL, NULL, NULL);
        ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
         "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
        /* It does have an issuing dist point extension, but that's not what
         * this is looking for (it wants a CRL dist points extension)
         */
        SetLastError(0xdeadbeef);
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
         (void *)cert, 0, NULL, NULL, NULL, NULL, NULL);
        ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
         "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
        SetLastError(0xdeadbeef);
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
         (void *)cert, CRYPT_GET_URL_FROM_PROPERTY, NULL, NULL, NULL, NULL,
         NULL);
        ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
         "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
        SetLastError(0xdeadbeef);
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
         (void *)cert, CRYPT_GET_URL_FROM_EXTENSION, NULL, NULL, NULL, NULL,
         NULL);
        ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
         "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
        CertFreeCertificateContext(cert);
    }
    cert = CertCreateCertificateContext(X509_ASN_ENCODING,
     certWithCRLDistPoint, sizeof(certWithCRLDistPoint));
    if (cert)
    {
        PCRYPT_URL_ARRAY urlArray;

        /* This cert has no AIA extension, so expect this to fail */
        SetLastError(0xdeadbeef);
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert, 0,
         NULL, NULL, NULL, NULL, NULL);
        ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
         "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
        SetLastError(0xdeadbeef);
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert,
         CRYPT_GET_URL_FROM_PROPERTY, NULL, NULL, NULL, NULL, NULL);
        ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
         "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
        SetLastError(0xdeadbeef);
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)cert,
         CRYPT_GET_URL_FROM_EXTENSION, NULL, NULL, NULL, NULL, NULL);
        ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
         "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
        /* It does have a CRL dist points extension */
        SetLastError(0xdeadbeef);
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
         (void *)cert, 0, NULL, NULL, NULL, NULL, NULL);
        ok(!ret && GetLastError() == E_INVALIDARG,
         "Expected E_INVALIDARG, got %08x\n", GetLastError());
        SetLastError(0xdeadbeef);
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
         (void *)cert, 0, NULL, NULL, NULL, &infoSize, NULL);
        ok(!ret && GetLastError() == E_INVALIDARG,
         "Expected E_INVALIDARG, got %08x\n", GetLastError());
        /* Can get it without specifying the location: */
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
         (void *)cert, 0, NULL, &urlArraySize, NULL, NULL, NULL);
        ok(ret, "CryptGetObjectUrl failed: %08x\n", GetLastError());
        urlArray = HeapAlloc(GetProcessHeap(), 0, urlArraySize);
        if (urlArray)
        {
            ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
             (void *)cert, 0, urlArray, &urlArraySize, NULL, NULL, NULL);
            ok(ret, "CryptGetObjectUrl failed: %08x\n", GetLastError());
            if (ret)
            {
                LPWSTR pUrl = url;
                CRYPT_URL_ARRAY expectedUrl = { 1, &pUrl };

                compareUrlArray(&expectedUrl, urlArray);
            }
            HeapFree(GetProcessHeap(), 0, urlArray);
        }
        /* or by specifying it's an extension: */
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
         (void *)cert, CRYPT_GET_URL_FROM_EXTENSION, NULL, &urlArraySize, NULL,
         NULL, NULL);
        ok(ret, "CryptGetObjectUrl failed: %08x\n", GetLastError());
        urlArray = HeapAlloc(GetProcessHeap(), 0, urlArraySize);
        if (urlArray)
        {
            ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
             (void *)cert, CRYPT_GET_URL_FROM_EXTENSION, urlArray,
             &urlArraySize, NULL, NULL, NULL);
            ok(ret, "CryptGetObjectUrl failed: %08x\n", GetLastError());
            if (ret)
            {
                LPWSTR pUrl = url;
                CRYPT_URL_ARRAY expectedUrl = { 1, &pUrl };

                compareUrlArray(&expectedUrl, urlArray);
            }
            HeapFree(GetProcessHeap(), 0, urlArray);
        }
        /* but it isn't contained in a property: */
        SetLastError(0xdeadbeef);
        ret = CryptGetObjectUrl(URL_OID_CERTIFICATE_CRL_DIST_POINT,
         (void *)cert, CRYPT_GET_URL_FROM_PROPERTY, NULL, &urlArraySize, NULL,
         NULL, NULL);
        ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
         "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
        CertFreeCertificateContext(cert);
    }
}
Ejemplo n.º 4
0
Archivo: net.c Proyecto: ccpgames/wine
BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_flags, CredHandle *cred_handle )
{
    SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
    SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
    BYTE *read_buf;
    SIZE_T read_buf_size = 2048;
    ULONG attrs = 0;
    CtxtHandle ctx;
    SSIZE_T size;
    const CERT_CONTEXT *cert;
    SECURITY_STATUS status;
    DWORD res = ERROR_SUCCESS;

    const DWORD isc_req_flags = ISC_REQ_ALLOCATE_MEMORY|ISC_REQ_USE_SESSION_KEY|ISC_REQ_CONFIDENTIALITY
        |ISC_REQ_SEQUENCE_DETECT|ISC_REQ_REPLAY_DETECT|ISC_REQ_MANUAL_CRED_VALIDATION;

    read_buf = heap_alloc(read_buf_size);
    if(!read_buf)
        return FALSE;

    status = InitializeSecurityContextW(cred_handle, NULL, hostname, isc_req_flags, 0, 0, NULL, 0,
            &ctx, &out_desc, &attrs, NULL);

    assert(status != SEC_E_OK);

    while(status == SEC_I_CONTINUE_NEEDED || status == SEC_E_INCOMPLETE_MESSAGE) {
        if(out_buf.cbBuffer) {
            assert(status == SEC_I_CONTINUE_NEEDED);

            TRACE("sending %u bytes\n", out_buf.cbBuffer);

            size = sock_send(conn->socket, out_buf.pvBuffer, out_buf.cbBuffer, 0);
            if(size != out_buf.cbBuffer) {
                ERR("send failed\n");
                res = ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
                break;
            }

            FreeContextBuffer(out_buf.pvBuffer);
            out_buf.pvBuffer = NULL;
            out_buf.cbBuffer = 0;
        }

        if(status == SEC_I_CONTINUE_NEEDED) {
            assert(in_bufs[1].cbBuffer < read_buf_size);

            memmove(read_buf, (BYTE*)in_bufs[0].pvBuffer+in_bufs[0].cbBuffer-in_bufs[1].cbBuffer, in_bufs[1].cbBuffer);
            in_bufs[0].cbBuffer = in_bufs[1].cbBuffer;

            in_bufs[1].BufferType = SECBUFFER_EMPTY;
            in_bufs[1].cbBuffer = 0;
            in_bufs[1].pvBuffer = NULL;
        }

        assert(in_bufs[0].BufferType == SECBUFFER_TOKEN);
        assert(in_bufs[1].BufferType == SECBUFFER_EMPTY);

        if(in_bufs[0].cbBuffer + 1024 > read_buf_size) {
            BYTE *new_read_buf;

            new_read_buf = heap_realloc(read_buf, read_buf_size + 1024);
            if(!new_read_buf) {
                status = E_OUTOFMEMORY;
                break;
            }

            in_bufs[0].pvBuffer = read_buf = new_read_buf;
            read_buf_size += 1024;
        }

        size = sock_recv(conn->socket, read_buf+in_bufs[0].cbBuffer, read_buf_size-in_bufs[0].cbBuffer, 0);
        if(size < 1) {
            status = ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
            break;
        }

        TRACE("recv %lu bytes\n", size);

        in_bufs[0].cbBuffer += size;
        in_bufs[0].pvBuffer = read_buf;
        status = InitializeSecurityContextW(cred_handle, &ctx, hostname,  isc_req_flags, 0, 0, &in_desc,
                0, NULL, &out_desc, &attrs, NULL);
        TRACE("InitializeSecurityContext ret %08x\n", status);

        if(status == SEC_E_OK) {
            if(in_bufs[1].BufferType == SECBUFFER_EXTRA)
                FIXME("SECBUFFER_EXTRA not supported\n");

            status = QueryContextAttributesW(&ctx, SECPKG_ATTR_STREAM_SIZES, &conn->ssl_sizes);
            if(status != SEC_E_OK) {
                WARN("Could not get sizes\n");
                break;
            }

            status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
            if(status == SEC_E_OK) {
                res = netconn_verify_cert(cert, hostname, security_flags);
                CertFreeCertificateContext(cert);
                if(res != ERROR_SUCCESS) {
                    WARN("cert verify failed: %u\n", res);
                    break;
                }
            }else {
                WARN("Could not get cert\n");
                break;
            }

            conn->ssl_buf = heap_alloc(conn->ssl_sizes.cbHeader + conn->ssl_sizes.cbMaximumMessage + conn->ssl_sizes.cbTrailer);
            if(!conn->ssl_buf) {
                res = GetLastError();
                break;
            }
        }
    }

    heap_free(read_buf);

    if(status != SEC_E_OK || res != ERROR_SUCCESS) {
        WARN("Failed to initialize security context failed: %08x\n", status);
        heap_free(conn->ssl_buf);
        conn->ssl_buf = NULL;
        DeleteSecurityContext(&ctx);
        set_last_error(res ? res : ERROR_WINHTTP_SECURE_CHANNEL_ERROR);
        return FALSE;
    }


    TRACE("established SSL connection\n");
    conn->secure = TRUE;
    conn->ssl_ctx = ctx;
    return TRUE;
}
Ejemplo n.º 5
0
static void test_retrieveObjectByUrl(void)
{
    BOOL ret;
    char tmpfile[MAX_PATH * 2], *ptr, url[MAX_PATH + 8];
    CRYPT_BLOB_ARRAY *pBlobArray;
    PCCERT_CONTEXT cert;
    PCCRL_CONTEXT crl;
    HCERTSTORE store;
    CRYPT_RETRIEVE_AUX_INFO aux = { 0 };
    FILETIME ft = { 0 };

    SetLastError(0xdeadbeef);
    ret = CryptRetrieveObjectByUrlA(NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL);
    ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER ||
                GetLastError() == E_INVALIDARG),
       "got 0x%x/%u (expected ERROR_INVALID_PARAMETER or E_INVALIDARG)\n",
       GetLastError(), GetLastError());

    make_tmp_file(tmpfile);
    ptr = strchr(tmpfile, ':');
    if (ptr)
        ptr += 2; /* skip colon and first slash */
    else
        ptr = tmpfile;
    snprintf(url, sizeof(url), "file:///%s", ptr);
    do {
        ptr = strchr(url, '\\');
        if (ptr)
            *ptr = '/';
    } while (ptr);

    pBlobArray = (CRYPT_BLOB_ARRAY *)0xdeadbeef;
    ret = CryptRetrieveObjectByUrlA(url, NULL, 0, 0, (void **)&pBlobArray,
     NULL, NULL, NULL, NULL);
    if (!ret && GetLastError() == ERROR_NOT_SUPPORTED)
    {
        /* File URL support was apparently removed in Vista/Windows 2008 */
        skip("File URLs not supported\n");
        return;
    }
    ok(ret, "CryptRetrieveObjectByUrlA failed: %d\n", GetLastError());
    ok(pBlobArray && pBlobArray != (CRYPT_BLOB_ARRAY *)0xdeadbeef,
     "Expected a valid pointer\n");
    if (pBlobArray && pBlobArray != (CRYPT_BLOB_ARRAY *)0xdeadbeef)
    {
        ok(pBlobArray->cBlob == 1, "Expected 1 blob, got %d\n",
         pBlobArray->cBlob);
        ok(pBlobArray->rgBlob[0].cbData == sizeof(certWithCRLDistPoint),
         "Unexpected size %d\n", pBlobArray->rgBlob[0].cbData);
        CryptMemFree(pBlobArray);
    }
    cert = (PCCERT_CONTEXT)0xdeadbeef;
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE, 0, 0,
     (void **)&cert, NULL, NULL, NULL, NULL);
    ok(cert && cert != (PCCERT_CONTEXT)0xdeadbeef, "Expected a cert\n");
    if (cert && cert != (PCCERT_CONTEXT)0xdeadbeef)
        CertFreeCertificateContext(cert);
    crl = (PCCRL_CONTEXT)0xdeadbeef;
    SetLastError(0xdeadbeef);
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CRL, 0, 0, (void **)&crl,
     NULL, NULL, NULL, NULL);
    /* w2k3,XP, newer w2k: CRYPT_E_NO_MATCH, 95: OSS_DATA_ERROR */
    ok(!ret && (GetLastError() == CRYPT_E_NO_MATCH ||
                GetLastError() == CRYPT_E_ASN1_BADTAG ||
                GetLastError() == OSS_DATA_ERROR),
       "got 0x%x/%u (expected CRYPT_E_NO_MATCH or CRYPT_E_ASN1_BADTAG or "
       "OSS_DATA_ERROR)\n", GetLastError(), GetLastError());

    /* only newer versions of cryptnet do the cleanup */
    if(!ret && GetLastError() != CRYPT_E_ASN1_BADTAG &&
               GetLastError() != OSS_DATA_ERROR) {
        ok(crl == NULL, "Expected CRL to be NULL\n");
    }

    if (crl && crl != (PCCRL_CONTEXT)0xdeadbeef)
        CertFreeCRLContext(crl);
    store = (HCERTSTORE)0xdeadbeef;
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CAPI2_ANY, 0, 0,
     &store, NULL, NULL, NULL, NULL);
    ok(ret, "CryptRetrieveObjectByUrlA failed: %d\n", GetLastError());
    if (store && store != (HCERTSTORE)0xdeadbeef)
    {
        DWORD certs = 0;

        cert = NULL;
        do {
            cert = CertEnumCertificatesInStore(store, cert);
            if (cert)
                certs++;
        } while (cert);
        ok(certs == 1, "Expected 1 cert, got %d\n", certs);
        CertCloseStore(store, 0);
    }
    /* Are file URLs cached? */
    cert = (PCCERT_CONTEXT)0xdeadbeef;
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE,
     CRYPT_CACHE_ONLY_RETRIEVAL, 0, (void **)&cert, NULL, NULL, NULL, NULL);
    ok(ret, "CryptRetrieveObjectByUrlA failed: %08x\n", GetLastError());
    if (cert && cert != (PCCERT_CONTEXT)0xdeadbeef)
        CertFreeCertificateContext(cert);

    cert = (PCCERT_CONTEXT)0xdeadbeef;
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE, 0, 0,
     (void **)&cert, NULL, NULL, NULL, &aux);
    /* w2k: success, 9x: fail with E_INVALIDARG */
    ok(ret || (GetLastError() == E_INVALIDARG),
       "got %u with 0x%x/%u (expected '!=0' or '0' with E_INVALIDARG)\n",
       ret, GetLastError(), GetLastError());
    if (cert && cert != (PCCERT_CONTEXT)0xdeadbeef)
        CertFreeCertificateContext(cert);

    cert = (PCCERT_CONTEXT)0xdeadbeef;
    aux.cbSize = sizeof(aux);
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE, 0, 0,
     (void **)&cert, NULL, NULL, NULL, &aux);
    /* w2k: success, 9x: fail with E_INVALIDARG */
    ok(ret || (GetLastError() == E_INVALIDARG),
       "got %u with 0x%x/%u (expected '!=0' or '0' with E_INVALIDARG)\n",
       ret, GetLastError(), GetLastError());
    if (!ret) {
        /* no more tests useful */
        DeleteFileA(tmpfile);
        skip("no usable CertificateContext\n");
        return;
    }

    aux.pLastSyncTime = &ft;
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE, 0, 0,
     (void **)&cert, NULL, NULL, NULL, &aux);
    ok(ft.dwLowDateTime || ft.dwHighDateTime,
     "Expected last sync time to be set\n");
    DeleteFileA(tmpfile);
    /* Okay, after being deleted, are file URLs still cached? */
    SetLastError(0xdeadbeef);
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE,
     CRYPT_CACHE_ONLY_RETRIEVAL, 0, (void **)&cert, NULL, NULL, NULL, NULL);
    ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
     GetLastError() == ERROR_PATH_NOT_FOUND),
     "Expected ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND, got %d\n",
     GetLastError());
}
Ejemplo n.º 6
0
void CAPICertificate::setUri (const std::string& capiUri) {
	valid_ = false;

	/* Syntax: "certstore:" <cert_store> ":" <hash> ":" <hash_of_cert> */

	if (!boost::iequals(capiUri.substr(0, 10), "certstore:")) {
		return;
	}

	/* Substring of subject: uses "storename" */
	std::string capiIdentity = capiUri.substr(10);
	std::string newCertStoreName;
	size_t pos = capiIdentity.find_first_of (':');

	if (pos == std::string::npos) {
		/* Using the default certificate store */
		newCertStoreName = "MY";
		certName_ = capiIdentity;
	}
	else {
		newCertStoreName = capiIdentity.substr(0, pos);
		certName_ = capiIdentity.substr(pos + 1);
	}

	if (certStoreHandle_ != NULL) {
		if (newCertStoreName != certStore_) {
			CertCloseStore(certStoreHandle_, 0);
			certStoreHandle_ = NULL;
		}
	}

	if (certStoreHandle_ == NULL) {
		certStoreHandle_ = CertOpenSystemStore(0, newCertStoreName.c_str());
		if (!certStoreHandle_) {
			return;
		}
	}

	certStore_ = newCertStoreName;

	PCCERT_CONTEXT certContext = findCertificateInStore (certStoreHandle_, certName_);

	if (!certContext) {
		return;
	}


	/* Now verify that we can have access to the corresponding private key */

	DWORD len;
	CRYPT_KEY_PROV_INFO *pinfo;
	HCRYPTPROV hprov;
	HCRYPTKEY key;

	if (!CertGetCertificateContextProperty(certContext,
			CERT_KEY_PROV_INFO_PROP_ID,
			NULL,
			&len)) {
		CertFreeCertificateContext(certContext);
		return;
	}

	pinfo = static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len));
	if (!pinfo) {
		CertFreeCertificateContext(certContext);
		return;
	}

	if (!CertGetCertificateContextProperty(certContext, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len)) {
		CertFreeCertificateContext(certContext);
		free(pinfo);
		return;
	}

	CertFreeCertificateContext(certContext);

	// Now verify if we have access to the private key
	if (!CryptAcquireContextW(&hprov, pinfo->pwszContainerName, pinfo->pwszProvName, pinfo->dwProvType, 0)) {
		free(pinfo);
		return;
	}


	char smartCardReader[1024];
	DWORD bufferLength = sizeof(smartCardReader);
	if (!CryptGetProvParam(hprov, PP_SMARTCARD_READER, (BYTE *)&smartCardReader, &bufferLength, 0)) {
		DWORD error = GetLastError();
		smartCardReaderName_ = "";
	}
	else {
		smartCardReaderName_ = smartCardReader;

		LONG result = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &scardContext_);
		DEBUG_SCARD_STATUS("SCardEstablishContext", result);
		if (SCARD_S_SUCCESS == result) {
			// Initiate monitoring for smartcard ejection
			smartCardTimer_ = timerFactory_->createTimer(SMARTCARD_EJECTION_CHECK_FREQUENCY_MILLISECONDS);
		}
		else {
			///Need to handle an error here
		}
	}

	if (!CryptGetUserKey(hprov, pinfo->dwKeySpec, &key)) {
		CryptReleaseContext(hprov, 0);
		free(pinfo);
		return;
	}

	CryptDestroyKey(key);
	CryptReleaseContext(hprov, 0);
	free(pinfo);

	if (smartCardTimer_) {
		smartCardTimer_->onTick.connect(boost::bind(&CAPICertificate::handleSmartCardTimerTick, this));
		smartCardTimer_->start();
	}

	valid_ = true;
}
Ejemplo n.º 7
0
bool isCertificateValidated(const generic_string & fullFilePath, const generic_string & subjectName2check)
{
	bool isOK = false;
	HCERTSTORE hStore = NULL;
	HCRYPTMSG hMsg = NULL;
	PCCERT_CONTEXT pCertContext = NULL;
	BOOL result;
	DWORD dwEncoding, dwContentType, dwFormatType;
	PCMSG_SIGNER_INFO pSignerInfo = NULL;
	DWORD dwSignerInfo;
	CERT_INFO CertInfo;
	LPTSTR szName = NULL;

	generic_string subjectName;

	try {
		// Get message handle and store handle from the signed file.
		result = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
			fullFilePath.c_str(),
			CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
			CERT_QUERY_FORMAT_FLAG_BINARY,
			0,
			&dwEncoding,
			&dwContentType,
			&dwFormatType,
			&hStore,
			&hMsg,
			NULL);

		if (!result)
		{
			generic_string errorMessage = TEXT("Check certificate of ") + fullFilePath + TEXT(" : ");
			errorMessage += GetLastErrorAsString(GetLastError());
			throw errorMessage;
		}

		// Get signer information size.
		result = CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo);
		if (!result)
		{
			generic_string errorMessage = TEXT("CryptMsgGetParam first call: ");
			errorMessage += GetLastErrorAsString(GetLastError());
			throw errorMessage;
		}

		// Allocate memory for signer information.
		pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
		if (!pSignerInfo)
		{
			generic_string errorMessage = TEXT("CryptMsgGetParam memory allocation problem: ");
			errorMessage += GetLastErrorAsString(GetLastError());
			throw errorMessage;
		}

		// Get Signer Information.
		result = CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, (PVOID)pSignerInfo, &dwSignerInfo);
		if (!result)
		{
			generic_string errorMessage = TEXT("CryptMsgGetParam: ");
			errorMessage += GetLastErrorAsString(GetLastError());
			throw errorMessage;
		}

		// Search for the signer certificate in the temporary 
		// certificate store.
		CertInfo.Issuer = pSignerInfo->Issuer;
		CertInfo.SerialNumber = pSignerInfo->SerialNumber;

		pCertContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, (PVOID)&CertInfo, NULL);
		if (not pCertContext)
		{
			generic_string errorMessage = TEXT("Certificate context: ");
			errorMessage += GetLastErrorAsString(GetLastError());
			throw errorMessage;
		}

		DWORD dwData;

		// Get Subject name size.
		dwData = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0);
		if (dwData <= 1)
		{
			throw generic_string(TEXT("Certificate checking error: getting data size problem."));
		}

		// Allocate memory for subject name.
		szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
		if (!szName)
		{
			throw generic_string(TEXT("Certificate checking error: memory allocation problem."));
		}

		// Get subject name.
		if (CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, szName, dwData) <= 1)
		{
			throw generic_string(TEXT("Cannot get certificate info."));
		}

		// check Subject name.
		subjectName = szName;
		if (subjectName != subjectName2check)
		{
			throw generic_string(TEXT("Certificate checking error: the certificate is not matched."));
		}

		isOK = true;
	}
	catch (generic_string s)
	{
		// display error message
		MessageBox(NULL, s.c_str(), TEXT("Certificate checking"), MB_OK);
	}
	catch (...)
	{
		// Unknown error
		generic_string errorMessage = TEXT("Unknown exception occured. ");
		errorMessage += GetLastErrorAsString(GetLastError());
		MessageBox(NULL, errorMessage.c_str(), TEXT("Certificate checking"), MB_OK);
	}

	// Clean up.
	if (pSignerInfo != NULL) LocalFree(pSignerInfo);
	if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
	if (hStore != NULL) CertCloseStore(hStore, 0);
	if (hMsg != NULL) CryptMsgClose(hMsg);
	if (szName != NULL) LocalFree(szName);

	return isOK;
}
Ejemplo n.º 8
0
BOOL WINAPI CryptVerifyMessageSignature(PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
 DWORD dwSignerIndex, const BYTE* pbSignedBlob, DWORD cbSignedBlob,
 BYTE* pbDecoded, DWORD* pcbDecoded, PCCERT_CONTEXT* ppSignerCert)
{
    BOOL ret = FALSE;
    HCRYPTMSG msg;

    TRACE("(%p, %d, %p, %d, %p, %p, %p)\n",
     pVerifyPara, dwSignerIndex, pbSignedBlob, cbSignedBlob,
     pbDecoded, pcbDecoded, ppSignerCert);

    if (ppSignerCert)
        *ppSignerCert = NULL;
    if (!pVerifyPara ||
     pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) ||
     GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) !=
     PKCS_7_ASN_ENCODING)
    {
        if(pcbDecoded)
            *pcbDecoded = 0;
        SetLastError(E_INVALIDARG);
        return FALSE;
    }

    msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType, 0, 0,
     pVerifyPara->hCryptProv, NULL, NULL);
    if (msg)
    {
        ret = CryptMsgUpdate(msg, pbSignedBlob, cbSignedBlob, TRUE);
        if (ret && pcbDecoded)
            ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, pbDecoded,
             pcbDecoded);
        if (ret)
        {
            CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg,
             dwSignerIndex);

            ret = FALSE;
            if (certInfo)
            {
                HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG,
                 pVerifyPara->dwMsgAndCertEncodingType,
                 pVerifyPara->hCryptProv, 0, msg);

                if (store)
                {
                    PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate(
                     msg, pVerifyPara, certInfo, store);

                    if (cert)
                    {
                        ret = CryptMsgControl(msg, 0,
                         CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo);
                        if (ret && ppSignerCert)
                            *ppSignerCert = cert;
                        else
                            CertFreeCertificateContext(cert);
                    }
                    CertCloseStore(store, 0);
                }
            }
            CryptMemFree(certInfo);
        }
        CryptMsgClose(msg);
    }
    if(!ret && pcbDecoded)
        *pcbDecoded = 0;
    TRACE("returning %d\n", ret);
    return ret;
}
Ejemplo n.º 9
0
int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop)
{
    HCERTSTORE cs;
    X509 *cert = NULL;
    RSA *rsa = NULL, *pub_rsa;
    CAPI_DATA *cd = calloc(1, sizeof(*cd));
    RSA_METHOD *my_rsa_method = calloc(1, sizeof(*my_rsa_method));

    if (cd == NULL || my_rsa_method == NULL) {
	SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE);
	goto err;
    }
    /* search CURRENT_USER first, then LOCAL_MACHINE */
    cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER |
		       CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY");
    if (cs == NULL) {
	CRYPTOAPIerr(CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE);
	goto err;
    }
    cd->cert_context = find_certificate_in_store(cert_prop, cs);
    CertCloseStore(cs, 0);
    if (!cd->cert_context) {
	cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE |
			   CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY");
	if (cs == NULL) {
	    CRYPTOAPIerr(CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE);
	    goto err;
	}
	cd->cert_context = find_certificate_in_store(cert_prop, cs);
	CertCloseStore(cs, 0);
	if (cd->cert_context == NULL) {
	    CRYPTOAPIerr(CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE);
	    goto err;
	}
    }

    /* cert_context->pbCertEncoded is the cert X509 DER encoded. */
    cert = d2i_X509(NULL, (unsigned char **) &cd->cert_context->pbCertEncoded,
		    cd->cert_context->cbCertEncoded);
    if (cert == NULL) {
	SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
	goto err;
    }

    /* set up stuff to use the private key */
#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 (CryptAcquireCertificatePrivateKey == NULL) {
	CryptAcquireCertificatePrivateKey = GetProcAddress(crypt32dll,
		"CryptAcquireCertificatePrivateKey");
	if (CryptAcquireCertificatePrivateKey == NULL) {
	    CRYPTOAPIerr(CRYPTOAPI_F_GET_PROC_ADDRESS);
	    goto err;
	}
    }
#endif
    if (!CryptAcquireCertificatePrivateKey(cd->cert_context, CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
	    NULL, &cd->crypt_prov, &cd->key_spec, &cd->free_crypt_prov)) {
	/* if we don't have a smart card reader here, and we try to access a
	 * smart card certificate, we get:
	 * "Error 1223: The operation was canceled by the user." */
	CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_ACQUIRE_CERTIFICATE_PRIVATE_KEY);
	goto err;
    }
    /* here we don't need to do CryptGetUserKey() or anything; all necessary key
     * info is in cd->cert_context, and then, in cd->crypt_prov.  */

    my_rsa_method->name = "Microsoft CryptoAPI RSA Method";
    my_rsa_method->rsa_pub_enc = rsa_pub_enc;
    my_rsa_method->rsa_pub_dec = rsa_pub_dec;
    my_rsa_method->rsa_priv_enc = rsa_priv_enc;
    my_rsa_method->rsa_priv_dec = rsa_priv_dec;
    /* my_rsa_method->init = init; */
    my_rsa_method->finish = finish;
    my_rsa_method->flags = RSA_METHOD_FLAG_NO_CHECK;
    my_rsa_method->app_data = (char *) cd;

    rsa = RSA_new();
    if (rsa == NULL) {
	SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE);
	goto err;
    }

    /* cert->cert_info->key->pkey is NULL until we call SSL_CTX_use_certificate(),
     * so we do it here then...  */
    if (!SSL_CTX_use_certificate(ssl_ctx, cert))
	goto err;
    /* the public key */
    pub_rsa = cert->cert_info->key->pkey->pkey.rsa;
    /* SSL_CTX_use_certificate() increased the reference count in 'cert', so
     * we decrease it here with X509_free(), or it will never be cleaned up. */
    X509_free(cert);
    cert = NULL;

    /* I'm not sure about what we have to fill in in the RSA, trying out stuff... */
    /* rsa->n indicates the key size */
    rsa->n = BN_dup(pub_rsa->n);
    rsa->flags |= RSA_FLAG_EXT_PKEY;
    if (!RSA_set_method(rsa, my_rsa_method))
	goto err;

    if (!SSL_CTX_use_RSAPrivateKey(ssl_ctx, rsa))
	goto err;
    /* SSL_CTX_use_RSAPrivateKey() increased the reference count in 'rsa', so
     * we decrease it here with RSA_free(), or it will never be cleaned up. */
    RSA_free(rsa);
    return 1;

  err:
    if (cert)
	X509_free(cert);
    if (rsa)
	RSA_free(rsa);
    else {
	if (my_rsa_method)
	    free(my_rsa_method);
	if (cd) {
	    if (cd->free_crypt_prov && cd->crypt_prov)
		CryptReleaseContext(cd->crypt_prov, 0);
	    if (cd->cert_context)
		CertFreeCertificateContext(cd->cert_context);
	    free(cd);
	}
    }
    return 0;
}
Ejemplo n.º 10
0
DWORD ShowCertsDlg(LPCTSTR szProviderName,
				  LPCTSTR szReaderName /* Can be NULL */
				  )
{
	HCRYPTPROV HMainCryptProv = NULL;
	BOOL bStatus = FALSE;
	LPTSTR szMainContainerName = NULL;
	CHAR szContainerName[1024];
	DWORD dwContainerNameLen = sizeof(szContainerName);
	DWORD dwErr = 0;
	DWORD dwFlags = CRYPT_FIRST;
	PCCERT_CONTEXT pContextArray[128];
	DWORD dwContextArrayLen = 0;
	HCRYPTPROV hProv = NULL;
	HCRYPTKEY hKey = NULL;
	LPBYTE pbCert = NULL;
	DWORD dwCertLen = 0;
	PCCERT_CONTEXT pCertContext = NULL;
	DWORD pKeySpecs[2] = { AT_KEYEXCHANGE, AT_SIGNATURE};

	if (szReaderName)
	{
		size_t ulNameLen = _tcslen(szReaderName);
		szMainContainerName = (LPTSTR) LocalAlloc(0, (ulNameLen + 6) * sizeof(TCHAR));
		if (!szMainContainerName)
		{
			return GetLastError();
		}
		_stprintf(szMainContainerName, _T("\\\\.\\%s\\"), szReaderName);
	}			

	bStatus = CryptAcquireContext(&HMainCryptProv,szMainContainerName,szProviderName,PROV_RSA_FULL,0);

	if (!bStatus)
	{
		dwErr = GetLastError();
		goto end;
	}

	/* Enumerate all the containers */
	while (CryptGetProvParam(HMainCryptProv,PP_ENUMCONTAINERS,(LPBYTE) szContainerName,&dwContainerNameLen,dwFlags) &&(dwContextArrayLen < 128))
	{
#ifndef _UNICODE
		if (CryptAcquireContext(&hProv,
				szContainerName,
				szProviderName,
				PROV_RSA_FULL,
				0))
#else
		// convert the container name to unicode
		int wLen = MultiByteToWideChar(CP_ACP, 0, szContainerName, -1, NULL, 0);
		LPWSTR szWideContainerName = (LPWSTR) LocalAlloc(0, wLen * sizeof(WCHAR));
		MultiByteToWideChar(CP_ACP, 0, szContainerName, -1, szWideContainerName, wLen);

		// Acquire a context on the current container
		if (CryptAcquireContext(&hProv,szWideContainerName,szProviderName,PROV_RSA_FULL,0))
#endif
		{
			// Loop over all the key specs
			for (int i = 0; i < 2; i++)
			{
				if (CryptGetUserKey(hProv,pKeySpecs[i],&hKey) )
				{
					if (CryptGetKeyParam(hKey,KP_CERTIFICATE,NULL,&dwCertLen,0))
					{
						pbCert = (LPBYTE) LocalAlloc(0, dwCertLen);
						if (!pbCert)
						{
							dwErr = GetLastError();
							goto end;
						}
						if (CryptGetKeyParam(hKey,KP_CERTIFICATE,pbCert,&dwCertLen,0))
						{
							pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, pbCert,dwCertLen);
							if (pCertContext)
							{
								pContextArray[dwContextArrayLen++] = pCertContext;

								CRYPT_KEY_PROV_INFO ProvInfo;
								ProvInfo.pwszContainerName = szWideContainerName;
								ProvInfo.pwszProvName = L"Microsoft Base Smart Card Crypto Provider";
								ProvInfo.dwProvType = PROV_RSA_FULL;
								ProvInfo.dwFlags = 0;
								ProvInfo.dwKeySpec = AT_SIGNATURE;
								ProvInfo.cProvParam = 0;
								ProvInfo.rgProvParam = NULL;
								
								CertSetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID, 0, &ProvInfo);

								HCERTSTORE dest = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL,
								CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_CURRENT_USER,L"My");
								if(CertAddCertificateContextToStore(dest, pCertContext,CERT_STORE_ADD_REPLACE_EXISTING, NULL))
								{
									//char certName[1024];
									//LPWSTR certName = (LPWSTR)new wchar_t[1024];
									LPTSTR certName;
									int cbSize = CertNameToStrW(pCertContext->dwCertEncodingType, &(pCertContext->pCertInfo->Subject),CERT_X500_NAME_STR,NULL,0);
									certName = (LPTSTR)malloc(cbSize * sizeof(TCHAR));

									if (CertNameToStrW(pCertContext->dwCertEncodingType, &(pCertContext->pCertInfo->Subject),CERT_X500_NAME_STR,certName,sizeof(certName)))
									{
									}
									printf("Installed certificate.");
								}
								else
									printf("Error while adding certificate to store");
							}
						}
						LocalFree(pbCert);
					}
					CryptDestroyKey(hKey);
					hKey = NULL;
				}
			}
			CryptReleaseContext(hProv, 0);
			hProv = NULL;
		}

#ifdef _UNICODE
		LocalFree(szWideContainerName);
#endif
		
		// prepare parameters for the next loop
		dwContainerNameLen = sizeof(szContainerName);
		dwFlags = 0;
	}

	if (dwContextArrayLen == 0)
		printf("No certificate contexts found on card\n");
	
end:
	while (dwContextArrayLen--)
	{
		CertFreeCertificateContext(pContextArray[dwContextArrayLen]);
	}
	if (hKey)
		CryptDestroyKey(hKey);
	if (hProv)
		CryptReleaseContext(hProv, 0);
	if (szMainContainerName)
		LocalFree(szMainContainerName);
	if (HMainCryptProv)
		CryptReleaseContext(HMainCryptProv, 0);
	return dwErr;
}
Ejemplo n.º 11
0
BOOL WINAPI CryptVerifyDetachedMessageSignature(
 PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara, DWORD dwSignerIndex,
 const BYTE *pbDetachedSignBlob, DWORD cbDetachedSignBlob, DWORD cToBeSigned,
 const BYTE *rgpbToBeSigned[], DWORD rgcbToBeSigned[],
 PCCERT_CONTEXT *ppSignerCert)
{
    BOOL ret = FALSE;
    HCRYPTMSG msg;

    TRACE("(%p, %d, %p, %d, %d, %p, %p, %p)\n", pVerifyPara, dwSignerIndex,
     pbDetachedSignBlob, cbDetachedSignBlob, cToBeSigned, rgpbToBeSigned,
     rgcbToBeSigned, ppSignerCert);

    if (ppSignerCert)
        *ppSignerCert = NULL;
    if (!pVerifyPara ||
     pVerifyPara->cbSize != sizeof(CRYPT_VERIFY_MESSAGE_PARA) ||
     GET_CMSG_ENCODING_TYPE(pVerifyPara->dwMsgAndCertEncodingType) !=
     PKCS_7_ASN_ENCODING)
    {
        SetLastError(E_INVALIDARG);
        return FALSE;
    }

    msg = CryptMsgOpenToDecode(pVerifyPara->dwMsgAndCertEncodingType,
     CMSG_DETACHED_FLAG, 0, pVerifyPara->hCryptProv, NULL, NULL);
    if (msg)
    {
        ret = CryptMsgUpdate(msg, pbDetachedSignBlob, cbDetachedSignBlob, TRUE);
        if (ret)
        {
            DWORD i;

            for (i = 0; ret && i < cToBeSigned; i++)
                ret = CryptMsgUpdate(msg, rgpbToBeSigned[i], rgcbToBeSigned[i],
                 i == cToBeSigned - 1);
        }
        if (ret)
        {
            CERT_INFO *certInfo = CRYPT_GetSignerCertInfoFromMsg(msg,
             dwSignerIndex);

            ret = FALSE;
            if (certInfo)
            {
                HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MSG,
                 pVerifyPara->dwMsgAndCertEncodingType,
                 pVerifyPara->hCryptProv, 0, msg);

                if (store)
                {
                    PCCERT_CONTEXT cert = CRYPT_GetSignerCertificate(
                     msg, pVerifyPara, certInfo, store);

                    if (cert)
                    {
                        ret = CryptMsgControl(msg, 0,
                         CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo);
                        if (ret && ppSignerCert)
                            *ppSignerCert = cert;
                        else
                            CertFreeCertificateContext(cert);
                    }
                    else
                        SetLastError(CRYPT_E_NOT_FOUND);
                    CertCloseStore(store, 0);
                }
                CryptMemFree(certInfo);
            }
        }
        CryptMsgClose(msg);
    }
    TRACE("returning %d\n", ret);
    return ret;
}
Ejemplo n.º 12
0
// Select, and return a handle to a server certificate located by name
// Usually used for a best guess at a certificate to be used as the SSL certificate for a server 
SECURITY_STATUS CertFindServerByName(PCCERT_CONTEXT & pCertContext, LPCTSTR pszSubjectName, boolean fUserStore)
{
   HCERTSTORE  hMyCertStore = NULL;
   TCHAR pszFriendlyNameString[128];
   TCHAR	pszNameString[128];

   if (pszSubjectName == NULL || _tcslen(pszSubjectName) == 0)
   {
      DebugMsg("**** No subject name specified!");
      return E_POINTER;
   }

   if (fUserStore)
      hMyCertStore = CertOpenSystemStore(NULL, _T("MY"));
   else
   {	// Open the local machine certificate store.
      hMyCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
         X509_ASN_ENCODING,
         NULL,
         CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE,
         L"MY");
   }

   if (!hMyCertStore)
   {
      int err = GetLastError();

      if (err == ERROR_ACCESS_DENIED)
         DebugMsg("**** CertOpenStore failed with 'access denied'");
      else
         DebugMsg("**** Error %d returned by CertOpenStore", err);
      return HRESULT_FROM_WIN32(err);
   }

   if (pCertContext)	// The caller passed in a certificate context we no longer need, so free it
      CertFreeCertificateContext(pCertContext);
   pCertContext = NULL;

   char * serverauth = szOID_PKIX_KP_SERVER_AUTH;
   CERT_ENHKEY_USAGE eku;
   PCCERT_CONTEXT pCertContextSaved = NULL;
   eku.cUsageIdentifier = 1;
   eku.rgpszUsageIdentifier = &serverauth;
   // Find a server certificate. Note that this code just searches for a 
   // certificate that has the required enhanced key usage for server authentication
   // it then selects the best one (ideally one that contains the server name
   // in the subject name).

   while (NULL != (pCertContext = CertFindCertificateInStore(hMyCertStore,
      X509_ASN_ENCODING,
      CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG,
      CERT_FIND_ENHKEY_USAGE,
      &eku,
      pCertContext)))
   {
      //ShowCertInfo(pCertContext);
      if (!CertGetNameString(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszFriendlyNameString, sizeof(pszFriendlyNameString)))
      {
         DebugMsg("CertGetNameString failed getting friendly name.");
         continue;
      }
      DebugMsg("Certificate '%S' is allowed to be used for server authentication.", ATL::CT2W(pszFriendlyNameString));
      if (!CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, sizeof(pszNameString)))
         DebugMsg("CertGetNameString failed getting subject name.");
      else if (_tcscmp(pszNameString, pszSubjectName))
         DebugMsg("Certificate has wrong subject name.");
      else if (CertCompareCertificateName(X509_ASN_ENCODING, &pCertContext->pCertInfo->Subject, &pCertContext->pCertInfo->Issuer))
      {
         if (!pCertContextSaved)
         {
            DebugMsg("A self-signed certificate was found and saved in case it is needed.");
            pCertContextSaved = CertDuplicateCertificateContext(pCertContext);
         }
      }
      else
      {
         DebugMsg("Certificate is acceptable.");
         if (pCertContextSaved)	// We have a saved self signed certificate context we no longer need, so free it
            CertFreeCertificateContext(pCertContextSaved);
         pCertContextSaved = NULL;
         break;
      }
   }

   if (pCertContextSaved && !pCertContext)
   {	// We have a saved self-signed certificate and nothing better 
      DebugMsg("A self-signed certificate was the best we had.");
      pCertContext = pCertContextSaved;
      pCertContextSaved = NULL;
   }

   if (!pCertContext)
   {
      DWORD LastError = GetLastError();
      if (LastError == CRYPT_E_NOT_FOUND)
      {
         DebugMsg("**** CertFindCertificateInStore did not find a certificate, creating one");
         pCertContext = CreateCertificate(true, pszSubjectName);
         if (!pCertContext)
         {
            LastError = GetLastError();
            DebugMsg("**** Error 0x%x returned by CreateCertificate", LastError);
            std::cout << "Could not create certificate, are you running as administrator?" << std::endl;
            return HRESULT_FROM_WIN32(LastError);
         }
      }
      else
      {
         DebugMsg("**** Error 0x%x returned by CertFindCertificateInStore", LastError);
         return HRESULT_FROM_WIN32(LastError);
      }
   }

   return SEC_E_OK;
}
Ejemplo n.º 13
0
BOOL CPublisherHelp::GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo, PCMSG_SIGNER_INFO *pCounterSignerInfo)
{
	PCCERT_CONTEXT pCertContext = NULL;
	BOOL fReturn = FALSE;
	BOOL fResult;
	DWORD dwSize;
	__try
	{
		*pCounterSignerInfo = NULL;
		// Loop through unathenticated attributes for
		// szOID_RSA_counterSign OID.
		for (DWORD n = 0; n < pSignerInfo->UnauthAttrs.cAttr; n++)
		{
			if (lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId,
				szOID_RSA_counterSign) == 0)
			{
				// Get size of CMSG_SIGNER_INFO structure.
				fResult = CryptDecodeObject(ENCODING,
					PKCS7_SIGNER_INFO,
					pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
					pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
					0,
					NULL,
					&dwSize);
				if (!fResult)
				{
					_tprintf(_T("CryptDecodeObject failed with %x\n"),
						GetLastError());
					__leave;
				}
				// Allocate memory for CMSG_SIGNER_INFO.
				*pCounterSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSize);
				if (!*pCounterSignerInfo)
				{
					_tprintf(_T("Unable to allocate memory for timestamp info.\n"));
					__leave;
				}
				// Decode and get CMSG_SIGNER_INFO structure
				// for timestamp certificate.
				fResult = CryptDecodeObject(ENCODING,
					PKCS7_SIGNER_INFO,
					pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData,
					pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData,
					0,
					(PVOID)*pCounterSignerInfo,
					&dwSize);
				if (!fResult)
				{
					_tprintf(_T("CryptDecodeObject failed with %x\n"),
						GetLastError());
					__leave;
				}
				fReturn = TRUE;
				break; // Break from for loop.
			}
		}
	}
	__finally
	{
		// Clean up.
		if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
	}
	return fReturn;
}
Ejemplo n.º 14
0
LPTSTR CPublisherHelp::GetSigningName(const WCHAR* szFileName){
	HCERTSTORE hStore = NULL;
	HCRYPTMSG hMsg = NULL;
	PCCERT_CONTEXT pCertContext = NULL;
	BOOL fResult;
	DWORD dwEncoding, dwContentType, dwFormatType;
	PCMSG_SIGNER_INFO pSignerInfo = NULL;
	PCMSG_SIGNER_INFO pCounterSignerInfo = NULL;
	DWORD dwSignerInfo;
	CERT_INFO CertInfo;
	SPROG_PUBLISHERINFO ProgPubInfo;
	ZeroMemory(&ProgPubInfo, sizeof(ProgPubInfo));
	__try{
		fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
			szFileName,
			CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
			CERT_QUERY_FORMAT_FLAG_BINARY,
			0,
			&dwEncoding,
			&dwContentType,
			&dwFormatType,
			&hStore,
			&hMsg,
			NULL);
		if (!fResult)
		{
			return NULL;
		}
		// Get signer information size.
		fResult = CryptMsgGetParam(hMsg,
			CMSG_SIGNER_INFO_PARAM,
			0,
			NULL,
			&dwSignerInfo);
		if (!fResult)
		{
			return NULL;
		}
		pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
		if (!pSignerInfo)
		{
			return NULL;
		}
		// Get Signer Information.
		fResult = CryptMsgGetParam(hMsg,
			CMSG_SIGNER_INFO_PARAM,
			0,
			(PVOID)pSignerInfo,
			&dwSignerInfo);
		if (!fResult)
		{
			return NULL;
		}
		// Get program name and publisher information from
		// signer info structure.
		if (GetProgAndPublisherInfo(pSignerInfo, &ProgPubInfo))
		{

		}
		else{
			return NULL;
		}
		// Search for the signer certificate in the temporary
		// certificate store.
		CertInfo.Issuer = pSignerInfo->Issuer;
		CertInfo.SerialNumber = pSignerInfo->SerialNumber;
		pCertContext = CertFindCertificateInStore(hStore,
			ENCODING,
			0,
			CERT_FIND_SUBJECT_CERT,
			(PVOID)&CertInfo,
			NULL);
		if (!pCertContext)
		{
			return NULL;
		}
		// Print Signer certificate information.

		LPTSTR szName = NULL;
		DWORD dwData;
		// Get Subject name size.
		if (!(dwData = CertGetNameString(pCertContext,
			CERT_NAME_SIMPLE_DISPLAY_TYPE,
			0,
			NULL,
			NULL,
			0)))
		{
			return NULL;
		}
		// Allocate memory for subject name.
		szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR));
		if (!szName)
		{
			return NULL;
		}
		// Get subject name.
		if (!(CertGetNameString(pCertContext,
			CERT_NAME_SIMPLE_DISPLAY_TYPE,
			0,
			NULL,
			szName,
			dwData)))
		{
			return NULL;
		}
		// Print Subject Name.

		return szName;
	}
	__finally
	{
		if (ProgPubInfo.lpszProgramName != NULL)
			LocalFree(ProgPubInfo.lpszProgramName);
		if (ProgPubInfo.lpszPublisherLink != NULL)
			LocalFree(ProgPubInfo.lpszPublisherLink);
		if (ProgPubInfo.lpszMoreInfoLink != NULL)
			LocalFree(ProgPubInfo.lpszMoreInfoLink);
		if (pSignerInfo != NULL) LocalFree(pSignerInfo);
		if (pCounterSignerInfo != NULL) LocalFree(pCounterSignerInfo);
		if (pCertContext != NULL) CertFreeCertificateContext(pCertContext);
		if (hStore != NULL) CertCloseStore(hStore, 0);
		if (hMsg != NULL) CryptMsgClose(hMsg);
	}
	return NULL;
}
Ejemplo n.º 15
0
SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE store,
                                                       PCCERT_CONTEXT *ret_cert)
{
    struct mac_session* s = (struct mac_session*)session;
    SECURITY_STATUS ret = SEC_E_OK;
    PCCERT_CONTEXT cert = NULL;
    SecCertificateRef mac_cert;
    CFArrayRef cert_array;
    int status;
    CFIndex cnt, i;
    CFDataRef data;
    BOOL res;

    TRACE("(%p/%p, %p)\n", s, s->context, cert);

#ifdef HAVE_SSLCOPYPEERCERTIFICATES
    status = SSLCopyPeerCertificates(s->context, &cert_array);
#else
    status = SSLGetPeerCertificates(s->context, &cert_array);
#endif
    if (status != noErr || !cert_array)
    {
        WARN("SSLCopyPeerCertificates failed: %d\n", status);
        return SEC_E_INTERNAL_ERROR;
    }

    cnt = CFArrayGetCount(cert_array);
    for (i=0; i < cnt; i++) {
        if (!(mac_cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, i)) ||
            (SecKeychainItemExport(mac_cert, kSecFormatX509Cert, 0, NULL, &data) != noErr))
        {
            WARN("Couldn't extract certificate data\n");
            ret = SEC_E_INTERNAL_ERROR;
            break;
        }

        res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, CFDataGetBytePtr(data), CFDataGetLength(data),
                                               CERT_STORE_ADD_REPLACE_EXISTING, i ? NULL : &cert);
        CFRelease(data);
        if (!res)
        {
            ret = GetLastError();
            WARN("CertAddEncodedCertificateToStore failed: %x\n", ret);
            break;
        }
    }

#ifndef HAVE_SSLCOPYPEERCERTIFICATES
    /* This is why SSLGetPeerCertificates was deprecated */
    CFArrayApplyFunction(cert_array, CFRangeMake(0, CFArrayGetCount(cert_array)),
                         schan_imp_cf_release, NULL);
#endif
    CFRelease(cert_array);
    if (ret != SEC_E_OK) {
        if(cert)
            CertFreeCertificateContext(cert);
        return ret;
    }

    *ret_cert = cert;
    return SEC_E_OK;
}
Ejemplo n.º 16
0
static sqInt sqSetupCert(sqSSL *ssl, char *certName, int server) {
	SCHANNEL_CRED sc_cred = { 0 };
	SECURITY_STATUS ret;
	HCERTSTORE hStore;
	PCCERT_CONTEXT pContext = NULL;
	DWORD dwPropSize;
	WCHAR wFriendlyName[MAX_NAME_SIZE];
	char  bFriendlyName[MAX_NAME_SIZE];

	if(certName) {
		hStore = CertOpenSystemStore(0, "MY");
		if(!hStore) {
			if(ssl->loglevel) printf("sqSetupCert: CertOpenSystemStore failed\n");
			return 0;
		}
		pContext = NULL;

		/* Enumerate the certificate store to find the cert with the given friendly name */
		while(pContext = CertEnumCertificatesInStore(hStore, pContext)) {
			if(ssl->loglevel) printf("Checking certificate: ");
			dwPropSize = MAX_NAME_SIZE * sizeof(WCHAR);
			if(!CertGetCertificateContextProperty(pContext, CERT_FRIENDLY_NAME_PROP_ID, wFriendlyName, &dwPropSize)) {
				if(ssl->loglevel) printf("<no friendly name>");
				continue;
			}
			if(!WideCharToMultiByte(CP_UTF8, 0, wFriendlyName, -1, bFriendlyName, MAX_NAME_SIZE, NULL, NULL)) {
				if(ssl->loglevel) printf("<utf-8 conversion failure>");
				continue;
			}
			if(ssl->loglevel) printf("%s\n", bFriendlyName);
			if(strcmp(certName, bFriendlyName) == 0) break;
		}

		if(pContext == 0) {
			/* For compatibility with older versions of SqueakSSL, attempt to match against subject string */
			pContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
												  0, CERT_FIND_SUBJECT_STR_A, certName, NULL);
		}

		if(!pContext) {
			if(ssl->loglevel) printf("sqSetupCert: No suitable certificate  found\n");
			CertCloseStore(hStore, 0);
			return 0;
		}
	}

	sc_cred.dwVersion = SCHANNEL_CRED_VERSION;
	sc_cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_MANUAL_CRED_VALIDATION;
	sc_cred.grbitEnabledProtocols = server ? SP_PROT_TLS1_SERVER | SP_PROT_SSL3_SERVER : 0;
	sc_cred.dwMinimumCipherStrength = 0;
	sc_cred.dwMaximumCipherStrength = 0;

	if(pContext) {
		sc_cred.cCreds = 1;
		sc_cred.paCred = &pContext;
	} else {
		sc_cred.cCreds = 0;
	}

	ret = AcquireCredentialsHandle(NULL, UNISP_NAME, 
									server ? SECPKG_CRED_INBOUND : SECPKG_CRED_OUTBOUND, 
									NULL, &sc_cred, NULL, NULL, &ssl->sslCred, NULL);
	if(ssl->loglevel) printf("AquireCredentialsHandle returned: %x\n", ret);

	if(pContext) {
		CertCloseStore(hStore, 0);
	    CertFreeCertificateContext(pContext);
	}

	if (ret != SEC_E_OK) {
		if(ssl->loglevel) printf("AquireCredentialsHandle error: %x\n", ret);
		return 0;
	}
	return 1;
}
Ejemplo n.º 17
0
PCCERT_CONTEXT DigiCrypt_ReadCertFromCard(void)
{
HCRYPTPROV hCryptProv;
BYTE       *pbData = NULL;   
HCRYPTKEY  hKey;          
DWORD cbData = 0;
DWORD dwKeyType=0, dwKeySpec = AT_SIGNATURE;
DWORD dwErrCode=0;
DWORD cspType=0;
DWORD cspFlag=CRYPT_SILENT;
char *psCspName = NULL;
char *psKeyContainer;
BOOL fRes = FALSE;
PCCERT_CONTEXT  pCertContext = NULL; 
CRYPT_KEY_PROV_INFO KeyProvInfo;
LPWSTR wszContainerName=NULL;
LPWSTR wszProvName=NULL;
DWORD cchContainerName;
DWORD cchCSPName;
HCRYPTPROV hProv;


DigiCrypt_ReleaseFirstAllowedCSP();

psCspName=DigiCrypt_GetFirstAllowedCSPNameNew();

//very dummy thing.. i check from csp creators why i should do so...
if(!lstrcmp(psCspName,"EstEID Card CSP"))
   fRes = CryptAcquireContext(&hProv,"XXX",psCspName,2, CRYPT_SILENT);
// end dummy//

if (psCspName == NULL || strstr(psCspName,psData_Est_CSP_Name) == NULL)
  return(pCertContext);

cspType=DigiCrypt_FindContext_GetCSPType(psCspName);

psKeyContainer=DigiCrypt_GetDefaultKeyContainerName(psCspName);

fRes = CryptAcquireContext(&hCryptProv,psKeyContainer,psCspName,cspType, CRYPT_SILENT);
if (fRes == FALSE)
  return(pCertContext);

// VS: use alsu auth keys if KEY_USAGE_CHECK=false
dwKeySpec = ConfigItem_lookup_int("KEY_USAGE_CHECK", 1) ? AT_SIGNATURE : 0;

fRes=CryptGetUserKey(hCryptProv, dwKeySpec, &hKey);
if (fRes == TRUE)
  {
  fRes=CryptGetKeyParam(hKey, KP_CERTIFICATE, NULL, &cbData, 0);
  if (fRes == TRUE)
    {
    pbData = malloc(cbData);
    if (pbData == NULL)
      fRes = FALSE;
    }
  if (fRes == TRUE)
    fRes=CryptGetKeyParam(hKey, KP_CERTIFICATE, pbData, &cbData, 0);
  if (fRes == TRUE)
    {
    pCertContext = CertCreateCertificateContext(MY_ENCODING_TYPE,pbData,cbData);
    if (pCertContext != NULL)
      { 
	  wszContainerName=NULL;
	  wszProvName=NULL;
	  cchContainerName = (lstrlen(psKeyContainer) + 1)  * sizeof(WCHAR);
	  cchCSPName = (lstrlen(psCspName) + 1) * sizeof(WCHAR);
      wszContainerName = (LPWSTR) malloc(cchContainerName);
      wszProvName = (LPWSTR) malloc(cchCSPName);
      mbstowcs(wszContainerName, psKeyContainer,cchContainerName);
	  mbstowcs(wszProvName, psCspName, cchCSPName);
      ZeroMemory((PVOID)&KeyProvInfo, sizeof(CRYPT_KEY_PROV_INFO));
      KeyProvInfo.pwszContainerName = (LPWSTR) wszContainerName;
      KeyProvInfo.pwszProvName      = (LPWSTR) wszProvName;
      KeyProvInfo.dwProvType        = PROV_RSA_SIG;
      KeyProvInfo.dwFlags           = 0;
      KeyProvInfo.dwKeySpec         = dwKeyType;
      fRes = CertSetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID, 0, (const void *) &KeyProvInfo);
      if (wszContainerName != NULL)
        free(wszContainerName);
      if (wszProvName != NULL)
        free(wszProvName);

      }
    }
  }

//if (pCertContext != NULL)
//  DigiCrypt_AddCertToStore(pCertContext);
if (fRes == FALSE && pCertContext != NULL)
  {
  CertFreeCertificateContext(pCertContext);
  pCertContext = NULL;
  }
if (pbData != NULL)
  free(pbData);
if (hCryptProv != 0)
  CryptReleaseContext(hCryptProv, 0);
return(pCertContext);
}
Ejemplo n.º 18
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;
}
/*****************************************************************************
 wmain

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

    HCERTSTORE              hStore = NULL;
    PCCERT_CONTEXT          pCert = NULL;
    PCCERT_CONTEXT          pStoreCert = NULL;

    char                    szStoreProvider[ 256 ] = { "TestExt" };

    // Store provider name
    LPWSTR pwszStoreProvider = NULL;
    // Store name
    LPWSTR pwszStoreName = L"TestStoreName";

    LPWSTR pwszCertPath = NULL;


    int i;

    //
    // options
    //

    for( i=1; i<argc; i++ )
    {
        if ( lstrcmpW (argv[i], L"/?") == 0 ||
             lstrcmpW (argv[i], L"-?") == 0 ) 
        {
            Usage( L"SampleStoreProvider.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"-p") == 0 )
        {
            if( i+1 >= argc )
            {
                hr = E_INVALIDARG;
                
                goto CleanUp;
            }

            pwszStoreProvider = argv[++i];
        }

    }

    if( i >= argc )
    {
        hr = E_INVALIDARG;
        
        goto CleanUp;
    }

    pwszCertPath = argv[i++];

    // Load the certificate from the file passed in as cmd line parameter;    
    if (!CryptQueryObject(
                                CERT_QUERY_OBJECT_FILE,         //dwObjectType 
                                pwszCertPath,                   //pvObject
                                CERT_QUERY_CONTENT_FLAG_CERT,   //dwExpectedContentTypeFlags
                                CERT_QUERY_FORMAT_FLAG_ALL,     //dwExpectedFormatTypeFlags 
                                0,                              //dwFlags
                                0,                              //pdwMsgAndCertEncodingType 
                                0,                              //pdwContentType 
                                0,                              //pdwFormatType 
                                0,                              //phCertStore
                                0,                              //phMsg 
                                (const void**)&pCert            //ppvContext
                                ))
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        
        goto CleanUp;
    }

    // Open the store using the sample provider name
    if( NULL != pwszStoreProvider )
    {
        if( 1 < WideCharToMultiByte(
                                CP_ACP, 
                                WC_ERR_INVALID_CHARS, 
                                pwszStoreProvider,
                                -1, 
                                szStoreProvider, 
                                sizeof(szStoreProvider),
                                NULL,    
                                NULL
                                ))
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            
            goto CleanUp;
        }
    }

    hStore = CertOpenStore(
                                szStoreProvider,        // lpszStoreProvider
                                X509_ASN_ENCODING,      // dwMsgAndCertEncodingType
                                NULL,                   // hCryptProv
                                0,                      // dwFlags (will create it if does not exists)
                                (void*)pwszStoreName);  // pvPara
    if (hStore == NULL)
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        
        goto CleanUp;
    }

    // Add a certificate to store
    if(!CertAddCertificateContextToStore(
                                hStore,                             // hCertStore
                                pCert,                              // pCertContext
                                CERT_STORE_ADD_REPLACE_EXISTING,    // dwAddDisposition
                                NULL                                // ppStoreContext
                                ))
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        
        goto CleanUp;
    }


    pStoreCert = CertFindCertificateInStore(
                                hStore,                             // hCertStore
                                X509_ASN_ENCODING,                  // dwCertEncodingType
                                0,                                  // dwFindFlags
                                CERT_FIND_EXISTING,                 // dwFindType        
                                pCert,                              // pvFindPara
                                NULL                                // pPrevCertContext
                                );
    if (pStoreCert == NULL)
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        
        goto CleanUp;
    }

    hr = S_OK;

CleanUp:

    if( NULL != pCert )
        CertFreeCertificateContext(pCert);
    
    if( NULL != pStoreCert )
        CertFreeCertificateContext(pStoreCert);

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

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

    return (DWORD)hr;
}
Ejemplo n.º 20
0
HRESULT WINAPI SoftpubAuthenticode(CRYPT_PROVIDER_DATA *data)
{
    BOOL ret;
    CERT_CHAIN_POLICY_STATUS policyStatus = { sizeof(policyStatus), 0 };

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

    if (data->pWintrustData->dwUIChoice != WTD_UI_NONE)
        FIXME("unimplemented for UI choice %d\n",
         data->pWintrustData->dwUIChoice);
    if (!data->csSigners)
    {
        ret = FALSE;
        policyStatus.dwError = TRUST_E_NOSIGNATURE;
    }
    else
    {
        DWORD i;

        ret = TRUE;
        for (i = 0; ret && i < data->csSigners; i++)
        {
            BYTE hash[20];
            DWORD size = sizeof(hash);

            /* First make sure cert isn't disallowed */
            if ((ret = CertGetCertificateContextProperty(
             data->pasSigners[i].pasCertChain[0].pCert,
             CERT_SIGNATURE_HASH_PROP_ID, hash, &size)))
            {
                static const WCHAR disallowedW[] =
                 { 'D','i','s','a','l','l','o','w','e','d',0 };
                HCERTSTORE disallowed = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
                 X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_CURRENT_USER,
                 disallowedW);

                if (disallowed)
                {
                    PCCERT_CONTEXT found = CertFindCertificateInStore(
                     disallowed, X509_ASN_ENCODING, 0, CERT_FIND_SIGNATURE_HASH,
                     hash, NULL);

                    if (found)
                    {
                        /* Disallowed!  Can't verify it. */
                        policyStatus.dwError = TRUST_E_SUBJECT_NOT_TRUSTED;
                        ret = FALSE;
                        CertFreeCertificateContext(found);
                    }
                    CertCloseStore(disallowed, 0);
                }
            }
            if (ret)
            {
                CERT_CHAIN_POLICY_PARA policyPara = { sizeof(policyPara), 0 };

                if (data->dwRegPolicySettings & WTPF_TRUSTTEST)
                    policyPara.dwFlags |= CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG;
                if (data->dwRegPolicySettings & WTPF_TESTCANBEVALID)
                    policyPara.dwFlags |= CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG;
                if (data->dwRegPolicySettings & WTPF_IGNOREEXPIRATION)
                    policyPara.dwFlags |=
                     CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG |
                     CERT_CHAIN_POLICY_IGNORE_CTL_NOT_TIME_VALID_FLAG |
                     CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG;
                if (data->dwRegPolicySettings & WTPF_IGNOREREVOKATION)
                    policyPara.dwFlags |=
                     CERT_CHAIN_POLICY_IGNORE_END_REV_UNKNOWN_FLAG |
                     CERT_CHAIN_POLICY_IGNORE_CTL_SIGNER_REV_UNKNOWN_FLAG |
                     CERT_CHAIN_POLICY_IGNORE_CA_REV_UNKNOWN_FLAG |
                     CERT_CHAIN_POLICY_IGNORE_ROOT_REV_UNKNOWN_FLAG;
                CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_AUTHENTICODE,
                 data->pasSigners[i].pChainContext, &policyPara, &policyStatus);
                if (policyStatus.dwError != NO_ERROR)
                    ret = FALSE;
            }
        }
    }
    if (!ret)
        data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV] =
         policyStatus.dwError;
    TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
     data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV]);
    return ret ? S_OK : S_FALSE;
}
Ejemplo n.º 21
0
Archivo: net.cpp Proyecto: wizzard/sdk
// handle WinHTTP callbacks (which can be in a worker thread context)
VOID CALLBACK WinHttpIO::asynccallback(HINTERNET hInternet, DWORD_PTR dwContext,
                                       DWORD dwInternetStatus,
                                       LPVOID lpvStatusInformation,
                                       DWORD dwStatusInformationLength)
{
    WinHttpContext* httpctx = (WinHttpContext*)dwContext;
    WinHttpIO* httpio = (WinHttpIO*)httpctx->httpio;

    if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING)
    {
        assert(!httpctx->req);

        if (httpctx->gzip)
        {
            inflateEnd(&httpctx->z);
        }
        
        delete httpctx;
        return;
    }

    httpio->lock();

    HttpReq* req = httpctx->req;

    // request cancellations that occured after asynccallback() was entered are caught here
    if (!req)
    {
        httpio->unlock();
        return;
    }

    switch (dwInternetStatus)
    {
        case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE:
        {
            DWORD size = *(DWORD*)lpvStatusInformation;

            if (!size)
            {
                if (debug)
                {
                    if (req->binary)
                    {
                        cout << "[received " << req->bufpos << " bytes of raw data]" << endl;
                    }
                    else
                    {
                        cout << "Received: " << req->in.c_str() << endl;
                    }
                }

                req->status = req->httpstatus == 200 ? REQ_SUCCESS : REQ_FAILURE;
                httpio->success = true;
            }
            else
            {
                char* ptr;

                if (httpctx->gzip)
                {
                    m_off_t zprevsize = httpctx->zin.size();
                    httpctx->zin.resize(zprevsize + size);
                    ptr = (char*)httpctx->zin.data() + zprevsize;
                }
                else
                {
                    ptr = (char*)req->reserveput((unsigned*)&size);
                    req->bufpos += size;
                }

                if (!WinHttpReadData(hInternet, ptr, size, NULL))
                {
                    httpio->cancel(req);
                }
            }

            httpio->httpevent();
            break;
        }

        case WINHTTP_CALLBACK_STATUS_READ_COMPLETE:
            if (dwStatusInformationLength)
            {
                if (req->httpio)
                {
                    req->httpio->lastdata = Waiter::ds;
                }
            
                if (httpctx->gzip)
                {
                    httpctx->z.next_in = (Bytef*)lpvStatusInformation;
                    httpctx->z.avail_in = dwStatusInformationLength;

                    req->bufpos += httpctx->z.avail_out;
                    int t = inflate(&httpctx->z, Z_SYNC_FLUSH);
                    req->bufpos -= httpctx->z.avail_out;

                    if ((char *)lpvStatusInformation + dwStatusInformationLength ==
                             httpctx->zin.data() + httpctx->zin.size())
                    {
                        httpctx->zin.clear();
                    }

                    if (t != Z_OK && (t != Z_STREAM_END || httpctx->z.avail_out))
                    {
                        httpio->cancel(req);
                    }
                }

                if (!WinHttpQueryDataAvailable(httpctx->hRequest, NULL))
                {
                    httpio->cancel(req);
                    httpio->httpevent();
                }
            }
            break;

        case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
        {
            DWORD statusCode;
            DWORD statusCodeSize = sizeof(statusCode);

            if (!WinHttpQueryHeaders(httpctx->hRequest,
                                     WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
                                     WINHTTP_HEADER_NAME_BY_INDEX,
                                     &statusCode,
                                     &statusCodeSize,
                                     WINHTTP_NO_HEADER_INDEX))
            {
                httpio->cancel(req);
                httpio->httpevent();
            }
            else
            {
                req->httpstatus = statusCode;

                if (req->httpio)
                {
                    req->httpio->lastdata = Waiter::ds;
                }

                if (!req->buf)
                {
                    // obtain original content length - always present if gzip is in use
                    DWORD contentLength;
                    DWORD contentLengthSize = sizeof(contentLength);

                    if (WinHttpQueryHeaders(httpctx->hRequest,
                                            WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_NUMBER,
                                            L"Original-Content-Length",
                                            &contentLength,
                                            &contentLengthSize,
                                            WINHTTP_NO_HEADER_INDEX))
                    {
                        req->setcontentlength(contentLength);

                        // check for gzip content encoding
                        WCHAR contentEncoding[16];
                        DWORD contentEncodingSize = sizeof(contentEncoding);

                        httpctx->gzip = WinHttpQueryHeaders(httpctx->hRequest,
                                                WINHTTP_QUERY_CONTENT_ENCODING,
                                                WINHTTP_HEADER_NAME_BY_INDEX,
                                                &contentEncoding,
                                                &contentEncodingSize,
                                                WINHTTP_NO_HEADER_INDEX)
                                    && !wcscmp(contentEncoding, L"gzip");

                        if (httpctx->gzip)
                        {
                            httpctx->z.zalloc = Z_NULL;
                            httpctx->z.zfree = Z_NULL;
                            httpctx->z.opaque = Z_NULL;
                            httpctx->z.avail_in = 0;
                            httpctx->z.next_in = Z_NULL;

                            inflateInit2(&httpctx->z, MAX_WBITS+16);

                            req->in.resize(contentLength);
                            httpctx->z.avail_out = contentLength;
                            httpctx->z.next_out = (unsigned char*)req->in.data();
                        }
                    }
                }

                if (!WinHttpQueryDataAvailable(httpctx->hRequest, NULL))
                {
                    httpio->cancel(req);
                    httpio->httpevent();
                }
                else if (httpio->waiter && httpio->noinetds)
                {
                    httpio->inetstatus(true);
                }
            }

            break;
        }

        case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
            if (httpio->waiter && GetLastError() != ERROR_WINHTTP_TIMEOUT)
            {
                httpio->inetstatus(false);
            }
            // fall through
        case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE:
            httpio->cancel(req);
            httpio->httpevent();
            break;

        case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
        {
            PCCERT_CONTEXT cert;
            DWORD len = sizeof cert;

            if (WinHttpQueryOption(httpctx->hRequest, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &len))
            {
                CRYPT_BIT_BLOB* pkey = &cert->pCertInfo->SubjectPublicKeyInfo.PublicKey;

                // this is an SSL connection: verify public key to prevent MITM attacks
                if (pkey->cbData != 270
                 || (memcmp(pkey->pbData, "\x30\x82\x01\x0a\x02\x82\x01\x01\x00" APISSLMODULUS1
                                          "\x02" APISSLEXPONENTSIZE APISSLEXPONENT, 270)
                  && memcmp(pkey->pbData, "\x30\x82\x01\x0a\x02\x82\x01\x01\x00" APISSLMODULUS2
                                          "\x02" APISSLEXPONENTSIZE APISSLEXPONENT, 270)))
                {
                    CertFreeCertificateContext(cert);
                    httpio->cancel(req);
                    httpio->httpevent();
                    break;
                }

                CertFreeCertificateContext(cert);
            }
        }
            // fall through
        case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE:
            if (httpctx->postpos < httpctx->postlen)
            {
                unsigned pos = httpctx->postpos;
                unsigned t = httpctx->postlen - pos;

                if (t > HTTP_POST_CHUNK_SIZE)
                {
                    t = HTTP_POST_CHUNK_SIZE;
                }

                httpctx->postpos += t;

                if (!WinHttpWriteData(httpctx->hRequest, (LPVOID)(httpctx->postdata + pos), t, NULL))
                {
                    req->httpio->cancel(req);
                }

                httpio->httpevent();
            }
            else
            {
                if (!WinHttpReceiveResponse(httpctx->hRequest, NULL))
                {
                    httpio->cancel(req);
                    httpio->httpevent();
                }
            }
    }

    httpio->unlock();
}
Ejemplo n.º 22
0
// Read URL server
LPSTR SoffidEssoManager::readURL (HINTERNET hSession, const wchar_t* host, int port,
		LPCWSTR path, BOOL allowUnknownCA, size_t *pSize)
{
	BOOL bResults = FALSE;
	HINTERNET hConnect = NULL, hRequest = NULL;

	DWORD dwDownloaded = -1;
	BYTE *buffer = NULL;

	if (debug)
	{
		log("Connecting to %s:%d...\n", host, port);
	}

	hConnect = WinHttpConnect(hSession, host, port, 0);

	if (hConnect)
	{
		if (debug)
		{
			log("Performing request %s...\n", path);
		}

		hRequest = WinHttpOpenRequest(hConnect, L"GET", path, NULL, WINHTTP_NO_REFERER,
				WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
	}

	// Send a request.
	if (hRequest)
	{
		if (debug)
			log("Sending request ...\n");

		WinHttpSetOption(hRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, NULL, 0);

		if (allowUnknownCA)
		{
			DWORD flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA;
			WinHttpSetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS, (LPVOID) &flags,
					sizeof flags);
		}

		bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
				WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
	}

	if (bResults && allowUnknownCA)
	{
		// Agreagar la CA ROOT
		PCERT_CONTEXT context;
		DWORD dwSize = sizeof context;
		BOOL result = WinHttpQueryOption(hRequest, WINHTTP_OPTION_SERVER_CERT_CONTEXT,
				&context, &dwSize);

		if (!result)
		{
			log("Cannot get context\n");
//			notifyError();
		}

		PCCERT_CONTEXT issuerContext = CertFindCertificateInStore(context->hCertStore,
				X509_ASN_ENCODING, 0, CERT_FIND_ISSUER_OF, context, NULL);
		HCERTSTORE systemStore = CertOpenStore((LPCSTR) 13, // CERT_STORE_PROV_SYSTEM_REGISTRY_W
				0, (HCRYPTPROV) NULL, (2 << 16) | // CERT_SYSTEM_STORE_LOCAL_MACHINE
						0x1000, // CERT_STORE_MAXIMUM_ALLOWED
				L"ROOT");
		CertAddCertificateContextToStore(systemStore, issuerContext,
				1 /*CERT_STORE_ADD_NEW*/, NULL);

		CertFreeCertificateContext(issuerContext);
		CertFreeCertificateContext(context);
	}

	// End the request.
	if (bResults)
	{
		if (debug)
			log("Waiting for response....\n");

		bResults = WinHttpReceiveResponse(hRequest, NULL);
	}

	// Keep checking for data until there is nothing left.
	DWORD used = 0;
	if (bResults)
	{
		const DWORD chunk = 4096;
		DWORD allocated = 0;
		do
		{
			if (used + chunk > allocated)
			{
				allocated += chunk;
				buffer = (LPBYTE) realloc(buffer, allocated);
			}

			dwDownloaded = 0;
			if (!WinHttpReadData(hRequest, &buffer[used], chunk, &dwDownloaded))
				dwDownloaded = -1;

			else
				used += dwDownloaded;
		} while (dwDownloaded > 0);

		buffer[used] = '\0';
	}

	DWORD dw = GetLastError();
	if (!bResults && debug)
	{
		if (dw == ERROR_WINHTTP_CANNOT_CONNECT)
			log("Error: Cannot connect\n");
		else if (dw == ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED)
			log("Error: Client CERT required\n");
		else if (dw == ERROR_WINHTTP_CONNECTION_ERROR)
			log("Error: Connection error\n");
		else if (dw == ERROR_WINHTTP_INCORRECT_HANDLE_STATE)
			log("Error: ERROR_WINHTTP_INCORRECT_HANDLE_STATE\n");
		else if (dw == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE)
			log("Error: ERROR_WINHTTP_INCORRECT_HANDLE_TYPE\n");
		else if (dw == ERROR_WINHTTP_INTERNAL_ERROR)
			log("Error: ERROR_WINHTTP_INTERNAL_ERROR\n");
		else if (dw == ERROR_WINHTTP_INVALID_URL)
			log("Error: ERROR_WINHTTP_INVALID_URL\n");
		else if (dw == ERROR_WINHTTP_LOGIN_FAILURE)
			log("Error: ERROR_WINHTTP_LOGIN_FAILURE\n");
		else if (dw == ERROR_WINHTTP_NAME_NOT_RESOLVED)
			log("Error: ERROR_WINHTTP_NAME_NOT_RESOLVED\n");
		else if (dw == ERROR_WINHTTP_OPERATION_CANCELLED)
			log("Error: ERROR_WINHTTP_OPERATION_CANCELLED\n");
		else if (dw == ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW)
			log("Error: ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW\n");
		else if (dw == ERROR_WINHTTP_SECURE_FAILURE)
			log("Error: ERROR_WINHTTP_SECURE_FAILURE\n");
		else if (dw == ERROR_WINHTTP_SHUTDOWN)
			log("Error: ERROR_WINHTTP_SHUTDOWN\n");
		else if (dw == ERROR_WINHTTP_TIMEOUT)
			log("Error: ERROR_WINHTTP_TIMEOUT\n");
		else if (dw == ERROR_WINHTTP_UNRECOGNIZED_SCHEME)
			log("Error: ERROR_WINHTTP_UNRECOGNIZED_SCHEME\n");
		else if (dw == ERROR_NOT_ENOUGH_MEMORY)
			log("Error: ERROR_NOT_ENOUGH_MEMORY\n");
		else if (dw == ERROR_INVALID_PARAMETER)
			log("Error: ERROR_INVALID_PARAMETER\n");
		else if (dw == ERROR_WINHTTP_RESEND_REQUEST)
			log("Error:  ERROR_WINHTTP_RESEND_REQUEST\n");
		else if (dw != ERROR_SUCCESS)
		{
			log("Unkonwn error %d\n", dw);
		}
//		notifyError();
	}

	// Close any open handles.
	if (hRequest)
		WinHttpCloseHandle(hRequest);
	if (hConnect)
		WinHttpCloseHandle(hConnect);
	if (hSession)
		WinHttpCloseHandle(hSession);

	SetLastError(dw);

	if (pSize != NULL)
		*pSize = used;

	return (LPSTR) buffer;
}
Ejemplo n.º 23
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;
}
Ejemplo n.º 24
0
/** The verbosity level. */
static unsigned  g_cVerbosityLevel = 1;


static const char *errorToString(DWORD dwErr)
{
    switch (dwErr)
    {
#define MY_CASE(a_uConst)       case a_uConst: return #a_uConst;
        MY_CASE(CRYPT_E_MSG_ERROR);
        MY_CASE(CRYPT_E_UNKNOWN_ALGO);
        MY_CASE(CRYPT_E_OID_FORMAT);
        MY_CASE(CRYPT_E_INVALID_MSG_TYPE);
        MY_CASE(CRYPT_E_UNEXPECTED_ENCODING);
        MY_CASE(CRYPT_E_AUTH_ATTR_MISSING);
        MY_CASE(CRYPT_E_HASH_VALUE);
        MY_CASE(CRYPT_E_INVALID_INDEX);
        MY_CASE(CRYPT_E_ALREADY_DECRYPTED);
        MY_CASE(CRYPT_E_NOT_DECRYPTED);
        MY_CASE(CRYPT_E_RECIPIENT_NOT_FOUND);
        MY_CASE(CRYPT_E_CONTROL_TYPE);
        MY_CASE(CRYPT_E_ISSUER_SERIALNUMBER);
        MY_CASE(CRYPT_E_SIGNER_NOT_FOUND);
        MY_CASE(CRYPT_E_ATTRIBUTES_MISSING);
        MY_CASE(CRYPT_E_STREAM_MSG_NOT_READY);
        MY_CASE(CRYPT_E_STREAM_INSUFFICIENT_DATA);
        MY_CASE(CRYPT_I_NEW_PROTECTION_REQUIRED);
        MY_CASE(CRYPT_E_BAD_LEN);
        MY_CASE(CRYPT_E_BAD_ENCODE);
        MY_CASE(CRYPT_E_FILE_ERROR);
        MY_CASE(CRYPT_E_NOT_FOUND);
        MY_CASE(CRYPT_E_EXISTS);
        MY_CASE(CRYPT_E_NO_PROVIDER);
        MY_CASE(CRYPT_E_SELF_SIGNED);
        MY_CASE(CRYPT_E_DELETED_PREV);
        MY_CASE(CRYPT_E_NO_MATCH);
        MY_CASE(CRYPT_E_UNEXPECTED_MSG_TYPE);
        MY_CASE(CRYPT_E_NO_KEY_PROPERTY);
        MY_CASE(CRYPT_E_NO_DECRYPT_CERT);
        MY_CASE(CRYPT_E_BAD_MSG);
        MY_CASE(CRYPT_E_NO_SIGNER);
        MY_CASE(CRYPT_E_PENDING_CLOSE);
        MY_CASE(CRYPT_E_REVOKED);
        MY_CASE(CRYPT_E_NO_REVOCATION_DLL);
        MY_CASE(CRYPT_E_NO_REVOCATION_CHECK);
        MY_CASE(CRYPT_E_REVOCATION_OFFLINE);
        MY_CASE(CRYPT_E_NOT_IN_REVOCATION_DATABASE);
        MY_CASE(CRYPT_E_INVALID_NUMERIC_STRING);
        MY_CASE(CRYPT_E_INVALID_PRINTABLE_STRING);
        MY_CASE(CRYPT_E_INVALID_IA5_STRING);
        MY_CASE(CRYPT_E_INVALID_X500_STRING);
        MY_CASE(CRYPT_E_NOT_CHAR_STRING);
        MY_CASE(CRYPT_E_FILERESIZED);
        MY_CASE(CRYPT_E_SECURITY_SETTINGS);
        MY_CASE(CRYPT_E_NO_VERIFY_USAGE_DLL);
        MY_CASE(CRYPT_E_NO_VERIFY_USAGE_CHECK);
        MY_CASE(CRYPT_E_VERIFY_USAGE_OFFLINE);
        MY_CASE(CRYPT_E_NOT_IN_CTL);
        MY_CASE(CRYPT_E_NO_TRUSTED_SIGNER);
        MY_CASE(CRYPT_E_MISSING_PUBKEY_PARA);
        MY_CASE(CRYPT_E_OSS_ERROR);
        default:
        {
            PCRTCOMERRMSG pWinComMsg = RTErrCOMGet(dwErr);
            if (pWinComMsg)
                return pWinComMsg->pszDefine;

            static char s_szErr[32];
            RTStrPrintf(s_szErr, sizeof(s_szErr), "%#x (%d)", dwErr, dwErr);
            return s_szErr;
        }
    }
}

#if 0 /* hacking */
static RTEXITCODE addToStore(const char *pszFilename, PCRTUTF16 pwszStore)
{
    /*
     * Open the source.
     */
    void   *pvFile;
    size_t  cbFile;
    int rc = RTFileReadAll(pszFilename, &pvFile, &cbFile);
    if (RT_FAILURE(rc))
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTFileReadAll failed on '%s': %Rrc", pszFilename, rc);

    RTEXITCODE rcExit = RTEXITCODE_FAILURE;

    PCCERT_CONTEXT pCertCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                                                           (PBYTE)pvFile,
                                                           (DWORD)cbFile);
    if (pCertCtx)
    {
        /*
         * Open the destination.
         */
        HCERTSTORE hDstStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
                                             PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                                             NULL /* hCryptProv = default */,
                                             /*CERT_SYSTEM_STORE_LOCAL_MACHINE*/ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG,
                                             pwszStore);
        if (hDstStore != NULL)
        {
#if 0
            DWORD dwContextType;
            if (CertAddSerializedElementToStore(hDstStore,
                                                pCertCtx->pbCertEncoded,
                                                pCertCtx->cbCertEncoded,
                                                CERT_STORE_ADD_NEW,
                                                0 /* dwFlags (reserved) */,
                                                CERT_STORE_ALL_CONTEXT_FLAG,
                                                &dwContextType,
                                                NULL))
            {
                RTMsgInfo("Successfully added '%s' to the '%ls' store (ctx type %u)", pszFilename, pwszStore, dwContextType);
                rcExit = RTEXITCODE_SUCCESS;
            }
            else
                RTMsgError("CertAddSerializedElementToStore returned %s", errorToString(GetLastError()));
#else
            if (CertAddCertificateContextToStore(hDstStore, pCertCtx, CERT_STORE_ADD_NEW, NULL))
            {
                RTMsgInfo("Successfully added '%s' to the '%ls' store", pszFilename, pwszStore);
                rcExit = RTEXITCODE_SUCCESS;
            }
            else
                RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError()));
#endif

            CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
        }
        else
            RTMsgError("CertOpenStore returned %s", errorToString(GetLastError()));
        CertFreeCertificateContext(pCertCtx);
    }
    else
        RTMsgError("CertCreateCertificateContext returned %s", errorToString(GetLastError()));
    RTFileReadAllFree(pvFile, cbFile);
    return rcExit;

#if 0

    CRYPT_DATA_BLOB Blob;
    Blob.cbData = (DWORD)cbData;
    Blob.pbData = (PBYTE)pvData;
    HCERTSTORE hSrcStore = PFXImportCertStore(&Blob, L"", )

#endif
}
Ejemplo n.º 25
0
/* {{{ static int ma_tls_set_client_certs(MARIADB_TLS *ctls) */
static int ma_tls_set_client_certs(MARIADB_TLS *ctls)
{
  MYSQL *mysql= ctls->pvio->mysql;
  char *certfile= mysql->options.ssl_cert,
       *keyfile= mysql->options.ssl_key,
       *cafile= mysql->options.ssl_ca;
  PCERT_CONTEXT ca_ctx= NULL;
  PCRL_CONTEXT crl_ctx = NULL;
       
  SC_CTX *sctx= (SC_CTX *)ctls->ssl;
  MARIADB_PVIO *pvio= ctls->pvio;

  if (cafile)
  {
    if (!(ca_ctx = ma_schannel_create_cert_context(pvio, cafile)))
      goto end;

    /* Add ca to in-memory certificate store */
    if (CertAddCertificateContextToStore(ca_CertStore, ca_ctx, CERT_STORE_ADD_NEWER, NULL) != TRUE &&
        GetLastError() != CRYPT_E_EXISTS)
    {
      ma_schannel_set_win_error(sctx->mysql);
      goto end;
    }
    ca_Check= 0;
    CertFreeCertificateContext(ca_ctx);
  }

  if (!certfile && keyfile)
    certfile= keyfile;
  if (!keyfile && certfile)
    keyfile= certfile;

  if (certfile && certfile[0])
    if (!(sctx->client_cert_ctx = ma_schannel_create_cert_context(ctls->pvio, certfile)))
      goto end;

  if (sctx->client_cert_ctx && keyfile[0])
    if (!ma_schannel_load_private_key(pvio, sctx->client_cert_ctx, keyfile))
      goto end;
 
  if (mysql->options.extension && mysql->options.extension->ssl_crl)
  {
    if (!(crl_ctx= (CRL_CONTEXT *)ma_schannel_create_crl_context(pvio, mysql->options.extension->ssl_crl)))
      goto end;
    /* Add ca to in-memory certificate store */
    if (CertAddCRLContextToStore(crl_CertStore, crl_ctx, CERT_STORE_ADD_NEWER, NULL) != TRUE &&
        GetLastError() != CRYPT_E_EXISTS)
    {
      ma_schannel_set_win_error(sctx->mysql);
      goto end;
    }
    crl_Check = 1;
    CertFreeCertificateContext(ca_ctx);
  }
  return 0;
  
end:
  if (ca_ctx)
    CertFreeCertificateContext(ca_ctx);
  if (sctx->client_cert_ctx)
    CertFreeCertificateContext(sctx->client_cert_ctx);
  if (crl_ctx)
    CertFreeCRLContext(crl_ctx);
  sctx->client_cert_ctx= NULL;
  return 1;
}
Ejemplo n.º 26
0
/**
 * Removes a certificate, given by file, from a store
 *
 * @returns true on success, false on failure (error message written).
 * @param   dwDst           The destination, like
 *                          CERT_SYSTEM_STORE_LOCAL_MACHINE or
 *                          CERT_SYSTEM_STORE_CURRENT_USER.
 * @param   pszStoreNm      The store name.
 * @param   pszCertFile     The file containing the certificate to add.
 */
static bool removeCertFromStoreByFile(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile)
{
    /*
     * Read the certificate file first.
     */
    PCCERT_CONTEXT  pSrcCtx   = NULL;
    HCERTSTORE      hSrcStore = NULL;
    if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
        return false;

    WCHAR wszName[1024];
    if (!CertGetNameStringW(pSrcCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/,
                            wszName, sizeof(wszName)))
    {
        RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError()));
        wszName[0] = '\0';
    }

    /*
     * Open the destination store.
     */
    bool fRc = false;
    HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
    if (hDstStore)
    {
        if (pSrcCtx)
        {
            fRc = true;
            unsigned        cDeleted = 0;
            PCCERT_CONTEXT  pCurCtx  = NULL;
            while ((pCurCtx = CertEnumCertificatesInStore(hDstStore, pCurCtx)) != NULL)
            {
                if (CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pCurCtx->pCertInfo, pSrcCtx->pCertInfo))
                {
                    if (g_cVerbosityLevel > 1)
                        RTMsgInfo("Removing '%ls'...", wszName);
                    PCCERT_CONTEXT pDeleteCtx = CertDuplicateCertificateContext(pCurCtx);
                    if (pDeleteCtx)
                    {
                        if (CertDeleteCertificateFromStore(pDeleteCtx))
                            cDeleted++;
                        else
                            RTMsgError("CertDeleteFromStore('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
                    }
                    else
                        RTMsgError("CertDuplicateCertificateContext('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
                }
            }

            if (!cDeleted)
                RTMsgInfo("Found no matching certificates to remove.");
        }
        else
        {
            RTMsgError("Path not implemented at line %d\n",  __LINE__);
        }

        CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
    }
    if (pSrcCtx)
        CertFreeCertificateContext(pSrcCtx);
    if (hSrcStore)
        CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
    return fRc;
}
Ejemplo n.º 27
0
static void test_retrieveObjectByUrl(void)
{
    BOOL ret;
    char tmpfile[MAX_PATH * 2], *ptr, url[MAX_PATH + 8];
    CRYPT_BLOB_ARRAY *pBlobArray;
    PCCERT_CONTEXT cert;
    PCCRL_CONTEXT crl;
    HCERTSTORE store;
    CRYPT_RETRIEVE_AUX_INFO aux = { 0 };
    FILETIME ft = { 0 };

    SetLastError(0xdeadbeef);
    ret = CryptRetrieveObjectByUrlA(NULL, NULL, 0, 0, NULL, NULL, NULL, NULL,
     NULL);
    ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
     "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());

    make_tmp_file(tmpfile);
    ptr = strchr(tmpfile, ':');
    if (ptr)
        ptr += 2; /* skip colon and first slash */
    else
        ptr = tmpfile;
    snprintf(url, sizeof(url), "file:///%s", ptr);
    do {
        ptr = strchr(url, '\\');
        if (ptr)
            *ptr = '/';
    } while (ptr);

    pBlobArray = (CRYPT_BLOB_ARRAY *)0xdeadbeef;
    ret = CryptRetrieveObjectByUrlA(url, NULL, 0, 0, (void **)&pBlobArray,
     NULL, NULL, NULL, NULL);
    ok(ret, "CryptRetrieveObjectByUrlA failed: %d\n", GetLastError());
    ok(pBlobArray && pBlobArray != (CRYPT_BLOB_ARRAY *)0xdeadbeef,
     "Expected a valid pointer\n");
    if (pBlobArray && pBlobArray != (CRYPT_BLOB_ARRAY *)0xdeadbeef)
    {
        ok(pBlobArray->cBlob == 1, "Expected 1 blob, got %d\n",
         pBlobArray->cBlob);
        ok(pBlobArray->rgBlob[0].cbData == sizeof(certWithCRLDistPoint),
         "Unexpected size %d\n", pBlobArray->rgBlob[0].cbData);
        CryptMemFree(pBlobArray);
    }
    cert = (PCCERT_CONTEXT)0xdeadbeef;
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE, 0, 0,
     (void **)&cert, NULL, NULL, NULL, NULL);
    ok(cert && cert != (PCCERT_CONTEXT)0xdeadbeef, "Expected a cert\n");
    if (cert && cert != (PCCERT_CONTEXT)0xdeadbeef)
        CertFreeCertificateContext(cert);
    crl = (PCCRL_CONTEXT)0xdeadbeef;
    SetLastError(0xdeadbeef);
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CRL, 0, 0, (void **)&crl,
     NULL, NULL, NULL, NULL);
    ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
     "Expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
    ok(crl == NULL, "Expected CRL to be NULL\n");
    if (crl && crl != (PCCRL_CONTEXT)0xdeadbeef)
        CertFreeCRLContext(crl);
    store = (HCERTSTORE)0xdeadbeef;
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CAPI2_ANY, 0, 0,
     (void **)&store, NULL, NULL, NULL, NULL);
    ok(ret, "CryptRetrieveObjectByUrlA failed: %d\n", GetLastError());
    if (store && store != (HCERTSTORE)0xdeadbeef)
    {
        DWORD certs = 0;

        cert = NULL;
        do {
            cert = CertEnumCertificatesInStore(store, cert);
            if (cert)
                certs++;
        } while (cert);
        ok(certs == 1, "Expected 1 cert, got %d\n", certs);
        CertCloseStore(store, 0);
    }
    /* Are file URLs cached? */
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE,
     CRYPT_CACHE_ONLY_RETRIEVAL, 0, (void **)&cert, NULL, NULL, NULL, NULL);
    ok(ret, "CryptRetrieveObjectByUrlA failed: %08x\n", GetLastError());
    if (cert && cert != (PCCERT_CONTEXT)0xdeadbeef)
        CertFreeCertificateContext(cert);
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE, 0, 0,
     (void **)&cert, NULL, NULL, NULL, &aux);
    ok(ret, "CryptRetrieveObjectByUrlA failed: %08x\n", GetLastError());
    if (cert && cert != (PCCERT_CONTEXT)0xdeadbeef)
        CertFreeCertificateContext(cert);
    aux.cbSize = sizeof(aux);
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE, 0, 0,
     (void **)&cert, NULL, NULL, NULL, &aux);
    ok(ret, "CryptRetrieveObjectByUrlA failed: %08x\n", GetLastError());
    aux.pLastSyncTime = &ft;
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE, 0, 0,
     (void **)&cert, NULL, NULL, NULL, &aux);
    ok(ft.dwLowDateTime || ft.dwHighDateTime,
     "Expected last sync time to be set\n");
    DeleteFileA(tmpfile);
    /* Okay, after being deleted, are file URLs still cached? */
    SetLastError(0xdeadbeef);
    ret = CryptRetrieveObjectByUrlA(url, CONTEXT_OID_CERTIFICATE,
     CRYPT_CACHE_ONLY_RETRIEVAL, 0, (void **)&cert, NULL, NULL, NULL, NULL);
    ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND ||
     GetLastError() == ERROR_PATH_NOT_FOUND),
     "Expected ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND, got %d\n",
     GetLastError());
}
Ejemplo n.º 28
0
static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode)
{
    SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
    SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
    SecHandle *cred = &cred_handle;
    BYTE *read_buf;
    SIZE_T read_buf_size = 2048;
    ULONG attrs = 0;
    CtxtHandle ctx;
    SSIZE_T size;
    int bits;
    const CERT_CONTEXT *cert;
    SECURITY_STATUS status;
    DWORD res = ERROR_SUCCESS;

    const DWORD isc_req_flags = ISC_REQ_ALLOCATE_MEMORY|ISC_REQ_USE_SESSION_KEY|ISC_REQ_CONFIDENTIALITY
        |ISC_REQ_SEQUENCE_DETECT|ISC_REQ_REPLAY_DETECT|ISC_REQ_MANUAL_CRED_VALIDATION;

    if(!ensure_cred_handle())
        return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;

    if(compat_mode) {
        if(!have_compat_cred_handle)
            return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
        cred = &compat_cred_handle;
    }

    read_buf = heap_alloc(read_buf_size);
    if(!read_buf)
        return ERROR_OUTOFMEMORY;

    status = InitializeSecurityContextW(cred, NULL, connection->server->name, isc_req_flags, 0, 0, NULL, 0,
            &ctx, &out_desc, &attrs, NULL);

    assert(status != SEC_E_OK);

    set_socket_blocking(connection, TRUE);

    while(status == SEC_I_CONTINUE_NEEDED || status == SEC_E_INCOMPLETE_MESSAGE) {
        if(out_buf.cbBuffer) {
            assert(status == SEC_I_CONTINUE_NEEDED);

            TRACE("sending %u bytes\n", out_buf.cbBuffer);

            size = sock_send(connection->socket, out_buf.pvBuffer, out_buf.cbBuffer, 0);
            if(size != out_buf.cbBuffer) {
                ERR("send failed\n");
                status = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
                break;
            }

            FreeContextBuffer(out_buf.pvBuffer);
            out_buf.pvBuffer = NULL;
            out_buf.cbBuffer = 0;
        }

        if(status == SEC_I_CONTINUE_NEEDED) {
            assert(in_bufs[1].cbBuffer < read_buf_size);

            memmove(read_buf, (BYTE*)in_bufs[0].pvBuffer+in_bufs[0].cbBuffer-in_bufs[1].cbBuffer, in_bufs[1].cbBuffer);
            in_bufs[0].cbBuffer = in_bufs[1].cbBuffer;

            in_bufs[1].BufferType = SECBUFFER_EMPTY;
            in_bufs[1].cbBuffer = 0;
            in_bufs[1].pvBuffer = NULL;
        }

        assert(in_bufs[0].BufferType == SECBUFFER_TOKEN);
        assert(in_bufs[1].BufferType == SECBUFFER_EMPTY);

        if(in_bufs[0].cbBuffer + 1024 > read_buf_size) {
            BYTE *new_read_buf;

            new_read_buf = heap_realloc(read_buf, read_buf_size + 1024);
            if(!new_read_buf) {
                status = E_OUTOFMEMORY;
                break;
            }

            in_bufs[0].pvBuffer = read_buf = new_read_buf;
            read_buf_size += 1024;
        }

        size = sock_recv(connection->socket, read_buf+in_bufs[0].cbBuffer, read_buf_size-in_bufs[0].cbBuffer, 0);
        if(size < 1) {
            WARN("recv error\n");
            res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
            break;
        }

        TRACE("recv %lu bytes\n", size);

        in_bufs[0].cbBuffer += size;
        in_bufs[0].pvBuffer = read_buf;
        status = InitializeSecurityContextW(cred, &ctx, connection->server->name,  isc_req_flags, 0, 0, &in_desc,
                0, NULL, &out_desc, &attrs, NULL);
        TRACE("InitializeSecurityContext ret %08x\n", status);

        if(status == SEC_E_OK) {
            if(SecIsValidHandle(&connection->ssl_ctx))
                DeleteSecurityContext(&connection->ssl_ctx);
            connection->ssl_ctx = ctx;

            if(in_bufs[1].BufferType == SECBUFFER_EXTRA)
                FIXME("SECBUFFER_EXTRA not supported\n");

            status = QueryContextAttributesW(&ctx, SECPKG_ATTR_STREAM_SIZES, &connection->ssl_sizes);
            if(status != SEC_E_OK) {
                WARN("Could not get sizes\n");
                break;
            }

            status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
            if(status == SEC_E_OK) {
                res = netconn_verify_cert(connection, cert, cert->hCertStore);
                CertFreeCertificateContext(cert);
                if(res != ERROR_SUCCESS) {
                    WARN("cert verify failed: %u\n", res);
                    break;
                }
            }else {
                WARN("Could not get cert\n");
                break;
            }

            connection->ssl_buf = heap_alloc(connection->ssl_sizes.cbHeader + connection->ssl_sizes.cbMaximumMessage
                    + connection->ssl_sizes.cbTrailer);
            if(!connection->ssl_buf) {
                res = GetLastError();
                break;
            }
        }
    }

    heap_free(read_buf);

    if(status != SEC_E_OK || res != ERROR_SUCCESS) {
        WARN("Failed to establish SSL connection: %08x (%u)\n", status, res);
        heap_free(connection->ssl_buf);
        connection->ssl_buf = NULL;
        return res ? res : ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
    }

    TRACE("established SSL connection\n");
    connection->secure = TRUE;
    connection->security_flags |= SECURITY_FLAG_SECURE;

    bits = NETCON_GetCipherStrength(connection);
    if (bits >= 128)
        connection->security_flags |= SECURITY_FLAG_STRENGTH_STRONG;
    else if (bits >= 56)
        connection->security_flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
    else
        connection->security_flags |= SECURITY_FLAG_STRENGTH_WEAK;

    if(connection->mask_errors)
        connection->server->security_flags = connection->security_flags;
    return ERROR_SUCCESS;
}
Ejemplo n.º 29
0
my_bool ma_schannel_verify_certs(SC_CTX *sctx, DWORD dwCertFlags)
{
  SECURITY_STATUS sRet;
  DWORD flags;
  MARIADB_PVIO *pvio= sctx->mysql->net.pvio;
  PCCERT_CONTEXT pServerCert= NULL;
  PCCERT_CONTEXT ca_CTX = NULL;
  PCCRL_CONTEXT crl_CTX = NULL;
  my_bool is_Ok = 0;

  if ((sRet= QueryContextAttributes(&sctx->ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&pServerCert)) != SEC_E_OK)
  {
    ma_schannel_set_sec_error(pvio, sRet);
    return 0;
  }

  if (ca_Check)
  {
    flags = CERT_STORE_SIGNATURE_FLAG |
      CERT_STORE_TIME_VALIDITY_FLAG;

    while ((ca_CTX = CertFindCertificateInStore(ca_CertStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
      0, CERT_FIND_ANY, 0, ca_CTX)) && !is_Ok)
    {
      if (sRet = CertVerifySubjectCertificateContext(pServerCert, ca_CTX, &flags))
        is_Ok = 1;
    }

    if (ca_CTX)
      CertFreeCertificateContext(ca_CTX);

    if (!is_Ok)
    {
      ma_schannel_set_win_error(pvio);
      return 0;
    }

    if (flags)
    {
      if ((flags & CERT_STORE_SIGNATURE_FLAG) != 0)
        pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Certificate signature check failed");
      else if ((flags & CERT_STORE_REVOCATION_FLAG) != 0)
        pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "certificate was revoked");
      else if ((flags & CERT_STORE_TIME_VALIDITY_FLAG) != 0)
        pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "certificate has expired");
      else
        pvio->set_error(sctx->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "Unknown error during certificate validation");
      return 0;
    }
  }

  /* Check if none of the certificates in the certificate chain have been revoked. */
  if (crl_Check)
  {
    while ((crl_CTX = CertEnumCRLsInStore(crl_CertStore, crl_CTX)))
    {
      PCRL_INFO Info[1];

      Info[0] = crl_CTX->pCrlInfo;
      if (!(CertVerifyCRLRevocation(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
        pServerCert->pCertInfo,
        1, Info)))
      {
        CertFreeCRLContext(crl_CTX);
        pvio->set_error(pvio->mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, "CRL Revocation failed");
        return 0;
      }
    }
    CertFreeCRLContext(crl_CTX);
  }
  return 1;
}
Ejemplo n.º 30
0
    Win32CertificatePtr Win32Certificate::findRootCertificate(
        Win32CertificateLocation certStoreLocation, 
        Win32CertificateStore certStore)
    {
        std::wstring storeName;
        switch (certStore)
        {
        case Cs_AddressBook:            storeName = L"AddressBook";      break;
        case Cs_AuthRoot:               storeName = L"AuthRoot";         break;
        case Cs_CertificateAuthority:   storeName = L"CA";               break;
        case Cs_Disallowed:             storeName = L"Disallowed";       break;
        case Cs_My:                     storeName = L"MY";               break;
        case Cs_Root:                   storeName = L"Root";             break;
        case Cs_TrustedPeople:          storeName = L"TrustedPeople";    break;
        case Cs_TrustedPublisher:       storeName = L"TrustedPublisher"; break;
        default:
            RCF_ASSERT(0 && "Invalid certificate store value.");
        }

        DWORD dwFlags = 0;
        switch (certStoreLocation)
        {
        case Cl_CurrentUser:            dwFlags = CERT_SYSTEM_STORE_CURRENT_USER;   break;
        case Cl_LocalMachine:           dwFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;  break;
        default:
            RCF_ASSERT(0 && "Invalid certificate store location value.");
        }

        Win32CertificatePtr issuerCertPtr;

        HCERTSTORE hCertStore = CertOpenStore(
            (LPCSTR) CERT_STORE_PROV_SYSTEM,
            X509_ASN_ENCODING,
            0,
            dwFlags,
            storeName.c_str());

        DWORD dwErr = GetLastError();

        RCF_VERIFY(
            hCertStore, 
            Exception(_RcfError_ApiError("CertOpenStore()"), dwErr));

        PCCERT_CONTEXT  pSubjectContext = getWin32Context();

        DWORD           dwCertFlags = 0;
        PCCERT_CONTEXT  pIssuerContext = NULL;

        pSubjectContext = CertDuplicateCertificateContext(pSubjectContext);
        if (pSubjectContext)
        {
            do 
            {
                dwCertFlags = 
                        CERT_STORE_REVOCATION_FLAG 
                    |   CERT_STORE_SIGNATURE_FLAG 
                    |   CERT_STORE_TIME_VALIDITY_FLAG;

                pIssuerContext = CertGetIssuerCertificateFromStore(
                    hCertStore,
                    pSubjectContext, 
                    0, 
                    &dwCertFlags);

                if (pIssuerContext) 
                {
                    CertFreeCertificateContext(pSubjectContext);
                    pSubjectContext = pIssuerContext;
                    if (dwCertFlags & CERT_STORE_NO_CRL_FLAG)
                    {
                        // No CRL list available. Proceed anyway.
                        dwCertFlags &= ~(CERT_STORE_NO_CRL_FLAG | CERT_STORE_REVOCATION_FLAG);
                    }
                    if (dwCertFlags) 
                    {
                        if ( dwCertFlags & CERT_STORE_TIME_VALIDITY_FLAG)
                        {
                            // Certificate is expired.
                            // ...
                        }
                        break;
                    }
                } 
                else if (GetLastError() == CRYPT_E_SELF_SIGNED) 
                {
                    // Got the root certificate.
                    issuerCertPtr.reset( new Win32Certificate(pSubjectContext) );
                }
            } 
            while (pIssuerContext);
        }

        CertCloseStore(hCertStore, 0);

        return issuerCertPtr;
    }