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