Imported Upstream version 17.22.1
[platform/upstream/libzypp.git] / tests / zypp / KeyRing_test.cc
1
2 #include <iostream>
3 #include <fstream>
4 #include <list>
5 #include <string>
6
7 #include "zypp/base/Logger.h"
8 #include "zypp/base/Exception.h"
9 #include "zypp/KeyRing.h"
10 #include "zypp/PublicKey.h"
11 #include "zypp/TmpPath.h"
12
13 #include <boost/test/unit_test.hpp>
14
15 #include "KeyRingTestReceiver.h"
16
17 using boost::unit_test::test_suite;
18 using boost::unit_test::test_case;
19
20 using namespace std;
21 using namespace zypp;
22 using namespace zypp::filesystem;
23
24 #define DATADIR (Pathname(TESTS_SRC_DIR) +  "/zypp/data/KeyRing")
25
26 BOOST_AUTO_TEST_CASE(keyring_test)
27 {
28   PublicKey key( Pathname(DATADIR) + "public.asc" );
29
30  /** 
31   * scenario #1
32   * import a not trusted key
33   * ask for accept, answer yes 'temporarily'
34   */
35   {
36     KeyRingTestReceiver keyring_callbacks;
37     KeyRingTestSignalReceiver receiver;
38     // base sandbox for playing
39     TmpDir tmp_dir;
40     KeyRing keyring( tmp_dir.path() );
41
42     BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 );
43     BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 );
44   
45     keyring.importKey( key, false );
46     
47     BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 1 );
48     BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 );
49     
50     BOOST_CHECK_MESSAGE( keyring.isKeyKnown( key.id() ), "Imported untrusted key should be known");
51     BOOST_CHECK_MESSAGE( ! keyring.isKeyTrusted( key.id() ), "Imported untrusted key should be untrusted");
52     
53     keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY);
54     bool to_continue = keyring.verifyFileSignatureWorkflow( DATADIR + "repomd.xml", "Blah Blah", DATADIR + "repomd.xml.asc");
55   
56     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnknownKey(), "Should not ask for unknown key, it was known");
57     BOOST_CHECK_MESSAGE( keyring_callbacks.askedAcceptKey(), "Verify Signature Workflow with only 1 untrusted key should ask user wether to trust and/or import");
58     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptVerFailed(), "The signature validates");
59     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnsignedFile(), "It is a signed file, so dont ask the opposite");
60     
61     BOOST_CHECK_MESSAGE( to_continue, "We did not import, but we trusted and signature validates.");
62   }
63
64   /** 
65   * scenario #1.1
66   * import a not trusted key
67   * ask to accept, answer yes 'temporarily'
68   * vorrupt the file and check
69   */
70   {
71     KeyRingTestReceiver keyring_callbacks;
72     KeyRingTestSignalReceiver receiver;
73     // base sandbox for playing
74     TmpDir tmp_dir;
75     KeyRing keyring( tmp_dir.path() );
76     
77     BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 );
78     BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 );
79   
80     keyring.importKey( key, false );
81     
82     keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY);
83
84     // now we will recheck with a corrupted file
85     bool to_continue = keyring.verifyFileSignatureWorkflow( DATADIR + "repomd.xml.corrupted", "Blah Blah", DATADIR + "repomd.xml.asc");
86     
87     // check wether the user got the right questions
88     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnknownKey(), "Should not ask for unknown key, it was known");
89     BOOST_CHECK_MESSAGE( keyring_callbacks.askedAcceptKey(), "Verify Signature Workflow with only 1 untrusted key should ask user wether to trust and/or import");
90     BOOST_CHECK_MESSAGE( keyring_callbacks.askedAcceptVerFailed(), "The signature does not validates");
91     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnsignedFile(), "It is a signed file, so dont ask the opposite");
92
93     BOOST_CHECK_MESSAGE( ! to_continue, "We did not continue with a corrupted file");
94   }
95   
96    /** 
97   * scenario #1.2
98   * import a not trusted key
99   * ask for trust, answer yes
100   * ask for import, answer no
101   * check without signature
102   */
103   {
104     KeyRingTestReceiver keyring_callbacks;
105     KeyRingTestSignalReceiver receiver;
106     // base sandbox for playing
107     TmpDir tmp_dir;
108     KeyRing keyring( tmp_dir.path() );
109     
110     keyring.importKey( key, false );
111     
112     keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY);
113     // now we will recheck with a unsigned file
114     bool to_continue = keyring.verifyFileSignatureWorkflow( DATADIR + "repomd.xml", "Blah Blah", Pathname() );
115     
116     // check wether the user got the right questions
117     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnknownKey(), "Should not ask for unknown key, it was known");
118     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptKey(), "No signature, no key to trust");
119     BOOST_CHECK_MESSAGE( keyring_callbacks.askedAcceptUnsignedFile(), "Ask the user wether to accept an unsigned file");
120     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptVerFailed(), "There is no signature to verify");
121     
122     BOOST_CHECK_MESSAGE( ! to_continue, "We did not continue with a unsigned file");
123   }
124   
125  /** scenario #2
126   * empty keyring
127   * should ask for unknown key
128   * answer no
129   */
130   {
131     KeyRingTestReceiver keyring_callbacks;
132     KeyRingTestSignalReceiver receiver;
133     // base sandbox for playing
134     TmpDir tmp_dir;
135     KeyRing keyring( tmp_dir.path() );
136
137     BOOST_CHECK_MESSAGE( ! keyring.isKeyKnown( key.id() ), "empty keyring has not known keys");
138
139     //keyring_callbacks.answerAcceptUnknownKey(true);
140     bool to_continue = keyring.verifyFileSignatureWorkflow( DATADIR + "repomd.xml", "Blah Blah", DATADIR + "repomd.xml.asc");
141     BOOST_CHECK_MESSAGE(keyring_callbacks.askedAcceptUnknownKey(), "Should ask to accept unknown key, empty keyring");
142     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptKey(), "Unknown key cant be trusted");
143     BOOST_CHECK_MESSAGE( ! to_continue, "We answered no to accept unknown key");
144   }
145
146   /** scenario #3
147   * import trusted key
148   * should ask nothing
149   * should emit signal
150   */
151   {
152     KeyRingTestReceiver keyring_callbacks;
153     KeyRingTestSignalReceiver receiver;
154     // base sandbox for playing
155     TmpDir tmp_dir;
156     KeyRing keyring( tmp_dir.path() );
157     
158     BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 );
159     BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 );
160   
161     keyring.importKey( key, true );
162
163     BOOST_CHECK_EQUAL( receiver._trusted_key_added_called, true );
164     
165     BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 );
166     BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 1 );
167     
168     BOOST_CHECK_MESSAGE( keyring.isKeyKnown( key.id() ), "Imported trusted key should be known");
169     BOOST_CHECK_MESSAGE( keyring.isKeyTrusted( key.id() ), "Imported trusted key should be trusted");
170     
171     bool to_continue = keyring.verifyFileSignatureWorkflow( DATADIR + "repomd.xml", "Blah Blah", DATADIR + "repomd.xml.asc");
172   
173     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnknownKey(), "Should not ask for unknown key, it was known");
174     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptKey(), "Verify Signature Workflow with only 1 untrusted key should ask user wether to trust and/or import");
175     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptVerFailed(), "The signature validates");
176     BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnsignedFile(), "It is a signed file, so dont ask the opposite");
177     
178     BOOST_CHECK_MESSAGE( to_continue, "We did not import, but we trusted and signature validates.");
179   }
180   //keyring.importKey( key, true );
181   //BOOST_CHECK_EQUAL( receiver._trusted_key_added_called, true );
182   //BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), 1 );
183
184   /* check signature id can be extracted */
185   
186 }
187
188 BOOST_AUTO_TEST_CASE(signature_test)
189 {
190   PublicKey key( DATADIR + "public.asc" );
191
192   {
193     KeyRingTestReceiver keyring_callbacks;
194     KeyRingTestSignalReceiver receiver;
195     // base sandbox for playing
196     TmpDir tmp_dir;
197     KeyRing keyring( tmp_dir.path() );
198     
199     BOOST_CHECK_EQUAL( keyring.readSignatureKeyId( DATADIR + "repomd.xml.asc" ), "BD61D89BD98821BE" );
200     BOOST_CHECK_THROW( keyring.readSignatureKeyId(Pathname()), Exception );
201     TmpFile tmp;
202     BOOST_CHECK_EQUAL( keyring.readSignatureKeyId(tmp.path()), "" );
203
204     keyring.importKey(key);
205
206     BOOST_CHECK(keyring.verifyFileSignature( DATADIR + "repomd.xml", DATADIR + "repomd.xml.asc"));
207     BOOST_CHECK( ! keyring.verifyFileSignature( DATADIR + "repomd.xml.corrupted", DATADIR + "repomd.xml.asc"));
208   }
209 }
210
211 BOOST_AUTO_TEST_CASE(keyring_import)
212 {
213   // base sandbox for playing
214   TmpDir tmp_dir;
215   KeyRing keyring( tmp_dir.path() );
216   struct Receiver: public callback::ReceiveReport<KeyRingSignals>
217   {
218     Receiver()
219     { connect(); }
220
221     virtual void trustedKeyAdded( const PublicKey & key_r )
222     { ++_cbcnt; }
223
224     virtual void trustedKeyRemoved( const PublicKey & key_r )
225     { --_cbcnt; }
226
227     unsigned _cbcnt = 0;
228   } receiver;
229
230   ///////////////////////////////////////////////////////////////////
231   // Make sure we get a proper callback notification if multiple
232   // keys are imported at once.
233   ///////////////////////////////////////////////////////////////////
234   PublicKey key( DATADIR + "installkey.gpg" );
235   BOOST_CHECK_EQUAL( key.hiddenKeys().size(), 2 );
236   BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), 0 );
237   keyring.importKey( key, true );
238   BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), 3 );
239   BOOST_CHECK_EQUAL( receiver._cbcnt, keyring.trustedPublicKeys().size() );
240 }
241
242 BOOST_AUTO_TEST_CASE(keyring_delete)
243 {
244   PublicKey key( Pathname(DATADIR) + "public.asc" );
245   /** scenario #3
246   * import and delete untrusted key
247   */
248   {
249     // base sandbox for playing
250     TmpDir tmp_dir;
251     KeyRing keyring( tmp_dir.path() );
252
253     BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 );
254     BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 );
255
256     keyring.importKey( key, false );
257
258     BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 1 );
259     BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 );
260
261     keyring.deleteKey( key.id(), false);
262
263     BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 );
264     BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 );
265   }
266
267   /** scenario #3.1
268   * import and delete trusted key
269   */
270   {
271     // base sandbox for playing
272     TmpDir tmp_dir;
273     KeyRing keyring( tmp_dir.path() );
274
275     BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 );
276     BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 );
277
278     keyring.importKey( key, true );
279
280     BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 );
281     BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 1 );
282
283     //try to delete from untrusted keyring
284     keyring.deleteKey( key.id(), false);
285
286     BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 );
287     BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 1 );
288
289     keyring.deleteKey( key.id(), true);
290
291     BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 );
292     BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 );
293   }
294 }
295