CredentialManager.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <fstream>
00014
00015 #include "zypp/ZConfig.h"
00016 #include "zypp/base/Function.h"
00017 #include "zypp/base/Logger.h"
00018 #include "zypp/base/Easy.h"
00019 #include "zypp/PathInfo.h"
00020
00021 #include "zypp/media/CredentialFileReader.h"
00022
00023 #include "zypp/media/CredentialManager.h"
00024
00025 #define USER_CREDENTIALS_FILE ".zypp/credentials.cat"
00026
00027 using namespace std;
00028
00030 namespace zypp
00031 {
00032
00033 namespace media
00034 {
00035
00037
00038
00039
00041
00042 const url::ViewOption AuthDataComparator::vopt =
00043 url::ViewOption::DEFAULTS
00044 - url::ViewOption::WITH_USERNAME
00045 - url::ViewOption::WITH_PASSWORD
00046 - url::ViewOption::WITH_QUERY_STR;
00047
00048 bool
00049 AuthDataComparator::operator()(
00050 const AuthData_Ptr & lhs, const AuthData_Ptr & rhs)
00051 {
00052 if (lhs->username() != rhs->username())
00053 return true;
00054
00055 if (lhs->url().asString(vopt) != rhs->url().asString(vopt))
00056 return true;
00057
00058 return false;
00059 }
00060
00062
00063
00064
00066
00067 CredManagerOptions::CredManagerOptions(const Pathname & rootdir)
00068 : globalCredFilePath(rootdir / ZConfig::instance().credentialsGlobalFile())
00069 , customCredFileDir(rootdir / ZConfig::instance().credentialsGlobalDir())
00070 {
00071 char * homedir = getenv("HOME");
00072 if (homedir)
00073 userCredFilePath = rootdir / homedir / USER_CREDENTIALS_FILE;
00074 }
00075
00076
00078
00079
00080
00081 struct CredentialManager::Impl
00082 {
00083 Impl(const CredManagerOptions & options);
00084
00085 ~Impl()
00086 {}
00087
00088 void init_globalCredentials();
00089 void init_userCredentials();
00090
00091 bool processCredentials(AuthData_Ptr & cred);
00092
00093 AuthData_Ptr getCred(const Url & url) const;
00094 AuthData_Ptr getCredFromFile(const Pathname & file);
00095 void saveGlobalCredentials();
00096 void saveUserCredentials();
00097
00098
00099 CredManagerOptions _options;
00100
00101 CredentialSet _credsGlobal;
00102 CredentialSet _credsUser;
00103 CredentialSet _credsTmp;
00104
00105 bool _globalDirty;
00106 bool _userDirty;
00107 };
00109
00110
00112
00113
00114
00116
00117 CredentialManager::Impl::Impl(const CredManagerOptions & options)
00118 : _options(options)
00119 , _globalDirty(false)
00120 , _userDirty(false)
00121 {
00122 init_globalCredentials();
00123 init_userCredentials();
00124 }
00125
00126
00127 void CredentialManager::Impl::init_globalCredentials()
00128 {
00129 if (_options.globalCredFilePath.empty())
00130 DBG << "global cred file not known";
00131 else if (PathInfo(_options.globalCredFilePath).isExist())
00132 {
00133
00134
00135
00136
00137
00138
00139 CredentialFileReader(_options.globalCredFilePath,
00140 bind(&Impl::processCredentials, this, _1));
00141 }
00142 else
00143 DBG << "global cred file does not exist";
00144
00145 _credsGlobal = _credsTmp; _credsTmp.clear();
00146 DBG << "Got " << _credsGlobal.size() << " global records." << endl;
00147 }
00148
00149
00150 void CredentialManager::Impl::init_userCredentials()
00151 {
00152 if (_options.userCredFilePath.empty())
00153 DBG << "user cred file not known";
00154 else if (PathInfo(_options.userCredFilePath).isExist())
00155 {
00156
00157
00158
00159
00160
00161 CredentialFileReader(_options.userCredFilePath,
00162 bind(&Impl::processCredentials, this, _1));
00163 }
00164 else
00165 DBG << "user cred file does not exist" << endl;
00166
00167 _credsUser = _credsTmp; _credsTmp.clear();
00168 DBG << "Got " << _credsUser.size() << " user records." << endl;
00169 }
00170
00171
00172 bool CredentialManager::Impl::processCredentials(AuthData_Ptr & cred)
00173 {
00174 _credsTmp.insert(cred);
00175 return true;
00176 }
00177
00178
00179 static AuthData_Ptr findIn(const CredentialManager::CredentialSet & set,
00180 const Url & url,
00181 url::ViewOption vopt)
00182 {
00183 const string & username = url.getUsername();
00184 for(CredentialManager::CredentialIterator it = set.begin(); it != set.end(); ++it)
00185 {
00186
00187 if (url.asString(vopt).find((*it)->url().asString(vopt)) == 0)
00188 {
00189 if (username.empty() || username == (*it)->username())
00190 return *it;
00191 }
00192 }
00193
00194 return AuthData_Ptr();
00195 }
00196
00197
00198 AuthData_Ptr CredentialManager::Impl::getCred(const Url & url) const
00199 {
00200 AuthData_Ptr result;
00201
00202
00203
00204
00205
00206 url::ViewOption vopt;
00207 vopt = vopt
00208 - url::ViewOption::WITH_USERNAME
00209 - url::ViewOption::WITH_PASSWORD
00210 - url::ViewOption::WITH_QUERY_STR;
00211
00212
00213 result = findIn(_credsGlobal, url, vopt);
00214
00215
00216 if (!result)
00217 result = findIn(_credsUser, url, vopt);
00218
00219 if (result)
00220 DBG << "Found credentials for '" << url << "':" << endl << *result;
00221 else
00222 DBG << "No credentials for '" << url << "'" << endl;
00223
00224 return result;
00225 }
00226
00227
00228 AuthData_Ptr CredentialManager::Impl::getCredFromFile(const Pathname & file)
00229 {
00230 AuthData_Ptr result;
00231
00232 Pathname credfile;
00233 if (file.absolute())
00234
00235 credfile = file;
00236 else
00237
00238 credfile = _options.customCredFileDir / file.basename();
00239
00240 CredentialFileReader(credfile, bind(&Impl::processCredentials, this, _1));
00241 if (_credsTmp.empty())
00242 WAR << file << " does not contain valid credentials or is not readable." << endl;
00243 else
00244 {
00245 result = *_credsTmp.begin();
00246 _credsTmp.clear();
00247 }
00248
00249 return result;
00250 }
00251
00252 static int save_creds_in_file(
00253 const CredentialManager::CredentialSet creds,
00254 const Pathname & file,
00255 const mode_t mode)
00256 {
00257 int ret = 0;
00258 filesystem::assert_dir(file.dirname());
00259
00260 std::ofstream fs(file.c_str());
00261 if (!fs)
00262 ret = 1;
00263
00264 for_(it, creds.begin(), creds.end())
00265 {
00266 (*it)->dumpAsIniOn(fs);
00267 fs << endl;
00268 }
00269 fs.close();
00270
00271 filesystem::chmod(file, mode);
00272
00273 return ret;
00274 }
00275
00276 void CredentialManager::Impl::saveGlobalCredentials()
00277 {
00278 save_creds_in_file(_credsGlobal, _options.globalCredFilePath, 0640);
00279 }
00280
00281 void CredentialManager::Impl::saveUserCredentials()
00282 {
00283 save_creds_in_file(_credsUser, _options.userCredFilePath, 0600);
00284 }
00285
00286
00288
00289
00290
00292
00293 CredentialManager::CredentialManager(const CredManagerOptions & opts)
00294 : _pimpl(new Impl(opts))
00295 {}
00296
00297
00298 AuthData_Ptr CredentialManager::getCred(const Url & url)
00299 {
00300 string credfile = url.getQueryParam("credentials");
00301 if (credfile.empty())
00302 return _pimpl->getCred(url);
00303 return _pimpl->getCredFromFile(credfile);
00304 }
00305
00306
00307 AuthData_Ptr CredentialManager::getCredFromFile(const Pathname & file)
00308 { return _pimpl->getCredFromFile(file); }
00309
00310
00311 void CredentialManager::addCred(const AuthData & cred)
00312 {
00313 Pathname credfile = cred.url().getQueryParam("credentials");
00314 if (credfile.empty())
00316 addUserCred(cred);
00317 else
00318 saveInFile(cred, credfile);
00319 }
00320
00321
00322 void CredentialManager::addGlobalCred(const AuthData & cred)
00323 {
00324 AuthData_Ptr c_ptr;
00325 c_ptr.reset(new AuthData(cred));
00326 pair<CredentialIterator, bool> ret = _pimpl->_credsGlobal.insert(c_ptr);
00327 if (ret.second)
00328 _pimpl->_globalDirty = true;
00329 else if ((*ret.first)->password() != cred.password())
00330 {
00331 _pimpl->_credsGlobal.erase(ret.first);
00332 _pimpl->_credsGlobal.insert(c_ptr);
00333 _pimpl->_globalDirty = true;
00334 }
00335 }
00336
00337
00338 void CredentialManager::addUserCred(const AuthData & cred)
00339 {
00340 AuthData_Ptr c_ptr;
00341 c_ptr.reset(new AuthData(cred));
00342 pair<CredentialIterator, bool> ret = _pimpl->_credsUser.insert(c_ptr);
00343 if (ret.second)
00344 _pimpl->_userDirty = true;
00345 else if ((*ret.first)->password() != cred.password())
00346 {
00347 _pimpl->_credsUser.erase(ret.first);
00348 _pimpl->_credsUser.insert(c_ptr);
00349 _pimpl->_userDirty = true;
00350 }
00351 }
00352
00353
00354 void CredentialManager::save()
00355 {
00356 if (_pimpl->_globalDirty)
00357 _pimpl->saveGlobalCredentials();
00358 if (_pimpl->_userDirty)
00359 _pimpl->saveUserCredentials();
00360 _pimpl->_globalDirty = false;
00361 _pimpl->_userDirty = false;
00362 }
00363
00364
00365 void CredentialManager::saveInGlobal(const AuthData & cred)
00366 {
00367 addGlobalCred(cred);
00368 save();
00369 }
00370
00371
00372 void CredentialManager::saveInUser(const AuthData & cred)
00373 {
00374 addUserCred(cred);
00375 save();
00376 }
00377
00378
00379 void CredentialManager::saveInFile(const AuthData & cred, const Pathname & credFile)
00380 {
00381 AuthData_Ptr c_ptr;
00382 c_ptr.reset(new AuthData(cred));
00383 c_ptr->setUrl(Url());
00384 CredentialManager::CredentialSet creds;
00385 creds.insert(c_ptr);
00386
00387 int ret;
00388 if (credFile.absolute())
00389 ret = save_creds_in_file(creds, credFile, 0640);
00390 else
00391 ret = save_creds_in_file(
00392 creds, _pimpl->_options.customCredFileDir / credFile, 0600);
00393
00394 if (!ret)
00395 {
00397 ERR << "error saving the credentials" << endl;
00398 }
00399 }
00400
00401
00402 void CredentialManager::clearAll(bool global)
00403 {
00404 if (global)
00405 {
00406 if (!filesystem::unlink(_pimpl->_options.globalCredFilePath))
00407 ERR << "could not delete user credentials file "
00408 << _pimpl->_options.globalCredFilePath << endl;
00409 _pimpl->_credsUser.clear();
00410 }
00411 else
00412 {
00413 if (!filesystem::unlink(_pimpl->_options.userCredFilePath))
00414 ERR << "could not delete global credentials file"
00415 << _pimpl->_options.userCredFilePath << endl;
00416 _pimpl->_credsGlobal.clear();
00417 }
00418 }
00419
00420
00421 CredentialManager::CredentialIterator CredentialManager::credsGlobalBegin() const
00422 { return _pimpl->_credsGlobal.begin(); }
00423
00424 CredentialManager::CredentialIterator CredentialManager::credsGlobalEnd() const
00425 { return _pimpl->_credsGlobal.end(); }
00426
00427 CredentialManager::CredentialSize CredentialManager::credsGlobalSize() const
00428 { return _pimpl->_credsGlobal.size(); }
00429
00430 bool CredentialManager::credsGlobalEmpty() const
00431 { return _pimpl->_credsGlobal.empty(); }
00432
00433
00434 CredentialManager::CredentialIterator CredentialManager::credsUserBegin() const
00435 { return _pimpl->_credsUser.begin(); }
00436
00437 CredentialManager::CredentialIterator CredentialManager::credsUserEnd() const
00438 { return _pimpl->_credsUser.end(); }
00439
00440 CredentialManager::CredentialSize CredentialManager::credsUserSize() const
00441 { return _pimpl->_credsUser.size(); }
00442
00443 bool CredentialManager::credsUserEmpty() const
00444 { return _pimpl->_credsUser.empty(); }
00445
00446
00448 }
00451 }