mirror of https://github.com/namecoin/ncdns
certinject: NSS improvements, now works on arbitrary NSS cert store directories.
parent
e5c7c09968
commit
2c8b5fe5ee
@ -0,0 +1,11 @@
|
||||
package certinject
|
||||
|
||||
import (
|
||||
"gopkg.in/hlandau/easyconfig.v1/cflag"
|
||||
)
|
||||
|
||||
var (
|
||||
flagGroup = cflag.NewGroup(nil, "certstore")
|
||||
nssFlag = cflag.Bool(flagGroup, "nss", false, nssExplain)
|
||||
certExpirePeriod = cflag.Int(flagGroup, "expire", 60 * 30, "Duration (in seconds) after which TLS certs will be removed from the trust store. Making this smaller than the DNS TTL (default 600) may cause TLS errors.")
|
||||
)
|
@ -1,15 +0,0 @@
|
||||
// +build !windows,!linux
|
||||
|
||||
package certinject
|
||||
|
||||
import "github.com/hlandau/xlog"
|
||||
|
||||
var log, Log = xlog.New("ncdns.certinject")
|
||||
|
||||
func InjectCert(derBytes []byte) {
|
||||
|
||||
}
|
||||
|
||||
func CleanCerts() {
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
// +build !linux
|
||||
|
||||
package certinject
|
||||
|
||||
var (
|
||||
nssExplain = "(Unsafe and experimental!) Synchronize TLS certs to an NSS sqlite3 trust store? This enables HTTPS to work with some NSS-based software. This is currently unsafe and should not be used."
|
||||
)
|
@ -0,0 +1,28 @@
|
||||
// +build !windows
|
||||
|
||||
package certinject
|
||||
|
||||
import "github.com/hlandau/xlog"
|
||||
|
||||
// This package is used to add and remove certificates to the system trust
|
||||
// store.
|
||||
// Currently only supports NSS sqlite3 stores.
|
||||
|
||||
var log, Log = xlog.New("ncdns.certinject")
|
||||
|
||||
// Injects the given cert into all configured trust stores.
|
||||
func InjectCert(derBytes []byte) {
|
||||
|
||||
if nssFlag.Value() {
|
||||
injectCertNss(derBytes)
|
||||
}
|
||||
}
|
||||
|
||||
// Cleans expired certs from all configured trust stores.
|
||||
func CleanCerts() {
|
||||
|
||||
if nssFlag.Value() {
|
||||
cleanCertsNss()
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
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"
|
||||
|
||||
var certDir = cflag.String(flagGroup, "nsscertdir", "", "Directory to store certificate files. Only use a directory that only ncdns can write to. (Required if nss is set.)")
|
||||
var nssDir = cflag.String(flagGroup, "nssdbdir", "", "Directory that contains NSS's cert9.db. (Required if nss is set.)")
|
||||
|
||||
func injectCertNss(derBytes []byte) {
|
||||
|
||||
if certDir.Value() == "" {
|
||||
log.Fatal("Empty nsscertdir configuration.")
|
||||
}
|
||||
if nssDir.Value() == "" {
|
||||
log.Fatal("Empty nssdbdir configuration.")
|
||||
}
|
||||
|
||||
fingerprint := sha256.Sum256(derBytes)
|
||||
|
||||
fingerprintHex := hex.EncodeToString(fingerprint[:])
|
||||
|
||||
path := certDir.Value() + "/" + fingerprintHex + ".pem"
|
||||
|
||||
injectCertFile(derBytes, path)
|
||||
|
||||
nickname := nicknameFromFingerprintHexNss(fingerprintHex)
|
||||
|
||||
// TODO: check whether we can replace CP with just P.
|
||||
cmd := exec.Command(nssCertutilName, "-d", "sql:" + nssDir.Value(), "-A", "-t", "CP,,", "-n", nickname, "-a", "-i", path)
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func cleanCertsNss() {
|
||||
|
||||
if certDir.Value() == "" {
|
||||
log.Fatal("Empty nsscertdir configuration.")
|
||||
}
|
||||
if nssDir.Value() == "" {
|
||||
log.Fatal("Empty nssdbdir configuration.")
|
||||
}
|
||||
|
||||
certFiles, _ := ioutil.ReadDir(certDir.Value() + "/")
|
||||
|
||||
// for all Namecoin certs in the folder
|
||||
for _, f := range certFiles {
|
||||
|
||||
// Check if the cert is expired
|
||||
expired, err := checkCertExpiredNss(f)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// delete the cert if it's expired
|
||||
if expired {
|
||||
|
||||
filename := f.Name()
|
||||
|
||||
fingerprintHex := strings.Replace(filename, ".pem", "", -1)
|
||||
|
||||
nickname := nicknameFromFingerprintHexNss(fingerprintHex)
|
||||
|
||||
// Delete the cert from NSS
|
||||
cmd := exec.Command(nssCertutilName, "-d", "sql:" + nssDir.Value(), "-D", "-n", nickname)
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Also delete the cert from the filesystem
|
||||
err = os.Remove(certDir.Value() + "/" + filename)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func checkCertExpiredNss(certFile os.FileInfo) (bool, error) {
|
||||
|
||||
// Get the last modified time
|
||||
certFileModTime := certFile.ModTime()
|
||||
|
||||
// If the cert's last modified timestamp differs too much from the current time in either direction, consider it expired
|
||||
expired := math.Abs( time.Since(certFileModTime).Seconds() ) > float64(certExpirePeriod.Value())
|
||||
|
||||
return expired, nil
|
||||
|
||||
}
|
||||
|
||||
func nicknameFromFingerprintHexNss(fingerprintHex string) string {
|
||||
return "Namecoin-" + fingerprintHex
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
// +build !windows
|
||||
|
||||
package certinject
|
||||
|
||||
var (
|
||||
nssCertutilName = "certutil"
|
||||
)
|
@ -1,89 +0,0 @@
|
||||
package certinject
|
||||
|
||||
import "crypto/sha256"
|
||||
import "encoding/hex"
|
||||
import "io/ioutil"
|
||||
import "os"
|
||||
import "os/exec"
|
||||
import "strings"
|
||||
import "math"
|
||||
import "time"
|
||||
|
||||
var homeDir = os.Getenv("HOME")
|
||||
|
||||
var certDir = homeDir + "/.ncdns/certs"
|
||||
var nssDir = "sql:" + homeDir + "/.pki/nssdb"
|
||||
|
||||
func injectCertNssShared(derBytes []byte) {
|
||||
|
||||
fingerprint := sha256.Sum256(derBytes)
|
||||
|
||||
fingerprintHex := hex.EncodeToString(fingerprint[:])
|
||||
|
||||
path := certDir + "/" + fingerprintHex + ".pem"
|
||||
|
||||
injectCertFile(derBytes, path)
|
||||
|
||||
nickname := nicknameFromFingerprintHexNssShared(fingerprintHex)
|
||||
|
||||
cmd := exec.Command("certutil", "-d", nssDir, "-A", "-t", "CP,,", "-n", nickname, "-a", "-i", path)
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func cleanCertsNssShared() {
|
||||
|
||||
certFiles, _ := ioutil.ReadDir(certDir + "/")
|
||||
|
||||
// for all Namecoin certs in the folder
|
||||
for _, f := range certFiles {
|
||||
|
||||
// Check if the cert is expired
|
||||
expired, err := checkCertExpiredNssShared(f)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// delete the cert if it's expired
|
||||
if expired {
|
||||
|
||||
filename := f.Name()
|
||||
|
||||
fingerprintHex := strings.Replace(filename, ".pem", "", -1)
|
||||
|
||||
nickname := nicknameFromFingerprintHexNssShared(fingerprintHex)
|
||||
|
||||
// Delete the cert from NSS
|
||||
cmd := exec.Command("certutil", "-d", nssDir, "-D", "-n", nickname)
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Also delete the cert from the filesystem
|
||||
err = os.Remove(certDir + "/" + filename)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func checkCertExpiredNssShared(certFile os.FileInfo) (bool, error) {
|
||||
|
||||
// Get the last modified time
|
||||
certFileModTime := certFile.ModTime()
|
||||
|
||||
// If the cert's last modified timestamp differs too much from the current time in either direction, consider it expired
|
||||
expired := math.Abs( time.Since(certFileModTime).Seconds() ) > float64(certExpirePeriod.Value())
|
||||
|
||||
return expired, nil
|
||||
|
||||
}
|
||||
|
||||
func nicknameFromFingerprintHexNssShared(fingerprintHex string) string {
|
||||
return "Namecoin-" + fingerprintHex
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package certinject
|
||||
|
||||
var (
|
||||
nssCertutilName = "nss-certutil"
|
||||
)
|
Loading…
Reference in New Issue