pull/125/merge
aerth 3 years ago committed by GitHub
commit cd2f87271a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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
}

@ -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
}

@ -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
}

@ -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
}

@ -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) {

@ -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)

@ -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)
}
}

Loading…
Cancel
Save