mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2024-11-29 10:28:53 +03:00
* validateCertificates(): change input parameters; added short description
This commit is contained in:
parent
d218e047a3
commit
766fbab071
3 changed files with 25 additions and 26 deletions
4
app.go
4
app.go
|
@ -178,13 +178,13 @@ func run(args options) {
|
||||||
}
|
}
|
||||||
address := net.JoinHostPort(config.BindHost, strconv.Itoa(config.TLS.PortHTTPS))
|
address := net.JoinHostPort(config.BindHost, strconv.Itoa(config.TLS.PortHTTPS))
|
||||||
// validate current TLS config and update warnings (it could have been loaded from file)
|
// validate current TLS config and update warnings (it could have been loaded from file)
|
||||||
data := validateCertificates(config.TLS)
|
data := validateCertificates(config.TLS.CertificateChain, config.TLS.PrivateKey, config.TLS.ServerName)
|
||||||
if !data.usable {
|
if !data.usable {
|
||||||
log.Fatal(data.WarningValidation)
|
log.Fatal(data.WarningValidation)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
config.Lock()
|
config.Lock()
|
||||||
config.TLS = data // update warnings
|
config.TLS.tlsConfigStatus = data // update warnings
|
||||||
config.Unlock()
|
config.Unlock()
|
||||||
|
|
||||||
// prepare certs for HTTPS server
|
// prepare certs for HTTPS server
|
||||||
|
|
31
control.go
31
control.go
|
@ -1025,7 +1025,7 @@ func handleTLSValidate(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data = validateCertificates(data)
|
data.tlsConfigStatus = validateCertificates(data.CertificateChain, data.PrivateKey, data.ServerName)
|
||||||
marshalTLS(w, data)
|
marshalTLS(w, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1051,7 +1051,7 @@ func handleTLSConfigure(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
restartHTTPS := false
|
restartHTTPS := false
|
||||||
data = validateCertificates(data)
|
data.tlsConfigStatus = validateCertificates(data.CertificateChain, data.PrivateKey, data.ServerName)
|
||||||
if !reflect.DeepEqual(config.TLS.tlsConfigSettings, data.tlsConfigSettings) {
|
if !reflect.DeepEqual(config.TLS.tlsConfigSettings, data.tlsConfigSettings) {
|
||||||
log.Printf("tls config settings have changed, will restart HTTPS server")
|
log.Printf("tls config settings have changed, will restart HTTPS server")
|
||||||
restartHTTPS = true
|
restartHTTPS = true
|
||||||
|
@ -1078,21 +1078,24 @@ func handleTLSConfigure(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateCertificates(data tlsConfig) tlsConfig {
|
/* Process certificate data and its private key.
|
||||||
|
CertificateChain, PrivateKey parameters are optional.
|
||||||
|
On error, return partially set object
|
||||||
|
with 'WarningValidation' field containing error description.
|
||||||
|
*/
|
||||||
|
func validateCertificates(CertificateChain, PrivateKey, ServerName string) tlsConfigStatus {
|
||||||
var err error
|
var err error
|
||||||
|
var data tlsConfigStatus
|
||||||
// clear out status for certificates
|
|
||||||
data.tlsConfigStatus = tlsConfigStatus{}
|
|
||||||
|
|
||||||
// check only public certificate separately from the key
|
// check only public certificate separately from the key
|
||||||
if data.CertificateChain != "" {
|
if CertificateChain != "" {
|
||||||
log.Tracef("got certificate: %s", data.CertificateChain)
|
log.Tracef("got certificate: %s", CertificateChain)
|
||||||
|
|
||||||
// now do a more extended validation
|
// now do a more extended validation
|
||||||
var certs []*pem.Block // PEM-encoded certificates
|
var certs []*pem.Block // PEM-encoded certificates
|
||||||
var skippedBytes []string // skipped bytes
|
var skippedBytes []string // skipped bytes
|
||||||
|
|
||||||
pemblock := []byte(data.CertificateChain)
|
pemblock := []byte(CertificateChain)
|
||||||
for {
|
for {
|
||||||
var decoded *pem.Block
|
var decoded *pem.Block
|
||||||
decoded, pemblock = pem.Decode(pemblock)
|
decoded, pemblock = pem.Decode(pemblock)
|
||||||
|
@ -1127,7 +1130,7 @@ func validateCertificates(data tlsConfig) tlsConfig {
|
||||||
// spew.Dump(parsedCerts)
|
// spew.Dump(parsedCerts)
|
||||||
|
|
||||||
opts := x509.VerifyOptions{
|
opts := x509.VerifyOptions{
|
||||||
DNSName: data.ServerName,
|
DNSName: ServerName,
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("number of certs - %d", len(parsedCerts))
|
log.Printf("number of certs - %d", len(parsedCerts))
|
||||||
|
@ -1164,13 +1167,13 @@ func validateCertificates(data tlsConfig) tlsConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate private key (right now the only validation possible is just parsing it)
|
// validate private key (right now the only validation possible is just parsing it)
|
||||||
if data.PrivateKey != "" {
|
if PrivateKey != "" {
|
||||||
// now do a more extended validation
|
// now do a more extended validation
|
||||||
var key *pem.Block // PEM-encoded certificates
|
var key *pem.Block // PEM-encoded certificates
|
||||||
var skippedBytes []string // skipped bytes
|
var skippedBytes []string // skipped bytes
|
||||||
|
|
||||||
// go through all pem blocks, but take first valid pem block and drop the rest
|
// go through all pem blocks, but take first valid pem block and drop the rest
|
||||||
pemblock := []byte(data.PrivateKey)
|
pemblock := []byte(PrivateKey)
|
||||||
for {
|
for {
|
||||||
var decoded *pem.Block
|
var decoded *pem.Block
|
||||||
decoded, pemblock = pem.Decode(pemblock)
|
decoded, pemblock = pem.Decode(pemblock)
|
||||||
|
@ -1202,8 +1205,8 @@ func validateCertificates(data tlsConfig) tlsConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if both are set, validate both in unison
|
// if both are set, validate both in unison
|
||||||
if data.PrivateKey != "" && data.CertificateChain != "" {
|
if PrivateKey != "" && CertificateChain != "" {
|
||||||
_, err = tls.X509KeyPair([]byte(data.CertificateChain), []byte(data.PrivateKey))
|
_, err = tls.X509KeyPair([]byte(CertificateChain), []byte(PrivateKey))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
data.WarningValidation = fmt.Sprintf("Invalid certificate or key: %s", err)
|
data.WarningValidation = fmt.Sprintf("Invalid certificate or key: %s", err)
|
||||||
return data
|
return data
|
||||||
|
|
|
@ -10,12 +10,10 @@ import (
|
||||||
. Bad private key
|
. Bad private key
|
||||||
. Valid certificate & private key */
|
. Valid certificate & private key */
|
||||||
func TestValidateCertificates(t *testing.T) {
|
func TestValidateCertificates(t *testing.T) {
|
||||||
var data tlsConfig
|
var data tlsConfigStatus
|
||||||
|
|
||||||
// bad cert
|
// bad cert
|
||||||
data.CertificateChain = "bad cert"
|
data = validateCertificates("bad cert", "", "")
|
||||||
data.PrivateKey = ""
|
|
||||||
data = validateCertificates(data)
|
|
||||||
if !(data.WarningValidation != "" &&
|
if !(data.WarningValidation != "" &&
|
||||||
!data.ValidCert &&
|
!data.ValidCert &&
|
||||||
!data.ValidChain) {
|
!data.ValidChain) {
|
||||||
|
@ -23,16 +21,14 @@ func TestValidateCertificates(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// bad priv key
|
// bad priv key
|
||||||
data.CertificateChain = ""
|
data = validateCertificates("", "bad priv key", "")
|
||||||
data.PrivateKey = "bad priv key"
|
|
||||||
data = validateCertificates(data)
|
|
||||||
if !(data.WarningValidation != "" &&
|
if !(data.WarningValidation != "" &&
|
||||||
!data.ValidKey) {
|
!data.ValidKey) {
|
||||||
t.Fatalf("bad priv key: validateCertificates(): %v", data)
|
t.Fatalf("bad priv key: validateCertificates(): %v", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// valid cert & priv key
|
// valid cert & priv key
|
||||||
data.CertificateChain = `-----BEGIN CERTIFICATE-----
|
CertificateChain := `-----BEGIN CERTIFICATE-----
|
||||||
MIICKzCCAZSgAwIBAgIJAMT9kPVJdM7LMA0GCSqGSIb3DQEBCwUAMC0xFDASBgNV
|
MIICKzCCAZSgAwIBAgIJAMT9kPVJdM7LMA0GCSqGSIb3DQEBCwUAMC0xFDASBgNV
|
||||||
BAoMC0FkR3VhcmQgTHRkMRUwEwYDVQQDDAxBZEd1YXJkIEhvbWUwHhcNMTkwMjI3
|
BAoMC0FkR3VhcmQgTHRkMRUwEwYDVQQDDAxBZEd1YXJkIEhvbWUwHhcNMTkwMjI3
|
||||||
MDkyNDIzWhcNNDYwNzE0MDkyNDIzWjAtMRQwEgYDVQQKDAtBZEd1YXJkIEx0ZDEV
|
MDkyNDIzWhcNNDYwNzE0MDkyNDIzWjAtMRQwEgYDVQQKDAtBZEd1YXJkIEx0ZDEV
|
||||||
|
@ -46,7 +42,7 @@ LwlXfbakf7qkVTlCNXgoY7RaJ8rJdPgOZPoCTVToEhT6u/cb1c2qp8QB0dNExDna
|
||||||
b0Z+dnODTZqQOJo6z/wIXlcUrnR4cQVvytXt8lFn+26l6Y6EMI26twC/xWr+1swq
|
b0Z+dnODTZqQOJo6z/wIXlcUrnR4cQVvytXt8lFn+26l6Y6EMI26twC/xWr+1swq
|
||||||
Muj4FeWHVDerquH4yMr1jsYLD3ci+kc5sbIX6TfVxQ==
|
Muj4FeWHVDerquH4yMr1jsYLD3ci+kc5sbIX6TfVxQ==
|
||||||
-----END CERTIFICATE-----`
|
-----END CERTIFICATE-----`
|
||||||
data.PrivateKey = `-----BEGIN PRIVATE KEY-----
|
PrivateKey := `-----BEGIN PRIVATE KEY-----
|
||||||
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALC/BSc8mI68tw5p
|
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALC/BSc8mI68tw5p
|
||||||
aYa7pjrySwWvXeetcFywOWHGVfLw9qiFWLdfESa3Y6tWMpZAXD9t1Xh9n211YUBV
|
aYa7pjrySwWvXeetcFywOWHGVfLw9qiFWLdfESa3Y6tWMpZAXD9t1Xh9n211YUBV
|
||||||
FGSB4ZshnM/tgEPU6t787lJD4NsIIRp++MkJxdAitN4oUTqL0bdpIwezQ/CrYuBX
|
FGSB4ZshnM/tgEPU6t787lJD4NsIIRp++MkJxdAitN4oUTqL0bdpIwezQ/CrYuBX
|
||||||
|
@ -62,7 +58,7 @@ O5EX70gpeGQMPDK0QSWpaazg956njJSDbNCFM4BccrdQbJu1cW4qOsfBAkAMgZuG
|
||||||
O88slmgTRHX4JGFmy3rrLiHNI2BbJSuJ++Yllz8beVzh6NfvuY+HKRCmPqoBPATU
|
O88slmgTRHX4JGFmy3rrLiHNI2BbJSuJ++Yllz8beVzh6NfvuY+HKRCmPqoBPATU
|
||||||
kXS9jgARhhiWXJrk
|
kXS9jgARhhiWXJrk
|
||||||
-----END PRIVATE KEY-----`
|
-----END PRIVATE KEY-----`
|
||||||
data = validateCertificates(data)
|
data = validateCertificates(CertificateChain, PrivateKey, "")
|
||||||
notBefore, _ := time.Parse(time.RFC3339, "2019-02-27T09:24:23Z")
|
notBefore, _ := time.Parse(time.RFC3339, "2019-02-27T09:24:23Z")
|
||||||
notAfter, _ := time.Parse(time.RFC3339, "2046-07-14T09:24:23Z")
|
notAfter, _ := time.Parse(time.RFC3339, "2046-07-14T09:24:23Z")
|
||||||
if !(data.WarningValidation != "" /* self signed */ &&
|
if !(data.WarningValidation != "" /* self signed */ &&
|
||||||
|
|
Loading…
Reference in a new issue