Programma C di esempio: creazione di una catena di certificati
Nell'esempio seguente viene creato e installato un motore di catena di certificati non definito. Il motore viene usato per compilare catene di certificati per ognuno dei certificati in un archivio certificati.
In questo esempio vengono illustrate le attività seguenti e le funzioni CryptoAPI :
- Preparazione per creare un motore di catena di certificati non definito dichiarando e inizializzando una struttura di dati CERT_CHAIN_ENGINE_CONFIG .
- Creazione del motore di ricerca con CertCreateCertificateChainEngine.
- Uso di CertOpenSystemStore per aprire l'archivio di sistema personale.
- Recupero di tutti i certificati dall'archivio aperto usando CertEnumCertificatesInStore in un ciclo.
- Per ogni certificato nell'archivio aperto, recuperando il nome dell'oggetto dal certificato usando CertGetNameString.
- Compilazione di una catena di certificati per ogni certificato usando CertGetCertificateChain.
- Creazione di un duplicato della catena di certificati usando CertDuplicateCertificateChain.
- Uso di CertFreeCertificateChain per rilasciare ogni catena prima della compilazione della catena successiva.
#pragma comment(lib, "crypt32.lib")
#include <stdio.h>
#include <windows.h>
#include <Wincrypt.h>
void MyHandleError(char *s);
void main(void)
{
//---------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Declare and initialize variables.
HCERTCHAINENGINE hChainEngine;
CERT_CHAIN_ENGINE_CONFIG ChainConfig;
PCCERT_CHAIN_CONTEXT pChainContext;
PCCERT_CHAIN_CONTEXT pDupContext;
HCERTSTORE hCertStore;
PCCERT_CONTEXT pCertContext = NULL;
CERT_ENHKEY_USAGE EnhkeyUsage;
CERT_USAGE_MATCH CertUsage;
CERT_CHAIN_PARA ChainPara;
DWORD dwFlags=0;
LPWSTR pszNameString;
//---------------------------------------------------------
// Initialize data structures.
if(!(pszNameString=(LPWSTR)malloc(256)))
MyHandleError("Memory allocation failed.");
EnhkeyUsage.cUsageIdentifier = 0;
EnhkeyUsage.rgpszUsageIdentifier=NULL;
CertUsage.dwType = USAGE_MATCH_TYPE_AND;
CertUsage.Usage = EnhkeyUsage;
ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
ChainPara.RequestedUsage=CertUsage;
ChainConfig.cbSize = sizeof(CERT_CHAIN_ENGINE_CONFIG);
ChainConfig.hRestrictedRoot= NULL ;
ChainConfig.hRestrictedTrust= NULL ;
ChainConfig.hRestrictedOther= NULL ;
ChainConfig.cAdditionalStore=0 ;
ChainConfig.rghAdditionalStore = NULL ;
ChainConfig.dwFlags = CERT_CHAIN_CACHE_END_CERT;
ChainConfig.dwUrlRetrievalTimeout= 0 ;
ChainConfig.MaximumCachedCertificates=0 ;
ChainConfig.CycleDetectionModulus = 0;
//---------------------------------------------------------
// Create the nondefault certificate chain engine.
if(CertCreateCertificateChainEngine(
&ChainConfig,
&hChainEngine))
{
printf("A chain engine has been created.\n");
}
else
{
MyHandleError("The engine creation function failed.");
}
// Open the My system store.
if(hCertStore=CertOpenSystemStore(NULL,L"MY"))
{
printf("The MY Store is open.\n");
}
else
{
MyHandleError("The MY system store did not open.");
}
//-------------------------------------------------------
// Loop through the certificates in the store,
// and create a chain for each.
while(pCertContext = CertEnumCertificatesInStore(
hCertStore,
pCertContext))
{
//-------------------------------------------------------------------
// Get and display the name of subject of the certificate.
if(CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pszNameString,
128))
{
printf("\nCertificate for %s found.\n",pszNameString);
}
else
{
MyHandleError("CertGetName failed.");
}
//-------------------------------------------------------------------
// Build a chain using CertGetCertificateChain
// and the certificate retrieved.
if(CertGetCertificateChain(
NULL, // use the default chain engine
pCertContext, // pointer to the end certificate
NULL, // use the default time
NULL, // search no additional stores
&ChainPara, // use AND logic and enhanced key usage
// as indicated in the ChainPara
// data structure
dwFlags,
NULL, // currently reserved
&pChainContext)) // return a pointer to the chain created
{
printf("The chain has been created. \n");
}
else
{
MyHandleError("The chain could not be created.");
}
//---------------------------------------------------------------
// Display some of the contents of the chain.
printf("The size of the chain context "
"is %d. \n",pChainContext->cbSize);
printf("%d simple chains found.\n",pChainContext->cChain);
printf("\nError status for the chain:\n");
DWORD errorStatus = pChainContext->TrustStatus->dwErrorStatus;
if((errorStatus & CERT_TRUST_IS_NOT_TIME_VALID) != 0)
{
printf("This certificate or one of the certificates in the "
"certificate chain is not time-valid.\n");
}
if((errorStatus & CERT_TRUST_IS_REVOKED) != 0)
{
printf("Trust for this certificate or one of the certificates "
"in the certificate chain has been revoked.\n");
}
if((errorStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID) != 0)
{
printf("The certificate or one of the certificates in the "
"certificate chain does not have a valid signature.\n");
}
if((errorStatus & CERT_TRUST_IS_NOT_VALID_FOR_USAGE) != 0)
{
printf("The certificate or certificate chain is not valid "
"in its proposed usage.\n");
}
if((errorStatus & CERT_TRUST_IS_UNTRUSTED_ROOT) != 0)
{
printf("The certificate or certificate chain is based "
"on an untrusted root.\n");
}
if((errorStatus & CERT_TRUST_REVOCATION_STATUS_UNKNOWN) != 0)
{
printf("The revocation status of the certificate or one of the"
"certificates in the certificate chain is unknown.\n");
}
if((errorStatus & CERT_TRUST_IS_CYCLIC) != 0)
{
printf("One of the certificates in the chain was issued by a "
"certification authority that the original certificate "
"had certified.\n");
}
if((errorStatus & CERT_TRUST_IS_PARTIAL_CHAIN) != 0)
{
printf("The certificate chain is not complete.\n");
}
if((errorStatus & CERT_TRUST_CTL_IS_NOT_TIME_VALID) != 0)
{
printf("A CTL used to create this chain was not time-valid.\n");
}
if((errorStatus & CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID) != 0)
{
printf("A CTL used to create this chain did not have a valid "
"signature.\n");
}
if((errorStatus & CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE) != 0)
{
printf("A CTL used to create this chain did not have a valid "
"signature.\n");
}
else // CERT_TRUST_NO_ERROR
{
printf("No error found for this certificate or chain.\n");
}
printf("\nInfo status for the chain:\n");
DWORD infoStatus = pChainContext->TrustStatus.dwInfoStatus;
if((infoStatus & CERT_TRUST_HAS_EXACT_MATCH_ISSUER) != 0)
{
printf("An exact match issuer certificate has been found for "
"this certificate.\n");
}
if((infoStatus & CERT_TRUST_HAS_KEY_MATCH_ISSUER) != 0)
{
printf("A key match issuer certificate has been found for this "
"certificate.\n");
}
if((infoStatus & CERT_TRUST_HAS_NAME_MATCH_ISSUER) != 0)
{
printf("A name match issuer certificate has been found for this "
"certificate.\n");
}
if((infoStatus & CERT_TRUST_IS_SELF_SIGNED) != 0)
{
printf("This certificate is self-signed.\n");
}
if((infoStatus & CERT_TRUST_IS_COMPLEX_CHAIN) != 0)
{
printf("The certificate chain created is a complex chain.\n");
}
else // No dwInfoStatus bits set
{
printf("No information status reported.\n");
}
//-------------------------------------------------------------------
// Duplicate the original chain.
if(pDupContext = CertDuplicateCertificateChain(
pChainContext ))
{
printf("Duplicated the chain.\n");
}
else
{
printf("Duplication failed.\n");
}
//-------------------------------------------------------------------
// Free both chains.
CertFreeCertificateChain(pDupContext);
printf("The duplicate chains is free.\n");
CertFreeCertificateChain(pChainContext);
printf("The Original chain is free.\n");
printf("\nPress Enter to continue.");
getchar();
} // end while loop
printf("\nThere are no more certificates in the store. \n");
//---------------------------------------------------------
// Free the chain engine.
CertFreeCertificateChainEngine(hChainEngine);
printf("The chain engine has been released.\n");
// Free memory for pszNameString.
if(pszNameString)
free(pszNameString);
printf("The demo program ran to completion without error.\n");
} // end main
//-------------------------------------------------------------------
// This example uses the function MyHandleError, a simple error
// handling function to print an error message and exit
// the program.
// For most applications, replace this function with one
// that does more extensive error reporting.
void MyHandleError(char *s)
{
fprintf(stderr,"An error occurred in running the program. \n");
fprintf(stderr,"%s\n",s);
fprintf(stderr, "Error number %x.\n", GetLastError());
fprintf(stderr, "Program terminating. \n");
exit(1);
} // end MyHandleError