PublicKey.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <climits>
00013
00014 #include <iostream>
00015 #include <vector>
00016
00017
00018
00019 #include "zypp/base/Gettext.h"
00020 #include "zypp/base/String.h"
00021 #include "zypp/base/Regex.h"
00022 #include "zypp/PublicKey.h"
00023 #include "zypp/ExternalProgram.h"
00024 #include "zypp/TmpPath.h"
00025 #include "zypp/PathInfo.h"
00026 #include "zypp/base/Exception.h"
00027 #include "zypp/base/Logger.h"
00028 #include "zypp/Date.h"
00029 #include "zypp/TmpPath.h"
00030
00031 #include <ctime>
00032
00033 using std::endl;
00034
00036 namespace zypp
00037 {
00038
00040
00041
00042
00044 struct PublicKey::Impl
00045 {
00046 Impl()
00047 {}
00048
00049 Impl( const Pathname & keyfile )
00050 {
00051 PathInfo info( keyfile );
00052 MIL << "Takeing pubkey from " << keyfile << " of size " << info.size() << " and sha1 " << filesystem::checksum(keyfile, "sha1") << endl;
00053
00054 if ( !info.isExist() )
00055 ZYPP_THROW(Exception("Can't read public key from " + keyfile.asString() + ", file not found"));
00056
00057 if ( copy( keyfile, _data_file.path() ) != 0 )
00058 ZYPP_THROW(Exception("Can't copy public key data from " + keyfile.asString() + " to " + _data_file.path().asString() ));
00059
00060 readFromFile();
00061 }
00062
00063 Impl( const filesystem::TmpFile & sharedfile )
00064 : _data_file( sharedfile )
00065 { readFromFile(); }
00066
00067 public:
00069 static shared_ptr<Impl> nullimpl()
00070 {
00071 static shared_ptr<Impl> _nullimpl( new Impl );
00072 return _nullimpl;
00073 }
00074
00075 std::string asString() const
00076 {
00077 return str::form( "[%s-%s] [%s] [%s] [TTL %d]",
00078 id().c_str(), str::hexstring(created(),8).substr(2).c_str(),
00079 name().c_str(),
00080 fingerprint().c_str(),
00081 daysToLive() );
00082 }
00083
00084 std::string id() const
00085 { return _id; }
00086
00087 std::string name() const
00088 { return _name; }
00089
00090 std::string fingerprint() const
00091 { return _fingerprint; }
00092
00093 std::string gpgPubkeyVersion() const
00094 { return _id.empty() ? _id : str::toLower( _id.substr(8,8) ); }
00095
00096 std::string gpgPubkeyRelease() const
00097 { return _created ? str::hexstring( _created ).substr(2) : std::string(); }
00098
00099 Date created() const
00100 { return _created; }
00101
00102 Date expires() const
00103 { return _expires; }
00104
00105 std::string expiresAsString() const
00106 {
00107 if ( !_expires )
00108 {
00109 return _("(does not expire)");
00110 }
00111 std::string ret( _expires.asString() );
00112 int ttl( daysToLive() );
00113 if ( ttl <= 90 )
00114 {
00115 ret += " ";
00116 if ( ttl < 0 )
00117 {
00118 ret += _("(EXPIRED)");
00119 }
00120 else if ( ttl == 0 )
00121 {
00122 ret += _("(expires within 24h)");
00123 }
00124 else
00125 {
00126 ret += str::form( _PL("(expires in %d day)", "(expires in %d days)", ttl ), ttl );
00127 }
00128 }
00129 return ret;
00130 }
00131
00132 Pathname path() const
00133 { return _data_file.path(); }
00134
00135 bool expired() const
00136 {
00137 Date exp( expires() );
00138 return( exp && exp < Date::now() );
00139 }
00140
00141 int daysToLive() const
00142 {
00143 Date exp( expires() );
00144 if ( ! expires() )
00145 return INT_MAX;
00146 exp -= Date::now();
00147 return exp < 0 ? exp / Date::day - 1 : exp / Date::day;
00148 }
00149
00150 protected:
00151
00152 void readFromFile()
00153 {
00154 PathInfo info( _data_file.path() );
00155 MIL << "Reading pubkey from " << info.path() << " of size " << info.size() << " and sha1 " << filesystem::checksum(info.path(), "sha1") << endl;
00156
00157 static filesystem::TmpDir dir;
00158 const char* argv[] =
00159 {
00160 "gpg",
00161 "-v",
00162 "--no-default-keyring",
00163 "--fixed-list-mode",
00164 "--with-fingerprint",
00165 "--with-colons",
00166 "--homedir",
00167 dir.path().asString().c_str(),
00168 "--quiet",
00169 "--no-tty",
00170 "--no-greeting",
00171 "--batch",
00172 "--status-fd",
00173 "1",
00174 _data_file.path().asString().c_str(),
00175 NULL
00176 };
00177
00178 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
00179
00180 std::string line;
00181 bool sawpub = false;
00182 bool sawsig = false;
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 for ( line = prog.receiveLine(); !line.empty(); line = prog.receiveLine() )
00193 {
00194
00195 if ( line.empty() )
00196 continue;
00197 if ( line[line.size()-1] == '\n' )
00198 line.erase( line.size()-1 );
00199
00200
00201 std::vector<std::string> words;
00202 str::splitFields( line, std::back_inserter(words), ":" );
00203 if( words.empty() )
00204 continue;
00205
00206 if ( words[0] == "pub" )
00207 {
00208 if ( sawpub )
00209 continue;
00210 sawpub = true;
00211
00212 _id = words[4];
00213 _name = words[9];
00214 _created = Date(str::strtonum<Date::ValueType>(words[5]));
00215 _expires = Date(str::strtonum<Date::ValueType>(words[6]));
00216
00217 }
00218 else if ( words[0] == "sig" )
00219 {
00220 if ( sawsig || words[words.size()-2] != "13x" )
00221 continue;
00222 sawsig = true;
00223
00224 if ( ! words[5].empty() )
00225 _created = Date(str::strtonum<Date::ValueType>(words[5]));
00226 if ( ! words[6].empty() )
00227 _expires = Date(str::strtonum<Date::ValueType>(words[6]));
00228 }
00229 else if ( words[0] == "fpr" )
00230 {
00231 _fingerprint = words[9];
00232 }
00233 else if ( words[0] == "uid" )
00234 {
00235 if ( ! words[9].empty() )
00236 _name = words[9];
00237 }
00238 }
00239 prog.close();
00240
00241 if ( _id.size() == 0 )
00242 ZYPP_THROW( BadKeyException( "File " + _data_file.path().asString() + " doesn't contain public key data" , _data_file.path() ) );
00243
00244
00245 str::replaceAll( _name, "\\x3a", ":" );
00246
00247 MIL << "Read pubkey from " << info.path() << ": " << asString() << endl;
00248 }
00249
00250 private:
00251 filesystem::TmpFile _data_file;
00252
00253 std::string _id;
00254 std::string _name;
00255 std::string _fingerprint;
00256 Date _created;
00257 Date _expires;
00258
00259 private:
00260 friend Impl * rwcowClone<Impl>( const Impl * rhs );
00262 Impl * clone() const
00263 { return new Impl( *this ); }
00264 };
00266
00268
00269
00270
00271
00272 PublicKey::PublicKey()
00273 : _pimpl( Impl::nullimpl() )
00274 {}
00275
00276 PublicKey::PublicKey( const Pathname & file )
00277 : _pimpl( new Impl(file) )
00278 {}
00279
00280 PublicKey::PublicKey( const filesystem::TmpFile & sharedfile )
00281 : _pimpl( new Impl(sharedfile) )
00282 {}
00283
00285
00286
00287
00288
00289 PublicKey::~PublicKey()
00290 {}
00291
00293
00294
00295
00297
00298 std::string PublicKey::asString() const
00299 { return _pimpl->asString(); }
00300
00301 std::string PublicKey::id() const
00302 { return _pimpl->id(); }
00303
00304 std::string PublicKey::name() const
00305 { return _pimpl->name(); }
00306
00307 std::string PublicKey::fingerprint() const
00308 { return _pimpl->fingerprint(); }
00309
00310 std::string PublicKey::gpgPubkeyVersion() const
00311 { return _pimpl->gpgPubkeyVersion(); }
00312
00313 std::string PublicKey::gpgPubkeyRelease() const
00314 { return _pimpl->gpgPubkeyRelease(); }
00315
00316 Date PublicKey::created() const
00317 { return _pimpl->created(); }
00318
00319 Date PublicKey::expires() const
00320 { return _pimpl->expires(); }
00321
00322 std::string PublicKey::expiresAsString() const
00323 { return _pimpl->expiresAsString(); }
00324
00325 bool PublicKey::expired() const
00326 { return _pimpl->expired(); }
00327
00328 int PublicKey::daysToLive() const
00329 { return _pimpl->daysToLive(); }
00330
00331 Pathname PublicKey::path() const
00332 { return _pimpl->path(); }
00333
00334 bool PublicKey::operator==( PublicKey b ) const
00335 {
00336 return ( b.id() == id()
00337 && b.fingerprint() == fingerprint()
00338 && b.created() == created() );
00339 }
00340
00341 bool PublicKey::operator==( std::string sid ) const
00342 {
00343 return sid == id();
00344 }
00345
00346 std::ostream & dumpOn( std::ostream & str, const PublicKey & obj )
00347 {
00348 str << "[" << obj.name() << "]" << endl;
00349 str << " fpr " << obj.fingerprint() << endl;
00350 str << " id " << obj.id() << endl;
00351 str << " cre " << obj.created() << endl;
00352 str << " exp " << obj.expiresAsString() << endl;
00353 str << " ttl " << obj.daysToLive() << endl;
00354 str << " rpm " << obj.gpgPubkeyVersion() << "-" << obj.gpgPubkeyRelease() << endl;
00355 str << "]";
00356 return str;
00357 }
00358
00360 }