Fix failed package download due to unkown repository type (bnc #386386)
[platform/upstream/libzypp.git] / zypp / PublicKey.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/PublicKey.cc
10  *
11 */
12 #include <iostream>
13
14 //#include "zypp/base/Logger.h"
15
16 #include "zypp/base/String.h"
17 #include "zypp/base/Regex.h"
18 #include "zypp/PublicKey.h"
19 #include "zypp/ExternalProgram.h"
20 #include "zypp/TmpPath.h"
21 #include "zypp/PathInfo.h"
22 #include "zypp/base/Exception.h"
23 #include "zypp/base/Logger.h"
24 #include "zypp/Date.h"
25
26 #include <ctime>
27
28 using std::endl;
29
30 ///////////////////////////////////////////////////////////////////
31 namespace zypp
32 { /////////////////////////////////////////////////////////////////    
33   //
34   //    CLASS NAME : PublicKey::Impl
35   //
36   /** PublicKey implementation. */
37   struct PublicKey::Impl
38   {
39     Impl()
40     {}
41
42     Impl(const Pathname &file)
43     {
44       readFromFile(file);
45       MIL << "Done reading key" << std::endl;
46     }
47     
48     public:
49       /** Offer default Impl. */
50       static shared_ptr<Impl> nullimpl()
51       {
52         static shared_ptr<Impl> _nullimpl( new Impl );
53         return _nullimpl;
54       }
55
56      
57     std::string asString() const
58     {
59       return "[" + id() + "] [" + name() + "] [" + fingerprint() + "]";
60     }
61     
62     std::string armoredData() const
63     { return _data; }
64     
65     std::string id() const
66     { return _id; }
67     
68     std::string name() const
69     { return _name; }
70     
71     std::string fingerprint() const
72     { return _fingerprint; }
73
74     Date created() const
75     { return _created; }
76
77     Date expires() const
78     { return _expires; }
79     
80     Pathname path() const
81     { 
82       return _data_file.path();
83       //return _data_file;
84     }
85     
86     protected:
87
88       // create Date from a string in format YYYY-MM-DD
89       Date createDate(const std::string &datestr)
90       {
91         // empty input
92         if (datestr.empty())
93         {
94             return Date();
95         }
96
97         tm date;
98         memset(&date, 0, sizeof(date));
99
100         try
101         {
102             // set the date
103             date.tm_year = str::strtonum<int>(std::string(datestr, 0, 4)) - 1900; // years since 1900
104             date.tm_mon = str::strtonum<int>(std::string(datestr, 5, 2)) - 1;     // months since January
105             date.tm_mday = str::strtonum<int>(std::string(datestr, 9, 2));        // day
106         }
107         catch(...)
108         {
109             WAR << "Cannot parse date string: " << datestr << std::endl;
110             return Date();
111         }
112
113         time_t time_epoch = ::mktime(&date);
114
115         return Date(time_epoch);
116      }
117       
118      void readFromFile( const Pathname &keyfile)
119      {
120        static str::regex rxColons("^([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):\n$");
121        
122        PathInfo info(keyfile);
123        MIL << "Reading pubkey from " << keyfile << " of size " << info.size() << " and sha1 " << filesystem::checksum(keyfile, "sha1")<< endl; 
124        if ( !info.isExist() )
125          ZYPP_THROW(Exception("Can't read public key from " + keyfile.asString() + ", file not found"));
126          
127        if ( copy( keyfile, _data_file.path() ) != 0 )
128          ZYPP_THROW(Exception("Can't copy public key data from " + keyfile.asString() + " to " +  _data_file.path().asString() ));
129
130        
131        filesystem::TmpDir dir;
132   
133         const char* argv[] =
134         {
135           "gpg",
136           "--no-default-keyring",
137           "--homedir",
138           dir.path().asString().c_str(),
139           "--with-fingerprint",
140           "--with-colons",
141           "--quiet",
142           "--no-tty",
143           "--no-greeting",
144           "--batch",
145           "--status-fd",
146           "1",
147           _data_file.path().asString().c_str(),
148           NULL
149         };
150   
151         ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
152   
153         std::string line;
154         int count = 0;
155   
156       // pub:-:1024:17:A84EDAE89C800ACA:2000-10-19:2008-06-21::-:SuSE Package Signing Key <build@suse.de>:
157   
158         for(line = prog.receiveLine(), count=0; !line.empty(); line = prog.receiveLine(), count++ )
159         {
160         //MIL << "[" << line << "]" << std::endl;
161           str::smatch what;
162           if(str::regex_match(line, what, rxColons))
163           {
164             if ( what[1] == "pub" )
165             {
166               _id = what[5];
167               _name = what[10];
168               //replace all escaped semicolon with real
169               str::replace_all(_name,"\\x3a",":");
170
171               _created = createDate(what[6]);
172               _expires = createDate(what[7]);
173             //return key;
174             }
175             else if ( what[1] == "fpr" )
176             {
177                 _fingerprint = what[10];
178             }
179           //dumpRegexpResults(what);
180           }
181         }
182         prog.close();
183         
184         if (_id.size() == 0 )
185           ZYPP_THROW(BadKeyException("File " + keyfile.asString() + " doesn't contain public key data" , keyfile));
186      }
187     
188   private:
189     std::string _id;
190     std::string _name;
191     std::string _fingerprint;
192     std::string _data;
193     filesystem::TmpFile _data_file;
194     Date _created;
195     Date _expires;
196     //Pathname _data_file;
197   private:
198     friend Impl * rwcowClone<Impl>( const Impl * rhs );
199     /** clone for RWCOW_pointer */
200     Impl * clone() const
201     { return new Impl( *this ); }
202   };
203   ///////////////////////////////////////////////////////////////////
204
205   ///////////////////////////////////////////////////////////////////
206   //
207   //    METHOD NAME : PublicKey::PublicKey
208   //    METHOD TYPE : Ctor
209   //
210   PublicKey::PublicKey()
211   : _pimpl( Impl::nullimpl() )
212   {}
213
214   PublicKey::PublicKey( const Pathname &file )
215   : _pimpl( new Impl(file) )
216   {}
217   ///////////////////////////////////////////////////////////////////
218   //
219   //    METHOD NAME : PublicKey::~PublicKey
220   //    METHOD TYPE : Dtor
221   //
222   PublicKey::~PublicKey()
223   {}
224
225   ///////////////////////////////////////////////////////////////////
226   //
227   // Forward to implementation:
228   //
229   ///////////////////////////////////////////////////////////////////
230
231   std::string PublicKey::asString() const
232   {
233     return _pimpl->asString();
234   }
235   
236   std::string PublicKey::armoredData() const
237   { return _pimpl->armoredData(); }
238     
239   std::string PublicKey::id() const
240   { return _pimpl->id(); }
241     
242   std::string PublicKey::name() const
243   { return _pimpl->name(); }
244     
245   std::string PublicKey::fingerprint() const
246   { return _pimpl->fingerprint(); }
247
248   Date PublicKey::created() const
249   { return _pimpl->created(); }
250
251   Date PublicKey::expires() const
252   { return _pimpl->expires(); }
253   
254   Pathname PublicKey::path() const
255   { return _pimpl->path(); }
256
257   bool PublicKey::operator==( PublicKey b ) const
258   {
259     return (b.id() == id()) && (b.fingerprint() == fingerprint() );
260   }
261     
262   bool PublicKey::operator==( std::string sid ) const
263   {
264     return sid == id();
265   }
266   
267   /////////////////////////////////////////////////////////////////
268 } // namespace zypp
269 ///////////////////////////////////////////////////////////////////