Skip to content
Open
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
5 changes: 5 additions & 0 deletions ssh/certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ func parseTuples(in []byte) (map[string]string, error) {
return tups, nil
}

var errEmptyPrincipal = errors.New("ssh: empty principal in certificate")

func parseCert(in []byte, privAlgo string) (*Certificate, error) {
nonce, rest, ok := parseString(in)
if !ok {
Expand Down Expand Up @@ -217,6 +219,9 @@ func parseCert(in []byte, privAlgo string) (*Certificate, error) {
if !ok {
return nil, errShortRead
}
if len(principal) == 0 {
return nil, errEmptyPrincipal
}
c.ValidPrincipals = append(c.ValidPrincipals, string(principal))
principals = rest
}
Expand Down
51 changes: 51 additions & 0 deletions ssh/certs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"errors"
"fmt"
"io"
"math/big"
Expand Down Expand Up @@ -74,6 +75,56 @@ func TestParseCertNestedSignatureKey(t *testing.T) {
}
}

func TestParseCertEmptyValidPrincipal(t *testing.T) {
signer, err := NewSignerFromKey(testPrivateKeys["ed25519"])
if err != nil {
t.Fatal(err)
}

cert := &Certificate{
Key: signer.PublicKey(),
CertType: UserCert,
ValidPrincipals: []string{""},
ValidBefore: CertTimeInfinity,
}
if err := cert.SignCert(rand.Reader, signer); err != nil {
t.Fatal(err)
}

blob := cert.Marshal()

_, err = ParsePublicKey(blob)
if err == nil {
t.Fatal("ParsePublicKey: expected error for certificate with an empty valid principal, got nil")
}
if !errors.Is(err, errEmptyPrincipal) {
t.Errorf("ParsePublicKey: got error %q, want %q", err, errEmptyPrincipal)
}
}

func TestParseCertNilValidPrincipals(t *testing.T) {
signer, err := NewSignerFromKey(testPrivateKeys["ed25519"])
if err != nil {
t.Fatal(err)
}

cert := &Certificate{
Key: signer.PublicKey(),
CertType: UserCert,
ValidPrincipals: nil,
ValidBefore: CertTimeInfinity,
}
if err := cert.SignCert(rand.Reader, signer); err != nil {
t.Fatal(err)
}

blob := cert.Marshal()

if _, err := ParsePublicKey(blob); err != nil {
t.Fatalf("ParsePublicKey: unexpected error for certificate with nil ValidPrincipals (valid for all): %v", err)
}
}

// Cert generated by ssh-keygen OpenSSH_6.8p1 OS X 10.10.3
// % ssh-keygen -s ca -I testcert -O source-address=192.168.1.0/24 -O force-command=/bin/sleep user.pub
// user.pub key: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDACh1rt2DXfV3hk6fszSQcQ/rueMId0kVD9U7nl8cfEnFxqOCrNT92g4laQIGl2mn8lsGZfTLg8ksHq3gkvgO3oo/0wHy4v32JeBOHTsN5AL4gfHNEhWeWb50ev47hnTsRIt9P4dxogeUo/hTu7j9+s9lLpEQXCvq6xocXQt0j8MV9qZBBXFLXVT3cWIkSqOdwt/5ZBg+1GSrc7WfCXVWgTk4a20uPMuJPxU4RQwZW6X3+O8Pqo8C3cW0OzZRFP6gUYUKUsTI5WntlS+LAxgw1mZNsozFGdbiOPRnEryE3SRldh9vjDR3tin1fGpA5P7+CEB/bqaXtG3V+F2OkqaMN
Expand Down
Loading