Remove obsolete ResStatus bits.
[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 #include <vector>
14
15 //#include "zypp/base/Logger.h"
16
17 #include "zypp/base/String.h"
18 #include "zypp/base/Regex.h"
19 #include "zypp/PublicKey.h"
20 #include "zypp/ExternalProgram.h"
21 #include "zypp/TmpPath.h"
22 #include "zypp/PathInfo.h"
23 #include "zypp/base/Exception.h"
24 #include "zypp/base/Logger.h"
25 #include "zypp/Date.h"
26 #include "zypp/TmpPath.h"
27
28 #include <ctime>
29
30 using std::endl;
31
32 ///////////////////////////////////////////////////////////////////
33 namespace zypp
34 { /////////////////////////////////////////////////////////////////
35
36   /////////////////////////////////////////////////////////////////
37   //
38   //    CLASS NAME : PublicKey::Impl
39   //
40   /** PublicKey implementation. */
41   struct PublicKey::Impl
42   {
43     Impl()
44     {}
45
46     Impl( const Pathname & keyfile )
47     {
48       PathInfo info( keyfile );
49       MIL << "Takeing pubkey from " << keyfile << " of size " << info.size() << " and sha1 " << filesystem::checksum(keyfile, "sha1") << endl;
50
51       if ( !info.isExist() )
52         ZYPP_THROW(Exception("Can't read public key from " + keyfile.asString() + ", file not found"));
53
54       if ( copy( keyfile, _data_file.path() ) != 0 )
55         ZYPP_THROW(Exception("Can't copy public key data from " + keyfile.asString() + " to " +  _data_file.path().asString() ));
56
57       readFromFile();
58     }
59
60     Impl( const filesystem::TmpFile & sharedfile )
61       : _data_file( sharedfile )
62     { readFromFile(); }
63
64     public:
65       /** Offer default Impl. */
66       static shared_ptr<Impl> nullimpl()
67       {
68         static shared_ptr<Impl> _nullimpl( new Impl );
69         return _nullimpl;
70       }
71
72       std::string asString() const
73       { return "[" + id() + "-" + str::hexstring(created(),8).substr(2) + "] [" + name() + "] [" + fingerprint() + "]"; }
74
75       std::string armoredData() const
76       { return _data; }
77
78       std::string id() const
79       { return _id; }
80
81       std::string name() const
82       { return _name; }
83
84       std::string fingerprint() const
85       { return _fingerprint; }
86
87       Date created() const
88       { return _created; }
89
90       Date expires() const
91       { return _expires; }
92
93       Pathname path() const
94       { return _data_file.path(); }
95
96     protected:
97
98       void readFromFile()
99       {
100         PathInfo info( _data_file.path() );
101         MIL << "Reading pubkey from " << info.path() << " of size " << info.size() << " and sha1 " << filesystem::checksum(info.path(), "sha1") << endl;
102
103         static filesystem::TmpDir dir;
104         const char* argv[] =
105         {
106           "gpg",
107           "-v",
108           "--no-default-keyring",
109           "--fixed-list-mode",
110           "--with-fingerprint",
111           "--with-colons",
112           "--homedir",
113           dir.path().asString().c_str(),
114           "--quiet",
115           "--no-tty",
116           "--no-greeting",
117           "--batch",
118           "--status-fd",
119           "1",
120           _data_file.path().asString().c_str(),
121           NULL
122         };
123
124         ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
125
126         std::string line;
127         bool sawpub = false;
128         bool sawsig = false;
129
130         // pub:-:1024:17:A84EDAE89C800ACA:971961473:1214043198::-:SuSE Package Signing Key <build@suse.de>:
131         // fpr:::::::::79C179B2E1C820C1890F9994A84EDAE89C800ACA:
132         // sig:::17:A84EDAE89C800ACA:1087899198:::::[selfsig]::13x:
133         // sig:::17:9E40E310000AABA4:980442706::::[User ID not found]:10x:
134         // sig:::1:77B2E6003D25D3D9:980443247::::[User ID not found]:10x:
135         // sub:-:2048:16:197448E88495160C:971961490:1214043258::: [expires: 2008-06-21]
136         // sig:::17:A84EDAE89C800ACA:1087899258:::::[keybind]::18x:
137
138         for ( line = prog.receiveLine(); !line.empty(); line = prog.receiveLine() )
139         {
140           // trim trailing NL.
141           if ( line.empty() )
142             continue;
143           if ( line[line.size()-1] == '\n' )
144             line.erase( line.size()-1 );
145
146           // split at ':'
147           std::vector<std::string> words;
148           str::splitFields( line, std::back_inserter(words), ":" );
149           if( words.empty() )
150             continue;
151
152           if ( words[0] == "pub" )
153           {
154             if ( sawpub )
155               continue;
156             sawpub = true;
157             // take default from pub
158             _id      = words[4];
159             _name    = words[9];
160             _created = Date(str::strtonum<Date::ValueType>(words[5]));
161             _expires = Date(str::strtonum<Date::ValueType>(words[6]));
162
163           }
164           else if ( words[0] == "sig" )
165           {
166             if ( sawsig || words[words.size()-2] != "13x"  )
167               continue;
168             sawsig = true;
169             // update creation and expire dates from 1st signature type "13x"
170             if ( ! words[5].empty() )
171               _created = Date(str::strtonum<Date::ValueType>(words[5]));
172             if ( ! words[6].empty() )
173               _expires = Date(str::strtonum<Date::ValueType>(words[6]));
174           }
175           else if ( words[0] == "fpr" )
176           {
177             _fingerprint = words[9];
178           }
179           else if ( words[0] == "uid" )
180           {
181             if ( ! words[9].empty() )
182               _name = words[9];
183           }
184         }
185         prog.close();
186
187         if ( _id.size() == 0 )
188           ZYPP_THROW( BadKeyException( "File " + _data_file.path().asString() + " doesn't contain public key data" , _data_file.path() ) );
189
190         //replace all escaped semicolon with real ':'
191         str::replaceAll( _name, "\\x3a", ":" );
192
193         MIL << "Read pubkey from " << info.path() << ": " << asString() << endl;
194       }
195
196     private:
197       filesystem::TmpFile _data_file;
198
199       std::string _id;
200       std::string _name;
201       std::string _fingerprint;
202       std::string _data;
203       Date        _created;
204       Date        _expires;
205
206     private:
207       friend Impl * rwcowClone<Impl>( const Impl * rhs );
208       /** clone for RWCOW_pointer */
209       Impl * clone() const
210       { return new Impl( *this ); }
211   };
212   ///////////////////////////////////////////////////////////////////
213
214   ///////////////////////////////////////////////////////////////////
215   //
216   //    METHOD NAME : PublicKey::PublicKey
217   //    METHOD TYPE : Ctor
218   //
219   PublicKey::PublicKey()
220   : _pimpl( Impl::nullimpl() )
221   {}
222
223   PublicKey::PublicKey( const Pathname & file )
224   : _pimpl( new Impl(file) )
225   {}
226
227   PublicKey::PublicKey( const filesystem::TmpFile & sharedfile )
228   : _pimpl( new Impl(sharedfile) )
229   {}
230
231   ///////////////////////////////////////////////////////////////////
232   //
233   //    METHOD NAME : PublicKey::~PublicKey
234   //    METHOD TYPE : Dtor
235   //
236   PublicKey::~PublicKey()
237   {}
238
239   ///////////////////////////////////////////////////////////////////
240   //
241   // Forward to implementation:
242   //
243   ///////////////////////////////////////////////////////////////////
244
245   std::string PublicKey::asString() const
246   { return _pimpl->asString(); }
247
248   std::string PublicKey::armoredData() const
249   { return _pimpl->armoredData(); }
250
251   std::string PublicKey::id() const
252   { return _pimpl->id(); }
253
254   std::string PublicKey::name() const
255   { return _pimpl->name(); }
256
257   std::string PublicKey::fingerprint() const
258   { return _pimpl->fingerprint(); }
259
260   Date PublicKey::created() const
261   { return _pimpl->created(); }
262
263   Date PublicKey::expires() const
264   { return _pimpl->expires(); }
265
266   Pathname PublicKey::path() const
267   { return _pimpl->path(); }
268
269   bool PublicKey::operator==( PublicKey b ) const
270   {
271     return (   b.id() == id()
272             && b.fingerprint() == fingerprint()
273             && b.created() == created() );
274   }
275
276   bool PublicKey::operator==( std::string sid ) const
277   {
278     return sid == id();
279   }
280
281   std::ostream & dumpOn( std::ostream & str, const PublicKey & obj )
282   {
283     str << "[" << obj.name() << "]" << endl;
284     str << "  fpr " << obj.fingerprint() << endl;
285     str << "   id " << obj.id() << endl;
286     str << "  cre " << obj.created() << endl;
287     str << "  exp " << obj.expires() << endl;
288     str << "]";
289     return str;
290   }
291
292   /////////////////////////////////////////////////////////////////
293 } // namespace zypp
294 ///////////////////////////////////////////////////////////////////