2012年10月8日 星期一

Save certificates to file store


#ifndef SSLCERTSTOREMANAGER_H
#define SSLCERTSTOREMANAGER_H

#include "Noncopyable.h"

#include <WinCrypt.h>

namespace WebCore
{

class SSLCertStoreManager :public Noncopyable
{
public:
    static SSLCertStoreManager& getInstance();

    bool findCertInStore(bool& inAcceptingStore, PCCERT_CONTEXT cert);

    bool saveCertInStore(bool inAcceptingStore, PCCERT_CONTEXT cert);

    ~SSLCertStoreManager();

private:
    SSLCertStoreManager();

    bool init();

    bool isStoreReady();

    bool find(PCCERT_CONTEXT cert, HCERTSTORE store);

    bool save(bool inAcceptingStore, PCCERT_CONTEXT cert);

    void flush();

    void open();

    void close();

    HCERTSTORE m_trustedStore;

    HCERTSTORE m_untrustedStore;

    bool m_ready;
};

}

#endif //SSLCERTSTOREMANAGER_H


#include "config.h"
#include "SSLCertStoreManager.h"

#include "WTFString.h"

#define ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

const LPCTSTR WebkitRegistryRoot = L"Software\\WebKit\\";
const LPCTSTR TrustedStorePosition = L"TrustedStoreKey";
const LPCTSTR UntrustedStorePosition = L"UntrustedStoreKey";

const LPCTSTR TrustedStoreFileName = L"\\SD\\BROWSER\\TrustedStore.sto";
const LPCTSTR UntrustedStoreFileName = L"\\SD\\BROWSER\\UntrustedStore.sto";

namespace WebCore
{

SSLCertStoreManager& SSLCertStoreManager::getInstance()
{
    static SSLCertStoreManager instance;
    return instance;
}

static HKEY getKey(LPCTSTR subKey)
{
    String strKey(WebkitRegistryRoot);
    strKey += subKey;

    HKEY hKey;
    if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER,
        strKey.charactersWithNullTermination(), 0, KEY_ALL_ACCESS, &hKey))
    {
        DWORD dwDisp = 0;
        int succ = RegCreateKeyEx(HKEY_CURRENT_USER,
            strKey.charactersWithNullTermination(), 0, NULL, 0, 0, NULL, &hKey, &dwDisp);
        if (succ != ERROR_SUCCESS)
            return NULL;
        RegCloseKey(hKey);

        return getKey(subKey);
    }
    return hKey;
}

static HANDLE getFileHandle(LPCTSTR storeFileName)
{
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = FALSE;

    //  Obtain a file handle.
    return CreateFile(
        storeFileName,
        GENERIC_READ|GENERIC_WRITE,
        0,
        &sa,
        OPEN_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
}

static HCERTSTORE openStore(LPCTSTR storeFileName)
{
    HANDLE hFile = getFileHandle(storeFileName);
    if (!hFile)
        return NULL;

    HCERTSTORE store = CertOpenStore(
        CERT_STORE_PROV_FILE,      //  load certificates from a file
        ENCODING_TYPE,
        NULL,                      //  use the default HCRYPTPROV
        0,
        hFile
        );
    CloseHandle(hFile);
   
    return store;
}

bool SSLCertStoreManager::init()
{
    m_trustedStore = openStore(TrustedStoreFileName);
    m_untrustedStore = openStore(UntrustedStoreFileName);

    m_ready = m_trustedStore && m_untrustedStore;
    return m_ready;
}

SSLCertStoreManager::SSLCertStoreManager()
{
    init();
}

SSLCertStoreManager::~SSLCertStoreManager()
{
    if (m_trustedStore)
        CertCloseStore(m_trustedStore, CERT_CLOSE_STORE_FORCE_FLAG);

    if (m_untrustedStore)
        CertCloseStore(m_untrustedStore, CERT_CLOSE_STORE_FORCE_FLAG);
}

bool SSLCertStoreManager::isStoreReady()
{
    return m_ready;
}

bool SSLCertStoreManager::find(PCCERT_CONTEXT cert, HCERTSTORE store)
{
    PCCERT_CONTEXT temp = CertFindCertificateInStore(
        store,
        ENCODING_TYPE,           // Use X509_ASN_ENCODING
        0,                       // No dwFlags needed
        CERT_FIND_EXISTING,
        cert,
        NULL);
   
    bool succ = (temp != NULL);

    if (temp != NULL)
         CertFreeCertificateContext(temp);

    return succ;
}

bool SSLCertStoreManager::findCertInStore(bool& inAcceptingStore, PCCERT_CONTEXT cert)
{
    if (!isStoreReady())
        return false;

    if (find(cert, m_trustedStore))
    {
        inAcceptingStore = true;
        return true;
    }

    if (find(cert, m_untrustedStore))
    {
        inAcceptingStore = false;
        return true;
    }

    return false;
}

bool SSLCertStoreManager::save(bool inAcceptingStore, PCCERT_CONTEXT cert)
{
    HCERTSTORE hStore = inAcceptingStore? m_trustedStore:m_untrustedStore;
   
    BOOL succ = CertAddCertificateContextToStore(hStore, cert, CERT_STORE_ADD_NEW, 0);
    if (!succ)
        return false;
   
    LPCTSTR storeName = inAcceptingStore? TrustedStoreFileName:UntrustedStoreFileName;

    HANDLE hFile = getFileHandle(storeName);
    if (!hFile)
        return false;

    succ = CertSaveStore(
        hStore,
        ENCODING_TYPE,
        CERT_STORE_SAVE_AS_STORE,
        CERT_STORE_SAVE_TO_FILE,
        hFile,
        0);

    CloseHandle(hFile);
    return succ && succ;
}

bool SSLCertStoreManager::saveCertInStore(bool inAcceptingStore, PCCERT_CONTEXT cert)
{
    if (!isStoreReady())
        return false;
    return save(inAcceptingStore, cert);
}

}




沒有留言:

張貼留言