libzypp 17.25.7
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
25using std::endl;
26
27#define USER_CREDENTIALS_FILE ".zypp/credentials.cat"
28
30namespace zypp
31{
33 namespace media
34 {
35
37 //
38 // CLASS NAME : AuthDataComparator
39 //
41
42 bool AuthDataComparator::operator()( const AuthData_Ptr & lhs, const AuthData_Ptr & rhs ) const
43 {
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
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
84
86
87 AuthData_Ptr getCred(const Url & url) const;
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 std::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
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 std::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 std::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 std::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
397 {
398 if (global)
399 {
401 ERR << "could not delete user credentials file "
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
#define USER_CREDENTIALS_FILE
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:28
#define DBG
Definition: Logger.h:78
#define ERR
Definition: Logger.h:81
#define WAR
Definition: Logger.h:80
Url url
Definition: MediaCurl.cc:66
Url manipulation class.
Definition: Url.h:92
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
Interim helper class to collect global options and settings.
Definition: ZConfig.h:60
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:221
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:124
bool absolute() const
Test for an absolute path.
Definition: Pathname.h:116
const char * c_str() const
String representation.
Definition: Pathname.h:110
std::string basename() const
Return the last component of this path.
Definition: Pathname.h:128
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
Class for handling media authentication data.
Definition: MediaUserAuth.h:31
std::string password() const
Definition: MediaUserAuth.h:57
Parse credentials files and catalogs.
CredentialSize credsUserSize() const
void save()
Saves any unsaved credentials added via addUserCred() or addGlobalCred() methods.
AuthData_Ptr getCredFromFile(const Pathname &file)
Read credentials from a file.
CredentialIterator credsGlobalBegin() const
CredentialIterator credsUserBegin() const
std::set< AuthData_Ptr, AuthDataComparator > CredentialSet
CredentialSet::const_iterator CredentialIterator
void saveInUser(const AuthData &cred)
Saves given cred to user's credentials file.
AuthData_Ptr getCred(const Url &url)
Get credentials for the specified url.
void addUserCred(const AuthData &cred)
Add new user credentials.
void saveInFile(const AuthData &, const Pathname &credFile)
Saves given cred to user specified credentials file.
CredentialIterator credsGlobalEnd() const
CredentialIterator credsUserEnd() const
CredentialSize credsGlobalSize() const
void addCred(const AuthData &cred)
Add new credentials with user callbacks.
void addGlobalCred(const AuthData &cred)
Add new global credentials.
CredentialSet::size_type CredentialSize
void saveInGlobal(const AuthData &cred)
Saves given cred to global credentials file.
void clearAll(bool global=false)
Remove all global or user credentials from memory and disk.
CredentialManager(const CredManagerOptions &opts=CredManagerOptions())
int chmod(const Pathname &path, mode_t mode)
Like 'chmod'.
Definition: PathInfo.cc:1054
int unlink(const Pathname &path)
Like 'unlink'.
Definition: PathInfo.cc:662
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
Definition: PathInfo.cc:320
static AuthData_Ptr findIn(const CredentialManager::CredentialSet &set, const Url &url, url::ViewOption vopt)
static int save_creds_in_file(const CredentialManager::CredentialSet creds, const Pathname &file, const mode_t mode)
shared_ptr< AuthData > AuthData_Ptr
Definition: MediaUserAuth.h:69
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
bool operator()(const AuthData_Ptr &lhs, const AuthData_Ptr &rhs) const
CredManagerOptions(const Pathname &rootdir="")
Impl(const CredManagerOptions &options)
AuthData_Ptr getCred(const Url &url) const
bool processCredentials(AuthData_Ptr &cred)
AuthData_Ptr getCredFromFile(const Pathname &file)
Url::asString() view options.
Definition: UrlBase.h:40
static const ViewOption WITH_PASSWORD
Option to include password in the URL string.
Definition: UrlBase.h:67
static const ViewOption DEFAULTS
Default combination of view options.
Definition: UrlBase.h:177
static const ViewOption WITH_USERNAME
Option to include username in the URL string.
Definition: UrlBase.h:58
static const ViewOption WITH_QUERY_STR
Option to include query string in the URL string.
Definition: UrlBase.h:101