summaryrefslogtreecommitdiff
authorzecke <zecke>2004-12-20 21:58:55 (UTC)
committer zecke <zecke>2004-12-20 21:58:55 (UTC)
commit5f35158ba0e7c2813768aaab6d6ad478dc0271a1 (patch) (side-by-side diff)
treea4d6e8000e14ecd4e48ffee18fba733f78fbd0a7
parent7479e7ac142eb830329fb08f16179bb3aca642e5 (diff)
downloadopie-5f35158ba0e7c2813768aaab6d6ad478dc0271a1.zip
opie-5f35158ba0e7c2813768aaab6d6ad478dc0271a1.tar.gz
opie-5f35158ba0e7c2813768aaab6d6ad478dc0271a1.tar.bz2
Restore lost change
-Kill Config instance in different scope for the same file -Work when a ftp client sends -la in a listdir request
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/transferserver.cpp10
1 files changed, 7 insertions, 3 deletions
diff --git a/core/launcher/transferserver.cpp b/core/launcher/transferserver.cpp
index 1d4ca40..2b2e435 100644
--- a/core/launcher/transferserver.cpp
+++ b/core/launcher/transferserver.cpp
@@ -107,406 +107,407 @@ QString SyncAuthentication::ownerName()
Contact c;
c = Contact::readVCard( vfilename )[0];
return c.fullName();
}
return QString::null;
}
QString SyncAuthentication::loginName()
{
struct passwd *pw = 0L;
#ifndef Q_OS_WIN32
pw = getpwuid( geteuid() );
return QString::fromLocal8Bit( pw->pw_name );
#else
//### revise
return QString();
#endif
}
int SyncAuthentication::isAuthorized(QHostAddress peeraddress)
{
Config cfg("Security");
cfg.setGroup("Sync");
// QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0");
uint auth_peer = cfg.readNumEntry("auth_peer", 0xc0a80100);
// QHostAddress allowed;
// allowed.setAddress(allowedstr);
// uint auth_peer = allowed.ip4Addr();
uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits", 24);
uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined
? 0xffffffff : (((1 << auth_peer_bits) - 1) << (32 - auth_peer_bits));
return (peeraddress.ip4Addr() & mask) == auth_peer;
}
bool SyncAuthentication::checkUser( const QString& user )
{
if ( user.isEmpty() ) return FALSE;
QString euser = loginName();
return user == euser;
}
bool SyncAuthentication::checkPassword( const QString& password )
{
#ifdef ALLOW_UNIX_USER_FTP
// First, check system password...
struct passwd *pw = 0;
struct spwd *spw = 0;
pw = getpwuid( geteuid() );
spw = getspnam( pw->pw_name );
QString cpwd = QString::fromLocal8Bit( pw->pw_passwd );
if ( cpwd == "x" && spw )
cpwd = QString::fromLocal8Bit( spw->sp_pwdp );
// Note: some systems use more than crypt for passwords.
QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) );
if ( cpwd == cpassword )
return TRUE;
#endif
static int lastdenial=0;
static int denials=0;
int now = time(0);
Config cfg("Security");
cfg.setGroup("SyncMode");
int mode = cfg.readNumEntry("Mode", 0x02 );
//No pass word needed if the user really needs it
if (mode & 0x04) {
QMessageBox unauth(
tr("Sync Connection"),
tr("<qt><p>An unauthorized system is requesting access to this device."
"<p>You chose IntelliSync so you may I allow or deny this connection.</qt>" ),
QMessageBox::Warning,
QMessageBox::Ok, QMessageBox::Cancel|QMessageBox::Default, QMessageBox::NoButton,
0, QString::null, TRUE, WStyle_StaysOnTop);
unauth.setButtonText(QMessageBox::Ok, tr("Allow" ) );
unauth.setButtonText(QMessageBox::Cancel, tr("Deny"));
switch( unauth.exec() ) {
case QMessageBox::Ok:
return TRUE;
break;
case QMessageBox::Cancel:
default:
denials++;
lastdenial=now;
return FALSE;
}
}
// Detect old Qtopia Desktop (no password) and fail
if ( password.isEmpty() ) {
if ( denials < 3 || now > lastdenial+600 ) {
QMessageBox unauth(
tr("Sync Connection"),
tr("<p>An unauthorized system is requesting access to this device."
"<p>If you are using a version of Qtopia Desktop older than 1.5.1, "
"please upgrade or change the security setting to use IntelliSync." ),
QMessageBox::Warning,
QMessageBox::Cancel, QMessageBox::NoButton, QMessageBox::NoButton,
0, QString::null, TRUE, WStyle_StaysOnTop);
unauth.setButtonText(QMessageBox::Cancel, tr("Deny"));
unauth.exec();
denials++;
lastdenial=now;
}
return FALSE;
}
// Second, check sync password...
static int lock=0;
if ( lock ) return FALSE;
++lock;
/*
* we need to support old Sync software and QtopiaDesktop
*/
if ( password.left(6) == "Qtopia" || password.left(6) == "rootme" ) {
- Config cfg( "Security" );
cfg.setGroup("Sync");
QStringList pwds = cfg.readListEntry("Passwords",' ');
for (QStringList::ConstIterator it=pwds.begin(); it!=pwds.end(); ++it) {
#ifndef Q_OS_WIN32
QString cpassword = QString::fromLocal8Bit(
crypt( password.mid(8).local8Bit(), (*it).left(2).latin1() ) );
#else
// ### revise
QString cpassword("");
#endif
if ( *it == cpassword ) {
lock--;
return TRUE;
}
}
// Unrecognized system. Be careful...
QMessageBox unrecbox(
tr("Sync Connection"),
tr( "<p>An unrecognized system is requesting access to this device."
"<p>If you have just initiated a Sync for the first time, this is normal."),
QMessageBox::Warning,
QMessageBox::Cancel, QMessageBox::Yes, QMessageBox::NoButton,
0, QString::null, TRUE, WStyle_StaysOnTop);
unrecbox.setButtonText(QMessageBox::Cancel, tr("Deny"));
unrecbox.setButtonText(QMessageBox::Yes, tr("Allow"));
if ( (denials > 2 && now < lastdenial+600)
|| unrecbox.exec() != QMessageBox::Yes)
{
denials++;
lastdenial=now;
lock--;
return FALSE;
} else {
const char salty[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/.";
char salt[2];
salt[0]= salty[rand() % (sizeof(salty)-1)];
salt[1]= salty[rand() % (sizeof(salty)-1)];
#ifndef Q_OS_WIN32
QString cpassword = QString::fromLocal8Bit(
crypt( password.mid(8).local8Bit(), salt ) );
#else
//### revise
QString cpassword("");
#endif
denials=0;
pwds.prepend(cpassword);
cfg.writeEntry("Passwords",pwds,' ');
lock--;
return TRUE;
}
}
lock--;
return FALSE;
}
ServerPI::ServerPI( int socket, QObject *parent, const char* name )
: QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ),
storFileSize(-1)
{
state = Connected;
setSocket( socket );
peerport = peerPort();
peeraddress = peerAddress();
#ifndef INSECURE
if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
state = Forbidden;
startTimer( 0 );
} else
#endif
{
connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
passiv = FALSE;
for( int i = 0; i < 4; i++ )
wait[i] = FALSE;
send( "220 Qtopia " QPE_VERSION " FTP Server" ); // No tr
state = Wait_USER;
dtp = new ServerDTP( this );
connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) );
connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) );
connect( dtp, SIGNAL( error(int) ), SLOT( dtpError(int) ) );
directory = QDir::currentDirPath();
static int p = 1024;
while ( !serversocket || !serversocket->ok() ) {
delete serversocket;
serversocket = new ServerSocket( ++p, this );
}
connect( serversocket, SIGNAL( newIncomming(int) ),
SLOT( newConnection(int) ) );
}
}
ServerPI::~ServerPI()
{
close();
if ( dtp )
dtp->close();
delete dtp;
delete serversocket;
}
bool ServerPI::verifyAuthorised()
{
if ( !SyncAuthentication::isAuthorized(peerAddress()) ) {
state = Forbidden;
return FALSE;
}
return TRUE;
}
void ServerPI::connectionClosed()
{
// odebug << "Debug: Connection closed" << oendl;
emit connectionClosed(this);
}
void ServerPI::send( const QString& msg )
{
QTextStream os( this );
os << msg << endl;
//odebug << "Reply: " << msg << "" << oendl;
}
void ServerPI::read()
{
while ( canReadLine() )
process( readLine().stripWhiteSpace() );
}
bool ServerPI::checkReadFile( const QString& file )
{
QString filename;
-
- if ( file[0] != "/" )
+
+ if ( file.length() == 1 && file[0] == "/" )
+ filename = file;
+ else if ( file[0] != "/" )
filename = directory.path() + "/" + file;
else
filename = file;
QFileInfo fi( filename );
return ( fi.exists() && fi.isReadable() );
}
bool ServerPI::checkWriteFile( const QString& file )
{
QString filename;
if ( file[0] != "/" )
filename = directory.path() + "/" + file;
else
filename = file;
QFileInfo fi( filename );
if ( fi.exists() )
if ( !QFile( filename ).remove() )
return FALSE;
return TRUE;
}
void ServerPI::process( const QString& message )
{
//odebug << "Command: " << message << "" << oendl;
// split message using "," as separator
QStringList msg = QStringList::split( " ", message );
if ( msg.isEmpty() ) return;
// command token
QString cmd = msg[0].upper();
// argument token
QString arg;
if ( msg.count() >= 2 )
arg = msg[1];
// full argument string
QString args;
if ( msg.count() >= 2 ) {
QStringList copy( msg );
// FIXME: for Qt3
// copy.pop_front()
copy.remove( copy.begin() );
args = copy.join( " " );
}
//odebug << "args: " << args << "" << oendl;
// we always respond to QUIT, regardless of state
if ( cmd == "QUIT" ) {
send( "211 Good bye!" ); // No tr
close();
return;
}
// connected to client
if ( Connected == state )
return;
// waiting for user name
if ( Wait_USER == state ) {
if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
send( "530 Please login with USER and PASS" ); // No tr
return;
}
send( "331 User name ok, need password" ); // No tr
state = Wait_PASS;
return;
}
// waiting for password
if ( Wait_PASS == state ) {
if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
send( "530 Please login with USER and PASS" ); // No tr
return;
}
send( "230 User logged in, proceed" ); // No tr
state = Ready;
return;
}
// ACCESS CONTROL COMMANDS
// Only an ALLO sent immediately before STOR is valid.
if ( cmd != "STOR" )
storFileSize = -1;
// account (ACCT)
if ( cmd == "ACCT" ) {
// even wu-ftp does not support it
send( "502 Command not implemented" ); // No tr
}
// change working directory (CWD)
else if ( cmd == "CWD" ) {
if ( !args.isEmpty() ) {
if ( directory.cd( args, TRUE ) )
send( "250 Requested file action okay, completed" ); // No tr
else
send( "550 Requested action not taken" ); // No tr
}
else
send( "500 Syntax error, command unrecognized" ); // No tr
}
// change to parent directory (CDUP)
else if ( cmd == "CDUP" ) {
if ( directory.cdUp() )
send( "250 Requested file action okay, completed" ); // No tr
else
send( "550 Requested action not taken" ); // No tr
}
// structure mount (SMNT)
else if ( cmd == "SMNT" ) {
// even wu-ftp does not support it
send( "502 Command not implemented" ); // No tr
}
// reinitialize (REIN)
@@ -572,256 +573,259 @@ void ServerPI::process( const QString& message )
sendFile( absFilePath( args ) );
}
else {
odebug << "550 Requested action not taken" << oendl;
send( "550 Requested action not taken" ); // No tr
}
// store (STOR)
else if ( cmd == "STOR" )
if ( !args.isEmpty() && checkWriteFile( absFilePath( args ) ) ) {
send( "150 File status okay" ); // No tr
retrieveFile( absFilePath( args ) );
}
else
send( "550 Requested action not taken" ); // No tr
// store unique (STOU)
else if ( cmd == "STOU" ) {
send( "502 Command not implemented" ); // No tr
}
// append (APPE)
else if ( cmd == "APPE" ) {
send( "502 Command not implemented" ); // No tr
}
// allocate (ALLO)
else if ( cmd == "ALLO" ) {
storFileSize = args.toInt();
send( "200 Command okay" ); // No tr
}
// restart (REST)
else if ( cmd == "REST" ) {
send( "502 Command not implemented" ); // No tr
}
// rename from (RNFR)
else if ( cmd == "RNFR" ) {
renameFrom = QString::null;
if ( args.isEmpty() )
send( "500 Syntax error, command unrecognized" ); // No tr
else {
QFile file( absFilePath( args ) );
if ( file.exists() ) {
send( "350 File exists, ready for destination name" ); // No tr
renameFrom = absFilePath( args );
}
else
send( "550 Requested action not taken" ); // No tr
}
}
// rename to (RNTO)
else if ( cmd == "RNTO" ) {
if ( lastCommand != "RNFR" )
send( "503 Bad sequence of commands" ); // No tr
else if ( args.isEmpty() )
send( "500 Syntax error, command unrecognized" ); // No tr
else {
QDir dir( absFilePath( args ) );
if ( dir.rename( renameFrom, absFilePath( args ), TRUE ) )
send( "250 Requested file action okay, completed." ); // No tr
else
send( "550 Requested action not taken" ); // No tr
}
}
// abort (ABOR)
else if ( cmd.contains( "ABOR" ) ) {
dtp->close();
if ( dtp->dtpMode() != ServerDTP::Idle )
send( "426 Connection closed; transfer aborted" ); // No tr
else
send( "226 Closing data connection" ); // No tr
}
// delete (DELE)
else if ( cmd == "DELE" ) {
if ( args.isEmpty() )
send( "500 Syntax error, command unrecognized" ); // No tr
else {
QFile file( absFilePath( args ) ) ;
if ( file.remove() ) {
send( "250 Requested file action okay, completed" ); // No tr
QCopEnvelope e("QPE/System", "linkChanged(QString)" );
e << file.name();
} else {
send( "550 Requested action not taken" ); // No tr
}
}
}
// remove directory (RMD)
else if ( cmd == "RMD" ) {
if ( args.isEmpty() )
send( "500 Syntax error, command unrecognized" ); // No tr
else {
QDir dir;
if ( dir.rmdir( absFilePath( args ), TRUE ) )
send( "250 Requested file action okay, completed" ); // No tr
else
send( "550 Requested action not taken" ); // No tr
}
}
// make directory (MKD)
else if ( cmd == "MKD" ) {
if ( args.isEmpty() ) {
odebug << " Error: no arg" << oendl;
send( "500 Syntax error, command unrecognized" ); // No tr
}
else {
QDir dir;
if ( dir.mkdir( absFilePath( args ), TRUE ) )
send( "250 Requested file action okay, completed." ); // No tr
else
send( "550 Requested action not taken" ); // No tr
}
}
// print working directory (PWD)
else if ( cmd == "PWD" ) {
send( "257 \"" + directory.path() +"\"" );
}
// list (LIST)
else if ( cmd == "LIST" ) {
+ if ( args == "-la" )
+ args = QString::null;
+
if ( sendList( absFilePath( args ) ) )
send( "150 File status okay" ); // No tr
else
send( "500 Syntax error, command unrecognized" ); // No tr
}
// size (SIZE)
else if ( cmd == "SIZE" ) {
QString filePath = absFilePath( args );
QFileInfo fi( filePath );
bool gzipfile = backupRestoreGzip( filePath );
if ( !fi.exists() && !gzipfile )
send( "500 Syntax error, command unrecognized" ); // No tr
else {
if ( !gzipfile )
send( "213 " + QString::number( fi.size() ) );
else {
Process duproc( QString("du") );
duproc.addArgument("-s");
QString in, out;
if ( !duproc.exec(in, out) ) {
odebug << "du process failed; just sending back 1K" << oendl;
send( "213 1024");
}
else {
QString size = out.left( out.find("\t") );
int guess = size.toInt()/5;
if ( filePath.contains("doc") ) // No tr
guess *= 1000;
odebug << "sending back gzip guess of " << guess << "" << oendl;
send( "213 " + QString::number(guess) );
}
}
}
}
// name list (NLST)
else if ( cmd == "NLST" ) {
send( "502 Command not implemented" ); // No tr
}
// site parameters (SITE)
else if ( cmd == "SITE" ) {
send( "502 Command not implemented" ); // No tr
}
// system (SYST)
else if ( cmd == "SYST" ) {
send( "215 UNIX Type: L8" ); // No tr
}
// status (STAT)
else if ( cmd == "STAT" ) {
send( "502 Command not implemented" ); // No tr
}
// help (HELP )
else if ( cmd == "HELP" ) {
send( "502 Command not implemented" ); // No tr
}
// noop (NOOP)
else if ( cmd == "NOOP" ) {
send( "200 Command okay" ); // No tr
}
// not implemented
else
send( "502 Command not implemented" ); // No tr
lastCommand = cmd;
}
bool ServerPI::backupRestoreGzip( const QString &file )
{
return (file.find( "backup" ) != -1 && // No tr
file.findRev( ".tgz" ) == (int)file.length()-4 );
}
bool ServerPI::backupRestoreGzip( const QString &file, QStringList &targets )
{
if ( file.find( "backup" ) != -1 && // No tr
file.findRev( ".tgz" ) == (int)file.length()-4 ) {
QFileInfo info( file );
targets = info.dirPath( TRUE );
odebug << "ServerPI::backupRestoreGzip for " << file.latin1() << " = " << targets.join(" ").latin1() << oendl;
return true;
}
return false;
}
void ServerPI::sendFile( const QString& file )
{
if ( passiv ) {
wait[SendFile] = TRUE;
waitfile = file;
if ( waitsocket )
newConnection( waitsocket );
}
else {
QStringList targets;
if ( backupRestoreGzip( file, targets ) )
dtp->sendGzipFile( file, targets, peeraddress, peerport );
else dtp->sendFile( file, peeraddress, peerport );
}
}
void ServerPI::retrieveFile( const QString& file )
{
if ( passiv ) {
wait[RetrieveFile] = TRUE;
waitfile = file;
if ( waitsocket )
newConnection( waitsocket );
}
else {
QStringList targets;
if ( backupRestoreGzip( file, targets ) )
dtp->retrieveGzipFile( file, peeraddress, peerport );
else
dtp->retrieveFile( file, peeraddress, peerport, storFileSize );
}
}
bool ServerPI::parsePort( const QString& pp )
{
QStringList p = QStringList::split( ",", pp );
if ( p.count() != 6 ) return FALSE;