Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SHA256 thumbprint based vCenter authentication #3384

Merged
merged 1 commit into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion govc/about/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (r *certResult) Write(w io.Writer) error {

if r.cmd.thumbprint {
u := r.cmd.Session.URL
_, err := fmt.Fprintf(w, "%s %s\n", u.Host, r.info.ThumbprintSHA1)
_, err := fmt.Fprintf(w, "%s %s\n", u.Host, r.info.ThumbprintSHA256)
return err
}

Expand Down
8 changes: 7 additions & 1 deletion govc/test/cli.bats
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ load test_helper
run govc about.cert -show
assert_success

# with -k=true we get thumbprint output and exit 0
# with -k=true we get sha256 thumbprint output and exit 0
thumbprint=$(govc about.cert -k=true -thumbprint)

# with -k=true we get thumbprint output and exit 60
Expand All @@ -77,6 +77,12 @@ load test_helper

run govc about -k=false -tls-known-hosts <(echo "nope nope")
assert_failure

# sha1 backwards compatibility
host=$(awk '{print $1}'<<<"$thumbprint")
sha1=$(govc about.cert -k=true -json | jq -r .thumbprintSHA1)
run govc about -k=false -tls-known-hosts <(echo "$host $sha1")
assert_success
}

@test "version" {
Expand Down
10 changes: 1 addition & 9 deletions object/host_certificate_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
package object

import (
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
Expand Down Expand Up @@ -58,14 +57,7 @@ func (info *HostCertificateInfo) FromCertificate(cert *x509.Certificate) *HostCe
info.Subject = info.fromName(info.subjectName)

info.ThumbprintSHA1 = soap.ThumbprintSHA1(cert)

// SHA-256 for info purposes only, API fields all use SHA-1
sum := sha256.Sum256(cert.Raw)
hex := make([]string, len(sum))
for i, b := range sum {
hex[i] = fmt.Sprintf("%02X", b)
}
info.ThumbprintSHA256 = strings.Join(hex, ":")
info.ThumbprintSHA256 = soap.ThumbprintSHA256(cert)

if info.Status == "" {
info.Status = string(types.HostCertificateManagerCertificateInfoCertificateStatusUnknown)
Expand Down
26 changes: 20 additions & 6 deletions vim25/soap/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"bytes"
"context"
"crypto/sha1"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"encoding/json"
Expand Down Expand Up @@ -387,6 +388,20 @@ func ThumbprintSHA1(cert *x509.Certificate) string {
return strings.Join(hex, ":")
}

// ThumbprintSHA256 returns the sha256 thumbprint of the given cert.
func ThumbprintSHA256(cert *x509.Certificate) string {
sum := sha256.Sum256(cert.Raw)
hex := make([]string, len(sum))
for i, b := range sum {
hex[i] = fmt.Sprintf("%02X", b)
}
return strings.Join(hex, ":")
}

func thumbprintMatches(thumbprint string, cert *x509.Certificate) bool {
return thumbprint == ThumbprintSHA256(cert) || thumbprint == ThumbprintSHA1(cert)
}

func (c *Client) dialTLSContext(
ctx context.Context,
network, addr string) (net.Conn, error) {
Expand Down Expand Up @@ -418,14 +433,13 @@ func (c *Client) dialTLSContext(
}

cert := conn.ConnectionState().PeerCertificates[0]
peer := ThumbprintSHA1(cert)
if thumbprint != peer {
_ = conn.Close()

return nil, fmt.Errorf("host %q thumbprint does not match %q", addr, thumbprint)
if thumbprintMatches(thumbprint, cert) {
return conn, nil
}

return conn, nil
_ = conn.Close()

return nil, fmt.Errorf("host %q thumbprint does not match %q", addr, thumbprint)
}

// splitHostPort is similar to net.SplitHostPort,
Expand Down
Loading