mkcert/truststore_nss.go

129 lines
3.4 KiB
Go
Raw Normal View History

2019-06-01 13:58:20 +00:00
// Copyright 2018 The mkcert Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
2018-06-28 05:29:20 +00:00
package main
import (
"log"
"os"
"os/exec"
"path/filepath"
2018-07-04 00:48:31 +00:00
"runtime"
2018-06-28 05:29:20 +00:00
"strings"
)
var (
hasNSS bool
2018-06-28 05:29:20 +00:00
hasCertutil bool
certutilPath string
nssDBs = []string{
filepath.Join(os.Getenv("HOME"), ".pki/nssdb"),
filepath.Join(os.Getenv("HOME"), "snap/chromium/current/.pki/nssdb"), // Snapcraft
"/etc/pki/nssdb", // CentOS 7
}
firefoxPaths = []string{
"/usr/bin/firefox", "/Applications/Firefox.app",
"/Applications/Firefox Developer Edition.app",
"/Applications/Firefox Nightly.app",
"C:\\Program Files\\Mozilla Firefox",
}
)
func init() {
allPaths := append(append([]string{}, nssDBs...), firefoxPaths...)
for _, path := range allPaths {
if pathExists(path) {
hasNSS = true
break
}
}
2018-06-28 05:29:20 +00:00
switch runtime.GOOS {
case "darwin":
switch {
case binaryExists("certutil"):
certutilPath, _ = exec.LookPath("certutil")
hasCertutil = true
case binaryExists("/usr/local/opt/nss/bin/certutil"):
// Check the default Homebrew path, to save executing Ruby. #135
certutilPath = "/usr/local/opt/nss/bin/certutil"
hasCertutil = true
default:
out, err := exec.Command("brew", "--prefix", "nss").Output()
if err == nil {
certutilPath = filepath.Join(strings.TrimSpace(string(out)), "bin", "certutil")
hasCertutil = pathExists(certutilPath)
}
}
case "linux":
if hasCertutil = binaryExists("certutil"); hasCertutil {
certutilPath, _ = exec.LookPath("certutil")
}
}
2018-06-28 05:29:20 +00:00
}
func (m *mkcert) checkNSS() bool {
2018-06-28 05:29:20 +00:00
if !hasCertutil {
return false
}
success := true
if m.forEachNSSProfile(func(profile string) {
2018-06-28 05:29:20 +00:00
err := exec.Command(certutilPath, "-V", "-d", profile, "-u", "L", "-n", m.caUniqueName()).Run()
if err != nil {
success = false
}
}) == 0 {
success = false
}
return success
}
func (m *mkcert) installNSS() bool {
if m.forEachNSSProfile(func(profile string) {
2018-06-28 05:29:20 +00:00
cmd := exec.Command(certutilPath, "-A", "-d", profile, "-t", "C,,", "-n", m.caUniqueName(), "-i", filepath.Join(m.CAROOT, rootName))
out, err := cmd.CombinedOutput()
fatalIfCmdErr(err, "certutil -A", out)
}) == 0 {
log.Printf("ERROR: no %s security databases found", NSSBrowsers)
return false
2018-06-28 05:29:20 +00:00
}
if !m.checkNSS() {
log.Printf("Installing in %s failed. Please report the issue with details about your environment at https://github.com/FiloSottile/mkcert/issues/new 👎", NSSBrowsers)
log.Printf("Note that if you never started %s, you need to do that at least once.", NSSBrowsers)
return false
2018-06-28 05:29:20 +00:00
}
return true
2018-06-28 05:29:20 +00:00
}
func (m *mkcert) uninstallNSS() {
m.forEachNSSProfile(func(profile string) {
2018-06-28 05:29:20 +00:00
err := exec.Command(certutilPath, "-V", "-d", profile, "-u", "L", "-n", m.caUniqueName()).Run()
if err != nil {
return
}
cmd := exec.Command(certutilPath, "-D", "-d", profile, "-n", m.caUniqueName())
out, err := cmd.CombinedOutput()
fatalIfCmdErr(err, "certutil -D", out)
})
}
func (m *mkcert) forEachNSSProfile(f func(profile string)) (found int) {
2018-06-28 05:29:20 +00:00
profiles, _ := filepath.Glob(FirefoxProfile)
profiles = append(profiles, nssDBs...)
2018-06-28 05:29:20 +00:00
for _, profile := range profiles {
if stat, err := os.Stat(profile); err != nil || !stat.IsDir() {
continue
}
if pathExists(filepath.Join(profile, "cert9.db")) {
2018-06-28 05:29:20 +00:00
f("sql:" + profile)
found++
} else if pathExists(filepath.Join(profile, "cert8.db")) {
f("dbm:" + profile)
found++
2018-06-28 05:29:20 +00:00
}
}
return
}