mesh/merge-gate head 6312bc421964 merged into trunk c294f7bd16dc — pass: builds brother → shanks; no bus step; every machine composes with the change as it…
mesh/repo-check head 6312bc421964 merged into trunk c294f7bd16dc — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered
106 lines
3.9 KiB
Go
106 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/pem"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// Captured from the printer 2026-10-20 (testdata/pin): it serves two self-signed certificates for one name, an
|
|
// ECDSA one to a client offering ECDSA and an RSA one to a client offering RSA only (issue 1503).
|
|
const (
|
|
printerECDSAPrint = "EA:B4:B7:0F:96:CD:A6:2B:61:53:2E:F0:A8:D6:9F:42:EA:9F:66:0A:82:5B:C2:43:0B:97:C5:9A:7A:B4:18:5B"
|
|
printerRSAPrint = "7A:3D:E2:A4:1E:AB:A9:7B:E6:61:0A:C4:18:DD:68:FF:9B:A5:77:E8:02:7F:7E:F8:97:D0:3B:82:A2:89:7D:F4"
|
|
)
|
|
|
|
func capturedDER(t *testing.T, name string) []byte {
|
|
t.Helper()
|
|
raw, err := os.ReadFile("testdata/pin/" + name)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
b, _ := pem.Decode(raw)
|
|
if b == nil {
|
|
t.Fatalf("%s is not PEM", name)
|
|
}
|
|
return b.Bytes
|
|
}
|
|
|
|
// 1503/AC1: the two captured certificates have the two fingerprints, and a pin listing both accepts each.
|
|
func TestThePrintersTwoCapturedCertificatesAreBothAcceptedByAPinListingBoth(t *testing.T) {
|
|
both := printerECDSAPrint + ", " + printerRSAPrint
|
|
for file, want := range map[string]string{"ecdsa.pem": printerECDSAPrint, "rsa.pem": printerRSAPrint} {
|
|
der := capturedDER(t, file)
|
|
if got := Fingerprint(der); got != want {
|
|
t.Fatalf("%s has fingerprint %s, want %s", file, got, want)
|
|
}
|
|
if err := pinned(both)([][]byte{der}, nil); err != nil {
|
|
t.Errorf("%s refused by a pin listing both: %v", file, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 1503/AC1: a server presenting one certificate is accepted when the pin lists its fingerprint among two.
|
|
func TestAPinListingTwoFingerprintsAcceptsTheCertificateTheServerPresents(t *testing.T) {
|
|
f := newFakePrinter(t, "B1891", "hunter2")
|
|
a, err := NewAdmin(f.host(), printerECDSAPrint+","+f.print(), "hunter2")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := a.Login(context.Background()); err != nil {
|
|
t.Fatalf("a pin listing the served certificate was refused: %v", err)
|
|
}
|
|
}
|
|
|
|
// 1503/AC2: a pin that lists only another certificate still refuses, and names every pinned fingerprint.
|
|
func TestAPinListingOnlyOtherCertificatesStillRefuses(t *testing.T) {
|
|
f := newFakePrinter(t, "B1891", "hunter2")
|
|
a, _ := NewAdmin(f.host(), printerECDSAPrint+" , "+printerRSAPrint, "hunter2")
|
|
err := a.Login(context.Background())
|
|
if err == nil {
|
|
t.Fatal("a certificate that is in no pinned fingerprint was accepted")
|
|
}
|
|
for _, want := range []string{f.print(), printerECDSAPrint, printerRSAPrint} {
|
|
if !strings.Contains(err.Error(), want) {
|
|
t.Errorf("error %q does not name %s", err, want)
|
|
}
|
|
}
|
|
if len(f.requests) != 0 {
|
|
t.Errorf("the server was sent %v", f.requests)
|
|
}
|
|
}
|
|
|
|
// 1503/AC1: a single fingerprint is still a valid pin, in either case.
|
|
func TestASingleFingerprintStillPins(t *testing.T) {
|
|
der := capturedDER(t, "rsa.pem")
|
|
for _, p := range []string{printerRSAPrint, strings.ToLower(printerRSAPrint), " " + printerRSAPrint + " "} {
|
|
if err := pinned(p)([][]byte{der}, nil); err != nil {
|
|
t.Errorf("pin %q refused: %v", p, err)
|
|
}
|
|
}
|
|
if err := pinned(printerECDSAPrint)([][]byte{der}, nil); err == nil {
|
|
t.Error("the other certificate's pin accepted the RSA certificate")
|
|
}
|
|
}
|
|
|
|
// 1503/AC3: the manifest's pattern takes one or more fingerprints, separated by commas and optional spaces, and
|
|
// nothing else.
|
|
func TestThePrinterCertificatePatternTakesACommaSeparatedList(t *testing.T) {
|
|
m := readManifest(t)
|
|
re := regexp.MustCompile(`^(?:` + m.Config["printer-certificate"]["pattern"].(string) + `)$`)
|
|
for _, ok := range []string{printerRSAPrint, printerECDSAPrint + "," + printerRSAPrint, printerECDSAPrint + ", " + printerRSAPrint} {
|
|
if !re.MatchString(ok) {
|
|
t.Errorf("pattern refuses %q", ok)
|
|
}
|
|
}
|
|
for _, bad := range []string{"", printerRSAPrint + ",", "," + printerRSAPrint, printerECDSAPrint + printerRSAPrint,
|
|
printerECDSAPrint + ",," + printerRSAPrint, printerECDSAPrint + ";" + printerRSAPrint, printerRSAPrint + ",EAB4", strings.ToLower(printerRSAPrint)} {
|
|
if re.MatchString(bad) {
|
|
t.Errorf("pattern admits %q", bad)
|
|
}
|
|
}
|
|
}
|