windows-nt/Source/XPSP1/NT/enduser/netmeeting/ui/conf/certui.cpp
2020-09-26 16:20:57 +08:00

1115 lines
30 KiB
C++

// File: certui.cpp
#include "precomp.h"
#include "resource.h"
#include "nmmkcert.h"
#include "certui.h"
#include <tsecctrl.h>
#include "SDKInternal.h"
#include "ConfUtil.h"
#define SZ_CRYPTDLGDLL "CRYPTDLG"
extern INmSysInfo2 * g_pNmSysInfo;
//
// While the credentials underlying the certificate we are using
// are in use, we need to keep the certificate context around
// and the store open. So we hold the currently open cert store
// and cert context in these globals:
static PCCERT_CONTEXT g_pCertContext;
static HCERTSTORE g_hCertStore;
TCHAR * FormatCert ( PBYTE pbEncodedCert, DWORD cbEncodedCert )
{
DWORD sc;
PCCERT_CONTEXT pCert = NULL, pIssuerCert = NULL, pCACert = NULL;
DWORD cbRet = 0;
CHAR * pSubject = NULL;
CHAR * pIssuer = NULL;
DWORD cbSubject = 0;
DWORD cbIssuer = 0;
DWORD dwFlags;
DWORD cbTotalRequired;
CHAR szLoadStringBuf[512];
HCERTSTORE hRootStore = NULL;
HCERTSTORE hCAStore = NULL;
BOOL fSelfIssued = FALSE;
TCHAR * pInfo = NULL;
TCHAR szNotBefore[64];
TCHAR szNotAfter[64];
ASSERT(pbEncodedCert);
ASSERT(cbEncodedCert);
//
// Get the certificate from the encoded blob
//
pCert = CertCreateCertificateContext ( X509_ASN_ENCODING,
pbEncodedCert,
cbEncodedCert );
if ( NULL == pCert )
{
// Creating the cert context failed
ERROR_OUT(("Error creating cert context from %x (%d bytes): %x",
pbEncodedCert, cbEncodedCert, GetLastError()));
goto cleanup;
}
//
// Get the subject information
//
cbSubject = CertNameToStr (
pCert->dwCertEncodingType,
&pCert->pCertInfo->Subject,
CERT_FORMAT_FLAGS,
NULL, 0);
if ( 0 == cbSubject )
{
ERROR_OUT(("GetUserInfo: no subject string"));
goto cleanup;
}
pSubject = new CHAR[cbSubject + 1];
if ( NULL == pSubject )
{
ERROR_OUT(("GetUserInfo: error allocating subject name"));
goto cleanup;
}
if ( 0 >= CertNameToStr (
pCert->dwCertEncodingType,
&pCert->pCertInfo->Subject,
CERT_FORMAT_FLAGS,
pSubject, cbSubject+1))
{
ERROR_OUT(("GetUserInfo: error getting subject string"));
goto cleanup;
}
//
// Get the issuer information
//
cbIssuer = CertNameToStr (
pCert->dwCertEncodingType,
&pCert->pCertInfo->Issuer,
CERT_FORMAT_FLAGS,
NULL, 0);
if ( 0 == cbIssuer )
{
ERROR_OUT(("GetUserInfo: no issuer string"));
goto cleanup;
}
pIssuer = new CHAR[cbIssuer + 1];
if ( NULL == pIssuer )
{
ERROR_OUT(("GetUserInfo: error allocating issuer name"));
}
if ( 0 >= CertNameToStr (
pCert->dwCertEncodingType,
&pCert->pCertInfo->Issuer,
CERT_FORMAT_FLAGS,
pIssuer, cbIssuer+1))
{
ERROR_OUT(("GetUserInfo: error getting issuer string"));
goto cleanup;
}
//
// Format the file time from the cert
//
SYSTEMTIME stNotBefore;
SYSTEMTIME stNotAfter;
FileTimeToSystemTime(&(pCert->pCertInfo->NotBefore), &stNotBefore);
FileTimeToSystemTime(&(pCert->pCertInfo->NotAfter), &stNotAfter);
FmtDateTime(&stNotBefore, szNotBefore, CCHMAX(szNotBefore));
FmtDateTime(&stNotAfter, szNotAfter, CCHMAX(szNotAfter));
//
// Open the root store for certificate verification
//
hRootStore = CertOpenSystemStore(0, "Root");
if( NULL == hRootStore )
{
ERROR_OUT(("Couldn't open root certificate store"));
goto cleanup;
}
//
// Get the issuer certificate from the root store and check for problems
//
dwFlags = CERT_STORE_REVOCATION_FLAG |
CERT_STORE_SIGNATURE_FLAG |
CERT_STORE_TIME_VALIDITY_FLAG;
// Get the issuer of this cert
pIssuerCert = CertGetIssuerCertificateFromStore(
hRootStore,
pCert,
NULL,
&dwFlags );
// If the issuer of the certificate cannot be found in the root store,
// check the CA store iteratively until we work our way back to a root
// certificate
pCACert = pCert;
while ( NULL == pIssuerCert )
{
PCCERT_CONTEXT pTmpCert;
if ( NULL == hCAStore )
{
hCAStore = CertOpenSystemStore(0, "CA");
if ( NULL == hCAStore )
{
ERROR_OUT(("Couldn't open CA certificate store"));
goto cleanup;
}
}
dwFlags = CERT_STORE_REVOCATION_FLAG |
CERT_STORE_SIGNATURE_FLAG |
CERT_STORE_TIME_VALIDITY_FLAG;
pTmpCert = CertGetIssuerCertificateFromStore(
hCAStore,
pCACert,
NULL,
&dwFlags );
if ( NULL == pTmpCert )
{
TRACE_OUT(("Issuer not found in CA store either"));
break;
}
if ( pCACert != pCert )
CertFreeCertificateContext(pCACert);
pCACert = pTmpCert;
if ((( CERT_STORE_REVOCATION_FLAG & dwFlags ) &&
!( CERT_STORE_NO_CRL_FLAG & dwFlags )) ||
( CERT_STORE_SIGNATURE_FLAG & dwFlags ) ||
( CERT_STORE_TIME_VALIDITY_FLAG & dwFlags ))
{
TRACE_OUT(("Problem with issuer in CA store: %x", dwFlags));
break;
}
dwFlags = CERT_STORE_REVOCATION_FLAG |
CERT_STORE_SIGNATURE_FLAG |
CERT_STORE_TIME_VALIDITY_FLAG;
pIssuerCert = CertGetIssuerCertificateFromStore(
hRootStore,
pCACert,
NULL,
&dwFlags );
}
if ( pCACert != pCert )
CertFreeCertificateContext ( pCACert );
//
// Total up the return buffer required
//
// BUGBUG this overestimates the requirements slightly because
// this formatting buffer contains specifiers which will be
// replaced during wsprintf
cbTotalRequired = cbSubject +
cbIssuer +
lstrlen(szNotBefore) +
lstrlen(szNotAfter) +
FLoadString2( IDS_FMTBUFFER, szLoadStringBuf,
sizeof(szLoadStringBuf)) + 1;
//
// If there are problems, account for the extra info:
//
if ( NULL == pIssuerCert )
{
// If after all we couldn't find the issuer check if this is
// a NetMeeting self-issued certificate and generate an appropriate
// message if so:
DWORD dwMagic;
DWORD cbMagic;
cbMagic = sizeof(dwMagic);
// BUGBUG: why is user prop not available for remote context?
//if (pSecurityInterface->pfn_CertGetCertificateContextProperty(pCert,
// CERT_FIRST_USER_PROP_ID, &dwMagic, &cbMagic) &&
// cbMagic == sizeof(dwMagic) && dwMagic == NMMKCERT_MAGIC )
if ( !lstrcmp( pIssuer, SZ_NMROOTNAME ))
{
// We're just going to return some generic text about the
// NetMeeting default certificate
cbTotalRequired = FLoadString2( IDS_GENERIC_NMDC_TEXT,
szLoadStringBuf, sizeof(szLoadStringBuf)) + 1;
fSelfIssued = TRUE;
}
else
{
cbTotalRequired += FLoadString2( IDS_CERTERR_NOISSUER,
szLoadStringBuf, sizeof(szLoadStringBuf)) + 1;
}
}
else
{
if ( dwFlags & CERT_STORE_SIGNATURE_FLAG )
{
WARNING_OUT(("Verify: Signature invalid"));
cbTotalRequired += FLoadString2( IDS_CERTERR_SIG,
szLoadStringBuf, sizeof(szLoadStringBuf)) + 1;
}
if ( dwFlags & CERT_STORE_TIME_VALIDITY_FLAG )
{
WARNING_OUT(("Verify: Cert expired"));
cbTotalRequired += FLoadString2( IDS_CERTERR_EXPIRED,
szLoadStringBuf, sizeof(szLoadStringBuf)) + 1;
}
if ( (dwFlags & CERT_STORE_REVOCATION_FLAG) &&
!(dwFlags & CERT_STORE_NO_CRL_FLAG ) )
{
WARNING_OUT(("Verify: Cert revoked"));
cbTotalRequired += FLoadString2( IDS_CERTERR_REVOKED,
szLoadStringBuf, sizeof(szLoadStringBuf)) + 1;
}
if ( 0 == (dwFlags & ~CERT_STORE_NO_CRL_FLAG) )
{
// Everything is OK:
cbTotalRequired += FLoadString2( IDS_CERT_VERIFIED,
szLoadStringBuf, sizeof(szLoadStringBuf));
}
}
//
// Allocate the required buffer
//
pInfo = new TCHAR[cbTotalRequired];
if ( NULL == pInfo )
{
ERROR_OUT(("Error allocating FormatCert return buffer"));
goto cleanup;
}
//
// If we're reporting on a NetMeeting issued certificate, just load
// the generic text and return.
//
if ( fSelfIssued )
{
FLoadString( IDS_GENERIC_NMDC_TEXT, pInfo, cbTotalRequired );
goto cleanup;
}
//
// If we are here we can go ahead and format the data into the buffer
//
FLoadString( IDS_FMTBUFFER, szLoadStringBuf,
sizeof(szLoadStringBuf));
//
// Do the formatting
//
wsprintf( pInfo, szLoadStringBuf, pSubject, pIssuer,
szNotBefore, szNotAfter );
if ( NULL == pIssuerCert )
{
FLoadString( IDS_CERTERR_NOISSUER,
szLoadStringBuf, sizeof(szLoadStringBuf));
lstrcat( pInfo, szLoadStringBuf );
}
else
{
if ( dwFlags & CERT_STORE_SIGNATURE_FLAG )
{
FLoadString( IDS_CERTERR_SIG,
szLoadStringBuf, sizeof(szLoadStringBuf));
lstrcat( pInfo, szLoadStringBuf );
}
if ( dwFlags & CERT_STORE_TIME_VALIDITY_FLAG )
{
FLoadString( IDS_CERTERR_EXPIRED,
szLoadStringBuf, sizeof(szLoadStringBuf));
lstrcat( pInfo, szLoadStringBuf );
}
if ( (dwFlags & CERT_STORE_REVOCATION_FLAG) &&
!(dwFlags & CERT_STORE_NO_CRL_FLAG ) )
{
FLoadString( IDS_CERTERR_REVOKED,
szLoadStringBuf, sizeof(szLoadStringBuf));
lstrcat( pInfo, szLoadStringBuf );
}
if ( 0 == (dwFlags & ~CERT_STORE_NO_CRL_FLAG) )
{
// Everything is OK:
FLoadString( IDS_CERT_VERIFIED,
szLoadStringBuf, sizeof(szLoadStringBuf));
lstrcat( pInfo, szLoadStringBuf );
}
}
ASSERT( cbRet < 1000 ); // Reasonableness check
cleanup:
if ( NULL != pSubject )
delete pSubject;
if ( NULL != pIssuer )
delete pIssuer;
if ( NULL != pCert )
{
CertFreeCertificateContext ( pCert );
}
if ( NULL != pIssuerCert )
{
CertFreeCertificateContext ( pIssuerCert );
}
if ( NULL != hRootStore )
{
if ( !CertCloseStore(hRootStore, CERT_CLOSE_STORE_CHECK_FLAG))
{
WARNING_OUT(("FormatCert: error closing root store"));
}
}
if ( NULL != hCAStore )
{
if ( !CertCloseStore(hCAStore, CERT_CLOSE_STORE_CHECK_FLAG))
{
WARNING_OUT(("FormatCert: error closing CA store"));
}
}
return pInfo;
}
BOOL RefreshSelfIssuedCert (VOID)
{
BOOL bRet = FALSE;
DWORD dwResult;
RegEntry reCONF(CONFERENCING_KEY, HKEY_CURRENT_USER);
if (reCONF.GetNumber(REGVAL_SECURITY_AUTHENTICATION,
DEFAULT_SECURITY_AUTHENTICATION))
{
return TRUE;
}
//
// If there's no sys info interface, that's probably OK, we're just
// being called in the setup wizard.
//
if (!g_pNmSysInfo)
return FALSE;
//
// Clear old cert out of transport
//
g_pNmSysInfo->ProcessSecurityData(
TPRTCTRL_SETX509CREDENTIALS,
0, 0,
&dwResult);
if ( g_pCertContext )
{
CertFreeCertificateContext ( g_pCertContext );
g_pCertContext = NULL;
}
if ( g_hCertStore )
{
if ( !CertCloseStore ( g_hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ))
{
WARNING_OUT(("SetSelfIssuedCert: closing store failed"));
}
g_hCertStore = NULL;
}
g_hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
X509_ASN_ENCODING,
0,
CERT_SYSTEM_STORE_CURRENT_USER,
WSZNMSTORE );
if ( g_hCertStore )
{
//
// We only expect one cert in here, get it
//
g_pCertContext = CertFindCertificateInStore(
g_hCertStore,
X509_ASN_ENCODING,
0,
CERT_FIND_ANY,
NULL,
NULL);
if ( g_pCertContext )
{
dwResult = -1;
g_pNmSysInfo->ProcessSecurityData(
TPRTCTRL_SETX509CREDENTIALS,
(DWORD_PTR)g_pCertContext, 0,
&dwResult);
//
// g_hCertStore and g_pCertContext now in use
//
if ( !dwResult )
{
bRet = TRUE;
}
else
{
ERROR_OUT(("RefreshSelfIssuedCert - failed in T.120"));
}
}
else
{
ERROR_OUT(("RefreshPrivacyCert: no cert in %s?", SZNMSTORE));
}
}
else
{
WARNING_OUT(("RefreshSelfIssuedCert: error opening %s store %x",
SZNMSTORE, GetLastError()));
}
return bRet;
}
DWORD NumUserCerts(VOID)
{
DWORD cCerts = 0;
HCERTSTORE hStore;
PCCERT_CONTEXT pCert = NULL;
if ( hStore = CertOpenSystemStore(0, "MY"))
{
while ( pCert = CertEnumCertificatesInStore(
hStore, (PCERT_CONTEXT)pCert ))
cCerts++;
if ( !CertCloseStore( hStore, CERT_CLOSE_STORE_CHECK_FLAG ))
{
WARNING_OUT(("NumUserCerts: error closing store"));
}
}
return cCerts;
}
#include "cryptdlg.h"
typedef BOOL (WINAPI *PFN_CERT_SELECT_CERTIFICATE)(PCERT_SELECT_STRUCT_A);
BOOL ChangeCertDlg ( HWND hwndParent, HINSTANCE hInstance,
PBYTE * ppEncodedCert, DWORD * pcbEncodedCert )
{
HINSTANCE hCryptDlg = LoadLibrary ( SZ_CRYPTDLGDLL );
PFN_CERT_SELECT_CERTIFICATE pfn_CertSelectCertificate;
RegEntry reCONF(CONFERENCING_KEY, HKEY_CURRENT_USER);
PCCERT_CONTEXT pOldCert = NULL;
BOOL bRet = FALSE;
//
// First, make sure we can get the CRYPTDLG entry point we need
//
if ( NULL == hCryptDlg )
{
ERROR_OUT(("Error loading CRYPTDLG"));
return bRet;
}
pfn_CertSelectCertificate =
(PFN_CERT_SELECT_CERTIFICATE)GetProcAddress ( hCryptDlg,
"CertSelectCertificateA" );
if ( NULL == pfn_CertSelectCertificate )
{
ERROR_OUT(("Error getting CertSelectCertificate entry point"));
goto cleanup;
}
//
// Prepare to bring up the choose dialog
//
CERT_SELECT_STRUCT_A css;
ZeroMemory ( &css, sizeof(css) );
css.dwSize = sizeof(css);
css.hwndParent = hwndParent;
css.hInstance = hInstance;
css.cCertStore = 1;
HCERTSTORE aCertStore[1];
aCertStore[0] = CertOpenSystemStore(0, "MY" );
if ( NULL == aCertStore[0] )
{
ERROR_OUT(("Error opening 'my' store"));
goto cleanup;
}
css.arrayCertStore = aCertStore;
css.szPurposeOid = szOID_PKIX_KP_CLIENT_AUTH; // BUGBUG add server auth?
PCCERT_CONTEXT pcc;
pcc = NULL;
//
// Now, get access to the current NetMeeting certificate, if any
//
LPBYTE pCertID;
DWORD cbCertID;
if ( cbCertID = reCONF.GetBinary ( REGVAL_CERT_ID, (void**)&pCertID ))
{
while ( pOldCert = CertEnumCertificatesInStore(
aCertStore[0], (PCERT_CONTEXT)pOldCert ))
{
if (cbCertID == pOldCert->pCertInfo->SerialNumber.cbData &&
!memcmp(pCertID, pOldCert->pCertInfo->SerialNumber.pbData,
pOldCert->pCertInfo->SerialNumber.cbData))
{
// pOldCert must now be freed via CertFreeCertificateContext
pcc = pOldCert;
break;
}
}
}
css.cCertContext = 0;
css.arrayCertContext = &pcc;
if (pfn_CertSelectCertificate ( &css ))
{
ASSERT(1 == css.cCertContext);
//
// It worked, return the new cert
//
CoTaskMemFree ( *ppEncodedCert );
if ( *ppEncodedCert = (PBYTE)CoTaskMemAlloc ( pcc->cbCertEncoded ))
{
memcpy ( *ppEncodedCert, pcc->pbCertEncoded, pcc->cbCertEncoded );
*pcbEncodedCert = pcc->cbCertEncoded;
bRet = TRUE;
}
}
cleanup:
if ( aCertStore[0] )
if (!CertCloseStore ( aCertStore[0], 0 ))
{
WARNING_OUT(("ChangeCertDlg: error closing store"));
}
if ( pOldCert )
{
CertFreeCertificateContext(pOldCert);
}
if ( hCryptDlg )
FreeLibrary ( hCryptDlg );
return bRet;
}
typedef BOOL (WINAPI *PFN_CERT_VIEW_PROPERTIES)(PCERT_VIEWPROPERTIES_STRUCT);
VOID ViewCertDlg ( HWND hwndParent, PCCERT_CONTEXT pCert )
{
HINSTANCE hCryptDlg = LoadLibrary ( SZ_CRYPTDLGDLL );
PFN_CERT_VIEW_PROPERTIES pfn_CertViewProperties;
//
// First, make sure we can get the CRYPTDLG entry point we need
//
if ( NULL == hCryptDlg )
{
ERROR_OUT(("Error loading CRYPTDLG"));
return;
}
pfn_CertViewProperties =
(PFN_CERT_VIEW_PROPERTIES)GetProcAddress ( hCryptDlg,
"CertViewPropertiesA" );
if ( NULL == pfn_CertViewProperties )
{
ERROR_OUT(("Error getting CertViewProperties entry point"));
goto cleanup;
}
CERT_VIEWPROPERTIES_STRUCT cvp;
ZeroMemory(&cvp, sizeof(cvp));
cvp.dwSize = sizeof(cvp);
cvp.pCertContext = pCert;
cvp.hwndParent = hwndParent;
pfn_CertViewProperties ( &cvp );
cleanup:
if ( hCryptDlg )
FreeLibrary ( hCryptDlg );
return;
}
VOID FreeT120EncodedCert ( PBYTE pbEncodedCert )
{
CoTaskMemFree(pbEncodedCert);
}
BOOL GetT120ActiveCert ( PBYTE * ppbEncodedCert, DWORD * pcbEncodedCert )
{
if ( !g_pNmSysInfo )
{
ERROR_OUT(("GetT120ActiveCert: g_pNmSysInfo NULL"));
return FALSE;
}
DWORD dwResult = -1;
g_pNmSysInfo->ProcessSecurityData(TPRTCTRL_GETX509CREDENTIALS,
(DWORD_PTR)ppbEncodedCert,
(DWORD_PTR)pcbEncodedCert,
&dwResult);
return ( dwResult == 0 );
}
BOOL SetT120CertInRegistry ( PBYTE pbEncodedCert, DWORD cbEncodedCert )
{
PCCERT_CONTEXT pCert = CertCreateCertificateContext ( X509_ASN_ENCODING,
pbEncodedCert,
cbEncodedCert );
if ( pCert )
{
RegEntry reCONF(CONFERENCING_KEY, HKEY_CURRENT_USER);
//
// Set the new value
//
reCONF.SetValue ( REGVAL_CERT_ID,
pCert->pCertInfo->SerialNumber.pbData,
pCert->pCertInfo->SerialNumber.cbData );
CertFreeCertificateContext(pCert);
return TRUE;
}
return FALSE;
}
BOOL SetT120ActiveCert ( BOOL fSelfIssued,
PBYTE pbEncodedCert, DWORD cbEncodedCert )
{
BOOL bRet = FALSE;
DWORD dwResult = -1;
if ( !g_pNmSysInfo )
{
ERROR_OUT(("SetT120ActiveCert: g_pNmSysInfo NULL"));
return FALSE;
}
//
// Clear old cert out of transport
//
g_pNmSysInfo->ProcessSecurityData(
TPRTCTRL_SETX509CREDENTIALS,
0, 0,
&dwResult);
if (!g_pNmSysInfo)
return FALSE;
if ( g_pCertContext )
{
CertFreeCertificateContext ( g_pCertContext );
g_pCertContext = NULL;
}
if ( g_hCertStore )
{
if ( !CertCloseStore ( g_hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ))
{
WARNING_OUT(("SetT120ActiveCert: closing store failed"));
}
g_hCertStore = NULL;
}
if ( fSelfIssued )
{
g_hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM,
X509_ASN_ENCODING,
0,
CERT_SYSTEM_STORE_CURRENT_USER,
WSZNMSTORE );
if ( g_hCertStore )
{
//
// We only expect one cert in here, get it
//
g_pCertContext = CertFindCertificateInStore(
g_hCertStore,
X509_ASN_ENCODING,
0,
CERT_FIND_ANY,
NULL,
NULL);
if ( g_pCertContext )
{
dwResult = -1;
g_pNmSysInfo->ProcessSecurityData(
TPRTCTRL_SETX509CREDENTIALS,
(DWORD_PTR)g_pCertContext, 0,
&dwResult);
bRet = ( dwResult == 0 ); // BUGBUG TPRTSEC_NOERROR
}
else
{
WARNING_OUT(("SetT120ActiveCert: no cert in %s?", SZNMSTORE));
}
}
else
{
WARNING_OUT(("SetT120ActiveCert: error opening %s store %x",
SZNMSTORE, GetLastError()));
}
}
else // !fSelfIssued
{
PCCERT_CONTEXT pCert = NULL;
PCCERT_CONTEXT pCertMatch = CertCreateCertificateContext (
X509_ASN_ENCODING,
pbEncodedCert,
cbEncodedCert );
if ( pCertMatch )
{
//
// Open the user's store
//
if ( g_hCertStore = CertOpenSystemStore(0, "MY"))
{
while ( pCert = CertEnumCertificatesInStore(
g_hCertStore, (PCERT_CONTEXT)pCert ))
{
//
// Is this the same cert?
//
if ( ( pCert->pCertInfo->SerialNumber.cbData ==
pCertMatch->pCertInfo->SerialNumber.cbData ) &&
(!memcmp(pCert->pCertInfo->SerialNumber.pbData,
pCertMatch->pCertInfo->SerialNumber.pbData,
pCert->pCertInfo->SerialNumber.cbData)))
{
DWORD dwResult = -1;
g_pNmSysInfo->ProcessSecurityData(
TPRTCTRL_SETX509CREDENTIALS,
(DWORD_PTR)pCert, 0, &dwResult);
bRet = ( dwResult == 0 ); // BUGBUG TPRTSEC_NOERROR
break;
}
}
if ( pCert )
{
// Found it.
g_pCertContext = pCert;
}
else
{
WARNING_OUT(("SetT120ActiveCert: matching cert not found"));
}
}
else
{
ERROR_OUT(("SetT120ActiveCert: can't open my store"));
}
CertFreeCertificateContext ( pCertMatch );
}
}
return bRet;
}
static PCCERT_CONTEXT IGetDefaultCert ( BOOL fSystemOnly,
HCERTSTORE * phCertStore )
{
RegEntry reCONF(CONFERENCING_KEY, HKEY_CURRENT_USER);
HCERTSTORE hStore = NULL;
PCCERT_CONTEXT pCertContext = NULL;
BOOL fNmDefaultCert = TRUE;
LPBYTE pCertID;
if ( fSystemOnly )
fNmDefaultCert = FALSE;
else
fNmDefaultCert = !reCONF.GetNumber(REGVAL_SECURITY_AUTHENTICATION,
DEFAULT_SECURITY_AUTHENTICATION);
hStore = CertOpenSystemStore(0, fNmDefaultCert ?
SZNMSTORE : "MY");
if ( NULL != hStore )
{
PCCERT_CONTEXT pCert = NULL;
DWORD cbCertID;
if (!fNmDefaultCert && ( cbCertID = reCONF.GetBinary (
REGVAL_CERT_ID, (void**)&pCertID )))
{
while ( pCert = CertEnumCertificatesInStore(
hStore, (PCERT_CONTEXT)pCert ))
{
if ( cbCertID == pCert->pCertInfo->SerialNumber.cbData &&
!memcmp(pCertID, pCert->pCertInfo->SerialNumber.pbData,
pCert->pCertInfo->SerialNumber.cbData))
{
// pCert must now be freed via CertFreeCertificateContext
pCertContext = pCert;
break;
}
}
}
if ( NULL == pCertContext )
{
// Delete the (stale) reg entry... the cert might have
// been deleted by other UI.
if ( !fNmDefaultCert )
reCONF.DeleteValue( REGVAL_CERT_ID );
// Find any old client certificate - if fNmDefaultCert this will be
// the only one in the store.
pCertContext = CertFindCertificateInStore(hStore,
X509_ASN_ENCODING,
0,
CERT_FIND_ANY,
NULL,
NULL);
}
}
else
{
WARNING_OUT(("User store %s not opened!", fNmDefaultCert ? SZNMSTORE : "MY"));
*phCertStore = NULL;
}
// Caller to free cert context
*phCertStore = hStore;
return pCertContext;
}
BOOL GetDefaultSystemCert ( PBYTE * ppEncodedCert, DWORD * pcbEncodedCert )
{
HCERTSTORE hStore;
PCCERT_CONTEXT pCertContext = IGetDefaultCert(TRUE, &hStore);
BOOL bRet = FALSE;
if ( pCertContext )
{
DWORD cb;
PBYTE pb;
if ( pb = (PBYTE)CoTaskMemAlloc ( pCertContext->cbCertEncoded ))
{
memcpy ( pb, pCertContext->pbCertEncoded,
pCertContext->cbCertEncoded );
*ppEncodedCert = pb;
*pcbEncodedCert = pCertContext->cbCertEncoded;
bRet = TRUE;
}
CertFreeCertificateContext(pCertContext);
}
if ( hStore )
{
if ( !CertCloseStore ( hStore, CERT_CLOSE_STORE_CHECK_FLAG ))
{
WARNING_OUT(("GetDefaultSystemCert: error closing store"));
}
}
return bRet;;
}
BOOL InitT120SecurityFromRegistry(VOID)
{
BOOL bRet = FALSE;
if ( !g_pNmSysInfo )
{
ERROR_OUT(("InitT120SecurityFromRegistry: g_pNmSysInfo NULL"));
return FALSE;
}
//
// Expect this to be called only once on startup
//
ASSERT( NULL == g_pCertContext );
ASSERT( NULL == g_hCertStore );
g_pCertContext = IGetDefaultCert(FALSE, &g_hCertStore);
if ( NULL == g_pCertContext )
{
WARNING_OUT(("No user certificate found!"));
// BUGBUG
// This means the transport will not be ready for secure
// calls... we return false but what does the caller do?
//
}
else
{
DWORD dwResult = -1;
g_pNmSysInfo->ProcessSecurityData(TPRTCTRL_SETX509CREDENTIALS,
(DWORD_PTR)g_pCertContext, 0, &dwResult);
if ( !dwResult )
bRet = TRUE;
else
{
ERROR_OUT(("InitT120SecurityFromRegistry: picked up bad cert"));
}
}
return bRet;
}
HRESULT SetCertFromCertInfo ( PCERT_INFO pCertInfo )
{
HRESULT hRet = S_FALSE;
ASSERT( pCertInfo );
if (!g_pNmSysInfo)
return hRet;
//
// Clear old cert out of transport
//
DWORD dwResult = -1;
g_pNmSysInfo->ProcessSecurityData(
TPRTCTRL_SETX509CREDENTIALS,
0, 0,
&dwResult);
if ( g_pCertContext )
{
CertFreeCertificateContext ( g_pCertContext );
g_pCertContext = NULL;
}
if ( g_hCertStore )
{
if ( !CertCloseStore ( g_hCertStore, CERT_CLOSE_STORE_CHECK_FLAG ))
{
WARNING_OUT(("SetCertFromCertInfo: closing store failed"));
}
g_hCertStore = NULL;
}
if ( g_hCertStore = CertOpenSystemStore(0, "MY"))
{
//
// Fix up relative pointers inside pCertInfo: Note that only
// the pointers relevant to CertGetSubjectCertificateFromStore
// are fixed up.
//
pCertInfo->SerialNumber.pbData += (DWORD_PTR)pCertInfo;
pCertInfo->Issuer.pbData += (DWORD_PTR)pCertInfo;
PCCERT_CONTEXT pCert = CertGetSubjectCertificateFromStore(
g_hCertStore, X509_ASN_ENCODING, pCertInfo );
if ( pCert )
{
g_pNmSysInfo->ProcessSecurityData(
TPRTCTRL_SETX509CREDENTIALS,
(DWORD_PTR)pCert, 0, &dwResult);
if ( 0 == dwResult ) // TPRTSEC_NO_ERROR
{
hRet = S_OK;
g_pCertContext = pCert;
}
}
else
{
WARNING_OUT(("SetCertFromCertInfo: matching cert not found"));
}
}
else
{
ERROR_OUT(("SetCertFromCertInfo: can't open my store"));
}
return hRet;
}