Skip to content

Commit 1b4ad6c

Browse files
committed
truststore_nss: retry certtool with sudo when it fails due to permissions
Based on @rfay's investigation and fix. Fixes #192 Closes #193
1 parent 00ded1d commit 1b4ad6c

File tree

2 files changed

+22
-8
lines changed

2 files changed

+22
-8
lines changed

truststore_java.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func (m *mkcert) installJava() {
8787
"-alias", m.caUniqueName(),
8888
}
8989

90-
out, err := m.execKeytool(exec.Command(keytoolPath, args...))
90+
out, err := execKeytool(exec.Command(keytoolPath, args...))
9191
fatalIfCmdErr(err, "keytool -importcert", out)
9292
}
9393

@@ -98,7 +98,7 @@ func (m *mkcert) uninstallJava() {
9898
"-keystore", cacertsPath,
9999
"-storepass", storePass,
100100
}
101-
out, err := m.execKeytool(exec.Command(keytoolPath, args...))
101+
out, err := execKeytool(exec.Command(keytoolPath, args...))
102102
if bytes.Contains(out, []byte("does not exist")) {
103103
return // cert didn't exist
104104
}
@@ -107,11 +107,11 @@ func (m *mkcert) uninstallJava() {
107107

108108
// execKeytool will execute a "keytool" command and if needed re-execute
109109
// the command with commandWithSudo to work around file permissions.
110-
func (m *mkcert) execKeytool(cmd *exec.Cmd) ([]byte, error) {
110+
func execKeytool(cmd *exec.Cmd) ([]byte, error) {
111111
out, err := cmd.CombinedOutput()
112112
if err != nil && bytes.Contains(out, []byte("java.io.FileNotFoundException")) && runtime.GOOS != "windows" {
113113
origArgs := cmd.Args[1:]
114-
cmd = commandWithSudo(keytoolPath)
114+
cmd = commandWithSudo(cmd.Path)
115115
cmd.Args = append(cmd.Args, origArgs...)
116116
cmd.Env = []string{
117117
"JAVA_HOME=" + javaHome,

truststore_nss.go

+18-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package main
66

77
import (
8+
"bytes"
89
"log"
910
"os"
1011
"os/exec"
@@ -83,8 +84,8 @@ func (m *mkcert) checkNSS() bool {
8384
func (m *mkcert) installNSS() bool {
8485
if m.forEachNSSProfile(func(profile string) {
8586
cmd := exec.Command(certutilPath, "-A", "-d", profile, "-t", "C,,", "-n", m.caUniqueName(), "-i", filepath.Join(m.CAROOT, rootName))
86-
out, err := cmd.CombinedOutput()
87-
fatalIfCmdErr(err, "certutil -A", out)
87+
out, err := execCertutil(cmd)
88+
fatalIfCmdErr(err, "certutil -A -d "+profile, out)
8889
}) == 0 {
8990
log.Printf("ERROR: no %s security databases found", NSSBrowsers)
9091
return false
@@ -104,11 +105,24 @@ func (m *mkcert) uninstallNSS() {
104105
return
105106
}
106107
cmd := exec.Command(certutilPath, "-D", "-d", profile, "-n", m.caUniqueName())
107-
out, err := cmd.CombinedOutput()
108-
fatalIfCmdErr(err, "certutil -D", out)
108+
out, err := execCertutil(cmd)
109+
fatalIfCmdErr(err, "certutil -D -d "+profile, out)
109110
})
110111
}
111112

113+
// execCertutil will execute a "certutil" command and if needed re-execute
114+
// the command with commandWithSudo to work around file permissions.
115+
func execCertutil(cmd *exec.Cmd) ([]byte, error) {
116+
out, err := cmd.CombinedOutput()
117+
if err != nil && bytes.Contains(out, []byte("SEC_ERROR_READ_ONLY")) && runtime.GOOS != "windows" {
118+
origArgs := cmd.Args[1:]
119+
cmd = commandWithSudo(cmd.Path)
120+
cmd.Args = append(cmd.Args, origArgs...)
121+
out, err = cmd.CombinedOutput()
122+
}
123+
return out, err
124+
}
125+
112126
func (m *mkcert) forEachNSSProfile(f func(profile string)) (found int) {
113127
profiles, _ := filepath.Glob(FirefoxProfile)
114128
profiles = append(profiles, nssDBs...)

0 commit comments

Comments
 (0)