summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/transferserver.cpp2
1 files changed, 1 insertions, 1 deletions
diff --git a/core/launcher/transferserver.cpp b/core/launcher/transferserver.cpp
index dea140d..aaa4425 100644
--- a/core/launcher/transferserver.cpp
+++ b/core/launcher/transferserver.cpp
@@ -41,385 +41,385 @@ extern "C" {
41#include <shadow.h> 41#include <shadow.h>
42#endif 42#endif
43 43
44#include <qdir.h> 44#include <qdir.h>
45#include <qfile.h> 45#include <qfile.h>
46#include <qtextstream.h> 46#include <qtextstream.h>
47#include <qdatastream.h> 47#include <qdatastream.h>
48#include <qmessagebox.h> 48#include <qmessagebox.h>
49#include <qstringlist.h> 49#include <qstringlist.h>
50#include <qfileinfo.h> 50#include <qfileinfo.h>
51#include <qregexp.h> 51#include <qregexp.h>
52//#include <qpe/qcopchannel_qws.h> 52//#include <qpe/qcopchannel_qws.h>
53#include <qpe/process.h> 53#include <qpe/process.h>
54#include <qpe/global.h> 54#include <qpe/global.h>
55#include <qpe/config.h> 55#include <qpe/config.h>
56#include <qpe/contact.h> 56#include <qpe/contact.h>
57#include <qpe/quuid.h> 57#include <qpe/quuid.h>
58#include <qpe/version.h> 58#include <qpe/version.h>
59#include <qpe/qcopenvelope_qws.h> 59#include <qpe/qcopenvelope_qws.h>
60 60
61#include "transferserver.h" 61#include "transferserver.h"
62#include "qprocess.h" 62#include "qprocess.h"
63 63
64const int block_size = 51200; 64const int block_size = 51200;
65 65
66TransferServer::TransferServer( Q_UINT16 port, QObject *parent , 66TransferServer::TransferServer( Q_UINT16 port, QObject *parent ,
67 const char* name ) 67 const char* name )
68 : QServerSocket( port, 1, parent, name ) 68 : QServerSocket( port, 1, parent, name )
69{ 69{
70 if ( !ok() ) 70 if ( !ok() )
71 qWarning( "Failed to bind to port %d", port ); 71 qWarning( "Failed to bind to port %d", port );
72} 72}
73 73
74TransferServer::~TransferServer() 74TransferServer::~TransferServer()
75{ 75{
76 76
77} 77}
78 78
79void TransferServer::newConnection( int socket ) 79void TransferServer::newConnection( int socket )
80{ 80{
81 (void) new ServerPI( socket, this ); 81 (void) new ServerPI( socket, this );
82} 82}
83 83
84/* 84/*
85 * small class in anonymous namespace 85 * small class in anonymous namespace
86 * to generate a QUUid for us 86 * to generate a QUUid for us
87 */ 87 */
88namespace { 88namespace {
89 struct UidGen { 89 struct UidGen {
90 QString uuid(); 90 QString uuid();
91 }; 91 };
92#if !defined(_OS_LINUX_) 92#if !defined(_OS_LINUX_)
93 QString UidGen::uuid() { 93 QString UidGen::uuid() {
94 uuid_t uuid; 94 uuid_t uuid;
95 uuid_generate( uuid ); 95 uuid_generate( uuid );
96 return QUUid( uuid ).toString(); 96 return QUUid( uuid ).toString();
97 } 97 }
98#else 98#else
99 /* 99 /*
100 * linux got a /proc/sys/kernel/random/uuid file 100 * linux got a /proc/sys/kernel/random/uuid file
101 * it'll generate the uuids for us 101 * it'll generate the uuids for us
102 */ 102 */
103 QString UidGen::uuid() { 103 QString UidGen::uuid() {
104 QFile file( "/proc/sys/kernel/random/uuid" ); 104 QFile file( "/proc/sys/kernel/random/uuid" );
105 if (!file.open(IO_ReadOnly ) ) 105 if (!file.open(IO_ReadOnly ) )
106 return QString::null; 106 return QString::null;
107 107
108 QTextStream stream(&file); 108 QTextStream stream(&file);
109 109
110 return "{" + stream.read().stripWhiteSpace() + "}"; 110 return "{" + stream.read().stripWhiteSpace() + "}";
111 } 111 }
112#endif 112#endif
113} 113}
114 114
115QString SyncAuthentication::serverId() 115QString SyncAuthentication::serverId()
116{ 116{
117 Config cfg("Security"); 117 Config cfg("Security");
118 cfg.setGroup("Sync"); 118 cfg.setGroup("Sync");
119 QString r=cfg.readEntry("serverid"); 119 QString r=cfg.readEntry("serverid");
120 if ( r.isEmpty() ) { 120 if ( r.isEmpty() ) {
121 UidGen gen; 121 UidGen gen;
122 r = gen.uuid(); 122 r = gen.uuid();
123 cfg.writeEntry("serverid", r ); 123 cfg.writeEntry("serverid", r );
124 } 124 }
125 return r; 125 return r;
126} 126}
127 127
128QString SyncAuthentication::ownerName() 128QString SyncAuthentication::ownerName()
129{ 129{
130 QString vfilename = Global::applicationFileName("addressbook", 130 QString vfilename = Global::applicationFileName("addressbook",
131 "businesscard.vcf"); 131 "businesscard.vcf");
132 if (QFile::exists(vfilename)) { 132 if (QFile::exists(vfilename)) {
133 Contact c; 133 Contact c;
134 c = Contact::readVCard( vfilename )[0]; 134 c = Contact::readVCard( vfilename )[0];
135 return c.fullName(); 135 return c.fullName();
136 } 136 }
137 137
138 return ""; 138 return "";
139} 139}
140 140
141QString SyncAuthentication::loginName() 141QString SyncAuthentication::loginName()
142{ 142{
143 struct passwd *pw; 143 struct passwd *pw;
144 pw = getpwuid( geteuid() ); 144 pw = getpwuid( geteuid() );
145 return QString::fromLocal8Bit( pw->pw_name ); 145 return QString::fromLocal8Bit( pw->pw_name );
146} 146}
147 147
148int SyncAuthentication::isAuthorized(QHostAddress peeraddress) 148int SyncAuthentication::isAuthorized(QHostAddress peeraddress)
149{ 149{
150 Config cfg("Security"); 150 Config cfg("Security");
151 cfg.setGroup("Sync"); 151 cfg.setGroup("Sync");
152// QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0"); 152// QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0");
153 uint auth_peer = cfg.readNumEntry("auth_peer",0xc0a80100); 153 uint auth_peer = cfg.readNumEntry("auth_peer",0xc0a80100);
154 154
155// QHostAddress allowed; 155// QHostAddress allowed;
156// allowed.setAddress(allowedstr); 156// allowed.setAddress(allowedstr);
157// uint auth_peer = allowed.ip4Addr(); 157// uint auth_peer = allowed.ip4Addr();
158 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits",24); 158 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits",24);
159 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined 159 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined
160 ? 0xffffffff : (((1<<auth_peer_bits)-1)<<(32-auth_peer_bits)); 160 ? 0xffffffff : (((1<<auth_peer_bits)-1)<<(32-auth_peer_bits));
161 return (peeraddress.ip4Addr() & mask) == auth_peer; 161 return (peeraddress.ip4Addr() & mask) == auth_peer;
162} 162}
163 163
164bool SyncAuthentication::checkUser( const QString& user ) 164bool SyncAuthentication::checkUser( const QString& user )
165{ 165{
166 if ( user.isEmpty() ) return FALSE; 166 if ( user.isEmpty() ) return FALSE;
167 QString euser = loginName(); 167 QString euser = loginName();
168 return user == euser; 168 return user == euser;
169} 169}
170 170
171bool SyncAuthentication::checkPassword( const QString& password ) 171bool SyncAuthentication::checkPassword( const QString& password )
172{ 172{
173#ifdef ALLOW_UNIX_USER_FTP 173#ifdef ALLOW_UNIX_USER_FTP
174 // First, check system password... 174 // First, check system password...
175 175
176 struct passwd *pw = 0; 176 struct passwd *pw = 0;
177 struct spwd *spw = 0; 177 struct spwd *spw = 0;
178 178
179 pw = getpwuid( geteuid() ); 179 pw = getpwuid( geteuid() );
180 spw = getspnam( pw->pw_name ); 180 spw = getspnam( pw->pw_name );
181 181
182 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd ); 182 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd );
183 if ( cpwd == "x" && spw ) 183 if ( cpwd == "x" && spw )
184 cpwd = QString::fromLocal8Bit( spw->sp_pwdp ); 184 cpwd = QString::fromLocal8Bit( spw->sp_pwdp );
185 185
186 // Note: some systems use more than crypt for passwords. 186 // Note: some systems use more than crypt for passwords.
187 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) ); 187 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) );
188 if ( cpwd == cpassword ) 188 if ( cpwd == cpassword )
189 return TRUE; 189 return TRUE;
190#endif 190#endif
191 191
192 static int lastdenial=0; 192 static int lastdenial=0;
193 static int denials=0; 193 static int denials=0;
194 int now = time(0); 194 int now = time(0);
195 195
196 // Detect old Qtopia Desktop (no password) 196 // Detect old Qtopia Desktop (no password)
197 if ( password.isEmpty() ) { 197 if ( password.isEmpty() ) {
198 if ( denials < 1 || now > lastdenial+600 ) { 198 if ( denials < 1 || now > lastdenial+600 ) {
199 QMessageBox::warning( 0,tr("Sync Connection"), 199 QMessageBox::warning( 0,tr("Sync Connection"),
200 tr("<p>An unauthorized system is requesting access to this device." 200 tr("<p>An unauthorized system is requesting access to this device."
201 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, " 201 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, "
202 "please upgrade."), 202 "please upgrade."),
203 tr("Deny") ); 203 tr("Deny") );
204 denials++; 204 denials++;
205 lastdenial=now; 205 lastdenial=now;
206 } 206 }
207 return FALSE; 207 return FALSE;
208 } 208 }
209 209
210 // Second, check sync password... 210 // Second, check sync password...
211 QString pass = password.left(6); 211 QString pass = password.left(6);
212 /* old QtopiaDesktops are sending 212 /* old QtopiaDesktops are sending
213 * rootme newer versions got a Qtopia 213 * rootme newer versions got a Qtopia
214 * prefixed. Qtopia prefix will suceed 214 * prefixed. Qtopia prefix will suceed
215 * until the sync software syncs up 215 * until the sync software syncs up
216 * FIXME 216 * FIXME
217 */ 217 */
218 if ( pass == "rootme" || pass == "Qtopia") { 218 if ( pass == "rootme" || pass == "Qtopia") {
219 219
220 QString cpassword = QString::fromLocal8Bit( crypt( password.mid(8).local8Bit(), "qp" ) ); 220 QString cpassword = QString::fromLocal8Bit( crypt( password.mid(8).local8Bit(), "qp" ) );
221 Config cfg("Security"); 221 Config cfg("Security");
222 cfg.setGroup("Sync"); 222 cfg.setGroup("Sync");
223 QString pwds = cfg.readEntry("Passwords"); 223 QString pwds = cfg.readEntry("Passwords");
224 if ( QStringList::split(QChar(' '),pwds).contains(cpassword) ) 224 if ( QStringList::split(QChar(' '),pwds).contains(cpassword) )
225 return TRUE; 225 return TRUE;
226 226
227 // Unrecognized system. Be careful... 227 // Unrecognized system. Be careful...
228 228
229 if ( (denials > 2 && now < lastdenial+600) 229 if ( (denials > 2 && now < lastdenial+600)
230 || QMessageBox::warning(0,tr("Sync Connection"), 230 || QMessageBox::warning(0,tr("Sync Connection"),
231 tr("<p>An unrecognized system is requesting access to this device." 231 tr("<p>An unrecognized system is requesting access to this device."
232 "<p>If you have just initiated a Sync for the first time, this is normal."), 232 "<p>If you have just initiated a Sync for the first time, this is normal."),
233 tr("Allow"),tr("Deny"))==1 ) 233 tr("Allow"),tr("Deny"), 0, 1, 1 ) ==1 )
234 { 234 {
235 denials++; 235 denials++;
236 lastdenial=now; 236 lastdenial=now;
237 return FALSE; 237 return FALSE;
238 } else { 238 } else {
239 denials=0; 239 denials=0;
240 cfg.writeEntry("Passwords",pwds+" "+cpassword); 240 cfg.writeEntry("Passwords",pwds+" "+cpassword);
241 return TRUE; 241 return TRUE;
242 } 242 }
243 } 243 }
244 244
245 return FALSE; 245 return FALSE;
246} 246}
247 247
248ServerPI::ServerPI( int socket, QObject *parent , const char* name ) 248ServerPI::ServerPI( int socket, QObject *parent , const char* name )
249 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ) 249 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 )
250{ 250{
251 state = Connected; 251 state = Connected;
252 252
253 setSocket( socket ); 253 setSocket( socket );
254 254
255 peerport = peerPort(); 255 peerport = peerPort();
256 peeraddress = peerAddress(); 256 peeraddress = peerAddress();
257 257
258#ifndef INSECURE 258#ifndef INSECURE
259 if ( !SyncAuthentication::isAuthorized(peeraddress) ) { 259 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
260 state = Forbidden; 260 state = Forbidden;
261 startTimer( 0 ); 261 startTimer( 0 );
262 } else 262 } else
263#endif 263#endif
264 { 264 {
265 connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); 265 connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
266 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); 266 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
267 267
268 passiv = FALSE; 268 passiv = FALSE;
269 for( int i = 0; i < 4; i++ ) 269 for( int i = 0; i < 4; i++ )
270 wait[i] = FALSE; 270 wait[i] = FALSE;
271 271
272 send( "220 Qtopia " QPE_VERSION " FTP Server" ); 272 send( "220 Qtopia " QPE_VERSION " FTP Server" );
273 state = Wait_USER; 273 state = Wait_USER;
274 274
275 dtp = new ServerDTP( this ); 275 dtp = new ServerDTP( this );
276 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) ); 276 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) );
277 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) ); 277 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) );
278 connect( dtp, SIGNAL( error( int ) ), SLOT( dtpError( int ) ) ); 278 connect( dtp, SIGNAL( error( int ) ), SLOT( dtpError( int ) ) );
279 279
280 280
281 directory = QDir::currentDirPath(); 281 directory = QDir::currentDirPath();
282 282
283 static int p = 1024; 283 static int p = 1024;
284 284
285 while ( !serversocket || !serversocket->ok() ) { 285 while ( !serversocket || !serversocket->ok() ) {
286 delete serversocket; 286 delete serversocket;
287 serversocket = new ServerSocket( ++p, this ); 287 serversocket = new ServerSocket( ++p, this );
288 } 288 }
289 connect( serversocket, SIGNAL( newIncomming( int ) ), 289 connect( serversocket, SIGNAL( newIncomming( int ) ),
290 SLOT( newConnection( int ) ) ); 290 SLOT( newConnection( int ) ) );
291 } 291 }
292} 292}
293 293
294ServerPI::~ServerPI() 294ServerPI::~ServerPI()
295{ 295{
296 296
297} 297}
298 298
299void ServerPI::connectionClosed() 299void ServerPI::connectionClosed()
300{ 300{
301 // qDebug( "Debug: Connection closed" ); 301 // qDebug( "Debug: Connection closed" );
302 delete this; 302 delete this;
303} 303}
304 304
305void ServerPI::send( const QString& msg ) 305void ServerPI::send( const QString& msg )
306{ 306{
307 QTextStream os( this ); 307 QTextStream os( this );
308 os << msg << endl; 308 os << msg << endl;
309 //qDebug( "Reply: %s", msg.latin1() ); 309 //qDebug( "Reply: %s", msg.latin1() );
310} 310}
311 311
312void ServerPI::read() 312void ServerPI::read()
313{ 313{
314 while ( canReadLine() ) 314 while ( canReadLine() )
315 process( readLine().stripWhiteSpace() ); 315 process( readLine().stripWhiteSpace() );
316} 316}
317 317
318bool ServerPI::checkReadFile( const QString& file ) 318bool ServerPI::checkReadFile( const QString& file )
319{ 319{
320 QString filename; 320 QString filename;
321 321
322 if ( file[0] != "/" ) 322 if ( file[0] != "/" )
323 filename = directory.path() + "/" + file; 323 filename = directory.path() + "/" + file;
324 else 324 else
325 filename = file; 325 filename = file;
326 326
327 QFileInfo fi( filename ); 327 QFileInfo fi( filename );
328 return ( fi.exists() && fi.isReadable() ); 328 return ( fi.exists() && fi.isReadable() );
329} 329}
330 330
331bool ServerPI::checkWriteFile( const QString& file ) 331bool ServerPI::checkWriteFile( const QString& file )
332{ 332{
333 QString filename; 333 QString filename;
334 334
335 if ( file[0] != "/" ) 335 if ( file[0] != "/" )
336 filename = directory.path() + "/" + file; 336 filename = directory.path() + "/" + file;
337 else 337 else
338 filename = file; 338 filename = file;
339 339
340 QFileInfo fi( filename ); 340 QFileInfo fi( filename );
341 341
342 if ( fi.exists() ) 342 if ( fi.exists() )
343 if ( !QFile( filename ).remove() ) 343 if ( !QFile( filename ).remove() )
344 return FALSE; 344 return FALSE;
345 return TRUE; 345 return TRUE;
346} 346}
347 347
348void ServerPI::process( const QString& message ) 348void ServerPI::process( const QString& message )
349{ 349{
350 //qDebug( "Command: %s", message.latin1() ); 350 //qDebug( "Command: %s", message.latin1() );
351 351
352 // split message using "," as separator 352 // split message using "," as separator
353 QStringList msg = QStringList::split( " ", message ); 353 QStringList msg = QStringList::split( " ", message );
354 if ( msg.isEmpty() ) return; 354 if ( msg.isEmpty() ) return;
355 355
356 // command token 356 // command token
357 QString cmd = msg[0].upper(); 357 QString cmd = msg[0].upper();
358 358
359 // argument token 359 // argument token
360 QString arg; 360 QString arg;
361 if ( msg.count() >= 2 ) 361 if ( msg.count() >= 2 )
362 arg = msg[1]; 362 arg = msg[1];
363 363
364 // full argument string 364 // full argument string
365 QString args; 365 QString args;
366 if ( msg.count() >= 2 ) { 366 if ( msg.count() >= 2 ) {
367 QStringList copy( msg ); 367 QStringList copy( msg );
368 // FIXME: for Qt3 368 // FIXME: for Qt3
369 // copy.pop_front() 369 // copy.pop_front()
370 copy.remove( copy.begin() ); 370 copy.remove( copy.begin() );
371 args = copy.join( " " ); 371 args = copy.join( " " );
372 } 372 }
373 373
374 //qDebug( "args: %s", args.latin1() ); 374 //qDebug( "args: %s", args.latin1() );
375 375
376 // we always respond to QUIT, regardless of state 376 // we always respond to QUIT, regardless of state
377 if ( cmd == "QUIT" ) { 377 if ( cmd == "QUIT" ) {
378 send( "211 Good bye!" ); 378 send( "211 Good bye!" );
379 delete this; 379 delete this;
380 return; 380 return;
381 } 381 }
382 382
383 // connected to client 383 // connected to client
384 if ( Connected == state ) 384 if ( Connected == state )
385 return; 385 return;
386 386
387 // waiting for user name 387 // waiting for user name
388 if ( Wait_USER == state ) { 388 if ( Wait_USER == state ) {
389 389
390 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) { 390 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
391 send( "530 Please login with USER and PASS" ); 391 send( "530 Please login with USER and PASS" );
392 return; 392 return;
393 } 393 }
394 send( "331 User name ok, need password" ); 394 send( "331 User name ok, need password" );
395 state = Wait_PASS; 395 state = Wait_PASS;
396 return; 396 return;
397 } 397 }
398 398
399 // waiting for password 399 // waiting for password
400 if ( Wait_PASS == state ) { 400 if ( Wait_PASS == state ) {
401 401
402 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) { 402 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
403 send( "530 Please login with USER and PASS" ); 403 send( "530 Please login with USER and PASS" );
404 return; 404 return;
405 } 405 }
406 send( "230 User logged in, proceed" ); 406 send( "230 User logged in, proceed" );
407 state = Ready; 407 state = Ready;
408 return; 408 return;
409 } 409 }
410 410
411 // ACCESS CONTROL COMMANDS 411 // ACCESS CONTROL COMMANDS
412 412
413 413
414 // account (ACCT) 414 // account (ACCT)
415 if ( cmd == "ACCT" ) { 415 if ( cmd == "ACCT" ) {
416 // even wu-ftp does not support it 416 // even wu-ftp does not support it
417 send( "502 Command not implemented" ); 417 send( "502 Command not implemented" );
418 } 418 }
419 419
420 // change working directory (CWD) 420 // change working directory (CWD)
421 else if ( cmd == "CWD" ) { 421 else if ( cmd == "CWD" ) {
422 422
423 if ( !args.isEmpty() ) { 423 if ( !args.isEmpty() ) {
424 if ( directory.cd( args, TRUE ) ) 424 if ( directory.cd( args, TRUE ) )
425 send( "250 Requested file action okay, completed" ); 425 send( "250 Requested file action okay, completed" );