@@ -2,9 +2,6 @@ package storage
22
33import (
44 "context"
5- "crypto"
6- "encoding/json"
7- "io"
85 "io/fs"
96 "path/filepath"
107 "strings"
@@ -30,64 +27,24 @@ func SignatureZipFilename(manifest *VSIXManifest) string {
3027
3128// Signature is a storage wrapper that can sign extensions on demand.
3229type Signature struct {
33- // Signer if provided, will be used to sign extensions. If not provided,
34- // no extensions will be signed.
35- Signer crypto.Signer
36- Logger slog.Logger
37- // SaveSigZips is a flag that will save the signed extension to disk.
38- // This is useful for debugging, but the server will never use this file.
39- saveSigZips bool
30+ Logger slog.Logger
31+ IncludeEmptySignatures bool
4032 Storage
4133}
4234
43- func NewSignatureStorage (logger slog.Logger , signer crypto.Signer , s Storage ) * Signature {
44- return & Signature {
45- Signer : signer ,
46- Storage : s ,
35+ func NewSignatureStorage (logger slog.Logger , includeEmptySignatures bool , s Storage ) * Signature {
36+ if includeEmptySignatures {
37+ logger .Info (context .Background (), "Signature storage enabled, if using VSCode on Windows, this will not work." )
4738 }
48- }
49-
50- func (s * Signature ) SaveSigZips () {
51- if ! s .saveSigZips {
52- s .Logger .Info (context .Background (), "extension signatures will be saved to disk, do not use this in production" )
39+ return & Signature {
40+ Logger : logger ,
41+ IncludeEmptySignatures : includeEmptySignatures ,
42+ Storage : s ,
5343 }
54- s .saveSigZips = true
5544}
5645
5746func (s * Signature ) SigningEnabled () bool {
58- return s .Signer != nil
59- }
60-
61- // AddExtension includes the signature manifest of the vsix. Signing happens on
62- // demand, so leave the manifest unsigned. This is safe to do even if
63- // 'signExtensions' is disabled, as these files lay dormant until signed.
64- func (s * Signature ) AddExtension (ctx context.Context , manifest * VSIXManifest , vsix []byte , extra ... File ) (string , error ) {
65- sigManifest , err := extensionsign .GenerateSignatureManifest (vsix )
66- if err != nil {
67- return "" , xerrors .Errorf ("generate signature manifest: %w" , err )
68- }
69-
70- sigManifestJSON , err := json .Marshal (sigManifest )
71- if err != nil {
72- return "" , xerrors .Errorf ("encode signature manifest: %w" , err )
73- }
74-
75- if s .SigningEnabled () && s .saveSigZips {
76- signed , err := s .SigZip (ctx , vsix , sigManifestJSON )
77- if err != nil {
78- s .Logger .Error (ctx , "signing manifest" , slog .Error (err ))
79- return "" , xerrors .Errorf ("sign and zip manifest: %w" , err )
80- }
81- extra = append (extra , File {
82- RelativePath : SignatureZipFilename (manifest ),
83- Content : signed ,
84- })
85- }
86-
87- return s .Storage .AddExtension (ctx , manifest , vsix , append (extra , File {
88- RelativePath : sigManifestName ,
89- Content : sigManifestJSON ,
90- })... )
47+ return s .IncludeEmptySignatures
9148}
9249
9350func (s * Signature ) Manifest (ctx context.Context , publisher , name string , version Version ) (* VSIXManifest , error ) {
@@ -116,60 +73,22 @@ func (s *Signature) Manifest(ctx context.Context, publisher, name string, versio
11673// Open will intercept requests for signed extensions payload.
11774// It does this by looking for 'SigzipFileExtension' or p7s.sig.
11875//
119- // The signed payload and signing process is taken from:
120- // https://github.com/filiptronicek/node-ovsx-sign
76+ // The signed payload is completely empty. Nothing it actually signed.
12177//
12278// Some notes:
12379//
12480// - VSCodium requires a signature to exist, but it does appear to actually read
12581// the signature. Meaning the signature could be empty, incorrect, or a
12682// picture of cat and it would work. There is no signature verification.
12783//
128- // - VSCode requires a signature payload to exist, but the context appear
129- // to be somewhat optional.
130- // Following another open source implementation, it appears the '.signature.p7s'
131- // file must exist, but it can be empty.
132- // The signature is stored in a '.signature.sig' file, although it is unclear
133- // is VSCode ever reads this file.
134- // TODO: Properly implement the p7s file, and diverge from the other open
135- // source implementation. Ideally this marketplace would match Microsoft's
136- // marketplace API.
84+ // - VSCode requires a signature payload to exist, but the content is optional
85+ // for linux users.
86+ // For windows users, the signature must be valid, and this implementation
87+ // will not work.
13788func (s * Signature ) Open (ctx context.Context , fp string ) (fs.File , error ) {
13889 if s .SigningEnabled () && strings .HasSuffix (filepath .Base (fp ), SigzipFileExtension ) {
139- base := filepath .Base (fp )
140- vsixPath := strings .TrimSuffix (base , SigzipFileExtension )
141-
142- // hijack this request, sign the sig manifest
143- manifest , err := s .Storage .Open (ctx , filepath .Join (filepath .Dir (fp ), sigManifestName ))
144- if err != nil {
145- // If this file is missing, it means the extension was added before
146- // signatures were handled by the marketplace.
147- // TODO: Generate the sig manifest payload and insert it?
148- return nil , xerrors .Errorf ("open signature manifest: %w" , err )
149- }
150- defer manifest .Close ()
151-
152- manifestData , err := io .ReadAll (manifest )
153- if err != nil {
154- return nil , xerrors .Errorf ("read signature manifest: %w" , err )
155- }
156-
157- vsix , err := s .Storage .Open (ctx , filepath .Join (filepath .Dir (fp ), vsixPath + ".vsix" ))
158- if err != nil {
159- // If this file is missing, it means the extension was added before
160- // signatures were handled by the marketplace.
161- // TODO: Generate the sig manifest payload and insert it?
162- return nil , xerrors .Errorf ("open signature manifest: %w" , err )
163- }
164- defer vsix .Close ()
165-
166- vsixData , err := io .ReadAll (vsix )
167- if err != nil {
168- return nil , xerrors .Errorf ("read signature manifest: %w" , err )
169- }
170-
171- // TODO: Fetch the VSIX payload from the storage
172- signed , err := s .SigZip (ctx , vsixData , manifestData )
90+ // hijack this request, return an empty signature payload
91+ signed , err := extensionsign .IncludeEmptySignature ()
17392 if err != nil {
17493 return nil , xerrors .Errorf ("sign and zip manifest: %w" , err )
17594 }
@@ -181,12 +100,3 @@ func (s *Signature) Open(ctx context.Context, fp string) (fs.File, error) {
181100
182101 return s .Storage .Open (ctx , fp )
183102}
184-
185- func (s * Signature ) SigZip (ctx context.Context , vsix []byte , sigManifest []byte ) ([]byte , error ) {
186- signed , err := extensionsign .SignAndZipManifest (s .Signer , vsix , sigManifest )
187- if err != nil {
188- s .Logger .Error (ctx , "signing manifest" , slog .Error (err ))
189- return nil , xerrors .Errorf ("sign and zip manifest: %w" , err )
190- }
191- return signed , nil
192- }
0 commit comments