Allow email SANs for S/MIME certificates (#152)

This commit is contained in:
Ben Toews
2019-04-11 20:59:44 -06:00
committed by Filippo Valsorda
parent c7c85b20ae
commit 0d4cf75db8
2 changed files with 16 additions and 3 deletions

11
cert.go
View File

@@ -19,6 +19,7 @@ import (
"log" "log"
"math/big" "math/big"
"net" "net"
"net/mail"
"os" "os"
"os/user" "os/user"
"path/filepath" "path/filepath"
@@ -61,18 +62,26 @@ func (m *mkcert) makeCert(hosts []string) {
NotBefore: time.Now(), NotBefore: time.Now(),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true, BasicConstraintsValid: true,
} }
for _, h := range hosts { for _, h := range hosts {
if ip := net.ParseIP(h); ip != nil { if ip := net.ParseIP(h); ip != nil {
tpl.IPAddresses = append(tpl.IPAddresses, ip) tpl.IPAddresses = append(tpl.IPAddresses, ip)
} else if email, err := mail.ParseAddress(h); err == nil && email.Address == h {
tpl.EmailAddresses = append(tpl.EmailAddresses, h)
} else { } else {
tpl.DNSNames = append(tpl.DNSNames, h) tpl.DNSNames = append(tpl.DNSNames, h)
} }
} }
if m.client { if m.client {
tpl.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth} tpl.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
} else if len(tpl.IPAddresses) > 0 || len(tpl.DNSNames) > 0 {
tpl.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}
}
if len(tpl.EmailAddresses) > 0 {
tpl.ExtKeyUsage = append(tpl.ExtKeyUsage, x509.ExtKeyUsageCodeSigning, x509.ExtKeyUsageEmailProtection)
} }
// IIS (the main target of PKCS #12 files), only shows the deprecated // IIS (the main target of PKCS #12 files), only shows the deprecated

View File

@@ -12,6 +12,7 @@ import (
"fmt" "fmt"
"log" "log"
"net" "net"
"net/mail"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
@@ -190,13 +191,16 @@ func (m *mkcert) Run(args []string) {
if ip := net.ParseIP(name); ip != nil { if ip := net.ParseIP(name); ip != nil {
continue continue
} }
if email, err := mail.ParseAddress(name); err == nil && email.Address == name {
continue
}
punycode, err := idna.ToASCII(name) punycode, err := idna.ToASCII(name)
if err != nil { if err != nil {
log.Fatalf("ERROR: %q is not a valid hostname or IP: %s", name, err) log.Fatalf("ERROR: %q is not a valid hostname, IP, or email: %s", name, err)
} }
args[i] = punycode args[i] = punycode
if !hostnameRegexp.MatchString(punycode) { if !hostnameRegexp.MatchString(punycode) {
log.Fatalf("ERROR: %q is not a valid hostname or IP", name) log.Fatalf("ERROR: %q is not a valid hostname, IP, or email", name)
} }
} }