view cinst/windowsstore.c @ 1360:bb17f55f6cf1

Added tag 0.9.4 for changeset c85da02d669e
author Andre Heinecke <andre.heinecke@intevation.de>
date Thu, 30 Oct 2014 14:52:03 +0100
parents 18211dce3106
children
line wrap: on
line source
/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU GPL (v>=2)
 * and comes with ABSOLUTELY NO WARRANTY!
 * See LICENSE.txt for details.
 */
#ifdef WIN32

#include <stdio.h>

#include "windowsstore.h"
#include "errorcodes.h"
#include "listutil.h"
#include "strhelp.h"
#include "logging.h"
#include "util.h"
#include "certhelp.h"

void
debug_print_subject(PCCERT_CONTEXT pCert)
{
  char pszNameString[256];
  if (!pCert || !g_debug)
    {
      return;
    }

  if(CertGetNameString(pCert,
                       CERT_NAME_SIMPLE_DISPLAY_TYPE,
                       0,
                       NULL,
                       pszNameString,
                       128))
    {
      DEBUGPRINTF("Certificate Subject: %s", pszNameString);
    }
}

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

  if (!to_remove)
    {
      return;
    }

  for (i=0; to_remove[i]; i++)
    {
      PCCERT_CONTEXT pc_to_remove = NULL;

      pc_to_remove = b64_to_cert_context(to_remove[i],
                                         strnlen(to_remove[i], MAX_LINE_LENGTH));

      if (pc_to_remove == NULL)
        {
          char *error = getLastErrorMsg();
          if (error)
            {
              ERRORPRINTF ("Failed to create cert context: %s \n", error);
              free (error);
            }
          continue;
        }

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

      if (pCert == NULL)
        {
          DEBUGPRINTF ("Did not find certificate\n");
          debug_print_subject (pc_to_remove);
          CertFreeCertificateContext (pc_to_remove);
          continue;
        }

      CertFreeCertificateContext (pc_to_remove);

      if (!CertDeleteCertificateFromStore (pCert))
        {
          /* From MSDN:
             The CertDeleteCertificateFromStore function always frees
             pCertContext by calling the CertFreeCertificateContext
             function, even if an error is encountered. */
          char *error = getLastErrorMsg();
          ERRORPRINTF ("Error deleting certificate. %s", error);
          debug_print_subject (pCert);
          free (error);
          continue;
        }
      log_certificate (elevated ? "Local Machine" : "Current User",
                       to_remove[i], false);
    }
  return;
}

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

  if (!to_install)
    {
      return;
    }

  for (i = 0; to_install[i]; i++)
    {
      PCCERT_CONTEXT pc_to_add = NULL;
      PCCERT_CONTEXT found_cert = NULL;

      pc_to_add = b64_to_cert_context(to_install[i],
                                      strnlen(to_install[i], MAX_LINE_LENGTH));

      if (pc_to_add == NULL)
        {
          continue;
        }

      found_cert = CertFindCertificateInStore (hStore,
                   X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                   0,
                   CERT_FIND_EXISTING,
                   pc_to_add,
                   NULL);
      if (found_cert != NULL)
        {
          /* DEBUGPRINTF ("Certificate already in store\n"); */
          CertFreeCertificateContext (found_cert);
          CertFreeCertificateContext (pc_to_add);
          continue;
        }

      ret = CertAddCertificateContextToStore (hStore,
                                              pc_to_add,
                                              CERT_STORE_ADD_ALWAYS,
                                              NULL);
      if (!ret)
        {
          char *error = getLastErrorMsg();
          if (error)
            {
              ERRORPRINTF ("Failed to add certificate: %s \n", error);
              debug_print_subject (pc_to_add);
              free (error);
            }
        }
      CertFreeCertificateContext (pc_to_add);
      log_certificate (elevated ? "Local Machine" : "Current User",
                       to_install[i], true);
    }
  return;
}

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

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

  if (!is_elevated())
    {
      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)
    {
      ERRORPRINTF ("Failed to access store.\n");
      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/