0b84afe1af4866d1eeaaeea3f3442b60ad9761a9
[platform/upstream/libzypp.git] / tests / zypp / RpmPkgSigCheck_test.cc
1 #include "TestSetup.h"
2 static TestSetup test;
3
4 #include "zypp/target/rpm/RpmDb.h"
5 using target::rpm::RpmDb;
6
7 #define DATADIR (Pathname(TESTS_SRC_DIR) / "/zypp/data/RpmPkgSigCheck")
8
9 ///////////////////////////////////////////////////////////////////
10 //
11 // - RpmDb::checkPackage (legacy) and RpmDb::checkPackageSignature are
12 // expected to produce the same result, except for ...
13 //
14 // Result comparison is not very sophisticated. As the detail strings are
15 // user visible (at least in zypper) we want a notification (breaking testcase)
16 // if something in the rpm format changes.
17 //
18 ///////////////////////////////////////////////////////////////////
19 namespace
20 {
21   struct CheckResult
22   {
23     CheckResult()
24     {}
25
26     CheckResult( RpmDb::CheckPackageResult && result_r )
27     : result { std::move(result_r) }
28     {}
29
30     CheckResult( RpmDb::CheckPackageResult && result_r,
31                  std::vector<std::pair<RpmDb::CheckPackageResult,std::string>> && detail_r )
32     : result { std::move(result_r) }
33     { static_cast<std::vector<std::pair<RpmDb::CheckPackageResult,std::string>>&>(detail) = std::move(detail_r); }
34
35     RpmDb::CheckPackageResult result;
36     RpmDb::CheckPackageDetail detail;
37   };
38
39   bool operator==( const CheckResult & lhs, const CheckResult & rhs )
40   {
41     if ( lhs.result != rhs.result )
42       return false;
43     // protect against reordered details:
44     if ( lhs.detail.size() != rhs.detail.size() )
45       return false;
46     for ( const auto & l : lhs.detail )
47     {
48       if ( std::find( rhs.detail.begin(), rhs.detail.end(), l ) == rhs.detail.end() )
49         return false;
50     }
51     return true;
52   }
53
54   std::ostream & operator<<( std::ostream & str, const CheckResult & obj )
55   {
56     str << "R: " << obj.result;
57     for ( const auto & el : obj.detail )
58       str << endl << "   "  << el.first << " | " << el.second;
59     return str;
60   }
61
62   CheckResult gcheckPackage( const Pathname & path_r )
63   {
64     CheckResult res;
65     res.result = test.target().rpmDb().checkPackage( path_r, res.detail );
66 //     cout << "==-" << path_r << endl;
67 //     cout << res << endl;
68     return res;
69   }
70
71   CheckResult gcheckPackageSignature( const Pathname & path_r )
72   {
73     CheckResult res;
74     res.result = test.target().rpmDb().checkPackageSignature( path_r, res.detail );
75 //     cout << "==!" << path_r << endl;
76 //     cout << res << endl;
77     return res;
78   }
79 } // namespace
80
81
82 BOOST_AUTO_TEST_CASE(no_pkg)
83 {
84   Pathname rpm { DATADIR/"no.rpm" };
85   CheckResult cp { gcheckPackage( rpm ) };
86   CheckResult cs { gcheckPackageSignature( rpm ) };
87   BOOST_CHECK_EQUAL( cp, cs );
88
89   CheckResult xpct { RpmDb::CHK_ERROR, {/*empty details*/} };
90   BOOST_CHECK_EQUAL( xpct, cs );
91 }
92
93 BOOST_AUTO_TEST_CASE(unsigned_pkg)
94 {
95   Pathname rpm { DATADIR/"unsigned.rpm" };
96   CheckResult cp { gcheckPackage( rpm ) };
97   CheckResult cs { gcheckPackageSignature( rpm ) };
98   // For unsigned packages the final result differs!
99   // (but only if the digests are OK)
100   BOOST_CHECK_EQUAL( cp.result, RpmDb::CHK_OK );
101   BOOST_CHECK_EQUAL( cs.result, RpmDb::CHK_NOSIG );
102   BOOST_CHECK_EQUAL( cp.detail, cs.detail );
103
104   CheckResult xpct { RpmDb::CHK_NOSIG, {
105     { RpmDb::CHK_OK,    "    Header SHA1 digest: OK" },
106     { RpmDb::CHK_OK,    "    Header SHA256 digest: OK" },
107     { RpmDb::CHK_OK,    "    Payload SHA256 digest: OK" },
108     { RpmDb::CHK_OK,    "    MD5 digest: OK" },
109     { RpmDb::CHK_NOSIG, "    Package is not signed!" },
110   } };
111   BOOST_CHECK_EQUAL( xpct, cs );
112 }
113
114 BOOST_AUTO_TEST_CASE(unsigned_broken_pkg)
115 {
116   Pathname rpm { DATADIR/"unsigned_broken.rpm" };
117   CheckResult cp { gcheckPackage( rpm ) };
118   CheckResult cs { gcheckPackageSignature( rpm ) };
119   // Unsigned, but a broken digest 'superseeds' CHK_NOSIG
120   BOOST_CHECK_EQUAL( cp, cs );
121
122   CheckResult xpct { RpmDb::CHK_FAIL, {
123     { RpmDb::CHK_OK,    "    Header SHA1 digest: OK" },
124     { RpmDb::CHK_OK,    "    Header SHA256 digest: OK" },
125     { RpmDb::CHK_FAIL,  "    Payload SHA256 digest: BAD (Expected 6632dfb6e78fd3346baa860da339acdedf6f019fb1b5448ba1baa6cef67de795 != 85156c232f4c76273bbbb134d8d869e93bbfc845dd0d79016856e5356dd33727)" },
126     { RpmDb::CHK_FAIL,  "    MD5 digest: BAD (Expected e3f474f75d2d2b267da4ff80fc071dd7 != cebe1e7d39b4356639a0779aa23f6e27)" },
127   } };
128   BOOST_CHECK_EQUAL( xpct, cs );
129 }
130
131 BOOST_AUTO_TEST_CASE(unsigned_broken_header_pkg)
132 {
133   Pathname rpm { DATADIR/"unsigned_broken_header.rpm" };
134   CheckResult cp { gcheckPackage( rpm ) };
135   CheckResult cs { gcheckPackageSignature( rpm ) };
136   // Unsigned, but a broken digest 'superseeds' CHK_NOSIG
137   BOOST_CHECK_EQUAL( cp, cs );
138
139   CheckResult xpct { RpmDb::CHK_FAIL, {
140     { RpmDb::CHK_FAIL,  "    Header SHA1 digest: BAD (Expected d6768447e13388b0c35fb151ebfa8f6646a115e9 != dd761ace671a5eb2669b269faf22a3cd72792138)" },
141     { RpmDb::CHK_FAIL,  "    Header SHA256 digest: BAD (Expected 2ce9f41bc0de68b4cb1aa1e18c1bea43dfaa01299ae61ef3e4466df332c792e5 != 4a9410db7131cead773afe1876f2490023ccc7dc47cbba47807430c53ea9649d)" },
142     { RpmDb::CHK_FAIL,  "    Payload SHA256 digest: BAD (Expected 6632dfb6e78fd3346baa860da339acdedf6f019fb1b5448ba1baa6cef67de795 != 85156c232f4c76273bbbb134d8d869e93bbfc845dd0d79016856e5356dd33727)" },
143     { RpmDb::CHK_FAIL,  "    MD5 digest: BAD (Expected e3f474f75d2d2b267da4ff80fc071dd7 != 9afd6b52896d23910280ddded1921071)" },
144   } };
145   BOOST_CHECK_EQUAL( xpct, cs );
146 }
147
148 BOOST_AUTO_TEST_CASE(signed_pkg_nokey)
149 {
150   Pathname rpm { DATADIR/"signed.rpm" };
151   CheckResult cp { gcheckPackage( rpm ) };
152   CheckResult cs { gcheckPackageSignature( rpm ) };
153   BOOST_CHECK_EQUAL( cp, cs );
154
155   CheckResult xpct { RpmDb::CHK_NOKEY, {
156     { RpmDb::CHK_NOKEY, "    Header V3 RSA/SHA256 Signature, key ID 3dbdc284: NOKEY" },
157     { RpmDb::CHK_OK,    "    Header SHA1 digest: OK" },
158     { RpmDb::CHK_OK,    "    Header SHA256 digest: OK" },
159     { RpmDb::CHK_OK,    "    Payload SHA256 digest: OK" },
160     { RpmDb::CHK_OK,    "    MD5 digest: OK" },
161   } };
162   BOOST_CHECK_EQUAL( xpct, cs );
163 }
164
165 BOOST_AUTO_TEST_CASE(signed_broken_pkg_nokey)
166 {
167   Pathname rpm { DATADIR/"signed_broken.rpm" };
168   CheckResult cp { gcheckPackage( rpm ) };
169   CheckResult cs { gcheckPackageSignature( rpm ) };
170   BOOST_CHECK_EQUAL( cp, cs );
171
172   CheckResult xpct { RpmDb::CHK_FAIL, {
173     { RpmDb::CHK_NOKEY, "    Header V3 RSA/SHA256 Signature, key ID 3dbdc284: NOKEY" },
174     { RpmDb::CHK_OK,    "    Header SHA1 digest: OK" },
175     { RpmDb::CHK_OK,    "    Header SHA256 digest: OK" },
176     { RpmDb::CHK_FAIL,  "    Payload SHA256 digest: BAD (Expected 6632dfb6e78fd3346baa860da339acdedf6f019fb1b5448ba1baa6cef67de795 != 85156c232f4c76273bbbb134d8d869e93bbfc845dd0d79016856e5356dd33727)" },
177     { RpmDb::CHK_FAIL,  "    MD5 digest: BAD (Expected 8e64684e4d5bd90c3c13f76ecbda9ee2 != 442a473472708c39f3ac2b5eb38b476f)" },
178   } };
179   BOOST_CHECK_EQUAL( xpct, cs );
180 }
181
182 BOOST_AUTO_TEST_CASE(signed_broken_header_pkg_nokey)
183 {
184   Pathname rpm { DATADIR/"signed_broken_header.rpm" };
185   CheckResult cp { gcheckPackage( rpm ) };
186   CheckResult cs { gcheckPackageSignature( rpm ) };
187   BOOST_CHECK_EQUAL( cp, cs );
188
189   CheckResult xpct { RpmDb::CHK_FAIL, {
190     { RpmDb::CHK_FAIL,  "    Header V3 RSA/SHA256 Signature, key ID 3dbdc284: BAD" },
191     { RpmDb::CHK_FAIL,  "    Header SHA1 digest: BAD (Expected 9ca2e3aec038e562d33442271ee52c08ded0d637 != 95286fd653f927df0a42746e310861d3f89bb75c)" },
192     { RpmDb::CHK_FAIL,  "    Header SHA256 digest: BAD (Expected e88100656c8e06b6e4bb9155f0dd111ef8042866941f02b623cb46e12a82f732 != 76b343bcb9b8aaf9998fdcf7392e234944a0b078c67667fa0d658208b9a66983)" },
193     { RpmDb::CHK_FAIL,  "    Payload SHA256 digest: BAD (Expected 6632dfb6e78fd3346baa860da339acdedf6f019fb1b5448ba1baa6cef67de795 != 85156c232f4c76273bbbb134d8d869e93bbfc845dd0d79016856e5356dd33727)" },
194     { RpmDb::CHK_FAIL,  "    MD5 digest: BAD (Expected 8e64684e4d5bd90c3c13f76ecbda9ee2 != 81df819a7d94638ff3ffe0bb93a7d177)" },
195
196   } };
197   BOOST_CHECK_EQUAL( xpct, cs );
198 }
199
200
201 ///////////////////////////////////////////////////////////////////
202 BOOST_AUTO_TEST_CASE(add_key)
203 {
204   PublicKey key { Pathname(DATADIR)/"signed.key" };
205   //cout << key << endl;
206   test.target().rpmDb().importPubkey( key );
207 }
208 ///////////////////////////////////////////////////////////////////
209
210
211 BOOST_AUTO_TEST_CASE(signed_pkg_withkey)
212 {
213   Pathname rpm { DATADIR/"signed.rpm" };
214   CheckResult cp { gcheckPackage( rpm ) };
215   CheckResult cs { gcheckPackageSignature( rpm ) };
216   BOOST_CHECK_EQUAL( cp, cs );
217
218   CheckResult xpct { RpmDb::CHK_OK, {
219     { RpmDb::CHK_OK,    "    Header V3 RSA/SHA256 Signature, key ID 3dbdc284: OK" },
220     { RpmDb::CHK_OK,    "    Header SHA1 digest: OK" },
221     { RpmDb::CHK_OK,    "    Header SHA256 digest: OK" },
222     { RpmDb::CHK_OK,    "    Payload SHA256 digest: OK" },
223     { RpmDb::CHK_OK,    "    MD5 digest: OK" },
224   } };
225   BOOST_CHECK_EQUAL( xpct, cs );
226 }
227
228 BOOST_AUTO_TEST_CASE(signed_broken_pkg_withkey)
229 {
230   Pathname rpm { DATADIR/"signed_broken.rpm" };
231   CheckResult cp { gcheckPackage( rpm ) };
232   CheckResult cs { gcheckPackageSignature( rpm ) };
233   BOOST_CHECK_EQUAL( cp, cs );
234
235   CheckResult xpct { RpmDb::CHK_FAIL, {
236     { RpmDb::CHK_OK,    "    Header V3 RSA/SHA256 Signature, key ID 3dbdc284: OK" },
237     { RpmDb::CHK_OK,    "    Header SHA1 digest: OK" },
238     { RpmDb::CHK_OK,    "    Header SHA256 digest: OK" },
239     { RpmDb::CHK_FAIL,  "    Payload SHA256 digest: BAD (Expected 6632dfb6e78fd3346baa860da339acdedf6f019fb1b5448ba1baa6cef67de795 != 85156c232f4c76273bbbb134d8d869e93bbfc845dd0d79016856e5356dd33727)" },
240     { RpmDb::CHK_FAIL,  "    MD5 digest: BAD (Expected 8e64684e4d5bd90c3c13f76ecbda9ee2 != 442a473472708c39f3ac2b5eb38b476f)" },
241   } };
242   BOOST_CHECK_EQUAL( xpct, cs );
243 }
244
245 BOOST_AUTO_TEST_CASE(signed_broken_header_pkg_withkey)
246 {
247   Pathname rpm { DATADIR/"signed_broken_header.rpm" };
248   CheckResult cp { gcheckPackage( rpm ) };
249   CheckResult cs { gcheckPackageSignature( rpm ) };
250   BOOST_CHECK_EQUAL( cp, cs );
251
252   CheckResult xpct { RpmDb::CHK_FAIL, {
253     { RpmDb::CHK_FAIL,  "    Header V3 RSA/SHA256 Signature, key ID 3dbdc284: BAD" },
254     { RpmDb::CHK_FAIL,  "    Header SHA1 digest: BAD (Expected 9ca2e3aec038e562d33442271ee52c08ded0d637 != 95286fd653f927df0a42746e310861d3f89bb75c)" },
255     { RpmDb::CHK_FAIL,  "    Header SHA256 digest: BAD (Expected e88100656c8e06b6e4bb9155f0dd111ef8042866941f02b623cb46e12a82f732 != 76b343bcb9b8aaf9998fdcf7392e234944a0b078c67667fa0d658208b9a66983)" },
256     { RpmDb::CHK_FAIL,  "    Payload SHA256 digest: BAD (Expected 6632dfb6e78fd3346baa860da339acdedf6f019fb1b5448ba1baa6cef67de795 != 85156c232f4c76273bbbb134d8d869e93bbfc845dd0d79016856e5356dd33727)" },
257     { RpmDb::CHK_FAIL,  "    MD5 digest: BAD (Expected 8e64684e4d5bd90c3c13f76ecbda9ee2 != 81df819a7d94638ff3ffe0bb93a7d177)" },
258   } };
259   BOOST_CHECK_EQUAL( xpct, cs );
260 }