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 //////////////////////////////////////////////////////////////////////
42 bool AuthDataComparator::operator()( const AuthData_Ptr & lhs, const AuthData_Ptr & rhs ) const
44 static const url::ViewOption vopt = url::ViewOption::DEFAULTS
45 - url::ViewOption::WITH_USERNAME
46 - url::ViewOption::WITH_PASSWORD
47 - url::ViewOption::WITH_QUERY_STR;
48 // std::less semantic!
49 int cmp = lhs->url().asString(vopt).compare( rhs->url().asString(vopt) );
51 cmp = lhs->username().compare( rhs->username() );
55 //////////////////////////////////////////////////////////////////////
57 // CLASS NAME : CredManagerOptions
59 //////////////////////////////////////////////////////////////////////
61 CredManagerOptions::CredManagerOptions(const Pathname & rootdir)
62 : globalCredFilePath(rootdir / ZConfig::instance().credentialsGlobalFile())
63 , customCredFileDir(rootdir / ZConfig::instance().credentialsGlobalDir())
65 char * homedir = getenv("HOME");
67 userCredFilePath = rootdir / homedir / USER_CREDENTIALS_FILE;
71 //////////////////////////////////////////////////////////////////////
73 // CLASS NAME : CredentialManager::Impl
75 struct CredentialManager::Impl
77 Impl(const CredManagerOptions & options);
82 void init_globalCredentials();
83 void init_userCredentials();
85 bool processCredentials(AuthData_Ptr & cred);
87 AuthData_Ptr getCred(const Url & url) const;
88 AuthData_Ptr getCredFromFile(const Pathname & file);
89 void saveGlobalCredentials();
90 void saveUserCredentials();
93 CredManagerOptions _options;
95 CredentialSet _credsGlobal;
96 CredentialSet _credsUser;
97 CredentialSet _credsTmp;
102 //////////////////////////////////////////////////////////////////////
105 //////////////////////////////////////////////////////////////////////
107 // CLASS NAME : CredentialManager::Impl
109 //////////////////////////////////////////////////////////////////////
111 CredentialManager::Impl::Impl(const CredManagerOptions & options)
113 , _globalDirty(false)
116 init_globalCredentials();
117 init_userCredentials();
121 void CredentialManager::Impl::init_globalCredentials()
123 if (_options.globalCredFilePath.empty())
124 DBG << "global cred file not known";
125 else if (PathInfo(_options.globalCredFilePath).isExist())
127 /* list<Pathname> entries;
128 if (filesystem::readdir(entries, _options.globalCredFilePath, false) != 0)
129 ZYPP_THROW(Exception("failed to read directory"));
131 for_(it, entries.begin(), entries.end())*/
133 CredentialFileReader(_options.globalCredFilePath,
134 bind(&Impl::processCredentials, this, _1));
137 DBG << "global cred file does not exist";
139 _credsGlobal = _credsTmp; _credsTmp.clear();
140 DBG << "Got " << _credsGlobal.size() << " global records." << endl;
144 void CredentialManager::Impl::init_userCredentials()
146 if (_options.userCredFilePath.empty())
147 DBG << "user cred file not known";
148 else if (PathInfo(_options.userCredFilePath).isExist())
150 /* list<Pathname> entries;
151 if (filesystem::readdir(entries, _options.userCredFilePath, false ) != 0)
152 ZYPP_THROW(Exception("failed to read directory"));
154 for_(it, entries.begin(), entries.end())*/
155 CredentialFileReader(_options.userCredFilePath,
156 bind(&Impl::processCredentials, this, _1));
159 DBG << "user cred file does not exist" << endl;
161 _credsUser = _credsTmp; _credsTmp.clear();
162 DBG << "Got " << _credsUser.size() << " user records." << endl;
166 bool CredentialManager::Impl::processCredentials(AuthData_Ptr & cred)
168 _credsTmp.insert(cred);
173 static AuthData_Ptr findIn(const CredentialManager::CredentialSet & set,
175 url::ViewOption vopt)
177 const string & username = url.getUsername();
178 for(CredentialManager::CredentialIterator it = set.begin(); it != set.end(); ++it)
180 // this ignores url params - not sure if it is good or bad...
181 if (url.asString(vopt).find((*it)->url().asString(vopt)) == 0)
183 if (username.empty() || username == (*it)->username())
188 return AuthData_Ptr();
192 AuthData_Ptr CredentialManager::Impl::getCred(const Url & url) const
196 // compare the urls via asString(), but ignore password
197 // default url::ViewOption will take care of that.
198 // operator==(Url,Url) compares the whole Url
200 url::ViewOption vopt;
202 - url::ViewOption::WITH_USERNAME
203 - url::ViewOption::WITH_PASSWORD
204 - url::ViewOption::WITH_QUERY_STR;
206 // search in global credentials
207 result = findIn(_credsGlobal, url, vopt);
209 // search in home credentials
211 result = findIn(_credsUser, url, vopt);
214 DBG << "Found credentials for '" << url << "':" << endl << *result;
216 DBG << "No credentials for '" << url << "'" << endl;
222 AuthData_Ptr CredentialManager::Impl::getCredFromFile(const Pathname & file)
228 // get from that file
231 // get from /etc/zypp/credentials.d, delete the leading path
232 credfile = _options.customCredFileDir / file.basename();
234 CredentialFileReader(credfile, bind(&Impl::processCredentials, this, _1));
235 if (_credsTmp.empty())
236 WAR << file << " does not contain valid credentials or is not readable." << endl;
239 result = *_credsTmp.begin();
246 static int save_creds_in_file(
247 const CredentialManager::CredentialSet creds,
248 const Pathname & file,
252 filesystem::assert_dir(file.dirname());
254 std::ofstream fs(file.c_str());
258 for_(it, creds.begin(), creds.end())
260 (*it)->dumpAsIniOn(fs);
265 filesystem::chmod(file, mode);
270 void CredentialManager::Impl::saveGlobalCredentials()
272 save_creds_in_file(_credsGlobal, _options.globalCredFilePath, 0640);
275 void CredentialManager::Impl::saveUserCredentials()
277 save_creds_in_file(_credsUser, _options.userCredFilePath, 0600);
281 //////////////////////////////////////////////////////////////////////
283 // CLASS NAME : CredentialManager
285 //////////////////////////////////////////////////////////////////////
287 CredentialManager::CredentialManager(const CredManagerOptions & opts)
288 : _pimpl(new Impl(opts))
292 AuthData_Ptr CredentialManager::getCred(const Url & url)
294 string credfile = url.getQueryParam("credentials");
295 if (credfile.empty())
296 return _pimpl->getCred(url);
297 return _pimpl->getCredFromFile(credfile);
301 AuthData_Ptr CredentialManager::getCredFromFile(const Pathname & file)
302 { return _pimpl->getCredFromFile(file); }
305 void CredentialManager::addCred(const AuthData & cred)
307 Pathname credfile = cred.url().getQueryParam("credentials");
308 if (credfile.empty())
309 //! \todo ask user where to store these creds. saving to user creds for now
312 saveInFile(cred, credfile);
316 void CredentialManager::addGlobalCred(const AuthData & cred)
319 c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed
320 pair<CredentialIterator, bool> ret = _pimpl->_credsGlobal.insert(c_ptr);
322 _pimpl->_globalDirty = true;
323 else if ((*ret.first)->password() != cred.password())
325 _pimpl->_credsGlobal.erase(ret.first);
326 _pimpl->_credsGlobal.insert(c_ptr);
327 _pimpl->_globalDirty = true;
332 void CredentialManager::addUserCred(const AuthData & cred)
335 c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed
336 pair<CredentialIterator, bool> ret = _pimpl->_credsUser.insert(c_ptr);
338 _pimpl->_userDirty = true;
339 else if ((*ret.first)->password() != cred.password())
341 _pimpl->_credsUser.erase(ret.first);
342 _pimpl->_credsUser.insert(c_ptr);
343 _pimpl->_userDirty = true;
348 void CredentialManager::save()
350 if (_pimpl->_globalDirty)
351 _pimpl->saveGlobalCredentials();
352 if (_pimpl->_userDirty)
353 _pimpl->saveUserCredentials();
354 _pimpl->_globalDirty = false;
355 _pimpl->_userDirty = false;
359 void CredentialManager::saveInGlobal(const AuthData & cred)
366 void CredentialManager::saveInUser(const AuthData & cred)
373 void CredentialManager::saveInFile(const AuthData & cred, const Pathname & credFile)
376 c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed
377 c_ptr->setUrl(Url()); // don't save url in custom creds file
378 CredentialManager::CredentialSet creds;
382 if (credFile.absolute())
383 ret = save_creds_in_file(creds, credFile, 0640);
385 ret = save_creds_in_file(
386 creds, _pimpl->_options.customCredFileDir / credFile, 0600);
390 //! \todo figure out the reason(?), call back to user
391 ERR << "error saving the credentials" << endl;
396 void CredentialManager::clearAll(bool global)
400 if (!filesystem::unlink(_pimpl->_options.globalCredFilePath))
401 ERR << "could not delete user credentials file "
402 << _pimpl->_options.globalCredFilePath << endl;
403 _pimpl->_credsUser.clear();
407 if (!filesystem::unlink(_pimpl->_options.userCredFilePath))
408 ERR << "could not delete global credentials file"
409 << _pimpl->_options.userCredFilePath << endl;
410 _pimpl->_credsGlobal.clear();
415 CredentialManager::CredentialIterator CredentialManager::credsGlobalBegin() const
416 { return _pimpl->_credsGlobal.begin(); }
418 CredentialManager::CredentialIterator CredentialManager::credsGlobalEnd() const
419 { return _pimpl->_credsGlobal.end(); }
421 CredentialManager::CredentialSize CredentialManager::credsGlobalSize() const
422 { return _pimpl->_credsGlobal.size(); }
424 bool CredentialManager::credsGlobalEmpty() const
425 { return _pimpl->_credsGlobal.empty(); }
428 CredentialManager::CredentialIterator CredentialManager::credsUserBegin() const
429 { return _pimpl->_credsUser.begin(); }
431 CredentialManager::CredentialIterator CredentialManager::credsUserEnd() const
432 { return _pimpl->_credsUser.end(); }
434 CredentialManager::CredentialSize CredentialManager::credsUserSize() const
435 { return _pimpl->_credsUser.size(); }
437 bool CredentialManager::credsUserEmpty() const
438 { return _pimpl->_credsUser.empty(); }
441 ////////////////////////////////////////////////////////////////////
443 //////////////////////////////////////////////////////////////////////
444 ////////////////////////////////////////////////////////////////////
446 //////////////////////////////////////////////////////////////////////