|
|
// 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 = NmLoadLibrary ( SZ_CRYPTDLGDLL ,TRUE); 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 = NmLoadLibrary ( SZ_CRYPTDLGDLL, TRUE ); 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))) { 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; }
|