From 73dfbc60d34dc610c8f76bb4e876cd84018a9796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= Date: Tue, 24 Jan 2017 17:07:28 +0100 Subject: [PATCH] Canonicalize docker references in signature.VerifyDockerManifestSignature MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After https://github.com/containers/image/pull/220, and especially future https://github.com/containers/image/pull/221, signing docker/distribution/reference.Named.String() would use the new fully-expanded normalization (as opposed to containers/image/docker/reference.Named.String(), which is minimized). For interoperability between various versions and signers, parse and normalize the expected and signed references before comparing them. This should be equivalent to prmMatchExact.matchesDockerReference(). Signed-off-by: Miloslav Trmač --- signature/docker.go | 11 ++++++++++- signature/docker_test.go | 17 +++++++++++++++++ signature/fixtures/invalid-reference.signature | Bin 0 -> 422 bytes 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 signature/fixtures/invalid-reference.signature diff --git a/signature/docker.go b/signature/docker.go index b2126be656..901a225a29 100644 --- a/signature/docker.go +++ b/signature/docker.go @@ -5,6 +5,7 @@ package signature import ( "fmt" + "github.com/containers/image/docker/reference" "github.com/containers/image/manifest" "github.com/opencontainers/go-digest" ) @@ -24,6 +25,10 @@ func SignDockerManifest(m []byte, dockerReference string, mech SigningMechanism, // using mech. func VerifyDockerManifestSignature(unverifiedSignature, unverifiedManifest []byte, expectedDockerReference string, mech SigningMechanism, expectedKeyIdentity string) (*Signature, error) { + expectedRef, err := reference.ParseNamed(expectedDockerReference) + if err != nil { + return nil, err + } sig, err := verifyAndExtractSignature(mech, unverifiedSignature, signatureAcceptanceRules{ validateKeyIdentity: func(keyIdentity string) error { if keyIdentity != expectedKeyIdentity { @@ -32,7 +37,11 @@ func VerifyDockerManifestSignature(unverifiedSignature, unverifiedManifest []byt return nil }, validateSignedDockerReference: func(signedDockerReference string) error { - if signedDockerReference != expectedDockerReference { + signedRef, err := reference.ParseNamed(signedDockerReference) + if err != nil { + return InvalidSignatureError{msg: fmt.Sprintf("Invalid docker reference %s in signature", signedDockerReference)} + } + if signedRef.String() != expectedRef.String() { return InvalidSignatureError{msg: fmt.Sprintf("Docker reference %s does not match %s", signedDockerReference, expectedDockerReference)} } diff --git a/signature/docker_test.go b/signature/docker_test.go index 766fb0363d..6d2f0b3d71 100644 --- a/signature/docker_test.go +++ b/signature/docker_test.go @@ -52,8 +52,19 @@ func TestVerifyDockerManifestSignature(t *testing.T) { assert.Equal(t, TestImageSignatureReference, sig.DockerReference) assert.Equal(t, TestImageManifestDigest, sig.DockerManifestDigest) + // Verification using a different canonicalization of TestImageSignatureReference + sig, err = VerifyDockerManifestSignature(signature, manifest, "docker.io/"+TestImageSignatureReference, mech, TestKeyFingerprint) + require.NoError(t, err) + assert.Equal(t, TestImageSignatureReference, sig.DockerReference) + assert.Equal(t, TestImageManifestDigest, sig.DockerManifestDigest) + // For extra paranoia, test that we return nil data on error. + // Invalid docker reference on input + sig, err = VerifyDockerManifestSignature(signature, manifest, "UPPERCASEISINVALID", mech, TestKeyFingerprint) + assert.Error(t, err) + assert.Nil(t, sig) + // Error computing Docker manifest invalidManifest, err := ioutil.ReadFile("fixtures/v2s1-invalid-signatures.manifest.json") require.NoError(t, err) @@ -72,6 +83,12 @@ func TestVerifyDockerManifestSignature(t *testing.T) { assert.Error(t, err) assert.Nil(t, sig) + // Invalid reference in the signature + invalidReferenceSignature, err := ioutil.ReadFile("fixtures/invalid-reference.signature") + sig, err = VerifyDockerManifestSignature(invalidReferenceSignature, manifest, TestImageSignatureReference, mech, TestKeyFingerprint) + assert.Error(t, err) + assert.Nil(t, sig) + // Docker reference mismatch sig, err = VerifyDockerManifestSignature(signature, manifest, "example.com/doesnt/match", mech, TestKeyFingerprint) assert.Error(t, err) diff --git a/signature/fixtures/invalid-reference.signature b/signature/fixtures/invalid-reference.signature new file mode 100644 index 0000000000000000000000000000000000000000..0236598301edcba98d3f89bbccee2aaad15359b6 GIT binary patch literal 422 zcmV;X0a^Z|0h_?f%)rEWyXccd_m-R!jHeF-Cox2{mnl>$B^PCuWF{x(C|Ol2Wu~O& zm1LGwg4ikf$=Rtzx<#pJsYR)I$*D?KN}&M(u0hU@!LFXco_=ADKAtX0wK__fxryni zNIG&8^D@&?i%WDXZSvW2;& zX`*>jYNDZ;k(s5XVOmO}nSpVtL5hK4l1Zw0nwf!#k$I}ADaf*t$^wu}5=-)PGm{mP z^Ycm)GxJi56pAy`^Abx+i&8;~@(W5b^Yb8HN-jzTDlS6kQ34v0nG1ASVs3$wm7$5L zg^{tPxuJ1wEmy}J76wKp1~yhEP|z@NaSFf!%wQq&|8$Q=T^&K+AJ_UH3HK}x-1sWU zqsKo#@`~v*(akr+t~AADy$M>hRG>mo{QS>(8