Index: ssh/certs_test.go |
=================================================================== |
--- a/ssh/certs_test.go |
+++ b/ssh/certs_test.go |
@@ -6,7 +6,9 @@ |
import ( |
"bytes" |
+ "crypto/rand" |
"testing" |
+ "time" |
) |
// Cert generated by ssh-keygen 6.0p1 Debian-4. |
@@ -16,16 +18,16 @@ |
func TestParseCert(t *testing.T) { |
authKeyBytes := []byte(exampleSSHCert) |
- key, _, _, rest, ok := ParseAuthorizedKey(authKeyBytes) |
- if !ok { |
- t.Fatalf("could not parse certificate") |
+ key, _, _, rest, err := ParseAuthorizedKey(authKeyBytes) |
+ if err != nil { |
+ t.Fatalf("ParseAuthorizedKey: %v", err) |
} |
if len(rest) > 0 { |
t.Errorf("rest: got %q, want empty", rest) |
} |
- if _, ok = key.(*OpenSSHCertV01); !ok { |
- t.Fatalf("got %#v, want *OpenSSHCertV01", key) |
+ if _, ok := key.(*Certificate); !ok { |
+ t.Fatalf("got %#v, want *Certificate", key) |
} |
marshaled := MarshalAuthorizedKey(key) |
@@ -37,19 +39,118 @@ |
} |
} |
-func TestVerifyCert(t *testing.T) { |
- key, _, _, _, _ := ParseAuthorizedKey([]byte(exampleSSHCert)) |
- validCert := key.(*OpenSSHCertV01) |
- if ok := validateOpenSSHCertV01Signature(validCert); !ok { |
- t.Error("Unable to validate certificate!") |
+func TestValidateCert(t *testing.T) { |
+ key, _, _, _, err := ParseAuthorizedKey([]byte(exampleSSHCert)) |
+ if err != nil { |
+ t.Fatalf("ParseAuthorizedKey: %v", err) |
+ } |
+ validCert, ok := key.(*Certificate) |
+ if !ok { |
+ t.Fatalf("got %v (%T), want *Certificate", key, key) |
+ } |
+ checker := CertChecker{} |
+ checker.IsAuthority = func(k PublicKey) bool { |
+ return bytes.Equal(k.Marshal(), validCert.SignatureKey.Marshal()) |
} |
- invalidCert := &OpenSSHCertV01{ |
- Key: rsaKey.PublicKey(), |
- SignatureKey: ecdsaKey.PublicKey(), |
- Signature: &signature{}, |
+ if err := checker.CheckCert("user", validCert); err != nil { |
+ t.Errorf("Unable to validate certificate: %v", err) |
} |
- if ok := validateOpenSSHCertV01Signature(invalidCert); ok { |
- t.Error("Invalid cert signature passed validation!") |
+ invalidCert := &Certificate{ |
+ Key: testPublicKeys["rsa"], |
+ SignatureKey: testPublicKeys["ecdsa"], |
+ ValidBefore: CertTimeInfinity, |
+ Signature: &Signature{}, |
+ } |
+ if err := checker.CheckCert("user", invalidCert); err == nil { |
+ t.Error("Invalid cert signature passed validation") |
} |
} |
+ |
+func TestValidateCertTime(t *testing.T) { |
+ cert := Certificate{ |
+ ValidPrincipals: []string{"user"}, |
+ Key: testPublicKeys["rsa"], |
+ ValidAfter: 50, |
+ ValidBefore: 100, |
+ } |
+ |
+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) |
+ |
+ for ts, ok := range map[int64]bool{ |
+ 25: false, |
+ 50: true, |
+ 99: true, |
+ 100: false, |
+ 125: false, |
+ } { |
+ checker := CertChecker{ |
+ Clock: func() time.Time { return time.Unix(ts, 0) }, |
+ } |
+ checker.IsAuthority = func(k PublicKey) bool { |
+ return bytes.Equal(k.Marshal(), |
+ testPublicKeys["ecdsa"].Marshal()) |
+ } |
+ |
+ if v := checker.CheckCert("user", &cert); (v == nil) != ok { |
+ t.Errorf("Authenticate(%d): %v", ts, v) |
+ } |
+ } |
+} |
+ |
+// TODO(hanwen): tests for |
+// |
+// host keys: |
+// * fallbacks |
+ |
+func TestHostKeyCert(t *testing.T) { |
+ cert := &Certificate{ |
+ ValidPrincipals: []string{"hostname", "hostname.domain"}, |
+ Key: testPublicKeys["rsa"], |
+ ValidBefore: CertTimeInfinity, |
+ CertType: HostCert, |
+ } |
+ cert.SignCert(rand.Reader, testSigners["ecdsa"]) |
+ |
+ checker := &CertChecker{ |
+ IsAuthority: func(p PublicKey) bool { |
+ return bytes.Equal(testPublicKeys["ecdsa"].Marshal(), p.Marshal()) |
+ }, |
+ } |
+ |
+ certSigner, err := NewCertSigner(cert, testSigners["rsa"]) |
+ if err != nil { |
+ t.Errorf("NewCertSigner: %v", err) |
+ } |
+ |
+ for _, name := range []string{"hostname", "otherhost"} { |
+ c1, c2, err := netPipe() |
+ if err != nil { |
+ t.Fatalf("netPipe: %v", err) |
+ } |
+ defer c1.Close() |
+ defer c2.Close() |
+ |
+ go func() { |
+ conf := ServerConfig{ |
+ NoClientAuth: true, |
+ } |
+ conf.AddHostKey(certSigner) |
+ _, _, _, err := NewServerConn(c1, &conf) |
+ if err != nil { |
+ t.Fatalf("NewServerConn: %v", err) |
+ } |
+ }() |
+ |
+ config := &ClientConfig{ |
+ User: "user", |
+ HostKeyCallback: checker.CheckHostKey, |
+ } |
+ _, _, _, err = NewClientConn(c2, name, config) |
+ |
+ succeed := name == "hostname" |
+ if (err == nil) != succeed { |
+ t.Fatalf("NewClientConn(%q): %v", name, err) |
+ } |
+ } |
+} |