1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/media/CredentialManager.cc
15 #include "zypp/ZConfig.h"
16 #include "zypp/base/Function.h"
17 #include "zypp/base/Logger.h"
18 #include "zypp/base/Easy.h"
19 #include "zypp/PathInfo.h"
21 #include "zypp/media/CredentialFileReader.h"
23 #include "zypp/media/CredentialManager.h"
25 #define USER_CREDENTIALS_FILE ".zypp/credentials.cat"
29 //////////////////////////////////////////////////////////////////////
31 { ////////////////////////////////////////////////////////////////////
32 //////////////////////////////////////////////////////////////////////
34 { ////////////////////////////////////////////////////////////////////
36 //////////////////////////////////////////////////////////////////////
38 // CLASS NAME : AuthDataComparator
40 //////////////////////////////////////////////////////////////////////
43 AuthDataComparator::operator()(
44 const AuthData_Ptr & lhs, const AuthData_Ptr & rhs)
46 static const url::ViewOption vopt =
47 url::ViewOption::DEFAULTS
48 - url::ViewOption::WITH_USERNAME
49 - url::ViewOption::WITH_PASSWORD
50 - url::ViewOption::WITH_QUERY_STR;
52 if (lhs->username() != rhs->username())
55 if (lhs->url().asString(vopt) != rhs->url().asString(vopt))
61 //////////////////////////////////////////////////////////////////////
63 // CLASS NAME : CredManagerOptions
65 //////////////////////////////////////////////////////////////////////
67 CredManagerOptions::CredManagerOptions(const Pathname & rootdir)
68 : globalCredFilePath(rootdir / ZConfig::instance().credentialsGlobalFile())
69 , customCredFileDir(rootdir / ZConfig::instance().credentialsGlobalDir())
71 char * homedir = getenv("HOME");
73 userCredFilePath = rootdir / homedir / USER_CREDENTIALS_FILE;
77 //////////////////////////////////////////////////////////////////////
79 // CLASS NAME : CredentialManager::Impl
81 struct CredentialManager::Impl
83 Impl(const CredManagerOptions & options);
88 void init_globalCredentials();
89 void init_userCredentials();
91 bool processCredentials(AuthData_Ptr & cred);
93 AuthData_Ptr getCred(const Url & url) const;
94 AuthData_Ptr getCredFromFile(const Pathname & file);
95 void saveGlobalCredentials();
96 void saveUserCredentials();
99 CredManagerOptions _options;
101 CredentialSet _credsGlobal;
102 CredentialSet _credsUser;
103 CredentialSet _credsTmp;
108 //////////////////////////////////////////////////////////////////////
111 //////////////////////////////////////////////////////////////////////
113 // CLASS NAME : CredentialManager::Impl
115 //////////////////////////////////////////////////////////////////////
117 CredentialManager::Impl::Impl(const CredManagerOptions & options)
119 , _globalDirty(false)
122 init_globalCredentials();
123 init_userCredentials();
127 void CredentialManager::Impl::init_globalCredentials()
129 if (_options.globalCredFilePath.empty())
130 DBG << "global cred file not known";
131 else if (PathInfo(_options.globalCredFilePath).isExist())
133 /* list<Pathname> entries;
134 if (filesystem::readdir(entries, _options.globalCredFilePath, false) != 0)
135 ZYPP_THROW(Exception("failed to read directory"));
137 for_(it, entries.begin(), entries.end())*/
139 CredentialFileReader(_options.globalCredFilePath,
140 bind(&Impl::processCredentials, this, _1));
143 DBG << "global cred file does not exist";
145 _credsGlobal = _credsTmp; _credsTmp.clear();
146 DBG << "Got " << _credsGlobal.size() << " global records." << endl;
150 void CredentialManager::Impl::init_userCredentials()
152 if (_options.userCredFilePath.empty())
153 DBG << "user cred file not known";
154 else if (PathInfo(_options.userCredFilePath).isExist())
156 /* list<Pathname> entries;
157 if (filesystem::readdir(entries, _options.userCredFilePath, false ) != 0)
158 ZYPP_THROW(Exception("failed to read directory"));
160 for_(it, entries.begin(), entries.end())*/
161 CredentialFileReader(_options.userCredFilePath,
162 bind(&Impl::processCredentials, this, _1));
165 DBG << "user cred file does not exist" << endl;
167 _credsUser = _credsTmp; _credsTmp.clear();
168 DBG << "Got " << _credsUser.size() << " user records." << endl;
172 bool CredentialManager::Impl::processCredentials(AuthData_Ptr & cred)
174 _credsTmp.insert(cred);
179 static AuthData_Ptr findIn(const CredentialManager::CredentialSet & set,
181 url::ViewOption vopt)
183 const string & username = url.getUsername();
184 for(CredentialManager::CredentialIterator it = set.begin(); it != set.end(); ++it)
186 // this ignores url params - not sure if it is good or bad...
187 if (url.asString(vopt).find((*it)->url().asString(vopt)) == 0)
189 if (username.empty() || username == (*it)->username())
194 return AuthData_Ptr();
198 AuthData_Ptr CredentialManager::Impl::getCred(const Url & url) const
202 // compare the urls via asString(), but ignore password
203 // default url::ViewOption will take care of that.
204 // operator==(Url,Url) compares the whole Url
206 url::ViewOption vopt;
208 - url::ViewOption::WITH_USERNAME
209 - url::ViewOption::WITH_PASSWORD
210 - url::ViewOption::WITH_QUERY_STR;
212 // search in global credentials
213 result = findIn(_credsGlobal, url, vopt);
215 // search in home credentials
217 result = findIn(_credsUser, url, vopt);
220 DBG << "Found credentials for '" << url << "':" << endl << *result;
222 DBG << "No credentials for '" << url << "'" << endl;
228 AuthData_Ptr CredentialManager::Impl::getCredFromFile(const Pathname & file)
234 // get from that file
237 // get from /etc/zypp/credentials.d, delete the leading path
238 credfile = _options.customCredFileDir / file.basename();
240 CredentialFileReader(credfile, bind(&Impl::processCredentials, this, _1));
241 if (_credsTmp.empty())
242 WAR << file << " does not contain valid credentials or is not readable." << endl;
245 result = *_credsTmp.begin();
252 static int save_creds_in_file(
253 const CredentialManager::CredentialSet creds,
254 const Pathname & file,
258 filesystem::assert_dir(file.dirname());
260 std::ofstream fs(file.c_str());
264 for_(it, creds.begin(), creds.end())
266 (*it)->dumpAsIniOn(fs);
271 filesystem::chmod(file, mode);
276 void CredentialManager::Impl::saveGlobalCredentials()
278 save_creds_in_file(_credsGlobal, _options.globalCredFilePath, 0640);
281 void CredentialManager::Impl::saveUserCredentials()
283 save_creds_in_file(_credsUser, _options.userCredFilePath, 0600);
287 //////////////////////////////////////////////////////////////////////
289 // CLASS NAME : CredentialManager
291 //////////////////////////////////////////////////////////////////////
293 CredentialManager::CredentialManager(const CredManagerOptions & opts)
294 : _pimpl(new Impl(opts))
298 AuthData_Ptr CredentialManager::getCred(const Url & url)
300 string credfile = url.getQueryParam("credentials");
301 if (credfile.empty())
302 return _pimpl->getCred(url);
303 return _pimpl->getCredFromFile(credfile);
307 AuthData_Ptr CredentialManager::getCredFromFile(const Pathname & file)
308 { return _pimpl->getCredFromFile(file); }
311 void CredentialManager::addCred(const AuthData & cred)
313 Pathname credfile = cred.url().getQueryParam("credentials");
314 if (credfile.empty())
315 //! \todo ask user where to store these creds. saving to user creds for now
318 saveInFile(cred, credfile);
322 void CredentialManager::addGlobalCred(const AuthData & cred)
325 c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed
326 pair<CredentialIterator, bool> ret = _pimpl->_credsGlobal.insert(c_ptr);
328 _pimpl->_globalDirty = true;
329 else if ((*ret.first)->password() != cred.password())
331 _pimpl->_credsGlobal.erase(ret.first);
332 _pimpl->_credsGlobal.insert(c_ptr);
333 _pimpl->_globalDirty = true;
338 void CredentialManager::addUserCred(const AuthData & cred)
341 c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed
342 pair<CredentialIterator, bool> ret = _pimpl->_credsUser.insert(c_ptr);
344 _pimpl->_userDirty = true;
345 else if ((*ret.first)->password() != cred.password())
347 _pimpl->_credsUser.erase(ret.first);
348 _pimpl->_credsUser.insert(c_ptr);
349 _pimpl->_userDirty = true;
354 void CredentialManager::save()
356 if (_pimpl->_globalDirty)
357 _pimpl->saveGlobalCredentials();
358 if (_pimpl->_userDirty)
359 _pimpl->saveUserCredentials();
360 _pimpl->_globalDirty = false;
361 _pimpl->_userDirty = false;
365 void CredentialManager::saveInGlobal(const AuthData & cred)
372 void CredentialManager::saveInUser(const AuthData & cred)
379 void CredentialManager::saveInFile(const AuthData & cred, const Pathname & credFile)
382 c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed
383 c_ptr->setUrl(Url()); // don't save url in custom creds file
384 CredentialManager::CredentialSet creds;
388 if (credFile.absolute())
389 ret = save_creds_in_file(creds, credFile, 0640);
391 ret = save_creds_in_file(
392 creds, _pimpl->_options.customCredFileDir / credFile, 0600);
396 //! \todo figure out the reason(?), call back to user
397 ERR << "error saving the credentials" << endl;
402 void CredentialManager::clearAll(bool global)
406 if (!filesystem::unlink(_pimpl->_options.globalCredFilePath))
407 ERR << "could not delete user credentials file "
408 << _pimpl->_options.globalCredFilePath << endl;
409 _pimpl->_credsUser.clear();
413 if (!filesystem::unlink(_pimpl->_options.userCredFilePath))
414 ERR << "could not delete global credentials file"
415 << _pimpl->_options.userCredFilePath << endl;
416 _pimpl->_credsGlobal.clear();
421 CredentialManager::CredentialIterator CredentialManager::credsGlobalBegin() const
422 { return _pimpl->_credsGlobal.begin(); }
424 CredentialManager::CredentialIterator CredentialManager::credsGlobalEnd() const
425 { return _pimpl->_credsGlobal.end(); }
427 CredentialManager::CredentialSize CredentialManager::credsGlobalSize() const
428 { return _pimpl->_credsGlobal.size(); }
430 bool CredentialManager::credsGlobalEmpty() const
431 { return _pimpl->_credsGlobal.empty(); }
434 CredentialManager::CredentialIterator CredentialManager::credsUserBegin() const
435 { return _pimpl->_credsUser.begin(); }
437 CredentialManager::CredentialIterator CredentialManager::credsUserEnd() const
438 { return _pimpl->_credsUser.end(); }
440 CredentialManager::CredentialSize CredentialManager::credsUserSize() const
441 { return _pimpl->_credsUser.size(); }
443 bool CredentialManager::credsUserEmpty() const
444 { return _pimpl->_credsUser.empty(); }
447 ////////////////////////////////////////////////////////////////////
449 //////////////////////////////////////////////////////////////////////
450 ////////////////////////////////////////////////////////////////////
452 //////////////////////////////////////////////////////////////////////