Skip to content

Commit

Permalink
advancedtls: add min/max TLS version option
Browse files Browse the repository at this point in the history
  • Loading branch information
ZhenLian authored and joeljeske committed Feb 4, 2023
1 parent 3151e83 commit fe1c6e0
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
29 changes: 29 additions & 0 deletions security/advancedtls/advancedtls.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,19 @@ const (
SkipVerification
)

// TLSVersionOptions contains the TLS version requirements for a client/server.
type TLSVersionOptions struct {
// MinVersion contains the minimum TLS version that is acceptable.
// By default, TLS 1.2 is currently used as the minimum when acting as a
// client, and TLS 1.0 when acting as a server. TLS 1.0 is the minimum
// supported by this package, both as a client and as a server.
MinVersion uint16
// MaxVersion contains the maximum TLS version that is acceptable.
// By default, the maximum version supported by this package is used,
// which is currently TLS 1.3.
MaxVersion uint16
}

// ClientOptions contains the fields needed to be filled by the client.
type ClientOptions struct {
// IdentityOptions is OPTIONAL on client side. This field only needs to be
Expand All @@ -184,6 +197,9 @@ type ClientOptions struct {
// RevocationConfig is the configurations for certificate revocation checks.
// It could be nil if such checks are not needed.
RevocationConfig *RevocationConfig
// VersionOptions contains the requirements for the TLS version being used.
// If not set, the default values would be used.
VersionOptions TLSVersionOptions
}

// ServerOptions contains the fields needed to be filled by the server.
Expand All @@ -205,6 +221,9 @@ type ServerOptions struct {
// RevocationConfig is the configurations for certificate revocation checks.
// It could be nil if such checks are not needed.
RevocationConfig *RevocationConfig
// VersionOptions contains the requirements for the TLS version being used.
// If not set, the default values would be used.
VersionOptions TLSVersionOptions
}

func (o *ClientOptions) config() (*tls.Config, error) {
Expand All @@ -222,11 +241,16 @@ func (o *ClientOptions) config() (*tls.Config, error) {
if o.IdentityOptions.GetIdentityCertificatesForServer != nil {
return nil, fmt.Errorf("GetIdentityCertificatesForServer cannot be specified on the client side")
}
if o.VersionOptions.MinVersion > o.VersionOptions.MaxVersion {
return nil, fmt.Errorf("the minimum TLS version is larger than maximum TLS version")
}
config := &tls.Config{
ServerName: o.ServerNameOverride,
// We have to set InsecureSkipVerify to true to skip the default checks and
// use the verification function we built from buildVerifyFunc.
InsecureSkipVerify: true,
MinVersion: o.VersionOptions.MinVersion,
MaxVersion: o.VersionOptions.MaxVersion,
}
// Propagate root-certificate-related fields in tls.Config.
switch {
Expand Down Expand Up @@ -293,6 +317,9 @@ func (o *ServerOptions) config() (*tls.Config, error) {
if o.IdentityOptions.GetIdentityCertificatesForClient != nil {
return nil, fmt.Errorf("GetIdentityCertificatesForClient cannot be specified on the server side")
}
if o.VersionOptions.MinVersion > o.VersionOptions.MaxVersion {
return nil, fmt.Errorf("Minumum TLS version is larger than maximum TLS version")
}
clientAuth := tls.NoClientCert
if o.RequireClientCert {
// We have to set clientAuth to RequireAnyClientCert to force underlying
Expand All @@ -302,6 +329,8 @@ func (o *ServerOptions) config() (*tls.Config, error) {
}
config := &tls.Config{
ClientAuth: clientAuth,
MinVersion: o.VersionOptions.MinVersion,
MaxVersion: o.VersionOptions.MaxVersion,
}
// Propagate root-certificate-related fields in tls.Config.
switch {
Expand Down
30 changes: 30 additions & 0 deletions security/advancedtls/advancedtls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func (s) TestClientOptionsConfigErrorCases(t *testing.T) {
clientVType VerificationType
IdentityOptions IdentityCertificateOptions
RootOptions RootCertificateOptions
VersionOptions TLSVersionOptions
}{
{
desc: "Skip default verification and provide no root credentials",
Expand Down Expand Up @@ -122,6 +123,13 @@ func (s) TestClientOptionsConfigErrorCases(t *testing.T) {
},
},
},
{
desc: "Invalid min/max TLS versions",
VersionOptions: TLSVersionOptions{
MinVersion: tls.VersionTLS13,
MaxVersion: tls.VersionTLS12,
},
},
}
for _, test := range tests {
test := test
Expand All @@ -130,6 +138,7 @@ func (s) TestClientOptionsConfigErrorCases(t *testing.T) {
VType: test.clientVType,
IdentityOptions: test.IdentityOptions,
RootOptions: test.RootOptions,
VersionOptions: test.VersionOptions,
}
_, err := clientOptions.config()
if err == nil {
Expand All @@ -145,6 +154,7 @@ func (s) TestClientOptionsConfigSuccessCases(t *testing.T) {
clientVType VerificationType
IdentityOptions IdentityCertificateOptions
RootOptions RootCertificateOptions
VersionOptions TLSVersionOptions
}{
{
desc: "Use system default if no fields in RootCertificateOptions is specified",
Expand All @@ -159,6 +169,10 @@ func (s) TestClientOptionsConfigSuccessCases(t *testing.T) {
IdentityOptions: IdentityCertificateOptions{
IdentityProvider: fakeProvider{pt: provTypeIdentity},
},
VersionOptions: TLSVersionOptions{
MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS13,
},
},
}
for _, test := range tests {
Expand All @@ -168,6 +182,7 @@ func (s) TestClientOptionsConfigSuccessCases(t *testing.T) {
VType: test.clientVType,
IdentityOptions: test.IdentityOptions,
RootOptions: test.RootOptions,
VersionOptions: test.VersionOptions,
}
clientConfig, err := clientOptions.config()
if err != nil {
Expand All @@ -192,6 +207,7 @@ func (s) TestServerOptionsConfigErrorCases(t *testing.T) {
serverVType VerificationType
IdentityOptions IdentityCertificateOptions
RootOptions RootCertificateOptions
VersionOptions TLSVersionOptions
}{
{
desc: "Skip default verification and provide no root credentials",
Expand Down Expand Up @@ -229,6 +245,13 @@ func (s) TestServerOptionsConfigErrorCases(t *testing.T) {
},
},
},
{
desc: "Invalid min/max TLS versions",
VersionOptions: TLSVersionOptions{
MinVersion: tls.VersionTLS13,
MaxVersion: tls.VersionTLS12,
},
},
}
for _, test := range tests {
test := test
Expand All @@ -238,6 +261,7 @@ func (s) TestServerOptionsConfigErrorCases(t *testing.T) {
RequireClientCert: test.requireClientCert,
IdentityOptions: test.IdentityOptions,
RootOptions: test.RootOptions,
VersionOptions: test.VersionOptions,
}
_, err := serverOptions.config()
if err == nil {
Expand All @@ -254,6 +278,7 @@ func (s) TestServerOptionsConfigSuccessCases(t *testing.T) {
serverVType VerificationType
IdentityOptions IdentityCertificateOptions
RootOptions RootCertificateOptions
VersionOptions TLSVersionOptions
}{
{
desc: "Use system default if no fields in RootCertificateOptions is specified",
Expand All @@ -275,6 +300,10 @@ func (s) TestServerOptionsConfigSuccessCases(t *testing.T) {
return nil, nil
},
},
VersionOptions: TLSVersionOptions{
MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS13,
},
},
}
for _, test := range tests {
Expand All @@ -285,6 +314,7 @@ func (s) TestServerOptionsConfigSuccessCases(t *testing.T) {
RequireClientCert: test.requireClientCert,
IdentityOptions: test.IdentityOptions,
RootOptions: test.RootOptions,
VersionOptions: test.VersionOptions,
}
serverConfig, err := serverOptions.config()
if err != nil {
Expand Down

0 comments on commit fe1c6e0

Please sign in to comment.