2023-03-01 21:28:48 +00:00
|
|
|
package inspect
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/tls"
|
|
|
|
"fmt"
|
2023-04-29 10:56:58 +01:00
|
|
|
"strconv"
|
2023-03-01 21:28:48 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// ConnectionState returns a set of information about a TLS ConnectionState.
|
|
|
|
func ConnectionState(c tls.ConnectionState) []Info {
|
|
|
|
var info = []Info{
|
|
|
|
&TLSConnectionState{
|
|
|
|
Version: c.Version,
|
|
|
|
CipherSuite: c.CipherSuite,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for i, cert := range c.PeerCertificates {
|
|
|
|
loc := "leaf certificate"
|
|
|
|
if i > 0 {
|
|
|
|
loc = fmt.Sprintf("intermediate certificate #%d", i)
|
|
|
|
}
|
|
|
|
info = append(info, CertificateInfo(loc, cert))
|
|
|
|
}
|
|
|
|
|
|
|
|
return info
|
|
|
|
}
|
|
|
|
|
|
|
|
// TLSSecurity provides an indicative security assessment of a negotiated TLS
|
|
|
|
// connection.
|
|
|
|
type TLSSecurity int
|
|
|
|
|
|
|
|
const (
|
|
|
|
TLSSecurityStrong = iota
|
|
|
|
TLSSecurityWeak
|
|
|
|
TLSSecurityInsecure
|
|
|
|
)
|
|
|
|
|
|
|
|
func (ts TLSSecurity) String() string {
|
|
|
|
switch ts {
|
|
|
|
case TLSSecurityStrong:
|
|
|
|
return "strong"
|
|
|
|
case TLSSecurityWeak:
|
|
|
|
return "weak"
|
|
|
|
case TLSSecurityInsecure:
|
|
|
|
return "insecure"
|
|
|
|
}
|
|
|
|
return "???"
|
|
|
|
}
|
|
|
|
|
2023-04-29 10:56:58 +01:00
|
|
|
// MarshalJSON returns a quoted string.
|
|
|
|
func (ts TLSSecurity) MarshalJSON() ([]byte, error) {
|
|
|
|
return strconv.AppendQuote(nil, ts.String()), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalYAML returns a string.
|
|
|
|
func (ts TLSSecurity) MarshalYAML() (any, error) {
|
|
|
|
return ts.String(), nil
|
|
|
|
}
|
|
|
|
|
2023-03-01 21:28:48 +00:00
|
|
|
// TLSConnectionState holds structured information about a negotiated TLS
|
|
|
|
// connection. It does not include the peer's certificate information.
|
|
|
|
type TLSConnectionState struct {
|
|
|
|
// Version of TLS protocol used.
|
|
|
|
Version uint16
|
|
|
|
|
|
|
|
// CipherSuite negotiated.
|
|
|
|
CipherSuite uint16
|
|
|
|
}
|
|
|
|
|
2023-04-29 10:50:18 +01:00
|
|
|
// Type indicates this is a TLS connection type.
|
2023-03-01 21:28:48 +00:00
|
|
|
func (tcs *TLSConnectionState) Type() Type {
|
|
|
|
return TypeTLSConnectionState
|
|
|
|
}
|
|
|
|
|
2023-04-29 10:50:18 +01:00
|
|
|
// Location returns the location data stored by TLSConnectionState.
|
2023-03-01 21:28:48 +00:00
|
|
|
func (tcs *TLSConnectionState) Location() string {
|
|
|
|
return "TLS handshake"
|
|
|
|
}
|
|
|
|
|
2023-04-29 10:50:18 +01:00
|
|
|
// Info returns structured information about the TLS connection.
|
2023-03-01 21:28:48 +00:00
|
|
|
func (tcs *TLSConnectionState) Info() []Section {
|
|
|
|
var security TLSSecurity = TLSSecurityStrong
|
|
|
|
|
|
|
|
ciphersuite := tls.CipherSuiteName(tcs.CipherSuite)
|
|
|
|
|
|
|
|
switch tcs.CipherSuite {
|
|
|
|
case tls.TLS_RSA_WITH_RC4_128_SHA,
|
|
|
|
tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
|
|
|
|
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
|
|
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
|
|
tls.TLS_RSA_WITH_AES_128_CBC_SHA256,
|
|
|
|
tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
|
|
|
|
tls.TLS_RSA_WITH_AES_256_GCM_SHA384:
|
|
|
|
// using plain RSA for key exchange isn't good
|
|
|
|
security = TLSSecurityInsecure
|
|
|
|
|
|
|
|
case tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
|
|
|
tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
|
|
|
|
// broken/bad symmetric ciphers
|
|
|
|
security = TLSSecurityInsecure
|
|
|
|
|
|
|
|
case tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
|
|
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
|
|
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
|
|
|
|
// CBC now considered weaker
|
|
|
|
security = TLSSecurityWeak
|
|
|
|
|
|
|
|
default:
|
|
|
|
// allow Go's opinion to augment our own
|
|
|
|
for _, bad := range tls.InsecureCipherSuites() {
|
|
|
|
if tcs.CipherSuite == bad.ID {
|
|
|
|
security = TLSSecurityInsecure
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var version string
|
|
|
|
switch tcs.Version {
|
|
|
|
case tls.VersionTLS10:
|
|
|
|
version = "TLSv1.0"
|
|
|
|
security = TLSSecurityInsecure
|
|
|
|
case tls.VersionTLS11:
|
|
|
|
version = "TLSv1.1"
|
|
|
|
security = TLSSecurityInsecure
|
|
|
|
case tls.VersionTLS12:
|
|
|
|
version = "TLSv1.2"
|
|
|
|
case tls.VersionTLS13:
|
|
|
|
version = "TLSv1.3"
|
|
|
|
}
|
|
|
|
|
|
|
|
return []Section{
|
|
|
|
Section{
|
|
|
|
Title: "TLS protocol negotatiated",
|
|
|
|
Fields: []Field{
|
|
|
|
Field{
|
|
|
|
Key: "Version",
|
|
|
|
Value: version,
|
|
|
|
},
|
|
|
|
Field{
|
|
|
|
Key: "Cipher suite",
|
|
|
|
Value: ciphersuite,
|
|
|
|
},
|
|
|
|
Field{
|
|
|
|
Key: "Security",
|
|
|
|
Value: security,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|