|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (c) 2001 David Faure <david@mandrakesoft.com>
|
|
|
|
Copyright (c) 2001 Laurent Montel <lmontel@mandrakesoft.com>
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License version 2 as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "tdefileshare.h"
|
|
|
|
#include <tqdir.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <kprocess.h>
|
|
|
|
#include <kprocio.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <kstaticdeleter.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kdirwatch.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <kdirnotify_stub.h>
|
|
|
|
#include <ksimpleconfig.h>
|
|
|
|
#include <kuser.h>
|
|
|
|
|
|
|
|
KFileShare::Authorization KFileShare::s_authorization = NotInitialized;
|
|
|
|
//TQStringList* KFileShare::s_shareList = 0L;
|
|
|
|
//static KStaticDeleter<TQStringList> sdShareList;
|
|
|
|
TQMap<TQString,TQString>* KFileShare::s_shareMap = 0L;
|
|
|
|
static KStaticDeleter<TQMap<TQString,TQString> > sdShareMap;
|
|
|
|
|
|
|
|
KFileShare::ShareMode KFileShare::s_shareMode;
|
|
|
|
bool KFileShare::s_sambaEnabled;
|
|
|
|
bool KFileShare::s_nfsEnabled;
|
|
|
|
bool KFileShare::s_restricted;
|
|
|
|
TQString KFileShare::s_fileShareGroup;
|
|
|
|
bool KFileShare::s_sharingEnabled;
|
|
|
|
|
|
|
|
|
|
|
|
#define FILESHARECONF "/etc/security/fileshare.conf"
|
|
|
|
|
|
|
|
KFileSharePrivate::KFileSharePrivate()
|
|
|
|
{
|
|
|
|
KDirWatch::self()->addFile(FILESHARECONF);
|
|
|
|
connect(KDirWatch::self(), TQT_SIGNAL(dirty (const TQString&)),this,
|
|
|
|
TQT_SLOT(slotFileChange(const TQString &)));
|
|
|
|
connect(KDirWatch::self(), TQT_SIGNAL(created(const TQString&)),this,
|
|
|
|
TQT_SLOT(slotFileChange(const TQString &)));
|
|
|
|
connect(KDirWatch::self(), TQT_SIGNAL(deleted(const TQString&)),this,
|
|
|
|
TQT_SLOT(slotFileChange(const TQString &)));
|
|
|
|
}
|
|
|
|
|
|
|
|
KFileSharePrivate::~KFileSharePrivate()
|
|
|
|
{
|
|
|
|
KDirWatch::self()->removeFile(FILESHARECONF);
|
|
|
|
}
|
|
|
|
|
|
|
|
KFileSharePrivate *KFileSharePrivate::_self=0L;
|
|
|
|
|
|
|
|
static KStaticDeleter<KFileSharePrivate> kstFileShare;
|
|
|
|
|
|
|
|
KFileSharePrivate* KFileSharePrivate::self()
|
|
|
|
{
|
|
|
|
if (!_self)
|
|
|
|
_self = kstFileShare.setObject(_self, new KFileSharePrivate());
|
|
|
|
return _self;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KFileSharePrivate::slotFileChange(const TQString &file)
|
|
|
|
{
|
|
|
|
if(file==FILESHARECONF) {
|
|
|
|
KFileShare::readConfig();
|
|
|
|
KFileShare::readShareList();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KFileShare::readConfig() // static
|
|
|
|
{
|
|
|
|
// Create KFileSharePrivate instance
|
|
|
|
KFileSharePrivate::self();
|
|
|
|
KSimpleConfig config(TQString::fromLatin1(FILESHARECONF),true);
|
|
|
|
|
|
|
|
s_sharingEnabled = config.readEntry("FILESHARING", "yes") == "yes";
|
|
|
|
s_restricted = config.readEntry("RESTRICT", "yes") == "yes";
|
|
|
|
s_fileShareGroup = config.readEntry("FILESHAREGROUP", "fileshare");
|
|
|
|
|
|
|
|
|
|
|
|
if (!s_sharingEnabled)
|
|
|
|
s_authorization = UserNotAllowed;
|
|
|
|
else
|
|
|
|
if (!s_restricted )
|
|
|
|
s_authorization = Authorized;
|
|
|
|
else {
|
|
|
|
// check if current user is in fileshare group
|
|
|
|
KUserGroup shareGroup(s_fileShareGroup);
|
|
|
|
if (shareGroup.users().findIndex(KUser()) > -1 )
|
|
|
|
s_authorization = Authorized;
|
|
|
|
else
|
|
|
|
s_authorization = UserNotAllowed;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config.readEntry("SHARINGMODE", "simple") == "simple")
|
|
|
|
s_shareMode = Simple;
|
|
|
|
else
|
|
|
|
s_shareMode = Advanced;
|
|
|
|
|
|
|
|
|
|
|
|
s_sambaEnabled = config.readEntry("SAMBA", "yes") == "yes";
|
|
|
|
s_nfsEnabled = config.readEntry("NFS", "yes") == "yes";
|
|
|
|
}
|
|
|
|
|
|
|
|
KFileShare::ShareMode KFileShare::shareMode() {
|
|
|
|
if ( s_authorization == NotInitialized )
|
|
|
|
readConfig();
|
|
|
|
|
|
|
|
return s_shareMode;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KFileShare::sharingEnabled() {
|
|
|
|
if ( s_authorization == NotInitialized )
|
|
|
|
readConfig();
|
|
|
|
|
|
|
|
return s_sharingEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KFileShare::isRestricted() {
|
|
|
|
if ( s_authorization == NotInitialized )
|
|
|
|
readConfig();
|
|
|
|
|
|
|
|
return s_restricted;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KFileShare::fileShareGroup() {
|
|
|
|
if ( s_authorization == NotInitialized )
|
|
|
|
readConfig();
|
|
|
|
|
|
|
|
return s_fileShareGroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool KFileShare::sambaEnabled() {
|
|
|
|
if ( s_authorization == NotInitialized )
|
|
|
|
readConfig();
|
|
|
|
|
|
|
|
return s_sambaEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KFileShare::nfsEnabled() {
|
|
|
|
if ( s_authorization == NotInitialized )
|
|
|
|
readConfig();
|
|
|
|
|
|
|
|
return s_nfsEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KFileShare::readShareList()
|
|
|
|
{
|
|
|
|
KFileSharePrivate::self();
|
|
|
|
if ( !s_shareMap )
|
|
|
|
sdShareMap.setObject( s_shareMap, new TQMap<TQString,TQString> );
|
|
|
|
else
|
|
|
|
s_shareMap->clear();
|
|
|
|
|
|
|
|
// /usr/sbin on Mandrake, $PATH allows flexibility for other distributions
|
|
|
|
TQString exe = findExe( "filesharelist" );
|
|
|
|
if (exe.isEmpty()) {
|
|
|
|
s_authorization = ErrorNotFound;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
KProcIO proc;
|
|
|
|
proc << exe;
|
|
|
|
if ( !proc.start( TDEProcess::Block ) ) {
|
|
|
|
kdError() << "Can't run " << exe << endl;
|
|
|
|
s_authorization = ErrorNotFound;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reading code shamelessly stolen from khostname.cpp ;)
|
|
|
|
TQString line;
|
|
|
|
TQString options;
|
|
|
|
TQString path;
|
|
|
|
int length;
|
|
|
|
TQRegExp rx_line("([^\\s]+)\\s+(.*)");
|
|
|
|
do {
|
|
|
|
length = proc.readln(line, true);
|
|
|
|
if ( length > 0 )
|
|
|
|
{
|
|
|
|
if ( line[length-1] != '/' )
|
|
|
|
line += '/';
|
|
|
|
if( rx_line.search( line ) != -1 ) {
|
|
|
|
options = rx_line.cap(1);
|
|
|
|
path = rx_line.cap(2);
|
|
|
|
(*s_shareMap)[path] = options;
|
|
|
|
}
|
|
|
|
kdDebug(7000) << "Shared dir:" << line << endl;
|
|
|
|
}
|
|
|
|
} while (length > -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int KFileShare::isDirectoryShared( const TQString& _path )
|
|
|
|
{
|
|
|
|
int ret(0);
|
|
|
|
|
|
|
|
if ( ! s_shareMap )
|
|
|
|
readShareList();
|
|
|
|
|
|
|
|
TQString path( _path );
|
|
|
|
if ( path[path.length()-1] != '/' )
|
|
|
|
path += '/';
|
|
|
|
//return s_shareList && s_shareList->contains( path );
|
|
|
|
if( (*s_shareMap).contains(path) && !((*s_shareMap)[path].isEmpty()) ) {
|
|
|
|
ret+=1;
|
|
|
|
if( (*s_shareMap)[path].find("readwrite") != -1 )
|
|
|
|
ret+=2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
KFileShare::Authorization KFileShare::authorization()
|
|
|
|
{
|
|
|
|
// The app should do this on startup, but if it doesn't, let's do here.
|
|
|
|
if ( s_authorization == NotInitialized )
|
|
|
|
readConfig();
|
|
|
|
return s_authorization;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KFileShare::findExe( const char* exeName )
|
|
|
|
{
|
|
|
|
// /usr/sbin on Mandrake, $PATH allows flexibility for other distributions
|
|
|
|
TQString path = TQString::fromLocal8Bit(getenv("PATH")) + TQString::fromLatin1(":/usr/sbin");
|
|
|
|
TQString exe = TDEStandardDirs::findExe( exeName, path );
|
|
|
|
if (exe.isEmpty())
|
|
|
|
kdError() << exeName << " not found in " << path << endl;
|
|
|
|
return exe;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KFileShare::setShared( const TQString& path, bool shared )
|
|
|
|
{
|
|
|
|
return SuSEsetShared( path, shared, false );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KFileShare::SuSEsetShared( const TQString& path, bool shared, bool rw )
|
|
|
|
{
|
|
|
|
if (! KFileShare::sharingEnabled() ||
|
|
|
|
KFileShare::shareMode() == Advanced)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
TQString exe = KFileShare::findExe( "fileshareset" );
|
|
|
|
if (exe.isEmpty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// we want to share, so we kick it first - just to be sure
|
|
|
|
TDEProcess proc;
|
|
|
|
proc << exe;
|
|
|
|
proc << "--remove";
|
|
|
|
proc << path;
|
|
|
|
proc.start( TDEProcess::Block );
|
|
|
|
proc.clearArguments();
|
|
|
|
|
|
|
|
proc << exe;
|
|
|
|
if( rw )
|
|
|
|
proc << "--rw";
|
|
|
|
if ( shared )
|
|
|
|
proc << "--add";
|
|
|
|
else
|
|
|
|
proc << "--remove";
|
|
|
|
proc << path;
|
|
|
|
proc.start( TDEProcess::Block ); // should be ok, the perl script terminates fast
|
|
|
|
bool ok = proc.normalExit() && (proc.exitStatus() == 0);
|
|
|
|
kdDebug(7000) << "KFileSharePropsPlugin::setShared normalExit="
|
|
|
|
<< proc.normalExit() << endl;
|
|
|
|
kdDebug(7000) << "KFileSharePropsPlugin::setShared exitStatus="
|
|
|
|
<< proc.exitStatus() << endl;
|
|
|
|
if ( proc.normalExit() ) {
|
|
|
|
switch( proc.exitStatus() ) {
|
|
|
|
case 1:
|
|
|
|
// User is not authorized
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
// Called script with --add, but path was already shared before.
|
|
|
|
// Result is nevertheless what the client wanted, so
|
|
|
|
// this is alright.
|
|
|
|
ok = true;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
// Invalid mount point
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
// Called script with --remove, but path was not shared before.
|
|
|
|
// Result is nevertheless what the client wanted, so
|
|
|
|
// this is alright.
|
|
|
|
ok = true;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
// There is no export method
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
// file sharing is disabled
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
// advanced sharing is enabled
|
|
|
|
break;
|
|
|
|
case 255:
|
|
|
|
// Abitrary error
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KFileShare::sambaActive()
|
|
|
|
{
|
|
|
|
// rcsmb is not executable by users, try ourselves
|
|
|
|
int status = system( "/sbin/checkproc -p /var/run/samba/smbd.pid /usr/sbin/smbd" );
|
|
|
|
return status != -1 && WIFEXITED( status ) && WEXITSTATUS( status ) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KFileShare::nfsActive()
|
|
|
|
{
|
|
|
|
// rcnfsserver is not executable by users, try ourselves
|
|
|
|
int status = system( "/sbin/checkproc /usr/sbin/rpc.mountd" );
|
|
|
|
if( status != -1 && WIFEXITED( status ) && WEXITSTATUS( status ) == 0 )
|
|
|
|
{
|
|
|
|
status = system( "/sbin/checkproc -n nfsd" );
|
|
|
|
if( status != -1 && WIFEXITED( status ) && WEXITSTATUS( status ) == 0 )
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "tdefileshare.moc"
|