win_cert_handler.c
来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 580 行 · 第 1/2 页
C
580 行
/**
* \brief Free the memory that was allocated to store the certificate enumeration.
*
* @param[in] numcas The number of CAs that are represented in the enumeration.
* @param[in] cas The array of CA names.
**/
void cert_handler_free_cert_enum(int numcas, cert_enum **cas)
{
cert_enum *casa = NULL;
int i = 0;
casa = (*cas);
for (i = 0; i < numcas; i++)
{
if (casa[i].certname != NULL) FREE(casa[i].certname);
if (casa[i].friendlyname != NULL) FREE(casa[i].friendlyname);
if (casa[i].issuer != NULL) FREE(casa[i].issuer);
}
free((*cas));
(*cas) = NULL;
}
char *do_sha1(char *tohash, int size)
{
EVP_MD_CTX ctx;
char *hash_ret;
int evp_ret_len;
if (!xsup_assert((tohash != NULL), "tohash != NULL", FALSE))
return NULL;
if (!xsup_assert((size > 0), "size > 0", FALSE))
return NULL;
hash_ret = (char *)Malloc(21); // We should get 20 bytes returned.
if (hash_ret == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for 'hash_ret' in "
"%s().\n", __FUNCTION__);
return NULL;
}
EVP_DigestInit(&ctx, EVP_sha1());
EVP_DigestUpdate(&ctx, tohash, size);
EVP_DigestFinal(&ctx, hash_ret, (int *)&evp_ret_len);
if (evp_ret_len != 20)
{
debug_printf(DEBUG_NORMAL, "Invalid result from OpenSSL SHA calls! "
"(%s:%d)\n", __FUNCTION__, __LINE__);
return NULL;
}
return hash_ret;
}
/**
* \brief Enumerate root CA certificates that are in the store that
* can be used for server authentication.
*
* @param[in] numcas An integer the specifies the number of CA certificates we are expected to
* return. This value should come from the cert_handler_num_root_ca_certs().
* On return, this will contain the number of certificates that are actually in
* the array.
*
* @param[in,out] cas An array of certificates that contains the number of certificates defined
* by numcas.
*
* \retval -1 on error
* \retval 0 on success
**/
int cert_handler_enum_root_ca_certs(int *numcas, cert_enum **cas)
{
PCCERT_CONTEXT pCertContext = NULL;
int certidx = 0;
int i = 0;
char pszNameString[256];
char pszSubjectString[1024];
DWORD size = 0;
CERT_ENHKEY_USAGE *enhkey = NULL;
cert_enum *casa = NULL;
SYSTEMTIME systime;
uint8_t *sha1hash = NULL;
char *temp = NULL;
if (hCertStore != NULL)
{
cert_handler_deinit();
cert_handler_init();
}
casa = Malloc((sizeof(cert_enum) * ((*numcas)+1)));
if (casa == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store certificate enumeration.\n");
return -1;
}
// Enumerate all of the certificates, and count only the ones that have the
// server authentication EKU set.
while ((hCertStore != NULL) && (pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext)) &&
(pCertContext != NULL))
{
// We only check this certificate if we can get it's name. If not, it is ignored.
if (!CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, sizeof(pszNameString)))
{
debug_printf(DEBUG_NORMAL, "Unable to determine certificate name.\n");
}
else
{
// Everything in this enum is out of the windows cert store.
casa[certidx].storetype = _strdup("WINDOWS");
sha1hash = do_sha1(pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
temp = convert_hex_to_str(sha1hash, 20);
casa[certidx].location = temp;
FREE(sha1hash);
#ifdef CHECK_EKU
if (CertGetEnhancedKeyUsage(pCertContext, 0, NULL, &size))
{
enhkey = malloc(size);
if (enhkey == NULL)
{
debug_printf(DEBUG_NORMAL, "Unable to allocate memory to get EKU data!\n");
return -1;
}
if (CertGetEnhancedKeyUsage(pCertContext, 0, enhkey, &size))
{
for (i = 0; i < enhkey->cUsageIdentifier; i++)
{
if (strcmp(enhkey->rgpszUsageIdentifier[i], szOID_PKIX_KP_SERVER_AUTH) == 0)
{
#endif
casa[certidx].certname = _strdup(pszNameString);
// Get the subject name for this certificate.
if (CertGetNameString(pCertContext, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL, pszSubjectString, sizeof(pszSubjectString)) > 0)
{
casa[certidx].friendlyname = _strdup(pszSubjectString);
}
memset(&pszSubjectString, 0x00, sizeof(pszSubjectString));
if (CertGetNameString(pCertContext, CERT_NAME_DNS_TYPE, 0, NULL, pszSubjectString, sizeof(pszSubjectString)) > 0)
{
casa[certidx].commonname = _strdup(pszSubjectString);
}
// Get the issuer name for this certificate.
if (CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, pszSubjectString, sizeof(pszSubjectString)) > 0)
{
casa[certidx].issuer = _strdup(pszSubjectString);
}
memset(&systime, 0x00, sizeof(systime));
if (FileTimeToSystemTime(&pCertContext->pCertInfo->NotAfter, &systime) != 0)
{
casa[certidx].day = systime.wDay;
casa[certidx].month = systime.wMonth;
casa[certidx].year = systime.wYear;
}
certidx++;
#ifdef CHECK_EKU
}
}
}
FREE(enhkey);
}
else
{
debug_printf(DEBUG_NORMAL, "Unable to determine EKU data size!\n");
return -1;
}
#endif
}
}
debug_printf(DEBUG_CERTS, "There were %d cert(s) that can be used for server authentication.\n", certidx);
(*cas) = casa;
return certidx;
}
/**
* \brief Add a certificate to our certificate store.
*
* @param[in] path_to_cert The full path name to the certificate we want to add to our store.
*
* \retval 0 on success
**/
int cert_handler_add_cert_to_store(char *path_to_cert)
{
HANDLE hFile;
PCCERT_CONTEXT pCertContext;
BYTE pbBuffer[8096];
DWORD cbBuffer;
DWORD dwErr;
LPVOID lastErrStr;
int retval = 0;
if ((hFile = CreateFile( path_to_cert,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL ) ) != INVALID_HANDLE_VALUE )
{
cbBuffer = 0;
memset( pbBuffer, 0, sizeof( pbBuffer ) );
if (ReadFile( hFile,
pbBuffer,
sizeof( pbBuffer ),
&cbBuffer,
NULL ) )
{
if ((pCertContext = CertCreateCertificateContext( X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
pbBuffer,
cbBuffer) ) )
{
if (hCertStore)
{
if (!CertAddCertificateContextToStore( hCertStore,
pCertContext,
CERT_STORE_ADD_NEW,
NULL ) )
{
dwErr = GetLastError();
if (dwErr == CRYPT_E_EXISTS )
{
//
// Certificate already exists
//
}
else
{
lastErrStr = GetLastErrorStr(dwErr);
debug_printf(DEBUG_NORMAL, "Unable to add certificate to store. Windows error was '%d'.\n", lastErrStr);
LocalFree(lastErrStr);
retval = IPC_EVENT_ERROR_CANT_ADD_CERT_TO_STORE;
}
}
}
else
{
debug_printf(DEBUG_NORMAL, "Certificate store isn't open!\n");
retval = IPC_EVENT_ERROR_FAILED_ROOT_CA_LOAD;
}
CertFreeCertificateContext( pCertContext );
pCertContext = NULL;
}
else
{
debug_printf(DEBUG_NORMAL, "Unable to read certificate file!\n");
retval = IPC_EVENT_ERROR_CANT_READ_FILE;
}
}
else
{
debug_printf(DEBUG_NORMAL, "Unable to open certificate file!\n");
retval = IPC_EVENT_ERROR_CANT_READ_FILE;
}
CloseHandle( hFile );
}
else
{
retval = IPC_EVENT_ERROR_CANT_READ_FILE;
}
return retval;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?