libzypp  11.13.5
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 
33  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)
358  if (_pimpl->_userDirty)
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  {
407  ERR << "could not delete user credentials file "
408  << _pimpl->_options.globalCredFilePath << endl;
409  _pimpl->_credsUser.clear();
410  }
411  else
412  {
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