libzypp  17.14.0
CredentialManager.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include <fstream>
14 
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"
20 
22 
24 
25 #define USER_CREDENTIALS_FILE ".zypp/credentials.cat"
26 
27 using namespace std;
28 
30 namespace zypp
31 {
32  namespace media
34  {
35 
37  //
38  // CLASS NAME : AuthDataComparator
39  //
41 
42  bool AuthDataComparator::operator()( const AuthData_Ptr & lhs, const AuthData_Ptr & rhs )
43  {
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) );
50  if ( ! cmp )
51  cmp = lhs->username().compare( rhs->username() );
52  return( cmp < 0 );
53  }
54 
56  //
57  // CLASS NAME : CredManagerOptions
58  //
60 
61  CredManagerOptions::CredManagerOptions(const Pathname & rootdir)
62  : globalCredFilePath(rootdir / ZConfig::instance().credentialsGlobalFile())
63  , customCredFileDir(rootdir / ZConfig::instance().credentialsGlobalDir())
64  {
65  char * homedir = getenv("HOME");
66  if (homedir)
67  userCredFilePath = rootdir / homedir / USER_CREDENTIALS_FILE;
68  }
69 
70 
72  //
73  // CLASS NAME : CredentialManager::Impl
74  //
76  {
77  Impl(const CredManagerOptions & options);
78 
80  {}
81 
83  void init_userCredentials();
84 
85  bool processCredentials(AuthData_Ptr & cred);
86 
87  AuthData_Ptr getCred(const Url & url) const;
89  void saveGlobalCredentials();
90  void saveUserCredentials();
91 
92 
94 
98 
101  };
103 
104 
106  //
107  // CLASS NAME : CredentialManager::Impl
108  //
110 
112  : _options(options)
113  , _globalDirty(false)
114  , _userDirty(false)
115  {
118  }
119 
120 
122  {
123  if (_options.globalCredFilePath.empty())
124  DBG << "global cred file not known";
125  else if (PathInfo(_options.globalCredFilePath).isExist())
126  {
127  /* list<Pathname> entries;
128  if (filesystem::readdir(entries, _options.globalCredFilePath, false) != 0)
129  ZYPP_THROW(Exception("failed to read directory"));
130 
131  for_(it, entries.begin(), entries.end())*/
132 
133  CredentialFileReader(_options.globalCredFilePath,
134  bind(&Impl::processCredentials, this, _1));
135  }
136  else
137  DBG << "global cred file does not exist";
138 
139  _credsGlobal = _credsTmp; _credsTmp.clear();
140  DBG << "Got " << _credsGlobal.size() << " global records." << endl;
141  }
142 
143 
145  {
146  if (_options.userCredFilePath.empty())
147  DBG << "user cred file not known";
148  else if (PathInfo(_options.userCredFilePath).isExist())
149  {
150  /* list<Pathname> entries;
151  if (filesystem::readdir(entries, _options.userCredFilePath, false ) != 0)
152  ZYPP_THROW(Exception("failed to read directory"));
153 
154  for_(it, entries.begin(), entries.end())*/
155  CredentialFileReader(_options.userCredFilePath,
156  bind(&Impl::processCredentials, this, _1));
157  }
158  else
159  DBG << "user cred file does not exist" << endl;
160 
161  _credsUser = _credsTmp; _credsTmp.clear();
162  DBG << "Got " << _credsUser.size() << " user records." << endl;
163  }
164 
165 
167  {
168  _credsTmp.insert(cred);
169  return true;
170  }
171 
172 
174  const Url & url,
175  url::ViewOption vopt)
176  {
177  const string & username = url.getUsername();
178  for(CredentialManager::CredentialIterator it = set.begin(); it != set.end(); ++it)
179  {
180  // this ignores url params - not sure if it is good or bad...
181  if (url.asString(vopt).find((*it)->url().asString(vopt)) == 0)
182  {
183  if (username.empty() || username == (*it)->username())
184  return *it;
185  }
186  }
187 
188  return AuthData_Ptr();
189  }
190 
191 
193  {
194  AuthData_Ptr result;
195 
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
199 
200  url::ViewOption vopt;
201  vopt = vopt
205 
206  // search in global credentials
207  result = findIn(_credsGlobal, url, vopt);
208 
209  // search in home credentials
210  if (!result)
211  result = findIn(_credsUser, url, vopt);
212 
213  if (result)
214  DBG << "Found credentials for '" << url << "':" << endl << *result;
215  else
216  DBG << "No credentials for '" << url << "'" << endl;
217 
218  return result;
219  }
220 
221 
223  {
224  AuthData_Ptr result;
225 
226  Pathname credfile;
227  if (file.absolute())
228  // get from that file
229  credfile = file;
230  else
231  // get from /etc/zypp/credentials.d, delete the leading path
232  credfile = _options.customCredFileDir / file.basename();
233 
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;
237  else
238  {
239  result = *_credsTmp.begin();
240  _credsTmp.clear();
241  }
242 
243  return result;
244  }
245 
246  static int save_creds_in_file(
248  const Pathname & file,
249  const mode_t mode)
250  {
251  int ret = 0;
253 
254  std::ofstream fs(file.c_str());
255  if (!fs)
256  ret = 1;
257 
258  for_(it, creds.begin(), creds.end())
259  {
260  (*it)->dumpAsIniOn(fs);
261  fs << endl;
262  }
263  fs.close();
264 
265  filesystem::chmod(file, mode);
266 
267  return ret;
268  }
269 
271  {
272  save_creds_in_file(_credsGlobal, _options.globalCredFilePath, 0640);
273  }
274 
276  {
277  save_creds_in_file(_credsUser, _options.userCredFilePath, 0600);
278  }
279 
280 
282  //
283  // CLASS NAME : CredentialManager
284  //
286 
288  : _pimpl(new Impl(opts))
289  {}
290 
291 
293  {
294  string credfile = url.getQueryParam("credentials");
295  if (credfile.empty())
296  return _pimpl->getCred(url);
297  return _pimpl->getCredFromFile(credfile);
298  }
299 
300 
302  { return _pimpl->getCredFromFile(file); }
303 
304 
306  {
307  Pathname credfile = cred.url().getQueryParam("credentials");
308  if (credfile.empty())
310  addUserCred(cred);
311  else
312  saveInFile(cred, credfile);
313  }
314 
315 
317  {
318  AuthData_Ptr c_ptr;
319  c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed
320  pair<CredentialIterator, bool> ret = _pimpl->_credsGlobal.insert(c_ptr);
321  if (ret.second)
322  _pimpl->_globalDirty = true;
323  else if ((*ret.first)->password() != cred.password())
324  {
325  _pimpl->_credsGlobal.erase(ret.first);
326  _pimpl->_credsGlobal.insert(c_ptr);
327  _pimpl->_globalDirty = true;
328  }
329  }
330 
331 
333  {
334  AuthData_Ptr c_ptr;
335  c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed
336  pair<CredentialIterator, bool> ret = _pimpl->_credsUser.insert(c_ptr);
337  if (ret.second)
338  _pimpl->_userDirty = true;
339  else if ((*ret.first)->password() != cred.password())
340  {
341  _pimpl->_credsUser.erase(ret.first);
342  _pimpl->_credsUser.insert(c_ptr);
343  _pimpl->_userDirty = true;
344  }
345  }
346 
347 
349  {
350  if (_pimpl->_globalDirty)
352  if (_pimpl->_userDirty)
354  _pimpl->_globalDirty = false;
355  _pimpl->_userDirty = false;
356  }
357 
358 
360  {
361  addGlobalCred(cred);
362  save();
363  }
364 
365 
367  {
368  addUserCred(cred);
369  save();
370  }
371 
372 
373  void CredentialManager::saveInFile(const AuthData & cred, const Pathname & credFile)
374  {
375  AuthData_Ptr c_ptr;
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
379  creds.insert(c_ptr);
380 
381  int ret;
382  if (credFile.absolute())
383  ret = save_creds_in_file(creds, credFile, 0640);
384  else
385  ret = save_creds_in_file(
386  creds, _pimpl->_options.customCredFileDir / credFile, 0600);
387 
388  if (!ret)
389  {
391  ERR << "error saving the credentials" << endl;
392  }
393  }
394 
395 
396  void CredentialManager::clearAll(bool global)
397  {
398  if (global)
399  {
401  ERR << "could not delete user credentials file "
402  << _pimpl->_options.globalCredFilePath << endl;
403  _pimpl->_credsUser.clear();
404  }
405  else
406  {
408  ERR << "could not delete global credentials file"
409  << _pimpl->_options.userCredFilePath << endl;
410  _pimpl->_credsGlobal.clear();
411  }
412  }
413 
414 
416  { return _pimpl->_credsGlobal.begin(); }
417 
419  { return _pimpl->_credsGlobal.end(); }
420 
422  { return _pimpl->_credsGlobal.size(); }
423 
425  { return _pimpl->_credsGlobal.empty(); }
426 
427 
429  { return _pimpl->_credsUser.begin(); }
430 
432  { return _pimpl->_credsUser.end(); }
433 
435  { return _pimpl->_credsUser.size(); }
436 
438  { return _pimpl->_credsUser.empty(); }
439 
440 
442  } // media
445 } // zypp
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition: PathInfo.cc:320
AuthData_Ptr getCred(const Url &url) const
static const ViewOption WITH_USERNAME
Option to include username in the URL string.
Definition: UrlBase.h:58
std::string password() const
Definition: MediaUserAuth.h:57
CredentialIterator credsGlobalEnd() const
void saveInFile(const AuthData &, const Pathname &credFile)
Saves given cred to user specified credentials file.
void save()
Saves any unsaved credentials added via addUserCred() or addGlobalCred() methods.
void addGlobalCred(const AuthData &cred)
Add new global credentials.
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
Definition: PathInfo.cc:1045
const char * c_str() const
String representation.
Definition: Pathname.h:109
static int save_creds_in_file(const CredentialManager::CredentialSet creds, const Pathname &file, const mode_t mode)
CredentialSet::size_type CredentialSize
Definition: Arch.h:344
AuthData_Ptr getCred(const Url &url)
Get credentials for the specified url.
Url url
Definition: MediaCurl.cc:180
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:127
void saveInGlobal(const AuthData &cred)
Saves given cred to global credentials file.
Url::asString() view options.
Definition: UrlBase.h:39
Impl(const CredManagerOptions &options)
#define ERR
Definition: Logger.h:81
bool empty() const
Test for an empty path.
Definition: Pathname.h:113
std::string getQueryParam(const std::string &param, EEncoding eflag=zypp::url::E_DECODED) const
Return the value for the specified query parameter.
Definition: Url.cc:655
int unlink(const Pathname &path)
Like 'unlink'.
Definition: PathInfo.cc:653
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:123
bool processCredentials(AuthData_Ptr &cred)
CredentialSize credsUserSize() const
Interim helper class to collect global options and settings.
Definition: ZConfig.h:59
#define WAR
Definition: Logger.h:80
void addUserCred(const AuthData &cred)
Add new user credentials.
Parse credentials files and catalogs.
bool absolute() const
Test for an absolute path.
Definition: Pathname.h:115
CredentialIterator credsGlobalBegin() const
Class for handling media authentication data.
Definition: MediaUserAuth.h:30
static const ViewOption WITH_QUERY_STR
Option to include query string in the URL string.
Definition: UrlBase.h:101
shared_ptr< AuthData > AuthData_Ptr
Definition: MediaUserAuth.h:69
static const ViewOption WITH_PASSWORD
Option to include password in the URL string.
Definition: UrlBase.h:67
std::set< AuthData_Ptr, AuthDataComparator > CredentialSet
CredentialIterator credsUserBegin() const
CredentialSet::const_iterator CredentialIterator
CredentialManager(const CredManagerOptions &opts=CredManagerOptions())
void clearAll(bool global=false)
Remove all global or user credentials from memory and disk.
CredentialIterator credsUserEnd() const
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
#define USER_CREDENTIALS_FILE
AuthData_Ptr getCredFromFile(const Pathname &file)
Read credentials from a file.
AuthData_Ptr getCredFromFile(const Pathname &file)
CredentialSize credsGlobalSize() const
void addCred(const AuthData &cred)
Add new credentials with user callbacks.
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
static AuthData_Ptr findIn(const CredentialManager::CredentialSet &set, const Url &url, url::ViewOption vopt)
Url manipulation class.
Definition: Url.h:87
void saveInUser(const AuthData &cred)
Saves given cred to user's credentials file.
#define DBG
Definition: Logger.h:78