view cinst/windowsstore.c @ 224:689b94dd89a9

Wrote FindNSS to build against nss without pkg-config support (Windows).
author Sascha Wilde <wilde@intevation.de>
date Thu, 27 Mar 2014 17:00:01 +0100
parents 57bef180d560
children 53ea9b975d1c
line wrap: on
line source
#ifdef WIN32

#include <stdio.h>

#include "windowsstore.h"
#include "errorcodes.h"
#include "listutil.h"
#include "strhelp.h"

static LPWSTR getLastErrorMsg()
{
  LPWSTR bufPtr = NULL;
  DWORD err = GetLastError();
  FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER |
                  FORMAT_MESSAGE_FROM_SYSTEM |
                  FORMAT_MESSAGE_IGNORE_INSERTS,
                  NULL, err, 0, (LPWSTR) &bufPtr, 0, NULL);
  if (!bufPtr)
    {
      HMODULE hWinhttp = GetModuleHandleW (L"crypt32");
      if (hWinhttp)
        {
          FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER |
                          FORMAT_MESSAGE_FROM_HMODULE |
                          FORMAT_MESSAGE_IGNORE_INSERTS,
                          hWinhttp, HRESULT_CODE (err), 0,
                          (LPWSTR) &bufPtr, 0, NULL);
        }
    }
  if (!bufPtr)
    printf ("Error getting last error for code: %lx \n", err);
  return bufPtr;
}

void
do_remove(HCERTSTORE hStore, char **to_remove)
{
  PCCERT_CONTEXT pCert = NULL;
  unsigned int i = 0;

  if (!to_remove)
    {
      return;
    }

  for (i=0; to_remove[i]; i++)
    {
      char *asn1_data = NULL;
      size_t asn1_size = 0;
      int ret = -1;
      DWORD j;
      PCCERT_CONTEXT pc_to_remove = NULL;

      ret = str_base64_decode (&asn1_data, &asn1_size, to_remove[i],
                               strnlen(to_remove[i], MAX_LINE_LENGTH));
      /* Decoding / parsing errors in here should not happen at all.
         The only errors which are not a bug would be out of memory or
         if the signed certificate list contained an invalid certificate. */
      if (ret != 0)
        {
          printf ("Error base64 certificate.\n");
          continue;
        }

      printf ("Deleting cert %s\n", to_remove[i]);
      pc_to_remove = CertCreateContext (CERT_STORE_CERTIFICATE_CONTEXT,
                                        X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                                        (const PBYTE) asn1_data,
                                        (DWORD) asn1_size,
                                        0,
                                        NULL);
      free (asn1_data); /* Windows has a copy */
      if (pc_to_remove == NULL)
        {
          LPWSTR error = getLastErrorMsg();
          if (error)
            {
              printf ("Failed to add certificate: %S \n", error);
              LocalFree (error);
            }
          continue;
        }

      pCert = CertFindCertificateInStore (hStore,
                                          X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                                          0,
                                          CERT_FIND_EXISTING,
                                          pc_to_remove,
                                          NULL);


        {
          char pszNameString[256];
          if(CertGetNameString(   
             pc_to_remove,   
             CERT_NAME_SIMPLE_DISPLAY_TYPE,   
             0,
             NULL,   
             pszNameString,   
             128))
          {
            printf("wanted: %s \n",pszNameString);
          }
          if(CertGetNameString(   
             pCert,   
             CERT_NAME_SIMPLE_DISPLAY_TYPE,   
             0,
             NULL,   
             pszNameString,   
             128))
          {
             printf("got: %s \n",pszNameString);
          }
        }

      CertFreeCertificateContext (pc_to_remove);

      if (pCert == NULL)
        {
          printf ("Did not find certificate\n");
          continue;
        }
      for (j = 0; j < pCert->cbCertEncoded; j++) {
          if (asn1_data[j] != pCert->pbCertEncoded[j]) {
              printf("%1x", (unsigned)(unsigned char)pCert->pbCertEncoded[j]);
          }
      }
      printf("\nWanted: \n");
      for (j = 0; j < pCert->cbCertEncoded; j++) {
          if (asn1_data[j] != pCert->pbCertEncoded[j]) {
              printf("%1x", (unsigned)(unsigned char)asn1_data[j]);
          }
      }
      printf("\n");

      if (!CertDeleteCertificateFromStore (pCert))
        {
          /* From MSDN:
             The CertDeleteCertificateFromStore function always frees
             pCertContext by calling the CertFreeCertificateContext
             function, even if an error is encountered. */
          LPWSTR error = getLastErrorMsg();
          printf ("Error deleting certificate. %S", error);
          LocalFree (error);
          continue;
        }
    }
  return;
}

void
do_install(HCERTSTORE hStore, char **to_install)
{
  int i = 0,
      ret = -1;

  if (!to_install)
    {
      return;
    }

  for (i = 0; to_install[i]; i++)
    {
      size_t cert_len = strnlen (to_install[i], MAX_LINE_LENGTH),
             buf_size = 0;
      char *buf = NULL;

      ret = str_base64_decode (&buf, &buf_size, to_install[i], cert_len);

      if (ret != 0)
        {
          printf ("decoding certificate failed\n");
          return;
        }

      printf ("Adding cert %s\n", to_install[i]);

      ret = CertAddEncodedCertificateToStore (hStore,
                                              X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                                              (PBYTE) buf,
                                              buf_size,
                                              CERT_STORE_ADD_ALWAYS,
                                              NULL);

      if (!ret)
        {
          LPWSTR error = getLastErrorMsg();
          if (error)
            {
              printf ("Failed to add certificate: %S \n", error);
              LocalFree (error);
            }
        }
      free (buf);
    }
  return;
}

int
write_stores_win (char **to_install, char **to_remove, bool user_store)
{
  HCERTSTORE hStore = NULL;

  if (!to_install && !to_remove)
    {
      /* Nothing to do */
      return 0;
    }

  if (user_store)
    {
      hStore = CertOpenStore (CERT_STORE_PROV_SYSTEM, 0,
                              0, CERT_SYSTEM_STORE_CURRENT_USER, L"Root");
    }
  else
    {
      hStore = CertOpenStore (CERT_STORE_PROV_SYSTEM, 0,
                              0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"Root");
    }

  if (!hStore)
    {
      return ERR_STORE_ACCESS_DENIED;
    }

  /* Do the actual work */
  do_install (hStore, to_install);

  do_remove (hStore, to_remove);

  if (hStore)
    {
      CertCloseStore (hStore, 0);
    }
  return 0;
}
#endif // WIN32

http://wald.intevation.org/projects/trustbridge/