diff --git a/certinject/certinject_notwindows.go b/certinject/certinject_notwindows.go index 5439eaa..d22a85e 100644 --- a/certinject/certinject_notwindows.go +++ b/certinject/certinject_notwindows.go @@ -2,23 +2,34 @@ package certinject +import "fmt" + // This package is used to add and remove certificates to the system trust // store. // Currently only supports NSS sqlite3 stores. // InjectCert injects the given cert into all configured trust stores. -func InjectCert(derBytes []byte) { - +func InjectCert(derBytes []byte) error { + if !nssFlag.Value() { + return fmt.Errorf("no trusted store chosen, did you mean to use %q flag?", nssFlag.CfName()) + } if nssFlag.Value() { - injectCertNss(derBytes) + if err := injectCertNss(derBytes); err != nil { + return err + } } + return nil } // CleanCerts cleans expired certs from all configured trust stores. -func CleanCerts() { - +func CleanCerts() error { + if !nssFlag.Value() { + return fmt.Errorf("no trusted store chosen, did you mean to use %q flag?", nssFlag.CfName()) + } if nssFlag.Value() { - cleanCertsNss() + if err := cleanCertsNss(); err != nil { + return err + } } - + return nil } diff --git a/certinject/certinject_windows.go b/certinject/certinject_windows.go index 279d720..267377f 100644 --- a/certinject/certinject_windows.go +++ b/certinject/certinject_windows.go @@ -1,6 +1,8 @@ package certinject import ( + "fmt" + "gopkg.in/hlandau/easyconfig.v1/cflag" ) @@ -20,24 +22,37 @@ var ( ) // InjectCert injects the given cert into all configured trust stores. -func InjectCert(derBytes []byte) { - +func InjectCert(derBytes []byte) error { + if !cryptoApiFlag.Value() && !nssFlag.Value() { + return fmt.Errorf("no trusted store chosen, did you mean to use %q or %q flags?", cryptoApiFlag.CfName(), nssFlag.CfName()) + } if cryptoApiFlag.Value() { - injectCertCryptoApi(derBytes) + if err := injectCertCryptoApi(derBytes); err != nil { + return err + } } if nssFlag.Value() { - injectCertNss(derBytes) + if err := injectCertNss(derBytes); err != nil { + return err + } } + return nil } // CleanCerts cleans expired certs from all configured trust stores. -func CleanCerts() { - +func CleanCerts() error { + if !cryptoApiFlag.Value() && !nssFlag.Value() { + return fmt.Errorf("no trusted store chosen, did you mean to use %q or %q flags?", cryptoApiFlag.CfName(), nssFlag.CfName()) + } if cryptoApiFlag.Value() { - cleanCertsCryptoApi() + if err := cleanCertsCryptoApi(); err != nil { + return err + } } if nssFlag.Value() { - cleanCertsNss() + if err := cleanCertsNss(); err != nil { + return err + } } - + return nil } diff --git a/certinject/cryptoapi_windows.go b/certinject/cryptoapi_windows.go index 5e52106..a8d5e08 100644 --- a/certinject/cryptoapi_windows.go +++ b/certinject/cryptoapi_windows.go @@ -18,7 +18,7 @@ const cryptoApiCertStoreRegistryKey = `SOFTWARE\Microsoft\EnterpriseCertificates const cryptoApiMagicName = "Namecoin" const cryptoApiMagicValue = 1 -func injectCertCryptoApi(derBytes []byte) { +func injectCertCryptoApi(derBytes []byte) error { // Format documentation of Microsoft's "Certificate Registry Blob": @@ -74,7 +74,7 @@ func injectCertCryptoApi(derBytes []byte) { certStoreKey, err := registry.OpenKey(cryptoApiCertStoreRegistryBase, cryptoApiCertStoreRegistryKey, registry.ALL_ACCESS) if err != nil { log.Errorf("Couldn't open cert store: %s", err) - return + return err } defer certStoreKey.Close() @@ -96,7 +96,7 @@ func injectCertCryptoApi(derBytes []byte) { certKey, _, err := registry.CreateKey(certStoreKey, fingerprintHexUpper, registry.ALL_ACCESS) if err != nil { log.Errorf("Couldn't create registry key for certificate: %s", err) - return + return err } defer certKey.Close() @@ -108,25 +108,26 @@ func injectCertCryptoApi(derBytes []byte) { err = certKey.SetDWordValue(cryptoApiMagicName, cryptoApiMagicValue) if err != nil { log.Errorf("Couldn't set magic registry value for certificate: %s", err) - return + return err } // Create the registry value which holds the certificate. err = certKey.SetBinaryValue("Blob", certBlob) if err != nil { log.Errorf("Couldn't set blob registry value for certificate: %s", err) - return + return err } + return nil } -func cleanCertsCryptoApi() { +func cleanCertsCryptoApi() error { // Open up the cert store. certStoreKey, err := registry.OpenKey(cryptoApiCertStoreRegistryBase, cryptoApiCertStoreRegistryKey, registry.ALL_ACCESS) if err != nil { log.Errorf("Couldn't open cert store: %s", err) - return + return err } defer certStoreKey.Close() @@ -134,7 +135,7 @@ func cleanCertsCryptoApi() { subKeys, err := certStoreKey.ReadSubKeyNames(0) if err != nil { log.Errorf("Couldn't list certs in cert store: %s", err) - return + return err } // for all certs in the cert store @@ -144,7 +145,7 @@ func cleanCertsCryptoApi() { expired, err := checkCertExpiredCryptoApi(certStoreKey, subKeyName) if err != nil { log.Errorf("Couldn't check if cert is expired: %s", err) - return + return err } // delete the cert if it's expired @@ -153,6 +154,7 @@ func cleanCertsCryptoApi() { } } + return nil } diff --git a/certinject/file.go b/certinject/file.go index cb97609..8ab4ba7 100644 --- a/certinject/file.go +++ b/certinject/file.go @@ -6,12 +6,8 @@ import ( ) // Injects a certificate by writing to a file. Might be relevant for non-CryptoAPI trust stores. -func injectCertFile(derBytes []byte, fileName string) { - +func injectCertFile(derBytes []byte, fileName string) error { pemBytes := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) err := ioutil.WriteFile(fileName, pemBytes, 0644) - if err != nil { - log.Errore(err, "Error writing cert!") - return - } + return err } diff --git a/certinject/nss.go b/certinject/nss.go index 0f2a348..9a94597 100644 --- a/certinject/nss.go +++ b/certinject/nss.go @@ -1,14 +1,17 @@ package certinject -import "crypto/sha256" -import "encoding/hex" -import "io/ioutil" -import "os" -import "os/exec" -import "strings" -import "math" -import "time" -import "gopkg.in/hlandau/easyconfig.v1/cflag" +import ( + "crypto/sha256" + "encoding/hex" + "io/ioutil" + "math" + "os" + "os/exec" + "strings" + "time" + + "gopkg.in/hlandau/easyconfig.v1/cflag" +) var certDir = cflag.String(flagGroup, "nsscertdir", "", "Directory to store "+ "certificate files. Only use a directory that only ncdns can write "+ @@ -16,7 +19,7 @@ var certDir = cflag.String(flagGroup, "nsscertdir", "", "Directory to store "+ var nssDir = cflag.String(flagGroup, "nssdbdir", "", "Directory that "+ "contains NSS's cert9.db. (Required if nss is set.)") -func injectCertNss(derBytes []byte) { +func injectCertNss(derBytes []byte) error { if certDir.Value() == "" { log.Fatal("Empty nsscertdir configuration.") @@ -31,7 +34,9 @@ func injectCertNss(derBytes []byte) { path := certDir.Value() + "/" + fingerprintHex + ".pem" - injectCertFile(derBytes, path) + if err := injectCertFile(derBytes, path); err != nil { + return err + } nickname := nicknameFromFingerprintHexNss(fingerprintHex) @@ -44,15 +49,18 @@ func injectCertNss(derBytes []byte) { if strings.Contains(string(stdoutStderr), "SEC_ERROR_PKCS11_GENERAL_ERROR") { log.Warn("Temporary SEC_ERROR_PKCS11_GENERAL_ERROR injecting certificate to NSS database; retrying in 1ms...") time.Sleep(1 * time.Millisecond) - injectCertNss(derBytes) + if err := injectCertNss(derBytes); err != nil { + return err + } } else { log.Errorf("Error injecting cert to NSS database: %s\n%s", err, stdoutStderr) } } + return nil } -func cleanCertsNss() { +func cleanCertsNss() error { if certDir.Value() == "" { log.Fatal("Empty nsscertdir configuration.") @@ -97,7 +105,9 @@ func cleanCertsNss() { } else if strings.Contains(string(stdoutStderr), "SEC_ERROR_PKCS11_GENERAL_ERROR") { log.Warn("Temporary SEC_ERROR_PKCS11_GENERAL_ERROR deleting certificate from NSS database; retrying in 1ms...") time.Sleep(1 * time.Millisecond) - cleanCertsNss() + if err := cleanCertsNss(); err != nil { + return err + } } else { log.Fatalf("Error deleting cert from NSS database: %s\n%s", err, stdoutStderr) } @@ -110,7 +120,7 @@ func cleanCertsNss() { } } } - + return nil } func checkCertExpiredNss(certFile os.FileInfo) (bool, error) { diff --git a/certinject/nss_internal_test.go b/certinject/nss_internal_test.go index 2a6dc16..321e0e2 100644 --- a/certinject/nss_internal_test.go +++ b/certinject/nss_internal_test.go @@ -13,7 +13,9 @@ func TestCheckCertExpired(t *testing.T) { bytesDummy := []byte(`TEST DATA`) - injectCertFile(bytesDummy, testFilename) + if err := injectCertFile(bytesDummy, testFilename); err != nil { + t.Fatal(err) + } defer os.Remove(testFilename) info1, err := os.Stat(testFilename) diff --git a/tlshook/tlshook.go b/tlshook/tlshook.go index 3922a01..68a2376 100644 --- a/tlshook/tlshook.go +++ b/tlshook/tlshook.go @@ -38,8 +38,9 @@ func DomainValueHookTLS(qname string, ncv *ncdomain.Value) (err error) { continue } - // TODO: check return value - certinject.InjectCert(derBytes) + if err := certinject.InjectCert(derBytes); err != nil { + log.Info("Failed to inject certificate: ", err) + } }