libzypp  13.10.6
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
43  AuthDataComparator::operator()(
44  const AuthData_Ptr & lhs, const AuthData_Ptr & rhs)
45  {
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;
51 
52  if (lhs->username() != rhs->username())
53  return true;
54 
55  if (lhs->url().asString(vopt) != rhs->url().asString(vopt))
56  return true;
57 
58  return false;
59  }
60 
62  //
63  // CLASS NAME : CredManagerOptions
64  //
66 
67  CredManagerOptions::CredManagerOptions(const Pathname & rootdir)
68  : globalCredFilePath(rootdir / ZConfig::instance().credentialsGlobalFile())
69  , customCredFileDir(rootdir / ZConfig::instance().credentialsGlobalDir())
70  {
71  char * homedir = getenv("HOME");
72  if (homedir)
73  userCredFilePath = rootdir / homedir / USER_CREDENTIALS_FILE;
74  }
75 
76 
78  //
79  // CLASS NAME : CredentialManager::Impl
80  //
82  {
83  Impl(const CredManagerOptions & options);
84 
86  {}
87 
89  void init_userCredentials();
90 
91  bool processCredentials(AuthData_Ptr & cred);
92 
93  AuthData_Ptr getCred(const Url & url) const;
94  AuthData_Ptr getCredFromFile(const Pathname & file);
95  void saveGlobalCredentials();
96  void saveUserCredentials();
97 
98 
100 
104 
107  };
109 
110 
112  //
113  // CLASS NAME : CredentialManager::Impl
114  //
116 
118  : _options(options)
119  , _globalDirty(false)
120  , _userDirty(false)
121  {
124  }
125 
126 
128  {
129  if (_options.globalCredFilePath.empty())
130  DBG << "global cred file not known";
131  else if (PathInfo(_options.globalCredFilePath).isExist())
132  {
133  /* list<Pathname> entries;
134  if (filesystem::readdir(entries, _options.globalCredFilePath, false) != 0)
135  ZYPP_THROW(Exception("failed to read directory"));
136 
137  for_(it, entries.begin(), entries.end())*/
138 
139  CredentialFileReader(_options.globalCredFilePath,
140  bind(&Impl::processCredentials, this, _1));
141  }
142  else
143  DBG << "global cred file does not exist";
144 
145  _credsGlobal = _credsTmp; _credsTmp.clear();
146  DBG << "Got " << _credsGlobal.size() << " global records." << endl;
147  }
148 
149 
151  {
152  if (_options.userCredFilePath.empty())
153  DBG << "user cred file not known";
154  else if (PathInfo(_options.userCredFilePath).isExist())
155  {
156  /* list<Pathname> entries;
157  if (filesystem::readdir(entries, _options.userCredFilePath, false ) != 0)
158  ZYPP_THROW(Exception("failed to read directory"));
159 
160  for_(it, entries.begin(), entries.end())*/
161  CredentialFileReader(_options.userCredFilePath,
162  bind(&Impl::processCredentials, this, _1));
163  }
164  else
165  DBG << "user cred file does not exist" << endl;
166 
167  _credsUser = _credsTmp; _credsTmp.clear();
168  DBG << "Got " << _credsUser.size() << " user records." << endl;
169  }
170 
171 
173  {
174  _credsTmp.insert(cred);
175  return true;
176  }
177 
178 
180  const Url & url,
181  url::ViewOption vopt)
182  {
183  const string & username = url.getUsername();
184  for(CredentialManager::CredentialIterator it = set.begin(); it != set.end(); ++it)
185  {
186  // this ignores url params - not sure if it is good or bad...
187  if (url.asString(vopt).find((*it)->url().asString(vopt)) == 0)
188  {
189  if (username.empty() || username == (*it)->username())
190  return *it;
191  }
192  }
193 
194  return AuthData_Ptr();
195  }
196 
197 
199  {
200  AuthData_Ptr result;
201 
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
205 
206  url::ViewOption vopt;
207  vopt = vopt
211 
212  // search in global credentials
213  result = findIn(_credsGlobal, url, vopt);
214 
215  // search in home credentials
216  if (!result)
217  result = findIn(_credsUser, url, vopt);
218 
219  if (result)
220  DBG << "Found credentials for '" << url << "':" << endl << *result;
221  else
222  DBG << "No credentials for '" << url << "'" << endl;
223 
224  return result;
225  }
226 
227 
229  {
230  AuthData_Ptr result;
231 
232  Pathname credfile;
233  if (file.absolute())
234  // get from that file
235  credfile = file;
236  else
237  // get from /etc/zypp/credentials.d, delete the leading path
238  credfile = _options.customCredFileDir / file.basename();
239 
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;
243  else
244  {
245  result = *_credsTmp.begin();
246  _credsTmp.clear();
247  }
248 
249  return result;
250  }
251 
252  static int save_creds_in_file(
254  const Pathname & file,
255  const mode_t mode)
256  {
257  int ret = 0;
258  filesystem::assert_dir(file.dirname());
259 
260  std::ofstream fs(file.c_str());
261  if (!fs)
262  ret = 1;
263 
264  for_(it, creds.begin(), creds.end())
265  {
266  (*it)->dumpAsIniOn(fs);
267  fs << endl;
268  }
269  fs.close();
270 
271  filesystem::chmod(file, mode);
272 
273  return ret;
274  }
275 
277  {
278  save_creds_in_file(_credsGlobal, _options.globalCredFilePath, 0640);
279  }
280 
282  {
283  save_creds_in_file(_credsUser, _options.userCredFilePath, 0600);
284  }
285 
286 
288  //
289  // CLASS NAME : CredentialManager
290  //
292 
294  : _pimpl(new Impl(opts))
295  {}
296 
297 
299  {
300  string credfile = url.getQueryParam("credentials");
301  if (credfile.empty())
302  return _pimpl->getCred(url);
303  return _pimpl->getCredFromFile(credfile);
304  }
305 
306 
308  { return _pimpl->getCredFromFile(file); }
309 
310 
312  {
313  Pathname credfile = cred.url().getQueryParam("credentials");
314  if (credfile.empty())
316  addUserCred(cred);
317  else
318  saveInFile(cred, credfile);
319  }
320 
321 
323  {
324  AuthData_Ptr c_ptr;
325  c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed
326  pair<CredentialIterator, bool> ret = _pimpl->_credsGlobal.insert(c_ptr);
327  if (ret.second)
328  _pimpl->_globalDirty = true;
329  else if ((*ret.first)->password() != cred.password())
330  {
331  _pimpl->_credsGlobal.erase(ret.first);
332  _pimpl->_credsGlobal.insert(c_ptr);
333  _pimpl->_globalDirty = true;
334  }
335  }
336 
337 
339  {
340  AuthData_Ptr c_ptr;
341  c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed
342  pair<CredentialIterator, bool> ret = _pimpl->_credsUser.insert(c_ptr);
343  if (ret.second)
344  _pimpl->_userDirty = true;
345  else if ((*ret.first)->password() != cred.password())
346  {
347  _pimpl->_credsUser.erase(ret.first);
348  _pimpl->_credsUser.insert(c_ptr);
349  _pimpl->_userDirty = true;
350  }
351  }
352 
353 
355  {
356  if (_pimpl->_globalDirty)
357  _pimpl->saveGlobalCredentials();
358  if (_pimpl->_userDirty)
359  _pimpl->saveUserCredentials();
360  _pimpl->_globalDirty = false;
361  _pimpl->_userDirty = false;
362  }
363 
364 
366  {
367  addGlobalCred(cred);
368  save();
369  }
370 
371 
373  {
374  addUserCred(cred);
375  save();
376  }
377 
378 
379  void CredentialManager::saveInFile(const AuthData & cred, const Pathname & credFile)
380  {
381  AuthData_Ptr c_ptr;
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
385  creds.insert(c_ptr);
386 
387  int ret;
388  if (credFile.absolute())
389  ret = save_creds_in_file(creds, credFile, 0640);
390  else
391  ret = save_creds_in_file(
392  creds, _pimpl->_options.customCredFileDir / credFile, 0600);
393 
394  if (!ret)
395  {
397  ERR << "error saving the credentials" << endl;
398  }
399  }
400 
401 
402  void CredentialManager::clearAll(bool global)
403  {
404  if (global)
405  {
406  if (!filesystem::unlink(_pimpl->_options.globalCredFilePath))
407  ERR << "could not delete user credentials file "
408  << _pimpl->_options.globalCredFilePath << endl;
409  _pimpl->_credsUser.clear();
410  }
411  else
412  {
413  if (!filesystem::unlink(_pimpl->_options.userCredFilePath))
414  ERR << "could not delete global credentials file"
415  << _pimpl->_options.userCredFilePath << endl;
416  _pimpl->_credsGlobal.clear();
417  }
418  }
419 
420 
422  { return _pimpl->_credsGlobal.begin(); }
423 
425  { return _pimpl->_credsGlobal.end(); }
426 
428  { return _pimpl->_credsGlobal.size(); }
429 
431  { return _pimpl->_credsGlobal.empty(); }
432 
433 
435  { return _pimpl->_credsUser.begin(); }
436 
438  { return _pimpl->_credsUser.end(); }
439 
441  { return _pimpl->_credsUser.size(); }
442 
444  { return _pimpl->_credsUser.empty(); }
445 
446 
448  } // media
451 } // zypp
CredentialSize credsGlobalSize() const
int assert_dir(const Pathname &path, unsigned mode)
Like &#39;mkdir -p&#39;.
Definition: PathInfo.cc:324
static const ViewOption WITH_USERNAME
Option to include username in the URL string.
Definition: UrlBase.h:58
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 &#39;chmod&#39;.
Definition: PathInfo.cc:1021
static int save_creds_in_file(const CredentialManager::CredentialSet creds, const Pathname &file, const mode_t mode)
CredentialSet::size_type CredentialSize
std::string getUsername(EEncoding eflag=zypp::url::E_DECODED) const
Returns the username from the URL authority.
Definition: Url.cc:566
AuthData_Ptr getCred(const Url &url)
Get credentials for the specified url.
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
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:49
std::string asString() const
Returns a default string representation of the Url object.
Definition: Url.cc:491
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:660
bool processCredentials(AuthData_Ptr &cred)
Interim helper class to collect global options and settings.
Definition: ZConfig.h:58
#define WAR
Definition: Logger.h:48
AuthData_Ptr getCred(const Url &url) const
void addUserCred(const AuthData &cred)
Add new user credentials.
zypp::Url url
Definition: MediaCurl.cc:193
CredentialIterator credsGlobalEnd() const
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:654
CredentialIterator credsGlobalBegin() const
Class for handling media authentication data.
Definition: MediaUserAuth.h:30
CredentialSize credsUserSize() const
CredentialIterator credsUserBegin() const
CredentialIterator credsUserEnd() const
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
CredentialSet::const_iterator CredentialIterator
CredentialManager(const CredManagerOptions &opts=CredManagerOptions())
void clearAll(bool global=false)
Remove all global or user credentials from memory and disk.
#define USER_CREDENTIALS_FILE
AuthData_Ptr getCredFromFile(const Pathname &file)
Read credentials from a file.
AuthData_Ptr getCredFromFile(const Pathname &file)
std::string password() const
Definition: MediaUserAuth.h:57
void addCred(const AuthData &cred)
Add new credentials with user callbacks.
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&#39;s credentials file.
#define DBG
Definition: Logger.h:46