summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/qws/transferserver.cpp1
1 files changed, 1 insertions, 0 deletions
diff --git a/core/qws/transferserver.cpp b/core/qws/transferserver.cpp
index 7bf6719..42ac917 100644
--- a/core/qws/transferserver.cpp
+++ b/core/qws/transferserver.cpp
@@ -1,414 +1,415 @@
/**********************************************************************
** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
/* OPIE */
#include <opie2/odebug.h>
/* STD */
#define _XOPEN_SOURCE
#include <pwd.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
+#include <crypt.h>
#ifndef Q_OS_MACX
#include <shadow.h>
#endif /* Q_OS_MACX */
/* we need the _OS_LINUX stuff first ! */
#ifndef _OS_LINUX_
// Is anybody able to review this ? The include "uuid/uuid.h" couldn't be found
// anywhere ? Therfore I removed it completely..
// I think it should be made permanentyl !? (eilers)
#warning "Where should uuid/uuid.h be found ? Removed this part .. (eilers)"
#if 0
extern "C"
{
#include <uuid/uuid.h>
#define UUID_H_INCLUDED
}
#endif
#endif // not defined linux
#if defined(_OS_LINUX_)
#include <shadow.h>
#elif defined(Q_OS_MACX)
#include <stdlib.h>
#endif
#include <qtextstream.h>
#include <qmessagebox.h>
//#include <qpe/qcopchannel_qws.h>
#include <qpe/process.h>
#include <qpe/global.h>
#include <qpe/config.h>
#include <qpe/contact.h>
#include <qpe/version.h>
#include <qpe/qcopenvelope_qws.h>
#include "transferserver.h"
#include <opie2/oprocess.h>
using namespace Opie::Core;
const int block_size = 51200;
TransferServer::TransferServer( Q_UINT16 port, QObject *parent ,
const char* name )
: QServerSocket( port, 1, parent, name )
{
if ( !ok() )
owarn << "Failed to bind to port " << port << "" << oendl;
}
TransferServer::~TransferServer()
{
}
void TransferServer::newConnection( int socket )
{
(void) new ServerPI( socket, this );
}
/*
* small class in anonymous namespace
* to generate a QUUid for us
*/
namespace
{
struct UidGen
{
QString uuid();
};
#if defined(Q_OS_MACX)
QString UidGen::uuid()
{
srandom( random() );
QString numStr = QString::number( random() );
return "{" + numStr + "}";
}
#elif defined(_OS_LINUX_)
/*
* linux got a /proc/sys/kernel/random/uuid file
* it'll generate the uuids for us
*/
QString UidGen::uuid()
{
QFile file( "/proc/sys/kernel/random/uuid" );
if (!file.open(IO_ReadOnly ) )
return QString::null;
QTextStream stream(&file);
return "{" + stream.read().stripWhiteSpace() + "}";
}
#else
QString UidGen::uuid()
{
uuid_t uuid;
::uuid_generate( uuid );
return QUUid( uuid ).toString();
}
#endif
}
QString SyncAuthentication::serverId()
{
Config cfg("Security");
cfg.setGroup("Sync");
QString r = cfg.readEntry("serverid");
if ( r.isEmpty() ) {
UidGen gen;
r = gen.uuid();
cfg.writeEntry("serverid", r );
}
return r;
}
QString SyncAuthentication::ownerName()
{
QString vfilename = Global::applicationFileName("addressbook",
"businesscard.vcf");
if (QFile::exists(vfilename)) {
Contact c;
c = Contact::readVCard( vfilename )[0];
return c.fullName();
}
return "";
}
QString SyncAuthentication::loginName()
{
struct passwd *pw;
pw = getpwuid( geteuid() );
return QString::fromLocal8Bit( pw->pw_name );
}
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);
// Detect old Qtopia Desktop (no password)
if ( password.isEmpty() ) {
if ( denials < 1 || now > lastdenial + 600 ) {
QMessageBox::warning( 0, 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."),
tr("Deny") );
denials++;
lastdenial = now;
}
return FALSE;
}
// Second, check sync password...
QString pass = password.left(6);
/* old QtopiaDesktops are sending
* rootme newer versions got a Qtopia
* prefixed. Qtopia prefix will suceed
* until the sync software syncs up
* FIXME
*/
if ( pass == "rootme" || pass == "Qtopia") {
QString cpassword = QString::fromLocal8Bit( crypt( password.mid(8).local8Bit(), "qp" ) );
Config cfg("Security");
cfg.setGroup("Sync");
QString pwds = cfg.readEntry("Passwords");
if ( QStringList::split(QChar(' '), pwds).contains(cpassword) )
return TRUE;
// Unrecognized system. Be careful...
if ( (denials > 2 && now < lastdenial + 600)
|| QMessageBox::warning(0, 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."),
tr("Allow"), tr("Deny"), 0, 1, 1 ) == 1 ) {
denials++;
lastdenial = now;
return FALSE;
}
else {
denials = 0;
cfg.writeEntry("Passwords", pwds + " " + cpassword);
return TRUE;
}
}
return FALSE;
}
ServerPI::ServerPI( int socket, QObject *parent , const char* name )
: QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 )
{
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" );
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()
{
}
void ServerPI::connectionClosed()
{
// odebug << "Debug: Connection closed" << oendl;
delete 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] != "/" )
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!" );
delete this;
return ;
}
// connected to client
if ( Connected == state )
return ;
// waiting for user name
if ( Wait_USER == state ) {