integrate keyring into zypp
[platform/upstream/libzypp.git] / zypp / KeyRing.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/KeyRing.cc
10  *
11 */
12 #include <iostream>
13 #include <fstream>
14 //#include "zypp/base/Logger.h"
15 #include <sys/file.h>
16 #include <cstdio>
17 #include <unistd.h>
18
19 #include "zypp/ZYppFactory.h"
20 #include "zypp/ZYpp.h"
21
22 #include <boost/regex.hpp>
23
24 #include "zypp/base/String.h"
25 #include "zypp/KeyRing.h"
26 #include "zypp/ExternalProgram.h"
27 #include "zypp/TmpPath.h"
28
29 using std::endl;
30 using namespace boost;
31 using namespace zypp::filesystem;
32 using namespace std;
33
34 ///////////////////////////////////////////////////////////////////
35 namespace zypp
36 { /////////////////////////////////////////////////////////////////
37
38   IMPL_PTR_TYPE(KeyRing);
39   
40   static void dumpRegexpResults( const boost::smatch &what )
41   {
42     for ( unsigned int k=0; k < what.size(); k++)
43     {
44       XXX << "[match "<< k << "] [" << what[k] << "]" << std::endl;
45     }
46   }
47   
48   ///////////////////////////////////////////////////////////////////
49   //
50   //    CLASS NAME : KeyRing::Impl
51   //
52   /** KeyRing implementation. */
53   struct KeyRing::Impl
54   {
55     Impl()
56     {}
57
58     Impl( const Pathname &general_kr, const Pathname &trusted_kr )
59     {
60       filesystem::assert_dir(general_kr);
61       filesystem::assert_dir(trusted_kr);
62       
63       _general_kr = general_kr;
64       _trusted_kr = trusted_kr;
65     }
66
67     void importKey( const Pathname &keyfile, bool trusted = false);
68     PublicKey readPublicKey( const Pathname &keyfile );
69     void deleteKey( const std::string &id, bool trusted );
70     std::list<PublicKey> trustedPublicKeys();
71     std::list<PublicKey> publicKeys();
72     bool verifyFileSignature( const Pathname &file, const Pathname &signature);
73     bool verifyFileTrustedSignature( const Pathname &file, const Pathname &signature);
74   private:
75     //mutable std::map<Locale, std::string> translations;
76     bool verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring);
77     void importKey( const Pathname &keyfile, const Pathname &keyring);
78     void deleteKey( const std::string &id, const Pathname &keyring );
79     std::list<PublicKey> publicKeys(const Pathname &keyring);
80     
81     Pathname _general_kr;
82     Pathname _trusted_kr;
83   public:
84     /** Offer default Impl. */
85     static shared_ptr<Impl> nullimpl()
86     {
87       static shared_ptr<Impl> _nullimpl( new Impl );
88       return _nullimpl;
89     }
90
91   private:
92     friend Impl * rwcowClone<Impl>( const Impl * rhs );
93     /** clone for RWCOW_pointer */
94     Impl * clone() const
95     { return new Impl( *this ); }
96   };
97   
98   void KeyRing::Impl::importKey( const Pathname &keyfile, bool trusted)
99   {
100     importKey( keyfile, trusted ? _trusted_kr : _general_kr );
101   }
102   
103   void KeyRing::Impl::deleteKey( const std::string &id, bool trusted)
104   {
105     deleteKey( id, trusted ? _trusted_kr : _general_kr );
106   }
107   
108   std::list<PublicKey> KeyRing::Impl::publicKeys()
109   {
110     return publicKeys( _general_kr );
111   }
112   
113   std::list<PublicKey> KeyRing::Impl::trustedPublicKeys()
114   {
115     return publicKeys( _trusted_kr );
116   }
117   
118   bool KeyRing::Impl::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
119   {
120     return verifyFile( file, signature, _trusted_kr );
121   }
122   
123   bool KeyRing::Impl::verifyFileSignature( const Pathname &file, const Pathname &signature)
124   {
125     return verifyFile( file, signature, _general_kr );
126   }
127   
128   PublicKey KeyRing::Impl::readPublicKey( const Pathname &keyfile )
129   {  
130     const char* argv[] =
131     {
132       "gpg",
133       "--with-fingerprint",
134       "--with-colons",
135       "--quiet",
136       "--no-tty",
137       "--no-greeting",
138       "--batch",
139       "--status-fd",
140       "1",  
141       keyfile.asString().c_str(),
142       NULL
143     };
144     
145     ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
146     
147     std::string line;
148     int count = 0;
149     
150     boost::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
151     
152     // pub:-:1024:17:A84EDAE89C800ACA:2000-10-19:2008-06-21::-:SuSE Package Signing Key <build@suse.de>:
153     
154     PublicKey key;
155     for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
156     {
157       //MIL << "[" << line << "]" << std::endl;
158       boost::smatch what;
159       if(boost::regex_match(line, what, rxColons, boost::match_extra))
160       {
161         if ( what[1] == "pub" )
162         {
163           key.id = what[5];
164           key.name = what[10];
165           return key;
166         }
167         //dumpRegexpResults(what);
168       }
169     }
170     prog.close();
171     return key;
172   }
173   
174   std::list<PublicKey> KeyRing::Impl::publicKeys(const Pathname &keyring)
175   {
176     const char* argv[] =
177     {
178       "gpg",
179       "--quiet",
180       "--list-keys",
181       "--with-colons",
182       "--with-fingerprint",
183       "--homedir",
184       keyring.asString().c_str(),
185       NULL
186     };
187     std::list<PublicKey> keys;
188     
189     ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
190     std::string line;
191     int count = 0;
192     
193     boost::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
194     
195     for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
196     {
197       //MIL << line << std::endl;
198       boost::smatch what;
199       if(boost::regex_match(line, what, rxColons, boost::match_extra))
200       {
201         if ( what[1] == "pub" )
202         {
203           PublicKey key;
204           key.id = what[5];
205           key.name = what[10];
206           MIL << "Found key " << key.id << " [" << key.name << "]" << std::endl;
207           keys.push_back(key);
208         }
209         dumpRegexpResults(what);
210       }
211     }
212     prog.close();
213     return keys;
214   }
215   
216   void KeyRing::Impl::importKey( const Pathname &keyfile, const Pathname &keyring)
217   {
218     const char* argv[] =
219     {
220       "gpg",
221       "--quiet",
222       "--no-tty",
223       "--no-greeting",
224       "--status-fd",
225       "1",  
226       "--homedir",
227       keyring.asString().c_str(),
228       "--import",
229       keyfile.asString().c_str(),
230       NULL
231     };
232     
233     int code;
234     ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
235     code = prog.close();
236     
237     if ( code != 0 )
238       ZYPP_THROW(Exception("failed to import key"));
239
240 //     boost::regex rxImported("^\\[GNUPG:\\] IMPORTED ([^[:space:]]+) (.+)\n$");
241 //     std::string line;
242 //     int count = 0;
243 //     for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
244 //     {
245 //       MIL << line << std::endl;
246 //        boost::smatch what;
247 //        if(boost::regex_match(line, what, rxImported, boost::match_extra))
248 //        {
249 //          MIL << std::endl;
250 //          PublicKey key;
251 //          key.id = what[1];
252 //          key.name = what[2];
253 //          return key;
254 //        }
255 //     }
256 //     prog.close();
257 //     throw Exception("failed to import key");
258 //     return PublicKey();
259   }
260   
261   void KeyRing::Impl::deleteKey( const std::string &id, const Pathname &keyring )
262   {
263     const char* argv[] =
264     {
265       "gpg",
266       "--yes",
267       "--quiet",
268       "--no-tty",
269       "--batch",
270       "--status-fd",
271       "1",
272       "--homedir",
273       keyring.asString().c_str(),
274       "--delete-keys",
275       id.c_str(),
276       NULL
277     };
278     
279     ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
280     
281     int code = prog.close();
282     if ( code )
283       ZYPP_THROW(Exception("Failed to delete key."));
284     else    
285       MIL << "Deleted key " << id << " from keyring " << keyring << std::endl;
286   }    
287   
288   bool KeyRing::Impl::verifyFile( const Pathname &file, const Pathname &signature, const Pathname &keyring)
289   {
290     const char* argv[] =
291     {
292       "gpg",
293       "--quiet",
294       "--no-tty",
295       "--batch",
296       "--no-greeting",
297       "--status-fd",
298       "1",
299       "--homedir",
300       keyring.asString().c_str(),
301       "--verify",
302       signature.asString().c_str(),
303       file.asString().c_str(),
304       NULL
305     };
306     
307     // no need to parse output for now
308     //     [GNUPG:] SIG_ID yCc4u223XRJnLnVAIllvYbUd8mQ 2006-03-29 1143618744
309     //     [GNUPG:] GOODSIG A84EDAE89C800ACA SuSE Package Signing Key <build@suse.de>
310     //     gpg: Good signature from "SuSE Package Signing Key <build@suse.de>"
311     //     [GNUPG:] VALIDSIG 79C179B2E1C820C1890F9994A84EDAE89C800ACA 2006-03-29 1143618744 0 3 0 17 2 00 79C179B2E1C820C1890F9994A84EDAE89C800ACA
312     //     [GNUPG:] TRUST_UNDEFINED
313     
314     //     [GNUPG:] ERRSIG A84EDAE89C800ACA 17 2 00 1143618744 9
315     //     [GNUPG:] NO_PUBKEY A84EDAE89C800ACA
316
317     ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
318     return (prog.close() == 0) ? true : false;
319   }
320   
321   ///////////////////////////////////////////////////////////////////
322
323   ///////////////////////////////////////////////////////////////////
324   //
325   //    CLASS NAME : KeyRing
326   //
327   ///////////////////////////////////////////////////////////////////
328
329   ///////////////////////////////////////////////////////////////////
330   //
331   //    METHOD NAME : KeyRing::KeyRing
332   //    METHOD TYPE : Ctor
333   //
334   KeyRing::KeyRing()
335   : _pimpl( Impl::nullimpl() )
336   {}
337
338   ///////////////////////////////////////////////////////////////////
339   //
340   //    METHOD NAME : KeyRing::KeyRing
341   //    METHOD TYPE : Ctor
342   //
343   KeyRing::KeyRing( const Pathname &general_kr, const Pathname &trusted_kr )
344   : _pimpl( new Impl(general_kr, trusted_kr) )
345   {}
346
347   ///////////////////////////////////////////////////////////////////
348   //
349   //    METHOD NAME : KeyRing::~KeyRing
350   //    METHOD TYPE : Dtor
351   //
352   KeyRing::~KeyRing()
353   {}
354
355   ///////////////////////////////////////////////////////////////////
356   //
357   // Forward to implementation:
358   //
359   ///////////////////////////////////////////////////////////////////
360
361   void KeyRing::importKey( const Pathname &keyfile, bool trusted)
362   {
363     _pimpl->importKey(keyfile, trusted);
364   }
365   
366   PublicKey KeyRing::readPublicKey( const Pathname &keyfile )
367   {
368     return _pimpl->readPublicKey(keyfile);
369   }
370   
371   void KeyRing::deleteKey( const std::string &id, bool trusted )
372   {
373     _pimpl->deleteKey(id, trusted);
374   }
375   
376   std::list<PublicKey> KeyRing::publicKeys()
377   {
378     return _pimpl->publicKeys();
379   }
380   
381   std::list<PublicKey> KeyRing::trustedPublicKeys()
382   {
383     return _pimpl->trustedPublicKeys();
384   }
385   
386   bool KeyRing::verifyFileSignature( const Pathname &file, const Pathname &signature)
387   {
388     return _pimpl->verifyFileSignature(file, signature);
389   }
390   
391   bool KeyRing::verifyFileTrustedSignature( const Pathname &file, const Pathname &signature)
392   {
393     return _pimpl->verifyFileTrustedSignature(file, signature);
394   }
395   
396   /////////////////////////////////////////////////////////////////
397 } // namespace zypp
398 ///////////////////////////////////////////////////////////////////