You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1796 lines
48 KiB
1796 lines
48 KiB
/***************************************************************************
|
|
smb4kfileio - Does file IO operations for Smb4K
|
|
-------------------
|
|
begin : Do Jan 1 2004
|
|
copyright : (C) 2004-2007 by Alexander Reinholdt
|
|
email : dustpuppy@users.berlios.de
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program 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 *
|
|
* General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
|
|
* MA 02110-1301 USA *
|
|
***************************************************************************/
|
|
|
|
// TQt includes
|
|
#include <tqdir.h>
|
|
#include <tqfile.h>
|
|
#include <tqtextstream.h>
|
|
|
|
// KDE includes
|
|
#include <kapplication.h>
|
|
#include <kdebug.h>
|
|
#include <klocale.h>
|
|
|
|
// system specific includes
|
|
#include <errno.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <grp.h>
|
|
#include <pwd.h>
|
|
|
|
// application specific includes
|
|
#include "smb4kfileio.h"
|
|
#include "smb4kdefs.h"
|
|
#include "smb4kerror.h"
|
|
#include "smb4kglobal.h"
|
|
#include "smb4ksettings.h"
|
|
|
|
using namespace Smb4KGlobal;
|
|
|
|
|
|
|
|
Smb4KFileIO::Smb4KFileIO( TQObject *parent, const char *name ) : TQObject( parent, name )
|
|
{
|
|
m_operation = NoOperation;
|
|
m_state = Idle;
|
|
m_error_occurred = false;
|
|
|
|
m_proc = new KProcess( this, "FileIOProcess" );
|
|
m_proc->setUseShell( true );
|
|
|
|
connect( m_proc, TQT_SIGNAL( receivedStderr( KProcess *, char *, int ) ),
|
|
this, TQT_SLOT( slotReceivedStderr( KProcess *, char *, int ) ) );
|
|
|
|
connect( m_proc, TQT_SIGNAL( receivedStdout( KProcess *, char *, int ) ),
|
|
this, TQT_SLOT( slotReceivedStdout( KProcess *, char *, int ) ) );
|
|
|
|
connect( m_proc, TQT_SIGNAL( processExited( KProcess * ) ),
|
|
this, TQT_SLOT( slotProcessExited( KProcess * ) ) );
|
|
|
|
connect( kapp, TQT_SIGNAL( shutDown() ),
|
|
this, TQT_SLOT( slotShutdown() ) );
|
|
}
|
|
|
|
|
|
Smb4KFileIO::~Smb4KFileIO()
|
|
{
|
|
}
|
|
|
|
|
|
bool Smb4KFileIO::writeSudoers( Smb4KFileIO::Operation operation )
|
|
{
|
|
m_operation = operation;
|
|
bool ok = false;
|
|
|
|
// Stop here if nothing has changed:
|
|
if ( m_operation == NoOperation )
|
|
{
|
|
emit finished();
|
|
|
|
ok = true;
|
|
|
|
return ok;
|
|
}
|
|
|
|
TQString file = "sudoers";
|
|
|
|
if ( createLockFile( file ) )
|
|
{
|
|
// Find the file first:
|
|
TQCString canonical_path = findFile( file );
|
|
|
|
if ( !canonical_path.isEmpty() )
|
|
{
|
|
// Stat the file, so that we know that it is safe to
|
|
// read from and write to it and whether we need to
|
|
// ask for the super user's password:
|
|
struct stat buf;
|
|
|
|
if ( lstat( canonical_path, &buf ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
Smb4KError::error( ERROR_GETTING_PERMISSIONS, canonical_path, strerror( error_number ) );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
// Look for the groups the user is in:
|
|
long ngroups_max;
|
|
ngroups_max = sysconf(_SC_NGROUPS_MAX);
|
|
|
|
gid_t list[ngroups_max];
|
|
|
|
if ( getgroups( ngroups_max, list ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
Smb4KError::error( ERROR_GETTING_GIDS, TQString(), strerror( error_number ) );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
gid_t sup_gid = 65534; // set this to gid 'nobody' for initialization
|
|
bool found_gid = false;
|
|
int i = 0;
|
|
|
|
while ( list[i] )
|
|
{
|
|
if ( list[i] == buf.st_gid )
|
|
{
|
|
sup_gid = list[i];
|
|
found_gid = true;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
// Error out if the file is irregular.
|
|
// Yes, yes, I know that this is normally done in a different
|
|
// way and that there might be a race here, but, hey, right here
|
|
// I don't care!
|
|
if ( !S_ISREG( buf.st_mode ) || S_ISFIFO( buf.st_mode ) || S_ISLNK( buf.st_mode ) )
|
|
{
|
|
Smb4KError::error( ERROR_FILE_IS_IRREGULAR, canonical_path, TQString() );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
// Check access rights:
|
|
if ( (buf.st_uid == getuid() && (buf.st_mode & 00600) == (S_IWUSR | S_IRUSR)) /* user */ ||
|
|
(found_gid && buf.st_gid == sup_gid && (buf.st_mode & 00060) == (S_IWGRP | S_IRGRP)) /* group */ ||
|
|
((buf.st_mode & 00006) == (S_IWOTH | S_IROTH)) /* others */ )
|
|
{
|
|
// The user has read and write access.
|
|
|
|
TQFile file ( canonical_path );
|
|
TQStringList contents;
|
|
|
|
if ( file.open( IO_ReadWrite ) )
|
|
{
|
|
TQTextStream ts( &file );
|
|
ts.setEncoding( TQTextStream::Locale );
|
|
|
|
contents = TQStringList::split( "\n", ts.read(), true );
|
|
|
|
bool write = false;
|
|
|
|
switch ( m_operation )
|
|
{
|
|
case Insert:
|
|
{
|
|
size_t hostnamelen = 255;
|
|
char *hn = new char[hostnamelen];
|
|
|
|
if ( gethostname( hn, hostnamelen ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
Smb4KError::error( ERROR_GETTING_HOSTNAME, TQString(), strerror( error_number ) );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
TQString hostname( hn );
|
|
|
|
delete [] hn;
|
|
|
|
if ( contents.grep( "# Entries for Smb4K users." ).count() == 0 )
|
|
{
|
|
contents.append( "# Entries for Smb4K users." );
|
|
contents.append( "# Generated by Smb4K. Please do not modify!" );
|
|
contents.append( "User_Alias\tSMB4KUSERS = "+TQString( "%1" ).arg( getpwuid( getuid() )->pw_name ) );
|
|
contents.append( "Defaults:SMB4KUSERS\tenv_keep += \"PASSWD USER\"" );
|
|
contents.append( "SMB4KUSERS\t"+hostname+" = NOPASSWD: "+Smb4KSettings::smb4k_kill() );
|
|
contents.append( "SMB4KUSERS\t"+hostname+" = NOPASSWD: "+Smb4KSettings::smb4k_umount() );
|
|
contents.append( "SMB4KUSERS\t"+hostname+" = NOPASSWD: "+Smb4KSettings::smb4k_mount() );
|
|
contents.append( "# End of Smb4K user entries." );
|
|
|
|
write = true;
|
|
}
|
|
else
|
|
{
|
|
// Find the beginning and the end of the entries in
|
|
// the sudoers file:
|
|
TQStringList::Iterator begin = contents.find( "# Entries for Smb4K users." );
|
|
TQStringList::Iterator end = contents.find( "# End of Smb4K user entries." );
|
|
|
|
for ( TQStringList::Iterator it = begin; it != end; ++it )
|
|
{
|
|
if ( (*it).startsWith( "User_Alias\tSMB4KUSERS" ) && (*it).contains( getpwuid( getuid() )->pw_name, true ) == 0 )
|
|
{
|
|
(*it).append( ","+TQString( getpwuid( getuid() )->pw_name ) );
|
|
|
|
write = true;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case Remove:
|
|
{
|
|
// Find the beginning and the end of the entries in
|
|
// the sudoers file:
|
|
TQStringList::Iterator begin = contents.find( "# Entries for Smb4K users." );
|
|
TQStringList::Iterator end = contents.find( "# End of Smb4K user entries." );
|
|
|
|
// Now, check if the user is in the list of users. If he is,
|
|
// remove him from there or remove all if he is the only one:
|
|
for ( TQStringList::Iterator it = begin; it != end; ++it )
|
|
{
|
|
if ( (*it).startsWith( "User_Alias\tSMB4KUSERS" ) )
|
|
{
|
|
TQString users = (*it).section( "=", 1, 1 ).stripWhiteSpace();
|
|
|
|
if ( users.contains( "," ) == 0 )
|
|
{
|
|
// In this case, there is only one user in the list. Check if
|
|
// it is the user who requested the removal:
|
|
if ( TQString::compare( users, getpwuid( getuid() )->pw_name ) == 0 )
|
|
{
|
|
// They are equal. Remove everything:
|
|
contents.erase( begin, end );
|
|
contents.remove( end );
|
|
|
|
write = true;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// They are not equal: Do nothing.
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// In this case there is more than one user in the list.
|
|
// Remove the user who requested the removal:
|
|
TQStringList list = TQStringList::split( ",", users, false );
|
|
list.remove( getpwuid( getuid() )->pw_name );
|
|
|
|
(*it).replace( users, list.join( "," ) );
|
|
|
|
write = true;
|
|
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
file.close();
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok; // false
|
|
}
|
|
};
|
|
|
|
if ( write )
|
|
{
|
|
// Prepare the contents: remove empty lines from the end.
|
|
TQStringList::Iterator it = contents.end();
|
|
|
|
// Move the iterator to the last entry in the list:
|
|
--it;
|
|
|
|
while ( (*it).stripWhiteSpace().isEmpty() )
|
|
{
|
|
it = contents.remove( it );
|
|
--it;
|
|
}
|
|
|
|
// Now write the contents to the file. The permissions
|
|
// will be preserved by this action.
|
|
ts << contents.join( "\n" ) << endl;
|
|
|
|
file.close();
|
|
}
|
|
else
|
|
{
|
|
// The entries are already in the file.
|
|
}
|
|
|
|
ok = true;
|
|
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok;
|
|
}
|
|
else
|
|
{
|
|
Smb4KError::error( ERROR_OPENING_FILE, canonical_path, file.errorString() );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok; // false
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The user does not have enough access rights to perform
|
|
// the modification of the sudoers file. So, we need to use
|
|
// kdesu to get the contents of the file.
|
|
|
|
// Compose the command:
|
|
TQString command;
|
|
command.append( "kdesu -t -c \"smb4k_cat " );
|
|
command.append( canonical_path+"\"" );
|
|
command.append( " ; sleep 2" );
|
|
|
|
m_state = ReadSudoers;
|
|
|
|
ok = true;
|
|
|
|
*m_proc << command;
|
|
m_proc->start( KProcess::NotifyOnExit, KProcess::AllOutput );
|
|
|
|
// The process is not finished, so finished() will be emitted
|
|
// later and the lock file will also be removed at the end.
|
|
|
|
return ok;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Smb4KError::error( ERROR_FILE_NOT_FOUND, canonical_path );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok; // false
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The error message has already been shown by
|
|
// Smb4KFileIO::createLockFile()
|
|
emit failed();
|
|
emit finished();
|
|
|
|
// We need not remove the lock file here.
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
|
|
bool Smb4KFileIO::writeSuperTab( Smb4KFileIO::Operation operation )
|
|
{
|
|
m_operation = operation;
|
|
bool ok = false;
|
|
|
|
// Stop here if nothing has changed:
|
|
if ( m_operation == NoOperation )
|
|
{
|
|
emit finished();
|
|
|
|
ok = true;
|
|
|
|
return ok;
|
|
}
|
|
|
|
TQString file = "super.tab";
|
|
|
|
if ( createLockFile( file ) )
|
|
{
|
|
// Find the file first:
|
|
TQCString canonical_path = findFile( file );
|
|
|
|
if ( !canonical_path.isEmpty() )
|
|
{
|
|
// Stat the file, so that we know that it is safe to
|
|
// read from and write to it and whether we need to
|
|
// ask for the super user's password:
|
|
struct stat buf;
|
|
|
|
if ( lstat( canonical_path, &buf ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
Smb4KError::error( ERROR_GETTING_PERMISSIONS, canonical_path, strerror( error_number ) );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
// Look for the groups the user is in:
|
|
long ngroups_max;
|
|
ngroups_max = sysconf(_SC_NGROUPS_MAX);
|
|
|
|
gid_t list[ngroups_max];
|
|
|
|
if ( getgroups( ngroups_max, list ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
Smb4KError::error( ERROR_GETTING_GIDS, TQString(), strerror( error_number ) );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
gid_t sup_gid = 65534; // set this to gid 'nobody' for initialization
|
|
bool found_gid = false;
|
|
int i = 0;
|
|
|
|
while ( list[i] )
|
|
{
|
|
if ( list[i] == buf.st_gid )
|
|
{
|
|
sup_gid = list[i];
|
|
found_gid = true;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
// Error out if the file is irregular.
|
|
// Yes, yes, I know that this is normally done in a different
|
|
// way and that there might be a race here, but, hey, right here
|
|
// I don't care!
|
|
if ( !S_ISREG( buf.st_mode ) || S_ISFIFO( buf.st_mode ) || S_ISLNK( buf.st_mode ) )
|
|
{
|
|
Smb4KError::error( ERROR_FILE_IS_IRREGULAR, canonical_path, TQString() );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
// Check access rights:
|
|
if ( (buf.st_uid == getuid() && (buf.st_mode & 00600) == (S_IWUSR | S_IRUSR)) /* user */ ||
|
|
(found_gid && buf.st_gid == sup_gid && (buf.st_mode & 00060) == (S_IWGRP | S_IRGRP)) /* group */ ||
|
|
((buf.st_mode & 00006) == (S_IWOTH | S_IROTH)) /* others */ )
|
|
{
|
|
// The user has read and write access.
|
|
|
|
TQFile file ( canonical_path );
|
|
TQStringList contents;
|
|
|
|
if ( file.open( IO_ReadWrite ) )
|
|
{
|
|
TQTextStream ts( &file );
|
|
ts.setEncoding( TQTextStream::Locale );
|
|
|
|
contents = TQStringList::split( "\n", ts.read(), true );
|
|
|
|
bool write = false;
|
|
|
|
switch ( m_operation )
|
|
{
|
|
case Insert:
|
|
{
|
|
size_t hostnamelen = 255;
|
|
char *hn = new char[hostnamelen];
|
|
|
|
if ( gethostname( hn, hostnamelen ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
Smb4KError::error( ERROR_GETTING_HOSTNAME, TQString(), strerror( error_number ) );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
TQString hostname( hn );
|
|
|
|
delete [] hn;
|
|
|
|
if ( contents.grep( "# Entries for Smb4K users." ).count() == 0 )
|
|
{
|
|
contents.append( "# Entries for Smb4K users." );
|
|
contents.append( "# Generated by Smb4K. Please do not modify!" );
|
|
contents.append( ":define Smb4KUsers "+TQString( "%1" ).arg( getpwuid( getuid() )->pw_name ) );
|
|
#ifndef __FreeBSD__
|
|
contents.append( "smb4k_kill\t"+Smb4KSettings::smb4k_kill()+
|
|
"\t$(Smb4KUsers)\tuid=root\tgid=root" );
|
|
contents.append( "smb4k_umount\t"+Smb4KSettings::smb4k_umount()+
|
|
"\t$(Smb4KUsers)\tuid=root\tgid=root" );
|
|
contents.append( "smb4k_mount\t"+Smb4KSettings::smb4k_mount()+
|
|
"\t$(Smb4KUsers)\tuid=root\tgid=root\tenv=PASSWD,USER" );
|
|
#else
|
|
contents.append( "smb4k_kill\t"+Smb4KSettings::smb4k_kill()+
|
|
"\t$(Smb4KUsers)\tuid=root\tgid=wheel" );
|
|
contents.append( "smb4k_umount\t"+Smb4KSettings::smb4k_umount()+
|
|
"\t$(Smb4KUsers)\tuid=root\tgid=wheel" );
|
|
contents.append( "smb4k_mount\t"+Smb4KSettings::smb4k_mount()+
|
|
"\t$(Smb4KUsers)\tuid=root\tgid=wheel\tsetenv=HOME=$CALLER_HOME\tenv=PASSWD,USER" );
|
|
#endif
|
|
contents.append( "# End of Smb4K user entries." );
|
|
|
|
write = true;
|
|
}
|
|
else
|
|
{
|
|
// Find the beginning and the end of the entries in
|
|
// the super.tab file:
|
|
TQStringList::Iterator begin = contents.find( "# Entries for Smb4K users." );
|
|
TQStringList::Iterator end = contents.find( "# End of Smb4K user entries." );
|
|
|
|
for ( TQStringList::Iterator it = begin; it != end; ++it )
|
|
{
|
|
if ( (*it).startsWith( ":define Smb4KUsers" ) && (*it).contains( getpwuid( getuid() )->pw_name, true ) == 0 )
|
|
{
|
|
(*it).append( ","+TQString( getpwuid( getuid() )->pw_name ) );
|
|
|
|
write = true;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case Remove:
|
|
{
|
|
// Find the beginning and the end of the entries in
|
|
// the super.tab file:
|
|
TQStringList::Iterator begin = contents.find( "# Entries for Smb4K users." );
|
|
TQStringList::Iterator end = contents.find( "# End of Smb4K user entries." );
|
|
|
|
// Now, check if the user is in the list of users. If he is,
|
|
// remove him from there or remove all if he is the only one:
|
|
for ( TQStringList::Iterator it = begin; it != end; ++it )
|
|
{
|
|
if ( (*it).startsWith( ":define Smb4KUsers" ) )
|
|
{
|
|
TQString users = (*it).section( "Smb4KUsers", 1, 1 ).stripWhiteSpace();
|
|
|
|
if ( users.contains( "," ) == 0 )
|
|
{
|
|
// In this case, there is only one user in the list. Check if
|
|
// it is the user who requested the removal:
|
|
if ( TQString::compare( users, getpwuid( getuid() )->pw_name ) == 0 )
|
|
{
|
|
// They are equal. Remove everything:
|
|
contents.erase( begin, end );
|
|
contents.remove( end );
|
|
|
|
write = true;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// They are not equal: Do nothing.
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// In this case there is more than one user in the list.
|
|
// Remove the user who requested the removal:
|
|
TQStringList list = TQStringList::split( ",", users, false );
|
|
list.remove( getpwuid( getuid() )->pw_name );
|
|
|
|
(*it).replace( users, list.join( "," ) );
|
|
|
|
write = true;
|
|
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
file.close();
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok; // false
|
|
}
|
|
};
|
|
|
|
if ( write )
|
|
{
|
|
// Prepare the contents: remove empty lines from the end.
|
|
TQStringList::Iterator it = contents.end();
|
|
|
|
// Move the iterator to the last entry in the list:
|
|
--it;
|
|
|
|
while ( (*it).stripWhiteSpace().isEmpty() )
|
|
{
|
|
it = contents.remove( it );
|
|
--it;
|
|
}
|
|
|
|
// Now write the contents to the file. The permissions
|
|
// will be preserved by this action.
|
|
ts << contents.join( "\n" ) << endl;
|
|
|
|
file.close();
|
|
}
|
|
else
|
|
{
|
|
// The entries are already in the file.
|
|
}
|
|
|
|
ok = true;
|
|
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok;
|
|
}
|
|
else
|
|
{
|
|
Smb4KError::error( ERROR_OPENING_FILE, canonical_path, file.errorString() );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok; // false
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The user does not have enough access rights to perform
|
|
// the modification of the sudoers file. So, we need to use
|
|
// kdesu to get the contents of the file.
|
|
|
|
// Compose the command:
|
|
TQString command;
|
|
command.append( "kdesu -t -c \"smb4k_cat " );
|
|
command.append( canonical_path+"\"" );
|
|
command.append( " ; sleep 2" );
|
|
|
|
m_state = ReadSuperTab;
|
|
|
|
ok = true;
|
|
|
|
*m_proc << command;
|
|
m_proc->start( KProcess::NotifyOnExit, KProcess::AllOutput );
|
|
|
|
// The process is not finished, so finished() will be emitted
|
|
// later and the lock file will also be removed at the end.
|
|
|
|
return ok;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Smb4KError::error( ERROR_FILE_NOT_FOUND, canonical_path );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return ok; // false
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// The error message has already been shown by
|
|
// Smb4KFileIO::createLockFile()
|
|
emit failed();
|
|
emit finished();
|
|
|
|
// We need not remove the lock file here.
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
|
|
bool Smb4KFileIO::createLockFile( const TQString &filename )
|
|
{
|
|
bool ok = false;
|
|
|
|
// Determine the directory where to write the lock file. First, try
|
|
// /var/lock and than /var/tmp. If that does not work either, fall
|
|
// back to /tmp.
|
|
if ( m_lock_file.isEmpty() )
|
|
{
|
|
TQValueList<TQCString> dirs;
|
|
dirs << "/var/lock" << "/var/tmp" << "/tmp";
|
|
|
|
struct stat buf;
|
|
|
|
for ( TQValueList<TQCString>::ConstIterator it = dirs.begin(); it != dirs.end(); ++it )
|
|
{
|
|
// First check if the directory is available and writable
|
|
if ( lstat( *it, &buf ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
if ( error_number != EACCES && error_number != ENOENT )
|
|
{
|
|
Smb4KError::error( ERROR_GETTING_PERMISSIONS, *it, strerror( error_number ) );
|
|
|
|
return ok; // false
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Look for the groups the user is in:
|
|
long ngroups_max;
|
|
ngroups_max = sysconf(_SC_NGROUPS_MAX);
|
|
|
|
gid_t list[ngroups_max];
|
|
|
|
if ( getgroups( ngroups_max, list ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
Smb4KError::error( ERROR_GETTING_GIDS, TQString(), strerror( error_number ) );
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
gid_t sup_gid = 65534; // set this to gid 'nobody' for initialization
|
|
bool found_gid = false;
|
|
int i = 0;
|
|
|
|
while ( list[i] )
|
|
{
|
|
if ( list[i] == buf.st_gid )
|
|
{
|
|
sup_gid = list[i];
|
|
found_gid = true;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
// Check whether we are stat'ing a directory and that the
|
|
// user has read/write permissions.
|
|
if ( S_ISDIR( buf.st_mode ) /* is directory */ &&
|
|
(buf.st_uid == getuid() && (buf.st_mode & 00600) == (S_IWUSR | S_IRUSR)) /* user */ ||
|
|
(found_gid && buf.st_gid == sup_gid && (buf.st_mode & 00060) == (S_IWGRP | S_IRGRP)) /* group */ ||
|
|
((buf.st_mode & 00006) == (S_IWOTH | S_IROTH)) /* others */ )
|
|
{
|
|
m_lock_file = *it+"/smb4k.lock";
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int file_descriptor;
|
|
|
|
// Create the lock file if necessary and open it:
|
|
if ( (file_descriptor = open( m_lock_file, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH )) == -1 )
|
|
{
|
|
// Error out if the opening failed:
|
|
int error_number = errno;
|
|
|
|
Smb4KError::error( ERROR_OPENING_FILE, m_lock_file, strerror( error_number ) );
|
|
|
|
return ok; // false
|
|
}
|
|
else
|
|
{
|
|
// Check what we actually opened:
|
|
|
|
struct stat file_stat;
|
|
|
|
if ( fstat( file_descriptor, &file_stat ) == -1 )
|
|
{
|
|
// Error out if we could not get the information about the file:
|
|
int error_number = errno;
|
|
|
|
// FIXME for >= 0.8.x: Change error code to ERROR_GETTING_STAT
|
|
Smb4KError::error( ERROR_GETTING_PERMISSIONS, TQString(), strerror( error_number ) );
|
|
|
|
return ok;
|
|
}
|
|
|
|
if ( !S_ISREG( file_stat.st_mode ) || S_ISFIFO( file_stat.st_mode ) || S_ISLNK( file_stat.st_mode ) )
|
|
{
|
|
// Close the file and error out, if we have opened an
|
|
// "irregular" file (i.e. a symlink, a fifo, etc.).
|
|
|
|
Smb4KError::error( ERROR_FILE_IS_IRREGULAR, m_lock_file );
|
|
|
|
if ( close( file_descriptor ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
Smb4KError::error( ERROR_CLOSING_FILE, m_lock_file, strerror( error_number ) );
|
|
}
|
|
|
|
return ok; // false
|
|
}
|
|
else
|
|
{
|
|
// Continue if the file is regular.
|
|
|
|
char buffer[1000];
|
|
ssize_t size;
|
|
|
|
if ( (size = read( file_descriptor, buffer, 1000 )) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
Smb4KError::error( ERROR_READING_FILE, m_lock_file, strerror( error_number ) );
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
if ( size >= 1000 )
|
|
{
|
|
// FIXME for >= 0.8.x: Change error code to ERROR_BUFFER_EXCEEDED
|
|
Smb4KError::error( ERROR_UNKNOWN, TQString(), i18n( "Buffer size exceeded" ) );
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
TQStringList contents = TQStringList::split( '\n', TQString::fromLocal8Bit( buffer, size ), false );
|
|
TQString test_string = ":"+filename;
|
|
TQString entry = contents.grep( test_string, true ).join( "\n" ).stripWhiteSpace();
|
|
|
|
if ( !entry.isEmpty() )
|
|
{
|
|
Smb4KError::error( ERROR_LOCKED, entry );
|
|
|
|
return ok; // false
|
|
}
|
|
else
|
|
{
|
|
contents << TQString( "%1:%2" ).arg( getpwuid( getuid() )->pw_name ).arg( filename );
|
|
TQCString out = contents.join( "\n" ).local8Bit();
|
|
|
|
if ( write( file_descriptor, out, out.length() ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
Smb4KError::error( ERROR_WRITING_FILE, m_lock_file, strerror( error_number ) );
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
if ( close( file_descriptor ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
Smb4KError::error( ERROR_CLOSING_FILE, m_lock_file, strerror( error_number ) );
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
ok = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
|
|
bool Smb4KFileIO::removeLockFile( const bool error_message )
|
|
{
|
|
// We already have the name and location of the lock
|
|
// file, so we do not need to define it here.
|
|
|
|
int file_descriptor;
|
|
bool ok = false;
|
|
|
|
// Open the lock file:
|
|
if ( (file_descriptor = open( m_lock_file, O_RDWR )) == -1 )
|
|
{
|
|
// Error out if the opening failed:
|
|
int error_number = errno;
|
|
|
|
if ( error_message && error_number != ENOENT )
|
|
{
|
|
Smb4KError::error( ERROR_OPENING_FILE, m_lock_file, strerror( error_number ) );
|
|
}
|
|
|
|
return ok; // false
|
|
}
|
|
else
|
|
{
|
|
// Check what we actually opened:
|
|
|
|
struct stat file_stat;
|
|
|
|
if ( fstat( file_descriptor, &file_stat ) == -1 )
|
|
{
|
|
// Error out if we could not get the information about the file:
|
|
int error_number = errno;
|
|
|
|
if ( error_message )
|
|
{
|
|
// FIXME for >= 0.8.x: Change error code to ERROR_GETTING_STAT
|
|
Smb4KError::error( ERROR_GETTING_PERMISSIONS, TQString(), strerror( error_number ) );
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
if ( !S_ISREG( file_stat.st_mode ) || S_ISFIFO( file_stat.st_mode ) || S_ISLNK( file_stat.st_mode ) )
|
|
{
|
|
// Close the file and error out, if we have opened an
|
|
// "irregular" file (i.e. a symlink, a fifo, etc.).
|
|
|
|
if ( error_message )
|
|
{
|
|
Smb4KError::error( ERROR_FILE_IS_IRREGULAR, m_lock_file );
|
|
}
|
|
|
|
if ( close( file_descriptor ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
if ( error_message )
|
|
{
|
|
Smb4KError::error( ERROR_CLOSING_FILE, m_lock_file, strerror( error_number ) );
|
|
}
|
|
}
|
|
|
|
return ok; // false
|
|
}
|
|
else
|
|
{
|
|
// Continue if the file is regular.
|
|
|
|
char buffer[1000];
|
|
ssize_t size;
|
|
|
|
if ( (size = read( file_descriptor, buffer, 1000 )) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
if ( error_message )
|
|
{
|
|
Smb4KError::error( ERROR_READING_FILE, m_lock_file, strerror( error_number ) );
|
|
}
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
if ( size >= 1000 )
|
|
{
|
|
if ( error_message )
|
|
{
|
|
// FIXME for >= 0.8.x: Change error code to ERROR_BUFFER_EXCEEDED
|
|
Smb4KError::error( ERROR_UNKNOWN, TQString(), i18n( "Buffer size exceeded" ) );
|
|
}
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
TQStringList contents = TQStringList::split( '\n', TQString::fromLocal8Bit( buffer, size ), false );
|
|
|
|
// Prepare the contents of the file and write it to the disk.
|
|
// It it should be empty, remove the lock file.
|
|
for ( TQStringList::Iterator it = contents.begin(); it != contents.end(); it++ )
|
|
{
|
|
if ( (*it).startsWith( TQString( getpwuid( getuid() )->pw_name )+":" ) )
|
|
{
|
|
*it = TQString();
|
|
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
contents.remove( TQString() );
|
|
|
|
if ( !contents.isEmpty() )
|
|
{
|
|
// Write the remaining contents to the lock file:
|
|
|
|
TQCString out = contents.join( "\n" ).local8Bit();
|
|
|
|
if ( write( file_descriptor, out, out.length() ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
if ( error_message )
|
|
{
|
|
Smb4KError::error( ERROR_WRITING_FILE, m_lock_file, strerror( error_number ) );
|
|
}
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
if ( close( file_descriptor ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
if ( error_message )
|
|
{
|
|
Smb4KError::error( ERROR_CLOSING_FILE, m_lock_file, strerror( error_number ) );
|
|
}
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
ok = true;
|
|
}
|
|
else
|
|
{
|
|
// Close and remove the lock file:
|
|
|
|
if ( close( file_descriptor ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
if ( error_message )
|
|
{
|
|
Smb4KError::error( ERROR_CLOSING_FILE, m_lock_file, strerror( error_number ) );
|
|
}
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
if ( unlink( m_lock_file ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
if ( error_message )
|
|
{
|
|
// FIXME for > 0.8.x: Replace error code with ERROR_REMOVING_FILE
|
|
Smb4KError::error( ERROR_UNKNOWN, m_lock_file, strerror( error_number ) );
|
|
}
|
|
|
|
return ok; // false
|
|
}
|
|
|
|
ok = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
|
|
const TQCString Smb4KFileIO::findFile( const TQString &filename )
|
|
{
|
|
TQStringList paths;
|
|
paths << "/etc";
|
|
paths << "/etc/samba";
|
|
paths << "/usr/local/etc";
|
|
paths << "/usr/local/etc/samba";
|
|
|
|
TQString canonical_path = TQString();
|
|
|
|
for ( TQStringList::ConstIterator it = paths.begin(); it != paths.end(); it++ )
|
|
{
|
|
TQDir::setCurrent( *it );
|
|
|
|
if ( TQFile::exists( filename ) )
|
|
{
|
|
canonical_path = TQDir::current().canonicalPath()+"/"+filename;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return canonical_path.local8Bit();
|
|
}
|
|
|
|
|
|
void Smb4KFileIO::processSudoers()
|
|
{
|
|
// If the output buffer is empty, we stop, because
|
|
// that most likely means, the user cancelled the
|
|
// kdesu dialog.
|
|
if ( m_buffer.stripWhiteSpace().isEmpty() )
|
|
{
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return;
|
|
}
|
|
|
|
TQStringList contents = TQStringList::split( "\n", m_buffer, true );
|
|
bool write = false;
|
|
|
|
switch ( m_operation )
|
|
{
|
|
case Insert:
|
|
{
|
|
size_t hostnamelen = 255;
|
|
char *hn = new char[hostnamelen];
|
|
|
|
if ( gethostname( hn, hostnamelen ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
Smb4KError::error( ERROR_GETTING_HOSTNAME, TQString(), strerror( error_number ) );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
}
|
|
|
|
TQString hostname( hn );
|
|
|
|
delete [] hn;
|
|
|
|
if ( contents.grep( "# Entries for Smb4K users." ).count() == 0 )
|
|
{
|
|
contents.append( "# Entries for Smb4K users." );
|
|
contents.append( "# Generated by Smb4K. Please do not modify!" );
|
|
contents.append( "User_Alias\tSMB4KUSERS = "+TQString( "%1" ).arg( getpwuid( getuid() )->pw_name ) );
|
|
contents.append( "Defaults:SMB4KUSERS\tenv_keep += \"PASSWD USER\"" );
|
|
contents.append( "SMB4KUSERS\t"+hostname+" = NOPASSWD: "+Smb4KSettings::smb4k_kill() );
|
|
contents.append( "SMB4KUSERS\t"+hostname+" = NOPASSWD: "+Smb4KSettings::smb4k_umount() );
|
|
contents.append( "SMB4KUSERS\t"+hostname+" = NOPASSWD: "+Smb4KSettings::smb4k_mount() );
|
|
contents.append( "# End of Smb4K user entries." );
|
|
|
|
write = true;
|
|
}
|
|
else
|
|
{
|
|
// Find the beginning and the end of the entries in
|
|
// the sudoers file:
|
|
TQStringList::Iterator begin = contents.find( "# Entries for Smb4K users." );
|
|
TQStringList::Iterator end = contents.find( "# End of Smb4K user entries." );
|
|
|
|
for ( TQStringList::Iterator it = begin; it != end; ++it )
|
|
{
|
|
if ( (*it).startsWith( "User_Alias\tSMB4KUSERS" ) && (*it).contains( getpwuid( getuid() )->pw_name, true ) == 0 )
|
|
{
|
|
(*it).append( ","+TQString( getpwuid( getuid() )->pw_name ) );
|
|
|
|
write = true;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case Remove:
|
|
{
|
|
// Find the beginning and the end of the entries in
|
|
// the sudoers file:
|
|
TQStringList::Iterator begin = contents.find( "# Entries for Smb4K users." );
|
|
TQStringList::Iterator end = contents.find( "# End of Smb4K user entries." );
|
|
|
|
// Now, check if the user is in the list of users. If he is,
|
|
// remove him from there or remove all if he is the only one:
|
|
for ( TQStringList::Iterator it = begin; it != end; ++it )
|
|
{
|
|
if ( (*it).startsWith( "User_Alias\tSMB4KUSERS" ) )
|
|
{
|
|
TQString users = (*it).section( "=", 1, 1 ).stripWhiteSpace();
|
|
|
|
if ( users.contains( "," ) == 0 )
|
|
{
|
|
// In this case, there is only one user in the list. Check if
|
|
// it is the user who requested the removal:
|
|
if ( TQString::compare( users, getpwuid( getuid() )->pw_name ) == 0 )
|
|
{
|
|
// They are equal. Remove everything:
|
|
contents.erase( begin, end );
|
|
contents.remove( end );
|
|
|
|
write = true;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// They are not equal: Do nothing.
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// In this case there is more than one user in the list.
|
|
// Remove the user who requested the removal:
|
|
TQStringList list = TQStringList::split( ",", users, false );
|
|
list.remove( getpwuid( getuid() )->pw_name );
|
|
|
|
(*it).replace( users, list.join( "," ) );
|
|
|
|
write = true;
|
|
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( write )
|
|
{
|
|
// Prepare the contents: remove empty lines from the end.
|
|
TQStringList::Iterator it = contents.end();
|
|
|
|
// Move the iterator to the last entry in the list:
|
|
--it;
|
|
|
|
while ( (*it).stripWhiteSpace().isEmpty() )
|
|
{
|
|
it = contents.remove( it );
|
|
--it;
|
|
}
|
|
|
|
// Create a temporary file and write the data to it:
|
|
TQCString template_string = tempDir().local8Bit()+"/XXXXXX";
|
|
char tmp[template_string.length()+1];
|
|
(void) qstrncpy( tmp, template_string, template_string.length()+1 );
|
|
|
|
TQFile temp_file;
|
|
int file_descriptor;
|
|
|
|
if ( (file_descriptor = mkstemp( tmp )) == -1 )
|
|
{
|
|
int err = errno;
|
|
|
|
Smb4KError::error( ERROR_CREATING_TEMP_FILE, tmp, strerror( err ) );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return;
|
|
}
|
|
|
|
if ( temp_file.open( IO_WriteOnly, file_descriptor ) )
|
|
{
|
|
TQTextStream ts( &temp_file );
|
|
ts.setEncoding( TQTextStream::Locale );
|
|
|
|
ts << contents.join( "\n" ) << endl;
|
|
|
|
temp_file.close();
|
|
}
|
|
else
|
|
{
|
|
Smb4KError::error( ERROR_WRITING_FILE, temp_file.name() );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return;
|
|
}
|
|
|
|
// Now move the file to the right location. Preserve the permissions
|
|
// and the owner:
|
|
TQString canonical_path = findFile( "sudoers" );
|
|
struct stat file_stat;
|
|
|
|
if ( stat( canonical_path.local8Bit(), &file_stat ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
Smb4KError::error( ERROR_GETTING_PERMISSIONS, TQString(), strerror( error_number ) );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return;
|
|
}
|
|
|
|
TQString perms = TQString( "%1" ).arg( (int)file_stat.st_mode, 0, 8 );
|
|
perms = perms.right( 4 );
|
|
TQString owner = TQString( "%1" ).arg( (int)file_stat.st_uid );
|
|
TQString group = TQString( "%1" ).arg( (int)file_stat.st_gid );
|
|
TQString temp_file_name = TQString( tmp );
|
|
|
|
// Assemble the command.
|
|
TQString command;
|
|
command.append( "kdesu -n -c \"smb4k_mv "+owner+":"+group+" "+perms+" " );
|
|
command.append( temp_file_name+" " );
|
|
command.append( canonical_path+"\" ; " );
|
|
command.append( "rm -f "+temp_file_name );
|
|
|
|
m_state = WriteSudoers;
|
|
|
|
*m_proc << command;
|
|
|
|
m_proc->start( KProcess::NotifyOnExit, KProcess::AllOutput );
|
|
}
|
|
else
|
|
{
|
|
// Everything OK.
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
}
|
|
}
|
|
|
|
|
|
void Smb4KFileIO::processSuperTab()
|
|
{
|
|
// If the output buffer is empty, we stop, because
|
|
// that most likely means, the user cancelled the
|
|
// kdesu dialog.
|
|
if ( m_buffer.stripWhiteSpace().isEmpty() )
|
|
{
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return;
|
|
}
|
|
|
|
TQStringList contents = TQStringList::split( "\n", m_buffer, true );
|
|
bool write = false;
|
|
|
|
switch ( m_operation )
|
|
{
|
|
case Insert:
|
|
{
|
|
size_t hostnamelen = 255;
|
|
char *hn = new char[hostnamelen];
|
|
|
|
if ( gethostname( hn, hostnamelen ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
Smb4KError::error( ERROR_GETTING_HOSTNAME, TQString(), strerror( error_number ) );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
}
|
|
|
|
TQString hostname( hn );
|
|
|
|
delete [] hn;
|
|
|
|
if ( contents.grep( "# Entries for Smb4K users." ).count() == 0 )
|
|
{
|
|
contents.append( "# Entries for Smb4K users." );
|
|
contents.append( "# Generated by Smb4K. Please do not modify!" );
|
|
contents.append( ":define Smb4KUsers "+TQString( "%1" ).arg( getpwuid( getuid() )->pw_name ) );
|
|
#ifndef __FreeBSD__
|
|
contents.append( "smb4k_kill\t"+Smb4KSettings::smb4k_kill()+
|
|
"\t$(Smb4KUsers)\tuid=root\tgid=root" );
|
|
contents.append( "smb4k_umount\t"+Smb4KSettings::smb4k_umount()+
|
|
"\t$(Smb4KUsers)\tuid=root\tgid=root" );
|
|
contents.append( "smb4k_mount\t"+Smb4KSettings::smb4k_mount()+
|
|
"\t$(Smb4KUsers)\tuid=root\tgid=root\tenv=PASSWD,USER" );
|
|
#else
|
|
contents.append( "smb4k_kill\t"+Smb4KSettings::smb4k_kill()+
|
|
"\t$(Smb4KUsers)\tuid=root\tgid=wheel" );
|
|
contents.append( "smb4k_umount\t"+Smb4KSettings::smb4k_umount()+
|
|
"\t$(Smb4KUsers)\tuid=root\tgid=wheel" );
|
|
contents.append( "smb4k_mount\t"+Smb4KSettings::smb4k_mount()+
|
|
"\t$(Smb4KUsers)\tuid=root\tgid=wheel\tsetenv=HOME=$CALLER_HOME\tenv=PASSWD,USER" );
|
|
#endif
|
|
contents.append( "# End of Smb4K user entries." );
|
|
|
|
write = true;
|
|
}
|
|
else
|
|
{
|
|
// Find the beginning and the end of the entries in
|
|
// the super.tab file:
|
|
TQStringList::Iterator begin = contents.find( "# Entries for Smb4K users." );
|
|
TQStringList::Iterator end = contents.find( "# End of Smb4K user entries." );
|
|
|
|
for ( TQStringList::Iterator it = begin; it != end; ++it )
|
|
{
|
|
if ( (*it).startsWith( ":define Smb4KUsers" ) && (*it).contains( getpwuid( getuid() )->pw_name, true ) == 0 )
|
|
{
|
|
(*it).append( ","+TQString( getpwuid( getuid() )->pw_name ) );
|
|
|
|
write = true;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case Remove:
|
|
{
|
|
// Find the beginning and the end of the entries in
|
|
// the super.tab file:
|
|
TQStringList::Iterator begin = contents.find( "# Entries for Smb4K users." );
|
|
TQStringList::Iterator end = contents.find( "# End of Smb4K user entries." );
|
|
|
|
// Now, check if the user is in the list of users. If he is,
|
|
// remove him from there or remove all if he is the only one:
|
|
for ( TQStringList::Iterator it = begin; it != end; ++it )
|
|
{
|
|
if ( (*it).startsWith( ":define Smb4KUsers" ) )
|
|
{
|
|
TQString users = (*it).section( "Smb4KUsers", 1, 1 ).stripWhiteSpace();
|
|
|
|
if ( users.contains( "," ) == 0 )
|
|
{
|
|
// In this case, there is only one user in the list. Check if
|
|
// it is the user who requested the removal:
|
|
if ( TQString::compare( users, getpwuid( getuid() )->pw_name ) == 0 )
|
|
{
|
|
// They are equal. Remove everything:
|
|
contents.erase( begin, end );
|
|
contents.remove( end );
|
|
|
|
write = true;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// They are not equal: Do nothing.
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// In this case there is more than one user in the list.
|
|
// Remove the user who requested the removal:
|
|
TQStringList list = TQStringList::split( ",", users, false );
|
|
list.remove( getpwuid( getuid() )->pw_name );
|
|
|
|
(*it).replace( users, list.join( "," ) );
|
|
|
|
write = true;
|
|
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
if ( write )
|
|
{
|
|
// Prepare the contents: remove empty lines from the end.
|
|
TQStringList::Iterator it = contents.end();
|
|
|
|
// Move the iterator to the last entry in the list:
|
|
--it;
|
|
|
|
while ( (*it).stripWhiteSpace().isEmpty() )
|
|
{
|
|
it = contents.remove( it );
|
|
--it;
|
|
}
|
|
|
|
// Create a temporary file and write the data to it:
|
|
TQCString template_string = tempDir().local8Bit()+"/XXXXXX";
|
|
char tmp[template_string.length()+1];
|
|
(void) qstrncpy( tmp, template_string, template_string.length()+1 );
|
|
|
|
TQFile temp_file;
|
|
int file_descriptor;
|
|
|
|
if ( (file_descriptor = mkstemp( tmp )) == -1 )
|
|
{
|
|
int err = errno;
|
|
|
|
Smb4KError::error( ERROR_CREATING_TEMP_FILE, tmp, strerror( err ) );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return;
|
|
}
|
|
|
|
if ( temp_file.open( IO_WriteOnly, file_descriptor ) )
|
|
{
|
|
TQTextStream ts( &temp_file );
|
|
ts.setEncoding( TQTextStream::Locale );
|
|
|
|
ts << contents.join( "\n" ) << endl;
|
|
|
|
temp_file.close();
|
|
}
|
|
else
|
|
{
|
|
Smb4KError::error( ERROR_WRITING_FILE, temp_file.name() );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return;
|
|
}
|
|
|
|
// Now move the file to the right location. Preserve the permissions
|
|
// and the owner:
|
|
TQString canonical_path = findFile( "super.tab" );
|
|
struct stat file_stat;
|
|
|
|
if ( stat( canonical_path.local8Bit(), &file_stat ) == -1 )
|
|
{
|
|
int error_number = errno;
|
|
|
|
Smb4KError::error( ERROR_GETTING_PERMISSIONS, TQString(), strerror( error_number ) );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
return;
|
|
}
|
|
|
|
TQString perms = TQString( "%1" ).arg( (int)file_stat.st_mode, 0, 8 );
|
|
perms = perms.right( 4 );
|
|
TQString owner = TQString( "%1" ).arg( (int)file_stat.st_uid );
|
|
TQString group = TQString( "%1" ).arg( (int)file_stat.st_gid );
|
|
TQString temp_file_name = TQString( tmp );
|
|
|
|
// Assemble the command.
|
|
TQString command;
|
|
command.append( "kdesu -n -c \"smb4k_mv "+owner+":"+group+" "+perms+" " );
|
|
command.append( temp_file_name+" " );
|
|
command.append( canonical_path+"\" ; " );
|
|
command.append( "rm -f "+temp_file_name );
|
|
|
|
m_state = WriteSuperTab;
|
|
|
|
*m_proc << command;
|
|
|
|
m_proc->start( KProcess::NotifyOnExit, KProcess::AllOutput );
|
|
}
|
|
else
|
|
{
|
|
// Everything OK.
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// TQT_SLOT IMPLEMENTATIONS
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
void Smb4KFileIO::slotShutdown()
|
|
{
|
|
removeLockFile( false );
|
|
}
|
|
|
|
|
|
void Smb4KFileIO::slotReceivedStderr( KProcess *, char *buf, int len )
|
|
{
|
|
TQString error_output = TQString::fromLocal8Bit( buf, len );
|
|
|
|
if ( error_output.contains( "smb4k_mv" ) != 0 )
|
|
{
|
|
m_error_occurred = true;
|
|
|
|
TQString canonical_path = findFile( (m_state == WriteSudoers ? "sudoers" : "super.tab") );
|
|
|
|
Smb4KError::error( ERROR_WRITING_FILE, canonical_path, m_buffer );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
}
|
|
else if ( error_output.contains( "smb4k_cat" ) != 0 )
|
|
{
|
|
m_error_occurred = true;
|
|
|
|
TQString canonical_path = findFile( (m_state == ReadSudoers ? "sudoers" : "super.tab") );
|
|
|
|
Smb4KError::error( ERROR_READING_FILE, canonical_path, m_buffer );
|
|
|
|
emit failed();
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
}
|
|
}
|
|
|
|
|
|
void Smb4KFileIO::slotReceivedStdout( KProcess *, char *buf, int len )
|
|
{
|
|
m_buffer.append( TQString::fromLocal8Bit( buf, len ) );
|
|
}
|
|
|
|
|
|
void Smb4KFileIO::slotProcessExited( KProcess * )
|
|
{
|
|
m_proc->clearArguments();
|
|
|
|
if ( !m_error_occurred )
|
|
{
|
|
switch ( m_state )
|
|
{
|
|
case ReadSudoers:
|
|
{
|
|
processSudoers();
|
|
|
|
break;
|
|
}
|
|
case WriteSudoers:
|
|
{
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
break;
|
|
}
|
|
case ReadSuperTab:
|
|
{
|
|
processSuperTab();
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
emit finished();
|
|
|
|
removeLockFile();
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Smb4KFileIO::slotReceivedStderr() has already done the
|
|
// necessary things.
|
|
}
|
|
|
|
m_buffer = TQString();
|
|
m_state = Idle;
|
|
m_error_occurred = false;
|
|
}
|
|
|
|
#include "smb4kfileio.moc"
|