libzypp
10.5.0
|
00001 /*---------------------------------------------------------------------\ 00002 | ____ _ __ __ ___ | 00003 | |__ / \ / / . \ . \ | 00004 | / / \ V /| _/ _/ | 00005 | / /__ | | | | | | | 00006 | /_____||_| |_| |_| | 00007 | | 00008 \---------------------------------------------------------------------*/ 00012 #include <iostream> 00013 #include <fstream> 00014 00015 #include "zypp/ZConfig.h" 00016 #include "zypp/base/Function.h" 00017 #include "zypp/base/Logger.h" 00018 #include "zypp/base/Easy.h" 00019 #include "zypp/PathInfo.h" 00020 00021 #include "zypp/media/CredentialFileReader.h" 00022 00023 #include "zypp/media/CredentialManager.h" 00024 00025 #define USER_CREDENTIALS_FILE ".zypp/credentials.cat" 00026 00027 using namespace std; 00028 00030 namespace zypp 00031 { 00032 00033 namespace media 00034 { 00035 00037 // 00038 // CLASS NAME : AuthDataComparator 00039 // 00041 00042 bool 00043 AuthDataComparator::operator()( 00044 const AuthData_Ptr & lhs, const AuthData_Ptr & rhs) 00045 { 00046 static const url::ViewOption vopt = 00047 url::ViewOption::DEFAULTS 00048 - url::ViewOption::WITH_USERNAME 00049 - url::ViewOption::WITH_PASSWORD 00050 - url::ViewOption::WITH_QUERY_STR; 00051 00052 if (lhs->username() != rhs->username()) 00053 return true; 00054 00055 if (lhs->url().asString(vopt) != rhs->url().asString(vopt)) 00056 return true; 00057 00058 return false; 00059 } 00060 00062 // 00063 // CLASS NAME : CredManagerOptions 00064 // 00066 00067 CredManagerOptions::CredManagerOptions(const Pathname & rootdir) 00068 : globalCredFilePath(rootdir / ZConfig::instance().credentialsGlobalFile()) 00069 , customCredFileDir(rootdir / ZConfig::instance().credentialsGlobalDir()) 00070 { 00071 char * homedir = getenv("HOME"); 00072 if (homedir) 00073 userCredFilePath = rootdir / homedir / USER_CREDENTIALS_FILE; 00074 } 00075 00076 00078 // 00079 // CLASS NAME : CredentialManager::Impl 00080 // 00081 struct CredentialManager::Impl 00082 { 00083 Impl(const CredManagerOptions & options); 00084 00085 ~Impl() 00086 {} 00087 00088 void init_globalCredentials(); 00089 void init_userCredentials(); 00090 00091 bool processCredentials(AuthData_Ptr & cred); 00092 00093 AuthData_Ptr getCred(const Url & url) const; 00094 AuthData_Ptr getCredFromFile(const Pathname & file); 00095 void saveGlobalCredentials(); 00096 void saveUserCredentials(); 00097 00098 00099 CredManagerOptions _options; 00100 00101 CredentialSet _credsGlobal; 00102 CredentialSet _credsUser; 00103 CredentialSet _credsTmp; 00104 00105 bool _globalDirty; 00106 bool _userDirty; 00107 }; 00109 00110 00112 // 00113 // CLASS NAME : CredentialManager::Impl 00114 // 00116 00117 CredentialManager::Impl::Impl(const CredManagerOptions & options) 00118 : _options(options) 00119 , _globalDirty(false) 00120 , _userDirty(false) 00121 { 00122 init_globalCredentials(); 00123 init_userCredentials(); 00124 } 00125 00126 00127 void CredentialManager::Impl::init_globalCredentials() 00128 { 00129 if (_options.globalCredFilePath.empty()) 00130 DBG << "global cred file not known"; 00131 else if (PathInfo(_options.globalCredFilePath).isExist()) 00132 { 00133 /* list<Pathname> entries; 00134 if (filesystem::readdir(entries, _options.globalCredFilePath, false) != 0) 00135 ZYPP_THROW(Exception("failed to read directory")); 00136 00137 for_(it, entries.begin(), entries.end())*/ 00138 00139 CredentialFileReader(_options.globalCredFilePath, 00140 bind(&Impl::processCredentials, this, _1)); 00141 } 00142 else 00143 DBG << "global cred file does not exist"; 00144 00145 _credsGlobal = _credsTmp; _credsTmp.clear(); 00146 DBG << "Got " << _credsGlobal.size() << " global records." << endl; 00147 } 00148 00149 00150 void CredentialManager::Impl::init_userCredentials() 00151 { 00152 if (_options.userCredFilePath.empty()) 00153 DBG << "user cred file not known"; 00154 else if (PathInfo(_options.userCredFilePath).isExist()) 00155 { 00156 /* list<Pathname> entries; 00157 if (filesystem::readdir(entries, _options.userCredFilePath, false ) != 0) 00158 ZYPP_THROW(Exception("failed to read directory")); 00159 00160 for_(it, entries.begin(), entries.end())*/ 00161 CredentialFileReader(_options.userCredFilePath, 00162 bind(&Impl::processCredentials, this, _1)); 00163 } 00164 else 00165 DBG << "user cred file does not exist" << endl; 00166 00167 _credsUser = _credsTmp; _credsTmp.clear(); 00168 DBG << "Got " << _credsUser.size() << " user records." << endl; 00169 } 00170 00171 00172 bool CredentialManager::Impl::processCredentials(AuthData_Ptr & cred) 00173 { 00174 _credsTmp.insert(cred); 00175 return true; 00176 } 00177 00178 00179 static AuthData_Ptr findIn(const CredentialManager::CredentialSet & set, 00180 const Url & url, 00181 url::ViewOption vopt) 00182 { 00183 const string & username = url.getUsername(); 00184 for(CredentialManager::CredentialIterator it = set.begin(); it != set.end(); ++it) 00185 { 00186 // this ignores url params - not sure if it is good or bad... 00187 if (url.asString(vopt).find((*it)->url().asString(vopt)) == 0) 00188 { 00189 if (username.empty() || username == (*it)->username()) 00190 return *it; 00191 } 00192 } 00193 00194 return AuthData_Ptr(); 00195 } 00196 00197 00198 AuthData_Ptr CredentialManager::Impl::getCred(const Url & url) const 00199 { 00200 AuthData_Ptr result; 00201 00202 // compare the urls via asString(), but ignore password 00203 // default url::ViewOption will take care of that. 00204 // operator==(Url,Url) compares the whole Url 00205 00206 url::ViewOption vopt; 00207 vopt = vopt 00208 - url::ViewOption::WITH_USERNAME 00209 - url::ViewOption::WITH_PASSWORD 00210 - url::ViewOption::WITH_QUERY_STR; 00211 00212 // search in global credentials 00213 result = findIn(_credsGlobal, url, vopt); 00214 00215 // search in home credentials 00216 if (!result) 00217 result = findIn(_credsUser, url, vopt); 00218 00219 if (result) 00220 DBG << "Found credentials for '" << url << "':" << endl << *result; 00221 else 00222 DBG << "No credentials for '" << url << "'" << endl; 00223 00224 return result; 00225 } 00226 00227 00228 AuthData_Ptr CredentialManager::Impl::getCredFromFile(const Pathname & file) 00229 { 00230 AuthData_Ptr result; 00231 00232 Pathname credfile; 00233 if (file.absolute()) 00234 // get from that file 00235 credfile = file; 00236 else 00237 // get from /etc/zypp/credentials.d, delete the leading path 00238 credfile = _options.customCredFileDir / file.basename(); 00239 00240 CredentialFileReader(credfile, bind(&Impl::processCredentials, this, _1)); 00241 if (_credsTmp.empty()) 00242 WAR << file << " does not contain valid credentials or is not readable." << endl; 00243 else 00244 { 00245 result = *_credsTmp.begin(); 00246 _credsTmp.clear(); 00247 } 00248 00249 return result; 00250 } 00251 00252 static int save_creds_in_file( 00253 const CredentialManager::CredentialSet creds, 00254 const Pathname & file, 00255 const mode_t mode) 00256 { 00257 int ret = 0; 00258 filesystem::assert_dir(file.dirname()); 00259 00260 std::ofstream fs(file.c_str()); 00261 if (!fs) 00262 ret = 1; 00263 00264 for_(it, creds.begin(), creds.end()) 00265 { 00266 (*it)->dumpAsIniOn(fs); 00267 fs << endl; 00268 } 00269 fs.close(); 00270 00271 filesystem::chmod(file, mode); 00272 00273 return ret; 00274 } 00275 00276 void CredentialManager::Impl::saveGlobalCredentials() 00277 { 00278 save_creds_in_file(_credsGlobal, _options.globalCredFilePath, 0640); 00279 } 00280 00281 void CredentialManager::Impl::saveUserCredentials() 00282 { 00283 save_creds_in_file(_credsUser, _options.userCredFilePath, 0600); 00284 } 00285 00286 00288 // 00289 // CLASS NAME : CredentialManager 00290 // 00292 00293 CredentialManager::CredentialManager(const CredManagerOptions & opts) 00294 : _pimpl(new Impl(opts)) 00295 {} 00296 00297 00298 AuthData_Ptr CredentialManager::getCred(const Url & url) 00299 { 00300 string credfile = url.getQueryParam("credentials"); 00301 if (credfile.empty()) 00302 return _pimpl->getCred(url); 00303 return _pimpl->getCredFromFile(credfile); 00304 } 00305 00306 00307 AuthData_Ptr CredentialManager::getCredFromFile(const Pathname & file) 00308 { return _pimpl->getCredFromFile(file); } 00309 00310 00311 void CredentialManager::addCred(const AuthData & cred) 00312 { 00313 Pathname credfile = cred.url().getQueryParam("credentials"); 00314 if (credfile.empty()) 00316 addUserCred(cred); 00317 else 00318 saveInFile(cred, credfile); 00319 } 00320 00321 00322 void CredentialManager::addGlobalCred(const AuthData & cred) 00323 { 00324 AuthData_Ptr c_ptr; 00325 c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed 00326 pair<CredentialIterator, bool> ret = _pimpl->_credsGlobal.insert(c_ptr); 00327 if (ret.second) 00328 _pimpl->_globalDirty = true; 00329 else if ((*ret.first)->password() != cred.password()) 00330 { 00331 _pimpl->_credsGlobal.erase(ret.first); 00332 _pimpl->_credsGlobal.insert(c_ptr); 00333 _pimpl->_globalDirty = true; 00334 } 00335 } 00336 00337 00338 void CredentialManager::addUserCred(const AuthData & cred) 00339 { 00340 AuthData_Ptr c_ptr; 00341 c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed 00342 pair<CredentialIterator, bool> ret = _pimpl->_credsUser.insert(c_ptr); 00343 if (ret.second) 00344 _pimpl->_userDirty = true; 00345 else if ((*ret.first)->password() != cred.password()) 00346 { 00347 _pimpl->_credsUser.erase(ret.first); 00348 _pimpl->_credsUser.insert(c_ptr); 00349 _pimpl->_userDirty = true; 00350 } 00351 } 00352 00353 00354 void CredentialManager::save() 00355 { 00356 if (_pimpl->_globalDirty) 00357 _pimpl->saveGlobalCredentials(); 00358 if (_pimpl->_userDirty) 00359 _pimpl->saveUserCredentials(); 00360 _pimpl->_globalDirty = false; 00361 _pimpl->_userDirty = false; 00362 } 00363 00364 00365 void CredentialManager::saveInGlobal(const AuthData & cred) 00366 { 00367 addGlobalCred(cred); 00368 save(); 00369 } 00370 00371 00372 void CredentialManager::saveInUser(const AuthData & cred) 00373 { 00374 addUserCred(cred); 00375 save(); 00376 } 00377 00378 00379 void CredentialManager::saveInFile(const AuthData & cred, const Pathname & credFile) 00380 { 00381 AuthData_Ptr c_ptr; 00382 c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed 00383 c_ptr->setUrl(Url()); // don't save url in custom creds file 00384 CredentialManager::CredentialSet creds; 00385 creds.insert(c_ptr); 00386 00387 int ret; 00388 if (credFile.absolute()) 00389 ret = save_creds_in_file(creds, credFile, 0640); 00390 else 00391 ret = save_creds_in_file( 00392 creds, _pimpl->_options.customCredFileDir / credFile, 0600); 00393 00394 if (!ret) 00395 { 00397 ERR << "error saving the credentials" << endl; 00398 } 00399 } 00400 00401 00402 void CredentialManager::clearAll(bool global) 00403 { 00404 if (global) 00405 { 00406 if (!filesystem::unlink(_pimpl->_options.globalCredFilePath)) 00407 ERR << "could not delete user credentials file " 00408 << _pimpl->_options.globalCredFilePath << endl; 00409 _pimpl->_credsUser.clear(); 00410 } 00411 else 00412 { 00413 if (!filesystem::unlink(_pimpl->_options.userCredFilePath)) 00414 ERR << "could not delete global credentials file" 00415 << _pimpl->_options.userCredFilePath << endl; 00416 _pimpl->_credsGlobal.clear(); 00417 } 00418 } 00419 00420 00421 CredentialManager::CredentialIterator CredentialManager::credsGlobalBegin() const 00422 { return _pimpl->_credsGlobal.begin(); } 00423 00424 CredentialManager::CredentialIterator CredentialManager::credsGlobalEnd() const 00425 { return _pimpl->_credsGlobal.end(); } 00426 00427 CredentialManager::CredentialSize CredentialManager::credsGlobalSize() const 00428 { return _pimpl->_credsGlobal.size(); } 00429 00430 bool CredentialManager::credsGlobalEmpty() const 00431 { return _pimpl->_credsGlobal.empty(); } 00432 00433 00434 CredentialManager::CredentialIterator CredentialManager::credsUserBegin() const 00435 { return _pimpl->_credsUser.begin(); } 00436 00437 CredentialManager::CredentialIterator CredentialManager::credsUserEnd() const 00438 { return _pimpl->_credsUser.end(); } 00439 00440 CredentialManager::CredentialSize CredentialManager::credsUserSize() const 00441 { return _pimpl->_credsUser.size(); } 00442 00443 bool CredentialManager::credsUserEmpty() const 00444 { return _pimpl->_credsUser.empty(); } 00445 00446 00448 } // media 00451 } // zypp