aheinecke@404: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik aheinecke@404: * Software engineering by Intevation GmbH aheinecke@404: * aheinecke@404: * This file is Free Software under the GNU GPL (v>=2) aheinecke@404: * and comes with ABSOLUTELY NO WARRANTY! aheinecke@404: * See LICENSE.txt for details. aheinecke@404: */ aheinecke@137: #ifdef WIN32 aheinecke@137: aheinecke@161: #include aheinecke@161: aheinecke@137: #include "windowsstore.h" aheinecke@161: #include "errorcodes.h" aheinecke@161: #include "listutil.h" aheinecke@161: #include "strhelp.h" aheinecke@253: #include "logging.h" aheinecke@321: #include "util.h" andre@1288: #include "certhelp.h" aheinecke@222: andre@219: void andre@1309: debug_print_subject(PCCERT_CONTEXT pCert) andre@1309: { andre@1309: char pszNameString[256]; andre@1309: if (!pCert || !g_debug) andre@1309: { andre@1309: return; andre@1309: } andre@1309: andre@1309: if(CertGetNameString(pCert, andre@1309: CERT_NAME_SIMPLE_DISPLAY_TYPE, andre@1309: 0, andre@1309: NULL, andre@1309: pszNameString, andre@1309: 128)) andre@1309: { andre@1309: DEBUGPRINTF("Certificate Subject: %s", pszNameString); andre@1309: } andre@1309: } andre@1309: andre@1309: void andre@215: do_remove(HCERTSTORE hStore, char **to_remove) aheinecke@137: { andre@215: PCCERT_CONTEXT pCert = NULL; andre@215: unsigned int i = 0; andre@624: bool elevated = is_elevated(); andre@215: andre@215: if (!to_remove) andre@215: { andre@215: return; andre@215: } andre@215: andre@215: for (i=0; to_remove[i]; i++) andre@215: { andre@215: PCCERT_CONTEXT pc_to_remove = NULL; andre@215: aheinecke@222: pc_to_remove = b64_to_cert_context(to_remove[i], aheinecke@222: strnlen(to_remove[i], MAX_LINE_LENGTH)); andre@215: andre@215: if (pc_to_remove == NULL) andre@215: { aheinecke@253: char *error = getLastErrorMsg(); andre@215: if (error) andre@215: { andre@626: ERRORPRINTF ("Failed to create cert context: %s \n", error); aheinecke@253: free (error); andre@215: } andre@215: continue; andre@215: } andre@215: andre@215: pCert = CertFindCertificateInStore (hStore, andre@218: X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, andre@215: 0, andre@215: CERT_FIND_EXISTING, andre@215: pc_to_remove, andre@215: NULL); andre@215: andre@215: if (pCert == NULL) andre@215: { andre@1309: DEBUGPRINTF ("Did not find certificate\n"); andre@1309: debug_print_subject (pc_to_remove); andre@1309: CertFreeCertificateContext (pc_to_remove); andre@215: continue; andre@215: } andre@215: andre@1309: CertFreeCertificateContext (pc_to_remove); andre@1309: andre@215: if (!CertDeleteCertificateFromStore (pCert)) andre@215: { andre@215: /* From MSDN: andre@215: The CertDeleteCertificateFromStore function always frees andre@215: pCertContext by calling the CertFreeCertificateContext andre@215: function, even if an error is encountered. */ aheinecke@253: char *error = getLastErrorMsg(); andre@626: ERRORPRINTF ("Error deleting certificate. %s", error); andre@1309: debug_print_subject (pCert); aheinecke@253: free (error); andre@215: continue; andre@215: } andre@624: log_certificate (elevated ? "Local Machine" : "Current User", andre@624: to_remove[i], false); andre@215: } andre@215: return; andre@215: } andre@215: andre@219: void andre@215: do_install(HCERTSTORE hStore, char **to_install) andre@215: { andre@215: int i = 0, andre@215: ret = -1; andre@624: bool elevated = is_elevated(); andre@215: andre@215: if (!to_install) andre@215: { andre@215: return; andre@215: } andre@215: andre@217: for (i = 0; to_install[i]; i++) andre@215: { aheinecke@222: PCCERT_CONTEXT pc_to_add = NULL; aheinecke@222: PCCERT_CONTEXT found_cert = NULL; andre@215: aheinecke@222: pc_to_add = b64_to_cert_context(to_install[i], aheinecke@222: strnlen(to_install[i], MAX_LINE_LENGTH)); andre@215: aheinecke@222: if (pc_to_add == NULL) andre@215: { aheinecke@222: continue; andre@215: } andre@215: aheinecke@222: found_cert = CertFindCertificateInStore (hStore, andre@905: X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, andre@905: 0, andre@905: CERT_FIND_EXISTING, andre@905: pc_to_add, andre@905: NULL); aheinecke@222: if (found_cert != NULL) aheinecke@222: { andre@1309: /* DEBUGPRINTF ("Certificate already in store\n"); */ aheinecke@222: CertFreeCertificateContext (found_cert); aheinecke@222: CertFreeCertificateContext (pc_to_add); aheinecke@222: continue; aheinecke@222: } andre@215: aheinecke@222: ret = CertAddCertificateContextToStore (hStore, aheinecke@222: pc_to_add, andre@215: CERT_STORE_ADD_ALWAYS, andre@215: NULL); andre@215: if (!ret) andre@215: { aheinecke@253: char *error = getLastErrorMsg(); andre@215: if (error) andre@215: { andre@626: ERRORPRINTF ("Failed to add certificate: %s \n", error); andre@1309: debug_print_subject (pc_to_add); aheinecke@253: free (error); andre@215: } andre@215: } andre@1309: CertFreeCertificateContext (pc_to_add); andre@624: log_certificate (elevated ? "Local Machine" : "Current User", andre@624: to_install[i], true); andre@215: } andre@215: return; andre@215: } andre@215: andre@215: int aheinecke@247: write_stores_win (char **to_install, char **to_remove) andre@215: { aheinecke@163: HCERTSTORE hStore = NULL; aheinecke@137: andre@215: if (!to_install && !to_remove) andre@215: { andre@215: /* Nothing to do */ andre@215: return 0; andre@215: } andre@215: aheinecke@247: if (!is_elevated()) aheinecke@163: { aheinecke@163: hStore = CertOpenStore (CERT_STORE_PROV_SYSTEM, 0, aheinecke@163: 0, CERT_SYSTEM_STORE_CURRENT_USER, L"Root"); aheinecke@163: } aheinecke@163: else aheinecke@163: { aheinecke@163: hStore = CertOpenStore (CERT_STORE_PROV_SYSTEM, 0, aheinecke@163: 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"Root"); aheinecke@137: } aheinecke@137: aheinecke@163: if (!hStore) aheinecke@163: { aheinecke@504: ERRORPRINTF ("Failed to access store.\n"); aheinecke@163: return ERR_STORE_ACCESS_DENIED; aheinecke@137: } aheinecke@137: andre@215: /* Do the actual work */ andre@215: do_install (hStore, to_install); aheinecke@137: andre@215: do_remove (hStore, to_remove); aheinecke@161: aheinecke@163: if (hStore) aheinecke@163: { aheinecke@163: CertCloseStore (hStore, 0); aheinecke@137: } aheinecke@163: return 0; aheinecke@137: } aheinecke@137: #endif // WIN32