...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package authenticode
18
19 import (
20 "archive/tar"
21 "bytes"
22 "crypto"
23 "io"
24 "io/ioutil"
25
26 "github.com/sassoftware/relic/lib/comdoc"
27 )
28
29 const (
30 msiTarExMeta = "__exmeta"
31 msiTarStorageUID = "__storage_uid"
32 )
33
34
35
36 func MsiToTar(cdf *comdoc.ComDoc, w io.Writer) error {
37 tw := tar.NewWriter(w)
38
39 var buf bytes.Buffer
40 if err := prehashMsiDir(cdf, cdf.RootStorage(), &buf); err != nil {
41 return err
42 }
43 if err := tarAddFile(tw, msiTarExMeta, buf.Bytes()); err != nil {
44 return err
45 }
46
47 if err := msiToTarDir(cdf, tw, cdf.RootStorage(), ""); err != nil {
48 return err
49 }
50 return tw.Close()
51 }
52
53
54 func DigestMsiTar(r io.Reader, hash crypto.Hash, extended bool) ([]byte, error) {
55 tr := tar.NewReader(r)
56 d := hash.New()
57 for {
58 hdr, err := tr.Next()
59 if err == io.EOF {
60 break
61 } else if err != nil {
62 return nil, err
63 }
64 if hdr.Name == msiTarExMeta {
65 if !extended {
66 continue
67 }
68 exmeta, err := ioutil.ReadAll(tr)
69 if err != nil {
70 return nil, err
71 }
72 d2 := hash.New()
73 d2.Write(exmeta)
74 prehash := d2.Sum(nil)
75 d.Write(prehash)
76 } else if hdr.Name == msiDigitalSignature || hdr.Name == msiDigitalSignatureEx {
77 continue
78 }
79 if _, err := io.Copy(d, tr); err != nil {
80 return nil, err
81 }
82 }
83 return d.Sum(nil), nil
84 }
85
86
87 func tarAddFile(tw *tar.Writer, name string, contents []byte) error {
88 hdr := &tar.Header{Name: name, Mode: 0644, Size: int64(len(contents))}
89 if err := tw.WriteHeader(hdr); err != nil {
90 return err
91 }
92 _, err := tw.Write(contents)
93 return err
94 }
95
96
97 func msiToTarDir(cdf *comdoc.ComDoc, tw *tar.Writer, parent *comdoc.DirEnt, path string) error {
98 files, err := cdf.ListDir(parent)
99 if err != nil {
100 return err
101 }
102 sortMsiFiles(files)
103 for _, item := range files {
104 itemPath := path + msiDecodeName(item.Name())
105 switch item.Type {
106 case comdoc.DirStream:
107 r, err := cdf.ReadStream(item)
108 if err != nil {
109 return err
110 }
111 hdr := &tar.Header{
112 Name: itemPath,
113 Mode: 0644,
114 Size: int64(item.StreamSize),
115 }
116 if err := tw.WriteHeader(hdr); err != nil {
117 return err
118 }
119 if _, err := io.Copy(tw, r); err != nil {
120 return err
121 }
122 case comdoc.DirStorage:
123 if err := msiToTarDir(cdf, tw, item, itemPath+"/"); err != nil {
124 return err
125 }
126 }
127 }
128
129 return tarAddFile(tw, path+msiTarStorageUID, parent.UID[:])
130 }
131
View as plain text