1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/PublicKey.cc
17 //#include "zypp/base/Logger.h"
19 #include "zypp/base/Gettext.h"
20 #include "zypp/base/String.h"
21 #include "zypp/base/Regex.h"
22 #include "zypp/PublicKey.h"
23 #include "zypp/ExternalProgram.h"
24 #include "zypp/TmpPath.h"
25 #include "zypp/PathInfo.h"
26 #include "zypp/base/Exception.h"
27 #include "zypp/base/Logger.h"
28 #include "zypp/Date.h"
29 #include "zypp/TmpPath.h"
35 ///////////////////////////////////////////////////////////////////
37 { /////////////////////////////////////////////////////////////////
39 /////////////////////////////////////////////////////////////////
41 // CLASS NAME : PublicKey::Impl
43 /** PublicKey implementation. */
44 struct PublicKey::Impl
49 Impl( const Pathname & keyfile )
51 PathInfo info( keyfile );
52 MIL << "Takeing pubkey from " << keyfile << " of size " << info.size() << " and sha1 " << filesystem::checksum(keyfile, "sha1") << endl;
54 if ( !info.isExist() )
55 ZYPP_THROW(Exception("Can't read public key from " + keyfile.asString() + ", file not found"));
57 if ( copy( keyfile, _data_file.path() ) != 0 )
58 ZYPP_THROW(Exception("Can't copy public key data from " + keyfile.asString() + " to " + _data_file.path().asString() ));
63 Impl( const filesystem::TmpFile & sharedfile )
64 : _data_file( sharedfile )
68 /** Offer default Impl. */
69 static shared_ptr<Impl> nullimpl()
71 static shared_ptr<Impl> _nullimpl( new Impl );
75 std::string asString() const
77 return str::form( "[%s-%s] [%s] [%s] [TTL %d]",
78 id().c_str(), str::hexstring(created(),8).substr(2).c_str(),
80 fingerprint().c_str(),
84 std::string id() const
87 std::string name() const
90 std::string fingerprint() const
91 { return _fingerprint; }
93 std::string gpgPubkeyVersion() const
94 { return _id.empty() ? _id : str::toLower( _id.substr(8,8) ); }
96 std::string gpgPubkeyRelease() const
97 { return _created ? str::hexstring( _created ).substr(2) : std::string(); }
105 std::string expiresAsString() const
108 { // translators: an annotation to a gpg keys expiry date
109 return _("(does not expire)");
111 std::string ret( _expires.asString() );
112 int ttl( daysToLive() );
117 { // translators: an annotation to a gpg keys expiry date
118 ret += _("(EXPIRED)");
121 { // translators: an annotation to a gpg keys expiry date
122 ret += _("(expires within 24h)");
125 { // translators: an annotation to a gpg keys expiry date
126 ret += str::form( _PL("(expires in %d day)", "(expires in %d days)", ttl ), ttl );
132 Pathname path() const
133 { return _data_file.path(); }
137 Date exp( expires() );
138 return( exp && exp < Date::now() );
141 int daysToLive() const
143 Date exp( expires() );
147 return exp < 0 ? exp / Date::day - 1 : exp / Date::day;
154 PathInfo info( _data_file.path() );
155 MIL << "Reading pubkey from " << info.path() << " of size " << info.size() << " and sha1 " << filesystem::checksum(info.path(), "sha1") << endl;
157 static filesystem::TmpDir dir;
162 "--no-default-keyring",
164 "--with-fingerprint",
167 dir.path().asString().c_str(),
174 _data_file.path().asString().c_str(),
178 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
184 // pub:-:1024:17:A84EDAE89C800ACA:971961473:1214043198::-:SuSE Package Signing Key <build@suse.de>:
185 // fpr:::::::::79C179B2E1C820C1890F9994A84EDAE89C800ACA:
186 // sig:::17:A84EDAE89C800ACA:1087899198:::::[selfsig]::13x:
187 // sig:::17:9E40E310000AABA4:980442706::::[User ID not found]:10x:
188 // sig:::1:77B2E6003D25D3D9:980443247::::[User ID not found]:10x:
189 // sub:-:2048:16:197448E88495160C:971961490:1214043258::: [expires: 2008-06-21]
190 // sig:::17:A84EDAE89C800ACA:1087899258:::::[keybind]::18x:
192 for ( line = prog.receiveLine(); !line.empty(); line = prog.receiveLine() )
197 if ( line[line.size()-1] == '\n' )
198 line.erase( line.size()-1 );
201 std::vector<std::string> words;
202 str::splitFields( line, std::back_inserter(words), ":" );
206 if ( words[0] == "pub" )
211 // take default from pub
214 _created = Date(str::strtonum<Date::ValueType>(words[5]));
215 _expires = Date(str::strtonum<Date::ValueType>(words[6]));
218 else if ( words[0] == "sig" )
220 if ( sawsig || words[words.size()-2] != "13x" )
223 // update creation and expire dates from 1st signature type "13x"
224 if ( ! words[5].empty() )
225 _created = Date(str::strtonum<Date::ValueType>(words[5]));
226 if ( ! words[6].empty() )
227 _expires = Date(str::strtonum<Date::ValueType>(words[6]));
229 else if ( words[0] == "fpr" )
231 _fingerprint = words[9];
233 else if ( words[0] == "uid" )
235 if ( ! words[9].empty() )
241 if ( _id.size() == 0 )
242 ZYPP_THROW( BadKeyException( "File " + _data_file.path().asString() + " doesn't contain public key data" , _data_file.path() ) );
244 //replace all escaped semicolon with real ':'
245 str::replaceAll( _name, "\\x3a", ":" );
247 MIL << "Read pubkey from " << info.path() << ": " << asString() << endl;
251 filesystem::TmpFile _data_file;
255 std::string _fingerprint;
260 friend Impl * rwcowClone<Impl>( const Impl * rhs );
261 /** clone for RWCOW_pointer */
263 { return new Impl( *this ); }
265 ///////////////////////////////////////////////////////////////////
267 ///////////////////////////////////////////////////////////////////
269 // METHOD NAME : PublicKey::PublicKey
270 // METHOD TYPE : Ctor
272 PublicKey::PublicKey()
273 : _pimpl( Impl::nullimpl() )
276 PublicKey::PublicKey( const Pathname & file )
277 : _pimpl( new Impl(file) )
280 PublicKey::PublicKey( const filesystem::TmpFile & sharedfile )
281 : _pimpl( new Impl(sharedfile) )
284 ///////////////////////////////////////////////////////////////////
286 // METHOD NAME : PublicKey::~PublicKey
287 // METHOD TYPE : Dtor
289 PublicKey::~PublicKey()
292 ///////////////////////////////////////////////////////////////////
294 // Forward to implementation:
296 ///////////////////////////////////////////////////////////////////
298 std::string PublicKey::asString() const
299 { return _pimpl->asString(); }
301 std::string PublicKey::id() const
302 { return _pimpl->id(); }
304 std::string PublicKey::name() const
305 { return _pimpl->name(); }
307 std::string PublicKey::fingerprint() const
308 { return _pimpl->fingerprint(); }
310 std::string PublicKey::gpgPubkeyVersion() const
311 { return _pimpl->gpgPubkeyVersion(); }
313 std::string PublicKey::gpgPubkeyRelease() const
314 { return _pimpl->gpgPubkeyRelease(); }
316 Date PublicKey::created() const
317 { return _pimpl->created(); }
319 Date PublicKey::expires() const
320 { return _pimpl->expires(); }
322 std::string PublicKey::expiresAsString() const
323 { return _pimpl->expiresAsString(); }
325 bool PublicKey::expired() const
326 { return _pimpl->expired(); }
328 int PublicKey::daysToLive() const
329 { return _pimpl->daysToLive(); }
331 Pathname PublicKey::path() const
332 { return _pimpl->path(); }
334 bool PublicKey::operator==( PublicKey b ) const
336 return ( b.id() == id()
337 && b.fingerprint() == fingerprint()
338 && b.created() == created() );
341 bool PublicKey::operator==( std::string sid ) const
346 std::ostream & dumpOn( std::ostream & str, const PublicKey & obj )
348 str << "[" << obj.name() << "]" << endl;
349 str << " fpr " << obj.fingerprint() << endl;
350 str << " id " << obj.id() << endl;
351 str << " cre " << obj.created() << endl;
352 str << " exp " << obj.expiresAsString() << endl;
353 str << " ttl " << obj.daysToLive() << endl;
354 str << " rpm " << obj.gpgPubkeyVersion() << "-" << obj.gpgPubkeyRelease() << endl;
359 /////////////////////////////////////////////////////////////////
361 ///////////////////////////////////////////////////////////////////