diff --git a/truststore.go b/truststore.go index d803570b8e536ff88bde3e6311ccd06f381a1d28..6bfded6d4133f8161163a7756c8f04b80d4c667b 100644 --- a/truststore.go +++ b/truststore.go @@ -58,8 +58,12 @@ func InstallFile(filename string, opts ...Option) error { func installCertificate(filename string, cert *x509.Certificate, opts []Option) error { o := newOptions(opts) - if o.withJava { - + if o.withJava && hasJava { + if !checkJava(cert) { + if err := installJava(filename, cert); err != nil { + return err + } + } } if o.withFirefox && hasNSS() { if !checkNSS(cert) { @@ -99,7 +103,9 @@ func UninstallFile(filename string, opts ...Option) error { func uninstallCertificate(filename string, cert *x509.Certificate, opts []Option) error { o := newOptions(opts) if o.withJava { - + if err := uninstallJava(filename, cert); err != nil { + return err + } } if o.withFirefox && checkNSS(cert) { if err := uninstallNSS(filename, cert); err != nil { diff --git a/truststore_java.go b/truststore_java.go index c099fbadaddd75275298f57d78a7baa2d5fbf8fc..030f2656ad94369b12efbf16e706d2cd25889993 100644 --- a/truststore_java.go +++ b/truststore_java.go @@ -1,7 +1,5 @@ -// +build ignore -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// Copyright (c) 2018 The truststore Authors. All rights reserved. +// Copyright (c) 2018 The mkcert Authors. All rights reserved. package truststore @@ -55,10 +53,12 @@ func init() { if err == nil { cacertsPath = filepath.Join(v, "jre", "lib", "security", "cacerts") } + + println(cacertsPath) } } -func (m *mkcert) checkJava() bool { +func checkJava(cert *x509.Certificate) bool { if !hasKeytool { return false } @@ -72,46 +72,57 @@ func (m *mkcert) checkJava() bool { } keytoolOutput, err := exec.Command(keytoolPath, "-list", "-keystore", cacertsPath, "-storepass", storePass).CombinedOutput() - fatalIfCmdErr(err, "keytool -list", keytoolOutput) + if err != nil { + debug("failed to execute \"keytool -list\": %s\n\n%s", err, keytoolOutput) + return false + } + // keytool outputs SHA1 and SHA256 (Java 9+) certificates in uppercase hex // with each octet pair delimitated by ":". Drop them from the keytool output keytoolOutput = bytes.Replace(keytoolOutput, []byte(":"), nil, -1) // pre-Java 9 uses SHA1 fingerprints s1, s256 := sha1.New(), sha256.New() - return exists(m.caCert, s1, keytoolOutput) || exists(m.caCert, s256, keytoolOutput) + return exists(cert, s1, keytoolOutput) || exists(cert, s256, keytoolOutput) } -func (m *mkcert) installJava() { +func installJava(filename string, cert *x509.Certificate) error { args := []string{ "-importcert", "-noprompt", "-keystore", cacertsPath, "-storepass", storePass, - "-file", filepath.Join(m.CAROOT, rootName), - "-alias", m.caUniqueName(), + "-file", filename, + "-alias", uniqueName(cert), } - out, err := m.execKeytool(exec.Command(keytoolPath, args...)) - fatalIfCmdErr(err, "keytool -importcert", out) + out, err := execKeytool(exec.Command(keytoolPath, args...)) + if err != nil { + return cmdError(err, "keytool -importcert", out) + } + + return nil } -func (m *mkcert) uninstallJava() { +func uninstallJava(filename string, cert *x509.Certificate) error { args := []string{ "-delete", - "-alias", m.caUniqueName(), + "-alias", uniqueName(cert), "-keystore", cacertsPath, "-storepass", storePass, } - out, err := m.execKeytool(exec.Command(keytoolPath, args...)) + out, err := execKeytool(exec.Command(keytoolPath, args...)) if bytes.Contains(out, []byte("does not exist")) { - return // cert didn't exist + return nil + } + if err != nil { + cmdError(err, "keytool -delete", out) } - fatalIfCmdErr(err, "keytool -delete", out) + return nil } // execKeytool will execute a "keytool" command and if needed re-execute // the command wrapped in 'sudo' to work around file permissions. -func (m *mkcert) execKeytool(cmd *exec.Cmd) ([]byte, error) { +func execKeytool(cmd *exec.Cmd) ([]byte, error) { out, err := cmd.CombinedOutput() if err != nil && bytes.Contains(out, []byte("java.io.FileNotFoundException")) && runtime.GOOS != "windows" { origArgs := cmd.Args[1:]