00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <vector>
00014
00015 #include "zypp/base/Logger.h"
00016 #include "zypp/base/Exception.h"
00017 #include "zypp/base/String.h"
00018
00019 #include "zypp/ExternalProgram.h"
00020 #include "zypp/PublicKey.h"
00021 #include "zypp/TmpPath.h"
00022 #include "zypp/PathInfo.h"
00023 #include "zypp/Date.h"
00024 #include "zypp/TmpPath.h"
00025
00026 using std::endl;
00027
00029 namespace zypp
00030 {
00031
00032
00033
00035 struct PublicKey::Impl
00036 {
00037 Impl()
00038 {}
00039
00040 Impl(const Pathname &file)
00041 {
00042 readFromFile(file);
00043 MIL << "Done reading key" << std::endl;
00044 }
00045
00046 public:
00048 static shared_ptr<Impl> nullimpl()
00049 {
00050 static shared_ptr<Impl> _nullimpl( new Impl );
00051 return _nullimpl;
00052 }
00053
00054 std::string asString() const
00055 {
00056 return "[" + id() + "-" + str::hexstring(created(),8).substr(2) + "] [" + name() + "] [" + fingerprint() + "]";
00057 }
00058
00059 std::string armoredData() const
00060 { return _data; }
00061
00062 std::string id() const
00063 { return _id; }
00064
00065 std::string name() const
00066 { return _name; }
00067
00068 std::string fingerprint() const
00069 { return _fingerprint; }
00070
00071 Date created() const
00072 { return _created; }
00073
00074 Date expires() const
00075 { return _expires; }
00076
00077 Pathname path() const
00078 {
00079 return _data_file.path();
00080
00081 }
00082
00083 protected:
00084
00085 void readFromFile( const Pathname &keyfile)
00086 {
00087
00088 PathInfo info(keyfile);
00089 MIL << "Reading pubkey from " << keyfile << " of size " << info.size() << " and sha1 " << filesystem::checksum(keyfile, "sha1")<< endl;
00090 if ( !info.isExist() )
00091 ZYPP_THROW(Exception("Can't read public key from " + keyfile.asString() + ", file not found"));
00092
00093 if ( copy( keyfile, _data_file.path() ) != 0 )
00094 ZYPP_THROW(Exception("Can't copy public key data from " + keyfile.asString() + " to " + _data_file.path().asString() ));
00095
00096 filesystem::TmpDir dir;
00097 const char* argv[] =
00098 {
00099 "gpg",
00100 "-v",
00101 "--no-default-keyring",
00102 "--fixed-list-mode",
00103 "--with-fingerprint",
00104 "--with-colons",
00105 "--homedir",
00106 dir.path().asString().c_str(),
00107 "--quiet",
00108 "--no-tty",
00109 "--no-greeting",
00110 "--batch",
00111 "--status-fd",
00112 "1",
00113 _data_file.path().asString().c_str(),
00114 NULL
00115 };
00116
00117 ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true);
00118
00119 std::string line;
00120 bool sawpub = false;
00121 bool sawsig = false;
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 for ( line = prog.receiveLine(); !line.empty(); line = prog.receiveLine() )
00132 {
00133
00134 if ( line.empty() )
00135 continue;
00136 if ( line[line.size()-1] == '\n' )
00137 line.erase( line.size()-1 );
00138
00139
00140 std::vector<std::string> words;
00141 str::splitFields( line, std::back_inserter(words), ":" );
00142 if( words.empty() )
00143 continue;
00144
00145 if ( words[0] == "pub" )
00146 {
00147 if ( sawpub )
00148 continue;
00149 sawpub = true;
00150
00151 _id = words[4];
00152 _name = words[9];
00153 _created = Date(str::strtonum<Date::ValueType>(words[5]));
00154 _expires = Date(str::strtonum<Date::ValueType>(words[6]));
00155
00156 }
00157 else if ( words[0] == "sig" )
00158 {
00159 if ( sawsig || words[words.size()-2] != "13x" )
00160 continue;
00161 sawsig = true;
00162
00163 if ( ! words[5].empty() )
00164 _created = Date(str::strtonum<Date::ValueType>(words[5]));
00165 if ( ! words[6].empty() )
00166 _expires = Date(str::strtonum<Date::ValueType>(words[6]));
00167 }
00168 else if ( words[0] == "fpr" )
00169 {
00170 _fingerprint = words[9];
00171 }
00172 else if ( words[0] == "uid" )
00173 {
00174 if ( ! words[9].empty() )
00175 _name = words[9];
00176 }
00177 }
00178 prog.close();
00179
00180 if ( _id.size() == 0 )
00181 ZYPP_THROW( BadKeyException( "File " + keyfile.asString() + " doesn't contain public key data" , keyfile ) );
00182
00183
00184 str::replace_all( _name, "\\x3a", ":" );
00185 }
00186
00187 private:
00188 std::string _id;
00189 std::string _name;
00190 std::string _fingerprint;
00191 std::string _data;
00192 filesystem::TmpFile _data_file;
00193 Date _created;
00194 Date _expires;
00195
00196 private:
00197 friend Impl * rwcowClone<Impl>( const Impl * rhs );
00199 Impl * clone() const
00200 { return new Impl( *this ); }
00201 };
00203
00205
00206
00207
00208
00209 PublicKey::PublicKey()
00210 : _pimpl( Impl::nullimpl() )
00211 {}
00212
00213 PublicKey::PublicKey( const Pathname &file )
00214 : _pimpl( new Impl(file) )
00215 {
00216 MIL << *this << endl;
00217 }
00219
00220
00221
00222
00223 PublicKey::~PublicKey()
00224 {}
00225
00227
00228
00229
00231
00232 std::string PublicKey::asString() const
00233 {
00234 return _pimpl->asString();
00235 }
00236
00237 std::string PublicKey::armoredData() const
00238 { return _pimpl->armoredData(); }
00239
00240 std::string PublicKey::id() const
00241 { return _pimpl->id(); }
00242
00243 std::string PublicKey::name() const
00244 { return _pimpl->name(); }
00245
00246 std::string PublicKey::fingerprint() const
00247 { return _pimpl->fingerprint(); }
00248
00249 Date PublicKey::created() const
00250 { return _pimpl->created(); }
00251
00252 Date PublicKey::expires() const
00253 { return _pimpl->expires(); }
00254
00255 Pathname PublicKey::path() const
00256 { return _pimpl->path(); }
00257
00258 bool PublicKey::operator==( PublicKey b ) const
00259 {
00260 return( b.id() == id()
00261 && b.fingerprint() == fingerprint()
00262 && b.created() == created() );
00263 }
00264
00265 bool PublicKey::operator==( std::string sid ) const
00266 {
00267 return sid == id();
00268 }
00269
00270 std::ostream & dumpOn( std::ostream & str, const PublicKey & obj )
00271 {
00272 str << "[" << obj.name() << "]" << endl;
00273 str << " fpr " << obj.fingerprint() << endl;
00274 str << " id " << obj.id() << endl;
00275 str << " cre " << obj.created() << endl;
00276 str << " exp " << obj.expires() << endl;
00277 str << "]";
00278 return str;
00279 }
00280
00282 }