win_cert_handler.c
来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 580 行 · 第 1/2 页
C
580 行
/**
* Windows certificate handler
*
* Licensed under a dual GPL/BSD license. (See LICENSE file for more info.)
*
* \file win_cert_handler.c
*
* \author chris@open1x.org
*
* $Id: win_cert_handler.c,v 1.1.2.18 2008/01/21 22:51:48 chessing Exp $
* $Date: 2008/01/21 22:51:48 $
**/
#include <windows.h>
#include <wincrypt.h>
#include <openssl/hmac.h>
#ifdef WINDOWS
#include "../../stdintwin.h"
#endif
#include "../../xsup_err.h"
#include "../../../lib/libxsupconfig/xsupconfig.h"
#include "../../../lib/libxsupconfig/xsupconfig_structs.h"
#include "../../context.h"
#include "../../xsup_debug.h"
#include "../cert_handler.h"
#include "../../ipc_events_index.h"
// #define CHECK_EKU 1 // Only show root certs with the server EKUs. (Same as Windows XP defaults.)
HCERTSTORE hCertStore = NULL;
/**
* \brief Initialize the Windows certificate store.
*
* \retval XENONE on success
* \retval XEGENERROR on failure
**/
int cert_handler_init()
{
debug_printf(DEBUG_CERTS, "Starting Certificate Services...\n");
if (hCertStore = CertOpenStore( CERT_STORE_PROV_SYSTEM, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"ROOT"))
{
return XEGENERROR;
}
return XENONE;
}
/**
* \brief Close the certificate store handle.
**/
void cert_handler_deinit()
{
debug_printf(DEBUG_CERTS, "Killing certificate services...\n");
if (hCertStore != NULL) CertCloseStore(hCertStore, 0);
hCertStore = NULL;
}
/**
* \brief Look for a container value (such as "OU=") and return the value that it is
* set to.
*
* @param[in] pszSubjectString The string that we want to search for the data.
* @param[in] container The container value that we are looking for. (Such as "OU=")
*
* \retval NULL on error
* \retval ptr to a string that contains the value.
**/
static char *cert_handler_get_container_value(char *pszSubjectString, char *container)
{
char *temp = NULL;
char *end = NULL;
char *result = NULL;
temp = Malloc(strlen(pszSubjectString)+1);
if (temp == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store temporary work buffer!\n");
return NULL;
}
end = strstr(pszSubjectString, container);
if (end == NULL) return NULL; // Couldn't find what we were looking for.
strcpy(temp, end);
if (temp[strlen(container)] == '"')
{
// It is a quoted value.
end = strstr(&temp[strlen(container)], "\"");
end[0] = 0x00; // Set it to a NULL.
}
else
{
end = strstr(&temp[strlen(container)], ",");
if (end != NULL) // If we are already at the end, we will return NULL. So ignore it.
end[0] = 0x00; // Set it to a NULL.
}
result = Malloc(strlen(temp));
if (result == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store final result! (in %s())\n",
__FUNCTION__);
return NULL;
}
strcpy(result, &temp[strlen(container)]);
FREE(temp);
return result;
}
/**
* \brief Parse the ASN.1 Encoded Subject information, and pull out things like the CN,
* OU, O, etc.
*
* @param[in] pCertContext A pointer to the certificate context for the certificate we want
* to gather the data for.
* @param[in,out] certinfo A pointer to the structure that we will populate with the
* certificate information.
*
* \note Not all of the values listed in the structure will be present in all of the
* certificates that we are looking at. The caller should be prepared to deal
* with some (or perhaps all) of the fields being NULL.
*
* \retval 0 on success
* \retval -1 on failure
**/
int cert_handler_get_info(PCCERT_CONTEXT pCertContext, cert_info *certinfo)
{
char pszSubjectString[1024];
char *temp;
if (CertNameToStr(X509_ASN_ENCODING, &pCertContext->pCertInfo->Subject, CERT_X500_NAME_STR, pszSubjectString, 1024) > 0)
{
certinfo->C = cert_handler_get_container_value(pszSubjectString, "C=");
certinfo->S = cert_handler_get_container_value(pszSubjectString, "S=");
certinfo->L = cert_handler_get_container_value(pszSubjectString, "L=");
certinfo->O = cert_handler_get_container_value(pszSubjectString, "O=");
certinfo->OU = cert_handler_get_container_value(pszSubjectString, "OU=");
certinfo->CN = cert_handler_get_container_value(pszSubjectString, "CN=");
return 0;
}
return -1;
}
PCCERT_CONTEXT win_cert_handler_get_from_win_store(char *storetype, char *location)
{
PCCERT_CONTEXT pCertContext = NULL;
CRYPT_HASH_BLOB toFindData;
uint8_t *hashData;
if (storetype == NULL) return NULL;
if (location == NULL) return NULL;
str2hex(location, &hashData, &toFindData.cbData);
toFindData.pbData = hashData;
pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_HASH, &toFindData, NULL);
FREE(hashData); // Clean up the memory no matter what.
if (pCertContext == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't locate the certificate!\n");
return NULL;
}
return pCertContext;
}
/**
* \brief Given the certificate name, get the information about it.
*
* @param[in] certname The certificate's "friendly" name that we want to use.
* @param[in,out] certinfo A pointer to the structure that will contain all
* of the certificate information requested.
*
* \retval 0 on success
* \retval -1 on error
**/
int cert_handler_get_info_from_store(char *storetype, char *location, cert_info *certinfo)
{
PCCERT_CONTEXT pCertContext = NULL;
pCertContext = win_cert_handler_get_from_win_store(storetype, location);
if (pCertContext == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't locate the certificate!\n");
return -1;
}
return cert_handler_get_info(pCertContext, certinfo);
}
/**
* \brief Free all of the fields that are included in a cert_info structure.
*
* @param[in] cinfo A pointer to the structure that we want to free the members of.
**/
void cert_handler_free_cert_info(cert_info *cinfo)
{
FREE(cinfo->C);
FREE(cinfo->CN);
FREE(cinfo->O);
FREE(cinfo->L);
FREE(cinfo->OU);
FREE(cinfo->S);
}
/**
* \brief Determine the number of root CA certificates are in the store that
* can be used for server authentication.
*
* \retval -1 on error
* \retval >=0 is the number of certificates that will be in the list.
**/
int cert_handler_num_root_ca_certs()
{
PCCERT_CONTEXT pCertContext = NULL;
int numcerts = 0;
int i = 0;
char pszNameString[256];
DWORD size = 0;
CERT_ENHKEY_USAGE *enhkey = NULL;
if (hCertStore != NULL)
{
cert_handler_deinit();
cert_handler_init();
}
// Enumerate all of the certificates, and count only the ones that have the
// server authentication EKU set.
while ((pCertContext = CertEnumCertificatesInStore(hCertStore, pCertContext)))
{
// 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, 128))
{
debug_printf(DEBUG_NORMAL, "Unable to determine certificate name.\n");
}
else
{
#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
numcerts++;
#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", numcerts);
return numcerts;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?