summaryrefslogtreecommitdiff
authorzecke <zecke>2002-07-12 13:51:37 (UTC)
committer zecke <zecke>2002-07-12 13:51:37 (UTC)
commit716211b5e06bb25145cfbcf62a11a7c52c79dde5 (patch) (unidiff)
tree595c4c15cb0ca31f2579be42ee029c1c30454b9c
parent7c12000481b535ce54951ef8a53b439814f8fcd6 (diff)
downloadopie-716211b5e06bb25145cfbcf62a11a7c52c79dde5.zip
opie-716211b5e06bb25145cfbcf62a11a7c52c79dde5.tar.gz
opie-716211b5e06bb25145cfbcf62a11a7c52c79dde5.tar.bz2
Security fix by trolltech
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/desktop.cpp4
-rw-r--r--core/launcher/launcher.pro2
-rw-r--r--core/launcher/qcopbridge.cpp424
-rw-r--r--core/launcher/qcopbridge.h7
-rw-r--r--core/launcher/transferserver.cpp213
-rw-r--r--core/launcher/transferserver.h23
6 files changed, 392 insertions, 281 deletions
diff --git a/core/launcher/desktop.cpp b/core/launcher/desktop.cpp
index 24dce73..541b4be 100644
--- a/core/launcher/desktop.cpp
+++ b/core/launcher/desktop.cpp
@@ -568,4 +568,4 @@ void Desktop::execAutoStart() {
568 e << QString(appName); 568 e << QString(appName);
569 } else { 569 } //else {
570 } 570 //}
571} 571}
diff --git a/core/launcher/launcher.pro b/core/launcher/launcher.pro
index ccf8231..169edc1 100644
--- a/core/launcher/launcher.pro
+++ b/core/launcher/launcher.pro
@@ -101,3 +101,3 @@ DEPENDPATH += $(OPIEDIR)/rsync
101 TARGET = qpe 101 TARGET = qpe
102 LIBS += -lqpe -lcrypt -lopie 102 LIBS += -lqpe -lcrypt -lopie -luuid
103 103
diff --git a/core/launcher/qcopbridge.cpp b/core/launcher/qcopbridge.cpp
index 2d084fc..85993ee 100644
--- a/core/launcher/qcopbridge.cpp
+++ b/core/launcher/qcopbridge.cpp
@@ -1,5 +1,5 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
@@ -23,4 +23,7 @@
23 23
24#ifdef QWS
24#include <qpe/qcopenvelope_qws.h> 25#include <qpe/qcopenvelope_qws.h>
26#endif
25#include <qpe/qpeapplication.h> 27#include <qpe/qpeapplication.h>
28#include <qpe/version.h>
26 29
@@ -33,9 +36,7 @@
33#include <qregexp.h> 36#include <qregexp.h>
37#ifdef QWS
34#include <qcopchannel_qws.h> 38#include <qcopchannel_qws.h>
39#endif
35 40
36// actually this is wrong, _XOPEN_SOURCE should get defined on the commandline
37// and it should have a proper value assigned. (Simon)
38#if !defined(_XOPEN_SOURCE)
39#define _XOPEN_SOURCE 41#define _XOPEN_SOURCE
40#endif
41#include <pwd.h> 42#include <pwd.h>
@@ -52,3 +53,3 @@ const int block_size = 51200;
52 53
53QCopBridge::QCopBridge( Q_UINT16 port, QObject *parent, 54QCopBridge::QCopBridge( Q_UINT16 port, QObject *parent ,
54 const char* name ) 55 const char* name )
@@ -59,10 +60,12 @@ QCopBridge::QCopBridge( Q_UINT16 port, QObject *parent,
59 if ( !ok() ) 60 if ( !ok() )
60 qWarning( "Failed to bind to port %d", port ); 61 qWarning( "Failed to bind to port %d", port );
61 else { 62 else {
62 desktopChannel = new QCopChannel( "QPE/Desktop", this ); 63#ifndef QT_NO_COP
63 connect( desktopChannel, SIGNAL(received(const QCString &, const QByteArray &)), 64 desktopChannel = new QCopChannel( "QPE/Desktop", this );
64 this, SLOT(desktopMessage( const QCString &, const QByteArray &)) ); 65 connect( desktopChannel, SIGNAL(received(const QCString &, const QByteArray &)),
65 cardChannel = new QCopChannel( "QPE/Card", this ); 66 this, SLOT(desktopMessage( const QCString &, const QByteArray &)) );
66 connect( cardChannel, SIGNAL(received(const QCString &, const QByteArray &)), 67 cardChannel = new QCopChannel( "QPE/Card", this );
67 this, SLOT(desktopMessage( const QCString &, const QByteArray &)) ); 68 connect( cardChannel, SIGNAL(received(const QCString &, const QByteArray &)),
69 this, SLOT(desktopMessage( const QCString &, const QByteArray &)) );
70#endif
68 } 71 }
@@ -73,3 +76,5 @@ QCopBridge::~QCopBridge()
73{ 76{
77#ifndef QT_NO_COP
74 delete desktopChannel; 78 delete desktopChannel;
79#endif
75} 80}
@@ -81,7 +86,9 @@ void QCopBridge::newConnection( int socket )
81 connect ( pi, SIGNAL( connectionClosed( QCopBridgePI *) ), this, SLOT( connectionClosed( QCopBridgePI *) ) ); 86 connect ( pi, SIGNAL( connectionClosed( QCopBridgePI *) ), this, SLOT( connectionClosed( QCopBridgePI *) ) );
87#ifndef QT_NO_COP
82 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::DisableSuspend; 88 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::DisableSuspend;
83 89#endif
90
84 if ( sendSync ) { 91 if ( sendSync ) {
85 pi ->startSync(); 92 pi ->startSync();
86 sendSync = FALSE; 93 sendSync = FALSE;
87 } 94 }
@@ -93,5 +100,7 @@ void QCopBridge::connectionClosed( QCopBridgePI *pi )
93 if ( openConnections.count() == 0 ) { 100 if ( openConnections.count() == 0 ) {
94 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable; 101#ifndef QT_NO_COP
102 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable;
103#endif
95 } 104 }
96} 105}
97 106
@@ -101,3 +110,3 @@ void QCopBridge::closeOpenConnections()
101 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) 110 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() )
102 pi->close(); 111 pi->close();
103} 112}
@@ -111,4 +120,4 @@ void QCopBridge::desktopMessage( const QCString &command, const QByteArray &args
111 if ( paren <= 0 ) { 120 if ( paren <= 0 ) {
112 qDebug("DesktopMessage: bad qcop syntax"); 121 qDebug("DesktopMessage: bad qcop syntax");
113 return; 122 return;
114 } 123 }
@@ -117,4 +126,4 @@ void QCopBridge::desktopMessage( const QCString &command, const QByteArray &args
117 if ( params[params.length()-1] != ')' ) { 126 if ( params[params.length()-1] != ')' ) {
118 qDebug("DesktopMessage: bad qcop syntax"); 127 qDebug("DesktopMessage: bad qcop syntax");
119 return; 128 return;
120 } 129 }
@@ -126,29 +135,47 @@ void QCopBridge::desktopMessage( const QCString &command, const QByteArray &args
126 if ( paramList.count() ) { 135 if ( paramList.count() ) {
127 QDataStream stream( args, IO_ReadOnly ); 136 QDataStream stream( args, IO_ReadOnly );
128 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) { 137 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) {
129 QString str; 138 QString str;
130 if ( *it == "QString" ) { 139 if ( *it == "QString" ) {
131 stream >> str; 140 stream >> str;
132 } else if ( *it == "QCString" ) { 141 } else if ( *it == "QCString" ) {
133 QCString cstr; 142 QCString cstr;
134 stream >> cstr; 143 stream >> cstr;
135 str = QString::fromLocal8Bit( cstr ); 144 str = QString::fromLocal8Bit( cstr );
136 } else if ( *it == "int" ) { 145 } else if ( *it == "int" ) {
137 int i; 146 int i;
138 stream >> i; 147 stream >> i;
139 str = QString::number( i ); 148 str = QString::number( i );
140 } else if ( *it == "bool" ) { 149 } else if ( *it == "bool" ) {
141 int i; 150 int i;
142 stream >> i; 151 stream >> i;
143 str = QString::number( i ); 152 str = QString::number( i );
144 } else { 153 } else {
145 qDebug(" cannot route the argument type %s through the qcop bridge", (*it).latin1() ); 154 qDebug(" cannot route the argument type %s throught the qcop bridge", (*it).latin1() );
146 return; 155 return;
147 } 156 }
148 str.replace( QRegExp("&"), "&amp;" ); 157 QString estr;
149 str.replace( QRegExp(" "), "&0x20;" ); 158 for (int i=0; i<(int)str.length(); i++) {
150 str.replace( QRegExp("\n"), "&0x0d;" ); 159 QChar ch = str[i];
151 str.replace( QRegExp("\r"), "&0x0a;" ); 160 if ( ch.row() )
152 data += " " + str; 161 goto quick;
153 } 162 switch (ch.cell()) {
163 case '&':
164 estr.append( "&amp;" );
165 break;
166 case ' ':
167 estr.append( "&0x20;" );
168 break;
169 case '\n':
170 estr.append( "&0x0d;" );
171 break;
172 case '\r':
173 estr.append( "&0x0a;" );
174 break;
175 default: quick:
176 estr.append(ch);
177 }
178 }
179 data += " " + estr;
180 }
154 } 181 }
@@ -157,10 +184,10 @@ void QCopBridge::desktopMessage( const QCString &command, const QByteArray &args
157 if ( command == "startSync()" ) { 184 if ( command == "startSync()" ) {
158 // we need to buffer it a bit 185 // we need to buffer it a bit
159 sendSync = TRUE; 186 sendSync = TRUE;
160 startTimer( 20000 ); 187 startTimer( 20000 );
161 } 188 }
162 189
163 QCopBridgePI *pi; 190 QCopBridgePI *pi;
164 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) { 191 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) {
165 pi->sendDesktopMessage( sendCommand ); 192 pi->sendDesktopMessage( sendCommand );
166 } 193 }
@@ -175,4 +202,4 @@ void QCopBridge::timerEvent( QTimerEvent * )
175 202
176QCopBridgePI::QCopBridgePI( int socket, QObject *parent, const char* name ) 203QCopBridgePI::QCopBridgePI( int socket, QObject *parent , const char* name )
177 : QSocket( parent, name ) 204 : QSocket( parent, name )
178{ 205{
@@ -184,19 +211,24 @@ QCopBridgePI::QCopBridgePI( int socket, QObject *parent, const char* name )
184#ifndef INSECURE 211#ifndef INSECURE
185 if ( !accessAuthorized(peeraddress) ) { 212 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
186 state = Forbidden; 213 state = Forbidden;
187 startTimer( 0 ); 214 startTimer( 0 );
188 } else 215 } else
189#endif 216 #endif
190 { 217 {
191 state = Connected; 218 state = Connected;
192 sendSync = FALSE; 219 sendSync = FALSE;
193 connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); 220 connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
194 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); 221 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
195 222
196 send( "220 Qtopia QCop bridge ready!" ); 223 QString intro="220 Qtopia ";
197 state = Wait_USER; 224 intro += QPE_VERSION; intro += ";";
198 225 intro += "challenge="; intro += SyncAuthentication::serverId(); intro += ";";
199 // idle timer to close connections when not used anymore 226 intro += "loginname="; intro += SyncAuthentication::loginName(); intro += ";";
200 startTimer( 60000 ); 227 intro += "displayname="; intro += SyncAuthentication::ownerName(); intro += ";";
201 connected = TRUE; 228 send( intro );
229 state = Wait_USER;
230
231 // idle timer to close connections when not used anymore
232 startTimer( 60000 );
233 connected = TRUE;
202 } 234 }
@@ -234,34 +266,3 @@ void QCopBridgePI::read()
234 while ( canReadLine() ) 266 while ( canReadLine() )
235 process( readLine().stripWhiteSpace() ); 267 process( readLine().stripWhiteSpace() );
236}
237
238bool QCopBridgePI::checkUser( const QString& user )
239{
240 if ( user.isEmpty() ) return FALSE;
241
242 struct passwd *pw;
243 pw = getpwuid( geteuid() );
244 QString euser = QString::fromLocal8Bit( pw->pw_name );
245 return user == euser;
246}
247
248bool QCopBridgePI::checkPassword( const QString& password )
249{
250 // ### HACK for testing on local host
251 return true;
252
253 /*
254 struct passwd *pw = 0;
255 struct spwd *spw = 0;
256
257 pw = getpwuid( geteuid() );
258 spw = getspnam( pw->pw_name );
259
260 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd );
261 if ( cpwd == "x" && spw )
262 cpwd = QString::fromLocal8Bit( spw->sp_pwdp );
263
264 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) );
265 return cpwd == cpassword;
266*/
267} 268}
@@ -282,9 +283,9 @@ void QCopBridgePI::process( const QString& message )
282 if ( msg.count() >= 2 ) 283 if ( msg.count() >= 2 )
283 arg = msg[1]; 284 arg = msg[1];
284 285
285 // we always respond to QUIT, regardless of state 286 // we always respond to QUIT, regardless of state
286 if ( cmd == "QUIT" ) { 287 if ( cmd == "QUIT" ) {
287 send( "211 Have a nice day!" ); 288 send( "211 Have a nice day!" );
288 delete this; 289 delete this;
289 return; 290 return;
290 } 291 }
@@ -293,3 +294,3 @@ void QCopBridgePI::process( const QString& message )
293 if ( Connected == state ) 294 if ( Connected == state )
294 return; 295 return;
295 296
@@ -298,9 +299,9 @@ void QCopBridgePI::process( const QString& message )
298 299
299 if ( cmd != "USER" || msg.count() < 2 || !checkUser( arg ) ) { 300 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
300 send( "530 Please login with USER and PASS" ); 301 send( "530 Please login with USER and PASS" );
301 return; 302 return;
302 } 303 }
303 send( "331 User name ok, need password" ); 304 send( "331 User name ok, need password" );
304 state = Wait_PASS; 305 state = Wait_PASS;
305 return; 306 return;
306 } 307 }
@@ -310,14 +311,13 @@ void QCopBridgePI::process( const QString& message )
310 311
311 if ( cmd != "PASS" || !checkPassword( arg ) ) { 312 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
312 //if ( cmd != "PASS" || msg.count() < 2 || !checkPassword( arg ) ) { 313 send( "530 Please login with USER and PASS" );
313 send( "530 Please login with USER and PASS" ); 314 return;
314 return; 315 }
315 } 316 send( "230 User logged in, proceed" );
316 send( "230 User logged in, proceed" ); 317 state = Ready;
317 state = Ready; 318 if ( sendSync ) {
318 if ( sendSync ) { 319 sendDesktopMessage( "startSync()" );
319 sendDesktopMessage( "startSync()" ); 320 sendSync = FALSE;
320 sendSync = FALSE; 321 }
321 } 322 return;
322 return;
323 } 323 }
@@ -326,6 +326,6 @@ void QCopBridgePI::process( const QString& message )
326 else if ( cmd == "NOOP" ) { 326 else if ( cmd == "NOOP" ) {
327 connected = TRUE; 327 connected = TRUE;
328 send( "200 Command okay" ); 328 send( "200 Command okay" );
329 } 329 }
330 330
331 // call (CALL) 331 // call (CALL)
@@ -333,74 +333,78 @@ void QCopBridgePI::process( const QString& message )
333 333
334 // example: call QPE/System execute(QString) addressbook 334 // example: call QPE/System execute(QString) addressbook
335 335
336 if ( msg.count() < 3 ) { 336 if ( msg.count() < 3 ) {
337 send( "500 Syntax error, command unrecognized" ); 337 send( "500 Syntax error, command unrecognized" );
338 } 338 }
339 else { 339 else {
340 340
341 QString channel = msg[1]; 341 QString channel = msg[1];
342 QString command = msg[2]; 342 QString command = msg[2];
343 343
344 command.stripWhiteSpace(); 344 command.stripWhiteSpace();
345 345
346 int paren = command.find( "(" ); 346 int paren = command.find( "(" );
347 if ( paren <= 0 ) { 347 if ( paren <= 0 ) {
348 send( "500 Syntax error, command unrecognized" ); 348 send( "500 Syntax error, command unrecognized" );
349 return; 349 return;
350 } 350 }
351 351
352 QString params = command.mid( paren + 1 ); 352 QString params = command.mid( paren + 1 );
353 if ( params[params.length()-1] != ')' ) { 353 if ( params[params.length()-1] != ')' ) {
354 send( "500 Syntax error, command unrecognized" ); 354 send( "500 Syntax error, command unrecognized" );
355 return; 355 return;
356 } 356 }
357 357
358 params.truncate( params.length()-1 ); 358 params.truncate( params.length()-1 );
359 QByteArray buffer; 359 QByteArray buffer;
360 QDataStream ds( buffer, IO_WriteOnly ); 360 QDataStream ds( buffer, IO_WriteOnly );
361 361
362 int msgId = 3; 362 int msgId = 3;
363 363
364 QStringList paramList = QStringList::split( ",", params ); 364 QStringList paramList = QStringList::split( ",", params );
365 if ( paramList.count() > msg.count() - 3 ) { 365 if ( paramList.count() > msg.count() - 3 ) {
366 send( "500 Syntax error, command unrecognized" ); 366 send( "500 Syntax error, command unrecognized" );
367 return; 367 return;
368 } 368 }
369 369
370 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) { 370 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) {
371 371
372 QString arg = msg[msgId]; 372 QString arg = msg[msgId];
373 arg.replace( QRegExp("&0x20;"), " " ); 373 arg.replace( QRegExp("&0x20;"), " " );
374 arg.replace( QRegExp("&amp;"), "&" ); 374 arg.replace( QRegExp("&amp;"), "&" );
375 arg.replace( QRegExp("&0x0d;"), "\n" ); 375 arg.replace( QRegExp("&0x0d;"), "\n" );
376 arg.replace( QRegExp("&0x0a;"), "\r" ); 376 arg.replace( QRegExp("&0x0a;"), "\r" );
377 if ( *it == "QString" ) 377 if ( *it == "QString" )
378 ds << arg; 378 ds << arg;
379 else if ( *it == "QCString" ) 379 else if ( *it == "QCString" )
380 ds << arg.local8Bit(); 380 ds << arg.local8Bit();
381 else if ( *it == "int" ) 381 else if ( *it == "int" )
382 ds << arg.toInt(); 382 ds << arg.toInt();
383 else if ( *it == "bool" ) 383 else if ( *it == "bool" )
384 ds << arg.toInt(); 384 ds << arg.toInt();
385 else { 385 else {
386 send( "500 Syntax error, command unrecognized" ); 386 send( "500 Syntax error, command unrecognized" );
387 return; 387 return;
388 } 388 }
389 msgId++; 389 msgId++;
390 } 390 }
391 391
392 if ( !QCopChannel::isRegistered( channel.latin1() ) ) { 392#ifndef QT_NO_COP
393 // send message back about it 393 if ( !QCopChannel::isRegistered( channel.latin1() ) ) {
394 QString answer = "599 ChannelNotRegistered " + channel; 394 // send message back about it
395 send( answer ); 395 QString answer = "599 ChannelNotRegistered " + channel;
396 return; 396 send( answer );
397 } 397 return;
398 398 }
399 if ( paramList.count() ) 399#endif
400 QCopChannel::send( channel.latin1(), command.latin1(), buffer ); 400
401 else 401#ifndef QT_NO_COP
402 QCopChannel::send( channel.latin1(), command.latin1() ); 402 if ( paramList.count() )
403 403 QCopChannel::send( channel.latin1(), command.latin1(), buffer );
404 send( "200 Command okay" ); 404 else
405 } 405 QCopChannel::send( channel.latin1(), command.latin1() );
406
407 send( "200 Command okay" );
408#endif
409 }
406 } 410 }
@@ -408,3 +412,3 @@ void QCopBridgePI::process( const QString& message )
408 else 412 else
409 send( "502 Command not implemented" ); 413 send( "502 Command not implemented" );
410} 414}
@@ -416,5 +420,5 @@ void QCopBridgePI::timerEvent( QTimerEvent * )
416 if ( connected ) 420 if ( connected )
417 connected = FALSE; 421 connected = FALSE;
418 else 422 else
419 connectionClosed(); 423 connectionClosed();
420} 424}
diff --git a/core/launcher/qcopbridge.h b/core/launcher/qcopbridge.h
index 114b3ee..408d10d 100644
--- a/core/launcher/qcopbridge.h
+++ b/core/launcher/qcopbridge.h
@@ -1,5 +1,5 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
@@ -81,5 +81,2 @@ protected slots:
81protected: 81protected:
82 bool checkUser( const QString& user );
83 bool checkPassword( const QString& pw );
84
85 void timerEvent( QTimerEvent *e ); 82 void timerEvent( QTimerEvent *e );
diff --git a/core/launcher/transferserver.cpp b/core/launcher/transferserver.cpp
index 7294f9c..a6dab07 100644
--- a/core/launcher/transferserver.cpp
+++ b/core/launcher/transferserver.cpp
@@ -1,5 +1,5 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
@@ -24,2 +24,9 @@
24#include <stdlib.h> 24#include <stdlib.h>
25#include <time.h>
26#include <shadow.h>
27
28extern "C" {
29#include <uuid/uuid.h>
30#define UUID_H_INCLUDED
31}
25 32
@@ -39,4 +46,10 @@
39#include <qpe/process.h> 46#include <qpe/process.h>
47#include <qpe/global.h>
40#include <qpe/config.h> 48#include <qpe/config.h>
49#include <qpe/contact.h>
50#include <qpe/quuid.h>
51#include <qpe/version.h>
52#ifdef QWS
41#include <qpe/qcopenvelope_qws.h> 53#include <qpe/qcopenvelope_qws.h>
54#endif
42 55
@@ -47,3 +60,3 @@ const int block_size = 51200;
47 60
48TransferServer::TransferServer( Q_UINT16 port, QObject *parent, 61TransferServer::TransferServer( Q_UINT16 port, QObject *parent ,
49 const char* name ) 62 const char* name )
@@ -65,3 +78,3 @@ void TransferServer::newConnection( int socket )
65 78
66bool accessAuthorized(QHostAddress peeraddress) 79QString SyncAuthentication::serverId()
67{ 80{
@@ -69,17 +82,123 @@ bool accessAuthorized(QHostAddress peeraddress)
69 cfg.setGroup("Sync"); 82 cfg.setGroup("Sync");
70 uint auth_peer = cfg.readNumEntry("auth_peer",0xc0a80100); 83 QString r=cfg.readEntry("serverid");
84 if ( r.isEmpty() ) {
85 uuid_t uuid;
86 uuid_generate( uuid );
87 cfg.writeEntry("serverid",(r = QUuid( uuid ).toString()));
88 }
89 return r;
90}
91
92QString SyncAuthentication::ownerName()
93{
94 QString vfilename = Global::applicationFileName("addressbook",
95 "businesscard.vcf");
96 if (QFile::exists(vfilename)) {
97 Contact c;
98 c = Contact::readVCard( vfilename )[0];
99 return c.fullName();
100 }
101
102 return "";
103}
104
105QString SyncAuthentication::loginName()
106{
107 struct passwd *pw;
108 pw = getpwuid( geteuid() );
109 return QString::fromLocal8Bit( pw->pw_name );
110}
111
112int SyncAuthentication::isAuthorized(QHostAddress peeraddress)
113{
114 Config cfg("Security");
115 cfg.setGroup("Sync");
116 QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0");
117 QHostAddress allowed;
118 allowed.setAddress(allowedstr);
119 uint auth_peer = allowed.ip4Addr();
71 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits",24); 120 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits",24);
72 bool ok = (peeraddress.ip4Addr() & (((1<<auth_peer_bits)-1)<<(32-auth_peer_bits))) 121 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined
73 == auth_peer; 122 ? 0xffffffff : (((1<<auth_peer_bits)-1)<<(32-auth_peer_bits));
74 /* Allows denial-of-service attack. 123 return (peeraddress.ip4Addr() & mask) == auth_peer;
75 if ( !ok ) { 124}
76 QMessageBox::warning(0,tr("Security"), 125
77 tr("<p>An attempt to access this device from %1 has been denied.") 126bool SyncAuthentication::checkUser( const QString& user )
78 .arg(peeraddress.toString())); 127{
79 } 128 if ( user.isEmpty() ) return FALSE;
80 */ 129 QString euser = loginName();
81 return ok; 130 return user == euser;
82} 131}
83 132
84ServerPI::ServerPI( int socket, QObject *parent, const char* name ) 133bool SyncAuthentication::checkPassword( const QString& password )
134{
135#ifdef ALLOW_UNIX_USER_FTP
136 // First, check system password...
137
138 struct passwd *pw = 0;
139 struct spwd *spw = 0;
140
141 pw = getpwuid( geteuid() );
142 spw = getspnam( pw->pw_name );
143
144 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd );
145 if ( cpwd == "x" && spw )
146 cpwd = QString::fromLocal8Bit( spw->sp_pwdp );
147
148 // Note: some systems use more than crypt for passwords.
149 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) );
150 if ( cpwd == cpassword )
151 return TRUE;
152#endif
153
154 static int lastdenial=0;
155 static int denials=0;
156 int now = time(0);
157
158 // Detect old Qtopia Desktop (no password)
159 if ( password.isEmpty() ) {
160 if ( denials < 1 || now > lastdenial+600 ) {
161 QMessageBox::warning( 0,tr("Sync Connection"),
162 tr("<p>An unauthorized system is requesting access to this device."
163 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, "
164 "please upgrade."),
165 tr("Deny") );
166 denials++;
167 lastdenial=now;
168 }
169 return FALSE;
170 }
171
172 // Second, check sync password...
173 if ( password.left(6) == "Qtopia" ) {
174 QString cpassword = QString::fromLocal8Bit( crypt( password.mid(8).local8Bit(), "qp" ) );
175 Config cfg("Security");
176 cfg.setGroup("Sync");
177 QString pwds = cfg.readEntry("Passwords");
178 if ( QStringList::split(QChar(' '),pwds).contains(cpassword) )
179 return TRUE;
180
181 // Unrecognized system. Be careful...
182
183 if ( (denials > 2 && now < lastdenial+600)
184 || QMessageBox::warning(0,tr("Sync Connection"),
185 tr("<p>An unrecognized system is requesting access to this device."
186 "<p>If you have just initiated a Sync for the first time, this is normal."),
187 tr("Allow"),tr("Deny"))==1 )
188 {
189 denials++;
190 lastdenial=now;
191 return FALSE;
192 } else {
193 denials=0;
194 cfg.writeEntry("Passwords",pwds+" "+cpassword);
195 return TRUE;
196 }
197 }
198
199 return FALSE;
200}
201
202
203ServerPI::ServerPI( int socket, QObject *parent , const char* name )
85 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ) 204 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 )
@@ -94,3 +213,3 @@ ServerPI::ServerPI( int socket, QObject *parent, const char* name )
94#ifndef INSECURE 213#ifndef INSECURE
95 if ( !accessAuthorized(peeraddress) ) { 214 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
96 state = Forbidden; 215 state = Forbidden;
@@ -107,3 +226,3 @@ ServerPI::ServerPI( int socket, QObject *parent, const char* name )
107 226
108 send( "220 Qtopia transfer service ready!" ); 227 send( "220 Qtopia " QPE_VERSION " FTP Server" );
109 state = Wait_USER; 228 state = Wait_USER;
@@ -153,33 +272,2 @@ void ServerPI::read()
153 272
154bool ServerPI::checkUser( const QString& user )
155{
156 if ( user.isEmpty() ) return FALSE;
157
158 struct passwd *pw;
159 pw = getpwuid( geteuid() );
160 QString euser = QString::fromLocal8Bit( pw->pw_name );
161 return user == euser;
162}
163
164bool ServerPI::checkPassword( const QString& /* password */ )
165{
166 // ### HACK for testing on local host
167 return true;
168
169 /*
170 struct passwd *pw = 0;
171 struct spwd *spw = 0;
172
173 pw = getpwuid( geteuid() );
174 spw = getspnam( pw->pw_name );
175
176 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd );
177 if ( cpwd == "x" && spw )
178 cpwd = QString::fromLocal8Bit( spw->sp_pwdp );
179
180 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) );
181 return cpwd == cpassword;
182*/
183}
184
185bool ServerPI::checkReadFile( const QString& file ) 273bool ServerPI::checkReadFile( const QString& file )
@@ -256,3 +344,3 @@ void ServerPI::process( const QString& message )
256 344
257 if ( cmd != "USER" || msg.count() < 2 || !checkUser( arg ) ) { 345 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
258 send( "530 Please login with USER and PASS" ); 346 send( "530 Please login with USER and PASS" );
@@ -268,4 +356,3 @@ void ServerPI::process( const QString& message )
268 356
269 if ( cmd != "PASS" || !checkPassword( arg ) ) { 357 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
270 //if ( cmd != "PASS" || msg.count() < 2 || !checkPassword( arg ) ) {
271 send( "530 Please login with USER and PASS" ); 358 send( "530 Please login with USER and PASS" );
@@ -456,6 +543,9 @@ void ServerPI::process( const QString& message )
456 QFile file( absFilePath( args ) ) ; 543 QFile file( absFilePath( args ) ) ;
457 if ( file.remove() ) 544 if ( file.remove() ) {
458 send( "250 Requested file action okay, completed" ); 545 send( "250 Requested file action okay, completed" );
459 else 546 QCopEnvelope e("QPE/System", "linkChanged(QString)" );
547 e << file.name();
548 } else {
460 send( "550 Requested action not taken" ); 549 send( "550 Requested action not taken" );
550 }
461 } 551 }
@@ -636,5 +726,12 @@ void ServerPI::dtpCompleted()
636{ 726{
637 dtp->close();
638 waitsocket = 0;
639 send( "226 Closing data connection, file transfer successful" ); 727 send( "226 Closing data connection, file transfer successful" );
728 if ( dtp->dtpMode() == ServerDTP::RetrieveFile ) {
729 QString fn = dtp->fileName();
730 if ( fn.right(8)==".desktop" && fn.find("/Documents/")>=0 ) {
731 QCopEnvelope e("QPE/System", "linkChanged(QString)" );
732 e << fn;
733 }
734 }
735 waitsocket = 0;
736 dtp->close();
640} 737}
@@ -854,3 +951,3 @@ void ServerPI::timerEvent( QTimerEvent * )
854 951
855ServerDTP::ServerDTP( QObject *parent, const char* name ) 952ServerDTP::ServerDTP( QObject *parent = 0, const char* name = 0)
856 : QSocket( parent, name ), mode( Idle ), createTargzProc( 0 ), 953 : QSocket( parent, name ), mode( Idle ), createTargzProc( 0 ),
@@ -893,4 +990,6 @@ void ServerDTP::extractTarDone()
893 qDebug("extract done"); 990 qDebug("extract done");
991#ifndef QT_NO_COP
894 QCopEnvelope e( "QPE/Desktop", "restoreDone(QString)" ); 992 QCopEnvelope e( "QPE/Desktop", "restoreDone(QString)" );
895 e << file.name(); 993 e << file.name();
994#endif
896} 995}
diff --git a/core/launcher/transferserver.h b/core/launcher/transferserver.h
index 076e460..a3bb060 100644
--- a/core/launcher/transferserver.h
+++ b/core/launcher/transferserver.h
@@ -1,5 +1,5 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
@@ -38,2 +38,16 @@ public:
38 38
39class SyncAuthentication : QObject
40{
41 Q_OBJECT
42
43public:
44 static int isAuthorized(QHostAddress peeraddress);
45 static bool checkPassword(const QString& pw);
46 static bool checkUser(const QString& user);
47
48 static QString serverId();
49 static QString loginName();
50 static QString ownerName();
51};
52
39 53
@@ -67,2 +81,3 @@ public:
67 QByteArray buffer() { return buf.buffer(); } 81 QByteArray buffer() { return buf.buffer(); }
82 QString fileName() const { return file.name(); }
68 83
@@ -133,4 +148,2 @@ protected slots:
133protected: 148protected:
134 bool checkUser( const QString& user );
135 bool checkPassword( const QString& pw );
136 bool checkReadFile( const QString& file ); 149 bool checkReadFile( const QString& file );
@@ -166,3 +179 @@ private:
166}; };
167
168bool accessAuthorized(QHostAddress peeraddress);