Skip to content

Commit

Permalink
Merge pull request #3384 from dougm/thumbprint-sha256
Browse files Browse the repository at this point in the history
Add support for SHA256 thumbprint based vCenter authentication
  • Loading branch information
dougm authored Mar 11, 2024
2 parents 1fb3f62 + 8bfb252 commit d62c0ac
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 17 deletions.
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

0 comments on commit d62c0ac

Please sign in to comment.