...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package rpm
18
19
20
21 import (
22 "encoding/hex"
23 "fmt"
24 "io"
25 "os"
26 "strings"
27 "time"
28
29 rpmutils "github.com/sassoftware/go-rpmutils"
30 "github.com/sassoftware/relic/lib/audit"
31 "github.com/sassoftware/relic/lib/binpatch"
32 "github.com/sassoftware/relic/lib/certloader"
33 "github.com/sassoftware/relic/lib/magic"
34 "github.com/sassoftware/relic/lib/pgptools"
35 "github.com/sassoftware/relic/signers"
36 "github.com/sassoftware/relic/signers/sigerrors"
37 )
38
39 var RpmSigner = &signers.Signer{
40 Name: "rpm",
41 Magic: magic.FileTypeRPM,
42 CertTypes: signers.CertTypePgp,
43 FormatLog: formatLog,
44 Sign: sign,
45 Verify: verify,
46 }
47
48 func init() {
49 signers.Register(RpmSigner)
50 }
51
52 func formatLog(attrs *audit.Info) string {
53 return fmt.Sprintf("nevra=%s md5=%s sha1=%s",
54 attrs.Attributes["rpm.nevra"],
55 attrs.Attributes["rpm.md5"],
56 attrs.Attributes["rpm.sha1"],
57 )
58 }
59
60 func sign(r io.Reader, cert *certloader.Certificate, opts signers.SignOpts) ([]byte, error) {
61 config := &rpmutils.SignatureOptions{
62 Hash: opts.Hash,
63 CreationTime: opts.Time.UTC().Round(time.Second),
64 }
65 header, err := rpmutils.SignRpmStream(r, cert.PgpKey.PrivateKey, config)
66 if err != nil {
67 return nil, err
68 }
69 blob, err := header.DumpSignatureHeader(true)
70 if err != nil {
71 return nil, err
72 }
73 patch := binpatch.New()
74 patch.Add(0, int64(header.OriginalSignatureHeaderSize()), blob)
75 md5, _ := header.GetBytes(rpmutils.SIG_MD5)
76 sha1, _ := header.GetString(rpmutils.SIG_SHA1)
77 opts.Audit.Attributes["rpm.nevra"] = nevra(header)
78 opts.Audit.Attributes["rpm.md5"] = hex.EncodeToString(md5)
79 opts.Audit.Attributes["rpm.sha1"] = sha1
80 return opts.SetBinPatch(patch)
81 }
82
83 func verify(f *os.File, opts signers.VerifyOpts) ([]*signers.Signature, error) {
84
85 header, sigs, err := rpmutils.Verify(f, opts.TrustedPgp)
86 if err != nil {
87 return nil, err
88 }
89 if len(sigs) == 0 {
90 return nil, sigerrors.NotSignedError{Type: "RPM"}
91 }
92 var ret []*signers.Signature
93 seen := make(map[uint64]bool)
94 for _, sig := range sigs {
95 if seen[sig.KeyId] {
96 continue
97 }
98 seen[sig.KeyId] = true
99 rsig := &signers.Signature{
100 Package: nevra(header),
101 CreationTime: sig.CreationTime,
102 Hash: sig.Hash,
103 }
104 if sig.Signer == nil {
105 if !opts.NoChain {
106 return nil, pgptools.ErrNoKey(sig.KeyId)
107 }
108 rsig.Signer = fmt.Sprintf("UNKNOWN(%x)", sig.KeyId)
109 } else {
110 rsig.SignerPgp = sig.Signer
111 }
112 ret = append(ret, rsig)
113 }
114 return ret, nil
115 }
116
117 func nevra(header *rpmutils.RpmHeader) string {
118 nevra, _ := header.GetNEVRA()
119 snevra := nevra.String()
120
121 snevra = snevra[:len(snevra)-4]
122
123 snevra = strings.Replace(snevra, "-0:", "-", -1)
124 return snevra
125 }
126
View as plain text