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 (
2018-07-04 02:26:37 +00:00
hasNSS bool
2018-06-28 05:29:20 +00:00
hasCertutil bool
certutilPath string
2018-07-04 02:26:37 +00:00
nssDB = filepath . Join ( os . Getenv ( "HOME" ) , ".pki/nssdb" )
2018-06-28 05:29:20 +00:00
)
func init ( ) {
_ , err := os . Stat ( FirefoxPath )
2018-07-04 02:26:37 +00:00
hasNSS = ! os . IsNotExist ( err )
2018-06-28 05:29:20 +00:00
2018-07-04 02:26:37 +00:00
switch runtime . GOOS {
case "darwin" :
out , err := exec . Command ( "brew" , "--prefix" , "nss" ) . Output ( )
if err != nil {
return
}
certutilPath = filepath . Join ( strings . TrimSpace ( string ( out ) ) , "bin" , "certutil" )
2018-06-28 05:29:20 +00:00
2018-07-04 02:26:37 +00:00
_ , err = os . Stat ( certutilPath )
hasCertutil = ! os . IsNotExist ( err )
case "linux" :
_ , err := os . Stat ( nssDB )
hasNSS = hasNSS && ! os . IsNotExist ( err )
certutilPath , err = exec . LookPath ( "certutil" )
hasCertutil = err == nil
}
2018-06-28 05:29:20 +00:00
}
2018-07-04 02:26:37 +00:00
func ( m * mkcert ) checkNSS ( ) bool {
2018-06-28 05:29:20 +00:00
if ! hasCertutil {
return false
}
success := true
2018-07-04 02:26:37 +00:00
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
}
2018-07-04 02:26:37 +00:00
func ( m * mkcert ) installNSS ( ) {
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 ( )
2018-07-04 00:48:31 +00:00
if err != nil {
log . Printf ( "!!! You've hit a known issue. Please report the entire command output at https://github.com/FiloSottile/mkcert/issues/12\nProfile path: %s\nOS: %s/%s\ncertutil: %s\n" , profile , runtime . GOOS , runtime . GOARCH , certutilPath )
cmd := exec . Command ( "ls" , "-l" , profile [ 4 : ] )
cmd . Stdout , cmd . Stderr = os . Stderr , os . Stderr
cmd . Run ( )
}
2018-06-28 05:29:20 +00:00
fatalIfCmdErr ( err , "certutil -A" , out )
} ) == 0 {
2018-07-04 02:26:37 +00:00
log . Printf ( "ERROR: no %s security databases found" , NSSBrowsers )
2018-06-28 05:29:20 +00:00
}
2018-07-04 02:26:37 +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 )
2018-06-28 05:29:20 +00:00
}
}
2018-07-04 02:26:37 +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 )
} )
}
2018-07-04 02:26:37 +00:00
func ( m * mkcert ) forEachNSSProfile ( f func ( profile string ) ) ( found int ) {
2018-06-28 05:29:20 +00:00
profiles , _ := filepath . Glob ( FirefoxProfile )
2018-07-04 02:26:37 +00:00
if _ , err := os . Stat ( nssDB ) ; ! os . IsNotExist ( err ) {
profiles = append ( profiles , nssDB )
}
2018-06-28 05:29:20 +00:00
if len ( profiles ) == 0 {
return
}
for _ , profile := range profiles {
2018-07-04 16:59:33 +00:00
if stat , err := os . Stat ( profile ) ; err != nil || ! stat . IsDir ( ) {
continue
}
2018-06-28 05:29:20 +00:00
if _ , err := os . Stat ( filepath . Join ( profile , "cert9.db" ) ) ; ! os . IsNotExist ( err ) {
f ( "sql:" + profile )
found ++
2018-07-12 17:47:05 +00:00
continue
}
if _ , err := os . Stat ( filepath . Join ( profile , "cert8.db" ) ) ; ! os . IsNotExist ( err ) {
f ( "dbm:" + profile )
found ++
2018-06-28 05:29:20 +00:00
}
}
return
}