diff --git a/internal/arduino/resources/resources_test.go b/internal/arduino/resources/resources_test.go index 0ca1bdd884b..3cd1d7a0098 100644 --- a/internal/arduino/resources/resources_test.go +++ b/internal/arduino/resources/resources_test.go @@ -131,29 +131,45 @@ func TestIndexDownloadAndSignatureWithinArchive(t *testing.T) { require.NoError(t, err) defer ln.Close() go server.Serve(ln) + defer server.Close() - validIdxURL, err := url.Parse("http://" + ln.Addr().String() + "/valid/package_index.tar.bz2") - require.NoError(t, err) - idxResource := &IndexResource{URL: validIdxURL} - destDir, err := paths.MkTempDir("", "") - require.NoError(t, err) - defer destDir.RemoveAll() - err = idxResource.Download(ctx, destDir, func(curr *rpc.DownloadProgress) {}, downloader.GetDefaultConfig()) - require.NoError(t, err) - require.True(t, destDir.Join("package_index.json").Exist()) - require.True(t, destDir.Join("package_index.json.sig").Exist()) - - invalidIdxURL, err := url.Parse("http://" + ln.Addr().String() + "/invalid/package_index.tar.bz2") - require.NoError(t, err) - invIdxResource := &IndexResource{URL: invalidIdxURL} - invDestDir, err := paths.MkTempDir("", "") - require.NoError(t, err) - defer invDestDir.RemoveAll() - err = invIdxResource.Download(ctx, invDestDir, func(curr *rpc.DownloadProgress) {}, downloader.GetDefaultConfig()) - require.Error(t, err) - require.Contains(t, err.Error(), "invalid signature") - require.False(t, invDestDir.Join("package_index.json").Exist()) - require.False(t, invDestDir.Join("package_index.json.sig").Exist()) + { + validIdxURL, err := url.Parse("http://" + ln.Addr().String() + "/valid_signature_in_the_future/package_index.tar.bz2") + require.NoError(t, err) + idxResource := &IndexResource{URL: validIdxURL} + destDir, err := paths.MkTempDir("", "") + require.NoError(t, err) + defer destDir.RemoveAll() + err = idxResource.Download(ctx, destDir, func(curr *rpc.DownloadProgress) {}, downloader.GetDefaultConfig()) + require.ErrorContains(t, err, "is your system clock set correctly?") + require.False(t, destDir.Join("package_index.json").Exist()) + require.False(t, destDir.Join("package_index.json.sig").Exist()) + } + { + validIdxURL, err := url.Parse("http://" + ln.Addr().String() + "/valid/package_index.tar.bz2") + require.NoError(t, err) + idxResource := &IndexResource{URL: validIdxURL} + destDir, err := paths.MkTempDir("", "") + require.NoError(t, err) + defer destDir.RemoveAll() + err = idxResource.Download(ctx, destDir, func(curr *rpc.DownloadProgress) {}, downloader.GetDefaultConfig()) + require.NoError(t, err) + require.True(t, destDir.Join("package_index.json").Exist()) + require.True(t, destDir.Join("package_index.json.sig").Exist()) + } + { + invalidIdxURL, err := url.Parse("http://" + ln.Addr().String() + "/invalid/package_index.tar.bz2") + require.NoError(t, err) + invIdxResource := &IndexResource{URL: invalidIdxURL} + invDestDir, err := paths.MkTempDir("", "") + require.NoError(t, err) + defer invDestDir.RemoveAll() + err = invIdxResource.Download(ctx, invDestDir, func(curr *rpc.DownloadProgress) {}, downloader.GetDefaultConfig()) + require.Error(t, err) + require.Contains(t, err.Error(), "invalid signature") + require.False(t, invDestDir.Join("package_index.json").Exist()) + require.False(t, invDestDir.Join("package_index.json.sig").Exist()) + } } func TestIndexFileName(t *testing.T) { diff --git a/internal/arduino/resources/testdata/valid_signature_in_the_future/package_index.tar.bz2 b/internal/arduino/resources/testdata/valid_signature_in_the_future/package_index.tar.bz2 new file mode 100644 index 00000000000..22284c67be4 Binary files /dev/null and b/internal/arduino/resources/testdata/valid_signature_in_the_future/package_index.tar.bz2 differ diff --git a/internal/arduino/security/signatures.go b/internal/arduino/security/signatures.go index fb6ed9b0697..ebd86e4a037 100644 --- a/internal/arduino/security/signatures.go +++ b/internal/arduino/security/signatures.go @@ -16,12 +16,14 @@ package security import ( + "bytes" "embed" "errors" "io" "os" "github.com/ProtonMail/go-crypto/openpgp" + pgperrors "github.com/ProtonMail/go-crypto/openpgp/errors" "github.com/arduino/arduino-cli/internal/i18n" "github.com/arduino/go-paths-helper" ) @@ -71,16 +73,19 @@ func VerifySignature(targetPath *paths.Path, signaturePath *paths.Path, arduinoK if err != nil { return false, nil, errors.New(i18n.Tr("retrieving Arduino public keys: %s", err)) } - target, err := targetPath.Open() + target, err := targetPath.ReadFile() if err != nil { return false, nil, errors.New(i18n.Tr("opening target file: %s", err)) } - defer target.Close() - signature, err := signaturePath.Open() + signature, err := signaturePath.ReadFile() if err != nil { return false, nil, errors.New(i18n.Tr("opening signature file: %s", err)) } - defer signature.Close() - signer, err := openpgp.CheckDetachedSignature(keyRing, target, signature, nil) + signer, err := openpgp.CheckDetachedSignature(keyRing, bytes.NewBuffer(target), bytes.NewBuffer(signature), nil) + + if errors.Is(err, pgperrors.ErrSignatureExpired) { + err = errors.New(i18n.Tr("signature expired: is your system clock set correctly?")) + } + return (signer != nil && err == nil), signer, err }
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: