kfileshare.cpp
00001 /* This file is part of the KDE project 00002 Copyright (c) 2001 David Faure <david@mandrakesoft.com> 00003 Copyright (c) 2001 Laurent Montel <lmontel@mandrakesoft.com> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License version 2 as published by the Free Software Foundation. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "kfileshare.h" 00021 #include <tqdir.h> 00022 #include <tqfile.h> 00023 #include <tqregexp.h> 00024 #include <kprocess.h> 00025 #include <kprocio.h> 00026 #include <klocale.h> 00027 #include <kstaticdeleter.h> 00028 #include <kstandarddirs.h> 00029 #include <kdebug.h> 00030 #include <kdirwatch.h> 00031 #include <stdio.h> 00032 #include <stdlib.h> 00033 #include <errno.h> 00034 #include <kdirnotify_stub.h> 00035 #include <ksimpleconfig.h> 00036 #include <kuser.h> 00037 00038 KFileShare::Authorization KFileShare::s_authorization = NotInitialized; 00039 //TQStringList* KFileShare::s_shareList = 0L; 00040 //static KStaticDeleter<TQStringList> sdShareList; 00041 TQMap<TQString,TQString>* KFileShare::s_shareMap = 0L; 00042 static KStaticDeleter<TQMap<TQString,TQString> > sdShareMap; 00043 00044 KFileShare::ShareMode KFileShare::s_shareMode; 00045 bool KFileShare::s_sambaEnabled; 00046 bool KFileShare::s_nfsEnabled; 00047 bool KFileShare::s_restricted; 00048 TQString KFileShare::s_fileShareGroup; 00049 bool KFileShare::s_sharingEnabled; 00050 00051 00052 #define FILESHARECONF "/etc/security/fileshare.conf" 00053 00054 KFileSharePrivate::KFileSharePrivate() 00055 { 00056 KDirWatch::self()->addFile(FILESHARECONF); 00057 connect(KDirWatch::self(), TQT_SIGNAL(dirty (const TQString&)),this, 00058 TQT_SLOT(slotFileChange(const TQString &))); 00059 connect(KDirWatch::self(), TQT_SIGNAL(created(const TQString&)),this, 00060 TQT_SLOT(slotFileChange(const TQString &))); 00061 connect(KDirWatch::self(), TQT_SIGNAL(deleted(const TQString&)),this, 00062 TQT_SLOT(slotFileChange(const TQString &))); 00063 } 00064 00065 KFileSharePrivate::~KFileSharePrivate() 00066 { 00067 KDirWatch::self()->removeFile(FILESHARECONF); 00068 } 00069 00070 KFileSharePrivate *KFileSharePrivate::_self=0L; 00071 00072 static KStaticDeleter<KFileSharePrivate> kstFileShare; 00073 00074 KFileSharePrivate* KFileSharePrivate::self() 00075 { 00076 if (!_self) 00077 _self = kstFileShare.setObject(_self, new KFileSharePrivate()); 00078 return _self; 00079 } 00080 00081 void KFileSharePrivate::slotFileChange(const TQString &file) 00082 { 00083 if(file==FILESHARECONF) { 00084 KFileShare::readConfig(); 00085 KFileShare::readShareList(); 00086 } 00087 } 00088 00089 void KFileShare::readConfig() // static 00090 { 00091 // Create KFileSharePrivate instance 00092 KFileSharePrivate::self(); 00093 KSimpleConfig config(TQString::fromLatin1(FILESHARECONF),true); 00094 00095 s_sharingEnabled = config.readEntry("FILESHARING", "yes") == "yes"; 00096 s_restricted = config.readEntry("RESTRICT", "yes") == "yes"; 00097 s_fileShareGroup = config.readEntry("FILESHAREGROUP", "fileshare"); 00098 00099 00100 if (!s_sharingEnabled) 00101 s_authorization = UserNotAllowed; 00102 else 00103 if (!s_restricted ) 00104 s_authorization = Authorized; 00105 else { 00106 // check if current user is in fileshare group 00107 KUserGroup shareGroup(s_fileShareGroup); 00108 if (shareGroup.users().findIndex(KUser()) > -1 ) 00109 s_authorization = Authorized; 00110 else 00111 s_authorization = UserNotAllowed; 00112 } 00113 00114 if (config.readEntry("SHARINGMODE", "simple") == "simple") 00115 s_shareMode = Simple; 00116 else 00117 s_shareMode = Advanced; 00118 00119 00120 s_sambaEnabled = config.readEntry("SAMBA", "yes") == "yes"; 00121 s_nfsEnabled = config.readEntry("NFS", "yes") == "yes"; 00122 } 00123 00124 KFileShare::ShareMode KFileShare::shareMode() { 00125 if ( s_authorization == NotInitialized ) 00126 readConfig(); 00127 00128 return s_shareMode; 00129 } 00130 00131 bool KFileShare::sharingEnabled() { 00132 if ( s_authorization == NotInitialized ) 00133 readConfig(); 00134 00135 return s_sharingEnabled; 00136 } 00137 00138 bool KFileShare::isRestricted() { 00139 if ( s_authorization == NotInitialized ) 00140 readConfig(); 00141 00142 return s_restricted; 00143 } 00144 00145 TQString KFileShare::fileShareGroup() { 00146 if ( s_authorization == NotInitialized ) 00147 readConfig(); 00148 00149 return s_fileShareGroup; 00150 } 00151 00152 00153 bool KFileShare::sambaEnabled() { 00154 if ( s_authorization == NotInitialized ) 00155 readConfig(); 00156 00157 return s_sambaEnabled; 00158 } 00159 00160 bool KFileShare::nfsEnabled() { 00161 if ( s_authorization == NotInitialized ) 00162 readConfig(); 00163 00164 return s_nfsEnabled; 00165 } 00166 00167 00168 void KFileShare::readShareList() 00169 { 00170 KFileSharePrivate::self(); 00171 if ( !s_shareMap ) 00172 sdShareMap.setObject( s_shareMap, new TQMap<TQString,TQString> ); 00173 else 00174 s_shareMap->clear(); 00175 00176 // /usr/sbin on Mandrake, $PATH allows flexibility for other distributions 00177 TQString exe = findExe( "filesharelist" ); 00178 if (exe.isEmpty()) { 00179 s_authorization = ErrorNotFound; 00180 return; 00181 } 00182 KProcIO proc; 00183 proc << exe; 00184 if ( !proc.start( KProcess::Block ) ) { 00185 kdError() << "Can't run " << exe << endl; 00186 s_authorization = ErrorNotFound; 00187 return; 00188 } 00189 00190 // Reading code shamelessly stolen from khostname.cpp ;) 00191 TQString line; 00192 TQString options; 00193 TQString path; 00194 int length; 00195 TQRegExp rx_line("([^\\s]+)\\s+(.*)"); 00196 do { 00197 length = proc.readln(line, true); 00198 if ( length > 0 ) 00199 { 00200 if ( line[length-1] != '/' ) 00201 line += '/'; 00202 if( rx_line.search( line ) != -1 ) { 00203 options = rx_line.cap(1); 00204 path = rx_line.cap(2); 00205 (*s_shareMap)[path] = options; 00206 } 00207 kdDebug(7000) << "Shared dir:" << line << endl; 00208 } 00209 } while (length > -1); 00210 } 00211 00212 00213 int KFileShare::isDirectoryShared( const TQString& _path ) 00214 { 00215 int ret(0); 00216 00217 if ( ! s_shareMap ) 00218 readShareList(); 00219 00220 TQString path( _path ); 00221 if ( path[path.length()-1] != '/' ) 00222 path += '/'; 00223 //return s_shareList && s_shareList->contains( path ); 00224 if( (*s_shareMap).contains(path) && !((*s_shareMap)[path].isEmpty()) ) { 00225 ret+=1; 00226 if( (*s_shareMap)[path].find("readwrite") != -1 ) 00227 ret+=2; 00228 } 00229 00230 return ret; 00231 } 00232 00233 KFileShare::Authorization KFileShare::authorization() 00234 { 00235 // The app should do this on startup, but if it doesn't, let's do here. 00236 if ( s_authorization == NotInitialized ) 00237 readConfig(); 00238 return s_authorization; 00239 } 00240 00241 TQString KFileShare::findExe( const char* exeName ) 00242 { 00243 // /usr/sbin on Mandrake, $PATH allows flexibility for other distributions 00244 TQString path = TQString::fromLocal8Bit(getenv("PATH")) + TQString::fromLatin1(":/usr/sbin"); 00245 TQString exe = KStandardDirs::findExe( exeName, path ); 00246 if (exe.isEmpty()) 00247 kdError() << exeName << " not found in " << path << endl; 00248 return exe; 00249 } 00250 00251 bool KFileShare::setShared( const TQString& path, bool shared ) 00252 { 00253 return SuSEsetShared( path, shared, false ); 00254 } 00255 00256 bool KFileShare::SuSEsetShared( const TQString& path, bool shared, bool rw ) 00257 { 00258 if (! KFileShare::sharingEnabled() || 00259 KFileShare::shareMode() == Advanced) 00260 return false; 00261 00262 TQString exe = KFileShare::findExe( "fileshareset" ); 00263 if (exe.isEmpty()) 00264 return false; 00265 00266 // we want to share, so we kick it first - just to be sure 00267 KProcess proc; 00268 proc << exe; 00269 proc << "--remove"; 00270 proc << path; 00271 proc.start( KProcess::Block ); 00272 proc.clearArguments(); 00273 00274 proc << exe; 00275 if( rw ) 00276 proc << "--rw"; 00277 if ( shared ) 00278 proc << "--add"; 00279 else 00280 proc << "--remove"; 00281 proc << path; 00282 proc.start( KProcess::Block ); // should be ok, the perl script terminates fast 00283 bool ok = proc.normalExit() && (proc.exitStatus() == 0); 00284 kdDebug(7000) << "KFileSharePropsPlugin::setShared normalExit=" 00285 << proc.normalExit() << endl; 00286 kdDebug(7000) << "KFileSharePropsPlugin::setShared exitStatus=" 00287 << proc.exitStatus() << endl; 00288 if ( proc.normalExit() ) { 00289 switch( proc.exitStatus() ) { 00290 case 1: 00291 // User is not authorized 00292 break; 00293 case 3: 00294 // Called script with --add, but path was already shared before. 00295 // Result is nevertheless what the client wanted, so 00296 // this is alright. 00297 ok = true; 00298 break; 00299 case 4: 00300 // Invalid mount point 00301 break; 00302 case 5: 00303 // Called script with --remove, but path was not shared before. 00304 // Result is nevertheless what the client wanted, so 00305 // this is alright. 00306 ok = true; 00307 break; 00308 case 6: 00309 // There is no export method 00310 break; 00311 case 7: 00312 // file sharing is disabled 00313 break; 00314 case 8: 00315 // advanced sharing is enabled 00316 break; 00317 case 255: 00318 // Abitrary error 00319 break; 00320 } 00321 } 00322 00323 return ok; 00324 } 00325 00326 bool KFileShare::sambaActive() 00327 { 00328 // rcsmb is not executable by users, try ourselves 00329 int status = system( "/sbin/checkproc -p /var/run/samba/smbd.pid /usr/sbin/smbd" ); 00330 return status != -1 && WIFEXITED( status ) && WEXITSTATUS( status ) == 0; 00331 } 00332 00333 bool KFileShare::nfsActive() 00334 { 00335 // rcnfsserver is not executable by users, try ourselves 00336 int status = system( "/sbin/checkproc /usr/sbin/rpc.mountd" ); 00337 if( status != -1 && WIFEXITED( status ) && WEXITSTATUS( status ) == 0 ) 00338 { 00339 status = system( "/sbin/checkproc -n nfsd" ); 00340 if( status != -1 && WIFEXITED( status ) && WEXITSTATUS( status ) == 0 ) 00341 return true; 00342 } 00343 return false; 00344 } 00345 00346 #include "kfileshare.moc"