certinject: add support for the shared NSS trust store on GNU/Linux systems.

pull/17/head
JeremyRand 7 years ago
parent 09a88dc989
commit e5c7c09968
No known key found for this signature in database
GPG Key ID: B3F2D165786D6570

@ -0,0 +1,34 @@
package certinject
import "gopkg.in/hlandau/easyconfig.v1/cflag"
import "github.com/hlandau/xlog"
// This package is used to add and remove certificates to the system trust
// store.
// Currently only supports the system NSS store.
var log, Log = xlog.New("ncdns.certinject")
var (
flagGroup = cflag.NewGroup(nil, "certstore")
nssSharedFlag = cflag.Bool(flagGroup, "nss-shared", false, "Synchronize TLS certs to the NSS shared trust store? This enables HTTPS to work with Chromium/Chrome. Only use if you've set up null HPKP in Chromium/Chrome as per documentation. If you haven't set up null HPKP, or if you access ncdns from browsers not based on Chromium, this is unsafe and should not be used.")
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.")
)
// Injects the given cert into all configured trust stores.
func InjectCert(derBytes []byte) {
if nssSharedFlag.Value() {
injectCertNssShared(derBytes)
}
}
// Cleans expired certs from all configured trust stores.
func CleanCerts() {
if nssSharedFlag.Value() {
cleanCertsNssShared()
}
}

@ -1,4 +1,4 @@
// +build !windows
// +build !windows,!linux
package certinject

@ -0,0 +1,89 @@
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
}
Loading…
Cancel
Save