MediaCIFS.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00013 #include <iostream>
00014 #include <fstream>
00015
00016 #include "zypp/base/Logger.h"
00017 #include "zypp/base/Gettext.h"
00018 #include "zypp/TmpPath.h"
00019 #include "zypp/KVMap.h"
00020 #include "zypp/media/Mount.h"
00021 #include "zypp/media/MediaUserAuth.h"
00022 #include "zypp/media/CredentialManager.h"
00023 #include "zypp/ZYppCallbacks.h"
00024 #include "zypp/ZConfig.h"
00025
00026 #include "zypp/media/MediaCIFS.h"
00027
00028 #include <sys/types.h>
00029 #include <sys/mount.h>
00030 #include <errno.h>
00031 #include <dirent.h>
00032
00033 using namespace std;
00034
00035 namespace zypp {
00036 namespace media {
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 inline string getShare( Pathname spath_r )
00047 {
00048 if ( spath_r.empty() )
00049 return string();
00050
00051 string share( spath_r.absolutename().asString() );
00052 string::size_type sep = share.find( "/", 1 );
00053 if ( sep == string::npos )
00054 share = share.erase( 0, 1 );
00055 else
00056 share = share.substr( 1, sep-1 );
00057
00058
00059 while ( (sep = share.find( "%2f" )) != string::npos ) {
00060 share.replace( sep, 3, "/" );
00061 }
00062
00063 return share;
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 inline Pathname stripShare( Pathname spath_r )
00075 {
00076 if ( spath_r.empty() )
00077 return Pathname();
00078
00079 string striped( spath_r.absolutename().asString() );
00080 string::size_type sep = striped.find( "/", 1 );
00081 if ( sep == string::npos )
00082 return "/";
00083
00084 return striped.substr( sep );
00085 }
00086
00088
00089
00090
00092
00094
00095
00096
00097
00098
00099
00100
00101 MediaCIFS::MediaCIFS( const Url & url_r,
00102 const Pathname & attach_point_hint_r )
00103 : MediaHandler( url_r, attach_point_hint_r,
00104 stripShare( url_r.getPathName() ),
00105 false )
00106 {
00107 MIL << "MediaCIFS::MediaCIFS(" << url_r << ", " << attach_point_hint_r << ")" << endl;
00108 }
00109
00111
00112
00113
00114
00129 void MediaCIFS::attachTo(bool next)
00130 {
00131 if(_url.getHost().empty())
00132 ZYPP_THROW(MediaBadUrlEmptyHostException(_url));
00133 if(next)
00134 ZYPP_THROW(MediaNotSupportedException(_url));
00135
00136 string path = "//";
00137 path += _url.getHost() + "/" + getShare( _url.getPathName() );
00138
00139 MediaSourceRef media( new MediaSource( "cifs", path));
00140 AttachedMedia ret( findAttachedMedia( media));
00141
00142 if( ret.mediaSource &&
00143 ret.attachPoint &&
00144 !ret.attachPoint->empty())
00145 {
00146 DBG << "Using a shared media "
00147 << ret.mediaSource->name
00148 << " attached on "
00149 << ret.attachPoint->path
00150 << endl;
00151
00152 removeAttachPoint();
00153 setAttachPoint(ret.attachPoint);
00154 setMediaSource(ret.mediaSource);
00155 return;
00156 }
00157
00158 std::string mountpoint = attachPoint().asString();
00159 if( !isUseableAttachPoint(attachPoint()))
00160 {
00161 mountpoint = createAttachPoint().asString();
00162 if( mountpoint.empty())
00163 ZYPP_THROW( MediaBadAttachPointException(url()));
00164 setAttachPoint( mountpoint, true);
00165 }
00166
00167 Mount mount;
00168 CredentialManager cm;
00169
00170 Mount::Options options( _url.getQueryParam("mountoptions") );
00171 string username = _url.getUsername();
00172 string password = _url.getPassword();
00173
00174 if ( ! options.has( "rw" ) ) {
00175 options["ro"];
00176 }
00177
00178
00179 string workgroup = _url.getQueryParam("workgroup");
00180 if ( workgroup.empty() )
00181 workgroup = _url.getQueryParam("domain");
00182 if ( !workgroup.empty() )
00183 options["domain"] = workgroup;
00184
00185
00186
00187 Mount::Options::iterator toEnv;
00188 toEnv = options.find("username");
00189 if ( toEnv != options.end() ) {
00190 if ( username.empty() )
00191 username = toEnv->second;
00192 options.erase( toEnv );
00193 }
00194
00195 toEnv = options.find("user");
00196 if ( toEnv != options.end() ) {
00197 if ( username.empty() )
00198 username = toEnv->second;
00199 options.erase( toEnv );
00200 }
00201
00202
00203
00204 toEnv = options.find("password");
00205 if ( toEnv != options.end() ) {
00206 if ( password.empty() )
00207 password = toEnv->second;
00208 options.erase( toEnv );
00209 }
00210
00211 toEnv = options.find("pass");
00212 if ( toEnv != options.end() ) {
00213 if ( password.empty() )
00214 password = toEnv->second;
00215 options.erase( toEnv );
00216 }
00217
00218 if ( username.empty() || password.empty() )
00219 {
00220 AuthData_Ptr c = cm.getCred(_url);
00221 if (c)
00222 {
00223 username = c->username();
00224 password = c->password();
00225 }
00226 }
00227
00228 bool firstTry = true;
00229 bool authRequired = false;
00230 AuthData authdata;
00231 do
00232 {
00233
00234 if ( !firstTry )
00235 {
00236 username = authdata.username();
00237 password = authdata.password();
00238 }
00239
00240
00241 Mount::Environment environment;
00242 if ( !username.empty() )
00243 environment["USER"] = username;
00244 if ( !password.empty() )
00245 environment["PASSWD"] = password;
00246
00248
00249
00250 filesystem::TmpPath credentials;
00251 if ( !username.empty() || !password.empty() )
00252 {
00253 filesystem::TmpFile tmp;
00254 ofstream outs( tmp.path().asString().c_str() );
00255 outs << "username=" << username << endl;
00256 outs << "password=" << password << endl;
00257 outs.close();
00258
00259 credentials = tmp;
00260 options["credentials"] = credentials.path().asString();
00261 }
00262 else
00263 {
00264
00265 if ( options.has( "noguest" ) )
00266 options.erase( "noguest" );
00267 else
00268
00269
00270 options["guest"];
00271 }
00272
00273
00275
00276 try
00277 {
00278 mount.mount( path, mountpoint, "cifs",
00279 options.asString(), environment );
00280 setMediaSource(media);
00281 break;
00282 }
00283 catch (const MediaMountException & e)
00284 {
00285 ZYPP_CAUGHT( e );
00286
00287 if ( e.mountError() == "Permission denied" )
00288 authRequired = authenticate( authdata, firstTry );
00289 else
00290 ZYPP_RETHROW( e );
00291 }
00292
00293 firstTry = false;
00294 }
00295 while ( authRequired );
00296
00297
00298
00299 int limit = 3;
00300 bool mountsucceeded;
00301 while( !(mountsucceeded=isAttached()) && --limit)
00302 sleep(1);
00303
00304 if ( !mountsucceeded )
00305 {
00306 setMediaSource(MediaSourceRef());
00307 try
00308 {
00309 mount.umount(attachPoint().asString());
00310 }
00311 catch (const MediaException & excpt_r)
00312 {
00313 ZYPP_CAUGHT(excpt_r);
00314 }
00315 ZYPP_THROW(MediaMountException(
00316 "Unable to verify that the media was mounted",
00317 path, mountpoint
00318 ));
00319 }
00320 }
00321
00323
00324
00325
00326
00327
00328
00329 bool
00330 MediaCIFS::isAttached() const
00331 {
00332 return checkAttached(true);
00333 }
00334
00336
00337
00338
00339
00340
00341
00342
00343 void MediaCIFS::releaseFrom( const std::string & ejectDev )
00344 {
00345 Mount mount;
00346 mount.umount(attachPoint().asString());
00347 }
00348
00350
00351
00352
00353
00354
00355
00356 void MediaCIFS::getFile (const Pathname & filename) const
00357 {
00358 MediaHandler::getFile( filename );
00359 }
00360
00362
00363
00364
00365
00366
00367
00368 void MediaCIFS::getDir( const Pathname & dirname, bool recurse_r ) const
00369 {
00370 MediaHandler::getDir( dirname, recurse_r );
00371 }
00372
00374
00375
00376
00377
00378
00379
00380
00381 void MediaCIFS::getDirInfo( std::list<std::string> & retlist,
00382 const Pathname & dirname, bool dots ) const
00383 {
00384 MediaHandler::getDirInfo( retlist, dirname, dots );
00385 }
00386
00388
00389
00390
00391
00392
00393
00394
00395 void MediaCIFS::getDirInfo( filesystem::DirContent & retlist,
00396 const Pathname & dirname, bool dots ) const
00397 {
00398 MediaHandler::getDirInfo( retlist, dirname, dots );
00399 }
00400
00401 bool MediaCIFS::getDoesFileExist( const Pathname & filename ) const
00402 {
00403 return MediaHandler::getDoesFileExist( filename );
00404 }
00405
00406 bool MediaCIFS::authenticate(AuthData & authdata, bool firstTry) const
00407 {
00409 CredentialManager cm(CredManagerOptions(ZConfig::instance().systemRoot()));
00410
00411
00412 AuthData_Ptr cmcred = cm.getCred(_url);
00413
00414 AuthData_Ptr smbcred;
00415 smbcred.reset(new AuthData());
00416 callback::SendReport<AuthenticationReport> auth_report;
00417
00418
00419 if (!_url.getUsername().empty() && firstTry)
00420 smbcred->setUsername(_url.getUsername());
00421
00422 else if (cmcred)
00423 smbcred->setUsername(cmcred->username());
00424
00425
00426 cmcred.reset();
00427
00428 string prompt_msg = str::form(
00430 _("Authentication required for '%s'"), _url.asString().c_str());
00431
00432
00433 if (auth_report->prompt(_url, prompt_msg, *smbcred))
00434 {
00435 DBG << "callback answer: retry" << endl
00436 << "AuthData: " << *smbcred << endl;
00437
00438 if (smbcred->valid())
00439 {
00440 cmcred = smbcred;
00441
00442
00450 }
00451 }
00452 else
00453 DBG << "callback answer: cancel" << endl;
00454
00455
00456 if (cmcred)
00457 {
00458 authdata.setUsername(cmcred->username());
00459 authdata.setPassword(cmcred->password());
00460
00461
00462 cmcred->setUrl(_url);
00463 cm.addCred(*cmcred);
00464 cm.save();
00465
00466 return true;
00467 }
00468
00469 return false;
00470 }
00471
00472
00473 }
00474 }